diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b963163..06321b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,8 @@ jobs: CARGO: cargo # When CARGO is set to CROSS, TARGET is set to `--target matrix.target`. TARGET: + # Make quickcheck run more tests for hopefully better coverage. + QUICKCHECK_TESTS: 100000 runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/Cargo.toml b/Cargo.toml index 837f0f3..0589a90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,8 +37,12 @@ libc = { version = "0.2.18", default-features = false, optional = true } [dev-dependencies] quickcheck = { version = "1.0.3", default-features = false } +[profile.release] +debug = true + [profile.bench] debug = true [profile.test] opt-level = 3 +debug = true diff --git a/README.md b/README.md index b7e11fb..3b92e18 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ memchr ====== -The `memchr` crate provides heavily optimized routines for searching bytes. +This library provides heavily optimized routines for string search primitives. [![Build status](https://github.com/BurntSushi/rust-memchr/workflows/ci/badge.svg)](https://github.com/BurntSushi/rust-memchr/actions) [![](https://meritbadge.herokuapp.com/memchr)](https://crates.io/crates/memchr) @@ -15,23 +15,15 @@ Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/). ### Overview -The `memchr` function is traditionally provided by libc, but its -performance can vary significantly depending on the specific -implementation of libc that is used. They can range from manually tuned -Assembly implementations (like that found in GNU's libc) all the way to -non-vectorized C implementations (like that found in MUSL). +* The top-level module provides routines for searching for 1, 2 or 3 bytes + in the forward or reverse direction. When searching for more than one byte, + positions are considered a match if the byte at that position matches any + of the bytes. +* The `memmem` sub-module provides forward and reverse substring search + routines. -To smooth out the differences between implementations of libc, at least -on `x86_64` for Rust 1.27+, this crate provides its own implementation of -`memchr` that should perform competitively with the one found in GNU's libc. -The implementation is in pure Rust and has no dependency on a C compiler or an -Assembler. - -Additionally, GNU libc also provides an extension, `memrchr`. This crate -provides its own implementation of `memrchr` as well, on top of `memchr2`, -`memchr3`, `memrchr2` and `memrchr3`. The difference between `memchr` and -`memchr2` is that `memchr2` permits finding all occurrences of two bytes -instead of one. Similarly for `memchr3`. +In all such cases, routines operate on `&[u8]` without regard to encoding. This +is exactly what you want when searching either UTF-8 or arbitrary bytes. ### Compiling without the standard library @@ -43,10 +35,9 @@ memchr links to the standard library by default, but you can disable the memchr = { version = "2", default-features = false } ``` -On x86 platforms, when the `std` feature is disabled, the SSE2 -implementation of memchr will be used in compilers that support it. When -`std` is enabled, the AVX implementation of memchr will be used if the CPU -is determined to support it at runtime. +On x86 platforms, when the `std` feature is disabled, the SSE2 accelerated +implementations will be used. When `std` is enabled, AVX accelerated +implementations will be used if the CPU is determined to support it at runtime. ### Using libc @@ -58,11 +49,11 @@ using `memchr` from libc is desirable and a vectorized routine is not otherwise available in this crate, then enabling the `libc` feature will use libc's version of `memchr`. -The rest of the functions in this crate, e.g., `memchr2` or `memrchr3`, are not -a standard part of libc, so they will always use the implementations in this -crate. One exception to this is `memrchr`, which is an extension commonly found -on Linux. On Linux, `memrchr` is used in precisely the same scenario as -`memchr`, as described above. +The rest of the functions in this crate, e.g., `memchr2` or `memrchr3` and the +substring search routines, will always use the implementations in this crate. +One exception to this is `memrchr`, which is an extension in `libc` found on +Linux. On Linux, `memrchr` is used in precisely the same scenario as `memchr`, +as described above. ### Minimum Rust version policy @@ -77,3 +68,20 @@ version of Rust. In general, this crate will be conservative with respect to the minimum supported version of Rust. + + +### Testing strategy + +Given the complexity of the code in this crate, along with the pervasive use +of `unsafe`, this crate has an extensive testing strategy. It combines multiple +approaches: + +* Hand-written tests. +* Exhaustive-style testing meant to exercise all possible branching and offset + calculations. +* Property based testing through [`quickcheck`](https://github.com/BurntSushi/quickcheck). +* Fuzz testing through [`cargo fuzz`](https://github.com/rust-fuzz/cargo-fuzz). +* A huge suite of benchmarks that are also run as tests. Benchmarks always + confirm that the expected result occurs. + +Improvements to the testing infrastructue are very welcome. diff --git a/bench/Cargo.toml b/bench/Cargo.toml index 4677b40..644bf0b 100644 --- a/bench/Cargo.toml +++ b/bench/Cargo.toml @@ -18,6 +18,10 @@ harness = false path = "src/bench.rs" [dependencies] +bstr = "0.2.15" criterion = "0.3.3" memchr = { version = "*", path = ".." } libc = "0.2.81" +regex = "1.4.5" +sliceslice = "0.2.1" +twoway = "0.2.1" diff --git a/bench/data/code/rust-library.rs b/bench/data/code/rust-library.rs new file mode 100644 index 0000000..7a4c034 --- /dev/null +++ b/bench/data/code/rust-library.rs @@ -0,0 +1,52095 @@ +use std::collections::LinkedList; +use test::Bencher; + +#[bench] +fn bench_collect_into(b: &mut Bencher) { + let v = &[0; 64]; + b.iter(|| { + let _: LinkedList<_> = v.iter().cloned().collect(); + }) +} + +#[bench] +fn bench_push_front(b: &mut Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + }) +} + +#[bench] +fn bench_push_back(b: &mut Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + }) +} + +#[bench] +fn bench_push_back_pop_back(b: &mut Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + m.pop_back(); + }) +} + +#[bench] +fn bench_push_front_pop_front(b: &mut Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + m.pop_front(); + }) +} + +#[bench] +fn bench_iter(b: &mut Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().count() == 128); + }) +} +#[bench] +fn bench_iter_mut(b: &mut Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().count() == 128); + }) +} +#[bench] +fn bench_iter_rev(b: &mut Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().rev().count() == 128); + }) +} +#[bench] +fn bench_iter_mut_rev(b: &mut Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().rev().count() == 128); + }) +} +use test::{black_box, Bencher}; + +#[bench] +fn char_iterator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); +} + +#[bench] +fn char_iterator_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars() { + black_box(ch); + } + }); +} + +#[bench] +fn char_iterator_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb + Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); +} + +#[bench] +fn char_iterator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().rev().count()); +} + +#[bench] +fn char_iterator_rev_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars().rev() { + black_box(ch); + } + }); +} + +#[bench] +fn char_indicesator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().count(), len)); +} + +#[bench] +fn char_indicesator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); +} + +#[bench] +fn split_unicode_ascii(b: &mut Bencher) { + let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; + + b.iter(|| assert_eq!(s.split('V').count(), 3)); +} + +#[bench] +fn split_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(' ').count(), len)); +} + +#[bench] +fn split_extern_fn(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + fn pred(c: char) -> bool { + c == ' ' + } + + b.iter(|| assert_eq!(s.split(pred).count(), len)); +} + +#[bench] +fn split_closure(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); +} + +#[bench] +fn split_slice(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + let c: &[char] = &[' ']; + b.iter(|| assert_eq!(s.split(c).count(), len)); +} + +#[bench] +fn bench_join(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let sep = "→"; + let v = vec![s, s, s, s, s, s, s, s, s, s]; + b.iter(|| { + assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9); + }) +} + +#[bench] +fn bench_contains_short_short(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "sit"; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) +} + +#[bench] +fn bench_contains_short_long(b: &mut Bencher) { + let haystack = "\ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ +ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ +eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ +sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ +tempus vel, gravida nec quam. + +In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ +sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ +diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ +lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ +eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ +interdum. Curabitur ut nisi justo. + +Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ +mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ +lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ +est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ +felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ +ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ +feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ +Aliquam sit amet placerat lorem. + +Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ +mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ +Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ +lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ +suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ +cursus accumsan. + +Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ +feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ +vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ +leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ +malesuada sollicitudin quam eu fermentum."; + let needle = "english"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) +} + +#[bench] +fn bench_contains_bad_naive(b: &mut Bencher) { + let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let needle = "aaaaaaaab"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) +} + +#[bench] +fn bench_contains_equal(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) +} + +macro_rules! make_test_inner { + ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => { + #[bench] + fn $name(bencher: &mut Bencher) { + let mut $s = $str; + black_box(&mut $s); + bencher.iter(|| { + for _ in 0..$iters { + black_box($code); + } + }); + } + }; +} + +macro_rules! make_test { + ($name:ident, $s:ident, $code:expr) => { + make_test!($name, $s, $code, 1); + }; + ($name:ident, $s:ident, $code:expr, $iters:expr) => { + mod $name { + use test::Bencher; + use test::black_box; + + // Short strings: 65 bytes each + make_test_inner!($s, $code, short_ascii, + "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!", $iters); + make_test_inner!($s, $code, short_mixed, + "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!", $iters); + make_test_inner!($s, $code, short_pile_of_poo, + "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!", $iters); + make_test_inner!($s, $code, long_lorem_ipsum,"\ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ +ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ +eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ +sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ +tempus vel, gravida nec quam. + +In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ +sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ +diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ +lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ +eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ +interdum. Curabitur ut nisi justo. + +Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ +mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ +lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ +est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ +felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ +ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ +feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ +Aliquam sit amet placerat lorem. + +Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ +mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ +Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ +lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ +suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ +cursus accumsan. + +Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ +feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ +vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ +leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ +malesuada sollicitudin quam eu fermentum!", $iters); + } + } +} + +make_test!(chars_count, s, s.chars().count()); + +make_test!(contains_bang_str, s, s.contains("!")); +make_test!(contains_bang_char, s, s.contains('!')); + +make_test!(match_indices_a_str, s, s.match_indices("a").count()); + +make_test!(split_a_str, s, s.split("a").count()); + +make_test!(trim_ascii_char, s, { s.trim_matches(|c: char| c.is_ascii()) }); +make_test!(trim_start_ascii_char, s, { s.trim_start_matches(|c: char| c.is_ascii()) }); +make_test!(trim_end_ascii_char, s, { s.trim_end_matches(|c: char| c.is_ascii()) }); + +make_test!(find_underscore_char, s, s.find('_')); +make_test!(rfind_underscore_char, s, s.rfind('_')); +make_test!(find_underscore_str, s, s.find("_")); + +make_test!(find_zzz_char, s, s.find('\u{1F4A4}')); +make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}')); +make_test!(find_zzz_str, s, s.find("\u{1F4A4}")); + +make_test!(starts_with_ascii_char, s, s.starts_with('/'), 1024); +make_test!(ends_with_ascii_char, s, s.ends_with('/'), 1024); +make_test!(starts_with_unichar, s, s.starts_with('\u{1F4A4}'), 1024); +make_test!(ends_with_unichar, s, s.ends_with('\u{1F4A4}'), 1024); +make_test!(starts_with_str, s, s.starts_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024); +make_test!(ends_with_str, s, s.ends_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024); + +make_test!(split_space_char, s, s.split(' ').count()); +make_test!(split_terminator_space_char, s, s.split_terminator(' ').count()); + +make_test!(splitn_space_char, s, s.splitn(10, ' ').count()); +make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count()); + +make_test!(split_space_str, s, s.split(" ").count()); +make_test!(split_ad_str, s, s.split("ad").count()); +use std::iter::repeat; +use test::{black_box, Bencher}; + +#[bench] +fn bench_with_capacity(b: &mut Bencher) { + b.iter(|| String::with_capacity(100)); +} + +#[bench] +fn bench_push_str(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + b.iter(|| { + let mut r = String::new(); + r.push_str(s); + }); +} + +const REPETITIONS: u64 = 10_000; + +#[bench] +fn bench_push_str_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push_str("a") + } + }); +} + +#[bench] +fn bench_push_char_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('a') + } + }); +} + +#[bench] +fn bench_push_char_two_bytes(b: &mut Bencher) { + b.bytes = REPETITIONS * 2; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('â') + } + }); +} + +#[bench] +fn from_utf8_lossy_100_ascii(b: &mut Bencher) { + let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { + let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_invalid(b: &mut Bencher) { + let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_invalid(b: &mut Bencher) { + let s = repeat(0xf5).take(100).collect::>(); + b.iter(|| { + let _ = String::from_utf8_lossy(&s); + }); +} + +#[bench] +fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + // ensure our operation produces an exact-size string before we benchmark it + let mut r = String::with_capacity(s.len()); + r.push_str(s); + assert_eq!(r.len(), r.capacity()); + b.iter(|| { + let mut r = String::with_capacity(s.len()); + r.push_str(s); + r.shrink_to_fit(); + r + }); +} + +#[bench] +fn bench_from_str(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + b.iter(|| String::from(s)) +} + +#[bench] +fn bench_from(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + b.iter(|| String::from(s)) +} + +#[bench] +fn bench_to_string(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + b.iter(|| s.to_string()) +} + +#[bench] +fn bench_insert_char_short(b: &mut Bencher) { + let s = "Hello, World!"; + b.iter(|| { + let mut x = String::from(s); + black_box(&mut x).insert(6, black_box(' ')); + x + }) +} + +#[bench] +fn bench_insert_char_long(b: &mut Bencher) { + let s = "Hello, World!"; + b.iter(|| { + let mut x = String::from(s); + black_box(&mut x).insert(6, black_box('❤')); + x + }) +} + +#[bench] +fn bench_insert_str_short(b: &mut Bencher) { + let s = "Hello, World!"; + b.iter(|| { + let mut x = String::from(s); + black_box(&mut x).insert_str(6, black_box(" ")); + x + }) +} + +#[bench] +fn bench_insert_str_long(b: &mut Bencher) { + let s = "Hello, World!"; + b.iter(|| { + let mut x = String::from(s); + black_box(&mut x).insert_str(6, black_box(" rustic ")); + x + }) +} +use rand::RngCore; +use std::iter::{repeat, FromIterator}; +use test::{black_box, Bencher}; + +#[bench] +fn bench_new(b: &mut Bencher) { + b.iter(|| Vec::::new()) +} + +fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| Vec::::with_capacity(src_len)) +} + +#[bench] +fn bench_with_capacity_0000(b: &mut Bencher) { + do_bench_with_capacity(b, 0) +} + +#[bench] +fn bench_with_capacity_0010(b: &mut Bencher) { + do_bench_with_capacity(b, 10) +} + +#[bench] +fn bench_with_capacity_0100(b: &mut Bencher) { + do_bench_with_capacity(b, 100) +} + +#[bench] +fn bench_with_capacity_1000(b: &mut Bencher) { + do_bench_with_capacity(b, 1000) +} + +fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| (0..src_len).collect::>()) +} + +#[bench] +fn bench_from_fn_0000(b: &mut Bencher) { + do_bench_from_fn(b, 0) +} + +#[bench] +fn bench_from_fn_0010(b: &mut Bencher) { + do_bench_from_fn(b, 10) +} + +#[bench] +fn bench_from_fn_0100(b: &mut Bencher) { + do_bench_from_fn(b, 100) +} + +#[bench] +fn bench_from_fn_1000(b: &mut Bencher) { + do_bench_from_fn(b, 1000) +} + +fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| repeat(5).take(src_len).collect::>()) +} + +#[bench] +fn bench_from_elem_0000(b: &mut Bencher) { + do_bench_from_elem(b, 0) +} + +#[bench] +fn bench_from_elem_0010(b: &mut Bencher) { + do_bench_from_elem(b, 10) +} + +#[bench] +fn bench_from_elem_0100(b: &mut Bencher) { + do_bench_from_elem(b, 100) +} + +#[bench] +fn bench_from_elem_1000(b: &mut Bencher) { + do_bench_from_elem(b, 1000) +} + +fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| src.as_slice().to_vec()); +} + +#[bench] +fn bench_from_slice_0000(b: &mut Bencher) { + do_bench_from_slice(b, 0) +} + +#[bench] +fn bench_from_slice_0010(b: &mut Bencher) { + do_bench_from_slice(b, 10) +} + +#[bench] +fn bench_from_slice_0100(b: &mut Bencher) { + do_bench_from_slice(b, 100) +} + +#[bench] +fn bench_from_slice_1000(b: &mut Bencher) { + do_bench_from_slice(b, 1000) +} + +fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec<_> = FromIterator::from_iter(src.iter().cloned()); + dst + }); +} + +#[bench] +fn bench_from_iter_0000(b: &mut Bencher) { + do_bench_from_iter(b, 0) +} + +#[bench] +fn bench_from_iter_0010(b: &mut Bencher) { + do_bench_from_iter(b, 10) +} + +#[bench] +fn bench_from_iter_0100(b: &mut Bencher) { + do_bench_from_iter(b, 100) +} + +#[bench] +fn bench_from_iter_1000(b: &mut Bencher) { + do_bench_from_iter(b, 1000) +} + +fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone()); + dst + }); +} + +#[bench] +fn bench_extend_0000_0000(b: &mut Bencher) { + do_bench_extend(b, 0, 0) +} + +#[bench] +fn bench_extend_0000_0010(b: &mut Bencher) { + do_bench_extend(b, 0, 10) +} + +#[bench] +fn bench_extend_0000_0100(b: &mut Bencher) { + do_bench_extend(b, 0, 100) +} + +#[bench] +fn bench_extend_0000_1000(b: &mut Bencher) { + do_bench_extend(b, 0, 1000) +} + +#[bench] +fn bench_extend_0010_0010(b: &mut Bencher) { + do_bench_extend(b, 10, 10) +} + +#[bench] +fn bench_extend_0100_0100(b: &mut Bencher) { + do_bench_extend(b, 100, 100) +} + +#[bench] +fn bench_extend_1000_1000(b: &mut Bencher) { + do_bench_extend(b, 1000, 1000) +} + +fn do_bench_extend_from_slice(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend_from_slice(&src); + dst + }); +} + +#[bench] +fn bench_extend_recycle(b: &mut Bencher) { + let mut data = vec![0; 1000]; + + b.iter(|| { + let tmp = std::mem::take(&mut data); + let mut to_extend = black_box(Vec::new()); + to_extend.extend(tmp.into_iter()); + data = black_box(to_extend); + }); + + black_box(data); +} + +#[bench] +fn bench_extend_from_slice_0000_0000(b: &mut Bencher) { + do_bench_extend_from_slice(b, 0, 0) +} + +#[bench] +fn bench_extend_from_slice_0000_0010(b: &mut Bencher) { + do_bench_extend_from_slice(b, 0, 10) +} + +#[bench] +fn bench_extend_from_slice_0000_0100(b: &mut Bencher) { + do_bench_extend_from_slice(b, 0, 100) +} + +#[bench] +fn bench_extend_from_slice_0000_1000(b: &mut Bencher) { + do_bench_extend_from_slice(b, 0, 1000) +} + +#[bench] +fn bench_extend_from_slice_0010_0010(b: &mut Bencher) { + do_bench_extend_from_slice(b, 10, 10) +} + +#[bench] +fn bench_extend_from_slice_0100_0100(b: &mut Bencher) { + do_bench_extend_from_slice(b, 100, 100) +} + +#[bench] +fn bench_extend_from_slice_1000_1000(b: &mut Bencher) { + do_bench_extend_from_slice(b, 1000, 1000) +} + +fn do_bench_clone(b: &mut Bencher, src_len: usize) { + let src: Vec = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| src.clone()); +} + +#[bench] +fn bench_clone_0000(b: &mut Bencher) { + do_bench_clone(b, 0) +} + +#[bench] +fn bench_clone_0010(b: &mut Bencher) { + do_bench_clone(b, 10) +} + +#[bench] +fn bench_clone_0100(b: &mut Bencher) { + do_bench_clone(b, 100) +} + +#[bench] +fn bench_clone_1000(b: &mut Bencher) { + do_bench_clone(b, 1000) +} + +fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..src_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = (times * src_len) as u64; + + b.iter(|| { + let mut dst = dst.clone(); + + for _ in 0..times { + dst.clone_from(&src); + dst = black_box(dst); + } + dst + }); +} + +#[bench] +fn bench_clone_from_01_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 0) +} + +#[bench] +fn bench_clone_from_01_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 10) +} + +#[bench] +fn bench_clone_from_01_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 100) +} + +#[bench] +fn bench_clone_from_01_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 10) +} + +#[bench] +fn bench_clone_from_01_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 100) +} + +#[bench] +fn bench_clone_from_01_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 100) +} + +#[bench] +fn bench_clone_from_01_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 0) +} + +#[bench] +fn bench_clone_from_01_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 10) +} + +#[bench] +fn bench_clone_from_01_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 100) +} + +#[bench] +fn bench_clone_from_10_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 0) +} + +#[bench] +fn bench_clone_from_10_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 10) +} + +#[bench] +fn bench_clone_from_10_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 100) +} + +#[bench] +fn bench_clone_from_10_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 10) +} + +#[bench] +fn bench_clone_from_10_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 100) +} + +#[bench] +fn bench_clone_from_10_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 100) +} + +#[bench] +fn bench_clone_from_10_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 0) +} + +#[bench] +fn bench_clone_from_10_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 10) +} + +#[bench] +fn bench_clone_from_10_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 100) +} + +macro_rules! bench_in_place { + ($($fname:ident, $type:ty, $count:expr, $init:expr);*) => { + $( + #[bench] + fn $fname(b: &mut Bencher) { + b.iter(|| { + let src: Vec<$type> = black_box(vec![$init; $count]); + src.into_iter() + .enumerate() + .map(|(idx, e)| idx as $type ^ e) + .collect::>() + }); + } + )+ + }; +} + +bench_in_place![ + bench_in_place_xxu8_0010_i0, u8, 10, 0; + bench_in_place_xxu8_0100_i0, u8, 100, 0; + bench_in_place_xxu8_1000_i0, u8, 1000, 0; + bench_in_place_xxu8_0010_i1, u8, 10, 1; + bench_in_place_xxu8_0100_i1, u8, 100, 1; + bench_in_place_xxu8_1000_i1, u8, 1000, 1; + bench_in_place_xu32_0010_i0, u32, 10, 0; + bench_in_place_xu32_0100_i0, u32, 100, 0; + bench_in_place_xu32_1000_i0, u32, 1000, 0; + bench_in_place_xu32_0010_i1, u32, 10, 1; + bench_in_place_xu32_0100_i1, u32, 100, 1; + bench_in_place_xu32_1000_i1, u32, 1000, 1; + bench_in_place_u128_0010_i0, u128, 10, 0; + bench_in_place_u128_0100_i0, u128, 100, 0; + bench_in_place_u128_1000_i0, u128, 1000, 0; + bench_in_place_u128_0010_i1, u128, 10, 1; + bench_in_place_u128_0100_i1, u128, 100, 1; + bench_in_place_u128_1000_i1, u128, 1000, 1 +]; + +#[bench] +fn bench_in_place_recycle(b: &mut Bencher) { + let mut data = vec![0; 1000]; + + b.iter(|| { + let tmp = std::mem::take(&mut data); + data = black_box( + tmp.into_iter() + .enumerate() + .map(|(idx, e)| idx.wrapping_add(e)) + .fuse() + .peekable() + .collect::>(), + ); + }); +} + +#[bench] +fn bench_in_place_zip_recycle(b: &mut Bencher) { + let mut data = vec![0u8; 1000]; + let mut rng = rand::thread_rng(); + let mut subst = vec![0u8; 1000]; + rng.fill_bytes(&mut subst[..]); + + b.iter(|| { + let tmp = std::mem::take(&mut data); + let mangled = tmp + .into_iter() + .zip(subst.iter().copied()) + .enumerate() + .map(|(i, (d, s))| d.wrapping_add(i as u8) ^ s) + .collect::>(); + data = black_box(mangled); + }); +} + +#[bench] +fn bench_in_place_zip_iter_mut(b: &mut Bencher) { + let mut data = vec![0u8; 256]; + let mut rng = rand::thread_rng(); + let mut subst = vec![0u8; 1000]; + rng.fill_bytes(&mut subst[..]); + + b.iter(|| { + data.iter_mut().enumerate().for_each(|(i, d)| { + *d = d.wrapping_add(i as u8) ^ subst[i]; + }); + }); + + black_box(data); +} + +pub fn vec_cast(input: Vec) -> Vec { + input.into_iter().map(|e| unsafe { std::mem::transmute_copy(&e) }).collect() +} + +#[bench] +fn bench_transmute(b: &mut Bencher) { + let mut vec = vec![10u32; 100]; + b.bytes = 800; // 2 casts x 4 bytes x 100 + b.iter(|| { + let v = std::mem::take(&mut vec); + let v = black_box(vec_cast::(v)); + let v = black_box(vec_cast::(v)); + vec = v; + }); +} + +#[derive(Clone)] +struct Droppable(usize); + +impl Drop for Droppable { + fn drop(&mut self) { + black_box(self); + } +} + +#[bench] +fn bench_in_place_collect_droppable(b: &mut Bencher) { + let v: Vec = std::iter::repeat_with(|| Droppable(0)).take(1000).collect(); + b.iter(|| { + v.clone() + .into_iter() + .skip(100) + .enumerate() + .map(|(i, e)| Droppable(i ^ e.0)) + .collect::>() + }) +} + +const LEN: usize = 16384; + +#[bench] +fn bench_chain_collect(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| data.iter().cloned().chain([1].iter().cloned()).collect::>()); +} + +#[bench] +fn bench_chain_chain_collect(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| { + data.iter() + .cloned() + .chain([1].iter().cloned()) + .chain([2].iter().cloned()) + .collect::>() + }); +} + +#[bench] +fn bench_nest_chain_chain_collect(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| { + data.iter().cloned().chain([1].iter().chain([2].iter()).cloned()).collect::>() + }); +} + +#[bench] +fn bench_range_map_collect(b: &mut Bencher) { + b.iter(|| (0..LEN).map(|_| u32::default()).collect::>()); +} + +#[bench] +fn bench_chain_extend_ref(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| { + let mut v = Vec::::with_capacity(data.len() + 1); + v.extend(data.iter().chain([1].iter())); + v + }); +} + +#[bench] +fn bench_chain_extend_value(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| { + let mut v = Vec::::with_capacity(data.len() + 1); + v.extend(data.iter().cloned().chain(Some(1))); + v + }); +} + +#[bench] +fn bench_rev_1(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| { + let mut v = Vec::::new(); + v.extend(data.iter().rev()); + v + }); +} + +#[bench] +fn bench_rev_2(b: &mut Bencher) { + let data = black_box([0; LEN]); + b.iter(|| { + let mut v = Vec::::with_capacity(data.len()); + v.extend(data.iter().rev()); + v + }); +} + +#[bench] +fn bench_map_regular(b: &mut Bencher) { + let data = black_box([(0, 0); LEN]); + b.iter(|| { + let mut v = Vec::::new(); + v.extend(data.iter().map(|t| t.1)); + v + }); +} + +#[bench] +fn bench_map_fast(b: &mut Bencher) { + let data = black_box([(0, 0); LEN]); + b.iter(|| { + let mut result = Vec::with_capacity(data.len()); + for i in 0..data.len() { + unsafe { + *result.get_unchecked_mut(i) = data[i].0; + result.set_len(i); + } + } + result + }); +} + +fn random_sorted_fill(mut seed: u32, buf: &mut [u32]) { + let mask = if buf.len() < 8192 { + 0xFF + } else if buf.len() < 200_000 { + 0xFFFF + } else { + 0xFFFF_FFFF + }; + + for item in buf.iter_mut() { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + + *item = seed & mask; + } + + buf.sort(); +} + +fn bench_vec_dedup_old(b: &mut Bencher, sz: usize) { + let mut template = vec![0u32; sz]; + b.bytes = std::mem::size_of_val(template.as_slice()) as u64; + random_sorted_fill(0x43, &mut template); + + let mut vec = template.clone(); + b.iter(|| { + let len = { + let (dedup, _) = vec.partition_dedup(); + dedup.len() + }; + vec.truncate(len); + + black_box(vec.first()); + vec.clear(); + vec.extend_from_slice(&template); + }); +} + +fn bench_vec_dedup_new(b: &mut Bencher, sz: usize) { + let mut template = vec![0u32; sz]; + b.bytes = std::mem::size_of_val(template.as_slice()) as u64; + random_sorted_fill(0x43, &mut template); + + let mut vec = template.clone(); + b.iter(|| { + vec.dedup(); + black_box(vec.first()); + vec.clear(); + vec.extend_from_slice(&template); + }); +} + +#[bench] +fn bench_dedup_old_100(b: &mut Bencher) { + bench_vec_dedup_old(b, 100); +} +#[bench] +fn bench_dedup_new_100(b: &mut Bencher) { + bench_vec_dedup_new(b, 100); +} + +#[bench] +fn bench_dedup_old_1000(b: &mut Bencher) { + bench_vec_dedup_old(b, 1000); +} +#[bench] +fn bench_dedup_new_1000(b: &mut Bencher) { + bench_vec_dedup_new(b, 1000); +} + +#[bench] +fn bench_dedup_old_10000(b: &mut Bencher) { + bench_vec_dedup_old(b, 10000); +} +#[bench] +fn bench_dedup_new_10000(b: &mut Bencher) { + bench_vec_dedup_new(b, 10000); +} + +#[bench] +fn bench_dedup_old_100000(b: &mut Bencher) { + bench_vec_dedup_old(b, 100000); +} +#[bench] +fn bench_dedup_new_100000(b: &mut Bencher) { + bench_vec_dedup_new(b, 100000); +} +// Disabling on android for the time being +// See https://github.com/rust-lang/rust/issues/73535#event-3477699747 +#![cfg(not(target_os = "android"))] +#![feature(btree_drain_filter)] +#![feature(map_first_last)] +#![feature(repr_simd)] +#![feature(slice_partition_dedup)] +#![feature(test)] + +extern crate test; + +mod binary_heap; +mod btree; +mod linked_list; +mod slice; +mod str; +mod string; +mod vec; +mod vec_deque; +use std::collections::BTreeMap; +use std::iter::Iterator; +use std::ops::RangeBounds; +use std::vec::Vec; + +use rand::{seq::SliceRandom, thread_rng, Rng}; +use test::{black_box, Bencher}; + +macro_rules! map_insert_rand_bench { + ($name: ident, $n: expr, $map: ident) => { + #[bench] + pub fn $name(b: &mut Bencher) { + let n: usize = $n; + let mut map = $map::new(); + // setup + let mut rng = thread_rng(); + + for _ in 0..n { + let i = rng.gen::() % n; + map.insert(i, i); + } + + // measure + b.iter(|| { + let k = rng.gen::() % n; + map.insert(k, k); + map.remove(&k); + }); + black_box(map); + } + }; +} + +macro_rules! map_insert_seq_bench { + ($name: ident, $n: expr, $map: ident) => { + #[bench] + pub fn $name(b: &mut Bencher) { + let mut map = $map::new(); + let n: usize = $n; + // setup + for i in 0..n { + map.insert(i * 2, i * 2); + } + + // measure + let mut i = 1; + b.iter(|| { + map.insert(i, i); + map.remove(&i); + i = (i + 2) % n; + }); + black_box(map); + } + }; +} + +macro_rules! map_find_rand_bench { + ($name: ident, $n: expr, $map: ident) => { + #[bench] + pub fn $name(b: &mut Bencher) { + let mut map = $map::new(); + let n: usize = $n; + + // setup + let mut rng = thread_rng(); + let mut keys: Vec<_> = (0..n).map(|_| rng.gen::() % n).collect(); + + for &k in &keys { + map.insert(k, k); + } + + keys.shuffle(&mut rng); + + // measure + let mut i = 0; + b.iter(|| { + let t = map.get(&keys[i]); + i = (i + 1) % n; + black_box(t); + }) + } + }; +} + +macro_rules! map_find_seq_bench { + ($name: ident, $n: expr, $map: ident) => { + #[bench] + pub fn $name(b: &mut Bencher) { + let mut map = $map::new(); + let n: usize = $n; + + // setup + for i in 0..n { + map.insert(i, i); + } + + // measure + let mut i = 0; + b.iter(|| { + let x = map.get(&i); + i = (i + 1) % n; + black_box(x); + }) + } + }; +} + +map_insert_rand_bench! {insert_rand_100, 100, BTreeMap} +map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap} + +map_insert_seq_bench! {insert_seq_100, 100, BTreeMap} +map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap} + +map_find_rand_bench! {find_rand_100, 100, BTreeMap} +map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap} + +map_find_seq_bench! {find_seq_100, 100, BTreeMap} +map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap} + +fn bench_iteration(b: &mut Bencher, size: i32) { + let mut map = BTreeMap::::new(); + let mut rng = thread_rng(); + + for _ in 0..size { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for entry in &map { + black_box(entry); + } + }); +} + +#[bench] +pub fn iteration_20(b: &mut Bencher) { + bench_iteration(b, 20); +} + +#[bench] +pub fn iteration_1000(b: &mut Bencher) { + bench_iteration(b, 1000); +} + +#[bench] +pub fn iteration_100000(b: &mut Bencher) { + bench_iteration(b, 100000); +} + +fn bench_iteration_mut(b: &mut Bencher, size: i32) { + let mut map = BTreeMap::::new(); + let mut rng = thread_rng(); + + for _ in 0..size { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for kv in map.iter_mut() { + black_box(kv); + } + }); +} + +#[bench] +pub fn iteration_mut_20(b: &mut Bencher) { + bench_iteration_mut(b, 20); +} + +#[bench] +pub fn iteration_mut_1000(b: &mut Bencher) { + bench_iteration_mut(b, 1000); +} + +#[bench] +pub fn iteration_mut_100000(b: &mut Bencher) { + bench_iteration_mut(b, 100000); +} + +fn bench_first_and_last(b: &mut Bencher, size: i32) { + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + b.iter(|| { + for _ in 0..10 { + black_box(map.first_key_value()); + black_box(map.last_key_value()); + } + }); +} + +#[bench] +pub fn first_and_last_0(b: &mut Bencher) { + bench_first_and_last(b, 0); +} + +#[bench] +pub fn first_and_last_100(b: &mut Bencher) { + bench_first_and_last(b, 100); +} + +#[bench] +pub fn first_and_last_10k(b: &mut Bencher) { + bench_first_and_last(b, 10_000); +} + +const BENCH_RANGE_SIZE: i32 = 145; +const BENCH_RANGE_COUNT: i32 = BENCH_RANGE_SIZE * (BENCH_RANGE_SIZE - 1) / 2; + +fn bench_range(b: &mut Bencher, f: F) +where + F: Fn(i32, i32) -> R, + R: RangeBounds, +{ + let map: BTreeMap<_, _> = (0..BENCH_RANGE_SIZE).map(|i| (i, i)).collect(); + b.iter(|| { + let mut c = 0; + for i in 0..BENCH_RANGE_SIZE { + for j in i + 1..BENCH_RANGE_SIZE { + black_box(map.range(f(i, j))); + c += 1; + } + } + debug_assert_eq!(c, BENCH_RANGE_COUNT); + }); +} + +#[bench] +pub fn range_included_excluded(b: &mut Bencher) { + bench_range(b, |i, j| i..j); +} + +#[bench] +pub fn range_included_included(b: &mut Bencher) { + bench_range(b, |i, j| i..=j); +} + +#[bench] +pub fn range_included_unbounded(b: &mut Bencher) { + bench_range(b, |i, _| i..); +} + +#[bench] +pub fn range_unbounded_unbounded(b: &mut Bencher) { + bench_range(b, |_, _| ..); +} + +fn bench_iter(b: &mut Bencher, repeats: i32, size: i32) { + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + b.iter(|| { + for _ in 0..repeats { + black_box(map.iter()); + } + }); +} + +/// Contrast range_unbounded_unbounded with `iter()`. +#[bench] +pub fn range_unbounded_vs_iter(b: &mut Bencher) { + bench_iter(b, BENCH_RANGE_COUNT, BENCH_RANGE_SIZE); +} + +#[bench] +pub fn iter_0(b: &mut Bencher) { + bench_iter(b, 1_000, 0); +} + +#[bench] +pub fn iter_1(b: &mut Bencher) { + bench_iter(b, 1_000, 1); +} + +#[bench] +pub fn iter_100(b: &mut Bencher) { + bench_iter(b, 1_000, 100); +} + +#[bench] +pub fn iter_10k(b: &mut Bencher) { + bench_iter(b, 1_000, 10_000); +} + +#[bench] +pub fn iter_1m(b: &mut Bencher) { + bench_iter(b, 1_000, 1_000_000); +} + +const FAT: usize = 256; + +// The returned map has small keys and values. +// Benchmarks on it have a counterpart in set.rs with the same keys and no values at all. +fn slim_map(n: usize) -> BTreeMap { + (0..n).map(|i| (i, i)).collect::>() +} + +// The returned map has small keys and large values. +fn fat_val_map(n: usize) -> BTreeMap { + (0..n).map(|i| (i, [i; FAT])).collect::>() +} + +#[bench] +pub fn clone_slim_100(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| src.clone()) +} + +#[bench] +pub fn clone_slim_100_and_clear(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| src.clone().clear()) +} + +#[bench] +pub fn clone_slim_100_and_drain_all(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| src.clone().drain_filter(|_, _| true).count()) +} + +#[bench] +pub fn clone_slim_100_and_drain_half(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| { + let mut map = src.clone(); + assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 100 / 2); + assert_eq!(map.len(), 100 / 2); + }) +} + +#[bench] +pub fn clone_slim_100_and_into_iter(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| src.clone().into_iter().count()) +} + +#[bench] +pub fn clone_slim_100_and_pop_all(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| { + let mut map = src.clone(); + while map.pop_first().is_some() {} + map + }); +} + +#[bench] +pub fn clone_slim_100_and_remove_all(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| { + let mut map = src.clone(); + while let Some(elt) = map.iter().map(|(&i, _)| i).next() { + let v = map.remove(&elt); + debug_assert!(v.is_some()); + } + map + }); +} + +#[bench] +pub fn clone_slim_100_and_remove_half(b: &mut Bencher) { + let src = slim_map(100); + b.iter(|| { + let mut map = src.clone(); + for i in (0..100).step_by(2) { + let v = map.remove(&i); + debug_assert!(v.is_some()); + } + assert_eq!(map.len(), 100 / 2); + map + }) +} + +#[bench] +pub fn clone_slim_10k(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| src.clone()) +} + +#[bench] +pub fn clone_slim_10k_and_clear(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| src.clone().clear()) +} + +#[bench] +pub fn clone_slim_10k_and_drain_all(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| src.clone().drain_filter(|_, _| true).count()) +} + +#[bench] +pub fn clone_slim_10k_and_drain_half(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| { + let mut map = src.clone(); + assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 10_000 / 2); + assert_eq!(map.len(), 10_000 / 2); + }) +} + +#[bench] +pub fn clone_slim_10k_and_into_iter(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| src.clone().into_iter().count()) +} + +#[bench] +pub fn clone_slim_10k_and_pop_all(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| { + let mut map = src.clone(); + while map.pop_first().is_some() {} + map + }); +} + +#[bench] +pub fn clone_slim_10k_and_remove_all(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| { + let mut map = src.clone(); + while let Some(elt) = map.iter().map(|(&i, _)| i).next() { + let v = map.remove(&elt); + debug_assert!(v.is_some()); + } + map + }); +} + +#[bench] +pub fn clone_slim_10k_and_remove_half(b: &mut Bencher) { + let src = slim_map(10_000); + b.iter(|| { + let mut map = src.clone(); + for i in (0..10_000).step_by(2) { + let v = map.remove(&i); + debug_assert!(v.is_some()); + } + assert_eq!(map.len(), 10_000 / 2); + map + }) +} + +#[bench] +pub fn clone_fat_val_100(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| src.clone()) +} + +#[bench] +pub fn clone_fat_val_100_and_clear(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| src.clone().clear()) +} + +#[bench] +pub fn clone_fat_val_100_and_drain_all(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| src.clone().drain_filter(|_, _| true).count()) +} + +#[bench] +pub fn clone_fat_val_100_and_drain_half(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| { + let mut map = src.clone(); + assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 100 / 2); + assert_eq!(map.len(), 100 / 2); + }) +} + +#[bench] +pub fn clone_fat_val_100_and_into_iter(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| src.clone().into_iter().count()) +} + +#[bench] +pub fn clone_fat_val_100_and_pop_all(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| { + let mut map = src.clone(); + while map.pop_first().is_some() {} + map + }); +} + +#[bench] +pub fn clone_fat_val_100_and_remove_all(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| { + let mut map = src.clone(); + while let Some(elt) = map.iter().map(|(&i, _)| i).next() { + let v = map.remove(&elt); + debug_assert!(v.is_some()); + } + map + }); +} + +#[bench] +pub fn clone_fat_val_100_and_remove_half(b: &mut Bencher) { + let src = fat_val_map(100); + b.iter(|| { + let mut map = src.clone(); + for i in (0..100).step_by(2) { + let v = map.remove(&i); + debug_assert!(v.is_some()); + } + assert_eq!(map.len(), 100 / 2); + map + }) +} +use std::collections::BTreeSet; + +use rand::{thread_rng, Rng}; +use test::Bencher; + +fn random(n: usize) -> BTreeSet { + let mut rng = thread_rng(); + let mut set = BTreeSet::new(); + while set.len() < n { + set.insert(rng.gen()); + } + assert_eq!(set.len(), n); + set +} + +fn neg(n: usize) -> BTreeSet { + let set: BTreeSet = (-(n as i32)..=-1).collect(); + assert_eq!(set.len(), n); + set +} + +fn pos(n: usize) -> BTreeSet { + let set: BTreeSet = (1..=(n as i32)).collect(); + assert_eq!(set.len(), n); + set +} + +fn stagger(n1: usize, factor: usize) -> [BTreeSet; 2] { + let n2 = n1 * factor; + let mut sets = [BTreeSet::new(), BTreeSet::new()]; + for i in 0..(n1 + n2) { + let b = i % (factor + 1) != 0; + sets[b as usize].insert(i as u32); + } + assert_eq!(sets[0].len(), n1); + assert_eq!(sets[1].len(), n2); + sets +} + +macro_rules! set_bench { + ($name: ident, $set_func: ident, $result_func: ident, $sets: expr) => { + #[bench] + pub fn $name(b: &mut Bencher) { + // setup + let sets = $sets; + + // measure + b.iter(|| sets[0].$set_func(&sets[1]).$result_func()) + } + }; +} + +fn slim_set(n: usize) -> BTreeSet { + (0..n).collect::>() +} + +#[bench] +pub fn clone_100(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| src.clone()) +} + +#[bench] +pub fn clone_100_and_clear(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| src.clone().clear()) +} + +#[bench] +pub fn clone_100_and_drain_all(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| src.clone().drain_filter(|_| true).count()) +} + +#[bench] +pub fn clone_100_and_drain_half(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| { + let mut set = src.clone(); + assert_eq!(set.drain_filter(|i| i % 2 == 0).count(), 100 / 2); + assert_eq!(set.len(), 100 / 2); + }) +} + +#[bench] +pub fn clone_100_and_into_iter(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| src.clone().into_iter().count()) +} + +#[bench] +pub fn clone_100_and_pop_all(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| { + let mut set = src.clone(); + while set.pop_first().is_some() {} + set + }); +} + +#[bench] +pub fn clone_100_and_remove_all(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| { + let mut set = src.clone(); + while let Some(elt) = set.iter().copied().next() { + let ok = set.remove(&elt); + debug_assert!(ok); + } + set + }); +} + +#[bench] +pub fn clone_100_and_remove_half(b: &mut Bencher) { + let src = slim_set(100); + b.iter(|| { + let mut set = src.clone(); + for i in (0..100).step_by(2) { + let ok = set.remove(&i); + debug_assert!(ok); + } + assert_eq!(set.len(), 100 / 2); + set + }) +} + +#[bench] +pub fn clone_10k(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| src.clone()) +} + +#[bench] +pub fn clone_10k_and_clear(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| src.clone().clear()) +} + +#[bench] +pub fn clone_10k_and_drain_all(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| src.clone().drain_filter(|_| true).count()) +} + +#[bench] +pub fn clone_10k_and_drain_half(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| { + let mut set = src.clone(); + assert_eq!(set.drain_filter(|i| i % 2 == 0).count(), 10_000 / 2); + assert_eq!(set.len(), 10_000 / 2); + }) +} + +#[bench] +pub fn clone_10k_and_into_iter(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| src.clone().into_iter().count()) +} + +#[bench] +pub fn clone_10k_and_pop_all(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| { + let mut set = src.clone(); + while set.pop_first().is_some() {} + set + }); +} + +#[bench] +pub fn clone_10k_and_remove_all(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| { + let mut set = src.clone(); + while let Some(elt) = set.iter().copied().next() { + let ok = set.remove(&elt); + debug_assert!(ok); + } + set + }); +} + +#[bench] +pub fn clone_10k_and_remove_half(b: &mut Bencher) { + let src = slim_set(10_000); + b.iter(|| { + let mut set = src.clone(); + for i in (0..10_000).step_by(2) { + let ok = set.remove(&i); + debug_assert!(ok); + } + assert_eq!(set.len(), 10_000 / 2); + set + }) +} + +set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]} +set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]} +set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]} +set_bench! {intersection_100_pos_vs_10k_neg, intersection, count, [pos(100), neg(10_000)]} +set_bench! {intersection_10k_neg_vs_100_pos, intersection, count, [neg(10_000), pos(100)]} +set_bench! {intersection_10k_neg_vs_10k_pos, intersection, count, [neg(10_000), pos(10_000)]} +set_bench! {intersection_10k_pos_vs_100_neg, intersection, count, [pos(10_000), neg(100)]} +set_bench! {intersection_10k_pos_vs_10k_neg, intersection, count, [pos(10_000), neg(10_000)]} +set_bench! {intersection_random_100_vs_100, intersection, count, [random(100), random(100)]} +set_bench! {intersection_random_100_vs_10k, intersection, count, [random(100), random(10_000)]} +set_bench! {intersection_random_10k_vs_100, intersection, count, [random(10_000), random(100)]} +set_bench! {intersection_random_10k_vs_10k, intersection, count, [random(10_000), random(10_000)]} +set_bench! {intersection_staggered_100_vs_100, intersection, count, stagger(100, 1)} +set_bench! {intersection_staggered_10k_vs_10k, intersection, count, stagger(10_000, 1)} +set_bench! {intersection_staggered_100_vs_10k, intersection, count, stagger(100, 100)} +set_bench! {difference_random_100_vs_100, difference, count, [random(100), random(100)]} +set_bench! {difference_random_100_vs_10k, difference, count, [random(100), random(10_000)]} +set_bench! {difference_random_10k_vs_100, difference, count, [random(10_000), random(100)]} +set_bench! {difference_random_10k_vs_10k, difference, count, [random(10_000), random(10_000)]} +set_bench! {difference_staggered_100_vs_100, difference, count, stagger(100, 1)} +set_bench! {difference_staggered_10k_vs_10k, difference, count, stagger(10_000, 1)} +set_bench! {difference_staggered_100_vs_10k, difference, count, stagger(100, 100)} +set_bench! {is_subset_100_vs_100, is_subset, clone, [pos(100), pos(100)]} +set_bench! {is_subset_100_vs_10k, is_subset, clone, [pos(100), pos(10_000)]} +set_bench! {is_subset_10k_vs_100, is_subset, clone, [pos(10_000), pos(100)]} +set_bench! {is_subset_10k_vs_10k, is_subset, clone, [pos(10_000), pos(10_000)]} +mod map; +mod set; +use std::{mem, ptr}; + +use rand::distributions::{Alphanumeric, Standard}; +use rand::{thread_rng, Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; +use test::{black_box, Bencher}; + +#[bench] +fn iterator(b: &mut Bencher) { + // peculiar numbers to stop LLVM from optimising the summation + // out. + let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); + + b.iter(|| { + let mut sum = 0; + for x in &v { + sum += *x; + } + // sum == 11806, to stop dead code elimination. + if sum == 0 { + panic!() + } + }) +} + +#[bench] +fn mut_iterator(b: &mut Bencher) { + let mut v = vec![0; 100]; + + b.iter(|| { + let mut i = 0; + for x in &mut v { + *x = i; + i += 1; + } + }) +} + +#[bench] +fn concat(b: &mut Bencher) { + let xss: Vec> = (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.concat(); + }); +} + +#[bench] +fn join(b: &mut Bencher) { + let xss: Vec> = (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| xss.join(&0)); +} + +#[bench] +fn push(b: &mut Bencher) { + let mut vec = Vec::::new(); + b.iter(|| { + vec.push(0); + black_box(&vec); + }); +} + +#[bench] +fn starts_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| vec.starts_with(&vec)) +} + +#[bench] +fn starts_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| vec.starts_with(&vec)) +} + +#[bench] +fn starts_with_diff_one_element_at_end(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..99).collect(); + match_vec.push(0); + b.iter(|| vec.starts_with(&match_vec)) +} + +#[bench] +fn ends_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| vec.ends_with(&vec)) +} + +#[bench] +fn ends_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| vec.ends_with(&vec)) +} + +#[bench] +fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..100).collect(); + match_vec[0] = 200; + b.iter(|| vec.starts_with(&match_vec)) +} + +#[bench] +fn contains_last_element(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| vec.contains(&99)) +} + +#[bench] +fn zero_1kb_from_elem(b: &mut Bencher) { + b.iter(|| vec![0u8; 1024]); +} + +#[bench] +fn zero_1kb_set_memory(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + let vp = v.as_mut_ptr(); + ptr::write_bytes(vp, 0, 1024); + v.set_len(1024); + } + v + }); +} + +#[bench] +fn zero_1kb_loop_set(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for i in 0..1024 { + v[i] = 0; + } + }); +} + +#[bench] +fn zero_1kb_mut_iter(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for x in &mut v { + *x = 0; + } + v + }); +} + +#[bench] +fn random_inserts(b: &mut Bencher) { + let mut rng = thread_rng(); + b.iter(|| { + let mut v = vec![(0, 0); 30]; + for _ in 0..100 { + let l = v.len(); + v.insert(rng.gen::() % (l + 1), (1, 1)); + } + }) +} + +#[bench] +fn random_removes(b: &mut Bencher) { + let mut rng = thread_rng(); + b.iter(|| { + let mut v = vec![(0, 0); 130]; + for _ in 0..100 { + let l = v.len(); + v.remove(rng.gen::() % l); + } + }) +} + +fn gen_ascending(len: usize) -> Vec { + (0..len as u64).collect() +} + +fn gen_descending(len: usize) -> Vec { + (0..len as u64).rev().collect() +} + +const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + +fn gen_random(len: usize) -> Vec { + let mut rng = XorShiftRng::from_seed(SEED); + (&mut rng).sample_iter(&Standard).take(len).collect() +} + +fn gen_random_bytes(len: usize) -> Vec { + let mut rng = XorShiftRng::from_seed(SEED); + (&mut rng).sample_iter(&Standard).take(len).collect() +} + +fn gen_mostly_ascending(len: usize) -> Vec { + let mut rng = XorShiftRng::from_seed(SEED); + let mut v = gen_ascending(len); + for _ in (0usize..).take_while(|x| x * x <= len) { + let x = rng.gen::() % len; + let y = rng.gen::() % len; + v.swap(x, y); + } + v +} + +fn gen_mostly_descending(len: usize) -> Vec { + let mut rng = XorShiftRng::from_seed(SEED); + let mut v = gen_descending(len); + for _ in (0usize..).take_while(|x| x * x <= len) { + let x = rng.gen::() % len; + let y = rng.gen::() % len; + v.swap(x, y); + } + v +} + +fn gen_strings(len: usize) -> Vec { + let mut rng = XorShiftRng::from_seed(SEED); + let mut v = vec![]; + for _ in 0..len { + let n = rng.gen::() % 20 + 1; + v.push((&mut rng).sample_iter(&Alphanumeric).take(n).collect()); + } + v +} + +fn gen_big_random(len: usize) -> Vec<[u64; 16]> { + let mut rng = XorShiftRng::from_seed(SEED); + (&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect() +} + +macro_rules! sort { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + b.iter(|| v.clone().$f()); + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; + } + }; +} + +macro_rules! sort_strings { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + let v = v.iter().map(|s| &**s).collect::>(); + b.iter(|| v.clone().$f()); + b.bytes = $len * mem::size_of::<&str>() as u64; + } + }; +} + +macro_rules! sort_expensive { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + b.iter(|| { + let mut v = v.clone(); + let mut count = 0; + v.$f(|a: &u64, b: &u64| { + count += 1; + if count % 1_000_000_000 == 0 { + panic!("should not happen"); + } + (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap() + }); + black_box(count); + }); + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; + } + }; +} + +macro_rules! sort_lexicographic { + ($f:ident, $name:ident, $gen:expr, $len:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let v = $gen($len); + b.iter(|| v.clone().$f(|x| x.to_string())); + b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; + } + }; +} + +sort!(sort, sort_small_ascending, gen_ascending, 10); +sort!(sort, sort_small_descending, gen_descending, 10); +sort!(sort, sort_small_random, gen_random, 10); +sort!(sort, sort_small_big, gen_big_random, 10); +sort!(sort, sort_medium_random, gen_random, 100); +sort!(sort, sort_large_ascending, gen_ascending, 10000); +sort!(sort, sort_large_descending, gen_descending, 10000); +sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000); +sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000); +sort!(sort, sort_large_random, gen_random, 10000); +sort!(sort, sort_large_big, gen_big_random, 10000); +sort_strings!(sort, sort_large_strings, gen_strings, 10000); +sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000); + +sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10); +sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10); +sort!(sort_unstable, sort_unstable_small_random, gen_random, 10); +sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10); +sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100); +sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000); +sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000); +sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000); +sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000); +sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000); +sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); +sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); +sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); + +sort_lexicographic!(sort_by_key, sort_by_key_lexicographic, gen_random, 10000); +sort_lexicographic!(sort_unstable_by_key, sort_unstable_by_key_lexicographic, gen_random, 10000); +sort_lexicographic!(sort_by_cached_key, sort_by_cached_key_lexicographic, gen_random, 10000); + +macro_rules! reverse { + ($name:ident, $ty:ty, $f:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + // odd length and offset by 1 to be as unaligned as possible + let n = 0xFFFFF; + let mut v: Vec<_> = (0..1 + (n / mem::size_of::<$ty>() as u64)).map($f).collect(); + b.iter(|| black_box(&mut v[1..]).reverse()); + b.bytes = n; + } + }; +} + +reverse!(reverse_u8, u8, |x| x as u8); +reverse!(reverse_u16, u16, |x| x as u16); +reverse!(reverse_u8x3, [u8; 3], |x| [x as u8, (x >> 8) as u8, (x >> 16) as u8]); +reverse!(reverse_u32, u32, |x| x as u32); +reverse!(reverse_u64, u64, |x| x as u64); +reverse!(reverse_u128, u128, |x| x as u128); +#[repr(simd)] +struct F64x4(f64, f64, f64, f64); +reverse!(reverse_simd_f64x4, F64x4, |x| { + let x = x as f64; + F64x4(x, x, x, x) +}); + +macro_rules! rotate { + ($name:ident, $gen:expr, $len:expr, $mid:expr) => { + #[bench] + fn $name(b: &mut Bencher) { + let size = mem::size_of_val(&$gen(1)[0]); + let mut v = $gen($len * 8 / size); + b.iter(|| black_box(&mut v).rotate_left(($mid * 8 + size - 1) / size)); + b.bytes = (v.len() * size) as u64; + } + }; +} + +rotate!(rotate_tiny_by1, gen_random, 16, 1); +rotate!(rotate_tiny_half, gen_random, 16, 16 / 2); +rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16 / 2 + 1); + +rotate!(rotate_medium_by1, gen_random, 9158, 1); +rotate!(rotate_medium_by727_u64, gen_random, 9158, 727); +rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727); +rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727); +rotate!(rotate_medium_half, gen_random, 9158, 9158 / 2); +rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158 / 2 + 1); + +// Intended to use more RAM than the machine has cache +rotate!(rotate_huge_by1, gen_random, 5 * 1024 * 1024, 1); +rotate!(rotate_huge_by9199_u64, gen_random, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by9199_strings, gen_strings, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by9199_big, gen_big_random, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by1234577_u64, gen_random, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_by1234577_strings, gen_strings, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_by1234577_big, gen_big_random, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_half, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2); +rotate!(rotate_huge_half_plus_one, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2 + 1); +use std::collections::VecDeque; +use test::{black_box, Bencher}; + +#[bench] +fn bench_new(b: &mut Bencher) { + b.iter(|| { + let ring: VecDeque = VecDeque::new(); + black_box(ring); + }) +} + +#[bench] +fn bench_grow_1025(b: &mut Bencher) { + b.iter(|| { + let mut deq = VecDeque::new(); + for i in 0..1025 { + deq.push_front(i); + } + black_box(deq); + }) +} + +#[bench] +fn bench_iter_1000(b: &mut Bencher) { + let ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for &i in &ring { + sum += i; + } + black_box(sum); + }) +} + +#[bench] +fn bench_mut_iter_1000(b: &mut Bencher) { + let mut ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for i in &mut ring { + sum += *i; + } + black_box(sum); + }) +} + +#[bench] +fn bench_try_fold(b: &mut Bencher) { + let ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b)))) +} +use std::collections::BinaryHeap; + +use rand::{seq::SliceRandom, thread_rng}; +use test::{black_box, Bencher}; + +#[bench] +fn bench_find_smallest_1000(b: &mut Bencher) { + let mut rng = thread_rng(); + let mut vec: Vec = (0..100_000).collect(); + vec.shuffle(&mut rng); + + b.iter(|| { + let mut iter = vec.iter().copied(); + let mut heap: BinaryHeap<_> = iter.by_ref().take(1000).collect(); + + for x in iter { + let mut max = heap.peek_mut().unwrap(); + // This comparison should be true only 1% of the time. + // Unnecessary `sift_down`s will degrade performance + if x < *max { + *max = x; + } + } + + heap + }) +} + +#[bench] +fn bench_peek_mut_deref_mut(b: &mut Bencher) { + let mut bheap = BinaryHeap::from(vec![42]); + let vec: Vec = (0..1_000_000).collect(); + + b.iter(|| { + let vec = black_box(&vec); + let mut peek_mut = bheap.peek_mut().unwrap(); + // The compiler shouldn't be able to optimize away the `sift_down` + // assignment in `PeekMut`'s `DerefMut` implementation since + // the loop may not run. + for &i in vec.iter() { + *peek_mut = i; + } + // Remove the already minimal overhead of the sift_down + std::mem::forget(peek_mut); + }) +} + +#[bench] +fn bench_from_vec(b: &mut Bencher) { + let mut rng = thread_rng(); + let mut vec: Vec = (0..100_000).collect(); + vec.shuffle(&mut rng); + + b.iter(|| BinaryHeap::from(vec.clone())) +} + +#[bench] +fn bench_into_sorted_vec(b: &mut Bencher) { + let bheap: BinaryHeap = (0..10_000).collect(); + + b.iter(|| bheap.clone().into_sorted_vec()) +} + +#[bench] +fn bench_push(b: &mut Bencher) { + let mut bheap = BinaryHeap::with_capacity(50_000); + let mut rng = thread_rng(); + let mut vec: Vec = (0..50_000).collect(); + vec.shuffle(&mut rng); + + b.iter(|| { + for &i in vec.iter() { + bheap.push(i); + } + black_box(&mut bheap); + bheap.clear(); + }) +} + +#[bench] +fn bench_pop(b: &mut Bencher) { + let mut bheap = BinaryHeap::with_capacity(10_000); + + b.iter(|| { + bheap.extend((0..10_000).rev()); + black_box(&mut bheap); + while let Some(elem) = bheap.pop() { + black_box(elem); + } + }) +} +use std::{collections::VecDeque, time::Instant}; + +const VECDEQUE_LEN: i32 = 100000; +const WARMUP_N: usize = 100; +const BENCH_N: usize = 1000; + +fn main() { + let a: VecDeque = (0..VECDEQUE_LEN).collect(); + let b: VecDeque = (0..VECDEQUE_LEN).collect(); + + for _ in 0..WARMUP_N { + let mut c = a.clone(); + let mut d = b.clone(); + c.append(&mut d); + } + + let mut durations = Vec::with_capacity(BENCH_N); + + for _ in 0..BENCH_N { + let mut c = a.clone(); + let mut d = b.clone(); + let before = Instant::now(); + c.append(&mut d); + let after = Instant::now(); + durations.push(after.duration_since(before)); + } + + let l = durations.len(); + durations.sort(); + + assert!(BENCH_N % 2 == 0); + let median = (durations[(l / 2) - 1] + durations[l / 2]) / 2; + println!("\ncustom-bench vec_deque_append {:?} ns/iter\n", median.as_nanos()); +} +use std::collections::LinkedList; +use std::panic::{catch_unwind, AssertUnwindSafe}; + +#[test] +fn test_basic() { + let mut m = LinkedList::>::new(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(box 1); + assert_eq!(m.pop_front(), Some(box 1)); + m.push_back(box 2); + m.push_back(box 3); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(box 2)); + assert_eq!(m.pop_front(), Some(box 3)); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(box 1); + m.push_back(box 3); + m.push_back(box 5); + m.push_back(box 7); + assert_eq!(m.pop_front(), Some(box 1)); + + let mut n = LinkedList::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.front().unwrap(), &3); + let x = n.front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.back().unwrap(), &2); + let y = n.back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); +} + +fn generate_test() -> LinkedList { + list_from(&[0, 1, 2, 3, 4, 5, 6]) +} + +fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() +} + +#[test] +fn test_split_off() { + // singleton + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(0); + assert_eq!(m.len(), 0); + assert_eq!(p.len(), 1); + assert_eq!(p.back(), Some(&1)); + assert_eq!(p.front(), Some(&1)); + } + + // not singleton, forwards + { + let u = vec![1, 2, 3, 4, 5]; + let mut m = list_from(&u); + let mut n = m.split_off(2); + assert_eq!(m.len(), 2); + assert_eq!(n.len(), 3); + for elt in 1..3 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 3..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + // not singleton, backwards + { + let u = vec![1, 2, 3, 4, 5]; + let mut m = list_from(&u); + let mut n = m.split_off(4); + assert_eq!(m.len(), 4); + assert_eq!(n.len(), 1); + for elt in 1..5 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 5..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + + // no-op on the last index + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(1); + assert_eq!(m.len(), 1); + assert_eq!(p.len(), 0); + assert_eq!(m.back(), Some(&1)); + assert_eq!(m.front(), Some(&1)); + } +} + +#[test] +fn test_iterator() { + let m = generate_test(); + for (i, elt) in m.iter().enumerate() { + assert_eq!(i as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iterator_clone() { + let mut n = LinkedList::new(); + n.push_back(2); + n.push_back(3); + n.push_back(4); + let mut it = n.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next_back(), jt.next_back()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_iterator_double_end() { + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next_back().unwrap(), &5); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn test_rev_iter() { + let m = generate_test(); + for (i, elt) in m.iter().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().rev().next(), None); + n.push_front(4); + let mut it = n.iter().rev(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for (i, elt) in m.iter_mut().enumerate() { + assert_eq!(i as i32, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = LinkedList::new(); + assert!(n.iter_mut().next().is_none()); + n.push_front(4); + n.push_back(5); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next().is_some()); + assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_mut_double_end() { + let mut n = LinkedList::new(); + assert!(n.iter_mut().next_back().is_none()); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(*it.next().unwrap(), 6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(*it.next_back().unwrap(), 4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(*it.next_back().unwrap(), 5); + assert!(it.next_back().is_none()); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iter() { + let mut m = generate_test(); + for (i, elt) in m.iter_mut().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert!(n.iter_mut().rev().next().is_none()); + n.push_front(4); + let mut it = n.iter_mut().rev(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] +fn test_eq() { + let mut n = list_from(&[]); + let mut m = list_from(&[]); + assert!(n == m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert!(n == m); + + let n = list_from(&[2, 3, 4]); + let m = list_from(&[1, 2, 3]); + assert!(n != m); +} + +#[test] +fn test_hash() { + use crate::hash; + + let mut x = LinkedList::new(); + let mut y = LinkedList::new(); + + assert!(hash(&x) == hash(&y)); + + x.push_back(1); + x.push_back(2); + x.push_back(3); + + y.push_front(3); + y.push_front(2); + y.push_front(1); + + assert!(hash(&x) == hash(&y)); +} + +#[test] +fn test_ord() { + let n = list_from(&[]); + let m = list_from(&[1, 2, 3]); + assert!(n < m); + assert!(m > n); + assert!(n <= n); + assert!(n >= n); +} + +#[test] +fn test_ord_nan() { + let nan = 0.0f64 / 0.0; + let n = list_from(&[nan]); + let m = list_from(&[nan]); + assert!(!(n < m)); + assert!(!(n > m)); + assert!(!(n <= m)); + assert!(!(n >= m)); + + let n = list_from(&[nan]); + let one = list_from(&[1.0f64]); + assert!(!(n < one)); + assert!(!(n > one)); + assert!(!(n <= one)); + assert!(!(n >= one)); + + let u = list_from(&[1.0f64, 2.0, nan]); + let v = list_from(&[1.0f64, 2.0, 3.0]); + assert!(!(u < v)); + assert!(!(u > v)); + assert!(!(u <= v)); + assert!(!(u >= v)); + + let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]); + let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]); + assert!(!(s < t)); + assert!(s > one); + assert!(!(s <= one)); + assert!(s >= one); +} + +#[test] +fn test_show() { + let list: LinkedList<_> = (0..10).collect(); + assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); + assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[test] +fn test_extend_ref() { + let mut a = LinkedList::new(); + a.push_back(1); + + a.extend(&[2, 3, 4]); + + assert_eq!(a.len(), 4); + assert_eq!(a, list_from(&[1, 2, 3, 4])); + + let mut b = LinkedList::new(); + b.push_back(5); + b.push_back(6); + a.extend(&b); + + assert_eq!(a.len(), 6); + assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6])); +} + +#[test] +fn test_extend() { + let mut a = LinkedList::new(); + a.push_back(1); + a.extend(vec![2, 3, 4]); // uses iterator + + assert_eq!(a.len(), 4); + assert!(a.iter().eq(&[1, 2, 3, 4])); + + let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect(); + a.extend(b); // specializes to `append` + + assert_eq!(a.len(), 7); + assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7])); +} + +#[test] +fn test_contains() { + let mut l = LinkedList::new(); + l.extend(&[2, 3, 4]); + + assert!(l.contains(&3)); + assert!(!l.contains(&1)); + + l.clear(); + + assert!(!l.contains(&3)); +} + +#[test] +fn drain_filter_empty() { + let mut list: LinkedList = LinkedList::new(); + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn drain_filter_zst() { + let mut list: LinkedList<_> = vec![(), (), (), (), ()].into_iter().collect(); + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn drain_filter_false() { + let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(list.len(), initial_len); + assert_eq!(list.into_iter().collect::>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn drain_filter_true() { + let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + let initial_len = list.len(); + let mut count = 0; + + { + let mut iter = list.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(list.len(), 0); + assert_eq!(list.into_iter().collect::>(), vec![]); +} + +#[test] +fn drain_filter_complex() { + { + // [+xxx++++++xxxxx++++x+x++] + let mut list = vec![ + 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, + 39, + ] + .into_iter() + .collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 14); + assert_eq!( + list.into_iter().collect::>(), + vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] + ); + } + + { + // [xxx++++++xxxxx++++x+x++] + let mut list = vec![ + 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39, + ] + .into_iter() + .collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 13); + assert_eq!( + list.into_iter().collect::>(), + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] + ); + } + + { + // [xxx++++++xxxxx++++x+x] + let mut list = + vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36] + .into_iter() + .collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(list.len(), 11); + assert_eq!( + list.into_iter().collect::>(), + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35] + ); + } + + { + // [xxxxxxxxxx+++++++++++] + let mut list = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] + .into_iter() + .collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { + // [+++++++++++xxxxxxxxxx] + let mut list = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + .into_iter() + .collect::>(); + + let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(list.len(), 10); + assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} + +#[test] +fn drain_filter_drop_panic_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + q.push_front(D(false)); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok(); + + assert_eq!(unsafe { DROPS }, 8); + assert!(q.is_empty()); +} + +#[test] +fn drain_filter_pred_panic_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug)] + struct D(u32); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(3)); + q.push_back(D(4)); + q.push_back(D(5)); + q.push_back(D(6)); + q.push_back(D(7)); + q.push_front(D(2)); + q.push_front(D(1)); + q.push_front(D(0)); + + catch_unwind(AssertUnwindSafe(|| { + drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true })) + })) + .ok(); + + assert_eq!(unsafe { DROPS }, 2); // 0 and 1 + assert_eq!(q.len(), 6); +} + +#[test] +fn test_drop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe { DROPS }, 2); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_clear() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe { DROPS }, 4); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} +use std::any::Any; +use std::cell::RefCell; +use std::cmp::PartialEq; +use std::iter::TrustedLen; +use std::mem; +use std::sync::{Arc, Weak}; + +#[test] +fn uninhabited() { + enum Void {} + let mut a = Weak::::new(); + a = a.clone(); + assert!(a.upgrade().is_none()); + + let mut a: Weak = a; // Unsizing + a = a.clone(); + assert!(a.upgrade().is_none()); +} + +#[test] +fn slice() { + let a: Arc<[u32; 3]> = Arc::new([3, 2, 1]); + let a: Arc<[u32]> = a; // Unsizing + let b: Arc<[u32]> = Arc::from(&[3, 2, 1][..]); // Conversion + assert_eq!(a, b); + + // Exercise is_dangling() with a DST + let mut a = Arc::downgrade(&a); + a = a.clone(); + assert!(a.upgrade().is_some()); +} + +#[test] +fn trait_object() { + let a: Arc = Arc::new(4); + let a: Arc = a; // Unsizing + + // Exercise is_dangling() with a DST + let mut a = Arc::downgrade(&a); + a = a.clone(); + assert!(a.upgrade().is_some()); + + let mut b = Weak::::new(); + b = b.clone(); + assert!(b.upgrade().is_none()); + let mut b: Weak = b; // Unsizing + b = b.clone(); + assert!(b.upgrade().is_none()); +} + +#[test] +fn float_nan_ne() { + let x = Arc::new(f32::NAN); + assert!(x != x); + assert!(!(x == x)); +} + +#[test] +fn partial_eq() { + struct TestPEq(RefCell); + impl PartialEq for TestPEq { + fn eq(&self, other: &TestPEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Arc::new(TestPEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 4); +} + +#[test] +fn eq() { + #[derive(Eq)] + struct TestEq(RefCell); + impl PartialEq for TestEq { + fn eq(&self, other: &TestEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Arc::new(TestEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 0); +} + +// The test code below is identical to that in `rc.rs`. +// For better maintainability we therefore define this type alias. +type Rc = Arc; + +const SHARED_ITER_MAX: u16 = 100; + +fn assert_trusted_len(_: &I) {} + +#[test] +fn shared_from_iter_normal() { + // Exercise the base implementation for non-`TrustedLen` iterators. + { + // `Filter` is never `TrustedLen` since we don't + // know statically how many elements will be kept: + let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new); + + // Collecting into a `Vec` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::>(); + let rc = iter.collect::>(); + assert_eq!(&*vec, &*rc); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. +} + +#[test] +fn shared_from_iter_trustedlen_normal() { + // Exercise the `TrustedLen` implementation under normal circumstances + // where `size_hint()` matches `(_, Some(exact_len))`. + { + let iter = (0..SHARED_ITER_MAX).map(Box::new); + assert_trusted_len(&iter); + + // Collecting into a `Vec` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::>(); + let rc = iter.collect::>(); + assert_eq!(&*vec, &*rc); + assert_eq!(mem::size_of::>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc)); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. + + // Try a ZST to make sure it is handled well. + { + let iter = (0..SHARED_ITER_MAX).map(drop); + let vec = iter.clone().collect::>(); + let rc = iter.collect::>(); + assert_eq!(&*vec, &*rc); + assert_eq!(0, mem::size_of_val(&*rc)); + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } +} + +#[test] +#[should_panic = "I've almost got 99 problems."] +fn shared_from_iter_trustedlen_panic() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. + let iter = (0..SHARED_ITER_MAX).map(|val| match val { + 98 => panic!("I've almost got 99 problems."), + _ => Box::new(val), + }); + assert_trusted_len(&iter); + let _ = iter.collect::>(); + + panic!("I am unreachable."); +} + +#[test] +fn shared_from_iter_trustedlen_no_fuse() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner. + struct Iter(std::vec::IntoIter>>); + + unsafe impl TrustedLen for Iter {} + + impl Iterator for Iter { + fn size_hint(&self) -> (usize, Option) { + (2, Some(2)) + } + + type Item = Box; + + fn next(&mut self) -> Option { + self.0.next().flatten() + } + } + + let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))]; + let iter = Iter(vec.into_iter()); + assert_trusted_len(&iter); + assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::>()); +} +use std::borrow::Cow; +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::str::{from_utf8, from_utf8_unchecked}; + +#[test] +fn test_le() { + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert_ne!("foo", "bar"); +} + +#[test] +fn test_find() { + assert_eq!("hello".find('l'), Some(2)); + assert_eq!("hello".find(|c: char| c == 'o'), Some(4)); + assert!("hello".find('x').is_none()); + assert!("hello".find(|c: char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); + assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); +} + +#[test] +fn test_rfind() { + assert_eq!("hello".rfind('l'), Some(3)); + assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4)); + assert!("hello".rfind('x').is_none()); + assert!("hello".rfind(|c: char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); + assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); +} + +#[test] +fn test_collect() { + let empty = ""; + let s: String = empty.chars().collect(); + assert_eq!(empty, s); + let data = "ประเทศไทย中"; + let s: String = data.chars().collect(); + assert_eq!(data, s); +} + +#[test] +fn test_into_bytes() { + let data = String::from("asdf"); + let buf = data.into_bytes(); + assert_eq!(buf, b"asdf"); +} + +#[test] +fn test_find_str() { + // byte positions + assert_eq!("".find(""), Some(0)); + assert!("banana".find("apple pie").is_none()); + + let data = "abcabc"; + assert_eq!(data[0..6].find("ab"), Some(0)); + assert_eq!(data[2..6].find("ab"), Some(3 - 2)); + assert!(data[2..4].find("ab").is_none()); + + let string = "ประเทศไทย中华Việt Nam"; + let mut data = String::from(string); + data.push_str(string); + assert!(data.find("ไท华").is_none()); + assert_eq!(data[0..43].find(""), Some(0)); + assert_eq!(data[6..43].find(""), Some(6 - 6)); + + assert_eq!(data[0..43].find("ประ"), Some(0)); + assert_eq!(data[0..43].find("ทศไ"), Some(12)); + assert_eq!(data[0..43].find("ย中"), Some(24)); + assert_eq!(data[0..43].find("iệt"), Some(34)); + assert_eq!(data[0..43].find("Nam"), Some(40)); + + assert_eq!(data[43..86].find("ประ"), Some(43 - 43)); + assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43)); + assert_eq!(data[43..86].find("ย中"), Some(67 - 43)); + assert_eq!(data[43..86].find("iệt"), Some(77 - 43)); + assert_eq!(data[43..86].find("Nam"), Some(83 - 43)); + + // find every substring -- assert that it finds it, or an earlier occurrence. + let string = "Việt Namacbaabcaabaaba"; + for (i, ci) in string.char_indices() { + let ip = i + ci.len_utf8(); + for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) { + let pat = &string[i..ip + j]; + assert!(match string.find(pat) { + None => false, + Some(x) => x <= i, + }); + assert!(match string.rfind(pat) { + None => false, + Some(x) => x >= i, + }); + } + } +} + +fn s(x: &str) -> String { + x.to_string() +} + +macro_rules! test_concat { + ($expected: expr, $string: expr) => {{ + let s: String = $string.concat(); + assert_eq!($expected, s); + }}; +} + +#[test] +fn test_concat_for_different_types() { + test_concat!("ab", vec![s("a"), s("b")]); + test_concat!("ab", vec!["a", "b"]); +} + +#[test] +fn test_concat_for_different_lengths() { + let empty: &[&str] = &[]; + test_concat!("", empty); + test_concat!("a", ["a"]); + test_concat!("ab", ["a", "b"]); + test_concat!("abc", ["", "a", "bc"]); +} + +macro_rules! test_join { + ($expected: expr, $string: expr, $delim: expr) => {{ + let s = $string.join($delim); + assert_eq!($expected, s); + }}; +} + +#[test] +fn test_join_for_different_types() { + test_join!("a-b", ["a", "b"], "-"); + let hyphen = "-".to_string(); + test_join!("a-b", [s("a"), s("b")], &*hyphen); + test_join!("a-b", vec!["a", "b"], &*hyphen); + test_join!("a-b", &*vec!["a", "b"], "-"); + test_join!("a-b", vec![s("a"), s("b")], "-"); +} + +#[test] +fn test_join_for_different_lengths() { + let empty: &[&str] = &[]; + test_join!("", empty, "-"); + test_join!("a", ["a"], "-"); + test_join!("a-b", ["a", "b"], "-"); + test_join!("-a-bc", ["", "a", "bc"], "-"); +} + +// join has fast paths for small separators up to 4 bytes +// this tests the slow paths. +#[test] +fn test_join_for_different_lengths_with_long_separator() { + assert_eq!("~~~~~".len(), 15); + + let empty: &[&str] = &[]; + test_join!("", empty, "~~~~~"); + test_join!("a", ["a"], "~~~~~"); + test_join!("a~~~~~b", ["a", "b"], "~~~~~"); + test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~"); +} + +#[test] +fn test_join_isue_80335() { + use core::{borrow::Borrow, cell::Cell}; + + struct WeirdBorrow { + state: Cell, + } + + impl Default for WeirdBorrow { + fn default() -> Self { + WeirdBorrow { state: Cell::new(false) } + } + } + + impl Borrow for WeirdBorrow { + fn borrow(&self) -> &str { + let state = self.state.get(); + if state { + "0" + } else { + self.state.set(true); + "123456" + } + } + } + + let arr: [WeirdBorrow; 3] = Default::default(); + test_join!("0-0-0", arr, "-"); +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_unsafe_slice() { + assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) }); + assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) }); + assert_eq!("", unsafe { "abc".get_unchecked(1..1) }); + fn a_million_letter_a() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("aaaaaaaaaa"); + i += 1; + } + rs + } + fn half_a_million_letter_a() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("aaaaa"); + i += 1; + } + rs + } + let letters = a_million_letter_a(); + assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) }); +} + +#[test] +fn test_starts_with() { + assert!("".starts_with("")); + assert!("abc".starts_with("")); + assert!("abc".starts_with("a")); + assert!(!"a".starts_with("abc")); + assert!(!"".starts_with("abc")); + assert!(!"ödd".starts_with("-")); + assert!("ödd".starts_with("öd")); +} + +#[test] +fn test_ends_with() { + assert!("".ends_with("")); + assert!("abc".ends_with("")); + assert!("abc".ends_with("c")); + assert!(!"a".ends_with("abc")); + assert!(!"".ends_with("abc")); + assert!(!"ddö".ends_with("-")); + assert!("ddö".ends_with("dö")); +} + +#[test] +fn test_is_empty() { + assert!("".is_empty()); + assert!(!"a".is_empty()); +} + +#[test] +fn test_replacen() { + assert_eq!("".replacen('a', "b", 5), ""); + assert_eq!("acaaa".replacen("a", "b", 3), "bcbba"); + assert_eq!("aaaa".replacen("a", "b", 0), "aaaa"); + + let test = "test"; + assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast "); + assert_eq!(" test test ".replacen(test, "toast", 0), " test test "); + assert_eq!(" test test ".replacen(test, "", 5), " "); + + assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789"); +} + +#[test] +fn test_replace() { + let a = "a"; + assert_eq!("".replace(a, "b"), ""); + assert_eq!("a".replace(a, "b"), "b"); + assert_eq!("ab".replace(a, "b"), "bb"); + let test = "test"; + assert_eq!(" test test ".replace(test, "toast"), " toast toast "); + assert_eq!(" test test ".replace(test, ""), " "); +} + +#[test] +fn test_replace_2a() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let a = "ประเ"; + let a2 = "دولة الكويتทศไทย中华"; + assert_eq!(data.replace(a, repl), a2); +} + +#[test] +fn test_replace_2b() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let b = "ะเ"; + let b2 = "ปรدولة الكويتทศไทย中华"; + assert_eq!(data.replace(b, repl), b2); +} + +#[test] +fn test_replace_2c() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let c = "中华"; + let c2 = "ประเทศไทยدولة الكويت"; + assert_eq!(data.replace(c, repl), c2); +} + +#[test] +fn test_replace_2d() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let d = "ไท华"; + assert_eq!(data.replace(d, repl), data); +} + +#[test] +fn test_replace_pattern() { + let data = "abcdαβγδabcdαβγδ"; + assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ"); + assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ"); + assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ"); + assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ"); +} + +// The current implementation of SliceIndex fails to handle methods +// orthogonally from range types; therefore, it is worth testing +// all of the indexing operations on each input. +mod slice_index { + // Test a slicing operation **that should succeed,** + // testing it on all of the indexing methods. + // + // This is not suitable for testing failure on invalid inputs. + macro_rules! assert_range_eq { + ($s:expr, $range:expr, $expected:expr) => { + let mut s: String = $s.to_owned(); + let mut expected: String = $expected.to_owned(); + { + let s: &str = &s; + let expected: &str = &expected; + + assert_eq!(&s[$range], expected, "(in assertion for: index)"); + assert_eq!(s.get($range), Some(expected), "(in assertion for: get)"); + unsafe { + assert_eq!( + s.get_unchecked($range), + expected, + "(in assertion for: get_unchecked)", + ); + } + } + { + let s: &mut str = &mut s; + let expected: &mut str = &mut expected; + + assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",); + assert_eq!( + s.get_mut($range), + Some(&mut expected[..]), + "(in assertion for: get_mut)", + ); + unsafe { + assert_eq!( + s.get_unchecked_mut($range), + expected, + "(in assertion for: get_unchecked_mut)", + ); + } + } + }; + } + + // Make sure the macro can actually detect bugs, + // because if it can't, then what are we even doing here? + // + // (Be aware this only demonstrates the ability to detect bugs + // in the FIRST method that panics, as the macro is not designed + // to be used in `should_panic`) + #[test] + #[should_panic(expected = "out of bounds")] + fn assert_range_eq_can_fail_by_panic() { + assert_range_eq!("abc", 0..5, "abc"); + } + + // (Be aware this only demonstrates the ability to detect bugs + // in the FIRST method it calls, as the macro is not designed + // to be used in `should_panic`) + #[test] + #[should_panic(expected = "==")] + fn assert_range_eq_can_fail_by_inequality() { + assert_range_eq!("abc", 0..2, "abc"); + } + + // Generates test cases for bad index operations. + // + // This generates `should_panic` test cases for Index/IndexMut + // and `None` test cases for get/get_mut. + macro_rules! panic_cases { + ($( + in mod $case_name:ident { + data: $data:expr; + + // optional: + // + // a similar input for which DATA[input] succeeds, and the corresponding + // output str. This helps validate "critical points" where an input range + // straddles the boundary between valid and invalid. + // (such as the input `len..len`, which is just barely valid) + $( + good: data[$good:expr] == $output:expr; + )* + + bad: data[$bad:expr]; + message: $expect_msg:expr; // must be a literal + } + )*) => {$( + mod $case_name { + #[test] + fn pass() { + let mut v: String = $data.into(); + + $( assert_range_eq!(v, $good, $output); )* + + { + let v: &str = &v; + assert_eq!(v.get($bad), None, "(in None assertion for get)"); + } + + { + let v: &mut str = &mut v; + assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)"); + } + } + + #[test] + #[should_panic(expected = $expect_msg)] + fn index_fail() { + let v: String = $data.into(); + let v: &str = &v; + let _v = &v[$bad]; + } + + #[test] + #[should_panic(expected = $expect_msg)] + fn index_mut_fail() { + let mut v: String = $data.into(); + let v: &mut str = &mut v; + let _v = &mut v[$bad]; + } + } + )*}; + } + + #[test] + fn simple_ascii() { + assert_range_eq!("abc", .., "abc"); + + assert_range_eq!("abc", 0..2, "ab"); + assert_range_eq!("abc", 0..=1, "ab"); + assert_range_eq!("abc", ..2, "ab"); + assert_range_eq!("abc", ..=1, "ab"); + + assert_range_eq!("abc", 1..3, "bc"); + assert_range_eq!("abc", 1..=2, "bc"); + assert_range_eq!("abc", 1..1, ""); + assert_range_eq!("abc", 1..=0, ""); + } + + #[test] + fn simple_unicode() { + // 日本 + assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}"); + + assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}"); + assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}"); + assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}"); + assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}"); + + assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}"); + assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}"); + assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}"); + + let data = "ประเทศไทย中华"; + assert_range_eq!(data, 0..3, "ป"); + assert_range_eq!(data, 3..6, "ร"); + assert_range_eq!(data, 3..3, ""); + assert_range_eq!(data, 30..33, "华"); + + /*0: 中 + 3: 华 + 6: V + 7: i + 8: ệ + 11: t + 12: + 13: N + 14: a + 15: m */ + let ss = "中华Việt Nam"; + assert_range_eq!(ss, 3..6, "华"); + assert_range_eq!(ss, 6..16, "Việt Nam"); + assert_range_eq!(ss, 6..=15, "Việt Nam"); + assert_range_eq!(ss, 6.., "Việt Nam"); + + assert_range_eq!(ss, 0..3, "中"); + assert_range_eq!(ss, 3..7, "华V"); + assert_range_eq!(ss, 3..=6, "华V"); + assert_range_eq!(ss, 3..3, ""); + assert_range_eq!(ss, 3..=2, ""); + } + + #[test] + #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM + #[cfg_attr(miri, ignore)] // Miri is too slow + fn simple_big() { + fn a_million_letter_x() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("华华华华华华华华华华"); + i += 1; + } + rs + } + fn half_a_million_letter_x() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("华华华华华"); + i += 1; + } + rs + } + let letters = a_million_letter_x(); + assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x()); + } + + #[test] + #[should_panic] + fn test_slice_fail() { + &"中华Việt Nam"[0..2]; + } + + panic_cases! { + in mod rangefrom_len { + data: "abcdef"; + good: data[6..] == ""; + bad: data[7..]; + message: "out of bounds"; + } + + in mod rangeto_len { + data: "abcdef"; + good: data[..6] == "abcdef"; + bad: data[..7]; + message: "out of bounds"; + } + + in mod rangetoinclusive_len { + data: "abcdef"; + good: data[..=5] == "abcdef"; + bad: data[..=6]; + message: "out of bounds"; + } + + in mod rangeinclusive_len { + data: "abcdef"; + good: data[0..=5] == "abcdef"; + bad: data[0..=6]; + message: "out of bounds"; + } + + in mod range_len_len { + data: "abcdef"; + good: data[6..6] == ""; + bad: data[7..7]; + message: "out of bounds"; + } + + in mod rangeinclusive_len_len { + data: "abcdef"; + good: data[6..=5] == ""; + bad: data[7..=6]; + message: "out of bounds"; + } + } + + panic_cases! { + in mod rangeinclusive_exhausted { + data: "abcdef"; + + good: data[0..=5] == "abcdef"; + good: data[{ + let mut iter = 0..=5; + iter.by_ref().count(); // exhaust it + iter + }] == ""; + + // 0..=6 is out of bounds before exhaustion, so it + // stands to reason that it still would be after. + bad: data[{ + let mut iter = 0..=6; + iter.by_ref().count(); // exhaust it + iter + }]; + message: "out of bounds"; + } + } + + panic_cases! { + in mod range_neg_width { + data: "abcdef"; + good: data[4..4] == ""; + bad: data[4..3]; + message: "begin <= end (4 <= 3)"; + } + + in mod rangeinclusive_neg_width { + data: "abcdef"; + good: data[4..=3] == ""; + bad: data[4..=2]; + message: "begin <= end (4 <= 3)"; + } + } + + mod overflow { + panic_cases! { + in mod rangeinclusive { + data: "hello"; + // note: using 0 specifically ensures that the result of overflowing is 0..0, + // so that `get` doesn't simply return None for the wrong reason. + bad: data[0..=usize::MAX]; + message: "maximum usize"; + } + + in mod rangetoinclusive { + data: "hello"; + bad: data[..=usize::MAX]; + message: "maximum usize"; + } + } + } + + mod boundary { + const DATA: &str = "abcαβγ"; + + const BAD_START: usize = 4; + const GOOD_START: usize = 3; + const BAD_END: usize = 6; + const GOOD_END: usize = 7; + const BAD_END_INCL: usize = BAD_END - 1; + const GOOD_END_INCL: usize = GOOD_END - 1; + + // it is especially important to test all of the different range types here + // because some of the logic may be duplicated as part of micro-optimizations + // to dodge unicode boundary checks on half-ranges. + panic_cases! { + in mod range_1 { + data: super::DATA; + bad: data[super::BAD_START..super::GOOD_END]; + message: + "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + } + + in mod range_2 { + data: super::DATA; + bad: data[super::GOOD_START..super::BAD_END]; + message: + "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + } + + in mod rangefrom { + data: super::DATA; + bad: data[super::BAD_START..]; + message: + "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + } + + in mod rangeto { + data: super::DATA; + bad: data[..super::BAD_END]; + message: + "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + } + + in mod rangeinclusive_1 { + data: super::DATA; + bad: data[super::BAD_START..=super::GOOD_END_INCL]; + message: + "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + } + + in mod rangeinclusive_2 { + data: super::DATA; + bad: data[super::GOOD_START..=super::BAD_END_INCL]; + message: + "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + } + + in mod rangetoinclusive { + data: super::DATA; + bad: data[..=super::BAD_END_INCL]; + message: + "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + } + } + } + + const LOREM_PARAGRAPH: &str = "\ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \ + sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \ + quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \ + nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \ + tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \ + gravida nec quam."; + + // check the panic includes the prefix of the sliced string + #[test] + #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")] + fn test_slice_fail_truncated_1() { + &LOREM_PARAGRAPH[..1024]; + } + // check the truncation in the panic message + #[test] + #[should_panic(expected = "luctus, im`[...]")] + fn test_slice_fail_truncated_2() { + &LOREM_PARAGRAPH[..1024]; + } +} + +#[test] +fn test_str_slice_rangetoinclusive_ok() { + let s = "abcαβγ"; + assert_eq!(&s[..=2], "abc"); + assert_eq!(&s[..=4], "abcα"); +} + +#[test] +#[should_panic] +fn test_str_slice_rangetoinclusive_notok() { + let s = "abcαβγ"; + &s[..=3]; +} + +#[test] +fn test_str_slicemut_rangetoinclusive_ok() { + let mut s = "abcαβγ".to_owned(); + let s: &mut str = &mut s; + assert_eq!(&mut s[..=2], "abc"); + assert_eq!(&mut s[..=4], "abcα"); +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangetoinclusive_notok() { + let mut s = "abcαβγ".to_owned(); + let s: &mut str = &mut s; + &mut s[..=3]; +} + +#[test] +fn test_is_char_boundary() { + let s = "ศไทย中华Việt Nam β-release 🐱123"; + assert!(s.is_char_boundary(0)); + assert!(s.is_char_boundary(s.len())); + assert!(!s.is_char_boundary(s.len() + 1)); + for (i, ch) in s.char_indices() { + // ensure character locations are boundaries and continuation bytes are not + assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s); + for j in 1..ch.len_utf8() { + assert!( + !s.is_char_boundary(i + j), + "{} should not be a char boundary in {:?}", + i + j, + s + ); + } + } +} + +#[test] +fn test_trim_start_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** "); + assert_eq!(" *** *** ".trim_start_matches(chars), ""); + assert_eq!("foo *** ".trim_start_matches(chars), "foo *** "); + + assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12"); + assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123"); +} + +#[test] +fn test_trim_end_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo"); + assert_eq!(" *** *** ".trim_end_matches(chars), ""); + assert_eq!(" *** foo".trim_end_matches(chars), " *** foo"); + + assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar"); + assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar"); +} + +#[test] +fn test_trim_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); + assert_eq!(" *** *** ".trim_matches(chars), ""); + assert_eq!("foo".trim_matches(chars), "foo"); + + assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); + assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); +} + +#[test] +fn test_trim_start() { + assert_eq!("".trim_start(), ""); + assert_eq!("a".trim_start(), "a"); + assert_eq!(" ".trim_start(), ""); + assert_eq!(" blah".trim_start(), "blah"); + assert_eq!(" \u{3000} wut".trim_start(), "wut"); + assert_eq!("hey ".trim_start(), "hey "); +} + +#[test] +fn test_trim_end() { + assert_eq!("".trim_end(), ""); + assert_eq!("a".trim_end(), "a"); + assert_eq!(" ".trim_end(), ""); + assert_eq!("blah ".trim_end(), "blah"); + assert_eq!("wut \u{3000} ".trim_end(), "wut"); + assert_eq!(" hey".trim_end(), " hey"); +} + +#[test] +fn test_trim() { + assert_eq!("".trim(), ""); + assert_eq!("a".trim(), "a"); + assert_eq!(" ".trim(), ""); + assert_eq!(" blah ".trim(), "blah"); + assert_eq!("\nwut \u{3000} ".trim(), "wut"); + assert_eq!(" hey dude ".trim(), "hey dude"); +} + +#[test] +fn test_is_whitespace() { + assert!("".chars().all(|c| c.is_whitespace())); + assert!(" ".chars().all(|c| c.is_whitespace())); + assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space + assert!(" \n\t ".chars().all(|c| c.is_whitespace())); + assert!(!" _ ".chars().all(|c| c.is_whitespace())); +} + +#[test] +fn test_is_utf8() { + // deny overlong encodings + assert!(from_utf8(&[0xc0, 0x80]).is_err()); + assert!(from_utf8(&[0xc0, 0xae]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); + assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); + assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); + assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); + + // deny surrogates + assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); + assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); + + assert!(from_utf8(&[0xC2, 0x80]).is_ok()); + assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); + assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); + assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); +} + +#[test] +fn from_utf8_mostly_ascii() { + // deny invalid bytes embedded in long stretches of ascii + for i in 32..64 { + let mut data = [0; 128]; + data[i] = 0xC0; + assert!(from_utf8(&data).is_err()); + data[i] = 0xC2; + assert!(from_utf8(&data).is_err()); + } +} + +#[test] +fn from_utf8_error() { + macro_rules! test { + ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => { + let error = from_utf8($input).unwrap_err(); + assert_eq!(error.valid_up_to(), $expected_valid_up_to); + assert_eq!(error.error_len(), $expected_error_len); + }; + } + test!(b"A\xC3\xA9 \xFF ", 4, Some(1)); + test!(b"A\xC3\xA9 \x80 ", 4, Some(1)); + test!(b"A\xC3\xA9 \xC1 ", 4, Some(1)); + test!(b"A\xC3\xA9 \xC1", 4, Some(1)); + test!(b"A\xC3\xA9 \xC2", 4, None); + test!(b"A\xC3\xA9 \xC2 ", 4, Some(1)); + test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1)); + test!(b"A\xC3\xA9 \xE0", 4, None); + test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1)); + test!(b"A\xC3\xA9 \xE0\xA0", 4, None); + test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2)); + test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2)); + test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1)); + test!(b"A\xC3\xA9 \xF1", 4, None); + test!(b"A\xC3\xA9 \xF1\x80", 4, None); + test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None); + test!(b"A\xC3\xA9 \xF1 ", 4, Some(1)); + test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2)); + test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3)); +} + +#[test] +fn test_as_bytes() { + // no null + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, + 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, + ]; + let b: &[u8] = &[]; + assert_eq!("".as_bytes(), b); + assert_eq!("abc".as_bytes(), b"abc"); + assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); +} + +#[test] +#[should_panic] +fn test_as_bytes_fail() { + // Don't double free. (I'm not sure if this exercises the + // original problem code path anymore.) + let s = String::from(""); + let _bytes = s.as_bytes(); + panic!(); +} + +#[test] +fn test_as_ptr() { + let buf = "hello".as_ptr(); + unsafe { + assert_eq!(*buf.offset(0), b'h'); + assert_eq!(*buf.offset(1), b'e'); + assert_eq!(*buf.offset(2), b'l'); + assert_eq!(*buf.offset(3), b'l'); + assert_eq!(*buf.offset(4), b'o'); + } +} + +#[test] +fn vec_str_conversions() { + let s1: String = String::from("All mimsy were the borogoves"); + + let v: Vec = s1.as_bytes().to_vec(); + let s2: String = String::from(from_utf8(&v).unwrap()); + let mut i = 0; + let n1 = s1.len(); + let n2 = v.len(); + assert_eq!(n1, n2); + while i < n1 { + let a: u8 = s1.as_bytes()[i]; + let b: u8 = s2.as_bytes()[i]; + assert_eq!(a, b); + i += 1; + } +} + +#[test] +fn test_contains() { + assert!("abcde".contains("bcd")); + assert!("abcde".contains("abcd")); + assert!("abcde".contains("bcde")); + assert!("abcde".contains("")); + assert!("".contains("")); + assert!(!"abcde".contains("def")); + assert!(!"".contains("a")); + + let data = "ประเทศไทย中华Việt Nam"; + assert!(data.contains("ประเ")); + assert!(data.contains("ะเ")); + assert!(data.contains("中华")); + assert!(!data.contains("ไท华")); +} + +#[test] +fn test_contains_char() { + assert!("abc".contains('b')); + assert!("a".contains('a')); + assert!(!"abc".contains('d')); + assert!(!"".contains('a')); +} + +#[test] +fn test_split_at() { + let s = "ศไทย中华Việt Nam"; + for (index, _) in s.char_indices() { + let (a, b) = s.split_at(index); + assert_eq!(&s[..a.len()], a); + assert_eq!(&s[a.len()..], b); + } + let (a, b) = s.split_at(s.len()); + assert_eq!(a, s); + assert_eq!(b, ""); +} + +#[test] +fn test_split_at_mut() { + let mut s = "Hello World".to_string(); + { + let (a, b) = s.split_at_mut(5); + a.make_ascii_uppercase(); + b.make_ascii_lowercase(); + } + assert_eq!(s, "HELLO world"); +} + +#[test] +#[should_panic] +fn test_split_at_boundscheck() { + let s = "ศไทย中华Việt Nam"; + s.split_at(1); +} + +#[test] +fn test_escape_unicode() { + assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}"); + assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}"); + assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}"); + assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}"); + assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}"); + assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}"); + assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}"); + assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}"); + assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}"); +} + +#[test] +fn test_escape_debug() { + // Note that there are subtleties with the number of backslashes + // on the left- and right-hand sides. In particular, Unicode code points + // are usually escaped with two backslashes on the right-hand side, as + // they are escaped. However, when the character is unescaped (e.g., for + // printable characters), only a single backslash appears (as the character + // itself appears in the debug string). + assert_eq!("abc".escape_debug().to_string(), "abc"); + assert_eq!("a c".escape_debug().to_string(), "a c"); + assert_eq!("éèê".escape_debug().to_string(), "éèê"); + assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t"); + assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\"); + assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}"); + assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}"); + assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}"); + assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}"); + assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r"); + assert_eq!( + "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(), + "\\u{301}a\u{301}bé\\u{e000}" + ); +} + +#[test] +fn test_escape_default() { + assert_eq!("abc".escape_default().to_string(), "abc"); + assert_eq!("a c".escape_default().to_string(), "a c"); + assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}"); + assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t"); + assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\"); + assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}"); + assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}"); + assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}"); + assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}"); + assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r"); +} + +#[test] +fn test_total_ord() { + assert_eq!("1234".cmp("123"), Greater); + assert_eq!("123".cmp("1234"), Less); + assert_eq!("1234".cmp("1234"), Equal); + assert_eq!("12345555".cmp("123456"), Less); + assert_eq!("22".cmp("1234"), Greater); +} + +#[test] +fn test_iterator() { + let s = "ศไทย中华Việt Nam"; + let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm']; + + let mut pos = 0; + let it = s.chars(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(s.chars().count(), v.len()); +} + +#[test] +fn test_rev_iterator() { + let s = "ศไทย中华Việt Nam"; + let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ']; + + let mut pos = 0; + let it = s.chars().rev(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_chars_decoding() { + let mut bytes = [0; 4]; + for c in (0..0x110000).filter_map(std::char::from_u32) { + let s = c.encode_utf8(&mut bytes); + if Some(c) != s.chars().next() { + panic!("character {:x}={} does not decode correctly", c as u32, c); + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_chars_rev_decoding() { + let mut bytes = [0; 4]; + for c in (0..0x110000).filter_map(std::char::from_u32) { + let s = c.encode_utf8(&mut bytes); + if Some(c) != s.chars().rev().next() { + panic!("character {:x}={} does not decode correctly", c as u32, c); + } + } +} + +#[test] +fn test_iterator_clone() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert!(it.clone().zip(it).all(|(x, y)| x == y)); +} + +#[test] +fn test_iterator_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert_eq!(it.last(), Some('m')); +} + +#[test] +fn test_chars_debug() { + let s = "ศไทย中华Việt Nam"; + let c = s.chars(); + assert_eq!( + format!("{:?}", c), + r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"# + ); +} + +#[test] +fn test_bytesator() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, + 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, + ]; + let mut pos = 0; + + for b in s.bytes() { + assert_eq!(b, v[pos]); + pos += 1; + } +} + +#[test] +fn test_bytes_revator() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, + 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, + ]; + let mut pos = v.len(); + + for b in s.bytes().rev() { + pos -= 1; + assert_eq!(b, v[pos]); + } +} + +#[test] +fn test_bytesator_nth() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, + 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, + ]; + + let mut b = s.bytes(); + assert_eq!(b.nth(2).unwrap(), v[2]); + assert_eq!(b.nth(10).unwrap(), v[10]); + assert_eq!(b.nth(200), None); +} + +#[test] +fn test_bytesator_count() { + let s = "ศไทย中华Việt Nam"; + + let b = s.bytes(); + assert_eq!(b.count(), 28) +} + +#[test] +fn test_bytesator_last() { + let s = "ศไทย中华Việt Nam"; + + let b = s.bytes(); + assert_eq!(b.last().unwrap(), 109) +} + +#[test] +fn test_char_indicesator() { + let s = "ศไทย中华Việt Nam"; + let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; + let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm']; + + let mut pos = 0; + let it = s.char_indices(); + + for c in it { + assert_eq!(c, (p[pos], v[pos])); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(pos, p.len()); +} + +#[test] +fn test_char_indices_revator() { + let s = "ศไทย中华Việt Nam"; + let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; + let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ']; + + let mut pos = 0; + let it = s.char_indices().rev(); + + for c in it { + assert_eq!(c, (p[pos], v[pos])); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(pos, p.len()); +} + +#[test] +fn test_char_indices_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.char_indices(); + it.next(); + assert_eq!(it.last(), Some((27, 'm'))); +} + +#[test] +fn test_splitn_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.splitn(4, ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + // Unicode + let split: Vec<&str> = data.splitn(4, 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); +} + +#[test] +fn test_split_char_iterator_no_trailing() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split('\n').collect(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); + + let split: Vec<&str> = data.split_terminator('\n').collect(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); +} + +#[test] +fn test_split_char_iterator_inclusive() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split_inclusive('\n').collect(); + assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]); + + let uppercase_separated = "SheePSharKTurtlECaT"; + let mut first_char = true; + let split: Vec<&str> = uppercase_separated + .split_inclusive(|c: char| { + let split = !first_char && c.is_uppercase(); + first_char = split; + split + }) + .collect(); + assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]); +} + +#[test] +fn test_split_char_iterator_inclusive_rev() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split_inclusive('\n').rev().collect(); + assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]); + + // Note that the predicate is stateful and thus dependent + // on the iteration order. + // (A different predicate is needed for reverse iterator vs normal iterator.) + // Not sure if anything can be done though. + let uppercase_separated = "SheePSharKTurtlECaT"; + let mut term_char = true; + let split: Vec<&str> = uppercase_separated + .split_inclusive(|c: char| { + let split = term_char && c.is_uppercase(); + term_char = c.is_uppercase(); + split + }) + .rev() + .collect(); + assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]); +} + +#[test] +fn test_rsplit() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.rsplit(' ').collect(); + assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]); + + let split: Vec<&str> = data.rsplit("lämb").collect(); + assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]); + + let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect(); + assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]); +} + +#[test] +fn test_rsplitn() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.rsplitn(2, ' ').collect(); + assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]); + + let split: Vec<&str> = data.rsplitn(2, "lämb").collect(); + assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]); + + let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect(); + assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]); +} + +#[test] +fn test_split_once() { + assert_eq!("".split_once("->"), None); + assert_eq!("-".split_once("->"), None); + assert_eq!("->".split_once("->"), Some(("", ""))); + assert_eq!("a->".split_once("->"), Some(("a", ""))); + assert_eq!("->b".split_once("->"), Some(("", "b"))); + assert_eq!("a->b".split_once("->"), Some(("a", "b"))); + assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c"))); + assert_eq!("---".split_once("--"), Some(("", "-"))); +} + +#[test] +fn test_rsplit_once() { + assert_eq!("".rsplit_once("->"), None); + assert_eq!("-".rsplit_once("->"), None); + assert_eq!("->".rsplit_once("->"), Some(("", ""))); + assert_eq!("a->".rsplit_once("->"), Some(("a", ""))); + assert_eq!("->b".rsplit_once("->"), Some(("", "b"))); + assert_eq!("a->b".rsplit_once("->"), Some(("a", "b"))); + assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c"))); + assert_eq!("---".rsplit_once("--"), Some(("-", ""))); +} + +#[test] +fn test_split_whitespace() { + let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; + let words: Vec<&str> = data.split_whitespace().collect(); + assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) +} + +#[test] +fn test_lines() { + let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n"; + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); + + let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); +} + +#[test] +fn test_splitator() { + fn t(s: &str, sep: &str, u: &[&str]) { + let v: Vec<&str> = s.split(sep).collect(); + assert_eq!(v, u); + } + t("--1233345--", "12345", &["--1233345--"]); + t("abc::hello::there", "::", &["abc", "hello", "there"]); + t("::hello::there", "::", &["", "hello", "there"]); + t("hello::there::", "::", &["hello", "there", ""]); + t("::hello::there::", "::", &["", "hello", "there", ""]); + t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); + t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); + t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); + t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); + t("", ".", &[""]); + t("zz", "zz", &["", ""]); + t("ok", "z", &["ok"]); + t("zzz", "zz", &["", "z"]); + t("zzzzz", "zz", &["", "", "z"]); +} + +#[test] +fn test_str_default() { + use std::default::Default; + + fn t>() { + let s: S = Default::default(); + assert_eq!(s.as_ref(), ""); + } + + t::<&str>(); + t::(); + t::<&mut str>(); +} + +#[test] +fn test_str_container() { + fn sum_len(v: &[&str]) -> usize { + v.iter().map(|x| x.len()).sum() + } + + let s = "01234"; + assert_eq!(5, sum_len(&["012", "", "34"])); + assert_eq!(5, sum_len(&["01", "2", "34", ""])); + assert_eq!(5, sum_len(&[s])); +} + +#[test] +fn test_str_from_utf8() { + let xs = b"hello"; + assert_eq!(from_utf8(xs), Ok("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF"; + assert!(from_utf8(xs).is_err()); +} + +#[test] +fn test_pattern_deref_forward() { + let data = "aabcdaa"; + assert!(data.contains("bcd")); + assert!(data.contains(&"bcd")); + assert!(data.contains(&"bcd".to_string())); +} + +#[test] +fn test_empty_match_indices() { + let data = "aä中!"; + let vec: Vec<_> = data.match_indices("").collect(); + assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]); +} + +#[test] +fn test_bool_from_str() { + assert_eq!("true".parse().ok(), Some(true)); + assert_eq!("false".parse().ok(), Some(false)); + assert_eq!("not even a boolean".parse::().ok(), None); +} + +fn check_contains_all_substrings(s: &str) { + assert!(s.contains("")); + for i in 0..s.len() { + for j in i + 1..=s.len() { + assert!(s.contains(&s[i..j])); + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn strslice_issue_16589() { + assert!("bananas".contains("nana")); + + // prior to the fix for #16589, x.contains("abcdabcd") returned false + // test all substrings for good measure + check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd"); +} + +#[test] +fn strslice_issue_16878() { + assert!(!"1234567ah012345678901ah".contains("hah")); + assert!(!"00abc01234567890123456789abc".contains("bcabc")); +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_strslice_contains() { + let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'"; + check_contains_all_substrings(x); +} + +#[test] +fn test_rsplitn_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let mut split: Vec<&str> = data.rsplitn(4, ' ').collect(); + split.reverse(); + assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + + let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect(); + split.reverse(); + assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + + // Unicode + let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect(); + split.reverse(); + assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + + let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect(); + split.reverse(); + assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); +} + +#[test] +fn test_split_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split(' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + + let mut rsplit: Vec<&str> = data.split(' ').rev().collect(); + rsplit.reverse(); + assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + + let split: Vec<&str> = data.split(|c: char| c == ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + + let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect(); + rsplit.reverse(); + assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + + // Unicode + let split: Vec<&str> = data.split('ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + + let mut rsplit: Vec<&str> = data.split('ä').rev().collect(); + rsplit.reverse(); + assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + + let split: Vec<&str> = data.split(|c: char| c == 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + + let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect(); + rsplit.reverse(); + assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); +} + +#[test] +fn test_rev_split_char_iterator_no_trailing() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let mut split: Vec<&str> = data.split('\n').rev().collect(); + split.reverse(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); + + let mut split: Vec<&str> = data.split_terminator('\n').rev().collect(); + split.reverse(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); +} + +#[test] +fn test_utf16_code_units() { + assert_eq!("é\u{1F4A9}".encode_utf16().collect::>(), [0xE9, 0xD83D, 0xDCA9]) +} + +#[test] +fn starts_with_in_unicode() { + assert!(!"├── Cargo.toml".starts_with("# ")); +} + +#[test] +fn starts_short_long() { + assert!(!"".starts_with("##")); + assert!(!"##".starts_with("####")); + assert!("####".starts_with("##")); + assert!(!"##ä".starts_with("####")); + assert!("####ä".starts_with("##")); + assert!(!"##".starts_with("####ä")); + assert!("##ä##".starts_with("##ä")); + + assert!("".starts_with("")); + assert!("ä".starts_with("")); + assert!("#ä".starts_with("")); + assert!("##ä".starts_with("")); + assert!("ä###".starts_with("")); + assert!("#ä##".starts_with("")); + assert!("##ä#".starts_with("")); +} + +#[test] +fn contains_weird_cases() { + assert!("* \t".contains(' ')); + assert!(!"* \t".contains('?')); + assert!(!"* \t".contains('\u{1F4A9}')); +} + +#[test] +fn trim_ws() { + assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); + assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); + assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); + assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); + assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a"); + assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); + assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); + assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); + assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); + assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), ""); +} + +#[test] +fn to_lowercase() { + assert_eq!("".to_lowercase(), ""); + assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé "); + + // https://github.com/rust-lang/rust/issues/26035 + assert_eq!("ΑΣ".to_lowercase(), "ας"); + assert_eq!("Α'Σ".to_lowercase(), "α'ς"); + assert_eq!("Α''Σ".to_lowercase(), "α''ς"); + + assert_eq!("ΑΣ Α".to_lowercase(), "ας α"); + assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α"); + assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α"); + + assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α"); + assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α"); + + assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α"); + assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α"); + + assert_eq!("Α Σ".to_lowercase(), "α σ"); + assert_eq!("Α 'Σ".to_lowercase(), "α 'σ"); + assert_eq!("Α ''Σ".to_lowercase(), "α ''σ"); + + assert_eq!("Σ".to_lowercase(), "σ"); + assert_eq!("'Σ".to_lowercase(), "'σ"); + assert_eq!("''Σ".to_lowercase(), "''σ"); + + assert_eq!("ΑΣΑ".to_lowercase(), "ασα"); + assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α"); + assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α"); +} + +#[test] +fn to_uppercase() { + assert_eq!("".to_uppercase(), ""); + assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ"); +} + +#[test] +fn test_into_string() { + // The only way to acquire a Box in the first place is through a String, so just + // test that we can round-trip between Box and String. + let string = String::from("Some text goes here"); + assert_eq!(string.clone().into_boxed_str().into_string(), string); +} + +#[test] +fn test_box_slice_clone() { + let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!"); + let data2 = data.clone().into_boxed_str().clone().into_string(); + + assert_eq!(data, data2); +} + +#[test] +fn test_cow_from() { + let borrowed = "borrowed"; + let owned = String::from("owned"); + match (Cow::from(owned.clone()), Cow::from(borrowed)) { + (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), + _ => panic!("invalid `Cow::from`"), + } +} + +#[test] +fn test_repeat() { + assert_eq!("".repeat(3), ""); + assert_eq!("abc".repeat(0), ""); + assert_eq!("α".repeat(3), "ααα"); +} + +mod pattern { + use std::str::pattern::SearchStep::{self, Done, Match, Reject}; + use std::str::pattern::{Pattern, ReverseSearcher, Searcher}; + + macro_rules! make_test { + ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => { + #[allow(unused_imports)] + mod $name { + use std::str::pattern::SearchStep::{Match, Reject}; + use super::{cmp_search_to_vec}; + #[test] + fn fwd() { + cmp_search_to_vec(false, $p, $h, vec![$($e),*]); + } + #[test] + fn bwd() { + cmp_search_to_vec(true, $p, $h, vec![$($e),*]); + } + } + } + } + + fn cmp_search_to_vec<'a>( + rev: bool, + pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>, + haystack: &'a str, + right: Vec, + ) { + let mut searcher = pat.into_searcher(haystack); + let mut v = vec![]; + loop { + match if !rev { searcher.next() } else { searcher.next_back() } { + Match(a, b) => v.push(Match(a, b)), + Reject(a, b) => v.push(Reject(a, b)), + Done => break, + } + } + if rev { + v.reverse(); + } + + let mut first_index = 0; + let mut err = None; + + for (i, e) in right.iter().enumerate() { + match *e { + Match(a, b) | Reject(a, b) if a <= b && a == first_index => { + first_index = b; + } + _ => { + err = Some(i); + break; + } + } + } + + if let Some(err) = err { + panic!("Input skipped range at {}", err); + } + + if first_index != haystack.len() { + panic!("Did not cover whole input"); + } + + assert_eq!(v, right); + } + + make_test!( + str_searcher_ascii_haystack, + "bb", + "abbcbbd", + [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),] + ); + make_test!( + str_searcher_ascii_haystack_seq, + "bb", + "abbcbbbbd", + [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),] + ); + make_test!( + str_searcher_empty_needle_ascii_haystack, + "", + "abbcbbd", + [ + Match(0, 0), + Reject(0, 1), + Match(1, 1), + Reject(1, 2), + Match(2, 2), + Reject(2, 3), + Match(3, 3), + Reject(3, 4), + Match(4, 4), + Reject(4, 5), + Match(5, 5), + Reject(5, 6), + Match(6, 6), + Reject(6, 7), + Match(7, 7), + ] + ); + make_test!( + str_searcher_multibyte_haystack, + " ", + "├──", + [Reject(0, 3), Reject(3, 6), Reject(6, 9),] + ); + make_test!( + str_searcher_empty_needle_multibyte_haystack, + "", + "├──", + [ + Match(0, 0), + Reject(0, 3), + Match(3, 3), + Reject(3, 6), + Match(6, 6), + Reject(6, 9), + Match(9, 9), + ] + ); + make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]); + make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []); + make_test!( + char_searcher_ascii_haystack, + 'b', + "abbcbbd", + [ + Reject(0, 1), + Match(1, 2), + Match(2, 3), + Reject(3, 4), + Match(4, 5), + Match(5, 6), + Reject(6, 7), + ] + ); + make_test!( + char_searcher_multibyte_haystack, + ' ', + "├──", + [Reject(0, 3), Reject(3, 6), Reject(6, 9),] + ); + make_test!( + char_searcher_short_haystack, + '\u{1F4A9}', + "* \t", + [Reject(0, 1), Reject(1, 2), Reject(2, 3),] + ); +} + +macro_rules! generate_iterator_test { + { + $name:ident { + $( + ($($arg:expr),*) -> [$($t:tt)*]; + )* + } + with $fwd:expr, $bwd:expr; + } => { + #[test] + fn $name() { + $( + { + let res = vec![$($t)*]; + + let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect(); + assert_eq!(fwd_vec, res); + + let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect(); + bwd_vec.reverse(); + assert_eq!(bwd_vec, res); + } + )* + } + }; + { + $name:ident { + $( + ($($arg:expr),*) -> [$($t:tt)*]; + )* + } + with $fwd:expr; + } => { + #[test] + fn $name() { + $( + { + let res = vec![$($t)*]; + + let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect(); + assert_eq!(fwd_vec, res); + } + )* + } + } +} + +generate_iterator_test! { + double_ended_split { + ("foo.bar.baz", '.') -> ["foo", "bar", "baz"]; + ("foo::bar::baz", "::") -> ["foo", "bar", "baz"]; + } + with str::split, str::rsplit; +} + +generate_iterator_test! { + double_ended_split_terminator { + ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"]; + } + with str::split_terminator, str::rsplit_terminator; +} + +generate_iterator_test! { + double_ended_matches { + ("a1b2c3", char::is_numeric) -> ["1", "2", "3"]; + } + with str::matches, str::rmatches; +} + +generate_iterator_test! { + double_ended_match_indices { + ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")]; + } + with str::match_indices, str::rmatch_indices; +} + +generate_iterator_test! { + not_double_ended_splitn { + ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"]; + } + with str::splitn; +} + +generate_iterator_test! { + not_double_ended_rsplitn { + ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"]; + } + with str::rsplitn; +} + +#[test] +fn different_str_pattern_forwarding_lifetimes() { + use std::str::pattern::Pattern; + + fn foo<'a, P>(p: P) + where + for<'b> &'b P: Pattern<'a>, + { + for _ in 0..3 { + "asdf".find(&p); + } + } + + foo::<&str>("x"); +} + +#[test] +fn test_str_multiline() { + let a: String = "this \ +is a test" + .to_string(); + let b: String = "this \ + is \ + another \ + test" + .to_string(); + assert_eq!(a, "this is a test".to_string()); + assert_eq!(b, "this is another test".to_string()); +} + +#[test] +fn test_str_escapes() { + let x = "\\\\\ + "; + assert_eq!(x, r"\\"); // extraneous whitespace stripped +} + +#[test] +fn const_str_ptr() { + const A: [u8; 2] = ['h' as u8, 'i' as u8]; + const B: &'static [u8; 2] = &A; + const C: *const u8 = B as *const u8; + + // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) + #[cfg(not(miri))] + { + let foo = &A as *const u8; + assert_eq!(foo, C); + } + + unsafe { + assert_eq!(from_utf8_unchecked(&A), "hi"); + assert_eq!(*C, A[0]); + assert_eq!(*(&B[0] as *const u8), A[0]); + } +} + +#[test] +fn utf8() { + let yen: char = '¥'; // 0xa5 + let c_cedilla: char = 'ç'; // 0xe7 + let thorn: char = 'þ'; // 0xfe + let y_diaeresis: char = 'ÿ'; // 0xff + let pi: char = 'Π'; // 0x3a0 + + assert_eq!(yen as isize, 0xa5); + assert_eq!(c_cedilla as isize, 0xe7); + assert_eq!(thorn as isize, 0xfe); + assert_eq!(y_diaeresis as isize, 0xff); + assert_eq!(pi as isize, 0x3a0); + + assert_eq!(pi as isize, '\u{3a0}' as isize); + assert_eq!('\x0a' as isize, '\n' as isize); + + let bhutan: String = "འབྲུག་ཡུལ།".to_string(); + let japan: String = "日本".to_string(); + let uzbekistan: String = "Ўзбекистон".to_string(); + let austria: String = "Österreich".to_string(); + + let bhutan_e: String = + "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string(); + let japan_e: String = "\u{65e5}\u{672c}".to_string(); + let uzbekistan_e: String = + "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string(); + let austria_e: String = "\u{d6}sterreich".to_string(); + + let oo: char = 'Ö'; + assert_eq!(oo as isize, 0xd6); + + fn check_str_eq(a: String, b: String) { + let mut i: isize = 0; + for ab in a.bytes() { + println!("{}", i); + println!("{}", ab); + let bb: u8 = b.as_bytes()[i as usize]; + println!("{}", bb); + assert_eq!(ab, bb); + i += 1; + } + } + + check_str_eq(bhutan, bhutan_e); + check_str_eq(japan, japan_e); + check_str_eq(uzbekistan, uzbekistan_e); + check_str_eq(austria, austria_e); +} + +#[test] +fn utf8_chars() { + // Chars of 1, 2, 3, and 4 bytes + let chs: Vec = vec!['e', 'é', '€', '\u{10000}']; + let s: String = chs.iter().cloned().collect(); + let schs: Vec = s.chars().collect(); + + assert_eq!(s.len(), 10); + assert_eq!(s.chars().count(), 4); + assert_eq!(schs.len(), 4); + assert_eq!(schs.iter().cloned().collect::(), s); + + assert!((from_utf8(s.as_bytes()).is_ok())); + // invalid prefix + assert!((!from_utf8(&[0x80]).is_ok())); + // invalid 2 byte prefix + assert!((!from_utf8(&[0xc0]).is_ok())); + assert!((!from_utf8(&[0xc0, 0x10]).is_ok())); + // invalid 3 byte prefix + assert!((!from_utf8(&[0xe0]).is_ok())); + assert!((!from_utf8(&[0xe0, 0x10]).is_ok())); + assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok())); + // invalid 4 byte prefix + assert!((!from_utf8(&[0xf0]).is_ok())); + assert!((!from_utf8(&[0xf0, 0x10]).is_ok())); + assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok())); + assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok())); +} +use std::collections::BTreeSet; + +#[test] +fn test_hash() { + use crate::hash; + + let mut x = BTreeSet::new(); + let mut y = BTreeSet::new(); + + x.insert(1); + x.insert(2); + x.insert(3); + + y.insert(3); + y.insert(2); + y.insert(1); + + assert_eq!(hash(&x), hash(&y)); +} +use std::borrow::Cow; +use std::cell::Cell; +use std::collections::TryReserveError::*; +use std::ops::Bound; +use std::ops::Bound::*; +use std::ops::RangeBounds; +use std::panic; +use std::str; + +pub trait IntoCow<'a, B: ?Sized> +where + B: ToOwned, +{ + fn into_cow(self) -> Cow<'a, B>; +} + +impl<'a> IntoCow<'a, str> for String { + fn into_cow(self) -> Cow<'a, str> { + Cow::Owned(self) + } +} + +impl<'a> IntoCow<'a, str> for &'a str { + fn into_cow(self) -> Cow<'a, str> { + Cow::Borrowed(self) + } +} + +#[test] +fn test_from_str() { + let owned: Option = "string".parse().ok(); + assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); +} + +#[test] +fn test_from_cow_str() { + assert_eq!(String::from(Cow::Borrowed("string")), "string"); + assert_eq!(String::from(Cow::Owned(String::from("string"))), "string"); +} + +#[test] +fn test_unsized_to_string() { + let s: &str = "abc"; + let _: String = (*s).to_string(); +} + +#[test] +fn test_from_utf8() { + let xs = b"hello".to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), String::from("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF".to_vec(); + let err = String::from_utf8(xs).unwrap_err(); + assert_eq!(err.as_bytes(), b"hello\xff"); + let err_clone = err.clone(); + assert_eq!(err, err_clone); + assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); + assert_eq!(err_clone.utf8_error().valid_up_to(), 5); +} + +#[test] +fn test_from_utf8_lossy() { + let xs = b"hello"; + let ys: Cow<'_, str> = "hello".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + let ys: Cow<'_, str> = "ศไทย中华Việt Nam".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = b"Hello\xC2 There\xFF Goodbye"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow() + ); + + let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow() + ); + + let xs = b"\xF5foo\xF5\x80bar"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow() + ); + + let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow() + ); + + let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow() + ); + + let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow() + ); + + // surrogates + let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; + assert_eq!( + String::from_utf8_lossy(xs), + String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow() + ); +} + +#[test] +fn test_from_utf16() { + let pairs = [ + ( + String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), + vec![ + 0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39, + 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a, + ], + ), + ( + String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), + vec![ + 0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32, + 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a, + ], + ), + ( + String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), + vec![ + 0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11, + 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800, + 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a, + ], + ), + ( + String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), + vec![ + 0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b, + 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88, + 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801, + 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86, + 0x000a, + ], + ), + // Issue #12318, even-numbered non-BMP planes + (String::from("\u{20000}"), vec![0xD840, 0xDC00]), + ]; + + for p in &pairs { + let (s, u) = (*p).clone(); + let s_as_utf16 = s.encode_utf16().collect::>(); + let u_as_string = String::from_utf16(&u).unwrap(); + + assert!(core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok())); + assert_eq!(s_as_utf16, u); + + assert_eq!(u_as_string, s); + assert_eq!(String::from_utf16_lossy(&u), s); + + assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s); + assert_eq!(u_as_string.encode_utf16().collect::>(), u); + } +} + +#[test] +fn test_utf16_invalid() { + // completely positive cases tested above. + // lead + eof + assert!(String::from_utf16(&[0xD800]).is_err()); + // lead + lead + assert!(String::from_utf16(&[0xD800, 0xD800]).is_err()); + + // isolated trail + assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err()); + + // general + assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err()); +} + +#[test] +fn test_from_utf16_lossy() { + // completely positive cases tested above. + // lead + eof + assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}")); + // lead + lead + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}")); + + // isolated trail + assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}")); + + // general + assert_eq!( + String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), + String::from("\u{FFFD}𐒋\u{FFFD}") + ); +} + +#[test] +fn test_push_bytes() { + let mut s = String::from("ABC"); + unsafe { + let mv = s.as_mut_vec(); + mv.extend_from_slice(&[b'D']); + } + assert_eq!(s, "ABCD"); +} + +#[test] +fn test_push_str() { + let mut s = String::new(); + s.push_str(""); + assert_eq!(&s[0..], ""); + s.push_str("abc"); + assert_eq!(&s[0..], "abc"); + s.push_str("ประเทศไทย中华Việt Nam"); + assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam"); +} + +#[test] +fn test_add_assign() { + let mut s = String::new(); + s += ""; + assert_eq!(s.as_str(), ""); + s += "abc"; + assert_eq!(s.as_str(), "abc"); + s += "ประเทศไทย中华Việt Nam"; + assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam"); +} + +#[test] +fn test_push() { + let mut data = String::from("ประเทศไทย中"); + data.push('华'); + data.push('b'); // 1 byte + data.push('¢'); // 2 byte + data.push('€'); // 3 byte + data.push('𤭢'); // 4 byte + assert_eq!(data, "ประเทศไทย中华b¢€𤭢"); +} + +#[test] +fn test_pop() { + let mut data = String::from("ประเทศไทย中华b¢€𤭢"); + assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes + assert_eq!(data.pop().unwrap(), '€'); // 3 bytes + assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes + assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes + assert_eq!(data.pop().unwrap(), '华'); + assert_eq!(data, "ประเทศไทย中"); +} + +#[test] +fn test_split_off_empty() { + let orig = "Hello, world!"; + let mut split = String::from(orig); + let empty: String = split.split_off(orig.len()); + assert!(empty.is_empty()); +} + +#[test] +#[should_panic] +fn test_split_off_past_end() { + let orig = "Hello, world!"; + let mut split = String::from(orig); + let _ = split.split_off(orig.len() + 1); +} + +#[test] +#[should_panic] +fn test_split_off_mid_char() { + let mut shan = String::from("山"); + let _broken_mountain = shan.split_off(1); +} + +#[test] +fn test_split_off_ascii() { + let mut ab = String::from("ABCD"); + let orig_capacity = ab.capacity(); + let cd = ab.split_off(2); + assert_eq!(ab, "AB"); + assert_eq!(cd, "CD"); + assert_eq!(ab.capacity(), orig_capacity); +} + +#[test] +fn test_split_off_unicode() { + let mut nihon = String::from("日本語"); + let orig_capacity = nihon.capacity(); + let go = nihon.split_off("日本".len()); + assert_eq!(nihon, "日本"); + assert_eq!(go, "語"); + assert_eq!(nihon.capacity(), orig_capacity); +} + +#[test] +fn test_str_truncate() { + let mut s = String::from("12345"); + s.truncate(5); + assert_eq!(s, "12345"); + s.truncate(3); + assert_eq!(s, "123"); + s.truncate(0); + assert_eq!(s, ""); + + let mut s = String::from("12345"); + let p = s.as_ptr(); + s.truncate(3); + s.push_str("6"); + let p_ = s.as_ptr(); + assert_eq!(p_, p); +} + +#[test] +fn test_str_truncate_invalid_len() { + let mut s = String::from("12345"); + s.truncate(6); + assert_eq!(s, "12345"); +} + +#[test] +#[should_panic] +fn test_str_truncate_split_codepoint() { + let mut s = String::from("\u{FC}"); // ü + s.truncate(1); +} + +#[test] +fn test_str_clear() { + let mut s = String::from("12345"); + s.clear(); + assert_eq!(s.len(), 0); + assert_eq!(s, ""); +} + +#[test] +fn test_str_add() { + let a = String::from("12345"); + let b = a + "2"; + let b = b + "2"; + assert_eq!(b.len(), 7); + assert_eq!(b, "1234522"); +} + +#[test] +fn remove() { + let mut s = "ศไทย中华Việt Nam; foobar".to_string(); + assert_eq!(s.remove(0), 'ศ'); + assert_eq!(s.len(), 33); + assert_eq!(s, "ไทย中华Việt Nam; foobar"); + assert_eq!(s.remove(17), 'ệ'); + assert_eq!(s, "ไทย中华Vit Nam; foobar"); +} + +#[test] +#[should_panic] +fn remove_bad() { + "ศ".to_string().remove(1); +} + +#[test] +fn test_remove_matches() { + let mut s = "abc".to_string(); + + s.remove_matches('b'); + assert_eq!(s, "ac"); + s.remove_matches('b'); + assert_eq!(s, "ac"); + + let mut s = "abcb".to_string(); + + s.remove_matches('b'); + assert_eq!(s, "ac"); + + let mut s = "ศไทย中华Việt Nam; foobarศ".to_string(); + s.remove_matches('ศ'); + assert_eq!(s, "ไทย中华Việt Nam; foobar"); + + let mut s = "".to_string(); + s.remove_matches(""); + assert_eq!(s, ""); + + let mut s = "aaaaa".to_string(); + s.remove_matches('a'); + assert_eq!(s, ""); +} + +#[test] +fn test_retain() { + let mut s = String::from("α_β_γ"); + + s.retain(|_| true); + assert_eq!(s, "α_β_γ"); + + s.retain(|c| c != '_'); + assert_eq!(s, "αβγ"); + + s.retain(|c| c != 'β'); + assert_eq!(s, "αγ"); + + s.retain(|c| c == 'α'); + assert_eq!(s, "α"); + + s.retain(|_| false); + assert_eq!(s, ""); + + let mut s = String::from("0è0"); + let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let mut count = 0; + s.retain(|_| { + count += 1; + match count { + 1 => false, + 2 => true, + _ => panic!(), + } + }); + })); + assert!(std::str::from_utf8(s.as_bytes()).is_ok()); +} + +#[test] +fn insert() { + let mut s = "foobar".to_string(); + s.insert(0, 'ệ'); + assert_eq!(s, "ệfoobar"); + s.insert(6, 'ย'); + assert_eq!(s, "ệfooยbar"); +} + +#[test] +#[should_panic] +fn insert_bad1() { + "".to_string().insert(1, 't'); +} +#[test] +#[should_panic] +fn insert_bad2() { + "ệ".to_string().insert(1, 't'); +} + +#[test] +fn test_slicing() { + let s = "foobar".to_string(); + assert_eq!("foobar", &s[..]); + assert_eq!("foo", &s[..3]); + assert_eq!("bar", &s[3..]); + assert_eq!("oob", &s[1..4]); +} + +#[test] +fn test_simple_types() { + assert_eq!(1.to_string(), "1"); + assert_eq!((-1).to_string(), "-1"); + assert_eq!(200.to_string(), "200"); + assert_eq!(2.to_string(), "2"); + assert_eq!(true.to_string(), "true"); + assert_eq!(false.to_string(), "false"); + assert_eq!(("hi".to_string()).to_string(), "hi"); +} + +#[test] +fn test_vectors() { + let x: Vec = vec![]; + assert_eq!(format!("{:?}", x), "[]"); + assert_eq!(format!("{:?}", vec![1]), "[1]"); + assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); + assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]"); +} + +#[test] +fn test_from_iterator() { + let s = "ศไทย中华Việt Nam".to_string(); + let t = "ศไทย中华"; + let u = "Việt Nam"; + + let a: String = s.chars().collect(); + assert_eq!(s, a); + + let mut b = t.to_string(); + b.extend(u.chars()); + assert_eq!(s, b); + + let c: String = vec![t, u].into_iter().collect(); + assert_eq!(s, c); + + let mut d = t.to_string(); + d.extend(vec![u]); + assert_eq!(s, d); +} + +#[test] +fn test_drain() { + let mut s = String::from("αβγ"); + assert_eq!(s.drain(2..4).collect::(), "β"); + assert_eq!(s, "αγ"); + + let mut t = String::from("abcd"); + t.drain(..0); + assert_eq!(t, "abcd"); + t.drain(..1); + assert_eq!(t, "bcd"); + t.drain(3..); + assert_eq!(t, "bcd"); + t.drain(..); + assert_eq!(t, ""); +} + +#[test] +#[should_panic] +fn test_drain_start_overflow() { + let mut s = String::from("abc"); + s.drain((Excluded(usize::MAX), Included(0))); +} + +#[test] +#[should_panic] +fn test_drain_end_overflow() { + let mut s = String::from("abc"); + s.drain((Included(0), Included(usize::MAX))); +} + +#[test] +fn test_replace_range() { + let mut s = "Hello, world!".to_owned(); + s.replace_range(7..12, "世界"); + assert_eq!(s, "Hello, 世界!"); +} + +#[test] +#[should_panic] +fn test_replace_range_char_boundary() { + let mut s = "Hello, 世界!".to_owned(); + s.replace_range(..8, ""); +} + +#[test] +fn test_replace_range_inclusive_range() { + let mut v = String::from("12345"); + v.replace_range(2..=3, "789"); + assert_eq!(v, "127895"); + v.replace_range(1..=2, "A"); + assert_eq!(v, "1A895"); +} + +#[test] +#[should_panic] +fn test_replace_range_out_of_bounds() { + let mut s = String::from("12345"); + s.replace_range(5..6, "789"); +} + +#[test] +#[should_panic] +fn test_replace_range_inclusive_out_of_bounds() { + let mut s = String::from("12345"); + s.replace_range(5..=5, "789"); +} + +#[test] +#[should_panic] +fn test_replace_range_start_overflow() { + let mut s = String::from("123"); + s.replace_range((Excluded(usize::MAX), Included(0)), ""); +} + +#[test] +#[should_panic] +fn test_replace_range_end_overflow() { + let mut s = String::from("456"); + s.replace_range((Included(0), Included(usize::MAX)), ""); +} + +#[test] +fn test_replace_range_empty() { + let mut s = String::from("12345"); + s.replace_range(1..2, ""); + assert_eq!(s, "1345"); +} + +#[test] +fn test_replace_range_unbounded() { + let mut s = String::from("12345"); + s.replace_range(.., ""); + assert_eq!(s, ""); +} + +#[test] +fn test_replace_range_evil_start_bound() { + struct EvilRange(Cell); + + impl RangeBounds for EvilRange { + fn start_bound(&self) -> Bound<&usize> { + Bound::Included(if self.0.get() { + &1 + } else { + self.0.set(true); + &0 + }) + } + fn end_bound(&self) -> Bound<&usize> { + Bound::Unbounded + } + } + + let mut s = String::from("🦀"); + s.replace_range(EvilRange(Cell::new(false)), ""); + assert_eq!(Ok(""), str::from_utf8(s.as_bytes())); +} + +#[test] +fn test_replace_range_evil_end_bound() { + struct EvilRange(Cell); + + impl RangeBounds for EvilRange { + fn start_bound(&self) -> Bound<&usize> { + Bound::Included(&0) + } + fn end_bound(&self) -> Bound<&usize> { + Bound::Excluded(if self.0.get() { + &3 + } else { + self.0.set(true); + &4 + }) + } + } + + let mut s = String::from("🦀"); + s.replace_range(EvilRange(Cell::new(false)), ""); + assert_eq!(Ok(""), str::from_utf8(s.as_bytes())); +} + +#[test] +fn test_extend_ref() { + let mut a = "foo".to_string(); + a.extend(&['b', 'a', 'r']); + + assert_eq!(&a, "foobar"); +} + +#[test] +fn test_into_boxed_str() { + let xs = String::from("hello my name is bob"); + let ys = xs.into_boxed_str(); + assert_eq!(&*ys, "hello my name is bob"); +} + +#[test] +fn test_reserve_exact() { + // This is all the same as test_reserve + + let mut s = String::new(); + assert_eq!(s.capacity(), 0); + + s.reserve_exact(2); + assert!(s.capacity() >= 2); + + for _i in 0..16 { + s.push('0'); + } + + assert!(s.capacity() >= 16); + s.reserve_exact(16); + assert!(s.capacity() >= 32); + + s.push('0'); + + s.reserve_exact(16); + assert!(s.capacity() >= 33) +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_reserve() { + // These are the interesting cases: + // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) + // * > isize::MAX should always fail + // * On 16/32-bit should CapacityOverflow + // * On 64-bit should OOM + // * overflow may trigger when adding `len` to `cap` (in number of elements) + // * overflow may trigger when multiplying `new_cap` by size_of:: (to get bytes) + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + // On 16/32-bit, we check that allocations don't exceed isize::MAX, + // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. + // Any platform that succeeds for these requests is technically broken with + // ptr::offset because LLVM is the worst. + let guards_against_isize = usize::BITS < 64; + + { + // Note: basic stuff is checked by test_reserve + let mut empty_string: String = String::new(); + + // Check isize::MAX doesn't count as an overflow + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + // Play it again, frank! (just to be sure) + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + // Check isize::MAX + 1 does count as overflow + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } + + // Check usize::MAX does count as overflow + if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } else { + // Check isize::MAX + 1 is an OOM + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + + // Check usize::MAX is an OOM + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an OOM!") + } + } + } + + { + // Same basic idea, but with non-zero len + let mut ten_bytes: String = String::from("0123456789"); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + // Should always overflow in the add-to-len + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_reserve_exact() { + // This is exactly the same as test_try_reserve with the method changed. + // See that test for comments. + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + let guards_against_isize = usize::BITS < 64; + + { + let mut empty_string: String = String::new(); + + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } + + if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } else { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an OOM!") + } + } + } + + { + let mut ten_bytes: String = String::from("0123456789"); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } +} + +#[test] +fn test_from_char() { + assert_eq!(String::from('a'), 'a'.to_string()); + let s: String = 'x'.into(); + assert_eq!(s, 'x'.to_string()); +} + +#[test] +fn test_str_concat() { + let a: String = "hello".to_string(); + let b: String = "world".to_string(); + let s: String = format!("{}{}", a, b); + assert_eq!(s.as_bytes()[9], 'd' as u8); +} +use std::borrow::{Cow, ToOwned}; +use std::ffi::{CStr, OsStr}; +use std::path::Path; +use std::rc::Rc; +use std::sync::Arc; + +macro_rules! test_from_cow { + ($value:ident => $($ty:ty),+) => {$( + let borrowed = <$ty>::from(Cow::Borrowed($value)); + let owned = <$ty>::from(Cow::Owned($value.to_owned())); + assert_eq!($value, &*borrowed); + assert_eq!($value, &*owned); + )+}; + ($value:ident : & $ty:ty) => { + test_from_cow!($value => Box<$ty>, Rc<$ty>, Arc<$ty>); + } +} + +#[test] +fn test_from_cow_slice() { + let slice: &[i32] = &[1, 2, 3]; + test_from_cow!(slice: &[i32]); +} + +#[test] +fn test_from_cow_str() { + let string = "hello"; + test_from_cow!(string: &str); +} + +#[test] +fn test_from_cow_c_str() { + let string = CStr::from_bytes_with_nul(b"hello\0").unwrap(); + test_from_cow!(string: &CStr); +} + +#[test] +fn test_from_cow_os_str() { + let string = OsStr::new("hello"); + test_from_cow!(string: &OsStr); +} + +#[test] +fn test_from_cow_path() { + let path = Path::new("hello"); + test_from_cow!(path: &Path); +} + +#[test] +fn cow_const() { + // test that the methods of `Cow` are usable in a const context + + const COW: Cow<'_, str> = Cow::Borrowed("moo"); + + const IS_BORROWED: bool = COW.is_borrowed(); + assert!(IS_BORROWED); + + const IS_OWNED: bool = COW.is_owned(); + assert!(!IS_OWNED); +} +use std::borrow::Cow; +use std::cell::Cell; +use std::collections::TryReserveError::*; +use std::fmt::Debug; +use std::iter::InPlaceIterable; +use std::mem::{size_of, swap}; +use std::ops::Bound::*; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::rc::Rc; +use std::sync::atomic::{AtomicU32, Ordering}; +use std::vec::{Drain, IntoIter}; + +struct DropCounter<'a> { + count: &'a mut u32, +} + +impl Drop for DropCounter<'_> { + fn drop(&mut self) { + *self.count += 1; + } +} + +#[test] +fn test_small_vec_struct() { + assert_eq!(size_of::>(), size_of::() * 3); +} + +#[test] +fn test_double_drop() { + struct TwoVec { + x: Vec, + y: Vec, + } + + let (mut count_x, mut count_y) = (0, 0); + { + let mut tv = TwoVec { x: Vec::new(), y: Vec::new() }; + tv.x.push(DropCounter { count: &mut count_x }); + tv.y.push(DropCounter { count: &mut count_y }); + + // If Vec had a drop flag, here is where it would be zeroed. + // Instead, it should rely on its internal state to prevent + // doing anything significant when dropped multiple times. + drop(tv.x); + + // Here tv goes out of scope, tv.y should be dropped, but not tv.x. + } + + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); +} + +#[test] +fn test_reserve() { + let mut v = Vec::new(); + assert_eq!(v.capacity(), 0); + + v.reserve(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push(i); + } + + assert!(v.capacity() >= 16); + v.reserve(16); + assert!(v.capacity() >= 32); + + v.push(16); + + v.reserve(16); + assert!(v.capacity() >= 33) +} + +#[test] +fn test_zst_capacity() { + assert_eq!(Vec::<()>::new().capacity(), usize::MAX); +} + +#[test] +fn test_indexing() { + let v: Vec = vec![10, 20]; + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); + let mut x: usize = 0; + assert_eq!(v[x], 10); + assert_eq!(v[x + 1], 20); + x = x + 1; + assert_eq!(v[x], 20); + assert_eq!(v[x - 1], 10); +} + +#[test] +fn test_debug_fmt() { + let vec1: Vec = vec![]; + assert_eq!("[]", format!("{:?}", vec1)); + + let vec2 = vec![0, 1]; + assert_eq!("[0, 1]", format!("{:?}", vec2)); + + let slice: &[isize] = &[4, 5]; + assert_eq!("[4, 5]", format!("{:?}", slice)); +} + +#[test] +fn test_push() { + let mut v = vec![]; + v.push(1); + assert_eq!(v, [1]); + v.push(2); + assert_eq!(v, [1, 2]); + v.push(3); + assert_eq!(v, [1, 2, 3]); +} + +#[test] +fn test_extend() { + let mut v = Vec::new(); + let mut w = Vec::new(); + + v.extend(w.clone()); + assert_eq!(v, &[]); + + v.extend(0..3); + for i in 0..3 { + w.push(i) + } + + assert_eq!(v, w); + + v.extend(3..10); + for i in 3..10 { + w.push(i) + } + + assert_eq!(v, w); + + v.extend(w.clone()); // specializes to `append` + assert!(v.iter().eq(w.iter().chain(w.iter()))); + + // Zero sized types + #[derive(PartialEq, Debug)] + struct Foo; + + let mut a = Vec::new(); + let b = vec![Foo, Foo]; + + a.extend(b); + assert_eq!(a, &[Foo, Foo]); + + // Double drop + let mut count_x = 0; + { + let mut x = Vec::new(); + let y = vec![DropCounter { count: &mut count_x }]; + x.extend(y); + } + assert_eq!(count_x, 1); +} + +#[test] +fn test_extend_from_slice() { + let a: Vec = vec![1, 2, 3, 4, 5]; + let b: Vec = vec![6, 7, 8, 9, 0]; + + let mut v: Vec = a; + + v.extend_from_slice(&b); + + assert_eq!(v, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); +} + +#[test] +fn test_extend_ref() { + let mut v = vec![1, 2]; + v.extend(&[3, 4, 5]); + + assert_eq!(v.len(), 5); + assert_eq!(v, [1, 2, 3, 4, 5]); + + let w = vec![6, 7]; + v.extend(&w); + + assert_eq!(v.len(), 7); + assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]); +} + +#[test] +fn test_slice_from_ref() { + let values = vec![1, 2, 3, 4, 5]; + let slice = &values[1..3]; + + assert_eq!(slice, [2, 3]); +} + +#[test] +fn test_slice_from_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let slice = &mut values[2..]; + assert!(slice == [3, 4, 5]); + for p in slice { + *p += 2; + } + } + + assert!(values == [1, 2, 5, 6, 7]); +} + +#[test] +fn test_slice_to_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let slice = &mut values[..2]; + assert!(slice == [1, 2]); + for p in slice { + *p += 1; + } + } + + assert!(values == [2, 3, 3, 4, 5]); +} + +#[test] +fn test_split_at_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let (left, right) = values.split_at_mut(2); + { + let left: &[_] = left; + assert!(&left[..left.len()] == &[1, 2]); + } + for p in left { + *p += 1; + } + + { + let right: &[_] = right; + assert!(&right[..right.len()] == &[3, 4, 5]); + } + for p in right { + *p += 2; + } + } + + assert_eq!(values, [2, 3, 5, 6, 7]); +} + +#[test] +fn test_clone() { + let v: Vec = vec![]; + let w = vec![1, 2, 3]; + + assert_eq!(v, v.clone()); + + let z = w.clone(); + assert_eq!(w, z); + // they should be disjoint in memory. + assert!(w.as_ptr() != z.as_ptr()) +} + +#[test] +fn test_clone_from() { + let mut v = vec![]; + let three: Vec> = vec![box 1, box 2, box 3]; + let two: Vec> = vec![box 4, box 5]; + // zero, long + v.clone_from(&three); + assert_eq!(v, three); + + // equal + v.clone_from(&three); + assert_eq!(v, three); + + // long, short + v.clone_from(&two); + assert_eq!(v, two); + + // short, long + v.clone_from(&three); + assert_eq!(v, three) +} + +#[test] +fn test_retain() { + let mut vec = vec![1, 2, 3, 4]; + vec.retain(|&x| x % 2 == 0); + assert_eq!(vec, [2, 4]); +} + +#[test] +fn test_retain_pred_panic_with_hole() { + let v = (0..5).map(Rc::new).collect::>(); + catch_unwind(AssertUnwindSafe(|| { + let mut v = v.clone(); + v.retain(|r| match **r { + 0 => true, + 1 => false, + 2 => true, + _ => panic!(), + }); + })) + .unwrap_err(); + // Everything is dropped when predicate panicked. + assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); +} + +#[test] +fn test_retain_pred_panic_no_hole() { + let v = (0..5).map(Rc::new).collect::>(); + catch_unwind(AssertUnwindSafe(|| { + let mut v = v.clone(); + v.retain(|r| match **r { + 0 | 1 | 2 => true, + _ => panic!(), + }); + })) + .unwrap_err(); + // Everything is dropped when predicate panicked. + assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); +} + +#[test] +fn test_retain_drop_panic() { + struct Wrap(Rc); + + impl Drop for Wrap { + fn drop(&mut self) { + if *self.0 == 3 { + panic!(); + } + } + } + + let v = (0..5).map(|x| Rc::new(x)).collect::>(); + catch_unwind(AssertUnwindSafe(|| { + let mut v = v.iter().map(|r| Wrap(r.clone())).collect::>(); + v.retain(|w| match *w.0 { + 0 => true, + 1 => false, + 2 => true, + 3 => false, // Drop panic. + _ => true, + }); + })) + .unwrap_err(); + // Other elements are dropped when `drop` of one element panicked. + // The panicked wrapper also has its Rc dropped. + assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); +} + +#[test] +fn test_dedup() { + fn case(a: Vec, b: Vec) { + let mut v = a; + v.dedup(); + assert_eq!(v, b); + } + case(vec![], vec![]); + case(vec![1], vec![1]); + case(vec![1, 1], vec![1]); + case(vec![1, 2, 3], vec![1, 2, 3]); + case(vec![1, 1, 2, 3], vec![1, 2, 3]); + case(vec![1, 2, 2, 3], vec![1, 2, 3]); + case(vec![1, 2, 3, 3], vec![1, 2, 3]); + case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]); +} + +#[test] +fn test_dedup_by_key() { + fn case(a: Vec, b: Vec) { + let mut v = a; + v.dedup_by_key(|i| *i / 10); + assert_eq!(v, b); + } + case(vec![], vec![]); + case(vec![10], vec![10]); + case(vec![10, 11], vec![10]); + case(vec![10, 20, 30], vec![10, 20, 30]); + case(vec![10, 11, 20, 30], vec![10, 20, 30]); + case(vec![10, 20, 21, 30], vec![10, 20, 30]); + case(vec![10, 20, 30, 31], vec![10, 20, 30]); + case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]); +} + +#[test] +fn test_dedup_by() { + let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; + vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + + assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + + let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)]; + vec.dedup_by(|a, b| { + a.0 == b.0 && { + b.1 += a.1; + true + } + }); + + assert_eq!(vec, [("foo", 3), ("bar", 12)]); +} + +#[test] +fn test_dedup_unique() { + let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; + v2.dedup(); + // If the boxed pointers were leaked or otherwise misused, valgrind + // and/or rt should raise errors. +} + +#[test] +fn zero_sized_values() { + let mut v = Vec::new(); + assert_eq!(v.len(), 0); + v.push(()); + assert_eq!(v.len(), 1); + v.push(()); + assert_eq!(v.len(), 2); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), None); + + assert_eq!(v.iter().count(), 0); + v.push(()); + assert_eq!(v.iter().count(), 1); + v.push(()); + assert_eq!(v.iter().count(), 2); + + for &() in &v {} + + assert_eq!(v.iter_mut().count(), 2); + v.push(()); + assert_eq!(v.iter_mut().count(), 3); + v.push(()); + assert_eq!(v.iter_mut().count(), 4); + + for &mut () in &mut v {} + unsafe { + v.set_len(0); + } + assert_eq!(v.iter_mut().count(), 0); +} + +#[test] +fn test_partition() { + assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); +} + +#[test] +fn test_zip_unzip() { + let z1 = vec![(1, 4), (2, 5), (3, 6)]; + + let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip(); + + assert_eq!((1, 4), (left[0], right[0])); + assert_eq!((2, 5), (left[1], right[1])); + assert_eq!((3, 6), (left[2], right[2])); +} + +#[test] +fn test_cmp() { + let x: &[isize] = &[1, 2, 3, 4, 5]; + let cmp: &[isize] = &[1, 2, 3, 4, 5]; + assert_eq!(&x[..], cmp); + let cmp: &[isize] = &[3, 4, 5]; + assert_eq!(&x[2..], cmp); + let cmp: &[isize] = &[1, 2, 3]; + assert_eq!(&x[..3], cmp); + let cmp: &[isize] = &[2, 3, 4]; + assert_eq!(&x[1..4], cmp); + + let x: Vec = vec![1, 2, 3, 4, 5]; + let cmp: &[isize] = &[1, 2, 3, 4, 5]; + assert_eq!(&x[..], cmp); + let cmp: &[isize] = &[3, 4, 5]; + assert_eq!(&x[2..], cmp); + let cmp: &[isize] = &[1, 2, 3]; + assert_eq!(&x[..3], cmp); + let cmp: &[isize] = &[2, 3, 4]; + assert_eq!(&x[1..4], cmp); +} + +#[test] +fn test_vec_truncate_drop() { + static mut DROPS: u32 = 0; + struct Elem(i32); + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; + assert_eq!(unsafe { DROPS }, 0); + v.truncate(3); + assert_eq!(unsafe { DROPS }, 2); + v.truncate(0); + assert_eq!(unsafe { DROPS }, 5); +} + +#[test] +#[should_panic] +fn test_vec_truncate_fail() { + struct BadElem(i32); + impl Drop for BadElem { + fn drop(&mut self) { + let BadElem(ref mut x) = *self; + if *x == 0xbadbeef { + panic!("BadElem panic: 0xbadbeef") + } + } + } + + let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; + v.truncate(0); +} + +#[test] +fn test_index() { + let vec = vec![1, 2, 3]; + assert!(vec[1] == 2); +} + +#[test] +#[should_panic] +fn test_index_out_of_bounds() { + let vec = vec![1, 2, 3]; + let _ = vec[3]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_1() { + let x = vec![1, 2, 3, 4, 5]; + &x[!0..]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_2() { + let x = vec![1, 2, 3, 4, 5]; + &x[..6]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_3() { + let x = vec![1, 2, 3, 4, 5]; + &x[!0..4]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_4() { + let x = vec![1, 2, 3, 4, 5]; + &x[1..6]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_5() { + let x = vec![1, 2, 3, 4, 5]; + &x[3..2]; +} + +#[test] +#[should_panic] +fn test_swap_remove_empty() { + let mut vec = Vec::::new(); + vec.swap_remove(0); +} + +#[test] +fn test_move_items() { + let vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec { + vec2.push(i); + } + assert_eq!(vec2, [1, 2, 3]); +} + +#[test] +fn test_move_items_reverse() { + let vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.into_iter().rev() { + vec2.push(i); + } + assert_eq!(vec2, [3, 2, 1]); +} + +#[test] +fn test_move_items_zero_sized() { + let vec = vec![(), (), ()]; + let mut vec2 = vec![]; + for i in vec { + vec2.push(i); + } + assert_eq!(vec2, [(), (), ()]); +} + +#[test] +fn test_drain_empty_vec() { + let mut vec: Vec = vec![]; + let mut vec2: Vec = vec![]; + for i in vec.drain(..) { + vec2.push(i); + } + assert!(vec.is_empty()); + assert!(vec2.is_empty()); +} + +#[test] +fn test_drain_items() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.drain(..) { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [1, 2, 3]); +} + +#[test] +fn test_drain_items_reverse() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.drain(..).rev() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [3, 2, 1]); +} + +#[test] +fn test_drain_items_zero_sized() { + let mut vec = vec![(), (), ()]; + let mut vec2 = vec![]; + for i in vec.drain(..) { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [(), (), ()]); +} + +#[test] +#[should_panic] +fn test_drain_out_of_bounds() { + let mut v = vec![1, 2, 3, 4, 5]; + v.drain(5..6); +} + +#[test] +fn test_drain_range() { + let mut v = vec![1, 2, 3, 4, 5]; + for _ in v.drain(4..) {} + assert_eq!(v, &[1, 2, 3, 4]); + + let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect(); + for _ in v.drain(1..4) {} + assert_eq!(v, &[1.to_string(), 5.to_string()]); + + let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect(); + for _ in v.drain(1..4).rev() {} + assert_eq!(v, &[1.to_string(), 5.to_string()]); + + let mut v: Vec<_> = vec![(); 5]; + for _ in v.drain(1..4).rev() {} + assert_eq!(v, &[(), ()]); +} + +#[test] +fn test_drain_inclusive_range() { + let mut v = vec!['a', 'b', 'c', 'd', 'e']; + for _ in v.drain(1..=3) {} + assert_eq!(v, &['a', 'e']); + + let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect(); + for _ in v.drain(1..=5) {} + assert_eq!(v, &["0".to_string()]); + + let mut v: Vec = (0..=5).map(|x| x.to_string()).collect(); + for _ in v.drain(0..=5) {} + assert_eq!(v, Vec::::new()); + + let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect(); + for _ in v.drain(0..=3) {} + assert_eq!(v, &["4".to_string(), "5".to_string()]); + + let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect(); + for _ in v.drain(..=0) {} + assert_eq!(v, &["1".to_string()]); +} + +#[test] +fn test_drain_max_vec_size() { + let mut v = Vec::<()>::with_capacity(usize::MAX); + unsafe { + v.set_len(usize::MAX); + } + for _ in v.drain(usize::MAX - 1..) {} + assert_eq!(v.len(), usize::MAX - 1); + + let mut v = Vec::<()>::with_capacity(usize::MAX); + unsafe { + v.set_len(usize::MAX); + } + for _ in v.drain(usize::MAX - 1..=usize::MAX - 1) {} + assert_eq!(v.len(), usize::MAX - 1); +} + +#[test] +#[should_panic] +fn test_drain_index_overflow() { + let mut v = Vec::<()>::with_capacity(usize::MAX); + unsafe { + v.set_len(usize::MAX); + } + v.drain(0..=usize::MAX); +} + +#[test] +#[should_panic] +fn test_drain_inclusive_out_of_bounds() { + let mut v = vec![1, 2, 3, 4, 5]; + v.drain(5..=5); +} + +#[test] +#[should_panic] +fn test_drain_start_overflow() { + let mut v = vec![1, 2, 3]; + v.drain((Excluded(usize::MAX), Included(0))); +} + +#[test] +#[should_panic] +fn test_drain_end_overflow() { + let mut v = vec![1, 2, 3]; + v.drain((Included(0), Included(usize::MAX))); +} + +#[test] +fn test_drain_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug, PartialEq)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut v = vec![ + D(0, false), + D(1, false), + D(2, false), + D(3, false), + D(4, true), + D(5, false), + D(6, false), + ]; + + catch_unwind(AssertUnwindSafe(|| { + v.drain(2..=5); + })) + .ok(); + + assert_eq!(unsafe { DROPS }, 4); + assert_eq!(v, vec![D(0, false), D(1, false), D(6, false),]); +} + +#[test] +fn test_splice() { + let mut v = vec![1, 2, 3, 4, 5]; + let a = [10, 11, 12]; + v.splice(2..4, a.iter().cloned()); + assert_eq!(v, &[1, 2, 10, 11, 12, 5]); + v.splice(1..3, Some(20)); + assert_eq!(v, &[1, 20, 11, 12, 5]); +} + +#[test] +fn test_splice_inclusive_range() { + let mut v = vec![1, 2, 3, 4, 5]; + let a = [10, 11, 12]; + let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect(); + assert_eq!(v, &[1, 2, 10, 11, 12, 5]); + assert_eq!(t1, &[3, 4]); + let t2: Vec<_> = v.splice(1..=2, Some(20)).collect(); + assert_eq!(v, &[1, 20, 11, 12, 5]); + assert_eq!(t2, &[2, 10]); +} + +#[test] +#[should_panic] +fn test_splice_out_of_bounds() { + let mut v = vec![1, 2, 3, 4, 5]; + let a = [10, 11, 12]; + v.splice(5..6, a.iter().cloned()); +} + +#[test] +#[should_panic] +fn test_splice_inclusive_out_of_bounds() { + let mut v = vec![1, 2, 3, 4, 5]; + let a = [10, 11, 12]; + v.splice(5..=5, a.iter().cloned()); +} + +#[test] +fn test_splice_items_zero_sized() { + let mut vec = vec![(), (), ()]; + let vec2 = vec![]; + let t: Vec<_> = vec.splice(1..2, vec2.iter().cloned()).collect(); + assert_eq!(vec, &[(), ()]); + assert_eq!(t, &[()]); +} + +#[test] +fn test_splice_unbounded() { + let mut vec = vec![1, 2, 3, 4, 5]; + let t: Vec<_> = vec.splice(.., None).collect(); + assert_eq!(vec, &[]); + assert_eq!(t, &[1, 2, 3, 4, 5]); +} + +#[test] +fn test_splice_forget() { + let mut v = vec![1, 2, 3, 4, 5]; + let a = [10, 11, 12]; + std::mem::forget(v.splice(2..4, a.iter().cloned())); + assert_eq!(v, &[1, 2]); +} + +#[test] +fn test_into_boxed_slice() { + let xs = vec![1, 2, 3]; + let ys = xs.into_boxed_slice(); + assert_eq!(&*ys, [1, 2, 3]); +} + +#[test] +fn test_append() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![4, 5, 6]; + vec.append(&mut vec2); + assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + assert_eq!(vec2, []); +} + +#[test] +fn test_split_off() { + let mut vec = vec![1, 2, 3, 4, 5, 6]; + let orig_capacity = vec.capacity(); + let vec2 = vec.split_off(4); + assert_eq!(vec, [1, 2, 3, 4]); + assert_eq!(vec2, [5, 6]); + assert_eq!(vec.capacity(), orig_capacity); +} + +#[test] +fn test_split_off_take_all() { + let mut vec = vec![1, 2, 3, 4, 5, 6]; + let orig_ptr = vec.as_ptr(); + let orig_capacity = vec.capacity(); + let vec2 = vec.split_off(0); + assert_eq!(vec, []); + assert_eq!(vec2, [1, 2, 3, 4, 5, 6]); + assert_eq!(vec.capacity(), orig_capacity); + assert_eq!(vec2.as_ptr(), orig_ptr); +} + +#[test] +fn test_into_iter_as_slice() { + let vec = vec!['a', 'b', 'c']; + let mut into_iter = vec.into_iter(); + assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + let _ = into_iter.next().unwrap(); + assert_eq!(into_iter.as_slice(), &['b', 'c']); + let _ = into_iter.next().unwrap(); + let _ = into_iter.next().unwrap(); + assert_eq!(into_iter.as_slice(), &[]); +} + +#[test] +fn test_into_iter_as_mut_slice() { + let vec = vec!['a', 'b', 'c']; + let mut into_iter = vec.into_iter(); + assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + into_iter.as_mut_slice()[0] = 'x'; + into_iter.as_mut_slice()[1] = 'y'; + assert_eq!(into_iter.next().unwrap(), 'x'); + assert_eq!(into_iter.as_slice(), &['y', 'c']); +} + +#[test] +fn test_into_iter_debug() { + let vec = vec!['a', 'b', 'c']; + let into_iter = vec.into_iter(); + let debug = format!("{:?}", into_iter); + assert_eq!(debug, "IntoIter(['a', 'b', 'c'])"); +} + +#[test] +fn test_into_iter_count() { + assert_eq!(vec![1, 2, 3].into_iter().count(), 3); +} + +#[test] +fn test_into_iter_clone() { + fn iter_equal>(it: I, slice: &[i32]) { + let v: Vec = it.collect(); + assert_eq!(&v[..], slice); + } + let mut it = vec![1, 2, 3].into_iter(); + iter_equal(it.clone(), &[1, 2, 3]); + assert_eq!(it.next(), Some(1)); + let mut it = it.rev(); + iter_equal(it.clone(), &[3, 2]); + assert_eq!(it.next(), Some(3)); + iter_equal(it.clone(), &[2]); + assert_eq!(it.next(), Some(2)); + iter_equal(it.clone(), &[]); + assert_eq!(it.next(), None); +} + +#[test] +fn test_into_iter_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let v = vec![D(false), D(true), D(false)]; + + catch_unwind(move || drop(v.into_iter())).ok(); + + assert_eq!(unsafe { DROPS }, 3); +} + +#[test] +fn test_from_iter_specialization() { + let src: Vec = vec![0usize; 1]; + let srcptr = src.as_ptr(); + let sink = src.into_iter().collect::>(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr); +} + +#[test] +fn test_from_iter_partially_drained_in_place_specialization() { + let src: Vec = vec![0usize; 10]; + let srcptr = src.as_ptr(); + let mut iter = src.into_iter(); + iter.next(); + iter.next(); + let sink = iter.collect::>(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr); +} + +#[test] +fn test_from_iter_specialization_with_iterator_adapters() { + fn assert_in_place_trait(_: &T) {} + let src: Vec = vec![0usize; 256]; + let srcptr = src.as_ptr(); + let iter = src + .into_iter() + .enumerate() + .map(|i| i.0 + i.1) + .zip(std::iter::repeat(1usize)) + .map(|(a, b)| a + b) + .map_while(Option::Some) + .peekable() + .skip(1) + .map(|e| if e != usize::MAX { Ok(std::num::NonZeroUsize::new(e)) } else { Err(()) }); + assert_in_place_trait(&iter); + let sink = iter.collect::, _>>().unwrap(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr as *const usize); +} + +#[test] +fn test_from_iter_specialization_head_tail_drop() { + let drop_count: Vec<_> = (0..=2).map(|_| Rc::new(())).collect(); + let src: Vec<_> = drop_count.iter().cloned().collect(); + let srcptr = src.as_ptr(); + let iter = src.into_iter(); + let sink: Vec<_> = iter.skip(1).take(1).collect(); + let sinkptr = sink.as_ptr(); + assert_eq!(srcptr, sinkptr, "specialization was applied"); + assert_eq!(Rc::strong_count(&drop_count[0]), 1, "front was dropped"); + assert_eq!(Rc::strong_count(&drop_count[1]), 2, "one element was collected"); + assert_eq!(Rc::strong_count(&drop_count[2]), 1, "tail was dropped"); + assert_eq!(sink.len(), 1); +} + +#[test] +fn test_from_iter_specialization_panic_during_iteration_drops() { + let drop_count: Vec<_> = (0..=2).map(|_| Rc::new(())).collect(); + let src: Vec<_> = drop_count.iter().cloned().collect(); + let iter = src.into_iter(); + + let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { + let _ = iter + .enumerate() + .filter_map(|(i, e)| { + if i == 1 { + std::panic!("aborting iteration"); + } + Some(e) + }) + .collect::>(); + })); + + assert!( + drop_count.iter().map(Rc::strong_count).all(|count| count == 1), + "all items were dropped once" + ); +} + +#[test] +fn test_from_iter_specialization_panic_during_drop_leaks() { + static mut DROP_COUNTER: usize = 0; + + #[derive(Debug)] + enum Droppable { + DroppedTwice(Box), + PanicOnDrop, + } + + impl Drop for Droppable { + fn drop(&mut self) { + match self { + Droppable::DroppedTwice(_) => { + unsafe { + DROP_COUNTER += 1; + } + println!("Dropping!") + } + Droppable::PanicOnDrop => { + if !std::thread::panicking() { + panic!(); + } + } + } + } + } + + let mut to_free: *mut Droppable = core::ptr::null_mut(); + let mut cap = 0; + + let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { + let mut v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop]; + to_free = v.as_mut_ptr(); + cap = v.capacity(); + let _ = v.into_iter().take(0).collect::>(); + })); + + assert_eq!(unsafe { DROP_COUNTER }, 1); + // clean up the leak to keep miri happy + unsafe { + drop(Vec::from_raw_parts(to_free, 0, cap)); + } +} + +#[test] +fn test_cow_from() { + let borrowed: &[_] = &["borrowed", "(slice)"]; + let owned = vec!["owned", "(vec)"]; + match (Cow::from(owned.clone()), Cow::from(borrowed)) { + (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), + _ => panic!("invalid `Cow::from`"), + } +} + +#[test] +fn test_from_cow() { + let borrowed: &[_] = &["borrowed", "(slice)"]; + let owned = vec!["owned", "(vec)"]; + assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]); + assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]); +} + +#[allow(dead_code)] +fn assert_covariance() { + fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { + d + } + fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> { + i + } +} + +#[test] +fn from_into_inner() { + let vec = vec![1, 2, 3]; + let ptr = vec.as_ptr(); + let vec = vec.into_iter().collect::>(); + assert_eq!(vec, [1, 2, 3]); + assert_eq!(vec.as_ptr(), ptr); + + let ptr = &vec[1] as *const _; + let mut it = vec.into_iter(); + it.next().unwrap(); + let vec = it.collect::>(); + assert_eq!(vec, [2, 3]); + assert!(ptr != vec.as_ptr()); +} + +#[test] +fn overaligned_allocations() { + #[repr(align(256))] + struct Foo(usize); + let mut v = vec![Foo(273)]; + for i in 0..0x1000 { + v.reserve_exact(i); + assert!(v[0].0 == 273); + assert!(v.as_ptr() as usize & 0xff == 0); + v.shrink_to_fit(); + assert!(v[0].0 == 273); + assert!(v.as_ptr() as usize & 0xff == 0); + } +} + +#[test] +fn drain_filter_empty() { + let mut vec: Vec = vec![]; + + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_zst() { + let mut vec = vec![(), (), (), (), ()]; + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_false() { + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(vec.len(), initial_len); + assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn drain_filter_true() { + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_complex() { + { + // [+xxx++++++xxxxx++++x+x++] + let mut vec = vec![ + 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, + 39, + ]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 14); + assert_eq!(vec, vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); + } + + { + // [xxx++++++xxxxx++++x+x++] + let mut vec = vec![ + 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39, + ]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 13); + assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); + } + + { + // [xxx++++++xxxxx++++x+x] + let mut vec = + vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 11); + assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]); + } + + { + // [xxxxxxxxxx+++++++++++] + let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(vec.len(), 10); + assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { + // [+++++++++++xxxxxxxxxx] + let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(vec.len(), 10); + assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} + +// FIXME: re-enable emscripten once it can unwind again +#[test] +#[cfg(not(target_os = "emscripten"))] +fn drain_filter_consumed_panic() { + use std::rc::Rc; + use std::sync::Mutex; + + struct Check { + index: usize, + drop_counts: Rc>>, + } + + impl Drop for Check { + fn drop(&mut self) { + self.drop_counts.lock().unwrap()[self.index] += 1; + println!("drop: {}", self.index); + } + } + + let check_count = 10; + let drop_counts = Rc::new(Mutex::new(vec![0_usize; check_count])); + let mut data: Vec = (0..check_count) + .map(|index| Check { index, drop_counts: Rc::clone(&drop_counts) }) + .collect(); + + let _ = std::panic::catch_unwind(move || { + let filter = |c: &mut Check| { + if c.index == 2 { + panic!("panic at index: {}", c.index); + } + // Verify that if the filter could panic again on another element + // that it would not cause a double panic and all elements of the + // vec would still be dropped exactly once. + if c.index == 4 { + panic!("panic at index: {}", c.index); + } + c.index < 6 + }; + let drain = data.drain_filter(filter); + + // NOTE: The DrainFilter is explicitly consumed + drain.for_each(drop); + }); + + let drop_counts = drop_counts.lock().unwrap(); + assert_eq!(check_count, drop_counts.len()); + + for (index, count) in drop_counts.iter().cloned().enumerate() { + assert_eq!(1, count, "unexpected drop count at index: {} (count: {})", index, count); + } +} + +// FIXME: Re-enable emscripten once it can catch panics +#[test] +#[cfg(not(target_os = "emscripten"))] +fn drain_filter_unconsumed_panic() { + use std::rc::Rc; + use std::sync::Mutex; + + struct Check { + index: usize, + drop_counts: Rc>>, + } + + impl Drop for Check { + fn drop(&mut self) { + self.drop_counts.lock().unwrap()[self.index] += 1; + println!("drop: {}", self.index); + } + } + + let check_count = 10; + let drop_counts = Rc::new(Mutex::new(vec![0_usize; check_count])); + let mut data: Vec = (0..check_count) + .map(|index| Check { index, drop_counts: Rc::clone(&drop_counts) }) + .collect(); + + let _ = std::panic::catch_unwind(move || { + let filter = |c: &mut Check| { + if c.index == 2 { + panic!("panic at index: {}", c.index); + } + // Verify that if the filter could panic again on another element + // that it would not cause a double panic and all elements of the + // vec would still be dropped exactly once. + if c.index == 4 { + panic!("panic at index: {}", c.index); + } + c.index < 6 + }; + let _drain = data.drain_filter(filter); + + // NOTE: The DrainFilter is dropped without being consumed + }); + + let drop_counts = drop_counts.lock().unwrap(); + assert_eq!(check_count, drop_counts.len()); + + for (index, count) in drop_counts.iter().cloned().enumerate() { + assert_eq!(1, count, "unexpected drop count at index: {} (count: {})", index, count); + } +} + +#[test] +fn drain_filter_unconsumed() { + let mut vec = vec![1, 2, 3, 4]; + let drain = vec.drain_filter(|&mut x| x % 2 != 0); + drop(drain); + assert_eq!(vec, [2, 4]); +} + +#[test] +fn test_reserve_exact() { + // This is all the same as test_reserve + + let mut v = Vec::new(); + assert_eq!(v.capacity(), 0); + + v.reserve_exact(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push(i); + } + + assert!(v.capacity() >= 16); + v.reserve_exact(16); + assert!(v.capacity() >= 32); + + v.push(16); + + v.reserve_exact(16); + assert!(v.capacity() >= 33) +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_reserve() { + // These are the interesting cases: + // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) + // * > isize::MAX should always fail + // * On 16/32-bit should CapacityOverflow + // * On 64-bit should OOM + // * overflow may trigger when adding `len` to `cap` (in number of elements) + // * overflow may trigger when multiplying `new_cap` by size_of:: (to get bytes) + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + // On 16/32-bit, we check that allocations don't exceed isize::MAX, + // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. + // Any platform that succeeds for these requests is technically broken with + // ptr::offset because LLVM is the worst. + let guards_against_isize = usize::BITS < 64; + + { + // Note: basic stuff is checked by test_reserve + let mut empty_bytes: Vec = Vec::new(); + + // Check isize::MAX doesn't count as an overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + // Play it again, frank! (just to be sure) + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + // Check isize::MAX + 1 does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } + + // Check usize::MAX does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } else { + // Check isize::MAX + 1 is an OOM + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + + // Check usize::MAX is an OOM + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an OOM!") + } + } + } + + { + // Same basic idea, but with non-zero len + let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + // Should always overflow in the add-to-len + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } + + { + // Same basic idea, but with interesting type size + let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + // Should fail in the mul-by-size + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { + } else { + panic!("usize::MAX should trigger an overflow!"); + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_reserve_exact() { + // This is exactly the same as test_try_reserve with the method changed. + // See that test for comments. + + const MAX_CAP: usize = isize::MAX as usize; + const MAX_USIZE: usize = usize::MAX; + + let guards_against_isize = size_of::() < 8; + + { + let mut empty_bytes: Vec = Vec::new(); + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } else { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an OOM!") + } + } + } + + { + let mut ten_bytes: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } + + { + let mut ten_u32s: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } +} + +#[test] +fn test_stable_pointers() { + /// Pull an element from the iterator, then drop it. + /// Useful to cover both the `next` and `drop` paths of an iterator. + fn next_then_drop(mut i: I) { + i.next().unwrap(); + drop(i); + } + + // Test that, if we reserved enough space, adding and removing elements does not + // invalidate references into the vector (such as `v0`). This test also + // runs in Miri, which would detect such problems. + // Note that this test does *not* constitute a stable guarantee that all these functions do not + // reallocate! Only what is explicitly documented at + // is stably guaranteed. + let mut v = Vec::with_capacity(128); + v.push(13); + + // Laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. + let v0 = &mut v[0]; + let v0 = unsafe { &mut *(v0 as *mut _) }; + // Now do a bunch of things and occasionally use `v0` again to assert it is still valid. + + // Pushing/inserting and popping/removing + v.push(1); + v.push(2); + v.insert(1, 1); + assert_eq!(*v0, 13); + v.remove(1); + v.pop().unwrap(); + assert_eq!(*v0, 13); + v.push(1); + v.swap_remove(1); + assert_eq!(v.len(), 2); + v.swap_remove(1); // swap_remove the last element + assert_eq!(*v0, 13); + + // Appending + v.append(&mut vec![27, 19]); + assert_eq!(*v0, 13); + + // Extending + v.extend_from_slice(&[1, 2]); + v.extend(&[1, 2]); // `slice::Iter` (with `T: Copy`) specialization + v.extend(vec![2, 3]); // `vec::IntoIter` specialization + v.extend(std::iter::once(3)); // `TrustedLen` specialization + v.extend(std::iter::empty::()); // `TrustedLen` specialization with empty iterator + v.extend(std::iter::once(3).filter(|_| true)); // base case + v.extend(std::iter::once(&3)); // `cloned` specialization + assert_eq!(*v0, 13); + + // Truncation + v.truncate(2); + assert_eq!(*v0, 13); + + // Resizing + v.resize_with(v.len() + 10, || 42); + assert_eq!(*v0, 13); + v.resize_with(2, || panic!()); + assert_eq!(*v0, 13); + + // No-op reservation + v.reserve(32); + v.reserve_exact(32); + assert_eq!(*v0, 13); + + // Partial draining + v.resize_with(10, || 42); + next_then_drop(v.drain(5..)); + assert_eq!(*v0, 13); + + // Splicing + v.resize_with(10, || 42); + next_then_drop(v.splice(5.., vec![1, 2, 3, 4, 5])); // empty tail after range + assert_eq!(*v0, 13); + next_then_drop(v.splice(5..8, vec![1])); // replacement is smaller than original range + assert_eq!(*v0, 13); + next_then_drop(v.splice(5..6, vec![1; 10].into_iter().filter(|_| true))); // lower bound not exact + assert_eq!(*v0, 13); + + // spare_capacity_mut + v.spare_capacity_mut(); + assert_eq!(*v0, 13); + + // Smoke test that would fire even outside Miri if an actual relocation happened. + *v0 -= 13; + assert_eq!(v[0], 0); +} + +// https://github.com/rust-lang/rust/pull/49496 introduced specialization based on: +// +// ``` +// unsafe impl IsZero for *mut T { +// fn is_zero(&self) -> bool { +// (*self).is_null() +// } +// } +// ``` +// +// … to call `RawVec::with_capacity_zeroed` for creating `Vec<*mut T>`, +// which is incorrect for fat pointers since `<*mut T>::is_null` only looks at the data component. +// That is, a fat pointer can be “null” without being made entirely of zero bits. +#[test] +fn vec_macro_repeating_null_raw_fat_pointer() { + let raw_dyn = &mut (|| ()) as &mut dyn Fn() as *mut dyn Fn(); + let vtable = dbg!(ptr_metadata(raw_dyn)); + let null_raw_dyn = ptr_from_raw_parts(std::ptr::null_mut(), vtable); + assert!(null_raw_dyn.is_null()); + + let vec = vec![null_raw_dyn; 1]; + dbg!(ptr_metadata(vec[0])); + assert!(vec[0] == null_raw_dyn); + + // Polyfill for https://github.com/rust-lang/rfcs/pull/2580 + + fn ptr_metadata(ptr: *mut dyn Fn()) -> *mut () { + unsafe { std::mem::transmute::<*mut dyn Fn(), DynRepr>(ptr).vtable } + } + + fn ptr_from_raw_parts(data: *mut (), vtable: *mut ()) -> *mut dyn Fn() { + unsafe { std::mem::transmute::(DynRepr { data, vtable }) } + } + + #[repr(C)] + struct DynRepr { + data: *mut (), + vtable: *mut (), + } +} + +// This test will likely fail if you change the capacities used in +// `RawVec::grow_amortized`. +#[test] +fn test_push_growth_strategy() { + // If the element size is 1, we jump from 0 to 8, then double. + { + let mut v1: Vec = vec![]; + assert_eq!(v1.capacity(), 0); + + for _ in 0..8 { + v1.push(0); + assert_eq!(v1.capacity(), 8); + } + + for _ in 8..16 { + v1.push(0); + assert_eq!(v1.capacity(), 16); + } + + for _ in 16..32 { + v1.push(0); + assert_eq!(v1.capacity(), 32); + } + + for _ in 32..64 { + v1.push(0); + assert_eq!(v1.capacity(), 64); + } + } + + // If the element size is 2..=1024, we jump from 0 to 4, then double. + { + let mut v2: Vec = vec![]; + let mut v1024: Vec<[u8; 1024]> = vec![]; + assert_eq!(v2.capacity(), 0); + assert_eq!(v1024.capacity(), 0); + + for _ in 0..4 { + v2.push(0); + v1024.push([0; 1024]); + assert_eq!(v2.capacity(), 4); + assert_eq!(v1024.capacity(), 4); + } + + for _ in 4..8 { + v2.push(0); + v1024.push([0; 1024]); + assert_eq!(v2.capacity(), 8); + assert_eq!(v1024.capacity(), 8); + } + + for _ in 8..16 { + v2.push(0); + v1024.push([0; 1024]); + assert_eq!(v2.capacity(), 16); + assert_eq!(v1024.capacity(), 16); + } + + for _ in 16..32 { + v2.push(0); + v1024.push([0; 1024]); + assert_eq!(v2.capacity(), 32); + assert_eq!(v1024.capacity(), 32); + } + + for _ in 32..64 { + v2.push(0); + v1024.push([0; 1024]); + assert_eq!(v2.capacity(), 64); + assert_eq!(v1024.capacity(), 64); + } + } + + // If the element size is > 1024, we jump from 0 to 1, then double. + { + let mut v1025: Vec<[u8; 1025]> = vec![]; + assert_eq!(v1025.capacity(), 0); + + for _ in 0..1 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 1); + } + + for _ in 1..2 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 2); + } + + for _ in 2..4 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 4); + } + + for _ in 4..8 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 8); + } + + for _ in 8..16 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 16); + } + + for _ in 16..32 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 32); + } + + for _ in 32..64 { + v1025.push([0; 1025]); + assert_eq!(v1025.capacity(), 64); + } + } +} + +macro_rules! generate_assert_eq_vec_and_prim { + ($name:ident<$B:ident>($type:ty)) => { + fn $name + Debug, $B: Debug>(a: Vec, b: $type) { + assert!(a == b); + assert_eq!(a, b); + } + }; +} + +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_slice (&[B]) } +generate_assert_eq_vec_and_prim! { assert_eq_vec_and_array_3([B; 3]) } + +#[test] +fn partialeq_vec_and_prim() { + assert_eq_vec_and_slice(vec![1, 2, 3], &[1, 2, 3]); + assert_eq_vec_and_array_3(vec![1, 2, 3], [1, 2, 3]); +} + +macro_rules! assert_partial_eq_valid { + ($a2:expr, $a3:expr; $b2:expr, $b3: expr) => { + assert!($a2 == $b2); + assert!($a2 != $b3); + assert!($a3 != $b2); + assert!($a3 == $b3); + assert_eq!($a2, $b2); + assert_ne!($a2, $b3); + assert_ne!($a3, $b2); + assert_eq!($a3, $b3); + }; +} + +#[test] +fn partialeq_vec_full() { + let vec2: Vec<_> = vec![1, 2]; + let vec3: Vec<_> = vec![1, 2, 3]; + let slice2: &[_] = &[1, 2]; + let slice3: &[_] = &[1, 2, 3]; + let slicemut2: &[_] = &mut [1, 2]; + let slicemut3: &[_] = &mut [1, 2, 3]; + let array2: [_; 2] = [1, 2]; + let array3: [_; 3] = [1, 2, 3]; + let arrayref2: &[_; 2] = &[1, 2]; + let arrayref3: &[_; 3] = &[1, 2, 3]; + + assert_partial_eq_valid!(vec2,vec3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; slice2,slice3); + assert_partial_eq_valid!(vec2,vec3; slicemut2,slicemut3); + assert_partial_eq_valid!(slice2,slice3; vec2,vec3); + assert_partial_eq_valid!(slicemut2,slicemut3; vec2,vec3); + assert_partial_eq_valid!(vec2,vec3; array2,array3); + assert_partial_eq_valid!(vec2,vec3; arrayref2,arrayref3); + assert_partial_eq_valid!(vec2,vec3; arrayref2[..],arrayref3[..]); +} + +#[test] +fn test_vec_cycle() { + #[derive(Debug)] + struct C<'a> { + v: Vec>>>, + } + + impl<'a> C<'a> { + fn new() -> C<'a> { + C { v: Vec::new() } + } + } + + let mut c1 = C::new(); + let mut c2 = C::new(); + let mut c3 = C::new(); + + // Push + c1.v.push(Cell::new(None)); + c1.v.push(Cell::new(None)); + + c2.v.push(Cell::new(None)); + c2.v.push(Cell::new(None)); + + c3.v.push(Cell::new(None)); + c3.v.push(Cell::new(None)); + + // Set + c1.v[0].set(Some(&c2)); + c1.v[1].set(Some(&c3)); + + c2.v[0].set(Some(&c2)); + c2.v[1].set(Some(&c3)); + + c3.v[0].set(Some(&c1)); + c3.v[1].set(Some(&c2)); +} + +#[test] +fn test_vec_cycle_wrapped() { + struct Refs<'a> { + v: Vec>>>, + } + + struct C<'a> { + refs: Refs<'a>, + } + + impl<'a> Refs<'a> { + fn new() -> Refs<'a> { + Refs { v: Vec::new() } + } + } + + impl<'a> C<'a> { + fn new() -> C<'a> { + C { refs: Refs::new() } + } + } + + let mut c1 = C::new(); + let mut c2 = C::new(); + let mut c3 = C::new(); + + c1.refs.v.push(Cell::new(None)); + c1.refs.v.push(Cell::new(None)); + c2.refs.v.push(Cell::new(None)); + c2.refs.v.push(Cell::new(None)); + c3.refs.v.push(Cell::new(None)); + c3.refs.v.push(Cell::new(None)); + + c1.refs.v[0].set(Some(&c2)); + c1.refs.v[1].set(Some(&c3)); + c2.refs.v[0].set(Some(&c2)); + c2.refs.v[1].set(Some(&c3)); + c3.refs.v[0].set(Some(&c1)); + c3.refs.v[1].set(Some(&c2)); +} + +#[test] +fn test_zero_sized_vec_push() { + const N: usize = 8; + + for len in 0..N { + let mut tester = Vec::with_capacity(len); + assert_eq!(tester.len(), 0); + assert!(tester.capacity() >= len); + for _ in 0..len { + tester.push(()); + } + assert_eq!(tester.len(), len); + assert_eq!(tester.iter().count(), len); + tester.clear(); + } +} + +#[test] +fn test_vec_macro_repeat() { + assert_eq!(vec![1; 3], vec![1, 1, 1]); + assert_eq!(vec![1; 2], vec![1, 1]); + assert_eq!(vec![1; 1], vec![1]); + assert_eq!(vec![1; 0], vec![]); + + // from_elem syntax (see RFC 832) + let el = Box::new(1); + let n = 3; + assert_eq!(vec![el; n], vec![Box::new(1), Box::new(1), Box::new(1)]); +} + +#[test] +fn test_vec_swap() { + let mut a: Vec = vec![0, 1, 2, 3, 4, 5, 6]; + a.swap(2, 4); + assert_eq!(a[2], 4); + assert_eq!(a[4], 2); + let mut n = 42; + swap(&mut n, &mut a[0]); + assert_eq!(a[0], 42); + assert_eq!(n, 0); +} + +#[test] +fn test_extend_from_within_spec() { + #[derive(Copy)] + struct CopyOnly; + + impl Clone for CopyOnly { + fn clone(&self) -> Self { + panic!("extend_from_within must use specialization on copy"); + } + } + + vec![CopyOnly, CopyOnly].extend_from_within(..); +} + +#[test] +fn test_extend_from_within_clone() { + let mut v = vec![String::from("sssss"), String::from("12334567890"), String::from("c")]; + v.extend_from_within(1..); + + assert_eq!(v, ["sssss", "12334567890", "c", "12334567890", "c"]); +} + +#[test] +fn test_extend_from_within_complete_rande() { + let mut v = vec![0, 1, 2, 3]; + v.extend_from_within(..); + + assert_eq!(v, [0, 1, 2, 3, 0, 1, 2, 3]); +} + +#[test] +fn test_extend_from_within_empty_rande() { + let mut v = vec![0, 1, 2, 3]; + v.extend_from_within(1..1); + + assert_eq!(v, [0, 1, 2, 3]); +} + +#[test] +#[should_panic] +fn test_extend_from_within_out_of_rande() { + let mut v = vec![0, 1]; + v.extend_from_within(..3); +} + +#[test] +fn test_extend_from_within_zst() { + let mut v = vec![(); 8]; + v.extend_from_within(3..7); + + assert_eq!(v, [(); 12]); +} + +#[test] +fn test_extend_from_within_empty_vec() { + let mut v = Vec::::new(); + v.extend_from_within(..); + + assert_eq!(v, []); +} + +#[test] +fn test_extend_from_within() { + let mut v = vec![String::from("a"), String::from("b"), String::from("c")]; + v.extend_from_within(1..=2); + v.extend_from_within(..=1); + + assert_eq!(v, ["a", "b", "c", "b", "c", "a", "b"]); +} + +#[test] +fn test_vec_dedup_by() { + let mut vec: Vec = vec![1, -1, 2, 3, 1, -5, 5, -2, 2]; + + vec.dedup_by(|a, b| a.abs() == b.abs()); + + assert_eq!(vec, [1, 2, 3, 1, -5, -2]); +} + +#[test] +fn test_vec_dedup_empty() { + let mut vec: Vec = Vec::new(); + + vec.dedup(); + + assert_eq!(vec, []); +} + +#[test] +fn test_vec_dedup_one() { + let mut vec = vec![12i32]; + + vec.dedup(); + + assert_eq!(vec, [12]); +} + +#[test] +fn test_vec_dedup_multiple_ident() { + let mut vec = vec![12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11]; + + vec.dedup(); + + assert_eq!(vec, [12, 11]); +} + +#[test] +fn test_vec_dedup_partialeq() { + #[derive(Debug)] + struct Foo(i32, i32); + + impl PartialEq for Foo { + fn eq(&self, other: &Foo) -> bool { + self.0 == other.0 + } + } + + let mut vec = vec![Foo(0, 1), Foo(0, 5), Foo(1, 7), Foo(1, 9)]; + + vec.dedup(); + assert_eq!(vec, [Foo(0, 1), Foo(1, 7)]); +} + +#[test] +fn test_vec_dedup() { + let mut vec: Vec = Vec::with_capacity(8); + let mut template = vec.clone(); + + for x in 0u8..255u8 { + vec.clear(); + template.clear(); + + let iter = (0..8).map(move |bit| (x >> bit) & 1 == 1); + vec.extend(iter); + template.extend_from_slice(&vec); + + let (dedup, _) = template.partition_dedup(); + vec.dedup(); + + assert_eq!(vec, dedup); + } +} + +#[test] +fn test_vec_dedup_panicking() { + #[derive(Debug)] + struct Panic { + drop_counter: &'static AtomicU32, + value: bool, + index: usize, + } + + impl PartialEq for Panic { + fn eq(&self, other: &Self) -> bool { + self.value == other.value + } + } + + impl Drop for Panic { + fn drop(&mut self) { + let x = self.drop_counter.fetch_add(1, Ordering::SeqCst); + assert!(x != 4); + } + } + + static DROP_COUNTER: AtomicU32 = AtomicU32::new(0); + let expected = [ + Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 }, + ]; + let mut vec = vec![ + Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 }, + // these elements get deduplicated + Panic { drop_counter: &DROP_COUNTER, value: false, index: 1 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 2 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 3 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 4 }, + // here it panics + Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 }, + ]; + + let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + vec.dedup(); + })); + + let ok = vec.iter().zip(expected.iter()).all(|(x, y)| x.index == y.index); + + if !ok { + panic!("expected: {:?}\ngot: {:?}\n", expected, vec); + } +} + +// Regression test for issue #82533 +#[test] +fn test_extend_from_within_panicing_clone() { + struct Panic<'dc> { + drop_count: &'dc AtomicU32, + aaaaa: bool, + } + + impl Clone for Panic<'_> { + fn clone(&self) -> Self { + if self.aaaaa { + panic!("panic! at the clone"); + } + + Self { ..*self } + } + } + + impl Drop for Panic<'_> { + fn drop(&mut self) { + self.drop_count.fetch_add(1, Ordering::SeqCst); + } + } + + let count = core::sync::atomic::AtomicU32::new(0); + let mut vec = vec![ + Panic { drop_count: &count, aaaaa: false }, + Panic { drop_count: &count, aaaaa: true }, + Panic { drop_count: &count, aaaaa: false }, + ]; + + // This should clone&append one Panic{..} at the end, and then panic while + // cloning second Panic{..}. This means that `Panic::drop` should be called + // 4 times (3 for items already in vector, 1 for just appended). + // + // Previously just appended item was leaked, making drop_count = 3, instead of 4. + std::panic::catch_unwind(move || vec.extend_from_within(..)).unwrap_err(); + + assert_eq!(count.load(Ordering::SeqCst), 4); +} +#![feature(allocator_api)] +#![feature(box_syntax)] +#![feature(cow_is_borrowed)] +#![feature(const_cow_is_borrowed)] +#![feature(drain_filter)] +#![feature(exact_size_is_empty)] +#![feature(new_uninit)] +#![feature(pattern)] +#![feature(trusted_len)] +#![feature(try_reserve)] +#![feature(unboxed_closures)] +#![feature(associated_type_bounds)] +#![feature(binary_heap_into_iter_sorted)] +#![feature(binary_heap_drain_sorted)] +#![feature(slice_ptr_get)] +#![feature(binary_heap_retain)] +#![feature(binary_heap_as_slice)] +#![feature(inplace_iteration)] +#![feature(iter_map_while)] +#![feature(vecdeque_binary_search)] +#![feature(slice_group_by)] +#![feature(slice_partition_dedup)] +#![feature(vec_spare_capacity)] +#![feature(string_remove_matches)] + +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; + +mod arc; +mod binary_heap; +mod borrow; +mod boxed; +mod btree_set_hash; +mod cow_str; +mod fmt; +mod heap; +mod linked_list; +mod rc; +mod slice; +mod str; +mod string; +mod vec; +mod vec_deque; + +fn hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() +} + +// FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. +// See https://github.com/kripken/emscripten-fastcomp/issues/169 +#[cfg(not(target_os = "emscripten"))] +#[test] +fn test_boxed_hasher() { + let ordinary_hash = hash(&5u32); + + let mut hasher_1 = Box::new(DefaultHasher::new()); + 5u32.hash(&mut hasher_1); + assert_eq!(ordinary_hash, hasher_1.finish()); + + let mut hasher_2 = Box::new(DefaultHasher::new()) as Box; + 5u32.hash(&mut hasher_2); + assert_eq!(ordinary_hash, hasher_2.finish()); +} +use std::borrow::Cow; + +// check that Cow<'a, str> implements addition +#[test] +fn check_cow_add_cow() { + let borrowed1 = Cow::Borrowed("Hello, "); + let borrowed2 = Cow::Borrowed("World!"); + let borrow_empty = Cow::Borrowed(""); + + let owned1: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); + let owned2: Cow<'_, str> = Cow::Owned(String::from("Rustaceans!")); + let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); + + assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone()); + assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone()); + + assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone()); + assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone()); + + if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() { + panic!("Adding empty strings to a borrow should note allocate"); + } +} + +#[test] +fn check_cow_add_str() { + let borrowed = Cow::Borrowed("Hello, "); + let borrow_empty = Cow::Borrowed(""); + + let owned: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); + let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); + + assert_eq!("Hello, World!", borrowed.clone() + "World!"); + + assert_eq!("Hi, World!", owned.clone() + "World!"); + + if let Cow::Owned(_) = borrowed.clone() + "" { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = owned_empty.clone() + "Hello, " { + panic!("Adding empty strings to a borrow should note allocate"); + } +} + +#[test] +fn check_cow_add_assign_cow() { + let mut borrowed1 = Cow::Borrowed("Hello, "); + let borrowed2 = Cow::Borrowed("World!"); + let borrow_empty = Cow::Borrowed(""); + + let mut owned1: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); + let owned2: Cow<'_, str> = Cow::Owned(String::from("Rustaceans!")); + let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); + + let mut s = borrowed1.clone(); + s += borrow_empty.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrow_empty.clone(); + s += borrowed1.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrowed1.clone(); + s += owned_empty.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = owned_empty.clone(); + s += borrowed1.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + + owned1 += borrowed2; + borrowed1 += owned2; + + assert_eq!("Hi, World!", owned1); + assert_eq!("Hello, Rustaceans!", borrowed1); +} + +#[test] +fn check_cow_add_assign_str() { + let mut borrowed = Cow::Borrowed("Hello, "); + let borrow_empty = Cow::Borrowed(""); + + let mut owned: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); + let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); + + let mut s = borrowed.clone(); + s += ""; + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrow_empty.clone(); + s += "World!"; + assert_eq!("World!", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = owned_empty.clone(); + s += "World!"; + assert_eq!("World!", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + + owned += "World!"; + borrowed += "World!"; + + assert_eq!("Hi, World!", owned); + assert_eq!("Hello, World!", borrowed); +} + +#[test] +fn check_cow_clone_from() { + let mut c1: Cow<'_, str> = Cow::Owned(String::with_capacity(25)); + let s: String = "hi".to_string(); + assert!(s.capacity() < 25); + let c2: Cow<'_, str> = Cow::Owned(s); + c1.clone_from(&c2); + assert!(c1.into_owned().capacity() >= 25); + let mut c3: Cow<'_, str> = Cow::Borrowed("bye"); + c3.clone_from(&c2); + assert_eq!(c2, c3); +} +use std::any::Any; +use std::cell::RefCell; +use std::cmp::PartialEq; +use std::iter::TrustedLen; +use std::mem; +use std::rc::{Rc, Weak}; + +#[test] +fn uninhabited() { + enum Void {} + let mut a = Weak::::new(); + a = a.clone(); + assert!(a.upgrade().is_none()); + + let mut a: Weak = a; // Unsizing + a = a.clone(); + assert!(a.upgrade().is_none()); +} + +#[test] +fn slice() { + let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]); + let a: Rc<[u32]> = a; // Unsizing + let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion + assert_eq!(a, b); + + // Exercise is_dangling() with a DST + let mut a = Rc::downgrade(&a); + a = a.clone(); + assert!(a.upgrade().is_some()); +} + +#[test] +fn trait_object() { + let a: Rc = Rc::new(4); + let a: Rc = a; // Unsizing + + // Exercise is_dangling() with a DST + let mut a = Rc::downgrade(&a); + a = a.clone(); + assert!(a.upgrade().is_some()); + + let mut b = Weak::::new(); + b = b.clone(); + assert!(b.upgrade().is_none()); + let mut b: Weak = b; // Unsizing + b = b.clone(); + assert!(b.upgrade().is_none()); +} + +#[test] +fn float_nan_ne() { + let x = Rc::new(f32::NAN); + assert!(x != x); + assert!(!(x == x)); +} + +#[test] +fn partial_eq() { + struct TestPEq(RefCell); + impl PartialEq for TestPEq { + fn eq(&self, other: &TestPEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Rc::new(TestPEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 4); +} + +#[test] +fn eq() { + #[derive(Eq)] + struct TestEq(RefCell); + impl PartialEq for TestEq { + fn eq(&self, other: &TestEq) -> bool { + *self.0.borrow_mut() += 1; + *other.0.borrow_mut() += 1; + true + } + } + let x = Rc::new(TestEq(RefCell::new(0))); + assert!(x == x); + assert!(!(x != x)); + assert_eq!(*x.0.borrow(), 0); +} + +const SHARED_ITER_MAX: u16 = 100; + +fn assert_trusted_len(_: &I) {} + +#[test] +fn shared_from_iter_normal() { + // Exercise the base implementation for non-`TrustedLen` iterators. + { + // `Filter` is never `TrustedLen` since we don't + // know statically how many elements will be kept: + let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new); + + // Collecting into a `Vec` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::>(); + let rc = iter.collect::>(); + assert_eq!(&*vec, &*rc); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. +} + +#[test] +fn shared_from_iter_trustedlen_normal() { + // Exercise the `TrustedLen` implementation under normal circumstances + // where `size_hint()` matches `(_, Some(exact_len))`. + { + let iter = (0..SHARED_ITER_MAX).map(Box::new); + assert_trusted_len(&iter); + + // Collecting into a `Vec` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::>(); + let rc = iter.collect::>(); + assert_eq!(&*vec, &*rc); + assert_eq!(mem::size_of::>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc)); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. + + // Try a ZST to make sure it is handled well. + { + let iter = (0..SHARED_ITER_MAX).map(drop); + let vec = iter.clone().collect::>(); + let rc = iter.collect::>(); + assert_eq!(&*vec, &*rc); + assert_eq!(0, mem::size_of_val(&*rc)); + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } +} + +#[test] +#[should_panic = "I've almost got 99 problems."] +fn shared_from_iter_trustedlen_panic() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. + let iter = (0..SHARED_ITER_MAX).map(|val| match val { + 98 => panic!("I've almost got 99 problems."), + _ => Box::new(val), + }); + assert_trusted_len(&iter); + let _ = iter.collect::>(); + + panic!("I am unreachable."); +} + +#[test] +fn shared_from_iter_trustedlen_no_fuse() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner. + struct Iter(std::vec::IntoIter>>); + + unsafe impl TrustedLen for Iter {} + + impl Iterator for Iter { + fn size_hint(&self) -> (usize, Option) { + (2, Some(2)) + } + + type Item = Box; + + fn next(&mut self) -> Option { + self.0.next().flatten() + } + } + + let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))]; + let iter = Iter(vec.into_iter()); + assert_trusted_len(&iter); + assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::>()); +} +use std::cell::Cell; +use std::cmp::Ordering::{self, Equal, Greater, Less}; +use std::convert::identity; +use std::mem; +use std::panic; +use std::rc::Rc; +use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; + +use rand::distributions::Standard; +use rand::seq::SliceRandom; +use rand::{thread_rng, Rng, RngCore}; + +fn square(n: usize) -> usize { + n * n +} + +fn is_odd(n: &usize) -> bool { + *n % 2 == 1 +} + +#[test] +fn test_from_fn() { + // Test on-stack from_fn. + let mut v: Vec<_> = (0..3).map(square).collect(); + { + let v = v; + assert_eq!(v.len(), 3); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 4); + } + + // Test on-heap from_fn. + v = (0..5).map(square).collect(); + { + let v = v; + assert_eq!(v.len(), 5); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 4); + assert_eq!(v[3], 9); + assert_eq!(v[4], 16); + } +} + +#[test] +fn test_from_elem() { + // Test on-stack from_elem. + let mut v = vec![10, 10]; + { + let v = v; + assert_eq!(v.len(), 2); + assert_eq!(v[0], 10); + assert_eq!(v[1], 10); + } + + // Test on-heap from_elem. + v = vec![20; 6]; + { + let v = &v[..]; + assert_eq!(v[0], 20); + assert_eq!(v[1], 20); + assert_eq!(v[2], 20); + assert_eq!(v[3], 20); + assert_eq!(v[4], 20); + assert_eq!(v[5], 20); + } +} + +#[test] +fn test_is_empty() { + let xs: [i32; 0] = []; + assert!(xs.is_empty()); + assert!(![0].is_empty()); +} + +#[test] +fn test_len_divzero() { + type Z = [i8; 0]; + let v0: &[Z] = &[]; + let v1: &[Z] = &[[]]; + let v2: &[Z] = &[[], []]; + assert_eq!(mem::size_of::(), 0); + assert_eq!(v0.len(), 0); + assert_eq!(v1.len(), 1); + assert_eq!(v2.len(), 2); +} + +#[test] +fn test_get() { + let mut a = vec![11]; + assert_eq!(a.get(1), None); + a = vec![11, 12]; + assert_eq!(a.get(1).unwrap(), &12); + a = vec![11, 12, 13]; + assert_eq!(a.get(1).unwrap(), &12); +} + +#[test] +fn test_first() { + let mut a = vec![]; + assert_eq!(a.first(), None); + a = vec![11]; + assert_eq!(a.first().unwrap(), &11); + a = vec![11, 12]; + assert_eq!(a.first().unwrap(), &11); +} + +#[test] +fn test_first_mut() { + let mut a = vec![]; + assert_eq!(a.first_mut(), None); + a = vec![11]; + assert_eq!(*a.first_mut().unwrap(), 11); + a = vec![11, 12]; + assert_eq!(*a.first_mut().unwrap(), 11); +} + +#[test] +fn test_split_first() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert!(b.split_first().is_none()); + assert_eq!(a.split_first(), Some((&11, b))); + a = vec![11, 12]; + let b: &[i32] = &[12]; + assert_eq!(a.split_first(), Some((&11, b))); +} + +#[test] +fn test_split_first_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(b.split_first_mut().is_none()); + assert!(a.split_first_mut() == Some((&mut 11, b))); + a = vec![11, 12]; + let b: &mut [_] = &mut [12]; + assert!(a.split_first_mut() == Some((&mut 11, b))); +} + +#[test] +fn test_split_last() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert!(b.split_last().is_none()); + assert_eq!(a.split_last(), Some((&11, b))); + a = vec![11, 12]; + let b: &[_] = &[11]; + assert_eq!(a.split_last(), Some((&12, b))); +} + +#[test] +fn test_split_last_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(b.split_last_mut().is_none()); + assert!(a.split_last_mut() == Some((&mut 11, b))); + + a = vec![11, 12]; + let b: &mut [_] = &mut [11]; + assert!(a.split_last_mut() == Some((&mut 12, b))); +} + +#[test] +fn test_last() { + let mut a = vec![]; + assert_eq!(a.last(), None); + a = vec![11]; + assert_eq!(a.last().unwrap(), &11); + a = vec![11, 12]; + assert_eq!(a.last().unwrap(), &12); +} + +#[test] +fn test_last_mut() { + let mut a = vec![]; + assert_eq!(a.last_mut(), None); + a = vec![11]; + assert_eq!(*a.last_mut().unwrap(), 11); + a = vec![11, 12]; + assert_eq!(*a.last_mut().unwrap(), 12); +} + +#[test] +fn test_slice() { + // Test fixed length vector. + let vec_fixed = [1, 2, 3, 4]; + let v_a = vec_fixed[1..vec_fixed.len()].to_vec(); + assert_eq!(v_a.len(), 3); + + assert_eq!(v_a[0], 2); + assert_eq!(v_a[1], 3); + assert_eq!(v_a[2], 4); + + // Test on stack. + let vec_stack: &[_] = &[1, 2, 3]; + let v_b = vec_stack[1..3].to_vec(); + assert_eq!(v_b.len(), 2); + + assert_eq!(v_b[0], 2); + assert_eq!(v_b[1], 3); + + // Test `Box<[T]>` + let vec_unique = vec![1, 2, 3, 4, 5, 6]; + let v_d = vec_unique[1..6].to_vec(); + assert_eq!(v_d.len(), 5); + + assert_eq!(v_d[0], 2); + assert_eq!(v_d[1], 3); + assert_eq!(v_d[2], 4); + assert_eq!(v_d[3], 5); + assert_eq!(v_d[4], 6); +} + +#[test] +fn test_slice_from() { + let vec: &[_] = &[1, 2, 3, 4]; + assert_eq!(&vec[..], vec); + let b: &[_] = &[3, 4]; + assert_eq!(&vec[2..], b); + let b: &[_] = &[]; + assert_eq!(&vec[4..], b); +} + +#[test] +fn test_slice_to() { + let vec: &[_] = &[1, 2, 3, 4]; + assert_eq!(&vec[..4], vec); + let b: &[_] = &[1, 2]; + assert_eq!(&vec[..2], b); + let b: &[_] = &[]; + assert_eq!(&vec[..0], b); +} + +#[test] +fn test_pop() { + let mut v = vec![5]; + let e = v.pop(); + assert_eq!(v.len(), 0); + assert_eq!(e, Some(5)); + let f = v.pop(); + assert_eq!(f, None); + let g = v.pop(); + assert_eq!(g, None); +} + +#[test] +fn test_swap_remove() { + let mut v = vec![1, 2, 3, 4, 5]; + let mut e = v.swap_remove(0); + assert_eq!(e, 1); + assert_eq!(v, [5, 2, 3, 4]); + e = v.swap_remove(3); + assert_eq!(e, 4); + assert_eq!(v, [5, 2, 3]); +} + +#[test] +#[should_panic] +fn test_swap_remove_fail() { + let mut v = vec![1]; + let _ = v.swap_remove(0); + let _ = v.swap_remove(0); +} + +#[test] +fn test_swap_remove_noncopyable() { + // Tests that we don't accidentally run destructors twice. + let mut v: Vec> = Vec::new(); + v.push(box 0); + v.push(box 0); + v.push(box 0); + let mut _e = v.swap_remove(0); + assert_eq!(v.len(), 2); + _e = v.swap_remove(1); + assert_eq!(v.len(), 1); + _e = v.swap_remove(0); + assert_eq!(v.len(), 0); +} + +#[test] +fn test_push() { + // Test on-stack push(). + let mut v = vec![]; + v.push(1); + assert_eq!(v.len(), 1); + assert_eq!(v[0], 1); + + // Test on-heap push(). + v.push(2); + assert_eq!(v.len(), 2); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); +} + +#[test] +fn test_truncate() { + let mut v: Vec> = vec![box 6, box 5, box 4]; + v.truncate(1); + let v = v; + assert_eq!(v.len(), 1); + assert_eq!(*(v[0]), 6); + // If the unsafe block didn't drop things properly, we blow up here. +} + +#[test] +fn test_clear() { + let mut v: Vec> = vec![box 6, box 5, box 4]; + v.clear(); + assert_eq!(v.len(), 0); + // If the unsafe block didn't drop things properly, we blow up here. +} + +#[test] +fn test_retain() { + let mut v = vec![1, 2, 3, 4, 5]; + v.retain(is_odd); + assert_eq!(v, [1, 3, 5]); +} + +#[test] +fn test_binary_search() { + assert_eq!([1, 2, 3, 4, 5].binary_search(&5).ok(), Some(4)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&4).ok(), Some(3)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&3).ok(), Some(2)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&2).ok(), Some(1)); + assert_eq!([1, 2, 3, 4, 5].binary_search(&1).ok(), Some(0)); + + assert_eq!([2, 4, 6, 8, 10].binary_search(&1).ok(), None); + assert_eq!([2, 4, 6, 8, 10].binary_search(&5).ok(), None); + assert_eq!([2, 4, 6, 8, 10].binary_search(&4).ok(), Some(1)); + assert_eq!([2, 4, 6, 8, 10].binary_search(&10).ok(), Some(4)); + + assert_eq!([2, 4, 6, 8].binary_search(&1).ok(), None); + assert_eq!([2, 4, 6, 8].binary_search(&5).ok(), None); + assert_eq!([2, 4, 6, 8].binary_search(&4).ok(), Some(1)); + assert_eq!([2, 4, 6, 8].binary_search(&8).ok(), Some(3)); + + assert_eq!([2, 4, 6].binary_search(&1).ok(), None); + assert_eq!([2, 4, 6].binary_search(&5).ok(), None); + assert_eq!([2, 4, 6].binary_search(&4).ok(), Some(1)); + assert_eq!([2, 4, 6].binary_search(&6).ok(), Some(2)); + + assert_eq!([2, 4].binary_search(&1).ok(), None); + assert_eq!([2, 4].binary_search(&5).ok(), None); + assert_eq!([2, 4].binary_search(&2).ok(), Some(0)); + assert_eq!([2, 4].binary_search(&4).ok(), Some(1)); + + assert_eq!([2].binary_search(&1).ok(), None); + assert_eq!([2].binary_search(&5).ok(), None); + assert_eq!([2].binary_search(&2).ok(), Some(0)); + + assert_eq!([].binary_search(&1).ok(), None); + assert_eq!([].binary_search(&5).ok(), None); + + assert!([1, 1, 1, 1, 1].binary_search(&1).ok() != None); + assert!([1, 1, 1, 1, 2].binary_search(&1).ok() != None); + assert!([1, 1, 1, 2, 2].binary_search(&1).ok() != None); + assert!([1, 1, 2, 2, 2].binary_search(&1).ok() != None); + assert_eq!([1, 2, 2, 2, 2].binary_search(&1).ok(), Some(0)); + + assert_eq!([1, 2, 3, 4, 5].binary_search(&6).ok(), None); + assert_eq!([1, 2, 3, 4, 5].binary_search(&0).ok(), None); +} + +#[test] +fn test_reverse() { + let mut v = vec![10, 20]; + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); + v.reverse(); + assert_eq!(v[0], 20); + assert_eq!(v[1], 10); + + let mut v3 = Vec::::new(); + v3.reverse(); + assert!(v3.is_empty()); + + // check the 1-byte-types path + let mut v = (-50..51i8).collect::>(); + v.reverse(); + assert_eq!(v, (-50..51i8).rev().collect::>()); + + // check the 2-byte-types path + let mut v = (-50..51i16).collect::>(); + v.reverse(); + assert_eq!(v, (-50..51i16).rev().collect::>()); +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_sort() { + let mut rng = thread_rng(); + + for len in (2..25).chain(500..510) { + for &modulus in &[5, 10, 100, 1000] { + for _ in 0..10 { + let orig: Vec<_> = + rng.sample_iter::(&Standard).map(|x| x % modulus).take(len).collect(); + + // Sort in default order. + let mut v = orig.clone(); + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + // Sort in ascending order. + let mut v = orig.clone(); + v.sort_by(|a, b| a.cmp(b)); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + // Sort in descending order. + let mut v = orig.clone(); + v.sort_by(|a, b| b.cmp(a)); + assert!(v.windows(2).all(|w| w[0] >= w[1])); + + // Sort in lexicographic order. + let mut v1 = orig.clone(); + let mut v2 = orig.clone(); + v1.sort_by_key(|x| x.to_string()); + v2.sort_by_cached_key(|x| x.to_string()); + assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); + assert!(v1 == v2); + + // Sort with many pre-sorted runs. + let mut v = orig.clone(); + v.sort(); + v.reverse(); + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + v[a..b].reverse(); + } else { + v.swap(a, b); + } + } + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } + } + } + + // Sort using a completely random comparison function. + // This will reorder the elements *somehow*, but won't panic. + let mut v = [0; 500]; + for i in 0..v.len() { + v[i] = i as i32; + } + v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap()); + v.sort(); + for i in 0..v.len() { + assert_eq!(v[i], i as i32); + } + + // Should not panic. + [0i32; 0].sort(); + [(); 10].sort(); + [(); 100].sort(); + + let mut v = [0xDEADBEEFu64]; + v.sort(); + assert!(v == [0xDEADBEEF]); +} + +#[test] +fn test_sort_stability() { + // Miri is too slow + let large_range = if cfg!(miri) { 0..0 } else { 500..510 }; + let rounds = if cfg!(miri) { 1 } else { 10 }; + + for len in (2..25).chain(large_range) { + for _ in 0..rounds { + let mut counts = [0; 10]; + + // create a vector like [(6, 1), (5, 1), (6, 2), ...], + // where the first item of each tuple is random, but + // the second item represents which occurrence of that + // number this element is, i.e., the second elements + // will occur in sorted order. + let orig: Vec<_> = (0..len) + .map(|_| { + let n = thread_rng().gen::() % 10; + counts[n] += 1; + (n, counts[n]) + }) + .collect(); + + let mut v = orig.clone(); + // Only sort on the first element, so an unstable sort + // may mix up the counts. + v.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); + + // This comparison includes the count (the second item + // of the tuple), so elements with equal first items + // will need to be ordered with increasing + // counts... i.e., exactly asserting that this sort is + // stable. + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + let mut v = orig.clone(); + v.sort_by_cached_key(|&(x, _)| x); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } + } +} + +#[test] +fn test_rotate_left() { + let expected: Vec<_> = (0..13).collect(); + let mut v = Vec::new(); + + // no-ops + v.clone_from(&expected); + v.rotate_left(0); + assert_eq!(v, expected); + v.rotate_left(expected.len()); + assert_eq!(v, expected); + let mut zst_array = [(), (), ()]; + zst_array.rotate_left(2); + + // happy path + v = (5..13).chain(0..5).collect(); + v.rotate_left(8); + assert_eq!(v, expected); + + let expected: Vec<_> = (0..1000).collect(); + + // small rotations in large slice, uses ptr::copy + v = (2..1000).chain(0..2).collect(); + v.rotate_left(998); + assert_eq!(v, expected); + v = (998..1000).chain(0..998).collect(); + v.rotate_left(2); + assert_eq!(v, expected); + + // non-small prime rotation, has a few rounds of swapping + v = (389..1000).chain(0..389).collect(); + v.rotate_left(1000 - 389); + assert_eq!(v, expected); +} + +#[test] +fn test_rotate_right() { + let expected: Vec<_> = (0..13).collect(); + let mut v = Vec::new(); + + // no-ops + v.clone_from(&expected); + v.rotate_right(0); + assert_eq!(v, expected); + v.rotate_right(expected.len()); + assert_eq!(v, expected); + let mut zst_array = [(), (), ()]; + zst_array.rotate_right(2); + + // happy path + v = (5..13).chain(0..5).collect(); + v.rotate_right(5); + assert_eq!(v, expected); + + let expected: Vec<_> = (0..1000).collect(); + + // small rotations in large slice, uses ptr::copy + v = (2..1000).chain(0..2).collect(); + v.rotate_right(2); + assert_eq!(v, expected); + v = (998..1000).chain(0..998).collect(); + v.rotate_right(998); + assert_eq!(v, expected); + + // non-small prime rotation, has a few rounds of swapping + v = (389..1000).chain(0..389).collect(); + v.rotate_right(389); + assert_eq!(v, expected); +} + +#[test] +fn test_concat() { + let v: [Vec; 0] = []; + let c = v.concat(); + assert_eq!(c, []); + let d = [vec![1], vec![2, 3]].concat(); + assert_eq!(d, [1, 2, 3]); + + let v: &[&[_]] = &[&[1], &[2, 3]]; + assert_eq!(v.join(&0), [1, 0, 2, 3]); + let v: &[&[_]] = &[&[1], &[2], &[3]]; + assert_eq!(v.join(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_join() { + let v: [Vec; 0] = []; + assert_eq!(v.join(&0), []); + assert_eq!([vec![1], vec![2, 3]].join(&0), [1, 0, 2, 3]); + assert_eq!([vec![1], vec![2], vec![3]].join(&0), [1, 0, 2, 0, 3]); + + let v: [&[_]; 2] = [&[1], &[2, 3]]; + assert_eq!(v.join(&0), [1, 0, 2, 3]); + let v: [&[_]; 3] = [&[1], &[2], &[3]]; + assert_eq!(v.join(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_join_nocopy() { + let v: [String; 0] = []; + assert_eq!(v.join(","), ""); + assert_eq!(["a".to_string(), "ab".into()].join(","), "a,ab"); + assert_eq!(["a".to_string(), "ab".into(), "abc".into()].join(","), "a,ab,abc"); + assert_eq!(["a".to_string(), "ab".into(), "".into()].join(","), "a,ab,"); +} + +#[test] +fn test_insert() { + let mut a = vec![1, 2, 4]; + a.insert(2, 3); + assert_eq!(a, [1, 2, 3, 4]); + + let mut a = vec![1, 2, 3]; + a.insert(0, 0); + assert_eq!(a, [0, 1, 2, 3]); + + let mut a = vec![1, 2, 3]; + a.insert(3, 4); + assert_eq!(a, [1, 2, 3, 4]); + + let mut a = vec![]; + a.insert(0, 1); + assert_eq!(a, [1]); +} + +#[test] +#[should_panic] +fn test_insert_oob() { + let mut a = vec![1, 2, 3]; + a.insert(4, 5); +} + +#[test] +fn test_remove() { + let mut a = vec![1, 2, 3, 4]; + + assert_eq!(a.remove(2), 3); + assert_eq!(a, [1, 2, 4]); + + assert_eq!(a.remove(2), 4); + assert_eq!(a, [1, 2]); + + assert_eq!(a.remove(0), 1); + assert_eq!(a, [2]); + + assert_eq!(a.remove(0), 2); + assert_eq!(a, []); +} + +#[test] +#[should_panic] +fn test_remove_fail() { + let mut a = vec![1]; + let _ = a.remove(0); + let _ = a.remove(0); +} + +#[test] +fn test_capacity() { + let mut v = vec![0]; + v.reserve_exact(10); + assert!(v.capacity() >= 11); +} + +#[test] +fn test_slice_2() { + let v = vec![1, 2, 3, 4, 5]; + let v = &v[1..3]; + assert_eq!(v.len(), 2); + assert_eq!(v[0], 2); + assert_eq!(v[1], 3); +} + +macro_rules! assert_order { + (Greater, $a:expr, $b:expr) => { + assert_eq!($a.cmp($b), Greater); + assert!($a > $b); + }; + (Less, $a:expr, $b:expr) => { + assert_eq!($a.cmp($b), Less); + assert!($a < $b); + }; + (Equal, $a:expr, $b:expr) => { + assert_eq!($a.cmp($b), Equal); + assert_eq!($a, $b); + }; +} + +#[test] +fn test_total_ord_u8() { + let c = &[1u8, 2, 3]; + assert_order!(Greater, &[1u8, 2, 3, 4][..], &c[..]); + let c = &[1u8, 2, 3, 4]; + assert_order!(Less, &[1u8, 2, 3][..], &c[..]); + let c = &[1u8, 2, 3, 6]; + assert_order!(Equal, &[1u8, 2, 3, 6][..], &c[..]); + let c = &[1u8, 2, 3, 4, 5, 6]; + assert_order!(Less, &[1u8, 2, 3, 4, 5, 5, 5, 5][..], &c[..]); + let c = &[1u8, 2, 3, 4]; + assert_order!(Greater, &[2u8, 2][..], &c[..]); +} + +#[test] +fn test_total_ord_i32() { + let c = &[1, 2, 3]; + assert_order!(Greater, &[1, 2, 3, 4][..], &c[..]); + let c = &[1, 2, 3, 4]; + assert_order!(Less, &[1, 2, 3][..], &c[..]); + let c = &[1, 2, 3, 6]; + assert_order!(Equal, &[1, 2, 3, 6][..], &c[..]); + let c = &[1, 2, 3, 4, 5, 6]; + assert_order!(Less, &[1, 2, 3, 4, 5, 5, 5, 5][..], &c[..]); + let c = &[1, 2, 3, 4]; + assert_order!(Greater, &[2, 2][..], &c[..]); +} + +#[test] +fn test_iterator() { + let xs = [1, 2, 5, 10, 11]; + let mut it = xs.iter(); + assert_eq!(it.size_hint(), (5, Some(5))); + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.size_hint(), (4, Some(4))); + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iter_size_hints() { + let mut xs = [1, 2, 5, 10, 11]; + assert_eq!(xs.iter().size_hint(), (5, Some(5))); + assert_eq!(xs.iter_mut().size_hint(), (5, Some(5))); +} + +#[test] +fn test_iter_as_slice() { + let xs = [1, 2, 5, 10, 11]; + let mut iter = xs.iter(); + assert_eq!(iter.as_slice(), &[1, 2, 5, 10, 11]); + iter.next(); + assert_eq!(iter.as_slice(), &[2, 5, 10, 11]); +} + +#[test] +fn test_iter_as_ref() { + let xs = [1, 2, 5, 10, 11]; + let mut iter = xs.iter(); + assert_eq!(iter.as_ref(), &[1, 2, 5, 10, 11]); + iter.next(); + assert_eq!(iter.as_ref(), &[2, 5, 10, 11]); +} + +#[test] +fn test_iter_clone() { + let xs = [1, 2, 5]; + let mut it = xs.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_iter_is_empty() { + let xs = [1, 2, 5, 10, 11]; + for i in 0..xs.len() { + for j in i..xs.len() { + assert_eq!(xs[i..j].iter().is_empty(), xs[i..j].is_empty()); + } + } +} + +#[test] +fn test_mut_iterator() { + let mut xs = [1, 2, 3, 4, 5]; + for x in &mut xs { + *x += 1; + } + assert!(xs == [2, 3, 4, 5, 6]) +} + +#[test] +fn test_rev_iterator() { + let xs = [1, 2, 5, 10, 11]; + let ys = [11, 10, 5, 2, 1]; + let mut i = 0; + for &x in xs.iter().rev() { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, 5); +} + +#[test] +fn test_mut_rev_iterator() { + let mut xs = [1, 2, 3, 4, 5]; + for (i, x) in xs.iter_mut().rev().enumerate() { + *x += i; + } + assert!(xs == [5, 5, 5, 5, 5]) +} + +#[test] +fn test_move_iterator() { + let xs = vec![1, 2, 3, 4, 5]; + assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b), 12345); +} + +#[test] +fn test_move_rev_iterator() { + let xs = vec![1, 2, 3, 4, 5]; + assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b), 54321); +} + +#[test] +fn test_splitator() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1], &[3], &[5]]; + assert_eq!(xs.split(|x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[2, 3, 4, 5]]; + assert_eq!(xs.split(|x| *x == 1).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4], &[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split(|x| *x == 10).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; + assert_eq!(xs.split(|_| true).collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitator_inclusive() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; + assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 1).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 10).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]]; + assert_eq!(xs.split_inclusive(|_| true).collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitator_inclusive_reverse() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; + assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]]; + assert_eq!(xs.split_inclusive(|x| *x == 1).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 10).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]]; + assert_eq!(xs.split_inclusive(|_| true).rev().collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::>(), splits); +} + +#[test] +fn test_splitator_mut_inclusive() { + let xs = &mut [1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 1).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 10).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]]; + assert_eq!(xs.split_inclusive_mut(|_| true).collect::>(), splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitator_mut_inclusive_reverse() { + let xs = &mut [1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; + assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 1).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 10).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]]; + assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::>(), splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::>(), splits); +} + +#[test] +fn test_splitnator() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[3, 4, 5]]; + assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[], &[], &[4, 5]]; + assert_eq!(xs.splitn(4, |_| true).collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.splitn(2, |x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitnator_mut() { + let xs = &mut [1, 2, 3, 4, 5]; + + let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]]; + assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&mut [_]] = &[&mut [1], &mut [3, 4, 5]]; + assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&mut [_]] = &[&mut [], &mut [], &mut [], &mut [4, 5]]; + assert_eq!(xs.splitn_mut(4, |_| true).collect::>(), splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&mut [i32]] = &[&mut []]; + assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_rsplitator() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[5], &[3], &[1]]; + assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[2, 3, 4, 5], &[]]; + assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[], &[1, 2, 3, 4]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); +} + +#[test] +fn test_rsplitnator() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[5], &[1, 2, 3]]; + assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[], &[], &[], &[1, 2]]; + assert_eq!(xs.rsplitn(4, |_| true).collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::>(), splits); + assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none()); +} + +#[test] +fn test_windowsator() { + let v = &[1, 2, 3, 4]; + + let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]]; + assert_eq!(v.windows(2).collect::>(), wins); + + let wins: &[&[_]] = &[&[1, 2, 3], &[2, 3, 4]]; + assert_eq!(v.windows(3).collect::>(), wins); + assert!(v.windows(6).next().is_none()); + + let wins: &[&[_]] = &[&[3, 4], &[2, 3], &[1, 2]]; + assert_eq!(v.windows(2).rev().collect::>(), wins); +} + +#[test] +#[should_panic] +fn test_windowsator_0() { + let v = &[1, 2, 3, 4]; + let _it = v.windows(0); +} + +#[test] +fn test_chunksator() { + let v = &[1, 2, 3, 4, 5]; + + assert_eq!(v.chunks(2).len(), 3); + + let chunks: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; + assert_eq!(v.chunks(2).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1, 2, 3], &[4, 5]]; + assert_eq!(v.chunks(3).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(v.chunks(6).collect::>(), chunks); + + let chunks: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; + assert_eq!(v.chunks(2).rev().collect::>(), chunks); +} + +#[test] +#[should_panic] +fn test_chunksator_0() { + let v = &[1, 2, 3, 4]; + let _it = v.chunks(0); +} + +#[test] +fn test_chunks_exactator() { + let v = &[1, 2, 3, 4, 5]; + + assert_eq!(v.chunks_exact(2).len(), 2); + + let chunks: &[&[_]] = &[&[1, 2], &[3, 4]]; + assert_eq!(v.chunks_exact(2).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1, 2, 3]]; + assert_eq!(v.chunks_exact(3).collect::>(), chunks); + let chunks: &[&[_]] = &[]; + assert_eq!(v.chunks_exact(6).collect::>(), chunks); + + let chunks: &[&[_]] = &[&[3, 4], &[1, 2]]; + assert_eq!(v.chunks_exact(2).rev().collect::>(), chunks); +} + +#[test] +#[should_panic] +fn test_chunks_exactator_0() { + let v = &[1, 2, 3, 4]; + let _it = v.chunks_exact(0); +} + +#[test] +fn test_rchunksator() { + let v = &[1, 2, 3, 4, 5]; + + assert_eq!(v.rchunks(2).len(), 3); + + let chunks: &[&[_]] = &[&[4, 5], &[2, 3], &[1]]; + assert_eq!(v.rchunks(2).collect::>(), chunks); + let chunks: &[&[_]] = &[&[3, 4, 5], &[1, 2]]; + assert_eq!(v.rchunks(3).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(v.rchunks(6).collect::>(), chunks); + + let chunks: &[&[_]] = &[&[1], &[2, 3], &[4, 5]]; + assert_eq!(v.rchunks(2).rev().collect::>(), chunks); +} + +#[test] +#[should_panic] +fn test_rchunksator_0() { + let v = &[1, 2, 3, 4]; + let _it = v.rchunks(0); +} + +#[test] +fn test_rchunks_exactator() { + let v = &[1, 2, 3, 4, 5]; + + assert_eq!(v.rchunks_exact(2).len(), 2); + + let chunks: &[&[_]] = &[&[4, 5], &[2, 3]]; + assert_eq!(v.rchunks_exact(2).collect::>(), chunks); + let chunks: &[&[_]] = &[&[3, 4, 5]]; + assert_eq!(v.rchunks_exact(3).collect::>(), chunks); + let chunks: &[&[_]] = &[]; + assert_eq!(v.rchunks_exact(6).collect::>(), chunks); + + let chunks: &[&[_]] = &[&[2, 3], &[4, 5]]; + assert_eq!(v.rchunks_exact(2).rev().collect::>(), chunks); +} + +#[test] +#[should_panic] +fn test_rchunks_exactator_0() { + let v = &[1, 2, 3, 4]; + let _it = v.rchunks_exact(0); +} + +#[test] +fn test_reverse_part() { + let mut values = [1, 2, 3, 4, 5]; + values[1..4].reverse(); + assert!(values == [1, 4, 3, 2, 5]); +} + +#[test] +fn test_show() { + macro_rules! test_show_vec { + ($x:expr, $x_str:expr) => {{ + let (x, x_str) = ($x, $x_str); + assert_eq!(format!("{:?}", x), x_str); + assert_eq!(format!("{:?}", x), x_str); + }}; + } + let empty = Vec::::new(); + test_show_vec!(empty, "[]"); + test_show_vec!(vec![1], "[1]"); + test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); + test_show_vec!(vec![vec![], vec![1], vec![1, 1]], "[[], [1], [1, 1]]"); + + let empty_mut: &mut [i32] = &mut []; + test_show_vec!(empty_mut, "[]"); + let v = &mut [1]; + test_show_vec!(v, "[1]"); + let v = &mut [1, 2, 3]; + test_show_vec!(v, "[1, 2, 3]"); + let v: &mut [&mut [_]] = &mut [&mut [], &mut [1], &mut [1, 1]]; + test_show_vec!(v, "[[], [1], [1, 1]]"); +} + +#[test] +fn test_vec_default() { + macro_rules! t { + ($ty:ty) => {{ + let v: $ty = Default::default(); + assert!(v.is_empty()); + }}; + } + + t!(&[i32]); + t!(Vec); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault() { + let mut v = vec![]; + v.reserve_exact(!0); + v.push(1); + v.push(2); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault_managed() { + let mut v = vec![Rc::new(1)]; + v.reserve_exact(!0); + v.push(Rc::new(2)); +} + +#[test] +fn test_mut_split_at() { + let mut values = [1, 2, 3, 4, 5]; + { + let (left, right) = values.split_at_mut(2); + { + let left: &[_] = left; + assert!(left[..left.len()] == [1, 2]); + } + for p in left { + *p += 1; + } + + { + let right: &[_] = right; + assert!(right[..right.len()] == [3, 4, 5]); + } + for p in right { + *p += 2; + } + } + + assert!(values == [2, 3, 5, 6, 7]); +} + +#[derive(Clone, PartialEq)] +struct Foo; + +#[test] +fn test_iter_zero_sized() { + let mut v = vec![Foo, Foo, Foo]; + assert_eq!(v.len(), 3); + let mut cnt = 0; + + for f in &v { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 3); + + for f in &v[1..3] { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 5); + + for f in &mut v { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 8); + + for f in v { + assert!(f == Foo); + cnt += 1; + } + assert_eq!(cnt, 11); + + let xs: [Foo; 3] = [Foo, Foo, Foo]; + cnt = 0; + for f in &xs { + assert!(*f == Foo); + cnt += 1; + } + assert!(cnt == 3); +} + +#[test] +fn test_shrink_to_fit() { + let mut xs = vec![0, 1, 2, 3]; + for i in 4..100 { + xs.push(i) + } + assert_eq!(xs.capacity(), 128); + xs.shrink_to_fit(); + assert_eq!(xs.capacity(), 100); + assert_eq!(xs, (0..100).collect::>()); +} + +#[test] +fn test_starts_with() { + assert!(b"foobar".starts_with(b"foo")); + assert!(!b"foobar".starts_with(b"oob")); + assert!(!b"foobar".starts_with(b"bar")); + assert!(!b"foo".starts_with(b"foobar")); + assert!(!b"bar".starts_with(b"foobar")); + assert!(b"foobar".starts_with(b"foobar")); + let empty: &[u8] = &[]; + assert!(empty.starts_with(empty)); + assert!(!empty.starts_with(b"foo")); + assert!(b"foobar".starts_with(empty)); +} + +#[test] +fn test_ends_with() { + assert!(b"foobar".ends_with(b"bar")); + assert!(!b"foobar".ends_with(b"oba")); + assert!(!b"foobar".ends_with(b"foo")); + assert!(!b"foo".ends_with(b"foobar")); + assert!(!b"bar".ends_with(b"foobar")); + assert!(b"foobar".ends_with(b"foobar")); + let empty: &[u8] = &[]; + assert!(empty.ends_with(empty)); + assert!(!empty.ends_with(b"foo")); + assert!(b"foobar".ends_with(empty)); +} + +#[test] +fn test_mut_splitator() { + let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0]; + assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); + for slice in xs.split_mut(|x| *x == 0) { + slice.reverse(); + } + assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0]); + + let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0, 6, 7]; + for slice in xs.split_mut(|x| *x == 0).take(5) { + slice.reverse(); + } + assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0, 6, 7]); +} + +#[test] +fn test_mut_splitator_rev() { + let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0]; + for slice in xs.split_mut(|x| *x == 0).rev().take(4) { + slice.reverse(); + } + assert!(xs == [1, 2, 0, 4, 3, 0, 0, 6, 5, 0]); +} + +#[test] +fn test_get_mut() { + let mut v = [0, 1, 2]; + assert_eq!(v.get_mut(3), None); + v.get_mut(1).map(|e| *e = 7); + assert_eq!(v[1], 7); + let mut x = 2; + assert_eq!(v.get_mut(2), Some(&mut x)); +} + +#[test] +fn test_mut_chunks() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.chunks_mut(3).len(), 3); + for (i, chunk) in v.chunks_mut(3).enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 0, 0, 1, 1, 1, 2]; + assert_eq!(v, result); +} + +#[test] +fn test_mut_chunks_rev() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + for (i, chunk) in v.chunks_mut(3).rev().enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [2, 2, 2, 1, 1, 1, 0]; + assert_eq!(v, result); +} + +#[test] +#[should_panic] +fn test_mut_chunks_0() { + let mut v = [1, 2, 3, 4]; + let _it = v.chunks_mut(0); +} + +#[test] +fn test_mut_chunks_exact() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.chunks_exact_mut(3).len(), 2); + for (i, chunk) in v.chunks_exact_mut(3).enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 0, 0, 1, 1, 1, 6]; + assert_eq!(v, result); +} + +#[test] +fn test_mut_chunks_exact_rev() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + for (i, chunk) in v.chunks_exact_mut(3).rev().enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [1, 1, 1, 0, 0, 0, 6]; + assert_eq!(v, result); +} + +#[test] +#[should_panic] +fn test_mut_chunks_exact_0() { + let mut v = [1, 2, 3, 4]; + let _it = v.chunks_exact_mut(0); +} + +#[test] +fn test_mut_rchunks() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.rchunks_mut(3).len(), 3); + for (i, chunk) in v.rchunks_mut(3).enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [2, 1, 1, 1, 0, 0, 0]; + assert_eq!(v, result); +} + +#[test] +fn test_mut_rchunks_rev() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + for (i, chunk) in v.rchunks_mut(3).rev().enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 1, 1, 1, 2, 2, 2]; + assert_eq!(v, result); +} + +#[test] +#[should_panic] +fn test_mut_rchunks_0() { + let mut v = [1, 2, 3, 4]; + let _it = v.rchunks_mut(0); +} + +#[test] +fn test_mut_rchunks_exact() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.rchunks_exact_mut(3).len(), 2); + for (i, chunk) in v.rchunks_exact_mut(3).enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 1, 1, 1, 0, 0, 0]; + assert_eq!(v, result); +} + +#[test] +fn test_mut_rchunks_exact_rev() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + for (i, chunk) in v.rchunks_exact_mut(3).rev().enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 0, 0, 0, 1, 1, 1]; + assert_eq!(v, result); +} + +#[test] +#[should_panic] +fn test_mut_rchunks_exact_0() { + let mut v = [1, 2, 3, 4]; + let _it = v.rchunks_exact_mut(0); +} + +#[test] +fn test_mut_last() { + let mut x = [1, 2, 3, 4, 5]; + let h = x.last_mut(); + assert_eq!(*h.unwrap(), 5); + + let y: &mut [i32] = &mut []; + assert!(y.last_mut().is_none()); +} + +#[test] +fn test_to_vec() { + let xs: Box<_> = box [1, 2, 3]; + let ys = xs.to_vec(); + assert_eq!(ys, [1, 2, 3]); +} + +#[test] +fn test_in_place_iterator_specialization() { + let src: Box<[usize]> = box [1, 2, 3]; + let src_ptr = src.as_ptr(); + let sink: Box<_> = src.into_vec().into_iter().map(std::convert::identity).collect(); + let sink_ptr = sink.as_ptr(); + assert_eq!(src_ptr, sink_ptr); +} + +#[test] +fn test_box_slice_clone() { + let data = vec![vec![0, 1], vec![0], vec![1]]; + let data2 = data.clone().into_boxed_slice().clone().to_vec(); + + assert_eq!(data, data2); +} + +#[test] +#[allow(unused_must_use)] // here, we care about the side effects of `.clone()` +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_box_slice_clone_panics() { + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Arc; + + struct Canary { + count: Arc, + panics: bool, + } + + impl Drop for Canary { + fn drop(&mut self) { + self.count.fetch_add(1, Ordering::SeqCst); + } + } + + impl Clone for Canary { + fn clone(&self) -> Self { + if self.panics { + panic!() + } + + Canary { count: self.count.clone(), panics: self.panics } + } + } + + let drop_count = Arc::new(AtomicUsize::new(0)); + let canary = Canary { count: drop_count.clone(), panics: false }; + let panic = Canary { count: drop_count.clone(), panics: true }; + + std::panic::catch_unwind(move || { + // When xs is dropped, +5. + let xs = + vec![canary.clone(), canary.clone(), canary.clone(), panic, canary].into_boxed_slice(); + + // When panic is cloned, +3. + xs.clone(); + }) + .unwrap_err(); + + // Total = 8 + assert_eq!(drop_count.load(Ordering::SeqCst), 8); +} + +#[test] +fn test_copy_from_slice() { + let src = [0, 1, 2, 3, 4, 5]; + let mut dst = [0; 6]; + dst.copy_from_slice(&src); + assert_eq!(src, dst) +} + +#[test] +#[should_panic(expected = "source slice length (4) does not match destination slice length (5)")] +fn test_copy_from_slice_dst_longer() { + let src = [0, 1, 2, 3]; + let mut dst = [0; 5]; + dst.copy_from_slice(&src); +} + +#[test] +#[should_panic(expected = "source slice length (4) does not match destination slice length (3)")] +fn test_copy_from_slice_dst_shorter() { + let src = [0, 1, 2, 3]; + let mut dst = [0; 3]; + dst.copy_from_slice(&src); +} + +const MAX_LEN: usize = 80; + +static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ + // FIXME(RFC 1109): AtomicUsize is not Copy. + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), + AtomicUsize::new(0), +]; + +static VERSIONS: AtomicUsize = AtomicUsize::new(0); + +#[derive(Clone, Eq)] +struct DropCounter { + x: u32, + id: usize, + version: Cell, +} + +impl PartialEq for DropCounter { + fn eq(&self, other: &Self) -> bool { + self.partial_cmp(other) == Some(Ordering::Equal) + } +} + +impl PartialOrd for DropCounter { + fn partial_cmp(&self, other: &Self) -> Option { + self.version.set(self.version.get() + 1); + other.version.set(other.version.get() + 1); + VERSIONS.fetch_add(2, Relaxed); + self.x.partial_cmp(&other.x) + } +} + +impl Ord for DropCounter { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(other).unwrap() + } +} + +impl Drop for DropCounter { + fn drop(&mut self) { + DROP_COUNTS[self.id].fetch_add(1, Relaxed); + VERSIONS.fetch_sub(self.version.get(), Relaxed); + } +} + +macro_rules! test { + ($input:ident, $func:ident) => { + let len = $input.len(); + + // Work out the total number of comparisons required to sort + // this array... + let mut count = 0usize; + $input.to_owned().$func(|a, b| { + count += 1; + a.cmp(b) + }); + + // ... and then panic on each and every single one. + for panic_countdown in 0..count { + // Refresh the counters. + VERSIONS.store(0, Relaxed); + for i in 0..len { + DROP_COUNTS[i].store(0, Relaxed); + } + + let v = $input.to_owned(); + let _ = std::panic::catch_unwind(move || { + let mut v = v; + let mut panic_countdown = panic_countdown; + v.$func(|a, b| { + if panic_countdown == 0 { + SILENCE_PANIC.with(|s| s.set(true)); + panic!(); + } + panic_countdown -= 1; + a.cmp(b) + }) + }); + + // Check that the number of things dropped is exactly + // what we expect (i.e., the contents of `v`). + for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { + let count = c.load(Relaxed); + assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len); + } + + // Check that the most recent versions of values were dropped. + assert_eq!(VERSIONS.load(Relaxed), 0); + } + }; +} + +thread_local!(static SILENCE_PANIC: Cell = Cell::new(false)); + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] // no threads +fn panic_safe() { + let prev = panic::take_hook(); + panic::set_hook(Box::new(move |info| { + if !SILENCE_PANIC.with(|s| s.get()) { + prev(info); + } + })); + + let mut rng = thread_rng(); + + // Miri is too slow (but still need to `chain` to make the types match) + let lens = if cfg!(miri) { (1..10).chain(0..0) } else { (1..20).chain(70..MAX_LEN) }; + let moduli: &[u32] = if cfg!(miri) { &[5] } else { &[5, 20, 50] }; + + for len in lens { + for &modulus in moduli { + for &has_runs in &[false, true] { + let mut input = (0..len) + .map(|id| DropCounter { + x: rng.next_u32() % modulus, + id: id, + version: Cell::new(0), + }) + .collect::>(); + + if has_runs { + for c in &mut input { + c.x = c.id as u32; + } + + for _ in 0..5 { + let a = rng.gen::() % len; + let b = rng.gen::() % len; + if a < b { + input[a..b].reverse(); + } else { + input.swap(a, b); + } + } + } + + test!(input, sort_by); + test!(input, sort_unstable_by); + } + } + } + + // Set default panic hook again. + drop(panic::take_hook()); +} + +#[test] +fn repeat_generic_slice() { + assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]); + assert_eq!([1, 2, 3, 4].repeat(0), vec![]); + assert_eq!([1, 2, 3, 4].repeat(1), vec![1, 2, 3, 4]); + assert_eq!([1, 2, 3, 4].repeat(3), vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]); +} + +#[test] +#[allow(unreachable_patterns)] +fn subslice_patterns() { + // This test comprehensively checks the passing static and dynamic semantics + // of subslice patterns `..`, `x @ ..`, `ref x @ ..`, and `ref mut @ ..` + // in slice patterns `[$($pat), $(,)?]` . + + #[derive(PartialEq, Debug, Clone)] + struct N(u8); + + macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } + } + + macro_rules! c { + ($inp:expr, $typ:ty, $out:expr $(,)?) => { + assert_eq!($out, identity::<$typ>($inp)) + }; + } + + macro_rules! m { + ($e:expr, $p:pat => $b:expr) => { + match $e { + $p => $b, + _ => panic!(), + } + }; + } + + // == Slices == + + // Matching slices using `ref` patterns: + let mut v = vec![N(0), N(1), N(2), N(3), N(4)]; + let mut vc = (0..=4).collect::>(); + + let [..] = v[..]; // Always matches. + m!(v[..], [N(0), ref sub @ .., N(4)] => c!(sub, &[N], n![1, 2, 3])); + m!(v[..], [N(0), ref sub @ ..] => c!(sub, &[N], n![1, 2, 3, 4])); + m!(v[..], [ref sub @ .., N(4)] => c!(sub, &[N], n![0, 1, 2, 3])); + m!(v[..], [ref sub @ .., _, _, _, _, _] => c!(sub, &[N], &n![] as &[N])); + m!(v[..], [_, _, _, _, _, ref sub @ ..] => c!(sub, &[N], &n![] as &[N])); + m!(vc[..], [x, .., y] => c!((x, y), (u8, u8), (0, 4))); + + // Matching slices using `ref mut` patterns: + let [..] = v[..]; // Always matches. + m!(v[..], [N(0), ref mut sub @ .., N(4)] => c!(sub, &mut [N], n![1, 2, 3])); + m!(v[..], [N(0), ref mut sub @ ..] => c!(sub, &mut [N], n![1, 2, 3, 4])); + m!(v[..], [ref mut sub @ .., N(4)] => c!(sub, &mut [N], n![0, 1, 2, 3])); + m!(v[..], [ref mut sub @ .., _, _, _, _, _] => c!(sub, &mut [N], &mut n![] as &mut [N])); + m!(v[..], [_, _, _, _, _, ref mut sub @ ..] => c!(sub, &mut [N], &mut n![] as &mut [N])); + m!(vc[..], [x, .., y] => c!((x, y), (u8, u8), (0, 4))); + + // Matching slices using default binding modes (&): + let [..] = &v[..]; // Always matches. + m!(&v[..], [N(0), sub @ .., N(4)] => c!(sub, &[N], n![1, 2, 3])); + m!(&v[..], [N(0), sub @ ..] => c!(sub, &[N], n![1, 2, 3, 4])); + m!(&v[..], [sub @ .., N(4)] => c!(sub, &[N], n![0, 1, 2, 3])); + m!(&v[..], [sub @ .., _, _, _, _, _] => c!(sub, &[N], &n![] as &[N])); + m!(&v[..], [_, _, _, _, _, sub @ ..] => c!(sub, &[N], &n![] as &[N])); + m!(&vc[..], [x, .., y] => c!((x, y), (&u8, &u8), (&0, &4))); + + // Matching slices using default binding modes (&mut): + let [..] = &mut v[..]; // Always matches. + m!(&mut v[..], [N(0), sub @ .., N(4)] => c!(sub, &mut [N], n![1, 2, 3])); + m!(&mut v[..], [N(0), sub @ ..] => c!(sub, &mut [N], n![1, 2, 3, 4])); + m!(&mut v[..], [sub @ .., N(4)] => c!(sub, &mut [N], n![0, 1, 2, 3])); + m!(&mut v[..], [sub @ .., _, _, _, _, _] => c!(sub, &mut [N], &mut n![] as &mut [N])); + m!(&mut v[..], [_, _, _, _, _, sub @ ..] => c!(sub, &mut [N], &mut n![] as &mut [N])); + m!(&mut vc[..], [x, .., y] => c!((x, y), (&mut u8, &mut u8), (&mut 0, &mut 4))); + + // == Arrays == + let mut v = n![0, 1, 2, 3, 4]; + let vc = [0, 1, 2, 3, 4]; + + // Matching arrays by value: + m!(v.clone(), [N(0), sub @ .., N(4)] => c!(sub, [N; 3], n![1, 2, 3])); + m!(v.clone(), [N(0), sub @ ..] => c!(sub, [N; 4], n![1, 2, 3, 4])); + m!(v.clone(), [sub @ .., N(4)] => c!(sub, [N; 4], n![0, 1, 2, 3])); + m!(v.clone(), [sub @ .., _, _, _, _, _] => c!(sub, [N; 0], n![] as [N; 0])); + m!(v.clone(), [_, _, _, _, _, sub @ ..] => c!(sub, [N; 0], n![] as [N; 0])); + m!(v.clone(), [x, .., y] => c!((x, y), (N, N), (N(0), N(4)))); + m!(v.clone(), [..] => ()); + + // Matching arrays by ref patterns: + m!(v, [N(0), ref sub @ .., N(4)] => c!(sub, &[N; 3], &n![1, 2, 3])); + m!(v, [N(0), ref sub @ ..] => c!(sub, &[N; 4], &n![1, 2, 3, 4])); + m!(v, [ref sub @ .., N(4)] => c!(sub, &[N; 4], &n![0, 1, 2, 3])); + m!(v, [ref sub @ .., _, _, _, _, _] => c!(sub, &[N; 0], &n![] as &[N; 0])); + m!(v, [_, _, _, _, _, ref sub @ ..] => c!(sub, &[N; 0], &n![] as &[N; 0])); + m!(vc, [x, .., y] => c!((x, y), (u8, u8), (0, 4))); + + // Matching arrays by ref mut patterns: + m!(v, [N(0), ref mut sub @ .., N(4)] => c!(sub, &mut [N; 3], &mut n![1, 2, 3])); + m!(v, [N(0), ref mut sub @ ..] => c!(sub, &mut [N; 4], &mut n![1, 2, 3, 4])); + m!(v, [ref mut sub @ .., N(4)] => c!(sub, &mut [N; 4], &mut n![0, 1, 2, 3])); + m!(v, [ref mut sub @ .., _, _, _, _, _] => c!(sub, &mut [N; 0], &mut n![] as &mut [N; 0])); + m!(v, [_, _, _, _, _, ref mut sub @ ..] => c!(sub, &mut [N; 0], &mut n![] as &mut [N; 0])); + + // Matching arrays by default binding modes (&): + m!(&v, [N(0), sub @ .., N(4)] => c!(sub, &[N; 3], &n![1, 2, 3])); + m!(&v, [N(0), sub @ ..] => c!(sub, &[N; 4], &n![1, 2, 3, 4])); + m!(&v, [sub @ .., N(4)] => c!(sub, &[N; 4], &n![0, 1, 2, 3])); + m!(&v, [sub @ .., _, _, _, _, _] => c!(sub, &[N; 0], &n![] as &[N; 0])); + m!(&v, [_, _, _, _, _, sub @ ..] => c!(sub, &[N; 0], &n![] as &[N; 0])); + m!(&v, [..] => ()); + m!(&v, [x, .., y] => c!((x, y), (&N, &N), (&N(0), &N(4)))); + + // Matching arrays by default binding modes (&mut): + m!(&mut v, [N(0), sub @ .., N(4)] => c!(sub, &mut [N; 3], &mut n![1, 2, 3])); + m!(&mut v, [N(0), sub @ ..] => c!(sub, &mut [N; 4], &mut n![1, 2, 3, 4])); + m!(&mut v, [sub @ .., N(4)] => c!(sub, &mut [N; 4], &mut n![0, 1, 2, 3])); + m!(&mut v, [sub @ .., _, _, _, _, _] => c!(sub, &mut [N; 0], &mut n![] as &[N; 0])); + m!(&mut v, [_, _, _, _, _, sub @ ..] => c!(sub, &mut [N; 0], &mut n![] as &[N; 0])); + m!(&mut v, [..] => ()); + m!(&mut v, [x, .., y] => c!((x, y), (&mut N, &mut N), (&mut N(0), &mut N(4)))); +} + +#[test] +fn test_group_by() { + let slice = &[1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; + + let mut iter = slice.group_by(|a, b| a == b); + assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + assert_eq!(iter.next(), Some(&[3, 3][..])); + assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next(), Some(&[1][..])); + assert_eq!(iter.next(), Some(&[0][..])); + assert_eq!(iter.next(), None); + + let mut iter = slice.group_by(|a, b| a == b); + assert_eq!(iter.next_back(), Some(&[0][..])); + assert_eq!(iter.next_back(), Some(&[1][..])); + assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&[3, 3][..])); + assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); + assert_eq!(iter.next_back(), None); + + let mut iter = slice.group_by(|a, b| a == b); + assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + assert_eq!(iter.next_back(), Some(&[0][..])); + assert_eq!(iter.next(), Some(&[3, 3][..])); + assert_eq!(iter.next_back(), Some(&[1][..])); + assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn test_group_by_mut() { + let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; + + let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); + assert_eq!(iter.next(), Some(&mut [3, 3][..])); + assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next(), Some(&mut [1][..])); + assert_eq!(iter.next(), Some(&mut [0][..])); + assert_eq!(iter.next(), None); + + let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next_back(), Some(&mut [0][..])); + assert_eq!(iter.next_back(), Some(&mut [1][..])); + assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&mut [3, 3][..])); + assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..])); + assert_eq!(iter.next_back(), None); + + let mut iter = slice.group_by_mut(|a, b| a == b); + assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); + assert_eq!(iter.next_back(), Some(&mut [0][..])); + assert_eq!(iter.next(), Some(&mut [3, 3][..])); + assert_eq!(iter.next_back(), Some(&mut [1][..])); + assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); + assert_eq!(iter.next_back(), None); +} +use std::collections::TryReserveError::*; +use std::collections::{vec_deque::Drain, VecDeque}; +use std::fmt::Debug; +use std::mem::size_of; +use std::ops::Bound::*; +use std::panic::{catch_unwind, AssertUnwindSafe}; + +use crate::hash; + +use Taggy::*; +use Taggypar::*; + +#[test] +fn test_simple() { + let mut d = VecDeque::new(); + assert_eq!(d.len(), 0); + d.push_front(17); + d.push_front(42); + d.push_back(137); + assert_eq!(d.len(), 3); + d.push_back(137); + assert_eq!(d.len(), 4); + assert_eq!(*d.front().unwrap(), 42); + assert_eq!(*d.back().unwrap(), 137); + let mut i = d.pop_front(); + assert_eq!(i, Some(42)); + i = d.pop_back(); + assert_eq!(i, Some(137)); + i = d.pop_back(); + assert_eq!(i, Some(137)); + i = d.pop_back(); + assert_eq!(i, Some(17)); + assert_eq!(d.len(), 0); + d.push_back(3); + assert_eq!(d.len(), 1); + d.push_front(2); + assert_eq!(d.len(), 2); + d.push_back(4); + assert_eq!(d.len(), 3); + d.push_front(1); + assert_eq!(d.len(), 4); + assert_eq!(d[0], 1); + assert_eq!(d[1], 2); + assert_eq!(d[2], 3); + assert_eq!(d[3], 4); +} + +fn test_parameterized(a: T, b: T, c: T, d: T) { + let mut deq = VecDeque::new(); + assert_eq!(deq.len(), 0); + deq.push_front(a.clone()); + deq.push_front(b.clone()); + deq.push_back(c.clone()); + assert_eq!(deq.len(), 3); + deq.push_back(d.clone()); + assert_eq!(deq.len(), 4); + assert_eq!((*deq.front().unwrap()).clone(), b.clone()); + assert_eq!((*deq.back().unwrap()).clone(), d.clone()); + assert_eq!(deq.pop_front().unwrap(), b.clone()); + assert_eq!(deq.pop_back().unwrap(), d.clone()); + assert_eq!(deq.pop_back().unwrap(), c.clone()); + assert_eq!(deq.pop_back().unwrap(), a.clone()); + assert_eq!(deq.len(), 0); + deq.push_back(c.clone()); + assert_eq!(deq.len(), 1); + deq.push_front(b.clone()); + assert_eq!(deq.len(), 2); + deq.push_back(d.clone()); + assert_eq!(deq.len(), 3); + deq.push_front(a.clone()); + assert_eq!(deq.len(), 4); + assert_eq!(deq[0].clone(), a.clone()); + assert_eq!(deq[1].clone(), b.clone()); + assert_eq!(deq[2].clone(), c.clone()); + assert_eq!(deq[3].clone(), d.clone()); +} + +#[test] +fn test_push_front_grow() { + let mut deq = VecDeque::new(); + for i in 0..66 { + deq.push_front(i); + } + assert_eq!(deq.len(), 66); + + for i in 0..66 { + assert_eq!(deq[i], 65 - i); + } + + let mut deq = VecDeque::new(); + for i in 0..66 { + deq.push_back(i); + } + + for i in 0..66 { + assert_eq!(deq[i], i); + } +} + +#[test] +fn test_index() { + let mut deq = VecDeque::new(); + for i in 1..4 { + deq.push_front(i); + } + assert_eq!(deq[1], 2); +} + +#[test] +#[should_panic] +fn test_index_out_of_bounds() { + let mut deq = VecDeque::new(); + for i in 1..4 { + deq.push_front(i); + } + deq[3]; +} + +#[test] +#[should_panic] +fn test_range_start_overflow() { + let deq = VecDeque::from(vec![1, 2, 3]); + deq.range((Included(0), Included(usize::MAX))); +} + +#[test] +#[should_panic] +fn test_range_end_overflow() { + let deq = VecDeque::from(vec![1, 2, 3]); + deq.range((Excluded(usize::MAX), Included(0))); +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggy { + One(i32), + Two(i32, i32), + Three(i32, i32, i32), +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggypar { + Onepar(T), + Twopar(T, T), + Threepar(T, T, T), +} + +#[derive(Clone, PartialEq, Debug)] +struct RecCy { + x: i32, + y: i32, + t: Taggy, +} + +#[test] +fn test_param_int() { + test_parameterized::(5, 72, 64, 175); +} + +#[test] +fn test_param_taggy() { + test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); +} + +#[test] +fn test_param_taggypar() { + test_parameterized::>( + Onepar::(1), + Twopar::(1, 2), + Threepar::(1, 2, 3), + Twopar::(17, 42), + ); +} + +#[test] +fn test_param_reccy() { + let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; + let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; + let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; + let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; + test_parameterized::(reccy1, reccy2, reccy3, reccy4); +} + +#[test] +fn test_with_capacity() { + let mut d = VecDeque::with_capacity(0); + d.push_back(1); + assert_eq!(d.len(), 1); + let mut d = VecDeque::with_capacity(50); + d.push_back(1); + assert_eq!(d.len(), 1); +} + +#[test] +fn test_with_capacity_non_power_two() { + let mut d3 = VecDeque::with_capacity(3); + d3.push_back(1); + + // X = None, | = lo + // [|1, X, X] + assert_eq!(d3.pop_front(), Some(1)); + // [X, |X, X] + assert_eq!(d3.front(), None); + + // [X, |3, X] + d3.push_back(3); + // [X, |3, 6] + d3.push_back(6); + // [X, X, |6] + assert_eq!(d3.pop_front(), Some(3)); + + // Pushing the lo past half way point to trigger + // the 'B' scenario for growth + // [9, X, |6] + d3.push_back(9); + // [9, 12, |6] + d3.push_back(12); + + d3.push_back(15); + // There used to be a bug here about how the + // VecDeque made growth assumptions about the + // underlying Vec which didn't hold and lead + // to corruption. + // (Vec grows to next power of two) + // good- [9, 12, 15, X, X, X, X, |6] + // bug- [15, 12, X, X, X, |6, X, X] + assert_eq!(d3.pop_front(), Some(6)); + + // Which leads us to the following state which + // would be a failure case. + // bug- [15, 12, X, X, X, X, |X, X] + assert_eq!(d3.front(), Some(&9)); +} + +#[test] +fn test_reserve_exact() { + let mut d = VecDeque::new(); + d.push_back(0); + d.reserve_exact(50); + assert!(d.capacity() >= 51); +} + +#[test] +fn test_reserve() { + let mut d = VecDeque::new(); + d.push_back(0); + d.reserve(50); + assert!(d.capacity() >= 51); +} + +#[test] +fn test_swap() { + let mut d: VecDeque<_> = (0..5).collect(); + d.pop_front(); + d.swap(0, 3); + assert_eq!(d.iter().cloned().collect::>(), [4, 2, 3, 1]); +} + +#[test] +fn test_iter() { + let mut d = VecDeque::new(); + assert_eq!(d.iter().next(), None); + assert_eq!(d.iter().size_hint(), (0, Some(0))); + + for i in 0..5 { + d.push_back(i); + } + { + let b: &[_] = &[&0, &1, &2, &3, &4]; + assert_eq!(d.iter().collect::>(), b); + } + + for i in 6..9 { + d.push_front(i); + } + { + let b: &[_] = &[&8, &7, &6, &0, &1, &2, &3, &4]; + assert_eq!(d.iter().collect::>(), b); + } + + let mut it = d.iter(); + let mut len = d.len(); + loop { + match it.next() { + None => break, + _ => { + len -= 1; + assert_eq!(it.size_hint(), (len, Some(len))) + } + } + } +} + +#[test] +fn test_rev_iter() { + let mut d = VecDeque::new(); + assert_eq!(d.iter().rev().next(), None); + + for i in 0..5 { + d.push_back(i); + } + { + let b: &[_] = &[&4, &3, &2, &1, &0]; + assert_eq!(d.iter().rev().collect::>(), b); + } + + for i in 6..9 { + d.push_front(i); + } + let b: &[_] = &[&4, &3, &2, &1, &0, &6, &7, &8]; + assert_eq!(d.iter().rev().collect::>(), b); +} + +#[test] +fn test_mut_rev_iter_wrap() { + let mut d = VecDeque::with_capacity(3); + assert!(d.iter_mut().rev().next().is_none()); + + d.push_back(1); + d.push_back(2); + d.push_back(3); + assert_eq!(d.pop_front(), Some(1)); + d.push_back(4); + + assert_eq!(d.iter_mut().rev().map(|x| *x).collect::>(), vec![4, 3, 2]); +} + +#[test] +fn test_mut_iter() { + let mut d = VecDeque::new(); + assert!(d.iter_mut().next().is_none()); + + for i in 0..3 { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().enumerate() { + assert_eq!(*elt, 2 - i); + *elt = i; + } + + { + let mut it = d.iter_mut(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } +} + +#[test] +fn test_mut_rev_iter() { + let mut d = VecDeque::new(); + assert!(d.iter_mut().rev().next().is_none()); + + for i in 0..3 { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().rev().enumerate() { + assert_eq!(*elt, i); + *elt = i; + } + + { + let mut it = d.iter_mut().rev(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } +} + +#[test] +fn test_into_iter() { + // Empty iter + { + let d: VecDeque = VecDeque::new(); + let mut iter = d.into_iter(); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + // simple iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + + let b = vec![0, 1, 2, 3, 4]; + assert_eq!(d.into_iter().collect::>(), b); + } + + // wrapped iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + let b = vec![8, 7, 6, 0, 1, 2, 3, 4]; + assert_eq!(d.into_iter().collect::>(), b); + } + + // partially used + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + let mut it = d.into_iter(); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } +} + +#[test] +fn test_drain() { + // Empty iter + { + let mut d: VecDeque = VecDeque::new(); + + { + let mut iter = d.drain(..); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert!(d.is_empty()); + } + + // simple iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + + assert_eq!(d.drain(..).collect::>(), [0, 1, 2, 3, 4]); + assert!(d.is_empty()); + } + + // wrapped iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + assert_eq!(d.drain(..).collect::>(), [8, 7, 6, 0, 1, 2, 3, 4]); + assert!(d.is_empty()); + } + + // partially used + { + let mut d: VecDeque<_> = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + { + let mut it = d.drain(..); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } + assert!(d.is_empty()); + } +} + +#[test] +fn test_from_iter() { + let v = vec![1, 2, 3, 4, 5, 6, 7]; + let deq: VecDeque<_> = v.iter().cloned().collect(); + let u: Vec<_> = deq.iter().cloned().collect(); + assert_eq!(u, v); + + let seq = (0..).step_by(2).take(256); + let deq: VecDeque<_> = seq.collect(); + for (i, &x) in deq.iter().enumerate() { + assert_eq!(2 * i, x); + } + assert_eq!(deq.len(), 256); +} + +#[test] +fn test_clone() { + let mut d = VecDeque::new(); + d.push_front(17); + d.push_front(42); + d.push_back(137); + d.push_back(137); + assert_eq!(d.len(), 4); + let mut e = d.clone(); + assert_eq!(e.len(), 4); + while !d.is_empty() { + assert_eq!(d.pop_back(), e.pop_back()); + } + assert_eq!(d.len(), 0); + assert_eq!(e.len(), 0); +} + +#[test] +fn test_eq() { + let mut d = VecDeque::new(); + assert!(d == VecDeque::with_capacity(0)); + d.push_front(137); + d.push_front(17); + d.push_front(42); + d.push_back(137); + let mut e = VecDeque::with_capacity(0); + e.push_back(42); + e.push_back(17); + e.push_back(137); + e.push_back(137); + assert!(&e == &d); + e.pop_back(); + e.push_back(0); + assert!(e != d); + e.clear(); + assert!(e == VecDeque::new()); +} + +#[test] +fn test_partial_eq_array() { + let d = VecDeque::::new(); + assert!(d == []); + + let mut d = VecDeque::new(); + d.push_front('a'); + assert!(d == ['a']); + + let mut d = VecDeque::new(); + d.push_back('a'); + assert!(d == ['a']); + + let mut d = VecDeque::new(); + d.push_back('a'); + d.push_back('b'); + assert!(d == ['a', 'b']); +} + +#[test] +fn test_hash() { + let mut x = VecDeque::new(); + let mut y = VecDeque::new(); + + x.push_back(1); + x.push_back(2); + x.push_back(3); + + y.push_back(0); + y.push_back(1); + y.pop_front(); + y.push_back(2); + y.push_back(3); + + assert!(hash(&x) == hash(&y)); +} + +#[test] +fn test_hash_after_rotation() { + // test that two deques hash equal even if elements are laid out differently + let len = 28; + let mut ring: VecDeque = (0..len as i32).collect(); + let orig = ring.clone(); + for _ in 0..ring.capacity() { + // shift values 1 step to the right by pop, sub one, push + ring.pop_front(); + for elt in &mut ring { + *elt -= 1; + } + ring.push_back(len - 1); + assert_eq!(hash(&orig), hash(&ring)); + assert_eq!(orig, ring); + assert_eq!(ring, orig); + } +} + +#[test] +fn test_eq_after_rotation() { + // test that two deques are equal even if elements are laid out differently + let len = 28; + let mut ring: VecDeque = (0..len as i32).collect(); + let mut shifted = ring.clone(); + for _ in 0..10 { + // shift values 1 step to the right by pop, sub one, push + ring.pop_front(); + for elt in &mut ring { + *elt -= 1; + } + ring.push_back(len - 1); + } + + // try every shift + for _ in 0..shifted.capacity() { + shifted.pop_front(); + for elt in &mut shifted { + *elt -= 1; + } + shifted.push_back(len - 1); + assert_eq!(shifted, ring); + assert_eq!(ring, shifted); + } +} + +#[test] +fn test_ord() { + let x = VecDeque::new(); + let mut y = VecDeque::new(); + y.push_back(1); + y.push_back(2); + y.push_back(3); + assert!(x < y); + assert!(y > x); + assert!(x <= x); + assert!(x >= x); +} + +#[test] +fn test_show() { + let ringbuf: VecDeque<_> = (0..10).collect(); + assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); + assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[test] +fn test_drop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe { DROPS }, 2); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_clear() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe { DROPS }, 4); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = VecDeque::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} + +#[test] +fn test_reserve_grow() { + // test growth path A + // [T o o H] -> [T o o H . . . . ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } + + // test growth path B + // [H T o o] -> [. T o o H . . . ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..1 { + ring.push_back(i); + assert_eq!(ring.pop_front(), Some(i)); + } + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } + + // test growth path C + // [o o H T] -> [o o H . . . . T ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..3 { + ring.push_back(i); + assert_eq!(ring.pop_front(), Some(i)); + } + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } +} + +#[test] +fn test_get() { + let mut ring = VecDeque::new(); + ring.push_back(0); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), None); + + ring.push_back(1); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), Some(&1)); + assert_eq!(ring.get(2), None); + + ring.push_back(2); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), Some(&1)); + assert_eq!(ring.get(2), Some(&2)); + assert_eq!(ring.get(3), None); + + assert_eq!(ring.pop_front(), Some(0)); + assert_eq!(ring.get(0), Some(&1)); + assert_eq!(ring.get(1), Some(&2)); + assert_eq!(ring.get(2), None); + + assert_eq!(ring.pop_front(), Some(1)); + assert_eq!(ring.get(0), Some(&2)); + assert_eq!(ring.get(1), None); + + assert_eq!(ring.pop_front(), Some(2)); + assert_eq!(ring.get(0), None); + assert_eq!(ring.get(1), None); +} + +#[test] +fn test_get_mut() { + let mut ring = VecDeque::new(); + for i in 0..3 { + ring.push_back(i); + } + + match ring.get_mut(1) { + Some(x) => *x = -1, + None => (), + }; + + assert_eq!(ring.get_mut(0), Some(&mut 0)); + assert_eq!(ring.get_mut(1), Some(&mut -1)); + assert_eq!(ring.get_mut(2), Some(&mut 2)); + assert_eq!(ring.get_mut(3), None); + + assert_eq!(ring.pop_front(), Some(0)); + assert_eq!(ring.get_mut(0), Some(&mut -1)); + assert_eq!(ring.get_mut(1), Some(&mut 2)); + assert_eq!(ring.get_mut(2), None); +} + +#[test] +fn test_front() { + let mut ring = VecDeque::new(); + ring.push_back(10); + ring.push_back(20); + assert_eq!(ring.front(), Some(&10)); + ring.pop_front(); + assert_eq!(ring.front(), Some(&20)); + ring.pop_front(); + assert_eq!(ring.front(), None); +} + +#[test] +fn test_as_slices() { + let mut ring: VecDeque = VecDeque::with_capacity(127); + let cap = ring.capacity() as i32; + let first = cap / 2; + let last = cap - first; + for i in 0..first { + ring.push_back(i); + + let (left, right) = ring.as_slices(); + let expected: Vec<_> = (0..=i).collect(); + assert_eq!(left, &expected[..]); + assert_eq!(right, []); + } + + for j in -last..0 { + ring.push_front(j); + let (left, right) = ring.as_slices(); + let expected_left: Vec<_> = (-last..=j).rev().collect(); + let expected_right: Vec<_> = (0..first).collect(); + assert_eq!(left, &expected_left[..]); + assert_eq!(right, &expected_right[..]); + } + + assert_eq!(ring.len() as i32, cap); + assert_eq!(ring.capacity() as i32, cap); +} + +#[test] +fn test_as_mut_slices() { + let mut ring: VecDeque = VecDeque::with_capacity(127); + let cap = ring.capacity() as i32; + let first = cap / 2; + let last = cap - first; + for i in 0..first { + ring.push_back(i); + + let (left, right) = ring.as_mut_slices(); + let expected: Vec<_> = (0..=i).collect(); + assert_eq!(left, &expected[..]); + assert_eq!(right, []); + } + + for j in -last..0 { + ring.push_front(j); + let (left, right) = ring.as_mut_slices(); + let expected_left: Vec<_> = (-last..=j).rev().collect(); + let expected_right: Vec<_> = (0..first).collect(); + assert_eq!(left, &expected_left[..]); + assert_eq!(right, &expected_right[..]); + } + + assert_eq!(ring.len() as i32, cap); + assert_eq!(ring.capacity() as i32, cap); +} + +#[test] +fn test_append() { + let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); + + // normal append + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::>(), []); + + // append nothing to something + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::>(), []); + + // append something to nothing + b.append(&mut a); + assert_eq!(b.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(a.iter().cloned().collect::>(), []); +} + +#[test] +fn test_append_permutations() { + fn construct_vec_deque( + push_back: usize, + pop_back: usize, + push_front: usize, + pop_front: usize, + ) -> VecDeque { + let mut out = VecDeque::new(); + for a in 0..push_back { + out.push_back(a); + } + for b in 0..push_front { + out.push_front(push_back + b); + } + for _ in 0..pop_back { + out.pop_back(); + } + for _ in 0..pop_front { + out.pop_front(); + } + out + } + + // Miri is too slow + let max = if cfg!(miri) { 3 } else { 5 }; + + // Many different permutations of both the `VecDeque` getting appended to + // and the one getting appended are generated to check `append`. + // This ensures all 6 code paths of `append` are tested. + for src_push_back in 0..max { + for src_push_front in 0..max { + // doesn't pop more values than are pushed + for src_pop_back in 0..(src_push_back + src_push_front) { + for src_pop_front in 0..(src_push_back + src_push_front - src_pop_back) { + let src = construct_vec_deque( + src_push_back, + src_pop_back, + src_push_front, + src_pop_front, + ); + + for dst_push_back in 0..max { + for dst_push_front in 0..max { + for dst_pop_back in 0..(dst_push_back + dst_push_front) { + for dst_pop_front in + 0..(dst_push_back + dst_push_front - dst_pop_back) + { + let mut dst = construct_vec_deque( + dst_push_back, + dst_pop_back, + dst_push_front, + dst_pop_front, + ); + let mut src = src.clone(); + + // Assert that appending `src` to `dst` gives the same order + // of values as iterating over both in sequence. + let correct = dst + .iter() + .chain(src.iter()) + .cloned() + .collect::>(); + dst.append(&mut src); + assert_eq!(dst, correct); + assert!(src.is_empty()); + } + } + } + } + } + } + } + } +} + +struct DropCounter<'a> { + count: &'a mut u32, +} + +impl Drop for DropCounter<'_> { + fn drop(&mut self) { + *self.count += 1; + } +} + +#[test] +fn test_append_double_drop() { + let (mut count_a, mut count_b) = (0, 0); + { + let mut a = VecDeque::new(); + let mut b = VecDeque::new(); + a.push_back(DropCounter { count: &mut count_a }); + b.push_back(DropCounter { count: &mut count_b }); + + a.append(&mut b); + } + assert_eq!(count_a, 1); + assert_eq!(count_b, 1); +} + +#[test] +fn test_retain() { + let mut buf = VecDeque::new(); + buf.extend(1..5); + buf.retain(|&x| x % 2 == 0); + let v: Vec<_> = buf.into_iter().collect(); + assert_eq!(&v[..], &[2, 4]); +} + +#[test] +fn test_extend_ref() { + let mut v = VecDeque::new(); + v.push_back(1); + v.extend(&[2, 3, 4]); + + assert_eq!(v.len(), 4); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); + assert_eq!(v[2], 3); + assert_eq!(v[3], 4); + + let mut w = VecDeque::new(); + w.push_back(5); + w.push_back(6); + v.extend(&w); + + assert_eq!(v.len(), 6); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); + assert_eq!(v[2], 3); + assert_eq!(v[3], 4); + assert_eq!(v[4], 5); + assert_eq!(v[5], 6); +} + +#[test] +fn test_contains() { + let mut v = VecDeque::new(); + v.extend(&[2, 3, 4]); + + assert!(v.contains(&3)); + assert!(!v.contains(&1)); + + v.clear(); + + assert!(!v.contains(&3)); +} + +#[allow(dead_code)] +fn assert_covariance() { + fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { + d + } +} + +#[test] +fn test_is_empty() { + let mut v = VecDeque::::new(); + assert!(v.is_empty()); + assert!(v.iter().is_empty()); + assert!(v.iter_mut().is_empty()); + v.extend(&[2, 3, 4]); + assert!(!v.is_empty()); + assert!(!v.iter().is_empty()); + assert!(!v.iter_mut().is_empty()); + while let Some(_) = v.pop_front() { + assert_eq!(v.is_empty(), v.len() == 0); + assert_eq!(v.iter().is_empty(), v.iter().len() == 0); + assert_eq!(v.iter_mut().is_empty(), v.iter_mut().len() == 0); + } + assert!(v.is_empty()); + assert!(v.iter().is_empty()); + assert!(v.iter_mut().is_empty()); + assert!(v.into_iter().is_empty()); +} + +#[test] +fn test_reserve_exact_2() { + // This is all the same as test_reserve + + let mut v = VecDeque::new(); + + v.reserve_exact(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push_back(i); + } + + assert!(v.capacity() >= 16); + v.reserve_exact(16); + assert!(v.capacity() >= 32); + + v.push_back(16); + + v.reserve_exact(16); + assert!(v.capacity() >= 48) +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_reserve() { + // These are the interesting cases: + // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) + // * > isize::MAX should always fail + // * On 16/32-bit should CapacityOverflow + // * On 64-bit should OOM + // * overflow may trigger when adding `len` to `cap` (in number of elements) + // * overflow may trigger when multiplying `new_cap` by size_of:: (to get bytes) + + const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1; + const MAX_USIZE: usize = usize::MAX; + + // On 16/32-bit, we check that allocations don't exceed isize::MAX, + // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. + // Any platform that succeeds for these requests is technically broken with + // ptr::offset because LLVM is the worst. + let guards_against_isize = size_of::() < 8; + + { + // Note: basic stuff is checked by test_reserve + let mut empty_bytes: VecDeque = VecDeque::new(); + + // Check isize::MAX doesn't count as an overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + // Play it again, frank! (just to be sure) + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + // Check isize::MAX + 1 does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } + + // Check usize::MAX does count as overflow + if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } else { + // Check isize::MAX is an OOM + // VecDeque starts with capacity 7, always adds 1 to the capacity + // and also rounds the number to next power of 2 so this is the + // furthest we can go without triggering CapacityOverflow + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + } + + { + // Same basic idea, but with non-zero len + let mut ten_bytes: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + // Should always overflow in the add-to-len + if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } + + { + // Same basic idea, but with interesting type size + let mut ten_u32s: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + // Should fail in the mul-by-size + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { + } else { + panic!("usize::MAX should trigger an overflow!"); + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_reserve_exact() { + // This is exactly the same as test_try_reserve with the method changed. + // See that test for comments. + + const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1; + const MAX_USIZE: usize = usize::MAX; + + let guards_against_isize = size_of::() < 8; + + { + let mut empty_bytes: VecDeque = VecDeque::new(); + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + + if guards_against_isize { + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } + + if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } else { + // Check isize::MAX is an OOM + // VecDeque starts with capacity 7, always adds 1 to the capacity + // and also rounds the number to next power of 2 so this is the + // furthest we can go without triggering CapacityOverflow + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + } + + { + let mut ten_bytes: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } + + { + let mut ten_u32s: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); + + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { + panic!("isize::MAX shouldn't trigger an overflow!"); + } + if guards_against_isize { + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } + } else { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } + } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { + } else { + panic!("usize::MAX should trigger an overflow!") + } + } +} + +#[test] +fn test_rotate_nop() { + let mut v: VecDeque<_> = (0..10).collect(); + assert_unchanged(&v); + + v.rotate_left(0); + assert_unchanged(&v); + + v.rotate_left(10); + assert_unchanged(&v); + + v.rotate_right(0); + assert_unchanged(&v); + + v.rotate_right(10); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_right(3); + assert_unchanged(&v); + + v.rotate_right(3); + v.rotate_left(3); + assert_unchanged(&v); + + v.rotate_left(6); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_right(6); + v.rotate_left(6); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_left(7); + assert_unchanged(&v); + + v.rotate_right(4); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_left(1); + v.rotate_left(2); + v.rotate_left(3); + v.rotate_left(4); + assert_unchanged(&v); + + v.rotate_right(1); + v.rotate_right(2); + v.rotate_right(3); + v.rotate_right(4); + assert_unchanged(&v); + + fn assert_unchanged(v: &VecDeque) { + assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + } +} + +#[test] +fn test_rotate_left_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6, 7, 1][..], &[2][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[5, 6, 7, 1][..], &[2, 3, 4][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[7, 1][..], &[2, 3, 4, 5, 6][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7, 1][..], &[][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7, 1, 2][..], &[3][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[6, 7, 1, 2][..], &[3, 4, 5][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[1, 2][..], &[3, 4, 5, 6, 7][..])); +} + +#[test] +fn test_rotate_right_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[6, 7][..], &[1, 2, 3, 4, 5][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7][..], &[1, 2, 3][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7][..], &[1][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[7, 1, 2, 3, 4, 5, 6][..], &[][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[5, 6][..], &[7, 1, 2, 3, 4][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6][..], &[7, 1, 2][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[1, 2, 3, 4, 5, 6][..], &[7][..])); +} + +#[test] +fn test_rotate_left_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3, + 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_left(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[i], (i + total_shift) % n); + } + } +} + +#[test] +fn test_rotate_right_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3, + 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_right(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[(i + total_shift) % n], i); + } + } +} + +#[test] +fn test_try_fold_empty() { + assert_eq!(Some(0), VecDeque::::new().iter().try_fold(0, |_, _| None)); +} + +#[test] +fn test_try_fold_none() { + let v: VecDeque = (0..12).collect(); + assert_eq!(None, v.into_iter().try_fold(0, |a, b| if b < 11 { Some(a + b) } else { None })); +} + +#[test] +fn test_try_fold_ok() { + let v: VecDeque = (0..12).collect(); + assert_eq!(Ok::<_, ()>(66), v.into_iter().try_fold(0, |a, b| Ok(a + b))); +} + +#[test] +fn test_try_fold_unit() { + let v: VecDeque<()> = std::iter::repeat(()).take(42).collect(); + assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(()))); +} + +#[test] +fn test_try_fold_unit_none() { + let v: std::collections::VecDeque<()> = [(); 10].iter().cloned().collect(); + let mut iter = v.into_iter(); + assert!(iter.try_fold((), |_, _| None).is_none()); + assert_eq!(iter.len(), 9); +} + +#[test] +fn test_try_fold_rotated() { + let mut v: VecDeque<_> = (0..12).collect(); + for n in 0..10 { + if n & 1 == 0 { + v.rotate_left(n); + } else { + v.rotate_right(n); + } + assert_eq!(Ok::<_, ()>(66), v.iter().try_fold(0, |a, b| Ok(a + b))); + } +} + +#[test] +fn test_try_fold_moves_iter() { + let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); + let mut iter = v.into_iter(); + assert_eq!(iter.try_fold(0_i8, |acc, &x| acc.checked_add(x)), None); + assert_eq!(iter.next(), Some(&60)); +} + +#[test] +fn test_try_fold_exhaust_wrap() { + let mut v = VecDeque::with_capacity(7); + v.push_back(1); + v.push_back(1); + v.push_back(1); + v.pop_front(); + v.pop_front(); + let mut iter = v.iter(); + let _ = iter.try_fold(0, |_, _| Some(1)); + assert!(iter.is_empty()); +} + +#[test] +fn test_try_fold_wraparound() { + let mut v = VecDeque::with_capacity(8); + v.push_back(7); + v.push_back(8); + v.push_back(9); + v.push_front(2); + v.push_front(1); + let mut iter = v.iter(); + let _ = iter.find(|&&x| x == 2); + assert_eq!(Some(&7), iter.next()); +} + +#[test] +fn test_try_rfold_rotated() { + let mut v: VecDeque<_> = (0..12).collect(); + for n in 0..10 { + if n & 1 == 0 { + v.rotate_left(n); + } else { + v.rotate_right(n); + } + assert_eq!(Ok::<_, ()>(66), v.iter().try_rfold(0, |a, b| Ok(a + b))); + } +} + +#[test] +fn test_try_rfold_moves_iter() { + let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); + let mut iter = v.into_iter(); + assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None); + assert_eq!(iter.next_back(), Some(&70)); +} + +#[test] +fn truncate_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = VecDeque::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(true)); + q.push_front(D(false)); + q.push_front(D(false)); + + catch_unwind(AssertUnwindSafe(|| q.truncate(1))).ok(); + + assert_eq!(unsafe { DROPS }, 7); +} + +#[test] +fn test_drain_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug, PartialEq)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut v = VecDeque::new(); + v.push_back(D(4, false)); + v.push_back(D(5, false)); + v.push_back(D(6, false)); + v.push_front(D(3, false)); + v.push_front(D(2, true)); + v.push_front(D(1, false)); + v.push_front(D(0, false)); + + catch_unwind(AssertUnwindSafe(|| { + v.drain(1..=4); + })) + .ok(); + + assert_eq!(unsafe { DROPS }, 4); + assert_eq!(v.len(), 3); + drop(v); + assert_eq!(unsafe { DROPS }, 7); +} + +#[test] +fn test_binary_search() { + // Contiguous (front only) search: + let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into(); + assert!(deque.as_slices().1.is_empty()); + assert_eq!(deque.binary_search(&3), Ok(2)); + assert_eq!(deque.binary_search(&4), Err(3)); + + // Split search (both front & back non-empty): + let mut deque: VecDeque<_> = vec![5, 6].into(); + deque.push_front(3); + deque.push_front(2); + deque.push_front(1); + deque.push_back(10); + assert!(!deque.as_slices().0.is_empty()); + assert!(!deque.as_slices().1.is_empty()); + assert_eq!(deque.binary_search(&0), Err(0)); + assert_eq!(deque.binary_search(&1), Ok(0)); + assert_eq!(deque.binary_search(&5), Ok(3)); + assert_eq!(deque.binary_search(&7), Err(5)); + assert_eq!(deque.binary_search(&20), Err(6)); +} + +#[test] +fn test_binary_search_by() { + let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into(); + + assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&3)), Ok(2)); + assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&4)), Err(3)); +} + +#[test] +fn test_binary_search_by_key() { + let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into(); + + assert_eq!(deque.binary_search_by_key(&3, |&(v,)| v), Ok(2)); + assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3)); +} + +#[test] +fn test_partition_point() { + // Contiguous (front only) search: + let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into(); + assert!(deque.as_slices().1.is_empty()); + assert_eq!(deque.partition_point(|&v| v <= 3), 3); + + // Split search (both front & back non-empty): + let mut deque: VecDeque<_> = vec![5, 6].into(); + deque.push_front(3); + deque.push_front(2); + deque.push_front(1); + deque.push_back(10); + assert!(!deque.as_slices().0.is_empty()); + assert!(!deque.as_slices().1.is_empty()); + assert_eq!(deque.partition_point(|&v| v <= 5), 4); +} + +#[test] +fn test_zero_sized_push() { + const N: usize = 8; + + // Zero sized type + struct Zst; + + // Test that for all possible sequences of push_front / push_back, + // we end up with a deque of the correct size + + for len in 0..N { + let mut tester = VecDeque::with_capacity(len); + assert_eq!(tester.len(), 0); + assert!(tester.capacity() >= len); + for case in 0..(1 << len) { + assert_eq!(tester.len(), 0); + for bit in 0..len { + if case & (1 << bit) != 0 { + tester.push_front(Zst); + } else { + tester.push_back(Zst); + } + } + assert_eq!(tester.len(), len); + assert_eq!(tester.iter().count(), len); + tester.clear(); + } + } +} + +#[test] +fn test_from_zero_sized_vec() { + let v = vec![(); 100]; + let queue = VecDeque::from(v); + assert_eq!(queue.len(), 100); +} +#![deny(warnings)] + +use std::cell::RefCell; +use std::fmt::{self, Write}; + +#[test] +fn test_format() { + let s = fmt::format(format_args!("Hello, {}!", "world")); + assert_eq!(s, "Hello, world!"); +} + +struct A; +struct B; +struct C; +struct D; + +impl fmt::LowerHex for A { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("aloha") + } +} +impl fmt::UpperHex for B { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("adios") + } +} +impl fmt::Display for C { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(true, "☃", "123") + } +} +impl fmt::Binary for D { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("aa")?; + f.write_char('☃')?; + f.write_str("bb") + } +} + +macro_rules! t { + ($a:expr, $b:expr) => { + assert_eq!($a, $b) + }; +} + +#[test] +fn test_format_macro_interface() { + // Various edge cases without formats + t!(format!(""), ""); + t!(format!("hello"), "hello"); + t!(format!("hello {{"), "hello {"); + + // default formatters should work + t!(format!("{}", 1.0f32), "1"); + t!(format!("{}", 1.0f64), "1"); + t!(format!("{}", "a"), "a"); + t!(format!("{}", "a".to_string()), "a"); + t!(format!("{}", false), "false"); + t!(format!("{}", 'a'), "a"); + + // At least exercise all the formats + t!(format!("{}", true), "true"); + t!(format!("{}", '☃'), "☃"); + t!(format!("{}", 10), "10"); + t!(format!("{}", 10_usize), "10"); + t!(format!("{:?}", '☃'), "'☃'"); + t!(format!("{:?}", 10), "10"); + t!(format!("{:?}", 10_usize), "10"); + t!(format!("{:?}", "true"), "\"true\""); + t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); + t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#); + t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#); + t!(format!("{:o}", 10_usize), "12"); + t!(format!("{:x}", 10_usize), "a"); + t!(format!("{:X}", 10_usize), "A"); + t!(format!("{}", "foo"), "foo"); + t!(format!("{}", "foo".to_string()), "foo"); + if cfg!(target_pointer_width = "32") { + t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234"); + t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234"); + } else { + t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234"); + t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234"); + } + t!(format!("{:p}", 0x1234 as *const isize), "0x1234"); + t!(format!("{:p}", 0x1234 as *mut isize), "0x1234"); + t!(format!("{:x}", A), "aloha"); + t!(format!("{:X}", B), "adios"); + t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); + t!(format!("{1} {0}", 0, 1), "1 0"); + t!(format!("{foo} {bar}", foo = 0, bar = 1), "0 1"); + t!(format!("{foo} {1} {bar} {0}", 0, 1, foo = 2, bar = 3), "2 1 3 0"); + t!(format!("{} {0}", "a"), "a a"); + t!(format!("{_foo}", _foo = 6usize), "6"); + t!(format!("{foo_bar}", foo_bar = 1), "1"); + t!(format!("{}", 5 + 5), "10"); + t!(format!("{:#4}", C), "☃123"); + t!(format!("{:b}", D), "aa☃bb"); + + let a: &dyn fmt::Debug = &1; + t!(format!("{:?}", a), "1"); + + // Formatting strings and their arguments + t!(format!("{}", "a"), "a"); + t!(format!("{:4}", "a"), "a "); + t!(format!("{:4}", "☃"), "☃ "); + t!(format!("{:>4}", "a"), " a"); + t!(format!("{:<4}", "a"), "a "); + t!(format!("{:^5}", "a"), " a "); + t!(format!("{:^5}", "aa"), " aa "); + t!(format!("{:^4}", "a"), " a "); + t!(format!("{:^4}", "aa"), " aa "); + t!(format!("{:.4}", "a"), "a"); + t!(format!("{:4.4}", "a"), "a "); + t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa"); + t!(format!("{:2.4}", "aaaaa"), "aaaa"); + t!(format!("{:2.4}", "aaaa"), "aaaa"); + t!(format!("{:2.4}", "aaa"), "aaa"); + t!(format!("{:2.4}", "aa"), "aa"); + t!(format!("{:2.4}", "a"), "a "); + t!(format!("{:0>2}", "a"), "0a"); + t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa"); + t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a = 4), "aaaa"); + t!(format!("{:._a$}", "aaaaaaaaaaaaaaaaaa", _a = 4), "aaaa"); + t!(format!("{:1$}", "a", 4), "a "); + t!(format!("{1:0$}", 4, "a"), "a "); + t!(format!("{:a$}", "a", a = 4), "a "); + t!(format!("{:-#}", "a"), "a"); + t!(format!("{:+#}", "a"), "a"); + t!(format!("{:/^10.8}", "1234567890"), "/12345678/"); + + // Some float stuff + t!(format!("{:}", 1.0f32), "1"); + t!(format!("{:}", 1.0f64), "1"); + t!(format!("{:.3}", 1.0f64), "1.000"); + t!(format!("{:10.3}", 1.0f64), " 1.000"); + t!(format!("{:+10.3}", 1.0f64), " +1.000"); + t!(format!("{:+10.3}", -1.0f64), " -1.000"); + + t!(format!("{:e}", 1.2345e6f32), "1.2345e6"); + t!(format!("{:e}", 1.2345e6f64), "1.2345e6"); + t!(format!("{:E}", 1.2345e6f64), "1.2345E6"); + t!(format!("{:.3e}", 1.2345e6f64), "1.234e6"); + t!(format!("{:10.3e}", 1.2345e6f64), " 1.234e6"); + t!(format!("{:+10.3e}", 1.2345e6f64), " +1.234e6"); + t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6"); + + // Float edge cases + t!(format!("{}", -0.0), "-0"); + t!(format!("{:?}", 0.0), "0.0"); + + // sign aware zero padding + t!(format!("{:<3}", 1), "1 "); + t!(format!("{:>3}", 1), " 1"); + t!(format!("{:^3}", 1), " 1 "); + t!(format!("{:03}", 1), "001"); + t!(format!("{:<03}", 1), "001"); + t!(format!("{:>03}", 1), "001"); + t!(format!("{:^03}", 1), "001"); + t!(format!("{:+03}", 1), "+01"); + t!(format!("{:<+03}", 1), "+01"); + t!(format!("{:>+03}", 1), "+01"); + t!(format!("{:^+03}", 1), "+01"); + t!(format!("{:#05x}", 1), "0x001"); + t!(format!("{:<#05x}", 1), "0x001"); + t!(format!("{:>#05x}", 1), "0x001"); + t!(format!("{:^#05x}", 1), "0x001"); + t!(format!("{:05}", 1.2), "001.2"); + t!(format!("{:<05}", 1.2), "001.2"); + t!(format!("{:>05}", 1.2), "001.2"); + t!(format!("{:^05}", 1.2), "001.2"); + t!(format!("{:05}", -1.2), "-01.2"); + t!(format!("{:<05}", -1.2), "-01.2"); + t!(format!("{:>05}", -1.2), "-01.2"); + t!(format!("{:^05}", -1.2), "-01.2"); + t!(format!("{:+05}", 1.2), "+01.2"); + t!(format!("{:<+05}", 1.2), "+01.2"); + t!(format!("{:>+05}", 1.2), "+01.2"); + t!(format!("{:^+05}", 1.2), "+01.2"); + + // Ergonomic format_args! + t!(format!("{0:x} {0:X}", 15), "f F"); + t!(format!("{0:x} {0:X} {}", 15), "f F 15"); + t!(format!("{:x}{0:X}{a:x}{:X}{1:x}{a:X}", 13, 14, a = 15), "dDfEeF"); + t!(format!("{a:x} {a:X}", a = 15), "f F"); + + // And its edge cases + t!( + format!( + "{a:.0$} {b:.0$} {0:.0$}\n{a:.c$} {b:.c$} {c:.c$}", + 4, + a = "abcdefg", + b = "hijklmn", + c = 3 + ), + "abcd hijk 4\nabc hij 3" + ); + t!(format!("{a:.*} {0} {:.*}", 4, 3, "efgh", a = "abcdef"), "abcd 4 efg"); + t!(format!("{:.a$} {a} {a:#x}", "aaaaaa", a = 2), "aa 2 0x2"); + + // Test that pointers don't get truncated. + { + let val = usize::MAX; + let exp = format!("{:#x}", val); + t!(format!("{:p}", val as *const isize), exp); + } + + // Escaping + t!(format!("{{"), "{"); + t!(format!("}}"), "}"); + + // make sure that format! doesn't move out of local variables + let a = Box::new(3); + format!("{}", a); + format!("{}", a); + + // make sure that format! doesn't cause spurious unused-unsafe warnings when + // it's inside of an outer unsafe block + unsafe { + let a: isize = ::std::mem::transmute(3_usize); + format!("{}", a); + } + + // test that trailing commas are acceptable + format!("{}", "test",); + format!("{foo}", foo = "test",); +} + +// Basic test to make sure that we can invoke the `write!` macro with an +// fmt::Write instance. +#[test] +fn test_write() { + let mut buf = String::new(); + let _ = write!(&mut buf, "{}", 3); + { + let w = &mut buf; + let _ = write!(w, "{foo}", foo = 4); + let _ = write!(w, "{}", "hello"); + let _ = writeln!(w, "{}", "line"); + let _ = writeln!(w, "{foo}", foo = "bar"); + let _ = w.write_char('☃'); + let _ = w.write_str("str"); + } + + t!(buf, "34helloline\nbar\n☃str"); +} + +// Just make sure that the macros are defined, there's not really a lot that we +// can do with them just yet (to test the output) +#[test] +fn test_print() { + print!("hi"); + print!("{:?}", vec![0u8]); + println!("hello"); + println!("this is a {}", "test"); + println!("{foo}", foo = "bar"); +} + +// Just make sure that the macros are defined, there's not really a lot that we +// can do with them just yet (to test the output) +#[test] +fn test_format_args() { + let mut buf = String::new(); + { + let w = &mut buf; + let _ = write!(w, "{}", format_args!("{}", 1)); + let _ = write!(w, "{}", format_args!("test")); + let _ = write!(w, "{}", format_args!("{test}", test = 3)); + } + let s = buf; + t!(s, "1test3"); + + let s = fmt::format(format_args!("hello {}", "world")); + t!(s, "hello world"); + let s = format!("{}: {}", "args were", format_args!("hello {}", "world")); + t!(s, "args were: hello world"); +} + +#[test] +fn test_order() { + // Make sure format!() arguments are always evaluated in a left-to-right + // ordering + fn foo() -> isize { + static mut FOO: isize = 0; + unsafe { + FOO += 1; + FOO + } + } + assert_eq!( + format!("{} {} {a} {b} {} {c}", foo(), foo(), foo(), a = foo(), b = foo(), c = foo()), + "1 2 4 5 3 6".to_string() + ); +} + +#[test] +fn test_once() { + // Make sure each argument are evaluated only once even though it may be + // formatted multiple times + fn foo() -> isize { + static mut FOO: isize = 0; + unsafe { + FOO += 1; + FOO + } + } + assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a = foo()), "1 1 1 2 2 2".to_string()); +} + +#[test] +fn test_refcell() { + let refcell = RefCell::new(5); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); + let borrow = refcell.borrow_mut(); + assert_eq!(format!("{:?}", refcell), "RefCell { value: }"); + drop(borrow); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); +} +use std::collections::binary_heap::{Drain, PeekMut}; +use std::collections::BinaryHeap; +use std::iter::TrustedLen; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::sync::atomic::{AtomicU32, Ordering}; + +#[test] +fn test_iterator() { + let data = vec![5, 9, 3]; + let iterout = [9, 5, 3]; + let heap = BinaryHeap::from(data); + let mut i = 0; + for el in &heap { + assert_eq!(*el, iterout[i]); + i += 1; + } +} + +#[test] +fn test_iter_rev_cloned_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.iter().rev().cloned().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![9, 5, 3]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.into_iter().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_size_hint() { + let data = vec![5, 9]; + let pq = BinaryHeap::from(data); + + let mut it = pq.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next(), Some(9)); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(5)); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_into_iter_rev_collect() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from(data); + + let v: Vec<_> = pq.into_iter().rev().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_into_iter_sorted_collect() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + let it = heap.into_iter_sorted(); + let sorted = it.collect::>(); + assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); +} + +#[test] +fn test_drain_sorted_collect() { + let mut heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + let it = heap.drain_sorted(); + let sorted = it.collect::>(); + assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); +} + +fn check_exact_size_iterator(len: usize, it: I) { + let mut it = it; + + for i in 0..it.len() { + let (lower, upper) = it.size_hint(); + assert_eq!(Some(lower), upper); + assert_eq!(lower, len - i); + assert_eq!(it.len(), len - i); + it.next(); + } + assert_eq!(it.len(), 0); + assert!(it.is_empty()); +} + +#[test] +fn test_exact_size_iterator() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_exact_size_iterator(heap.len(), heap.iter()); + check_exact_size_iterator(heap.len(), heap.clone().into_iter()); + check_exact_size_iterator(heap.len(), heap.clone().into_iter_sorted()); + check_exact_size_iterator(heap.len(), heap.clone().drain()); + check_exact_size_iterator(heap.len(), heap.clone().drain_sorted()); +} + +fn check_trusted_len(len: usize, it: I) { + let mut it = it; + for i in 0..len { + let (lower, upper) = it.size_hint(); + if upper.is_some() { + assert_eq!(Some(lower), upper); + assert_eq!(lower, len - i); + } + it.next(); + } +} + +#[test] +fn test_trusted_len() { + let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_trusted_len(heap.len(), heap.clone().into_iter_sorted()); + check_trusted_len(heap.len(), heap.clone().drain_sorted()); +} + +#[test] +fn test_peek_and_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from(data); + while !heap.is_empty() { + assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } +} + +#[test] +fn test_peek_mut() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + } + assert_eq!(heap.peek(), Some(&9)); +} + +#[test] +fn test_peek_mut_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + assert_eq!(PeekMut::pop(top), 8); + } + assert_eq!(heap.peek(), Some(&9)); +} + +#[test] +fn test_push() { + let mut heap = BinaryHeap::from(vec![2, 4, 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == 9); + heap.push(11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == 11); + heap.push(5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == 11); + heap.push(27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == 27); + heap.push(3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == 27); + heap.push(103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == 103); +} + +#[test] +fn test_push_unique() { + let mut heap = BinaryHeap::>::from(vec![box 2, box 4, box 9]); + assert_eq!(heap.len(), 3); + assert!(**heap.peek().unwrap() == 9); + heap.push(box 11); + assert_eq!(heap.len(), 4); + assert!(**heap.peek().unwrap() == 11); + heap.push(box 5); + assert_eq!(heap.len(), 5); + assert!(**heap.peek().unwrap() == 11); + heap.push(box 27); + assert_eq!(heap.len(), 6); + assert!(**heap.peek().unwrap() == 27); + heap.push(box 3); + assert_eq!(heap.len(), 7); + assert!(**heap.peek().unwrap() == 27); + heap.push(box 103); + assert_eq!(heap.len(), 8); + assert!(**heap.peek().unwrap() == 103); +} + +fn check_to_vec(mut data: Vec) { + let heap = BinaryHeap::from(data.clone()); + let mut v = heap.clone().into_vec(); + v.sort(); + data.sort(); + + assert_eq!(v, data); + assert_eq!(heap.into_sorted_vec(), data); +} + +#[test] +fn test_to_vec() { + check_to_vec(vec![]); + check_to_vec(vec![5]); + check_to_vec(vec![3, 2]); + check_to_vec(vec![2, 3]); + check_to_vec(vec![5, 1, 2]); + check_to_vec(vec![1, 100, 2, 3]); + check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); + check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); + check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); +} + +#[test] +fn test_in_place_iterator_specialization() { + let src: Vec = vec![1, 2, 3]; + let src_ptr = src.as_ptr(); + let heap: BinaryHeap<_> = src.into_iter().map(std::convert::identity).collect(); + let heap_ptr = heap.iter().next().unwrap() as *const usize; + assert_eq!(src_ptr, heap_ptr); + let sink: Vec<_> = heap.into_iter().map(std::convert::identity).collect(); + let sink_ptr = sink.as_ptr(); + assert_eq!(heap_ptr, sink_ptr); +} + +#[test] +fn test_empty_pop() { + let mut heap = BinaryHeap::::new(); + assert!(heap.pop().is_none()); +} + +#[test] +fn test_empty_peek() { + let empty = BinaryHeap::::new(); + assert!(empty.peek().is_none()); +} + +#[test] +fn test_empty_peek_mut() { + let mut empty = BinaryHeap::::new(); + assert!(empty.peek_mut().is_none()); +} + +#[test] +fn test_from_iter() { + let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); + + for &x in &xs { + assert_eq!(q.pop().unwrap(), x); + } +} + +#[test] +fn test_drain() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain().take(5).count(), 5); + + assert!(q.is_empty()); +} + +#[test] +fn test_drain_sorted() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain_sorted().take(5).collect::>(), vec![9, 8, 7, 6, 5]); + + assert!(q.is_empty()); +} + +#[test] +fn test_drain_sorted_leak() { + static DROPS: AtomicU32 = AtomicU32::new(0); + + #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::SeqCst); + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut q = BinaryHeap::from(vec![ + D(0, false), + D(1, false), + D(2, false), + D(3, true), + D(4, false), + D(5, false), + ]); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok(); + + assert_eq!(DROPS.load(Ordering::SeqCst), 6); +} + +#[test] +fn test_extend_ref() { + let mut a = BinaryHeap::new(); + a.push(1); + a.push(2); + + a.extend(&[3, 4, 5]); + + assert_eq!(a.len(), 5); + assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); + + let mut a = BinaryHeap::new(); + a.push(1); + a.push(2); + let mut b = BinaryHeap::new(); + b.push(3); + b.push(4); + b.push(5); + + a.extend(&b); + + assert_eq!(a.len(), 5); + assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); +} + +#[test] +fn test_append() { + let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); + let mut b = BinaryHeap::from(vec![-20, 5, 43]); + + a.append(&mut b); + + assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); + assert!(b.is_empty()); +} + +#[test] +fn test_append_to_empty() { + let mut a = BinaryHeap::new(); + let mut b = BinaryHeap::from(vec![-20, 5, 43]); + + a.append(&mut b); + + assert_eq!(a.into_sorted_vec(), [-20, 5, 43]); + assert!(b.is_empty()); +} + +#[test] +fn test_extend_specialization() { + let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); + let b = BinaryHeap::from(vec![-20, 5, 43]); + + a.extend(b); + + assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); +} + +#[allow(dead_code)] +fn assert_covariance() { + fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { + d + } +} + +#[test] +fn test_retain() { + let mut a = BinaryHeap::from(vec![100, 10, 50, 1, 2, 20, 30]); + a.retain(|&x| x != 2); + + // Check that 20 moved into 10's place. + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|_| true); + + assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); + + a.retain(|&x| x < 50); + + assert_eq!(a.clone().into_vec(), [30, 20, 10, 1]); + + a.retain(|_| false); + + assert!(a.is_empty()); +} + +// old binaryheap failed this test +// +// Integrity means that all elements are present after a comparison panics, +// even if the order may not be correct. +// +// Destructors must be called exactly once per element. +// FIXME: re-enable emscripten once it can unwind again +#[test] +#[cfg(not(target_os = "emscripten"))] +fn panic_safe() { + use rand::{seq::SliceRandom, thread_rng}; + use std::cmp; + use std::panic::{self, AssertUnwindSafe}; + use std::sync::atomic::{AtomicUsize, Ordering}; + + static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); + + #[derive(Eq, PartialEq, Ord, Clone, Debug)] + struct PanicOrd(T, bool); + + impl Drop for PanicOrd { + fn drop(&mut self) { + // update global drop count + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } + } + + impl PartialOrd for PanicOrd { + fn partial_cmp(&self, other: &Self) -> Option { + if self.1 || other.1 { + panic!("Panicking comparison"); + } + self.0.partial_cmp(&other.0) + } + } + let mut rng = thread_rng(); + const DATASZ: usize = 32; + // Miri is too slow + let ntest = if cfg!(miri) { 1 } else { 10 }; + + // don't use 0 in the data -- we want to catch the zeroed-out case. + let data = (1..=DATASZ).collect::>(); + + // since it's a fuzzy test, run several tries. + for _ in 0..ntest { + for i in 1..=DATASZ { + DROP_COUNTER.store(0, Ordering::SeqCst); + + let mut panic_ords: Vec<_> = + data.iter().filter(|&&x| x != i).map(|&x| PanicOrd(x, false)).collect(); + let panic_item = PanicOrd(i, true); + + // heapify the sane items + panic_ords.shuffle(&mut rng); + let mut heap = BinaryHeap::from(panic_ords); + let inner_data; + + { + // push the panicking item to the heap and catch the panic + let thread_result = { + let mut heap_ref = AssertUnwindSafe(&mut heap); + panic::catch_unwind(move || { + heap_ref.push(panic_item); + }) + }; + assert!(thread_result.is_err()); + + // Assert no elements were dropped + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert!(drops == 0, "Must not drop items. drops={}", drops); + inner_data = heap.clone().into_vec(); + drop(heap); + } + let drops = DROP_COUNTER.load(Ordering::SeqCst); + assert_eq!(drops, DATASZ); + + let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::>(); + data_sorted.sort(); + assert_eq!(data_sorted, data); + } + } +} +use std::cell::Cell; +use std::mem::MaybeUninit; +use std::ptr::NonNull; + +#[test] +fn unitialized_zero_size_box() { + assert_eq!( + &*Box::<()>::new_uninit() as *const _, + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[()]>::new_uninit_slice(4).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[String]>::new_uninit_slice(0).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); +} + +#[derive(Clone, PartialEq, Eq, Debug)] +struct Dummy { + _data: u8, +} + +#[test] +fn box_clone_and_clone_from_equivalence() { + for size in (0..8).map(|i| 2usize.pow(i)) { + let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); + let clone = control.clone(); + let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); + copy.clone_from(&control); + assert_eq!(control, clone); + assert_eq!(control, copy); + } +} + +/// This test might give a false positive in case the box realocates, but the alocator keeps the +/// original pointer. +/// +/// On the other hand it won't give a false negative, if it fails than the memory was definitely not +/// reused +#[test] +fn box_clone_from_ptr_stability() { + for size in (0..8).map(|i| 2usize.pow(i)) { + let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); + let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); + let copy_raw = copy.as_ptr() as usize; + copy.clone_from(&control); + assert_eq!(copy.as_ptr() as usize, copy_raw); + } +} + +#[test] +fn box_deref_lval() { + let x = Box::new(Cell::new(5)); + x.set(1000); + assert_eq!(x.get(), 1000); +} +use std::alloc::{Allocator, Global, Layout, System}; + +/// Issue #45955 and #62251. +#[test] +fn alloc_system_overaligned_request() { + check_overalign_requests(System) +} + +#[test] +fn std_heap_overaligned_request() { + check_overalign_requests(Global) +} + +fn check_overalign_requests(allocator: T) { + for &align in &[4, 8, 16, 32] { + // less than and bigger than `MIN_ALIGN` + for &size in &[align / 2, align - 1] { + // size less than alignment + let iterations = 128; + unsafe { + let pointers: Vec<_> = (0..iterations) + .map(|_| { + allocator.allocate(Layout::from_size_align(size, align).unwrap()).unwrap() + }) + .collect(); + for &ptr in &pointers { + assert_eq!( + (ptr.as_non_null_ptr().as_ptr() as usize) % align, + 0, + "Got a pointer less aligned than requested" + ) + } + + // Clean up + for &ptr in &pointers { + allocator.deallocate( + ptr.as_non_null_ptr(), + Layout::from_size_align(size, align).unwrap(), + ) + } + } + } + } +} +/// Creates a [`Vec`] containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a [`Vec`] containing a given list of elements: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// ``` +/// +/// - Create a [`Vec`] from a given element and size: +/// +/// ``` +/// let v = vec![1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement [`Clone`] and the number of elements doesn't have to be +/// a constant. +/// +/// This will use `clone` to duplicate an expression, so one should be careful +/// using this with types having a nonstandard `Clone` implementation. For +/// example, `vec![Rc::new(1); 5]` will create a vector of five references +/// to the same boxed integer value, not five references pointing to independently +/// boxed integers. +/// +/// Also, note that `vec![expr; 0]` is allowed, and produces an empty vector. +/// This will still evaluate `expr`, however, and immediately drop the resulting value, so +/// be mindful of side effects. +/// +/// [`Vec`]: crate::vec::Vec +#[cfg(not(test))] +#[doc(alias = "alloc")] +#[doc(alias = "malloc")] +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable(box_syntax, liballoc_internals)] +macro_rules! vec { + () => ( + $crate::__rust_force_expr!($crate::vec::Vec::new()) + ); + ($elem:expr; $n:expr) => ( + $crate::__rust_force_expr!($crate::vec::from_elem($elem, $n)) + ); + ($($x:expr),+ $(,)?) => ( + $crate::__rust_force_expr!(<[_]>::into_vec(box [$($x),+])) + ); +} + +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is +// required for this macro definition, is not available. Instead use the +// `slice::into_vec` function which is only available with cfg(test) +// NB see the slice::hack module in slice.rs for more information +#[cfg(test)] +macro_rules! vec { + () => ( + $crate::vec::Vec::new() + ); + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec(box [$($x),*]) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +/// Creates a `String` using interpolation of runtime expressions. +/// +/// The first argument `format!` receives is a format string. This must be a string +/// literal. The power of the formatting string is in the `{}`s contained. +/// +/// Additional parameters passed to `format!` replace the `{}`s within the +/// formatting string in the order given unless named or positional parameters +/// are used; see [`std::fmt`] for more information. +/// +/// A common use for `format!` is concatenation and interpolation of strings. +/// The same convention is used with [`print!`] and [`write!`] macros, +/// depending on the intended destination of the string. +/// +/// To convert a single value to a string, use the [`to_string`] method. This +/// will use the [`Display`] formatting trait. +/// +/// [`std::fmt`]: ../std/fmt/index.html +/// [`print!`]: ../std/macro.print.html +/// [`write!`]: core::write +/// [`to_string`]: crate::string::ToString +/// [`Display`]: core::fmt::Display +/// +/// # Panics +/// +/// `format!` panics if a formatting trait implementation returns an error. +/// This indicates an incorrect implementation +/// since `fmt::Write for String` never returns an error itself. +/// +/// # Examples +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10, y = 30); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")] +macro_rules! format { + ($($arg:tt)*) => {{ + let res = $crate::fmt::format($crate::__export::format_args!($($arg)*)); + res + }} +} + +/// Force AST node to an expression to improve diagnostics in pattern position. +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] +macro_rules! __rust_force_expr { + ($e:expr) => { + $e + }; +} +//! Memory allocation APIs + +#![stable(feature = "alloc_module", since = "1.28.0")] + +#[cfg(not(test))] +use core::intrinsics; +use core::intrinsics::{min_align_of_val, size_of_val}; + +use core::ptr::Unique; +#[cfg(not(test))] +use core::ptr::{self, NonNull}; + +#[stable(feature = "alloc_module", since = "1.28.0")] +#[doc(inline)] +pub use core::alloc::*; + +#[cfg(test)] +mod tests; + +extern "Rust" { + // These are the magic symbols to call the global allocator. rustc generates + // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute + // (the code expanding that attribute macro generates those functions), or to call + // the default implementations in libstd (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) + // otherwise. + // The rustc fork of LLVM also special-cases these function names to be able to optimize them + // like `malloc`, `realloc`, and `free`, respectively. + #[rustc_allocator] + #[rustc_allocator_nounwind] + fn __rust_alloc(size: usize, align: usize) -> *mut u8; + #[rustc_allocator_nounwind] + fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); + #[rustc_allocator_nounwind] + fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; + #[rustc_allocator_nounwind] + fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; +} + +/// The global memory allocator. +/// +/// This type implements the [`Allocator`] trait by forwarding calls +/// to the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// Note: while this type is unstable, the functionality it provides can be +/// accessed through the [free functions in `alloc`](self#functions). +#[unstable(feature = "allocator_api", issue = "32838")] +#[derive(Copy, Clone, Default, Debug)] +#[cfg(not(test))] +pub struct Global; + +#[cfg(test)] +pub use std::alloc::Global; + +/// Allocate memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::alloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `alloc` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::alloc`]. +/// +/// # Examples +/// +/// ``` +/// use std::alloc::{alloc, dealloc, Layout}; +/// +/// unsafe { +/// let layout = Layout::new::(); +/// let ptr = alloc(layout); +/// +/// *(ptr as *mut u16) = 42; +/// assert_eq!(*(ptr as *mut u16), 42); +/// +/// dealloc(ptr, layout); +/// } +/// ``` +#[stable(feature = "global_alloc", since = "1.28.0")] +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + unsafe { __rust_alloc(layout.size(), layout.align()) } +} + +/// Deallocate memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::dealloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `dealloc` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::dealloc`]. +#[stable(feature = "global_alloc", since = "1.28.0")] +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } +} + +/// Reallocate memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::realloc`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `realloc` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::realloc`]. +#[stable(feature = "global_alloc", since = "1.28.0")] +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } +} + +/// Allocate zero-initialized memory with the global allocator. +/// +/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method +/// of the allocator registered with the `#[global_allocator]` attribute +/// if there is one, or the `std` crate’s default. +/// +/// This function is expected to be deprecated in favor of the `alloc_zeroed` method +/// of the [`Global`] type when it and the [`Allocator`] trait become stable. +/// +/// # Safety +/// +/// See [`GlobalAlloc::alloc_zeroed`]. +/// +/// # Examples +/// +/// ``` +/// use std::alloc::{alloc_zeroed, dealloc, Layout}; +/// +/// unsafe { +/// let layout = Layout::new::(); +/// let ptr = alloc_zeroed(layout); +/// +/// assert_eq!(*(ptr as *mut u16), 0); +/// +/// dealloc(ptr, layout); +/// } +/// ``` +#[stable(feature = "global_alloc", since = "1.28.0")] +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } +} + +#[cfg(not(test))] +impl Global { + #[inline] + fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocError> { + match layout.size() { + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + // SAFETY: `layout` is non-zero in size, + size => unsafe { + let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) }; + let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; + Ok(NonNull::slice_from_raw_parts(ptr, size)) + }, + } + } + + // SAFETY: Same as `Allocator::grow` + #[inline] + unsafe fn grow_impl( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + zeroed: bool, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + match old_layout.size() { + 0 => self.alloc_impl(new_layout, zeroed), + + // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size` + // as required by safety conditions. Other conditions must be upheld by the caller + old_size if old_layout.align() == new_layout.align() => unsafe { + let new_size = new_layout.size(); + + // `realloc` probably checks for `new_size >= old_layout.size()` or something similar. + intrinsics::assume(new_size >= old_layout.size()); + + let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; + if zeroed { + raw_ptr.add(old_size).write_bytes(0, new_size - old_size); + } + Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + }, + + // SAFETY: because `new_layout.size()` must be greater than or equal to `old_size`, + // both the old and new memory allocation are valid for reads and writes for `old_size` + // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap + // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract + // for `dealloc` must be upheld by the caller. + old_size => unsafe { + let new_ptr = self.alloc_impl(new_layout, zeroed)?; + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size); + self.deallocate(ptr, old_layout); + Ok(new_ptr) + }, + } + } +} + +#[unstable(feature = "allocator_api", issue = "32838")] +#[cfg(not(test))] +unsafe impl Allocator for Global { + #[inline] + fn allocate(&self, layout: Layout) -> Result, AllocError> { + self.alloc_impl(layout, false) + } + + #[inline] + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + self.alloc_impl(layout, true) + } + + #[inline] + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + if layout.size() != 0 { + // SAFETY: `layout` is non-zero in size, + // other conditions must be upheld by the caller + unsafe { dealloc(ptr.as_ptr(), layout) } + } + } + + #[inline] + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: all conditions must be upheld by the caller + unsafe { self.grow_impl(ptr, old_layout, new_layout, false) } + } + + #[inline] + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: all conditions must be upheld by the caller + unsafe { self.grow_impl(ptr, old_layout, new_layout, true) } + } + + #[inline] + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() <= old_layout.size(), + "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" + ); + + match new_layout.size() { + // SAFETY: conditions must be upheld by the caller + 0 => unsafe { + self.deallocate(ptr, old_layout); + Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0)) + }, + + // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller + new_size if old_layout.align() == new_layout.align() => unsafe { + // `realloc` probably checks for `new_size <= old_layout.size()` or something similar. + intrinsics::assume(new_size <= old_layout.size()); + + let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size); + let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; + Ok(NonNull::slice_from_raw_parts(ptr, new_size)) + }, + + // SAFETY: because `new_size` must be smaller than or equal to `old_layout.size()`, + // both the old and new memory allocation are valid for reads and writes for `new_size` + // bytes. Also, because the old allocation wasn't yet deallocated, it cannot overlap + // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract + // for `dealloc` must be upheld by the caller. + new_size => unsafe { + let new_ptr = self.allocate(new_layout)?; + ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size); + self.deallocate(ptr, old_layout); + Ok(new_ptr) + }, + } + } +} + +/// The allocator for unique pointers. +// This function must not unwind. If it does, MIR codegen will fail. +#[cfg(not(test))] +#[lang = "exchange_malloc"] +#[inline] +unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + match Global.allocate(layout) { + Ok(ptr) => ptr.as_mut_ptr(), + Err(_) => handle_alloc_error(layout), + } +} + +#[cfg_attr(not(test), lang = "box_free")] +#[inline] +// This signature has to be the same as `Box`, otherwise an ICE will happen. +// When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as +// well. +// For example if `Box` is changed to `struct Box(Unique, A)`, +// this function has to be changed to `fn box_free(Unique, A)` as well. +pub(crate) unsafe fn box_free(ptr: Unique, alloc: A) { + unsafe { + let size = size_of_val(ptr.as_ref()); + let align = min_align_of_val(ptr.as_ref()); + let layout = Layout::from_size_align_unchecked(size, align); + alloc.deallocate(ptr.cast().into(), layout) + } +} + +// # Allocation error handler + +extern "Rust" { + // This is the magic symbol to call the global alloc error handler. rustc generates + // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the + // default implementations below (`__rdl_oom`) otherwise. + #[rustc_allocator_nounwind] + fn __rust_alloc_error_handler(size: usize, align: usize) -> !; +} + +/// Abort on memory allocation error or failure. +/// +/// Callers of memory allocation APIs wishing to abort computation +/// in response to an allocation error are encouraged to call this function, +/// rather than directly invoking `panic!` or similar. +/// +/// The default behavior of this function is to print a message to standard error +/// and abort the process. +/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`]. +/// +/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html +/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html +#[stable(feature = "global_alloc", since = "1.28.0")] +#[cfg(not(test))] +#[rustc_allocator_nounwind] +#[cold] +pub fn handle_alloc_error(layout: Layout) -> ! { + unsafe { + __rust_alloc_error_handler(layout.size(), layout.align()); + } +} + +// For alloc test `std::alloc::handle_alloc_error` can be used directly. +#[cfg(test)] +pub use std::alloc::handle_alloc_error; + +#[cfg(not(any(target_os = "hermit", test)))] +#[doc(hidden)] +#[allow(unused_attributes)] +#[unstable(feature = "alloc_internals", issue = "none")] +pub mod __alloc_error_handler { + use crate::alloc::Layout; + + // called via generated `__rust_alloc_error_handler` + + // if there is no `#[alloc_error_handler]` + #[rustc_std_internal_symbol] + pub unsafe extern "C" fn __rdl_oom(size: usize, _align: usize) -> ! { + panic!("memory allocation of {} bytes failed", size) + } + + // if there is a `#[alloc_error_handler]` + #[rustc_std_internal_symbol] + pub unsafe extern "C" fn __rg_oom(size: usize, align: usize) -> ! { + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + extern "Rust" { + #[lang = "oom"] + fn oom_impl(layout: Layout) -> !; + } + unsafe { oom_impl(layout) } + } +} + +/// Specialize clones into pre-allocated, uninitialized memory. +/// Used by `Box::clone` and `Rc`/`Arc::make_mut`. +pub(crate) trait WriteCloneIntoRaw: Sized { + unsafe fn write_clone_into_raw(&self, target: *mut Self); +} + +impl WriteCloneIntoRaw for T { + #[inline] + default unsafe fn write_clone_into_raw(&self, target: *mut Self) { + // Having allocated *first* may allow the optimizer to create + // the cloned value in-place, skipping the local and move. + unsafe { target.write(self.clone()) }; + } +} + +impl WriteCloneIntoRaw for T { + #[inline] + unsafe fn write_clone_into_raw(&self, target: *mut Self) { + // We can always copy in-place, without ever involving a local value. + unsafe { target.copy_from_nonoverlapping(self, 1) }; + } +} +#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")] +#![doc(hidden)] + +use core::alloc::LayoutError; +use core::cmp; +use core::intrinsics; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::ops::Drop; +use core::ptr::{self, NonNull, Unique}; +use core::slice; + +use crate::alloc::{handle_alloc_error, Allocator, Global, Layout}; +use crate::boxed::Box; +use crate::collections::TryReserveError::{self, *}; + +#[cfg(test)] +mod tests; + +enum AllocInit { + /// The contents of the new memory are uninitialized. + Uninitialized, + /// The new memory is guaranteed to be zeroed. + Zeroed, +} + +/// A low-level utility for more ergonomically allocating, reallocating, and deallocating +/// a buffer of memory on the heap without having to worry about all the corner cases +/// involved. This type is excellent for building your own data structures like Vec and VecDeque. +/// In particular: +/// +/// * Produces `Unique::dangling()` on zero-sized types. +/// * Produces `Unique::dangling()` on zero-length allocations. +/// * Avoids freeing `Unique::dangling()`. +/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics). +/// * Guards against 32-bit systems allocating more than isize::MAX bytes. +/// * Guards against overflowing your length. +/// * Calls `handle_alloc_error` for fallible allocations. +/// * Contains a `ptr::Unique` and thus endows the user with all related benefits. +/// * Uses the excess returned from the allocator to use the largest available capacity. +/// +/// This type does not in anyway inspect the memory that it manages. When dropped it *will* +/// free its memory, but it *won't* try to drop its contents. It is up to the user of `RawVec` +/// to handle the actual things *stored* inside of a `RawVec`. +/// +/// Note that the excess of a zero-sized types is always infinite, so `capacity()` always returns +/// `usize::MAX`. This means that you need to be careful when round-tripping this type with a +/// `Box<[T]>`, since `capacity()` won't yield the length. +#[allow(missing_debug_implementations)] +pub struct RawVec { + ptr: Unique, + cap: usize, + alloc: A, +} + +impl RawVec { + /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so + /// they cannot call `Self::new()`. + /// + /// If you change `RawVec::new` or dependencies, please take care to not introduce anything + /// that would truly const-call something unstable. + pub const NEW: Self = Self::new(); + + /// Creates the biggest possible `RawVec` (on the system heap) + /// without allocating. If `T` has positive size, then this makes a + /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a + /// `RawVec` with capacity `usize::MAX`. Useful for implementing + /// delayed allocation. + pub const fn new() -> Self { + Self::new_in(Global) + } + + /// Creates a `RawVec` (on the system heap) with exactly the + /// capacity and alignment requirements for a `[T; capacity]`. This is + /// equivalent to calling `RawVec::new` when `capacity` is `0` or `T` is + /// zero-sized. Note that if `T` is zero-sized this means you will + /// *not* get a `RawVec` with the requested capacity. + /// + /// # Panics + /// + /// Panics if the requested capacity exceeds `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } + + /// Like `with_capacity`, but guarantees the buffer is zeroed. + #[inline] + pub fn with_capacity_zeroed(capacity: usize) -> Self { + Self::with_capacity_zeroed_in(capacity, Global) + } + + /// Reconstitutes a `RawVec` from a pointer and capacity. + /// + /// # Safety + /// + /// The `ptr` must be allocated (on the system heap), and with the given `capacity`. + /// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit + /// systems). ZST vectors may have a capacity up to `usize::MAX`. + /// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed. + #[inline] + pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { + unsafe { Self::from_raw_parts_in(ptr, capacity, Global) } + } +} + +impl RawVec { + // Tiny Vecs are dumb. Skip to: + // - 8 if the element size is 1, because any heap allocators is likely + // to round up a request of less than 8 bytes to at least 8 bytes. + // - 4 if elements are moderate-sized (<= 1 KiB). + // - 1 otherwise, to avoid wasting too much space for very short Vecs. + const MIN_NON_ZERO_CAP: usize = if mem::size_of::() == 1 { + 8 + } else if mem::size_of::() <= 1024 { + 4 + } else { + 1 + }; + + /// Like `new`, but parameterized over the choice of allocator for + /// the returned `RawVec`. + #[rustc_allow_const_fn_unstable(const_fn)] + pub const fn new_in(alloc: A) -> Self { + // `cap: 0` means "unallocated". zero-sized types are ignored. + Self { ptr: Unique::dangling(), cap: 0, alloc } + } + + /// Like `with_capacity`, but parameterized over the choice of + /// allocator for the returned `RawVec`. + #[inline] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self::allocate_in(capacity, AllocInit::Uninitialized, alloc) + } + + /// Like `with_capacity_zeroed`, but parameterized over the choice + /// of allocator for the returned `RawVec`. + #[inline] + pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { + Self::allocate_in(capacity, AllocInit::Zeroed, alloc) + } + + /// Converts a `Box<[T]>` into a `RawVec`. + pub fn from_box(slice: Box<[T], A>) -> Self { + unsafe { + let (slice, alloc) = Box::into_raw_with_allocator(slice); + RawVec::from_raw_parts_in(slice.as_mut_ptr(), slice.len(), alloc) + } + } + + /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. + /// + /// Note that this will correctly reconstitute any `cap` changes + /// that may have been performed. (See description of type for details.) + /// + /// # Safety + /// + /// * `len` must be greater than or equal to the most recently requested capacity, and + /// * `len` must be less than or equal to `self.capacity()`. + /// + /// Note, that the requested capacity and `self.capacity()` could differ, as + /// an allocator could overallocate and return a greater memory block than requested. + pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit], A> { + // Sanity-check one half of the safety requirement (we cannot check the other half). + debug_assert!( + len <= self.capacity(), + "`len` must be smaller than or equal to `self.capacity()`" + ); + + let me = ManuallyDrop::new(self); + unsafe { + let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); + Box::from_raw_in(slice, ptr::read(&me.alloc)) + } + } + + fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { + if mem::size_of::() == 0 { + Self::new_in(alloc) + } else { + // We avoid `unwrap_or_else` here because it bloats the amount of + // LLVM IR generated. + let layout = match Layout::array::(capacity) { + Ok(layout) => layout, + Err(_) => capacity_overflow(), + }; + match alloc_guard(layout.size()) { + Ok(_) => {} + Err(_) => capacity_overflow(), + } + let result = match init { + AllocInit::Uninitialized => alloc.allocate(layout), + AllocInit::Zeroed => alloc.allocate_zeroed(layout), + }; + let ptr = match result { + Ok(ptr) => ptr, + Err(_) => handle_alloc_error(layout), + }; + + Self { + ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, + cap: Self::capacity_from_bytes(ptr.len()), + alloc, + } + } + } + + /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator. + /// + /// # Safety + /// + /// The `ptr` must be allocated (via the given allocator `alloc`), and with the given + /// `capacity`. + /// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit + /// systems). ZST vectors may have a capacity up to `usize::MAX`. + /// If the `ptr` and `capacity` come from a `RawVec` created via `alloc`, then this is + /// guaranteed. + #[inline] + pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { + Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap: capacity, alloc } + } + + /// Gets a raw pointer to the start of the allocation. Note that this is + /// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must + /// be careful. + #[inline] + pub fn ptr(&self) -> *mut T { + self.ptr.as_ptr() + } + + /// Gets the capacity of the allocation. + /// + /// This will always be `usize::MAX` if `T` is zero-sized. + #[inline(always)] + pub fn capacity(&self) -> usize { + if mem::size_of::() == 0 { usize::MAX } else { self.cap } + } + + /// Returns a shared reference to the allocator backing this `RawVec`. + pub fn allocator(&self) -> &A { + &self.alloc + } + + fn current_memory(&self) -> Option<(NonNull, Layout)> { + if mem::size_of::() == 0 || self.cap == 0 { + None + } else { + // We have an allocated chunk of memory, so we can bypass runtime + // checks to get our current layout. + unsafe { + let align = mem::align_of::(); + let size = mem::size_of::() * self.cap; + let layout = Layout::from_size_align_unchecked(size, align); + Some((self.ptr.cast().into(), layout)) + } + } + } + + /// Ensures that the buffer contains at least enough space to hold `len + + /// additional` elements. If it doesn't already have enough capacity, will + /// reallocate enough space plus comfortable slack space to get amortized + /// *O*(1) behavior. Will limit this behavior if it would needlessly cause + /// itself to panic. + /// + /// If `len` exceeds `self.capacity()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe + /// code *you* write that relies on the behavior of this function may break. + /// + /// This is ideal for implementing a bulk-push operation like `extend`. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM. + /// + /// # Examples + /// + /// ``` + /// # #![feature(raw_vec_internals)] + /// # extern crate alloc; + /// # use std::ptr; + /// # use alloc::raw_vec::RawVec; + /// struct MyVec { + /// buf: RawVec, + /// len: usize, + /// } + /// + /// impl MyVec { + /// pub fn push_all(&mut self, elems: &[T]) { + /// self.buf.reserve(self.len, elems.len()); + /// // reserve would have aborted or panicked if the len exceeded + /// // `isize::MAX` so this is safe to do unchecked now. + /// for x in elems { + /// unsafe { + /// ptr::write(self.buf.ptr().add(self.len), x.clone()); + /// } + /// self.len += 1; + /// } + /// } + /// } + /// # fn main() { + /// # let mut vector = MyVec { buf: RawVec::new(), len: 0 }; + /// # vector.push_all(&[1, 3, 5, 7, 9]); + /// # } + /// ``` + #[inline] + pub fn reserve(&mut self, len: usize, additional: usize) { + // Callers expect this function to be very cheap when there is already sufficient capacity. + // Therefore, we move all the resizing and error-handling logic from grow_amortized and + // handle_reserve behind a call, while making sure that the this function is likely to be + // inlined as just a comparison and a call if the comparison fails. + #[cold] + fn do_reserve_and_handle( + slf: &mut RawVec, + len: usize, + additional: usize, + ) { + handle_reserve(slf.grow_amortized(len, additional)); + } + + if self.needs_to_grow(len, additional) { + do_reserve_and_handle(self, len, additional); + } + } + + /// The same as `reserve`, but returns on errors instead of panicking or aborting. + pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional) { + self.grow_amortized(len, additional) + } else { + Ok(()) + } + } + + /// Ensures that the buffer contains at least enough space to hold `len + + /// additional` elements. If it doesn't already, will reallocate the + /// minimum possible amount of memory necessary. Generally this will be + /// exactly the amount of memory necessary, but in principle the allocator + /// is free to give back more than we asked for. + /// + /// If `len` exceeds `self.capacity()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe code + /// *you* write that relies on the behavior of this function may break. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Aborts + /// + /// Aborts on OOM. + pub fn reserve_exact(&mut self, len: usize, additional: usize) { + handle_reserve(self.try_reserve_exact(len, additional)); + } + + /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. + pub fn try_reserve_exact( + &mut self, + len: usize, + additional: usize, + ) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } + } + + /// Shrinks the allocation down to the specified amount. If the given amount + /// is 0, actually completely deallocates. + /// + /// # Panics + /// + /// Panics if the given amount is *larger* than the current capacity. + /// + /// # Aborts + /// + /// Aborts on OOM. + pub fn shrink_to_fit(&mut self, amount: usize) { + handle_reserve(self.shrink(amount)); + } +} + +impl RawVec { + /// Returns if the buffer needs to grow to fulfill the needed extra capacity. + /// Mainly used to make inlining reserve-calls possible without inlining `grow`. + fn needs_to_grow(&self, len: usize, additional: usize) -> bool { + additional > self.capacity().wrapping_sub(len) + } + + fn capacity_from_bytes(excess: usize) -> usize { + debug_assert_ne!(mem::size_of::(), 0); + excess / mem::size_of::() + } + + fn set_ptr(&mut self, ptr: NonNull<[u8]>) { + self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; + self.cap = Self::capacity_from_bytes(ptr.len()); + } + + // This method is usually instantiated many times. So we want it to be as + // small as possible, to improve compile times. But we also want as much of + // its contents to be statically computable as possible, to make the + // generated code run faster. Therefore, this method is carefully written + // so that all of the code that depends on `T` is within it, while as much + // of the code that doesn't depend on `T` as possible is in functions that + // are non-generic over `T`. + fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { + // This is ensured by the calling contexts. + debug_assert!(additional > 0); + + if mem::size_of::() == 0 { + // Since we return a capacity of `usize::MAX` when `elem_size` is + // 0, getting to here necessarily means the `RawVec` is overfull. + return Err(CapacityOverflow); + } + + // Nothing we can really do about these checks, sadly. + let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?; + + // This guarantees exponential growth. The doubling cannot overflow + // because `cap <= isize::MAX` and the type of `cap` is `usize`. + let cap = cmp::max(self.cap * 2, required_cap); + let cap = cmp::max(Self::MIN_NON_ZERO_CAP, cap); + + let new_layout = Layout::array::(cap); + + // `finish_grow` is non-generic over `T`. + let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; + self.set_ptr(ptr); + Ok(()) + } + + // The constraints on this method are much the same as those on + // `grow_amortized`, but this method is usually instantiated less often so + // it's less critical. + fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { + if mem::size_of::() == 0 { + // Since we return a capacity of `usize::MAX` when the type size is + // 0, getting to here necessarily means the `RawVec` is overfull. + return Err(CapacityOverflow); + } + + let cap = len.checked_add(additional).ok_or(CapacityOverflow)?; + let new_layout = Layout::array::(cap); + + // `finish_grow` is non-generic over `T`. + let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; + self.set_ptr(ptr); + Ok(()) + } + + fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> { + assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity"); + + let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; + let new_size = amount * mem::size_of::(); + + let ptr = unsafe { + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + self.alloc.shrink(ptr, layout, new_layout).map_err(|_| TryReserveError::AllocError { + layout: new_layout, + non_exhaustive: (), + })? + }; + self.set_ptr(ptr); + Ok(()) + } +} + +// This function is outside `RawVec` to minimize compile times. See the comment +// above `RawVec::grow_amortized` for details. (The `A` parameter isn't +// significant, because the number of different `A` types seen in practice is +// much smaller than the number of `T` types.) +#[inline(never)] +fn finish_grow( + new_layout: Result, + current_memory: Option<(NonNull, Layout)>, + alloc: &mut A, +) -> Result, TryReserveError> +where + A: Allocator, +{ + // Check for the error here to minimize the size of `RawVec::grow_*`. + let new_layout = new_layout.map_err(|_| CapacityOverflow)?; + + alloc_guard(new_layout.size())?; + + let memory = if let Some((ptr, old_layout)) = current_memory { + debug_assert_eq!(old_layout.align(), new_layout.align()); + unsafe { + // The allocator checks for alignment equality + intrinsics::assume(old_layout.align() == new_layout.align()); + alloc.grow(ptr, old_layout, new_layout) + } + } else { + alloc.allocate(new_layout) + }; + + memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }) +} + +unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { + /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. + fn drop(&mut self) { + if let Some((ptr, layout)) = self.current_memory() { + unsafe { self.alloc.deallocate(ptr, layout) } + } + } +} + +// Central function for reserve error handling. +#[inline] +fn handle_reserve(result: Result<(), TryReserveError>) { + match result { + Err(CapacityOverflow) => capacity_overflow(), + Err(AllocError { layout, .. }) => handle_alloc_error(layout), + Ok(()) => { /* yay */ } + } +} + +// We need to guarantee the following: +// * We don't ever allocate `> isize::MAX` byte-size objects. +// * We don't overflow `usize::MAX` and actually allocate too little. +// +// On 64-bit we just need to check for overflow since trying to allocate +// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add +// an extra guard for this in case we're running on a platform which can use +// all 4GB in user-space, e.g., PAE or x32. + +#[inline] +fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { + if usize::BITS < 64 && alloc_size > isize::MAX as usize { + Err(CapacityOverflow) + } else { + Ok(()) + } +} + +// One central function responsible for reporting capacity overflows. This'll +// ensure that the code generation related to these panics is minimal as there's +// only one location which panics rather than a bunch throughout the module. +fn capacity_overflow() -> ! { + panic!("capacity overflow"); +} +//! Unicode string slices. +//! +//! *[See also the `str` primitive type](str).* +//! +//! The `&str` type is one of the two main string types, the other being `String`. +//! Unlike its `String` counterpart, its contents are borrowed. +//! +//! # Basic Usage +//! +//! A basic string declaration of `&str` type: +//! +//! ``` +//! let hello_world = "Hello, World!"; +//! ``` +//! +//! Here we have declared a string literal, also known as a string slice. +//! String literals have a static lifetime, which means the string `hello_world` +//! is guaranteed to be valid for the duration of the entire program. +//! We can explicitly specify `hello_world`'s lifetime as well: +//! +//! ``` +//! let hello_world: &'static str = "Hello, world!"; +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] +// Many of the usings in this module are only used in the test configuration. +// It's cleaner to just turn off the unused_imports warning than to fix them. +#![allow(unused_imports)] + +use core::borrow::{Borrow, BorrowMut}; +use core::iter::FusedIterator; +use core::mem; +use core::ptr; +use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher}; +use core::unicode::conversions; + +use crate::borrow::ToOwned; +use crate::boxed::Box; +use crate::slice::{Concat, Join, SliceIndex}; +use crate::string::String; +use crate::vec::Vec; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::pattern; +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub use core::str::EncodeUtf16; +#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] +pub use core::str::SplitAsciiWhitespace; +#[stable(feature = "split_inclusive", since = "1.53.0")] +pub use core::str::SplitInclusive; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::SplitWhitespace; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{from_utf8, from_utf8_mut, Bytes, CharIndices, Chars}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError}; +#[stable(feature = "str_escape", since = "1.34.0")] +pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{FromStr, Utf8Error}; +#[allow(deprecated)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Lines, LinesAny}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{MatchIndices, RMatchIndices}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Matches, RMatches}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{RSplit, Split}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{RSplitN, SplitN}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{RSplitTerminator, SplitTerminator}; + +/// Note: `str` in `Concat` is not meaningful here. +/// This type parameter of the trait only exists to enable another impl. +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Concat for [S] { + type Output = String; + + fn concat(slice: &Self) -> String { + Join::join(slice, "") + } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&str> for [S] { + type Output = String; + + fn join(slice: &Self, sep: &str) -> String { + unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) } + } +} + +macro_rules! specialize_for_lengths { + ($separator:expr, $target:expr, $iter:expr; $($num:expr),*) => {{ + let mut target = $target; + let iter = $iter; + let sep_bytes = $separator; + match $separator.len() { + $( + // loops with hardcoded sizes run much faster + // specialize the cases with small separator lengths + $num => { + for s in iter { + copy_slice_and_advance!(target, sep_bytes); + let content_bytes = s.borrow().as_ref(); + copy_slice_and_advance!(target, content_bytes); + } + }, + )* + _ => { + // arbitrary non-zero size fallback + for s in iter { + copy_slice_and_advance!(target, sep_bytes); + let content_bytes = s.borrow().as_ref(); + copy_slice_and_advance!(target, content_bytes); + } + } + } + target + }} +} + +macro_rules! copy_slice_and_advance { + ($target:expr, $bytes:expr) => { + let len = $bytes.len(); + let (head, tail) = { $target }.split_at_mut(len); + head.copy_from_slice($bytes); + $target = tail; + }; +} + +// Optimized join implementation that works for both Vec (T: Copy) and String's inner vec +// Currently (2018-05-13) there is a bug with type inference and specialization (see issue #36262) +// For this reason SliceConcat is not specialized for T: Copy and SliceConcat is the +// only user of this function. It is left in place for the time when that is fixed. +// +// the bounds for String-join are S: Borrow and for Vec-join Borrow<[T]> +// [T] and str both impl AsRef<[T]> for some T +// => s.borrow().as_ref() and we always have slices +fn join_generic_copy(slice: &[S], sep: &[T]) -> Vec +where + T: Copy, + B: AsRef<[T]> + ?Sized, + S: Borrow, +{ + let sep_len = sep.len(); + let mut iter = slice.iter(); + + // the first slice is the only one without a separator preceding it + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + + // compute the exact total length of the joined Vec + // if the `len` calculation overflows, we'll panic + // we would have run out of memory anyway and the rest of the function requires + // the entire Vec pre-allocated for safety + let reserved_len = sep_len + .checked_mul(iter.len()) + .and_then(|n| { + slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add) + }) + .expect("attempt to join into collection with len > usize::MAX"); + + // prepare an uninitialized buffer + let mut result = Vec::with_capacity(reserved_len); + debug_assert!(result.capacity() >= reserved_len); + + result.extend_from_slice(first.borrow().as_ref()); + + unsafe { + let pos = result.len(); + let target = result.get_unchecked_mut(pos..reserved_len); + + // copy separator and slices over without bounds checks + // generate loops with hardcoded offsets for small separators + // massive improvements possible (~ x2) + let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4); + + // A weird borrow implementation may return different + // slices for the length calculation and the actual copy. + // Make sure we don't expose uninitialized bytes to the caller. + let result_len = reserved_len - remain.len(); + result.set_len(result_len); + } + result +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for String { + #[inline] + fn borrow(&self) -> &str { + &self[..] + } +} + +#[stable(feature = "string_borrow_mut", since = "1.36.0")] +impl BorrowMut for String { + #[inline] + fn borrow_mut(&mut self) -> &mut str { + &mut self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for str { + type Owned = String; + #[inline] + fn to_owned(&self) -> String { + unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } + } + + fn clone_into(&self, target: &mut String) { + let mut b = mem::take(target).into_bytes(); + self.as_bytes().clone_into(&mut b); + *target = unsafe { String::from_utf8_unchecked(b) } + } +} + +/// Methods for string slices. +#[lang = "str_alloc"] +#[cfg(not(test))] +impl str { + /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "this is a string"; + /// let boxed_str = s.to_owned().into_boxed_str(); + /// let boxed_bytes = boxed_str.into_boxed_bytes(); + /// assert_eq!(*boxed_bytes, *s.as_bytes()); + /// ``` + #[stable(feature = "str_box_extras", since = "1.20.0")] + #[inline] + pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { + self.into() + } + + /// Replaces all matches of a pattern with another string. + /// + /// `replace` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "this is old"; + /// + /// assert_eq!("this is new", s.replace("old", "new")); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replace("cookie monster", "little lamb")); + /// ``` + #[must_use = "this returns the replaced string as a new allocation, \ + without modifying the original"] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { + let mut result = String::new(); + let mut last_end = 0; + for (start, part) in self.match_indices(from) { + result.push_str(unsafe { self.get_unchecked(last_end..start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); + result + } + + /// Replaces first N matches of a pattern with another string. + /// + /// `replacen` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice at most `count` times. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "foo foo 123 foo"; + /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2)); + /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3)); + /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); + /// ``` + #[must_use = "this returns the replaced string as a new allocation, \ + without modifying the original"] + #[stable(feature = "str_replacen", since = "1.16.0")] + pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String { + // Hope to reduce the times of re-allocation + let mut result = String::with_capacity(32); + let mut last_end = 0; + for (start, part) in self.match_indices(pat).take(count) { + result.push_str(unsafe { self.get_unchecked(last_end..start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); + result + } + + /// Returns the lowercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property + /// `Lowercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "HELLO"; + /// + /// assert_eq!("hello", s.to_lowercase()); + /// ``` + /// + /// A tricky example, with sigma: + /// + /// ``` + /// let sigma = "Σ"; + /// + /// assert_eq!("σ", sigma.to_lowercase()); + /// + /// // but at the end of a word, it's ς, not σ: + /// let odysseus = "ὈΔΥΣΣΕΎΣ"; + /// + /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase()); + /// ``` + /// + /// Languages without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_lowercase()); + /// ``` + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_lowercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + for (i, c) in self[..].char_indices() { + if c == 'Σ' { + // Σ maps to σ, except at the end of a word where it maps to ς. + // This is the only conditional (contextual) but language-independent mapping + // in `SpecialCasing.txt`, + // so hard-code it rather than have a generic "condition" mechanism. + // See https://github.com/rust-lang/rust/issues/26035 + map_uppercase_sigma(self, i, &mut s) + } else { + match conversions::to_lower(c) { + [a, '\0', _] => s.push(a), + [a, b, '\0'] => { + s.push(a); + s.push(b); + } + [a, b, c] => { + s.push(a); + s.push(b); + s.push(c); + } + } + } + } + return s; + + fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) { + // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + // for the definition of `Final_Sigma`. + debug_assert!('Σ'.len_utf8() == 2); + let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) + && !case_ignoreable_then_cased(from[i + 2..].chars()); + to.push_str(if is_word_final { "ς" } else { "σ" }); + } + + fn case_ignoreable_then_cased>(iter: I) -> bool { + use core::unicode::{Case_Ignorable, Cased}; + match iter.skip_while(|&c| Case_Ignorable(c)).next() { + Some(c) => Cased(c), + None => false, + } + } + } + + /// Returns the uppercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property + /// `Uppercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "hello"; + /// + /// assert_eq!("HELLO", s.to_uppercase()); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_uppercase()); + /// ``` + /// + /// One character can become multiple: + /// ``` + /// let s = "tschüß"; + /// + /// assert_eq!("TSCHÜSS", s.to_uppercase()); + /// ``` + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_uppercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + for c in self[..].chars() { + match conversions::to_upper(c) { + [a, '\0', _] => s.push(a), + [a, b, '\0'] => { + s.push(a); + s.push(b); + } + [a, b, c] => { + s.push(a); + s.push(b); + s.push(c); + } + } + } + s + } + + /// Converts a [`Box`] into a [`String`] without copying or allocating. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let string = String::from("birthday gift"); + /// let boxed_str = string.clone().into_boxed_str(); + /// + /// assert_eq!(boxed_str.into_string(), string); + /// ``` + #[stable(feature = "box_str", since = "1.4.0")] + #[inline] + pub fn into_string(self: Box) -> String { + let slice = Box::<[u8]>::from(self); + unsafe { String::from_utf8_unchecked(slice.into_vec()) } + } + + /// Creates a new [`String`] by repeating a string `n` times. + /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); + /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// // this will panic at runtime + /// "0123456789abcdef".repeat(usize::MAX); + /// ``` + #[stable(feature = "repeat_str", since = "1.16.0")] + pub fn repeat(&self, n: usize) -> String { + unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } + } + + /// Returns a copy of this string where each character is mapped to its + /// ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// To uppercase ASCII characters in addition to non-ASCII characters, use + /// [`to_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// let s = "Grüße, Jürgen ❤"; + /// + /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); + /// ``` + /// + /// [`make_ascii_uppercase`]: str::make_ascii_uppercase + /// [`to_uppercase`]: #method.to_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_uppercase(&self) -> String { + let mut bytes = self.as_bytes().to_vec(); + bytes.make_ascii_uppercase(); + // make_ascii_uppercase() preserves the UTF-8 invariant. + unsafe { String::from_utf8_unchecked(bytes) } + } + + /// Returns a copy of this string where each character is mapped to its + /// ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// To lowercase ASCII characters in addition to non-ASCII characters, use + /// [`to_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// let s = "Grüße, Jürgen ❤"; + /// + /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); + /// ``` + /// + /// [`make_ascii_lowercase`]: str::make_ascii_lowercase + /// [`to_lowercase`]: #method.to_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_lowercase(&self) -> String { + let mut bytes = self.as_bytes().to_vec(); + bytes.make_ascii_lowercase(); + // make_ascii_lowercase() preserves the UTF-8 invariant. + unsafe { String::from_utf8_unchecked(bytes) } + } +} + +/// Converts a boxed slice of bytes to a boxed string slice without checking +/// that the string contains valid UTF-8. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let smile_utf8 = Box::new([226, 152, 186]); +/// let smile = unsafe { std::str::from_boxed_utf8_unchecked(smile_utf8) }; +/// +/// assert_eq!("☺", &*smile); +/// ``` +#[stable(feature = "str_box_extras", since = "1.20.0")] +#[inline] +pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { + unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } +} +use super::*; + +use std::boxed::Box; +use std::clone::Clone; +use std::convert::{From, TryInto}; +use std::mem::drop; +use std::ops::Drop; +use std::option::Option::{self, None, Some}; +use std::sync::atomic::{ + self, + Ordering::{Acquire, SeqCst}, +}; +use std::sync::mpsc::channel; +use std::sync::Mutex; +use std::thread; + +use crate::vec::Vec; + +struct Canary(*mut atomic::AtomicUsize); + +impl Drop for Canary { + fn drop(&mut self) { + unsafe { + match *self { + Canary(c) => { + (*c).fetch_add(1, SeqCst); + } + } + } + } +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn manually_share_arc() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let arc_v = Arc::new(v); + + let (tx, rx) = channel(); + + let _t = thread::spawn(move || { + let arc_v: Arc> = rx.recv().unwrap(); + assert_eq!((*arc_v)[3], 4); + }); + + tx.send(arc_v.clone()).unwrap(); + + assert_eq!((*arc_v)[2], 3); + assert_eq!((*arc_v)[4], 5); +} + +#[test] +fn test_arc_get_mut() { + let mut x = Arc::new(3); + *Arc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Arc::get_mut(&mut x).is_none()); + drop(y); + assert!(Arc::get_mut(&mut x).is_some()); + let _w = Arc::downgrade(&x); + assert!(Arc::get_mut(&mut x).is_none()); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::::new()), 0); + assert_eq!(Weak::strong_count(&Weak::::new()), 0); + + let a = Arc::new(0); + let w = Arc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 1); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 2); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 2); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 1); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), 1); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), 0); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Arc::new(3); + assert_eq!(Arc::try_unwrap(x), Ok(3)); + let x = Arc::new(4); + let _y = x.clone(); + assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); + let x = Arc::new(5); + let _w = Arc::downgrade(&x); + assert_eq!(Arc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_from_raw() { + let x = Arc::new(box "hello"); + let y = x.clone(); + + let x_ptr = Arc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Arc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Arc = Arc::from("foo"); + + let ptr = Arc::into_raw(arc.clone()); + let arc2 = unsafe { Arc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(arc, arc2); + + let arc: Arc = Arc::new(123); + + let ptr = Arc::into_raw(arc.clone()); + let arc2 = unsafe { Arc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(arc2.to_string(), "123"); +} + +#[test] +fn into_from_weak_raw() { + let x = Arc::new(box "hello"); + let y = Arc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Arc = Arc::from("foo"); + let weak: Weak = Arc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Arc = Arc::new(123); + let weak: Weak = Arc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + +#[test] +fn test_cowarc_clone_make_mut() { + let mut cow0 = Arc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Arc::make_mut(&mut cow0)); + assert!(75 == *Arc::make_mut(&mut cow1)); + assert!(75 == *Arc::make_mut(&mut cow2)); + + *Arc::make_mut(&mut cow0) += 1; + *Arc::make_mut(&mut cow1) += 2; + *Arc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowarc_clone_unique2() { + let mut cow0 = Arc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Arc::make_mut(&mut cow0) += 1; + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowarc_clone_weak() { + let mut cow0 = Arc::new(75); + let cow1_weak = Arc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Arc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +#[test] +fn test_live() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: Mutex>>, + } + + let a = Arc::new(Cycle { x: Mutex::new(None) }); + let b = Arc::downgrade(&a.clone()); + *a.x.lock().unwrap() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn drop_arc() { + let mut canary = atomic::AtomicUsize::new(0); + let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + drop(x); + assert!(canary.load(Acquire) == 1); +} + +#[test] +fn drop_arc_weak() { + let mut canary = atomic::AtomicUsize::new(0); + let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let arc_weak = Arc::downgrade(&arc); + assert!(canary.load(Acquire) == 0); + drop(arc); + assert!(canary.load(Acquire) == 1); + drop(arc_weak); +} + +#[test] +fn test_strong_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + let b = w.upgrade().expect(""); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Arc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 1); + let x = w.clone(); + assert!(Arc::weak_count(&a) == 2); + drop(w); + drop(x); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Arc::strong_count(&a) == 2); + assert!(Arc::weak_count(&a) == 0); + let d = Arc::downgrade(&c); + assert!(Arc::weak_count(&c) == 1); + assert!(Arc::strong_count(&c) == 2); + + drop(a); + drop(c); + drop(d); +} + +#[test] +fn show_arc() { + let a = Arc::new(5); + assert_eq!(format!("{:?}", a), "5"); +} + +// Make sure deriving works with Arc +#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] +struct Foo { + inner: Arc, +} + +#[test] +fn test_unsized() { + let x: Arc<[i32]> = Arc::new([1, 2, 3]); + assert_eq!(format!("{:?}", x), "[1, 2, 3]"); + let y = Arc::downgrade(&x.clone()); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn test_maybe_thin_unsized() { + // If/when custom thin DSTs exist, this test should be updated to use one + use std::ffi::{CStr, CString}; + + let x: Arc = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + assert_eq!(format!("{:?}", x), "\"swordfish\""); + let y: Weak = Arc::downgrade(&x); + drop(x); + + // At this point, the weak points to a dropped DST + assert!(y.upgrade().is_none()); + // But we still need to be able to get the alloc layout to drop. + // CStr has no drop glue, but custom DSTs might, and need to work. + drop(y); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_arc = Arc::from(foo); + assert!(123 == *foo_arc); +} + +#[test] +fn test_new_weak() { + let foo: Weak = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Arc::new(5); + let same_five = five.clone(); + let other_five = Arc::new(5); + + assert!(Arc::ptr_eq(&five, &same_five)); + assert!(!Arc::ptr_eq(&five, &other_five)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_weak_count_locked() { + let mut a = Arc::new(atomic::AtomicBool::new(false)); + let a2 = a.clone(); + let t = thread::spawn(move || { + // Miri is too slow + let count = if cfg!(miri) { 1000 } else { 1000000 }; + for _i in 0..count { + Arc::get_mut(&mut a); + } + a.store(true, SeqCst); + }); + + while !a2.load(SeqCst) { + let n = Arc::weak_count(&a2); + assert!(n < 2, "bad weak count: {}", n); + #[cfg(miri)] // Miri's scheduler does not guarantee liveness, and thus needs this hint. + std::hint::spin_loop(); + } + t.join().unwrap(); +} + +#[test] +fn test_from_str() { + let r: Arc = Arc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Arc<[X]> = Arc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = + &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; + + // Should panic, but not cause memory corruption + let _r: Arc<[Fail]> = Arc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box = box 123; + let r: Arc = Arc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Arc = Arc::from(s); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box = box 123; + let r: Arc = Arc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box = box (); + let r: Arc = Arc::from(b); + + assert_eq!(format!("{:?}", r), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Arc = Arc::new(i32::MAX); + let r2: Arc = Arc::new("abc"); + + assert!(r1.clone().downcast::().is_err()); + + let r1i32 = r1.downcast::(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Arc::new(i32::MAX)); + + assert!(r2.clone().downcast::().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Arc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} + +#[test] +fn test_arc_cyclic_with_zero_refs() { + struct ZeroRefs { + inner: Weak, + } + let zero_refs = Arc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + ZeroRefs { inner: Weak::new() } + }); + + assert_eq!(Arc::strong_count(&zero_refs), 1); + assert_eq!(Arc::weak_count(&zero_refs), 0); + assert_eq!(zero_refs.inner.strong_count(), 0); + assert_eq!(zero_refs.inner.weak_count(), 0); +} + +#[test] +fn test_arc_new_cyclic_one_ref() { + struct OneRef { + inner: Weak, + } + let one_ref = Arc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + OneRef { inner: inner.clone() } + }); + + assert_eq!(Arc::strong_count(&one_ref), 1); + assert_eq!(Arc::weak_count(&one_ref), 1); + + let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); + assert!(Arc::ptr_eq(&one_ref, &one_ref2)); + + assert_eq!(Arc::strong_count(&one_ref), 2); + assert_eq!(Arc::weak_count(&one_ref), 1); +} + +#[test] +fn test_arc_cyclic_two_refs() { + struct TwoRefs { + inner1: Weak, + inner2: Weak, + } + let two_refs = Arc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + + let inner1 = inner.clone(); + let inner2 = inner1.clone(); + + TwoRefs { inner1, inner2 } + }); + + assert_eq!(Arc::strong_count(&two_refs), 1); + assert_eq!(Arc::weak_count(&two_refs), 2); + + let two_refs1 = Weak::upgrade(&two_refs.inner1).unwrap(); + assert!(Arc::ptr_eq(&two_refs, &two_refs1)); + + let two_refs2 = Weak::upgrade(&two_refs.inner2).unwrap(); + assert!(Arc::ptr_eq(&two_refs, &two_refs2)); + + assert_eq!(Arc::strong_count(&two_refs), 3); + assert_eq!(Arc::weak_count(&two_refs), 2); +} +//! A UTF-8–encoded, growable string. +//! +//! This module contains the [`String`] type, the [`ToString`] trait for +//! converting to strings, and several error types that may result from +//! working with [`String`]s. +//! +//! # Examples +//! +//! There are multiple ways to create a new [`String`] from a string literal: +//! +//! ``` +//! let s = "Hello".to_string(); +//! +//! let s = String::from("world"); +//! let s: String = "also this".into(); +//! ``` +//! +//! You can create a new [`String`] from an existing one by concatenating with +//! `+`: +//! +//! ``` +//! let s = "Hello".to_string(); +//! +//! let message = s + " world!"; +//! ``` +//! +//! If you have a vector of valid UTF-8 bytes, you can make a [`String`] out of +//! it. You can do the reverse too. +//! +//! ``` +//! let sparkle_heart = vec![240, 159, 146, 150]; +//! +//! // We know these bytes are valid, so we'll use `unwrap()`. +//! let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); +//! +//! assert_eq!("💖", sparkle_heart); +//! +//! let bytes = sparkle_heart.into_bytes(); +//! +//! assert_eq!(bytes, [240, 159, 146, 150]); +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; +use core::fmt; +use core::hash; +use core::iter::{FromIterator, FusedIterator}; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds}; +use core::ptr; +use core::slice; +use core::str::{lossy, pattern::Pattern}; + +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::str::{self, from_boxed_utf8_unchecked, Chars, FromStr, Utf8Error}; +use crate::vec::Vec; + +/// A UTF-8–encoded, growable string. +/// +/// The `String` type is the most common string type that has ownership over the +/// contents of the string. It has a close relationship with its borrowed +/// counterpart, the primitive [`str`]. +/// +/// # Examples +/// +/// You can create a `String` from [a literal string][`str`] with [`String::from`]: +/// +/// [`String::from`]: From::from +/// +/// ``` +/// let hello = String::from("Hello, world!"); +/// ``` +/// +/// You can append a [`char`] to a `String` with the [`push`] method, and +/// append a [`&str`] with the [`push_str`] method: +/// +/// ``` +/// let mut hello = String::from("Hello, "); +/// +/// hello.push('w'); +/// hello.push_str("orld!"); +/// ``` +/// +/// [`push`]: String::push +/// [`push_str`]: String::push_str +/// +/// If you have a vector of UTF-8 bytes, you can create a `String` from it with +/// the [`from_utf8`] method: +/// +/// ``` +/// // some bytes, in a vector +/// let sparkle_heart = vec![240, 159, 146, 150]; +/// +/// // We know these bytes are valid, so we'll use `unwrap()`. +/// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); +/// +/// assert_eq!("💖", sparkle_heart); +/// ``` +/// +/// [`from_utf8`]: String::from_utf8 +/// +/// # UTF-8 +/// +/// `String`s are always valid UTF-8. This has a few implications, the first of +/// which is that if you need a non-UTF-8 string, consider [`OsString`]. It is +/// similar, but without the UTF-8 constraint. The second implication is that +/// you cannot index into a `String`: +/// +/// ```compile_fail,E0277 +/// let s = "hello"; +/// +/// println!("The first letter of s is {}", s[0]); // ERROR!!! +/// ``` +/// +/// [`OsString`]: ../../std/ffi/struct.OsString.html +/// +/// Indexing is intended to be a constant-time operation, but UTF-8 encoding +/// does not allow us to do this. Furthermore, it's not clear what sort of +/// thing the index should return: a byte, a codepoint, or a grapheme cluster. +/// The [`bytes`] and [`chars`] methods return iterators over the first +/// two, respectively. +/// +/// [`bytes`]: str::bytes +/// [`chars`]: str::chars +/// +/// # Deref +/// +/// `String`s implement [`Deref`]``, and so inherit all of [`str`]'s +/// methods. In addition, this means that you can pass a `String` to a +/// function which takes a [`&str`] by using an ampersand (`&`): +/// +/// ``` +/// fn takes_str(s: &str) { } +/// +/// let s = String::from("Hello"); +/// +/// takes_str(&s); +/// ``` +/// +/// This will create a [`&str`] from the `String` and pass it in. This +/// conversion is very inexpensive, and so generally, functions will accept +/// [`&str`]s as arguments unless they need a `String` for some specific +/// reason. +/// +/// In certain cases Rust doesn't have enough information to make this +/// conversion, known as [`Deref`] coercion. In the following example a string +/// slice [`&'a str`][`&str`] implements the trait `TraitExample`, and the function +/// `example_func` takes anything that implements the trait. In this case Rust +/// would need to make two implicit conversions, which Rust doesn't have the +/// means to do. For that reason, the following example will not compile. +/// +/// ```compile_fail,E0277 +/// trait TraitExample {} +/// +/// impl<'a> TraitExample for &'a str {} +/// +/// fn example_func(example_arg: A) {} +/// +/// let example_string = String::from("example_string"); +/// example_func(&example_string); +/// ``` +/// +/// There are two options that would work instead. The first would be to +/// change the line `example_func(&example_string);` to +/// `example_func(example_string.as_str());`, using the method [`as_str()`] +/// to explicitly extract the string slice containing the string. The second +/// way changes `example_func(&example_string);` to +/// `example_func(&*example_string);`. In this case we are dereferencing a +/// `String` to a [`str`][`&str`], then referencing the [`str`][`&str`] back to +/// [`&str`]. The second way is more idiomatic, however both work to do the +/// conversion explicitly rather than relying on the implicit conversion. +/// +/// # Representation +/// +/// A `String` is made up of three components: a pointer to some bytes, a +/// length, and a capacity. The pointer points to an internal buffer `String` +/// uses to store its data. The length is the number of bytes currently stored +/// in the buffer, and the capacity is the size of the buffer in bytes. As such, +/// the length will always be less than or equal to the capacity. +/// +/// This buffer is always stored on the heap. +/// +/// You can look at these with the [`as_ptr`], [`len`], and [`capacity`] +/// methods: +/// +/// ``` +/// use std::mem; +/// +/// let story = String::from("Once upon a time..."); +/// +// FIXME Update this when vec_into_raw_parts is stabilized +/// // Prevent automatically dropping the String's data +/// let mut story = mem::ManuallyDrop::new(story); +/// +/// let ptr = story.as_mut_ptr(); +/// let len = story.len(); +/// let capacity = story.capacity(); +/// +/// // story has nineteen bytes +/// assert_eq!(19, len); +/// +/// // We can re-build a String out of ptr, len, and capacity. This is all +/// // unsafe because we are responsible for making sure the components are +/// // valid: +/// let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ; +/// +/// assert_eq!(String::from("Once upon a time..."), s); +/// ``` +/// +/// [`as_ptr`]: str::as_ptr +/// [`len`]: String::len +/// [`capacity`]: String::capacity +/// +/// If a `String` has enough capacity, adding elements to it will not +/// re-allocate. For example, consider this program: +/// +/// ``` +/// let mut s = String::new(); +/// +/// println!("{}", s.capacity()); +/// +/// for _ in 0..5 { +/// s.push_str("hello"); +/// println!("{}", s.capacity()); +/// } +/// ``` +/// +/// This will output the following: +/// +/// ```text +/// 0 +/// 5 +/// 10 +/// 20 +/// 20 +/// 40 +/// ``` +/// +/// At first, we have no memory allocated at all, but as we append to the +/// string, it increases its capacity appropriately. If we instead use the +/// [`with_capacity`] method to allocate the correct capacity initially: +/// +/// ``` +/// let mut s = String::with_capacity(25); +/// +/// println!("{}", s.capacity()); +/// +/// for _ in 0..5 { +/// s.push_str("hello"); +/// println!("{}", s.capacity()); +/// } +/// ``` +/// +/// [`with_capacity`]: String::with_capacity +/// +/// We end up with a different output: +/// +/// ```text +/// 25 +/// 25 +/// 25 +/// 25 +/// 25 +/// 25 +/// ``` +/// +/// Here, there's no need to allocate more memory inside the loop. +/// +/// [`str`]: prim@str +/// [`&str`]: prim@str +/// [`Deref`]: core::ops::Deref +/// [`as_str()`]: String::as_str +#[derive(PartialOrd, Eq, Ord)] +#[cfg_attr(not(test), rustc_diagnostic_item = "string_type")] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct String { + vec: Vec, +} + +/// A possible error value when converting a `String` from a UTF-8 byte vector. +/// +/// This type is the error type for the [`from_utf8`] method on [`String`]. It +/// is designed in such a way to carefully avoid reallocations: the +/// [`into_bytes`] method will give back the byte vector that was used in the +/// conversion attempt. +/// +/// [`from_utf8`]: String::from_utf8 +/// [`into_bytes`]: FromUtf8Error::into_bytes +/// +/// The [`Utf8Error`] type provided by [`std::str`] represents an error that may +/// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's +/// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` +/// through the [`utf8_error`] method. +/// +/// [`Utf8Error`]: core::str::Utf8Error +/// [`std::str`]: core::str +/// [`&str`]: prim@str +/// [`utf8_error`]: Self::utf8_error +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// // some invalid bytes, in a vector +/// let bytes = vec![0, 159]; +/// +/// let value = String::from_utf8(bytes); +/// +/// assert!(value.is_err()); +/// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FromUtf8Error { + bytes: Vec, + error: Utf8Error, +} + +/// A possible error value when converting a `String` from a UTF-16 byte slice. +/// +/// This type is the error type for the [`from_utf16`] method on [`String`]. +/// +/// [`from_utf16`]: String::from_utf16 +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// // 𝄞muic +/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, +/// 0xD800, 0x0069, 0x0063]; +/// +/// assert!(String::from_utf16(v).is_err()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct FromUtf16Error(()); + +impl String { + /// Creates a new empty `String`. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, it may cause excessive allocation later when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity`]: String::with_capacity + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = String::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn new() -> String { + String { vec: Vec::new() } + } + + /// Creates a new empty `String` with a particular capacity. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold `capacity` bytes. This is useful when you may be + /// appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity`]: String::capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new`] method. + /// + /// [`new`]: String::new + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for _ in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the string reallocate + /// s.push('a'); + /// ``` + #[inline] + #[doc(alias = "alloc")] + #[doc(alias = "malloc")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> String { + String { vec: Vec::with_capacity(capacity) } + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Since we don't + // require this method for testing purposes, I'll just stub it + // NB see the slice::hack module in slice.rs for more information + #[inline] + #[cfg(test)] + pub fn from_str(_: &str) -> String { + panic!("not available with cfg(test)"); + } + + /// Converts a vector of bytes to a `String`. + /// + /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes + /// ([`Vec`]) is made of bytes, so this function converts between the + /// two. Not all byte slices are valid `String`s, however: `String` + /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that + /// the bytes are valid UTF-8, and then does the conversion. + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the validity check, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the check. + /// + /// This method will take care to not copy the vector, for efficiency's + /// sake. + /// + /// If you need a [`&str`] instead of a `String`, consider + /// [`str::from_utf8`]. + /// + /// The inverse of this method is [`into_bytes`]. + /// + /// # Errors + /// + /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the + /// provided bytes are not UTF-8. The vector you moved in is also included. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// // We know these bytes are valid, so we'll use `unwrap()`. + /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let sparkle_heart = vec![0, 159, 146, 150]; + /// + /// assert!(String::from_utf8(sparkle_heart).is_err()); + /// ``` + /// + /// See the docs for [`FromUtf8Error`] for more details on what you can do + /// with this error. + /// + /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// [`Vec`]: crate::vec::Vec + /// [`&str`]: prim@str + /// [`into_bytes`]: String::into_bytes + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf8(vec: Vec) -> Result { + match str::from_utf8(&vec) { + Ok(..) => Ok(String { vec }), + Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), + } + } + + /// Converts a slice of bytes to a string, including invalid characters. + /// + /// Strings are made of bytes ([`u8`]), and a slice of bytes + /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts + /// between the two. Not all byte slices are valid strings, however: strings + /// are required to be valid UTF-8. During this conversion, + /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � + /// + /// [byteslice]: prim@slice + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the conversion, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the checks. + /// + /// [`from_utf8_unchecked`]: String::from_utf8_unchecked + /// + /// This function returns a [`Cow<'a, str>`]. If our byte slice is invalid + /// UTF-8, then we need to insert the replacement characters, which will + /// change the size of the string, and hence, require a `String`. But if + /// it's already valid UTF-8, we don't need a new allocation. This return + /// type allows us to handle both cases. + /// + /// [`Cow<'a, str>`]: crate::borrow::Cow + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = String::from_utf8_lossy(&sparkle_heart); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes + /// let input = b"Hello \xF0\x90\x80World"; + /// let output = String::from_utf8_lossy(input); + /// + /// assert_eq!("Hello �World", output); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { + let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); + + let (first_valid, first_broken) = if let Some(chunk) = iter.next() { + let lossy::Utf8LossyChunk { valid, broken } = chunk; + if valid.len() == v.len() { + debug_assert!(broken.is_empty()); + return Cow::Borrowed(valid); + } + (valid, broken) + } else { + return Cow::Borrowed(""); + }; + + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = String::with_capacity(v.len()); + res.push_str(first_valid); + if !first_broken.is_empty() { + res.push_str(REPLACEMENT); + } + + for lossy::Utf8LossyChunk { valid, broken } in iter { + res.push_str(valid); + if !broken.is_empty() { + res.push_str(REPLACEMENT); + } + } + + Cow::Owned(res) + } + + /// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0x0069, 0x0063]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16(v).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0xD800, 0x0069, 0x0063]; + /// assert!(String::from_utf16(v).is_err()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16(v: &[u16]) -> Result { + // This isn't done via collect::>() for performance reasons. + // FIXME: the function can be simplified again when #48994 is closed. + let mut ret = String::with_capacity(v.len()); + for c in decode_utf16(v.iter().cloned()) { + if let Ok(c) = c { + ret.push(c); + } else { + return Err(FromUtf16Error(())); + } + } + Ok(ret) + } + + /// Decode a UTF-16–encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0xDD1E, 0x0069, 0x0063, + /// 0xD834]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16_lossy(v)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16_lossy(v: &[u16]) -> String { + decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect() + } + + /// Decomposes a `String` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the string (in bytes), and the allocated capacity of the data + /// (in bytes). These are the same arguments in the same order as + /// the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `String`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `String` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: String::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let s = String::from("hello"); + /// + /// let (ptr, len, cap) = s.into_raw_parts(); + /// + /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; + /// assert_eq!(rebuilt, "hello"); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { + self.vec.into_raw_parts() + } + + /// Creates a new `String` from a length, capacity, and pointer. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * The memory at `buf` needs to have been previously allocated by the + /// same allocator the standard library uses, with a required alignment of exactly 1. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// * The first `length` bytes at `buf` need to be valid UTF-8. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. + /// + /// The ownership of `buf` is effectively transferred to the + /// `String` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::mem; + /// + /// unsafe { + /// let s = String::from("hello"); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent automatically dropping the String's data + /// let mut s = mem::ManuallyDrop::new(s); + /// + /// let ptr = s.as_mut_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// + /// let s = String::from_raw_parts(ptr, len, capacity); + /// + /// assert_eq!(String::from("hello"), s); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { + unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } + } + + /// Converts a vector of bytes to a `String` without checking that the + /// string contains valid UTF-8. + /// + /// See the safe version, [`from_utf8`], for more details. + /// + /// [`from_utf8`]: String::from_utf8 + /// + /// # Safety + /// + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, as the rest of + /// the standard library assumes that `String`s are valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = unsafe { + /// String::from_utf8_unchecked(sparkle_heart) + /// }; + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { + String { vec: bytes } + } + + /// Converts a `String` into a byte vector. + /// + /// This consumes the `String`, so we do not need to copy its contents. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = String::from("hello"); + /// let bytes = s.into_bytes(); + /// + /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_bytes(self) -> Vec { + self.vec + } + + /// Extracts a string slice containing the entire `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = String::from("foo"); + /// + /// assert_eq!("foo", s.as_str()); + /// ``` + #[inline] + #[stable(feature = "string_as_str", since = "1.7.0")] + pub fn as_str(&self) -> &str { + self + } + + /// Converts a `String` into a mutable string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("foobar"); + /// let s_mut_str = s.as_mut_str(); + /// + /// s_mut_str.make_ascii_uppercase(); + /// + /// assert_eq!("FOOBAR", s_mut_str); + /// ``` + #[inline] + #[stable(feature = "string_as_str", since = "1.7.0")] + pub fn as_mut_str(&mut self) -> &mut str { + self + } + + /// Appends a given string slice onto the end of this `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.push_str("bar"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_str(&mut self, string: &str) { + self.vec.extend_from_slice(string.as_bytes()) + } + + /// Returns this `String`'s capacity, in bytes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = String::with_capacity(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.vec.capacity() + } + + /// Ensures that this `String`'s capacity is at least `additional` bytes + /// larger than its length. + /// + /// The capacity may be increased by more than `additional` bytes if it + /// chooses, to prevent frequent reallocations. + /// + /// If you do not want this "at least" behavior, see the [`reserve_exact`] + /// method. + /// + /// # Panics + /// + /// Panics if the new capacity overflows [`usize`]. + /// + /// [`reserve_exact`]: String::reserve_exact + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::new(); + /// + /// s.reserve(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This may not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of 10 + /// assert_eq!(2, s.len()); + /// assert_eq!(10, s.capacity()); + /// + /// // Since we already have an extra 8 capacity, calling this... + /// s.reserve(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(10, s.capacity()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.vec.reserve(additional) + } + + /// Ensures that this `String`'s capacity is `additional` bytes + /// larger than its length. + /// + /// Consider using the [`reserve`] method unless you absolutely know + /// better than the allocator. + /// + /// [`reserve`]: String::reserve + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::new(); + /// + /// s.reserve_exact(10); + /// + /// assert!(s.capacity() >= 10); + /// ``` + /// + /// This may not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of 10 + /// assert_eq!(2, s.len()); + /// assert_eq!(10, s.capacity()); + /// + /// // Since we already have an extra 8 capacity, calling this... + /// s.reserve_exact(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(10, s.capacity()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.vec.reserve_exact(additional) + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `String`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.vec.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `String`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut output = String::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.push_str(data); + /// + /// Ok(output) + /// } + /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.vec.try_reserve_exact(additional) + } + + /// Shrinks the capacity of this `String` to match its length. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + self.vec.shrink_to_fit() + } + + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + + /// Appends the given [`char`] to the end of this `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("abc"); + /// + /// s.push('1'); + /// s.push('2'); + /// s.push('3'); + /// + /// assert_eq!("abc123", s); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, ch: char) { + match ch.len_utf8() { + 1 => self.vec.push(ch as u8), + _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()), + } + } + + /// Returns a byte slice of this `String`'s contents. + /// + /// The inverse of this method is [`from_utf8`]. + /// + /// [`from_utf8`]: String::from_utf8 + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = String::from("hello"); + /// + /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_bytes(&self) -> &[u8] { + &self.vec + } + + /// Shortens this `String` to the specified length. + /// + /// If `new_len` is greater than the string's current length, this has no + /// effect. + /// + /// Note that this method has no effect on the allocated capacity + /// of the string + /// + /// # Panics + /// + /// Panics if `new_len` does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("hello"); + /// + /// s.truncate(2); + /// + /// assert_eq!("he", s); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, new_len: usize) { + if new_len <= self.len() { + assert!(self.is_char_boundary(new_len)); + self.vec.truncate(new_len) + } + } + + /// Removes the last character from the string buffer and returns it. + /// + /// Returns [`None`] if this `String` is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('f')); + /// + /// assert_eq!(s.pop(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + let ch = self.chars().rev().next()?; + let newlen = self.len() - ch.len_utf8(); + unsafe { + self.vec.set_len(newlen); + } + Some(ch) + } + + /// Removes a [`char`] from this `String` at a byte position and returns it. + /// + /// This is an *O*(*n*) operation, as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than or equal to the `String`'s length, + /// or if it does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// assert_eq!(s.remove(0), 'f'); + /// assert_eq!(s.remove(1), 'o'); + /// assert_eq!(s.remove(0), 'o'); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, idx: usize) -> char { + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; + + let next = idx + ch.len_utf8(); + let len = self.len(); + unsafe { + ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next); + self.vec.set_len(len - (next - idx)); + } + ch + } + + /// Remove all matches of pattern `pat` in the `String`. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("Trees are not green, the sky is not blue."); + /// s.remove_matches("not "); + /// assert_eq!("Trees are green, the sky is blue.", s); + /// ``` + /// + /// Matches will be detected and removed iteratively, so in cases where + /// patterns overlap, only the first pattern will be removed: + /// + /// ``` + /// #![feature(string_remove_matches)] + /// let mut s = String::from("banana"); + /// s.remove_matches("ana"); + /// assert_eq!("bna", s); + /// ``` + #[unstable(feature = "string_remove_matches", reason = "new API", issue = "72826")] + pub fn remove_matches<'a, P>(&'a mut self, pat: P) + where + P: for<'x> Pattern<'x>, + { + use core::str::pattern::Searcher; + + let matches = { + let mut searcher = pat.into_searcher(self); + let mut matches = Vec::new(); + + while let Some(m) = searcher.next_match() { + matches.push(m); + } + + matches + }; + + let len = self.len(); + let mut shrunk_by = 0; + + // SAFETY: start and end will be on utf8 byte boundaries per + // the Searcher docs + unsafe { + for (start, end) in matches { + ptr::copy( + self.vec.as_mut_ptr().add(end - shrunk_by), + self.vec.as_mut_ptr().add(start - shrunk_by), + len - end, + ); + shrunk_by += end - start; + } + self.vec.set_len(len - shrunk_by); + } + } + + /// Retains only the characters specified by the predicate. + /// + /// In other words, remove all characters `c` such that `f(c)` returns `false`. + /// This method operates in place, visiting each character exactly once in the + /// original order, and preserves the order of the retained characters. + /// + /// # Examples + /// + /// ``` + /// let mut s = String::from("f_o_ob_ar"); + /// + /// s.retain(|c| c != '_'); + /// + /// assert_eq!(s, "foobar"); + /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut s = String::from("abcde"); + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// s.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(s, "bce"); + /// ``` + #[inline] + #[stable(feature = "string_retain", since = "1.26.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(char) -> bool, + { + struct SetLenOnDrop<'a> { + s: &'a mut String, + idx: usize, + del_bytes: usize, + } + + impl<'a> Drop for SetLenOnDrop<'a> { + fn drop(&mut self) { + let new_len = self.idx - self.del_bytes; + debug_assert!(new_len <= self.s.len()); + unsafe { self.s.vec.set_len(new_len) }; + } + } + + let len = self.len(); + let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 }; + + while guard.idx < len { + let ch = unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap() }; + let ch_len = ch.len_utf8(); + + if !f(ch) { + guard.del_bytes += ch_len; + } else if guard.del_bytes > 0 { + unsafe { + ptr::copy( + guard.s.vec.as_ptr().add(guard.idx), + guard.s.vec.as_mut_ptr().add(guard.idx - guard.del_bytes), + ch_len, + ); + } + } + + // Point idx to the next char + guard.idx += ch_len; + } + + drop(guard); + } + + /// Inserts a character into this `String` at a byte position. + /// + /// This is an *O*(*n*) operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::with_capacity(3); + /// + /// s.insert(0, 'f'); + /// s.insert(1, 'o'); + /// s.insert(2, 'o'); + /// + /// assert_eq!("foo", s); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, idx: usize, ch: char) { + assert!(self.is_char_boundary(idx)); + let mut bits = [0; 4]; + let bits = ch.encode_utf8(&mut bits).as_bytes(); + + unsafe { + self.insert_bytes(idx, bits); + } + } + + unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { + let len = self.len(); + let amt = bytes.len(); + self.vec.reserve(amt); + + unsafe { + ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); + ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + self.vec.set_len(len + amt); + } + } + + /// Inserts a string slice into this `String` at a byte position. + /// + /// This is an *O*(*n*) operation as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("bar"); + /// + /// s.insert_str(0, "foo"); + /// + /// assert_eq!("foobar", s); + /// ``` + #[inline] + #[stable(feature = "insert_str", since = "1.16.0")] + pub fn insert_str(&mut self, idx: usize, string: &str) { + assert!(self.is_char_boundary(idx)); + + unsafe { + self.insert_bytes(idx, string.as_bytes()); + } + } + + /// Returns a mutable reference to the contents of this `String`. + /// + /// # Safety + /// + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, as the rest of + /// the standard library assumes that `String`s are valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("hello"); + /// + /// unsafe { + /// let vec = s.as_mut_vec(); + /// assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); + /// + /// vec.reverse(); + /// } + /// assert_eq!(s, "olleh"); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { + &mut self.vec + } + + /// Returns the length of this `String`, in bytes, not [`char`]s or + /// graphemes. In other words, it may not be what a human considers the + /// length of the string. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let a = String::from("foo"); + /// assert_eq!(a.len(), 3); + /// + /// let fancy_f = String::from("ƒoo"); + /// assert_eq!(fancy_f.len(), 4); + /// assert_eq!(fancy_f.chars().count(), 3); + /// ``` + #[doc(alias = "length")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.vec.len() + } + + /// Returns `true` if this `String` has a length of zero, and `false` otherwise. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut v = String::new(); + /// assert!(v.is_empty()); + /// + /// v.push('a'); + /// assert!(!v.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the string into two at the given byte index. + /// + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Panics + /// + /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last + /// code point of the string. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// let mut hello = String::from("Hello, World!"); + /// let world = hello.split_off(7); + /// assert_eq!(hello, "Hello, "); + /// assert_eq!(world, "World!"); + /// # } + /// ``` + #[inline] + #[stable(feature = "string_split_off", since = "1.16.0")] + #[must_use = "use `.truncate()` if you don't need the other half"] + pub fn split_off(&mut self, at: usize) -> String { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); + unsafe { String::from_utf8_unchecked(other) } + } + + /// Truncates this `String`, removing all contents. + /// + /// While this means the `String` will have a length of zero, it does not + /// touch its capacity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("foo"); + /// + /// s.clear(); + /// + /// assert!(s.is_empty()); + /// assert_eq!(0, s.len()); + /// assert_eq!(3, s.capacity()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.vec.clear() + } + + /// Creates a draining iterator that removes the specified range in the `String` + /// and yields the removed `chars`. + /// + /// Note: The element range is removed even if the iterator is not + /// consumed until the end. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Remove the range up until the β from the string + /// let t: String = s.drain(..beta_offset).collect(); + /// assert_eq!(t, "α is alpha, "); + /// assert_eq!(s, "β is beta"); + /// + /// // A full range clears the string + /// s.drain(..); + /// assert_eq!(s, ""); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_> + where + R: RangeBounds, + { + // Memory safety + // + // The String version of Drain does not have the memory safety issues + // of the vector version. The data is just plain bytes. + // Because the range removal happens in Drop, if the Drain iterator is leaked, + // the removal will not happen. + let Range { start, end } = slice::range(range, ..self.len()); + assert!(self.is_char_boundary(start)); + assert!(self.is_char_boundary(end)); + + // Take out two simultaneous borrows. The &mut String won't be accessed + // until iteration is over, in Drop. + let self_ptr = self as *mut _; + // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. + let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); + + Drain { start, end, iter: chars_iter, string: self_ptr } + } + + /// Removes the specified range in the string, + /// and replaces it with the given string. + /// The given string doesn't need to be the same length as the range. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Replace the range up until the β from the string + /// s.replace_range(..beta_offset, "Α is capital alpha; "); + /// assert_eq!(s, "Α is capital alpha; β is beta"); + /// ``` + #[stable(feature = "splice", since = "1.27.0")] + pub fn replace_range(&mut self, range: R, replace_with: &str) + where + R: RangeBounds, + { + // Memory safety + // + // Replace_range does not have the memory safety issues of a vector Splice. + // of the vector version. The data is just plain bytes. + + // WARNING: Inlining this variable would be unsound (#81138) + let start = range.start_bound(); + match start { + Included(&n) => assert!(self.is_char_boundary(n)), + Excluded(&n) => assert!(self.is_char_boundary(n + 1)), + Unbounded => {} + }; + // WARNING: Inlining this variable would be unsound (#81138) + let end = range.end_bound(); + match end { + Included(&n) => assert!(self.is_char_boundary(n + 1)), + Excluded(&n) => assert!(self.is_char_boundary(n)), + Unbounded => {} + }; + + // Using `range` again would be unsound (#81138) + // We assume the bounds reported by `range` remain the same, but + // an adversarial implementation could change between calls + unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes()); + } + + /// Converts this `String` into a [`Box`]`<`[`str`]`>`. + /// + /// This will drop any excess capacity. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = String::from("hello"); + /// + /// let b = s.into_boxed_str(); + /// ``` + #[stable(feature = "box_str", since = "1.4.0")] + #[inline] + pub fn into_boxed_str(self) -> Box { + let slice = self.vec.into_boxed_slice(); + unsafe { from_boxed_utf8_unchecked(slice) } + } +} + +impl FromUtf8Error { + /// Returns a slice of [`u8`]s bytes that were attempted to convert to a `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); + /// ``` + #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[..] + } + + /// Returns the bytes that were attempted to convert to a `String`. + /// + /// This method is carefully constructed to avoid allocation. It will + /// consume the error, moving out the bytes, so that a copy of the bytes + /// does not need to be made. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let value = String::from_utf8(bytes); + /// + /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_bytes(self) -> Vec { + self.bytes + } + + /// Fetch a `Utf8Error` to get more details about the conversion failure. + /// + /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may + /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's + /// an analogue to `FromUtf8Error`. See its documentation for more details + /// on using it. + /// + /// [`std::str`]: core::str + /// [`&str`]: prim@str + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let bytes = vec![0, 159]; + /// + /// let error = String::from_utf8(bytes).unwrap_err().utf8_error(); + /// + /// // the first byte is invalid here + /// assert_eq!(1, error.valid_up_to()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn utf8_error(&self) -> Utf8Error { + self.error + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf8Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.error, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for FromUtf16Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt("invalid utf-16: lone surrogate found", f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for String { + fn clone(&self) -> Self { + String { vec: self.vec.clone() } + } + + fn clone_from(&mut self, source: &Self) { + self.vec.clone_from(&source.vec); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[stable(feature = "string_from_iter_by_ref", since = "1.17.0")] +impl<'a> FromIterator<&'a char> for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> FromIterator<&'a str> for String { + fn from_iter>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[stable(feature = "extend_string", since = "1.4.0")] +impl FromIterator for String { + fn from_iter>(iter: I) -> String { + let mut iterator = iter.into_iter(); + + // Because we're iterating over `String`s, we can avoid at least + // one allocation by getting the first string from the iterator + // and appending to it all the subsequent strings. + match iterator.next() { + None => String::new(), + Some(mut buf) => { + buf.extend(iterator); + buf + } + } + } +} + +#[stable(feature = "box_str2", since = "1.45.0")] +impl FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + +#[stable(feature = "herd_cows", since = "1.19.0")] +impl<'a> FromIterator> for String { + fn from_iter>>(iter: I) -> String { + let mut iterator = iter.into_iter(); + + // Because we're iterating over CoWs, we can (potentially) avoid at least + // one allocation by getting the first item and appending to it all the + // subsequent items. + match iterator.next() { + None => String::new(), + Some(cow) => { + let mut buf = cow.into_owned(); + buf.extend(iterator); + buf + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + let iterator = iter.into_iter(); + let (lower_bound, _) = iterator.size_hint(); + self.reserve(lower_bound); + iterator.for_each(move |c| self.push(c)); + } + + #[inline] + fn extend_one(&mut self, c: char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a> Extend<&'a char> for String { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &c: &'a char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Extend<&'a str> for String { + fn extend>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(s)); + } + + #[inline] + fn extend_one(&mut self, s: &'a str) { + self.push_str(s); + } +} + +#[stable(feature = "box_str2", since = "1.45.0")] +impl Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } +} + +#[stable(feature = "extend_string", since = "1.4.0")] +impl Extend for String { + fn extend>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } + + #[inline] + fn extend_one(&mut self, s: String) { + self.push_str(&s); + } +} + +#[stable(feature = "herd_cows", since = "1.19.0")] +impl<'a> Extend> for String { + fn extend>>(&mut self, iter: I) { + iter.into_iter().for_each(move |s| self.push_str(&s)); + } + + #[inline] + fn extend_one(&mut self, s: Cow<'a, str>) { + self.push_str(&s); + } +} + +/// A convenience impl that delegates to the impl for `&str`. +/// +/// # Examples +/// +/// ``` +/// assert_eq!(String::from("Hello world").find("world"), Some(6)); +/// ``` +#[unstable( + feature = "pattern", + reason = "API not fully fleshed out and ready to be stabilized", + issue = "27721" +)] +impl<'a, 'b> Pattern<'a> for &'b String { + type Searcher = <&'b str as Pattern<'a>>::Searcher; + + fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher { + self[..].into_searcher(haystack) + } + + #[inline] + fn is_contained_in(self, haystack: &'a str) -> bool { + self[..].is_contained_in(haystack) + } + + #[inline] + fn is_prefix_of(self, haystack: &'a str) -> bool { + self[..].is_prefix_of(haystack) + } + + #[inline] + fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> { + self[..].strip_prefix_of(haystack) + } + + #[inline] + fn is_suffix_of(self, haystack: &'a str) -> bool { + self[..].is_suffix_of(haystack) + } + + #[inline] + fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> { + self[..].strip_suffix_of(haystack) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for String { + #[inline] + fn eq(&self, other: &String) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &String) -> bool { + PartialEq::ne(&self[..], &other[..]) + } +} + +macro_rules! impl_eq { + ($lhs:ty, $rhs: ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &$rhs) -> bool { + PartialEq::ne(&self[..], &other[..]) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + PartialEq::eq(&self[..], &other[..]) + } + #[inline] + fn ne(&self, other: &$lhs) -> bool { + PartialEq::ne(&self[..], &other[..]) + } + } + }; +} + +impl_eq! { String, str } +impl_eq! { String, &'a str } +impl_eq! { Cow<'a, str>, str } +impl_eq! { Cow<'a, str>, &'b str } +impl_eq! { Cow<'a, str>, String } + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for String { + /// Creates an empty `String`. + #[inline] + fn default() -> String { + String::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for String { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for String { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for String { + #[inline] + fn hash(&self, hasher: &mut H) { + (**self).hash(hasher) + } +} + +/// Implements the `+` operator for concatenating two strings. +/// +/// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if +/// necessary). This is done to avoid allocating a new `String` and copying the entire contents on +/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by +/// repeated concatenation. +/// +/// The string on the right-hand side is only borrowed; its contents are copied into the returned +/// `String`. +/// +/// # Examples +/// +/// Concatenating two `String`s takes the first by value and borrows the second: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a + &b; +/// // `a` is moved and can no longer be used here. +/// ``` +/// +/// If you want to keep using the first `String`, you can clone it and append to the clone instead: +/// +/// ``` +/// let a = String::from("hello"); +/// let b = String::from(" world"); +/// let c = a.clone() + &b; +/// // `a` is still valid here. +/// ``` +/// +/// Concatenating `&str` slices can be done by converting the first to a `String`: +/// +/// ``` +/// let a = "hello"; +/// let b = " world"; +/// let c = a.to_string() + b; +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +impl Add<&str> for String { + type Output = String; + + #[inline] + fn add(mut self, other: &str) -> String { + self.push_str(other); + self + } +} + +/// Implements the `+=` operator for appending to a `String`. +/// +/// This has the same behavior as the [`push_str`][String::push_str] method. +#[stable(feature = "stringaddassign", since = "1.12.0")] +impl AddAssign<&str> for String { + #[inline] + fn add_assign(&mut self, other: &str) { + self.push_str(other); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index> for String { + type Output = str; + + #[inline] + fn index(&self, index: ops::Range) -> &str { + &self[..][index] + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index> for String { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeTo) -> &str { + &self[..][index] + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index> for String { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeFrom) -> &str { + &self[..][index] + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Index for String { + type Output = str; + + #[inline] + fn index(&self, _index: ops::RangeFull) -> &str { + unsafe { str::from_utf8_unchecked(&self.vec) } + } +} +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl ops::Index> for String { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeInclusive) -> &str { + Index::index(&**self, index) + } +} +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl ops::Index> for String { + type Output = str; + + #[inline] + fn index(&self, index: ops::RangeToInclusive) -> &str { + Index::index(&**self, index) + } +} + +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::IndexMut> for String { + #[inline] + fn index_mut(&mut self, index: ops::Range) -> &mut str { + &mut self[..][index] + } +} +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::IndexMut> for String { + #[inline] + fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { + &mut self[..][index] + } +} +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::IndexMut> for String { + #[inline] + fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { + &mut self[..][index] + } +} +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::IndexMut for String { + #[inline] + fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str { + unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } + } +} +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl ops::IndexMut> for String { + #[inline] + fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { + IndexMut::index_mut(&mut **self, index) + } +} +#[stable(feature = "inclusive_range", since = "1.26.0")] +impl ops::IndexMut> for String { + #[inline] + fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { + IndexMut::index_mut(&mut **self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for String { + type Target = str; + + #[inline] + fn deref(&self) -> &str { + unsafe { str::from_utf8_unchecked(&self.vec) } + } +} + +#[stable(feature = "derefmut_for_string", since = "1.3.0")] +impl ops::DerefMut for String { + #[inline] + fn deref_mut(&mut self) -> &mut str { + unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } + } +} + +/// A type alias for [`Infallible`]. +/// +/// This alias exists for backwards compatibility, and may be eventually deprecated. +/// +/// [`Infallible`]: core::convert::Infallible +#[stable(feature = "str_parse_error", since = "1.5.0")] +pub type ParseError = core::convert::Infallible; + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for String { + type Err = core::convert::Infallible; + #[inline] + fn from_str(s: &str) -> Result { + Ok(String::from(s)) + } +} + +/// A trait for converting a value to a `String`. +/// +/// This trait is automatically implemented for any type which implements the +/// [`Display`] trait. As such, `ToString` shouldn't be implemented directly: +/// [`Display`] should be implemented instead, and you get the `ToString` +/// implementation for free. +/// +/// [`Display`]: fmt::Display +#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToString { + /// Converts the given value to a `String`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let i = 5; + /// let five = String::from("5"); + /// + /// assert_eq!(five, i.to_string()); + /// ``` + #[rustc_conversion_suggestion] + #[stable(feature = "rust1", since = "1.0.0")] + fn to_string(&self) -> String; +} + +/// # Panics +/// +/// In this implementation, the `to_string` method panics +/// if the `Display` implementation returns an error. +/// This indicates an incorrect `Display` implementation +/// since `fmt::Write for String` never returns an error itself. +#[stable(feature = "rust1", since = "1.0.0")] +impl ToString for T { + // A common guideline is to not inline generic functions. However, + // removing `#[inline]` from this method causes non-negligible regressions. + // See , the last attempt + // to try to remove it. + #[inline] + default fn to_string(&self) -> String { + use fmt::Write; + let mut buf = String::new(); + buf.write_fmt(format_args!("{}", self)) + .expect("a Display implementation returned an error unexpectedly"); + buf + } +} + +#[stable(feature = "char_to_string_specialization", since = "1.46.0")] +impl ToString for char { + #[inline] + fn to_string(&self) -> String { + String::from(self.encode_utf8(&mut [0; 4])) + } +} + +#[stable(feature = "str_to_string_specialization", since = "1.9.0")] +impl ToString for str { + #[inline] + fn to_string(&self) -> String { + String::from(self) + } +} + +#[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")] +impl ToString for Cow<'_, str> { + #[inline] + fn to_string(&self) -> String { + self[..].to_owned() + } +} + +#[stable(feature = "string_to_string_specialization", since = "1.17.0")] +impl ToString for String { + #[inline] + fn to_string(&self) -> String { + self.to_owned() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for String { + #[inline] + fn as_ref(&self) -> &str { + self + } +} + +#[stable(feature = "string_as_mut", since = "1.43.0")] +impl AsMut for String { + #[inline] + fn as_mut(&mut self) -> &mut str { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[u8]> for String { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for String { + #[inline] + fn from(s: &str) -> String { + s.to_owned() + } +} + +#[stable(feature = "from_mut_str_for_string", since = "1.44.0")] +impl From<&mut str> for String { + /// Converts a `&mut str` into a `String`. + /// + /// The result is allocated on the heap. + #[inline] + fn from(s: &mut str) -> String { + s.to_owned() + } +} + +#[stable(feature = "from_ref_string", since = "1.35.0")] +impl From<&String> for String { + #[inline] + fn from(s: &String) -> String { + s.clone() + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "string_from_box", since = "1.18.0")] +impl From> for String { + /// Converts the given boxed `str` slice to a `String`. + /// It is notable that the `str` slice is owned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = s1.into_boxed_str(); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: Box) -> String { + s.into_string() + } +} + +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From for Box { + /// Converts the given `String` to a boxed `str` slice that is owned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = Box::from(s1); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: String) -> Box { + s.into_boxed_str() + } +} + +#[stable(feature = "string_from_cow_str", since = "1.14.0")] +impl<'a> From> for String { + fn from(s: Cow<'a, str>) -> String { + s.into_owned() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&'a str> for Cow<'a, str> { + /// Converts a string slice into a Borrowed variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant")); + /// ``` + #[inline] + fn from(s: &'a str) -> Cow<'a, str> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From for Cow<'a, str> { + /// Converts a String into an Owned variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// let s = "eggplant".to_string(); + /// let s2 = "eggplant".to_string(); + /// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2)); + /// ``` + #[inline] + fn from(s: String) -> Cow<'a, str> { + Cow::Owned(s) + } +} + +#[stable(feature = "cow_from_string_ref", since = "1.28.0")] +impl<'a> From<&'a String> for Cow<'a, str> { + /// Converts a String reference into a Borrowed variant. + /// No heap allocation is performed, and the string + /// is not copied. + /// + /// # Example + /// + /// ``` + /// # use std::borrow::Cow; + /// let s = "eggplant".to_string(); + /// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant")); + /// ``` + #[inline] + fn from(s: &'a String) -> Cow<'a, str> { + Cow::Borrowed(s.as_str()) + } +} + +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a> FromIterator for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a, 'b> FromIterator<&'b str> for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[stable(feature = "cow_str_from_iter", since = "1.12.0")] +impl<'a> FromIterator for Cow<'a, str> { + fn from_iter>(it: I) -> Cow<'a, str> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] +impl From for Vec { + /// Converts the given `String` to a vector `Vec` that holds values of type `u8`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s1 = String::from("hello world"); + /// let v1 = Vec::from(s1); + /// + /// for b in v1 { + /// println!("{}", b); + /// } + /// ``` + fn from(string: String) -> Vec { + string.into_bytes() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Write for String { + #[inline] + fn write_str(&mut self, s: &str) -> fmt::Result { + self.push_str(s); + Ok(()) + } + + #[inline] + fn write_char(&mut self, c: char) -> fmt::Result { + self.push(c); + Ok(()) + } +} + +/// A draining iterator for `String`. +/// +/// This struct is created by the [`drain`] method on [`String`]. See its +/// documentation for more. +/// +/// [`drain`]: String::drain +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain<'a> { + /// Will be used as &'a mut String in the destructor + string: *mut String, + /// Start of part to remove + start: usize, + /// End of part to remove + end: usize, + /// Current remaining range to remove + iter: Chars<'a>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.as_str()).finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_> { + fn drop(&mut self) { + unsafe { + // Use Vec::drain. "Reaffirm" the bounds checks to avoid + // panic code being inserted again. + let self_vec = (*self.string).as_mut_vec(); + if self.start <= self.end && self.end <= self_vec.len() { + self_vec.drain(self.start..self.end); + } + } + } +} + +impl<'a> Drain<'a> { + /// Returns the remaining (sub)string of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_drain_as_str)] + /// let mut s = String::from("abc"); + /// let mut drain = s.drain(..); + /// assert_eq!(drain.as_str(), "abc"); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_str(), "bc"); + /// ``` + #[unstable(feature = "string_drain_as_str", issue = "76905")] // Note: uncomment AsRef impls below when stabilizing. + pub fn as_str(&self) -> &str { + self.iter.as_str() + } +} + +// Uncomment when stabilizing `string_drain_as_str`. +// #[unstable(feature = "string_drain_as_str", issue = "76905")] +// impl<'a> AsRef for Drain<'a> { +// fn as_ref(&self) -> &str { +// self.as_str() +// } +// } +// +// #[unstable(feature = "string_drain_as_str", issue = "76905")] +// impl<'a> AsRef<[u8]> for Drain<'a> { +// fn as_ref(&self) -> &[u8] { +// self.as_str().as_bytes() +// } +// } + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_> {} + +#[stable(feature = "from_char_for_string", since = "1.46.0")] +impl From for String { + #[inline] + fn from(c: char) -> Self { + c.to_string() + } +} +//! A module for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; +use core::ops::{Add, AddAssign, Deref}; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::borrow::{Borrow, BorrowMut}; + +use crate::fmt; +use crate::string::String; + +use Cow::*; + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Borrow for Cow<'a, B> +where + B: ToOwned, + ::Owned: 'a, +{ + fn borrow(&self) -> &B { + &**self + } +} + +/// A generalization of `Clone` to borrowed data. +/// +/// Some types make it possible to go from borrowed to owned, usually by +/// implementing the `Clone` trait. But `Clone` works only for going from `&T` +/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data +/// from any borrow of a given type. +#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToOwned { + /// The resulting type after obtaining ownership. + #[stable(feature = "rust1", since = "1.0.0")] + type Owned: Borrow; + + /// Creates owned data from borrowed data, usually by cloning. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s: &str = "a"; + /// let ss: String = s.to_owned(); + /// + /// let v: &[i32] = &[1, 2]; + /// let vv: Vec = v.to_owned(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] + fn to_owned(&self) -> Self::Owned; + + /// Uses borrowed data to replace owned data, usually by cloning. + /// + /// This is borrow-generalized version of `Clone::clone_from`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(toowned_clone_into)] + /// let mut s: String = String::new(); + /// "hello".clone_into(&mut s); + /// + /// let mut v: Vec = Vec::new(); + /// [1, 2][..].clone_into(&mut v); + /// ``` + #[unstable(feature = "toowned_clone_into", reason = "recently added", issue = "41263")] + fn clone_into(&self, target: &mut Self::Owned) { + *target = self.to_owned(); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for T +where + T: Clone, +{ + type Owned = T; + fn to_owned(&self) -> T { + self.clone() + } + + fn clone_into(&self, target: &mut T) { + target.clone_from(self); + } +} + +/// A clone-on-write smart pointer. +/// +/// The type `Cow` is a smart pointer providing clone-on-write functionality: it +/// can enclose and provide immutable access to borrowed data, and clone the +/// data lazily when mutation or ownership is required. The type is designed to +/// work with general borrowed data via the `Borrow` trait. +/// +/// `Cow` implements `Deref`, which means that you can call +/// non-mutating methods directly on the data it encloses. If mutation +/// is desired, `to_mut` will obtain a mutable reference to an owned +/// value, cloning if necessary. +/// +/// If you need reference-counting pointers, note that +/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and +/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write +/// functionality as well. +/// +/// # Examples +/// +/// ``` +/// use std::borrow::Cow; +/// +/// fn abs_all(input: &mut Cow<[i32]>) { +/// for i in 0..input.len() { +/// let v = input[i]; +/// if v < 0 { +/// // Clones into a vector if not already owned. +/// input.to_mut()[i] = -v; +/// } +/// } +/// } +/// +/// // No clone occurs because `input` doesn't need to be mutated. +/// let slice = [0, 1, 2]; +/// let mut input = Cow::from(&slice[..]); +/// abs_all(&mut input); +/// +/// // Clone occurs because `input` needs to be mutated. +/// let slice = [-1, 0, 1]; +/// let mut input = Cow::from(&slice[..]); +/// abs_all(&mut input); +/// +/// // No clone occurs because `input` is already owned. +/// let mut input = Cow::from(vec![-1, 0, 1]); +/// abs_all(&mut input); +/// ``` +/// +/// Another example showing how to keep `Cow` in a struct: +/// +/// ``` +/// use std::borrow::Cow; +/// +/// struct Items<'a, X: 'a> where [X]: ToOwned> { +/// values: Cow<'a, [X]>, +/// } +/// +/// impl<'a, X: Clone + 'a> Items<'a, X> where [X]: ToOwned> { +/// fn new(v: Cow<'a, [X]>) -> Self { +/// Items { values: v } +/// } +/// } +/// +/// // Creates a container from borrowed values of a slice +/// let readonly = [1, 2]; +/// let borrowed = Items::new((&readonly[..]).into()); +/// match borrowed { +/// Items { values: Cow::Borrowed(b) } => println!("borrowed {:?}", b), +/// _ => panic!("expect borrowed value"), +/// } +/// +/// let mut clone_on_write = borrowed; +/// // Mutates the data from slice into owned vec and pushes a new value on top +/// clone_on_write.values.to_mut().push(3); +/// println!("clone_on_write = {:?}", clone_on_write.values); +/// +/// // The data was mutated. Let check it out. +/// match clone_on_write { +/// Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"), +/// _ => panic!("expect owned data"), +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Cow<'a, B: ?Sized + 'a> +where + B: ToOwned, +{ + /// Borrowed data. + #[stable(feature = "rust1", since = "1.0.0")] + Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B), + + /// Owned data. + #[stable(feature = "rust1", since = "1.0.0")] + Owned(#[stable(feature = "rust1", since = "1.0.0")] ::Owned), +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Cow<'_, B> { + fn clone(&self) -> Self { + match *self { + Borrowed(b) => Borrowed(b), + Owned(ref o) => { + let b: &B = o.borrow(); + Owned(b.to_owned()) + } + } + } + + fn clone_from(&mut self, source: &Self) { + match (self, source) { + (&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest), + (t, s) => *t = s.clone(), + } + } +} + +impl Cow<'_, B> { + /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. + /// + /// # Examples + /// + /// ``` + /// #![feature(cow_is_borrowed)] + /// use std::borrow::Cow; + /// + /// let cow = Cow::Borrowed("moo"); + /// assert!(cow.is_borrowed()); + /// + /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); + /// assert!(!bull.is_borrowed()); + /// ``` + #[unstable(feature = "cow_is_borrowed", issue = "65143")] + #[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")] + pub const fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + Owned(_) => false, + } + } + + /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(cow_is_borrowed)] + /// use std::borrow::Cow; + /// + /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); + /// assert!(cow.is_owned()); + /// + /// let bull = Cow::Borrowed("...moo?"); + /// assert!(!bull.is_owned()); + /// ``` + #[unstable(feature = "cow_is_borrowed", issue = "65143")] + #[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")] + pub const fn is_owned(&self) -> bool { + !self.is_borrowed() + } + + /// Acquires a mutable reference to the owned form of the data. + /// + /// Clones the data if it is not already owned. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let mut cow = Cow::Borrowed("foo"); + /// cow.to_mut().make_ascii_uppercase(); + /// + /// assert_eq!( + /// cow, + /// Cow::Owned(String::from("FOO")) as Cow + /// ); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_mut(&mut self) -> &mut ::Owned { + match *self { + Borrowed(borrowed) => { + *self = Owned(borrowed.to_owned()); + match *self { + Borrowed(..) => unreachable!(), + Owned(ref mut owned) => owned, + } + } + Owned(ref mut owned) => owned, + } + } + + /// Extracts the owned data. + /// + /// Clones the data if it is not already owned. + /// + /// # Examples + /// + /// Calling `into_owned` on a `Cow::Borrowed` clones the underlying data + /// and becomes a `Cow::Owned`: + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let s = "Hello world!"; + /// let cow = Cow::Borrowed(s); + /// + /// assert_eq!( + /// cow.into_owned(), + /// String::from(s) + /// ); + /// ``` + /// + /// Calling `into_owned` on a `Cow::Owned` is a no-op: + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let s = "Hello world!"; + /// let cow: Cow = Cow::Owned(String::from(s)); + /// + /// assert_eq!( + /// cow.into_owned(), + /// String::from(s) + /// ); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_owned(self) -> ::Owned { + match self { + Borrowed(borrowed) => borrowed.to_owned(), + Owned(owned) => owned, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Cow<'_, B> { + type Target = B; + + fn deref(&self) -> &B { + match *self { + Borrowed(borrowed) => borrowed, + Owned(ref owned) => owned.borrow(), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Cow<'_, B> where B: Eq + ToOwned {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Cow<'_, B> +where + B: Ord + ToOwned, +{ + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> +where + B: PartialEq + ToOwned, + C: ToOwned, +{ + #[inline] + fn eq(&self, other: &Cow<'b, C>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> +where + B: PartialOrd + ToOwned, +{ + #[inline] + fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Cow<'_, B> +where + B: fmt::Debug + ToOwned, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Cow<'_, B> +where + B: fmt::Display + ToOwned, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), + } + } +} + +#[stable(feature = "default", since = "1.11.0")] +impl Default for Cow<'_, B> +where + B: ToOwned, +{ + /// Creates an owned Cow<'a, B> with the default value for the contained owned value. + fn default() -> Self { + Owned(::Owned::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Cow<'_, B> +where + B: Hash + ToOwned, +{ + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for Cow<'_, T> { + fn as_ref(&self) -> &T { + self + } +} + +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> Add<&'a str> for Cow<'a, str> { + type Output = Cow<'a, str>; + + #[inline] + fn add(mut self, rhs: &'a str) -> Self::Output { + self += rhs; + self + } +} + +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> Add> for Cow<'a, str> { + type Output = Cow<'a, str>; + + #[inline] + fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { + self += rhs; + self + } +} + +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> AddAssign<&'a str> for Cow<'a, str> { + fn add_assign(&mut self, rhs: &'a str) { + if self.is_empty() { + *self = Cow::Borrowed(rhs) + } else if !rhs.is_empty() { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(rhs); + } + } +} + +#[stable(feature = "cow_add", since = "1.14.0")] +impl<'a> AddAssign> for Cow<'a, str> { + fn add_assign(&mut self, rhs: Cow<'a, str>) { + if self.is_empty() { + *self = rhs + } else if !rhs.is_empty() { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(&rhs); + } + } +} +//! # The Rust core allocation and collections library +//! +//! This library provides smart pointers and collections for managing +//! heap-allocated values. +//! +//! This library, like libcore, normally doesn’t need to be used directly +//! since its contents are re-exported in the [`std` crate](../std/index.html). +//! Crates that use the `#![no_std]` attribute however will typically +//! not depend on `std`, so they’d use this crate instead. +//! +//! ## Boxed values +//! +//! The [`Box`] type is a smart pointer type. There can only be one owner of a +//! [`Box`], and the owner can decide to mutate the contents, which live on the +//! heap. +//! +//! This type can be sent among threads efficiently as the size of a `Box` value +//! is the same as that of a pointer. Tree-like data structures are often built +//! with boxes because each node often has only one owner, the parent. +//! +//! ## Reference counted pointers +//! +//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended +//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and +//! only allows access to `&T`, a shared reference. +//! +//! This type is useful when inherited mutability (such as using [`Box`]) is too +//! constraining for an application, and is often paired with the [`Cell`] or +//! [`RefCell`] types in order to allow mutation. +//! +//! ## Atomically reference counted pointers +//! +//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It +//! provides all the same functionality of [`Rc`], except it requires that the +//! contained type `T` is shareable. Additionally, [`Arc`][`Arc`] is itself +//! sendable while [`Rc`][`Rc`] is not. +//! +//! This type allows for shared access to the contained data, and is often +//! paired with synchronization primitives such as mutexes to allow mutation of +//! shared resources. +//! +//! ## Collections +//! +//! Implementations of the most common general purpose data structures are +//! defined in this library. They are re-exported through the +//! [standard collections library](../std/collections/index.html). +//! +//! ## Heap interfaces +//! +//! The [`alloc`](alloc/index.html) module defines the low-level interface to the +//! default global allocator. It is not compatible with the libc allocator API. +//! +//! [`Arc`]: sync +//! [`Box`]: boxed +//! [`Cell`]: core::cell +//! [`Rc`]: rc +//! [`RefCell`]: core::cell + +#![allow(unused_attributes)] +#![stable(feature = "alloc", since = "1.36.0")] +#![doc( + html_root_url = "https://doc.rust-lang.org/nightly/", + html_playground_url = "https://play.rust-lang.org/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", + test(no_crate_inject, attr(allow(unused_variables), deny(warnings))) +)] +#![no_std] +#![needs_allocator] +#![warn(deprecated_in_future)] +#![warn(missing_docs)] +#![warn(missing_debug_implementations)] +#![allow(explicit_outlives_requirements)] +#![deny(unsafe_op_in_unsafe_fn)] +#![feature(rustc_allow_const_fn_unstable)] +#![cfg_attr(not(test), feature(generator_trait))] +#![cfg_attr(test, feature(test))] +#![cfg_attr(test, feature(new_uninit))] +#![feature(allocator_api)] +#![feature(array_chunks)] +#![feature(array_methods)] +#![feature(array_windows)] +#![feature(allow_internal_unstable)] +#![feature(arbitrary_self_types)] +#![feature(async_stream)] +#![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(cfg_sanitize)] +#![feature(cfg_target_has_atomic)] +#![feature(coerce_unsized)] +#![feature(const_btree_new)] +#![cfg_attr(bootstrap, feature(const_fn))] +#![cfg_attr(not(bootstrap), feature(const_fn_trait_bound))] +#![feature(cow_is_borrowed)] +#![feature(const_cow_is_borrowed)] +#![feature(destructuring_assignment)] +#![feature(dispatch_from_dyn)] +#![feature(core_intrinsics)] +#![feature(dropck_eyepatch)] +#![feature(exact_size_is_empty)] +#![feature(exclusive_range_pattern)] +#![feature(extend_one)] +#![feature(fmt_internals)] +#![feature(fn_traits)] +#![feature(fundamental)] +#![feature(inplace_iteration)] +// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]` +// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad +// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs +// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. +#![feature(intra_doc_pointers)] +#![feature(iter_zip)] +#![feature(lang_items)] +#![feature(layout_for_ptr)] +#![feature(maybe_uninit_ref)] +#![feature(negative_impls)] +#![feature(never_type)] +#![feature(nll)] +#![feature(nonnull_slice_from_raw_parts)] +#![feature(auto_traits)] +#![feature(option_result_unwrap_unchecked)] +#![cfg_attr(bootstrap, feature(or_patterns))] +#![feature(pattern)] +#![feature(ptr_internals)] +#![feature(rustc_attrs)] +#![feature(receiver_trait)] +#![feature(min_specialization)] +#![feature(set_ptr_value)] +#![feature(slice_ptr_get)] +#![feature(slice_ptr_len)] +#![feature(slice_range)] +#![feature(staged_api)] +#![feature(str_internals)] +#![feature(trusted_len)] +#![feature(unboxed_closures)] +#![feature(unicode_internals)] +#![feature(unsize)] +#![feature(unsized_fn_params)] +#![feature(allocator_internals)] +#![feature(slice_partition_dedup)] +#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)] +#![feature(alloc_layout_extra)] +#![feature(trusted_random_access)] +#![feature(try_trait)] +#![feature(min_type_alias_impl_trait)] +#![feature(associated_type_bounds)] +#![feature(slice_group_by)] +#![feature(decl_macro)] +// Allow testing this library + +#[cfg(test)] +#[macro_use] +extern crate std; +#[cfg(test)] +extern crate test; + +// Module with internal macros used by other modules (needs to be included before other modules). +#[macro_use] +mod macros; + +// Heaps provided for low-level allocation strategies + +pub mod alloc; + +// Primitive types using the heaps above + +// Need to conditionally define the mod from `boxed.rs` to avoid +// duplicating the lang-items when building in test cfg; but also need +// to allow code to have `use boxed::Box;` declarations. +#[cfg(not(test))] +pub mod boxed; +#[cfg(test)] +mod boxed { + pub use std::boxed::Box; +} +pub mod borrow; +pub mod collections; +pub mod fmt; +pub mod prelude; +pub mod raw_vec; +pub mod rc; +pub mod slice; +pub mod str; +pub mod string; +#[cfg(target_has_atomic = "ptr")] +pub mod sync; +#[cfg(target_has_atomic = "ptr")] +pub mod task; +#[cfg(test)] +mod tests; +pub mod vec; + +#[doc(hidden)] +#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] +pub mod __export { + pub use core::format_args; +} +//! Single-threaded reference-counting pointers. 'Rc' stands for 'Reference +//! Counted'. +//! +//! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, +//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new +//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a +//! given allocation is destroyed, the value stored in that allocation (often +//! referred to as "inner value") is also dropped. +//! +//! Shared references in Rust disallow mutation by default, and [`Rc`] +//! is no exception: you cannot generally obtain a mutable reference to +//! something inside an [`Rc`]. If you need mutability, put a [`Cell`] +//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability +//! inside an `Rc`][mutability]. +//! +//! [`Rc`] uses non-atomic reference counting. This means that overhead is very +//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`] +//! does not implement [`Send`][send]. As a result, the Rust compiler +//! will check *at compile time* that you are not sending [`Rc`]s between +//! threads. If you need multi-threaded, atomic reference counting, use +//! [`sync::Arc`][arc]. +//! +//! The [`downgrade`][downgrade] method can be used to create a non-owning +//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d +//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has +//! already been dropped. In other words, `Weak` pointers do not keep the value +//! inside the allocation alive; however, they *do* keep the allocation +//! (the backing store for the inner value) alive. +//! +//! A cycle between [`Rc`] pointers will never be deallocated. For this reason, +//! [`Weak`] is used to break cycles. For example, a tree could have strong +//! [`Rc`] pointers from parent nodes to children, and [`Weak`] pointers from +//! children back to their parents. +//! +//! `Rc` automatically dereferences to `T` (via the [`Deref`] trait), +//! so you can call `T`'s methods on a value of type [`Rc`][`Rc`]. To avoid name +//! clashes with `T`'s methods, the methods of [`Rc`][`Rc`] itself are associated +//! functions, called using [fully qualified syntax]: +//! +//! ``` +//! use std::rc::Rc; +//! +//! let my_rc = Rc::new(()); +//! Rc::downgrade(&my_rc); +//! ``` +//! +//! `Rc`'s implementations of traits like `Clone` may also be called using +//! fully qualified syntax. Some people prefer to use fully qualified syntax, +//! while others prefer using method-call syntax. +//! +//! ``` +//! use std::rc::Rc; +//! +//! let rc = Rc::new(()); +//! // Method-call syntax +//! let rc2 = rc.clone(); +//! // Fully qualified syntax +//! let rc3 = Rc::clone(&rc); +//! ``` +//! +//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the inner value may have +//! already been dropped. +//! +//! # Cloning references +//! +//! Creating a new reference to the same allocation as an existing reference counted pointer +//! is done using the `Clone` trait implemented for [`Rc`][`Rc`] and [`Weak`][`Weak`]. +//! +//! ``` +//! use std::rc::Rc; +//! +//! let foo = Rc::new(vec![1.0, 2.0, 3.0]); +//! // The two syntaxes below are equivalent. +//! let a = foo.clone(); +//! let b = Rc::clone(&foo); +//! // a and b both point to the same memory location as foo. +//! ``` +//! +//! The `Rc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly +//! the meaning of the code. In the example above, this syntax makes it easier to see that +//! this code is creating a new reference rather than copying the whole content of foo. +//! +//! # Examples +//! +//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`. +//! We want to have our `Gadget`s point to their `Owner`. We can't do this with +//! unique ownership, because more than one gadget may belong to the same +//! `Owner`. [`Rc`] allows us to share an `Owner` between multiple `Gadget`s, +//! and have the `Owner` remain allocated as long as any `Gadget` points at it. +//! +//! ``` +//! use std::rc::Rc; +//! +//! struct Owner { +//! name: String, +//! // ...other fields +//! } +//! +//! struct Gadget { +//! id: i32, +//! owner: Rc, +//! // ...other fields +//! } +//! +//! fn main() { +//! // Create a reference-counted `Owner`. +//! let gadget_owner: Rc = Rc::new( +//! Owner { +//! name: "Gadget Man".to_string(), +//! } +//! ); +//! +//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc` +//! // gives us a new pointer to the same `Owner` allocation, incrementing +//! // the reference count in the process. +//! let gadget1 = Gadget { +//! id: 1, +//! owner: Rc::clone(&gadget_owner), +//! }; +//! let gadget2 = Gadget { +//! id: 2, +//! owner: Rc::clone(&gadget_owner), +//! }; +//! +//! // Dispose of our local variable `gadget_owner`. +//! drop(gadget_owner); +//! +//! // Despite dropping `gadget_owner`, we're still able to print out the name +//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a +//! // single `Rc`, not the `Owner` it points to. As long as there are +//! // other `Rc` pointing at the same `Owner` allocation, it will remain +//! // live. The field projection `gadget1.owner.name` works because +//! // `Rc` automatically dereferences to `Owner`. +//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); +//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); +//! +//! // At the end of the function, `gadget1` and `gadget2` are destroyed, and +//! // with them the last counted references to our `Owner`. Gadget Man now +//! // gets destroyed as well. +//! } +//! ``` +//! +//! If our requirements change, and we also need to be able to traverse from +//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner` +//! to `Gadget` introduces a cycle. This means that their +//! reference counts can never reach 0, and the allocation will never be destroyed: +//! a memory leak. In order to get around this, we can use [`Weak`] +//! pointers. +//! +//! Rust actually makes it somewhat difficult to produce this loop in the first +//! place. In order to end up with two values that point at each other, one of +//! them needs to be mutable. This is difficult because [`Rc`] enforces +//! memory safety by only giving out shared references to the value it wraps, +//! and these don't allow direct mutation. We need to wrap the part of the +//! value we wish to mutate in a [`RefCell`], which provides *interior +//! mutability*: a method to achieve mutability through a shared reference. +//! [`RefCell`] enforces Rust's borrowing rules at runtime. +//! +//! ``` +//! use std::rc::Rc; +//! use std::rc::Weak; +//! use std::cell::RefCell; +//! +//! struct Owner { +//! name: String, +//! gadgets: RefCell>>, +//! // ...other fields +//! } +//! +//! struct Gadget { +//! id: i32, +//! owner: Rc, +//! // ...other fields +//! } +//! +//! fn main() { +//! // Create a reference-counted `Owner`. Note that we've put the `Owner`'s +//! // vector of `Gadget`s inside a `RefCell` so that we can mutate it through +//! // a shared reference. +//! let gadget_owner: Rc = Rc::new( +//! Owner { +//! name: "Gadget Man".to_string(), +//! gadgets: RefCell::new(vec![]), +//! } +//! ); +//! +//! // Create `Gadget`s belonging to `gadget_owner`, as before. +//! let gadget1 = Rc::new( +//! Gadget { +//! id: 1, +//! owner: Rc::clone(&gadget_owner), +//! } +//! ); +//! let gadget2 = Rc::new( +//! Gadget { +//! id: 2, +//! owner: Rc::clone(&gadget_owner), +//! } +//! ); +//! +//! // Add the `Gadget`s to their `Owner`. +//! { +//! let mut gadgets = gadget_owner.gadgets.borrow_mut(); +//! gadgets.push(Rc::downgrade(&gadget1)); +//! gadgets.push(Rc::downgrade(&gadget2)); +//! +//! // `RefCell` dynamic borrow ends here. +//! } +//! +//! // Iterate over our `Gadget`s, printing their details out. +//! for gadget_weak in gadget_owner.gadgets.borrow().iter() { +//! +//! // `gadget_weak` is a `Weak`. Since `Weak` pointers can't +//! // guarantee the allocation still exists, we need to call +//! // `upgrade`, which returns an `Option>`. +//! // +//! // In this case we know the allocation still exists, so we simply +//! // `unwrap` the `Option`. In a more complicated program, you might +//! // need graceful error handling for a `None` result. +//! +//! let gadget = gadget_weak.upgrade().unwrap(); +//! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name); +//! } +//! +//! // At the end of the function, `gadget_owner`, `gadget1`, and `gadget2` +//! // are destroyed. There are now no strong (`Rc`) pointers to the +//! // gadgets, so they are destroyed. This zeroes the reference count on +//! // Gadget Man, so he gets destroyed as well. +//! } +//! ``` +//! +//! [clone]: Clone::clone +//! [`Cell`]: core::cell::Cell +//! [`RefCell`]: core::cell::RefCell +//! [send]: core::marker::Send +//! [arc]: crate::sync::Arc +//! [`Deref`]: core::ops::Deref +//! [downgrade]: Rc::downgrade +//! [upgrade]: Weak::upgrade +//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable +//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name + +#![stable(feature = "rust1", since = "1.0.0")] + +#[cfg(not(test))] +use crate::boxed::Box; +#[cfg(test)] +use std::boxed::Box; + +use core::any::Any; +use core::borrow; +use core::cell::Cell; +use core::cmp::Ordering; +use core::convert::{From, TryFrom}; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::intrinsics::abort; +use core::iter; +use core::marker::{self, PhantomData, Unpin, Unsize}; +use core::mem::{self, align_of_val_raw, forget, size_of_val}; +use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +use core::pin::Pin; +use core::ptr::{self, NonNull}; +use core::slice::from_raw_parts_mut; + +use crate::alloc::{ + box_free, handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw, +}; +use crate::borrow::{Cow, ToOwned}; +use crate::string::String; +use crate::vec::Vec; + +#[cfg(test)] +mod tests; + +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +#[repr(C)] +struct RcBox { + strong: Cell, + weak: Cell, + value: T, +} + +/// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference +/// Counted'. +/// +/// See the [module-level documentation](./index.html) for more details. +/// +/// The inherent methods of `Rc` are all associated functions, which means +/// that you have to call them as e.g., [`Rc::get_mut(&mut value)`][get_mut] instead of +/// `value.get_mut()`. This avoids conflicts with methods of the inner type `T`. +/// +/// [get_mut]: Rc::get_mut +#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Rc { + ptr: NonNull>, + phantom: PhantomData>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl !marker::Send for Rc {} +#[stable(feature = "rust1", since = "1.0.0")] +impl !marker::Sync for Rc {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized> for Rc {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Rc {} + +impl Rc { + #[inline(always)] + fn inner(&self) -> &RcBox { + // This unsafety is ok because while this Rc is alive we're guaranteed + // that the inner pointer is valid. + unsafe { self.ptr.as_ref() } + } + + fn from_inner(ptr: NonNull>) -> Self { + Self { ptr, phantom: PhantomData } + } + + unsafe fn from_ptr(ptr: *mut RcBox) -> Self { + Self::from_inner(unsafe { NonNull::new_unchecked(ptr) }) + } +} + +impl Rc { + /// Constructs a new `Rc`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(value: T) -> Rc { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + Self::from_inner( + Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(), + ) + } + + /// Constructs a new `Rc` using a weak reference to itself. Attempting + /// to upgrade the weak reference before this function returns will result + /// in a `None` value. However, the weak reference may be cloned freely and + /// stored for use at a later time. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_new_cyclic)] + /// #![allow(dead_code)] + /// use std::rc::{Rc, Weak}; + /// + /// struct Gadget { + /// self_weak: Weak, + /// // ... more fields + /// } + /// impl Gadget { + /// pub fn new() -> Rc { + /// Rc::new_cyclic(|self_weak| { + /// Gadget { self_weak: self_weak.clone(), /* ... */ } + /// }) + /// } + /// } + /// ``` + #[unstable(feature = "arc_new_cyclic", issue = "75861")] + pub fn new_cyclic(data_fn: impl FnOnce(&Weak) -> T) -> Rc { + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let uninit_ptr: NonNull<_> = Box::leak(box RcBox { + strong: Cell::new(0), + weak: Cell::new(1), + value: mem::MaybeUninit::::uninit(), + }) + .into(); + + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(ptr::addr_of_mut!((*inner).value), data); + + let prev_value = (*inner).strong.get(); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + (*inner).strong.set(1); + } + + let strong = Rc::from_inner(init_ptr); + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + mem::forget(weak); + strong + } + + /// Constructs a new `Rc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Rc> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + |mem| mem as *mut RcBox>, + )) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// use std::rc::Rc; + /// + /// let zero = Rc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Rc> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + |mem| mem as *mut RcBox>, + )) + } + } + + /// Constructs a new `Rc`, returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::rc::Rc; + /// + /// let five = Rc::try_new(5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn try_new(value: T) -> Result, AllocError> { + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + Ok(Self::from_inner( + Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?) + .into(), + )) + } + + /// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + unsafe { + Ok(Rc::from_ptr(Rc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + |mem| mem as *mut RcBox>, + )?)) + } + } + + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if the allocation fails + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::rc::Rc; + /// + /// let zero = Rc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + //#[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + unsafe { + Ok(Rc::from_ptr(Rc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + |mem| mem as *mut RcBox>, + )?)) + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `value` will be pinned in memory and unable to be moved. + #[stable(feature = "pin", since = "1.33.0")] + pub fn pin(value: T) -> Pin> { + unsafe { Pin::new_unchecked(Rc::new(value)) } + } + + /// Returns the inner value, if the `Rc` has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same `Rc` that was + /// passed in. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new(3); + /// assert_eq!(Rc::try_unwrap(x), Ok(3)); + /// + /// let x = Rc::new(4); + /// let _y = Rc::clone(&x); + /// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4); + /// ``` + #[inline] + #[stable(feature = "rc_unique", since = "1.4.0")] + pub fn try_unwrap(this: Self) -> Result { + if Rc::strong_count(&this) == 1 { + unsafe { + let val = ptr::read(&*this); // copy the contained object + + // Indicate to Weaks that they can't be promoted by decrementing + // the strong count, and then remove the implicit "strong weak" + // pointer while also handling drop logic by just crafting a + // fake Weak. + this.inner().dec_strong(); + let _weak = Weak { ptr: this.ptr }; + forget(this); + Ok(val) + } + } else { + Err(this) + } + } +} + +impl Rc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } + } + + /// Constructs a new reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// use std::rc::Rc; + /// + /// let values = Rc::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate_zeroed(layout), + |mem| { + ptr::slice_from_raw_parts_mut(mem as *mut T, len) + as *mut RcBox<[mem::MaybeUninit]> + }, + )) + } + } +} + +impl Rc> { + /// Converts to `Rc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc { + Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl Rc<[mem::MaybeUninit]> { + /// Converts to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T]> { + unsafe { Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } + } +} + +impl Rc { + /// Consumes the `Rc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Rc` using + /// [`Rc::from_raw`][from_raw]. + /// + /// [from_raw]: Rc::from_raw + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let x_ptr = Rc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr = Self::as_ptr(&this); + mem::forget(this); + ptr + } + + /// Provides a raw pointer to the data. + /// + /// The counts are not affected in any way and the `Rc` is not consumed. The pointer is valid + /// for as long there are strong counts in the `Rc`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let y = Rc::clone(&x); + /// let x_ptr = Rc::as_ptr(&x); + /// assert_eq!(x_ptr, Rc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn as_ptr(this: &Self) -> *const T { + let ptr: *mut RcBox = NonNull::as_ptr(this.ptr); + + // SAFETY: This cannot go through Deref::deref or Rc::inner because + // this is required to retain raw/mut provenance such that e.g. `get_mut` can + // write through the pointer after the Rc is recovered through `from_raw`. + unsafe { ptr::addr_of_mut!((*ptr).value) } + } + + /// Constructs an `Rc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// [`Rc::into_raw`][into_raw] where `U` must have the same size + /// and alignment as `T`. This is trivially true if `U` is `T`. + /// Note that if `U` is not `T` but has the same size and alignment, this is + /// basically like transmuting references of different types. See + /// [`mem::transmute`][transmute] for more information on what + /// restrictions apply in this case. + /// + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Rc` is never accessed. + /// + /// [into_raw]: Rc::into_raw + /// [transmute]: core::mem::transmute + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let x_ptr = Rc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Rc` to prevent leak. + /// let x = Rc::from_raw(x_ptr); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + let offset = unsafe { data_offset(ptr) }; + + // Reverse the offset to find the original RcBox. + let rc_ptr = + unsafe { (ptr as *mut RcBox).set_ptr_value((ptr as *mut u8).offset(-offset)) }; + + unsafe { Self::from_ptr(rc_ptr) } + } + + /// Creates a new [`Weak`] pointer to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// let weak_five = Rc::downgrade(&five); + /// ``` + #[stable(feature = "rc_weak", since = "1.4.0")] + pub fn downgrade(this: &Self) -> Weak { + this.inner().inc_weak(); + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr.as_ptr())); + Weak { ptr: this.ptr } + } + + /// Gets the number of [`Weak`] pointers to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// let _weak_five = Rc::downgrade(&five); + /// + /// assert_eq!(1, Rc::weak_count(&five)); + /// ``` + #[inline] + #[stable(feature = "rc_counts", since = "1.15.0")] + pub fn weak_count(this: &Self) -> usize { + this.inner().weak() - 1 + } + + /// Gets the number of strong (`Rc`) pointers to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// let _also_five = Rc::clone(&five); + /// + /// assert_eq!(2, Rc::strong_count(&five)); + /// ``` + #[inline] + #[stable(feature = "rc_counts", since = "1.15.0")] + pub fn strong_count(this: &Self) -> usize { + this.inner().strong() + } + + /// Increments the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, and the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count(ptr); + /// + /// let five = Rc::from_raw(ptr); + /// assert_eq!(2, Rc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] + pub unsafe fn increment_strong_count(ptr: *const T) { + // Retain Rc, but don't touch refcount by wrapping in ManuallyDrop + let rc = unsafe { mem::ManuallyDrop::new(Rc::::from_raw(ptr)) }; + // Now increase refcount, but don't drop new refcount either + let _rc_clone: mem::ManuallyDrop<_> = rc.clone(); + } + + /// Decrements the strong reference count on the `Rc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Rc::into_raw`, and the + /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method. This method can be used to release + /// the final `Rc` and backing storage, but **should not** be called after + /// the final `Rc` has been released. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// unsafe { + /// let ptr = Rc::into_raw(five); + /// Rc::increment_strong_count(ptr); + /// + /// let five = Rc::from_raw(ptr); + /// assert_eq!(2, Rc::strong_count(&five)); + /// Rc::decrement_strong_count(ptr); + /// assert_eq!(1, Rc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] + pub unsafe fn decrement_strong_count(ptr: *const T) { + unsafe { mem::drop(Rc::from_raw(ptr)) }; + } + + /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to + /// this allocation. + #[inline] + fn is_unique(this: &Self) -> bool { + Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 + } + + /// Returns a mutable reference into the given `Rc`, if there are + /// no other `Rc` or [`Weak`] pointers to the same allocation. + /// + /// Returns [`None`] otherwise, because it is not safe to + /// mutate a shared value. + /// + /// See also [`make_mut`][make_mut], which will [`clone`][clone] + /// the inner value when there are other pointers. + /// + /// [make_mut]: Rc::make_mut + /// [clone]: Clone::clone + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(3); + /// *Rc::get_mut(&mut x).unwrap() = 4; + /// assert_eq!(*x, 4); + /// + /// let _y = Rc::clone(&x); + /// assert!(Rc::get_mut(&mut x).is_none()); + /// ``` + #[inline] + #[stable(feature = "rc_unique", since = "1.4.0")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None } + } + + /// Returns a mutable reference into the given `Rc`, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: Rc::get_mut + /// + /// # Safety + /// + /// Any other `Rc` or [`Weak`] pointers to the same allocation must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + // We are careful to *not* create a reference covering the "count" fields, as + // this would conflict with accesses to the reference counts (e.g. by `Weak`). + unsafe { &mut (*this.ptr.as_ptr()).value } + } + + #[inline] + #[stable(feature = "ptr_eq", since = "1.17.0")] + /// Returns `true` if the two `Rc`s point to the same allocation + /// (in a vein similar to [`ptr::eq`]). + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// let same_five = Rc::clone(&five); + /// let other_five = Rc::new(5); + /// + /// assert!(Rc::ptr_eq(&five, &same_five)); + /// assert!(!Rc::ptr_eq(&five, &other_five)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr.as_ptr() == other.ptr.as_ptr() + } +} + +impl Rc { + /// Makes a mutable reference into the given `Rc`. + /// + /// If there are other `Rc` pointers to the same allocation, then `make_mut` will + /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also + /// referred to as clone-on-write. + /// + /// If there are no other `Rc` pointers to this allocation, then [`Weak`] + /// pointers to this allocation will be disassociated. + /// + /// See also [`get_mut`], which will fail rather than cloning. + /// + /// [`clone`]: Clone::clone + /// [`get_mut`]: Rc::get_mut + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut data = Rc::new(5); + /// + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = Rc::clone(&data); // Won't clone inner data + /// *Rc::make_mut(&mut data) += 1; // Clones inner data + /// *Rc::make_mut(&mut data) += 1; // Won't clone anything + /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Now `data` and `other_data` point to different allocations. + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); + /// ``` + /// + /// [`Weak`] pointers will be disassociated: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut data = Rc::new(75); + /// let weak = Rc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Rc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` + #[inline] + #[stable(feature = "rc_unique", since = "1.4.0")] + pub fn make_mut(this: &mut Self) -> &mut T { + if Rc::strong_count(this) != 1 { + // Gotta clone the data, there are other Rcs. + // Pre-allocate memory to allow writing the cloned value directly. + let mut rc = Self::new_uninit(); + unsafe { + let data = Rc::get_mut_unchecked(&mut rc); + (**this).write_clone_into_raw(data.as_mut_ptr()); + *this = rc.assume_init(); + } + } else if Rc::weak_count(this) != 0 { + // Can just steal the data, all that's left is Weaks + let mut rc = Self::new_uninit(); + unsafe { + let data = Rc::get_mut_unchecked(&mut rc); + data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1); + + this.inner().dec_strong(); + // Remove implicit strong-weak ref (no need to craft a fake + // Weak here -- we know other Weaks can clean up for us) + this.inner().dec_weak(); + ptr::write(this, rc.assume_init()); + } + } + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the `Rc` itself to be `mut`, so we're returning the only possible + // reference to the allocation. + unsafe { &mut this.ptr.as_mut().value } + } +} + +impl Rc { + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] + /// Attempt to downcast the `Rc` to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// use std::rc::Rc; + /// + /// fn print_if_string(value: Rc) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Rc::new(my_string)); + /// print_if_string(Rc::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Rc> { + if (*self).is::() { + let ptr = self.ptr.cast::>(); + forget(self); + Ok(Rc::from_inner(ptr)) + } else { + Err(self) + } + } +} + +impl Rc { + /// Allocates an `RcBox` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided. + /// + /// The function `mem_to_rcbox` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `RcBox`. + unsafe fn allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, + ) -> *mut RcBox { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcBox)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + unsafe { + Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox) + .unwrap_or_else(|_| handle_alloc_error(layout)) + } + } + + /// Allocates an `RcBox` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_rcbox` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `RcBox`. + #[inline] + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, + ) -> Result<*mut RcBox, AllocError> { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcBox)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + + // Allocate for the layout. + let ptr = allocate(layout)?; + + // Initialize the RcBox + let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr()); + unsafe { + debug_assert_eq!(Layout::for_value(&*inner), layout); + + ptr::write(&mut (*inner).strong, Cell::new(1)); + ptr::write(&mut (*inner).weak, Cell::new(1)); + } + + Ok(inner) + } + + /// Allocates an `RcBox` with sufficient space for an unsized inner value + unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { + // Allocate for the `RcBox` using the given value. + unsafe { + Self::allocate_for_layout( + Layout::for_value(&*ptr), + |layout| Global.allocate(layout), + |mem| (ptr as *mut RcBox).set_ptr_value(mem), + ) + } + } + + fn from_box(v: Box) -> Rc { + unsafe { + let (box_unique, alloc) = Box::into_unique(v); + let bptr = box_unique.as_ptr(); + + let value_size = size_of_val(&*bptr); + let ptr = Self::allocate_for_ptr(bptr); + + // Copy value as bytes + ptr::copy_nonoverlapping( + bptr as *const T as *const u8, + &mut (*ptr).value as *mut _ as *mut u8, + value_size, + ); + + // Free the allocation without dropping its contents + box_free(box_unique, alloc); + + Self::from_ptr(ptr) + } + } +} + +impl Rc<[T]> { + /// Allocates an `RcBox<[T]>` with the given length. + unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { + unsafe { + Self::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate(layout), + |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>, + ) + } + } + + /// Copy elements from slice into newly allocated Rc<\[T\]> + /// + /// Unsafe because the caller must either take ownership or bind `T: Copy` + unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { + unsafe { + let ptr = Self::allocate_for_slice(v.len()); + ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).value as *mut [T] as *mut T, v.len()); + Self::from_ptr(ptr) + } + } + + /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + unsafe fn from_iter_exact(iter: impl iter::Iterator, len: usize) -> Rc<[T]> { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new RcBox will be dropped, then the memory freed. + struct Guard { + mem: NonNull, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl Drop for Guard { + fn drop(&mut self) { + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Global.deallocate(self.mem, self.layout); + } + } + } + + unsafe { + let ptr = Self::allocate_for_slice(len); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); + + // Pointer to first element + let elems = &mut (*ptr).value as *mut [T] as *mut T; + + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new RcBox. + forget(guard); + + Self::from_ptr(ptr) + } + } +} + +/// Specialization trait used for `From<&[T]>`. +trait RcFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +impl RcFromSlice for Rc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } + } +} + +impl RcFromSlice for Rc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + unsafe { Rc::copy_from_slice(v) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Rc { + type Target = T; + + #[inline(always)] + fn deref(&self) -> &T { + &self.inner().value + } +} + +#[unstable(feature = "receiver_trait", issue = "none")] +impl Receiver for Rc {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { + /// Drops the `Rc`. + /// + /// This will decrement the strong reference count. If the strong reference + /// count reaches zero then the only other references (if any) are + /// [`Weak`], so we `drop` the inner value. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Rc::new(Foo); + /// let foo2 = Rc::clone(&foo); + /// + /// drop(foo); // Doesn't print anything + /// drop(foo2); // Prints "dropped!" + /// ``` + fn drop(&mut self) { + unsafe { + self.inner().dec_strong(); + if self.inner().strong() == 0 { + // destroy the contained object + ptr::drop_in_place(Self::get_mut_unchecked(self)); + + // remove the implicit "strong weak" pointer now that we've + // destroyed the contents. + self.inner().dec_weak(); + + if self.inner().weak() == 0 { + Global.deallocate(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())); + } + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Rc { + /// Makes a clone of the `Rc` pointer. + /// + /// This creates another pointer to the same allocation, increasing the + /// strong reference count. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// let _ = Rc::clone(&five); + /// ``` + #[inline] + fn clone(&self) -> Rc { + self.inner().inc_strong(); + Self::from_inner(self.ptr) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Rc { + /// Creates a new `Rc`, with the `Default` value for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x: Rc = Default::default(); + /// assert_eq!(*x, 0); + /// ``` + #[inline] + fn default() -> Rc { + Rc::new(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +trait RcEqIdent { + fn eq(&self, other: &Rc) -> bool; + fn ne(&self, other: &Rc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl RcEqIdent for Rc { + #[inline] + default fn eq(&self, other: &Rc) -> bool { + **self == **other + } + + #[inline] + default fn ne(&self, other: &Rc) -> bool { + **self != **other + } +} + +// Hack to allow specializing on `Eq` even though `Eq` has a method. +#[rustc_unsafe_specialization_marker] +pub(crate) trait MarkerEq: PartialEq {} + +impl MarkerEq for T {} + +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Rc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to +/// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. +#[stable(feature = "rust1", since = "1.0.0")] +impl RcEqIdent for Rc { + #[inline] + fn eq(&self, other: &Rc) -> bool { + Rc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Rc) -> bool { + !Rc::ptr_eq(self, other) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Rc { + /// Equality for two `Rc`s. + /// + /// Two `Rc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Rc`s that point to the same allocation are + /// always equal. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five == Rc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Rc) -> bool { + RcEqIdent::eq(self, other) + } + + /// Inequality for two `Rc`s. + /// + /// Two `Rc`s are unequal if their inner values are unequal. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Rc`s that point to the same allocation are + /// never unequal. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five != Rc::new(6)); + /// ``` + #[inline] + fn ne(&self, other: &Rc) -> bool { + RcEqIdent::ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Rc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Rc { + /// Partial comparison for two `Rc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// use std::cmp::Ordering; + /// + /// let five = Rc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Rc::new(6))); + /// ``` + #[inline(always)] + fn partial_cmp(&self, other: &Rc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `Rc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five < Rc::new(6)); + /// ``` + #[inline(always)] + fn lt(&self, other: &Rc) -> bool { + **self < **other + } + + /// 'Less than or equal to' comparison for two `Rc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five <= Rc::new(5)); + /// ``` + #[inline(always)] + fn le(&self, other: &Rc) -> bool { + **self <= **other + } + + /// Greater-than comparison for two `Rc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five > Rc::new(4)); + /// ``` + #[inline(always)] + fn gt(&self, other: &Rc) -> bool { + **self > **other + } + + /// 'Greater than or equal to' comparison for two `Rc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// assert!(five >= Rc::new(5)); + /// ``` + #[inline(always)] + fn ge(&self, other: &Rc) -> bool { + **self >= **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Rc { + /// Comparison for two `Rc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// use std::cmp::Ordering; + /// + /// let five = Rc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&Rc::new(6))); + /// ``` + #[inline] + fn cmp(&self, other: &Rc) -> Ordering { + (**self).cmp(&**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Rc { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Rc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Rc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Rc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&**self as *const T), f) + } +} + +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Rc { + fn from(t: T) -> Self { + Rc::new(t) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&[T]> for Rc<[T]> { + /// Allocate a reference-counted slice and fill it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: &[i32] = &[1, 2, 3]; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &[T]) -> Rc<[T]> { + >::from_slice(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&str> for Rc { + /// Allocate a reference-counted string slice and copy `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let shared: Rc = Rc::from("statue"); + /// assert_eq!("statue", &shared[..]); + /// ``` + #[inline] + fn from(v: &str) -> Rc { + let rc = Rc::<[u8]>::from(v.as_bytes()); + unsafe { Rc::from_raw(Rc::into_raw(rc) as *const str) } + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From for Rc { + /// Allocate a reference-counted string slice and copy `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: String = "statue".to_owned(); + /// let shared: Rc = Rc::from(original); + /// assert_eq!("statue", &shared[..]); + /// ``` + #[inline] + fn from(v: String) -> Rc { + Rc::from(&v[..]) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Rc { + /// Move a boxed object to a new, reference counted, allocation. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: Box = Box::new(1); + /// let shared: Rc = Rc::from(original); + /// assert_eq!(1, *shared); + /// ``` + #[inline] + fn from(v: Box) -> Rc { + Rc::from_box(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Rc<[T]> { + /// Allocate a reference-counted slice and move `v`'s items into it. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: Box> = Box::new(vec![1, 2, 3]); + /// let shared: Rc> = Rc::from(original); + /// assert_eq!(vec![1, 2, 3], *shared); + /// ``` + #[inline] + fn from(mut v: Vec) -> Rc<[T]> { + unsafe { + let rc = Rc::copy_from_slice(&v); + + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + + rc + } + } +} + +#[stable(feature = "shared_from_cow", since = "1.45.0")] +impl<'a, B> From> for Rc +where + B: ToOwned + ?Sized, + Rc: From<&'a B> + From, +{ + #[inline] + fn from(cow: Cow<'a, B>) -> Rc { + match cow { + Cow::Borrowed(s) => Rc::from(s), + Cow::Owned(s) => Rc::from(s), + } + } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Rc<[T; N]> { + type Error = Rc<[T]>; + + fn try_from(boxed_slice: Rc<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl iter::FromIterator for Rc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Rc<[T]>` is done by first + /// collecting into a `Vec`. That is, when writing the following: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Rc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec` + /// and then it will allocate once for turning the `Vec` into the `Rc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Rc<[T]>`. For example: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::>()); + /// ``` + fn from_iter>(iter: I) -> Self { + ToRcSlice::to_rc_slice(iter.into_iter()) + } +} + +/// Specialization trait used for collecting into `Rc<[T]>`. +trait ToRcSlice: Iterator + Sized { + fn to_rc_slice(self) -> Rc<[T]>; +} + +impl> ToRcSlice for I { + default fn to_rc_slice(self) -> Rc<[T]> { + self.collect::>().into() + } +} + +impl> ToRcSlice for I { + fn to_rc_slice(self) -> Rc<[T]> { + // This is the case for a `TrustedLen` iterator. + let (low, high) = self.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, + high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + + unsafe { + // SAFETY: We need to ensure that the iterator has an exact length and we have. + Rc::from_iter_exact(self, low) + } + } else { + // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); + } + } +} + +/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the +/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [`Option`]`<`[`Rc`]`>`. +/// +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. +/// +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Rc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Rc`] pointers, since mutual owning references +/// would never allow either [`Rc`] to be dropped. For example, a tree could +/// have strong [`Rc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. +/// +/// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`]. +/// +/// [`upgrade`]: Weak::upgrade +#[stable(feature = "rc_weak", since = "1.4.0")] +pub struct Weak { + // This is a `NonNull` to allow optimizing the size of this type in enums, + // but it is not necessarily a valid pointer. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real pointer + // will ever have because RcBox has alignment at least 2. + // This is only possible when `T: Sized`; unsized `T` never dangle. + ptr: NonNull>, +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl !marker::Send for Weak {} +#[stable(feature = "rc_weak", since = "1.4.0")] +impl !marker::Sync for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized> for Weak {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Weak {} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::rc::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[stable(feature = "downgraded_weak", since = "1.10.0")] + pub fn new() -> Weak { + Weak { ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0") } + } +} + +pub(crate) fn is_dangling(ptr: *mut T) -> bool { + let address = ptr as *mut () as usize; + address == usize::MAX +} + +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a Cell, + strong: &'a Cell, +} + +impl Weak { + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// use std::ptr; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_ptr())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// ``` + /// + /// [`null`]: core::ptr::null + #[stable(feature = "rc_as_ptr", since = "1.45.0")] + pub fn as_ptr(&self) -> *const T { + let ptr: *mut RcBox = NonNull::as_ptr(self.ptr); + + if is_dangling(ptr) { + // If the pointer is dangling, we return the sentinel directly. This cannot be + // a valid payload address, as the payload is at least as aligned as RcBox (usize). + ptr as *const T + } else { + // SAFETY: if is_dangling returns false, then the pointer is dereferencable. + // The payload may be dropped at this point, and we have to maintain provenance, + // so use raw pointer manipulation. + unsafe { ptr::addr_of_mut!((*ptr).value) } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + let result = self.as_ptr(); + mem::forget(self); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// + /// let raw_1 = Rc::downgrade(&strong).into_raw(); + /// let raw_2 = Rc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Rc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Rc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + /// [`new`]: Weak::new + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + // See Weak::as_ptr for context on how the input pointer is derived. + + let ptr = if is_dangling(ptr as *mut T) { + // This is a dangling Weak. + ptr as *mut RcBox + } else { + // Otherwise, we're guaranteed the pointer came from a nondangling Weak. + // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. + let offset = unsafe { data_offset(ptr) }; + // Thus, we reverse the offset to get the whole RcBox. + // SAFETY: the pointer originated from a Weak, so this offset is safe. + unsafe { (ptr as *mut RcBox).set_ptr_value((ptr as *mut u8).offset(-offset)) } + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } } + } + + /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying + /// dropping of the inner value if successful. + /// + /// Returns [`None`] if the inner value has since been dropped. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let five = Rc::new(5); + /// + /// let weak_five = Rc::downgrade(&five); + /// + /// let strong_five: Option> = weak_five.upgrade(); + /// assert!(strong_five.is_some()); + /// + /// // Destroy all strong pointers. + /// drop(strong_five); + /// drop(five); + /// + /// assert!(weak_five.upgrade().is_none()); + /// ``` + #[stable(feature = "rc_weak", since = "1.4.0")] + pub fn upgrade(&self) -> Option> { + let inner = self.inner()?; + if inner.strong() == 0 { + None + } else { + inner.inc_strong(); + Some(Rc::from_inner(self.ptr)) + } + } + + /// Gets the number of strong (`Rc`) pointers pointing to this allocation. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { inner.strong() } else { 0 } + } + + /// Gets the number of `Weak` pointers pointing to this allocation. + /// + /// If no strong pointers remain, this will return zero. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { + self.inner() + .map(|inner| { + if inner.strong() > 0 { + inner.weak() - 1 // subtract the implicit weak ptr + } else { + 0 + } + }) + .unwrap_or(0) + } + + /// Returns `None` when the pointer is dangling and there is no allocated `RcBox`, + /// (i.e., when this `Weak` was created by `Weak::new`). + #[inline] + fn inner(&self) -> Option> { + if is_dangling(self.ptr.as_ptr()) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Rc` + // is dropped, the data field will be dropped in-place). + Some(unsafe { + let ptr = self.ptr.as_ptr(); + WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } + }) + } + } + + /// Returns `true` if the two `Weak`s point to the same allocation (similar to + /// [`ptr::eq`]), or if both don't point to any allocation + /// (because they were created with `Weak::new()`). + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let first_rc = Rc::new(5); + /// let first = Rc::downgrade(&first_rc); + /// let second = Rc::downgrade(&first_rc); + /// + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Rc::new(5); + /// let third = Rc::downgrade(&third_rc); + /// + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Rc::new(()); + /// let third = Rc::downgrade(&third_rc); + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq + #[inline] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] + pub fn ptr_eq(&self, other: &Self) -> bool { + self.ptr.as_ptr() == other.ptr.as_ptr() + } +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl Drop for Weak { + /// Drops the `Weak` pointer. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Rc::new(Foo); + /// let weak_foo = Rc::downgrade(&foo); + /// let other_weak_foo = Weak::clone(&weak_foo); + /// + /// drop(weak_foo); // Doesn't print anything + /// drop(foo); // Prints "dropped!" + /// + /// assert!(other_weak_foo.upgrade().is_none()); + /// ``` + fn drop(&mut self) { + let inner = if let Some(inner) = self.inner() { inner } else { return }; + + inner.dec_weak(); + // the weak count starts at 1, and will only go to zero if all + // the strong pointers have disappeared. + if inner.weak() == 0 { + unsafe { + Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())); + } + } + } +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl Clone for Weak { + /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// + /// # Examples + /// + /// ``` + /// use std::rc::{Rc, Weak}; + /// + /// let weak_five = Rc::downgrade(&Rc::new(5)); + /// + /// let _ = Weak::clone(&weak_five); + /// ``` + #[inline] + fn clone(&self) -> Weak { + if let Some(inner) = self.inner() { + inner.inc_weak() + } + Weak { ptr: self.ptr } + } +} + +#[stable(feature = "rc_weak", since = "1.4.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(Weak)") + } +} + +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`None`]: Option + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::rc::Weak; + /// + /// let empty: Weak = Default::default(); + /// assert!(empty.upgrade().is_none()); + /// ``` + fn default() -> Weak { + Weak::new() + } +} + +// NOTE: We checked_add here to deal with mem::forget safely. In particular +// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then +// you can free the allocation while outstanding Rcs (or Weaks) exist. +// We abort because this is such a degenerate scenario that we don't care about +// what happens -- no real program should ever experience this. +// +// This should have negligible overhead since you don't actually need to +// clone these much in Rust thanks to ownership and move-semantics. + +#[doc(hidden)] +trait RcInnerPtr { + fn weak_ref(&self) -> &Cell; + fn strong_ref(&self) -> &Cell; + + #[inline] + fn strong(&self) -> usize { + self.strong_ref().get() + } + + #[inline] + fn inc_strong(&self) { + let strong = self.strong(); + + // We want to abort on overflow instead of dropping the value. + // The reference count will never be zero when this is called; + // nevertheless, we insert an abort here to hint LLVM at + // an otherwise missed optimization. + if strong == 0 || strong == usize::MAX { + abort(); + } + self.strong_ref().set(strong + 1); + } + + #[inline] + fn dec_strong(&self) { + self.strong_ref().set(self.strong() - 1); + } + + #[inline] + fn weak(&self) -> usize { + self.weak_ref().get() + } + + #[inline] + fn inc_weak(&self) { + let weak = self.weak(); + + // We want to abort on overflow instead of dropping the value. + // The reference count will never be zero when this is called; + // nevertheless, we insert an abort here to hint LLVM at + // an otherwise missed optimization. + if weak == 0 || weak == usize::MAX { + abort(); + } + self.weak_ref().set(weak + 1); + } + + #[inline] + fn dec_weak(&self) { + self.weak_ref().set(self.weak() - 1); + } +} + +impl RcInnerPtr for RcBox { + #[inline(always)] + fn weak_ref(&self) -> &Cell { + &self.weak + } + + #[inline(always)] + fn strong_ref(&self) -> &Cell { + &self.strong + } +} + +impl<'a> RcInnerPtr for WeakInner<'a> { + #[inline(always)] + fn weak_ref(&self) -> &Cell { + self.weak + } + + #[inline(always)] + fn strong_ref(&self) -> &Cell { + self.strong + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl borrow::Borrow for Rc { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Rc { + fn as_ref(&self) -> &T { + &**self + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Rc {} + +/// Get the offset within an `RcBox` for the payload behind a pointer. +/// +/// # Safety +/// +/// The pointer must point to (and have valid metadata for) a previously +/// valid instance of T, but the T is allowed to be dropped. +unsafe fn data_offset(ptr: *const T) -> isize { + // Align the unsized value to the end of the RcBox. + // Because RcBox is repr(C), it will always be the last field in memory. + // SAFETY: since the only unsized types possible are slices, trait objects, + // and extern types, the input safety requirement is currently enough to + // satisfy the requirements of align_of_val_raw; this is an implementation + // detail of the language that may not be relied upon outside of std. + unsafe { data_offset_align(align_of_val_raw(ptr)) } +} + +#[inline] +fn data_offset_align(align: usize) -> isize { + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} +//! A dynamically-sized view into a contiguous sequence, `[T]`. +//! +//! *[See also the slice primitive type](slice).* +//! +//! Slices are a view into a block of memory represented as a pointer and a +//! length. +//! +//! ``` +//! // slicing a Vec +//! let vec = vec![1, 2, 3]; +//! let int_slice = &vec[..]; +//! // coercing an array to a slice +//! let str_slice: &[&str] = &["one", "two", "three"]; +//! ``` +//! +//! Slices are either mutable or shared. The shared slice type is `&[T]`, +//! while the mutable slice type is `&mut [T]`, where `T` represents the element +//! type. For example, you can mutate the block of memory that a mutable slice +//! points to: +//! +//! ``` +//! let x = &mut [1, 2, 3]; +//! x[1] = 7; +//! assert_eq!(x, &[1, 7, 3]); +//! ``` +//! +//! Here are some of the things this module contains: +//! +//! ## Structs +//! +//! There are several structs that are useful for slices, such as [`Iter`], which +//! represents iteration over a slice. +//! +//! ## Trait Implementations +//! +//! There are several implementations of common traits for slices. Some examples +//! include: +//! +//! * [`Clone`] +//! * [`Eq`], [`Ord`] - for slices whose element type are [`Eq`] or [`Ord`]. +//! * [`Hash`] - for slices whose element type is [`Hash`]. +//! +//! ## Iteration +//! +//! The slices implement `IntoIterator`. The iterator yields references to the +//! slice elements. +//! +//! ``` +//! let numbers = &[0, 1, 2]; +//! for n in numbers { +//! println!("{} is a number!", n); +//! } +//! ``` +//! +//! The mutable slice yields mutable references to the elements: +//! +//! ``` +//! let mut scores = [7, 8, 9]; +//! for score in &mut scores[..] { +//! *score += 1; +//! } +//! ``` +//! +//! This iterator yields mutable references to the slice's elements, so while +//! the element type of the slice is `i32`, the element type of the iterator is +//! `&mut i32`. +//! +//! * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default +//! iterators. +//! * Further methods that return iterators are [`.split`], [`.splitn`], +//! [`.chunks`], [`.windows`] and more. +//! +//! [`Hash`]: core::hash::Hash +//! [`.iter`]: slice::iter +//! [`.iter_mut`]: slice::iter_mut +//! [`.split`]: slice::split +//! [`.splitn`]: slice::splitn +//! [`.chunks`]: slice::chunks +//! [`.windows`]: slice::windows +#![stable(feature = "rust1", since = "1.0.0")] +// Many of the usings in this module are only used in the test configuration. +// It's cleaner to just turn off the unused_imports warning than to fix them. +#![cfg_attr(test, allow(unused_imports, dead_code))] + +use core::borrow::{Borrow, BorrowMut}; +use core::cmp::Ordering::{self, Less}; +use core::mem::{self, size_of}; +use core::ptr; + +use crate::alloc::{Allocator, Global}; +use crate::borrow::ToOwned; +use crate::boxed::Box; +use crate::vec::Vec; + +#[unstable(feature = "slice_range", issue = "76393")] +pub use core::slice::range; +#[unstable(feature = "array_chunks", issue = "74985")] +pub use core::slice::ArrayChunks; +#[unstable(feature = "array_chunks", issue = "74985")] +pub use core::slice::ArrayChunksMut; +#[unstable(feature = "array_windows", issue = "75027")] +pub use core::slice::ArrayWindows; +#[stable(feature = "slice_get_slice", since = "1.28.0")] +pub use core::slice::SliceIndex; +#[stable(feature = "from_ref", since = "1.28.0")] +pub use core::slice::{from_mut, from_ref}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{from_raw_parts, from_raw_parts_mut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{Chunks, Windows}; +#[stable(feature = "chunks_exact", since = "1.31.0")] +pub use core::slice::{ChunksExact, ChunksExactMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{ChunksMut, Split, SplitMut}; +#[unstable(feature = "slice_group_by", issue = "80552")] +pub use core::slice::{GroupBy, GroupByMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{Iter, IterMut}; +#[stable(feature = "rchunks", since = "1.31.0")] +pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; +#[stable(feature = "slice_rsplit", since = "1.27.0")] +pub use core::slice::{RSplit, RSplitMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; + +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// + +// HACK(japaric) needed for the implementation of `vec!` macro during testing +// N.B., see the `hack` module in this file for more details. +#[cfg(test)] +pub use hack::into_vec; + +// HACK(japaric) needed for the implementation of `Vec::clone` during testing +// N.B., see the `hack` module in this file for more details. +#[cfg(test)] +pub use hack::to_vec; + +// HACK(japaric): With cfg(test) `impl [T]` is not available, these three +// functions are actually methods that are in `impl [T]` but not in +// `core::slice::SliceExt` - we need to supply these functions for the +// `test_permutations` test +mod hack { + use core::alloc::Allocator; + + use crate::boxed::Box; + use crate::vec::Vec; + + // We shouldn't add inline attribute to this since this is used in + // `vec!` macro mostly and causes perf regression. See #71204 for + // discussion and perf results. + pub fn into_vec(b: Box<[T], A>) -> Vec { + unsafe { + let len = b.len(); + let (b, alloc) = Box::into_raw_with_allocator(b); + Vec::from_raw_parts_in(b as *mut T, len, len, alloc) + } + } + + #[inline] + pub fn to_vec(s: &[T], alloc: A) -> Vec { + T::to_vec(s, alloc) + } + + pub trait ConvertVec { + fn to_vec(s: &[Self], alloc: A) -> Vec + where + Self: Sized; + } + + impl ConvertVec for T { + #[inline] + default fn to_vec(s: &[Self], alloc: A) -> Vec { + struct DropGuard<'a, T, A: Allocator> { + vec: &'a mut Vec, + num_init: usize, + } + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { + #[inline] + fn drop(&mut self) { + // SAFETY: + // items were marked initialized in the loop below + unsafe { + self.vec.set_len(self.num_init); + } + } + } + let mut vec = Vec::with_capacity_in(s.len(), alloc); + let mut guard = DropGuard { vec: &mut vec, num_init: 0 }; + let slots = guard.vec.spare_capacity_mut(); + // .take(slots.len()) is necessary for LLVM to remove bounds checks + // and has better codegen than zip. + for (i, b) in s.iter().enumerate().take(slots.len()) { + guard.num_init = i; + slots[i].write(b.clone()); + } + core::mem::forget(guard); + // SAFETY: + // the vec was allocated and initialized above to at least this length. + unsafe { + vec.set_len(s.len()); + } + vec + } + } + + impl ConvertVec for T { + #[inline] + fn to_vec(s: &[Self], alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(s.len(), alloc); + // SAFETY: + // allocated above with the capacity of `s`, and initialize to `s.len()` in + // ptr::copy_to_non_overlapping below. + unsafe { + s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len()); + v.set_len(s.len()); + } + v + } + } +} + +#[lang = "slice_alloc"] +#[cfg(not(test))] +impl [T] { + /// Sorts the slice. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case. + /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable`](slice::sort_unstable). + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. + /// + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert!(v == [-5, -3, 1, 2, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort(&mut self) + where + T: Ord, + { + merge_sort(self, |a, b| a.lt(b)); + } + + /// Sorts the slice with a comparator function. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case. + /// + /// The comparator function must define a total ordering for the elements in the slice. If + /// the ordering is not total, the order of the elements is unspecified. An order is a + /// total order if it is (for all `a`, `b` and `c`): + /// + /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and + /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. + /// + /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use + /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. + /// + /// ``` + /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0]; + /// floats.sort_by(|a, b| a.partial_cmp(b).unwrap()); + /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]); + /// ``` + /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by`](slice::sort_unstable_by). + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. + /// + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. + /// + /// # Examples + /// + /// ``` + /// let mut v = [5, 4, 1, 3, 2]; + /// v.sort_by(|a, b| a.cmp(b)); + /// assert!(v == [1, 2, 3, 4, 5]); + /// + /// // reverse sorting + /// v.sort_by(|a, b| b.cmp(a)); + /// assert!(v == [5, 4, 3, 2, 1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sort_by(&mut self, mut compare: F) + where + F: FnMut(&T, &T) -> Ordering, + { + merge_sort(self, |a, b| compare(a, b) == Less); + } + + /// Sorts the slice with a key extraction function. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*)) + /// worst-case, where the key function is *O*(*m*). + /// + /// For expensive key functions (e.g. functions that are not simple property accesses or + /// basic operations), [`sort_by_cached_key`](slice::sort_by_cached_key) is likely to be + /// significantly faster, as it does not recompute element keys. + /// + /// When applicable, unstable sorting is preferred because it is generally faster than stable + /// sorting and it doesn't allocate auxiliary memory. + /// See [`sort_unstable_by_key`](slice::sort_unstable_by_key). + /// + /// # Current implementation + /// + /// The current algorithm is an adaptive, iterative merge sort inspired by + /// [timsort](https://en.wikipedia.org/wiki/Timsort). + /// It is designed to be very fast in cases where the slice is nearly sorted, or consists of + /// two or more sorted sequences concatenated one after another. + /// + /// Also, it allocates temporary storage half the size of `self`, but for short slices a + /// non-allocating insertion sort is used instead. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 1, -3, 2]; + /// + /// v.sort_by_key(|k| k.abs()); + /// assert!(v == [1, 2, -3, 4, -5]); + /// ``` + #[stable(feature = "slice_sort_by_key", since = "1.7.0")] + #[inline] + pub fn sort_by_key(&mut self, mut f: F) + where + F: FnMut(&T) -> K, + K: Ord, + { + merge_sort(self, |a, b| f(a).lt(&f(b))); + } + + /// Sorts the slice with a key extraction function. + /// + /// During sorting, the key function is called only once per element. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* + *n* \* log(*n*)) + /// worst-case, where the key function is *O*(*m*). + /// + /// For simple key functions (e.g., functions that are property accesses or + /// basic operations), [`sort_by_key`](slice::sort_by_key) is likely to be + /// faster. + /// + /// # Current implementation + /// + /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters, + /// which combines the fast average case of randomized quicksort with the fast worst case of + /// heapsort, while achieving linear time on slices with certain patterns. It uses some + /// randomization to avoid degenerate cases, but with a fixed seed to always provide + /// deterministic behavior. + /// + /// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the + /// length of the slice. + /// + /// # Examples + /// + /// ``` + /// let mut v = [-5i32, 4, 32, -3, 2]; + /// + /// v.sort_by_cached_key(|k| k.to_string()); + /// assert!(v == [-3, -5, 2, 32, 4]); + /// ``` + /// + /// [pdqsort]: https://github.com/orlp/pdqsort + #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] + #[inline] + pub fn sort_by_cached_key(&mut self, f: F) + where + F: FnMut(&T) -> K, + K: Ord, + { + // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. + macro_rules! sort_by_key { + ($t:ty, $slice:ident, $f:ident) => {{ + let mut indices: Vec<_> = + $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); + // The elements of `indices` are unique, as they are indexed, so any sort will be + // stable with respect to the original slice. We use `sort_unstable` here because + // it requires less memory allocation. + indices.sort_unstable(); + for i in 0..$slice.len() { + let mut index = indices[i].1; + while (index as usize) < i { + index = indices[index as usize].1; + } + indices[i].1 = index; + $slice.swap(i, index as usize); + } + }}; + } + + let sz_u8 = mem::size_of::<(K, u8)>(); + let sz_u16 = mem::size_of::<(K, u16)>(); + let sz_u32 = mem::size_of::<(K, u32)>(); + let sz_usize = mem::size_of::<(K, usize)>(); + + let len = self.len(); + if len < 2 { + return; + } + if sz_u8 < sz_u16 && len <= (u8::MAX as usize) { + return sort_by_key!(u8, self, f); + } + if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { + return sort_by_key!(u16, self, f); + } + if sz_u32 < sz_usize && len <= (u32::MAX as usize) { + return sort_by_key!(u32, self, f); + } + sort_by_key!(usize, self, f) + } + + /// Copies `self` into a new `Vec`. + /// + /// # Examples + /// + /// ``` + /// let s = [10, 40, 30]; + /// let x = s.to_vec(); + /// // Here, `s` and `x` can be modified independently. + /// ``` + #[rustc_conversion_suggestion] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_vec(&self) -> Vec + where + T: Clone, + { + self.to_vec_in(Global) + } + + /// Copies `self` into a new `Vec` with an allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let s = [10, 40, 30]; + /// let x = s.to_vec_in(System); + /// // Here, `s` and `x` can be modified independently. + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn to_vec_in(&self, alloc: A) -> Vec + where + T: Clone, + { + // N.B., see the `hack` module in this file for more details. + hack::to_vec(self, alloc) + } + + /// Converts `self` into a vector without clones or allocation. + /// + /// The resulting vector can be converted back into a box via + /// `Vec`'s `into_boxed_slice` method. + /// + /// # Examples + /// + /// ``` + /// let s: Box<[i32]> = Box::new([10, 40, 30]); + /// let x = s.into_vec(); + /// // `s` cannot be used anymore because it has been converted into `x`. + /// + /// assert_eq!(x, vec![10, 40, 30]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn into_vec(self: Box) -> Vec { + // N.B., see the `hack` module in this file for more details. + hack::into_vec(self) + } + + /// Creates a vector by repeating a slice `n` times. + /// + /// # Panics + /// + /// This function will panic if the capacity would overflow. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); + /// ``` + /// + /// A panic upon overflow: + /// + /// ```should_panic + /// // this will panic at runtime + /// b"0123456789abcdef".repeat(usize::MAX); + /// ``` + #[stable(feature = "repeat_generic_slice", since = "1.40.0")] + pub fn repeat(&self, n: usize) -> Vec + where + T: Copy, + { + if n == 0 { + return Vec::new(); + } + + // If `n` is larger than zero, it can be split as + // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`. + // `2^expn` is the number represented by the leftmost '1' bit of `n`, + // and `rem` is the remaining part of `n`. + + // Using `Vec` to access `set_len()`. + let capacity = self.len().checked_mul(n).expect("capacity overflow"); + let mut buf = Vec::with_capacity(capacity); + + // `2^expn` repetition is done by doubling `buf` `expn`-times. + buf.extend(self); + { + let mut m = n >> 1; + // If `m > 0`, there are remaining bits up to the leftmost '1'. + while m > 0 { + // `buf.extend(buf)`: + unsafe { + ptr::copy_nonoverlapping( + buf.as_ptr(), + (buf.as_mut_ptr() as *mut T).add(buf.len()), + buf.len(), + ); + // `buf` has capacity of `self.len() * n`. + let buf_len = buf.len(); + buf.set_len(buf_len * 2); + } + + m >>= 1; + } + } + + // `rem` (`= n - 2^expn`) repetition is done by copying + // first `rem` repetitions from `buf` itself. + let rem_len = capacity - buf.len(); // `self.len() * rem` + if rem_len > 0 { + // `buf.extend(buf[0 .. rem_len])`: + unsafe { + // This is non-overlapping since `2^expn > rem`. + ptr::copy_nonoverlapping( + buf.as_ptr(), + (buf.as_mut_ptr() as *mut T).add(buf.len()), + rem_len, + ); + // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`). + buf.set_len(capacity); + } + } + buf + } + + /// Flattens a slice of `T` into a single value `Self::Output`. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(["hello", "world"].concat(), "helloworld"); + /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn concat(&self) -> >::Output + where + Self: Concat, + { + Concat::concat(self) + } + + /// Flattens a slice of `T` into a single value `Self::Output`, placing a + /// given separator between each. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(["hello", "world"].join(" "), "hello world"); + /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); + /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]); + /// ``` + #[stable(feature = "rename_connect_to_join", since = "1.3.0")] + pub fn join(&self, sep: Separator) -> >::Output + where + Self: Join, + { + Join::join(self, sep) + } + + /// Flattens a slice of `T` into a single value `Self::Output`, placing a + /// given separator between each. + /// + /// # Examples + /// + /// ``` + /// # #![allow(deprecated)] + /// assert_eq!(["hello", "world"].connect(" "), "hello world"); + /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] + pub fn connect(&self, sep: Separator) -> >::Output + where + Self: Join, + { + Join::join(self, sep) + } +} + +#[lang = "slice_u8_alloc"] +#[cfg(not(test))] +impl [u8] { + /// Returns a vector containing a copy of this slice where each byte + /// is mapped to its ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_uppercase(&self) -> Vec { + let mut me = self.to_vec(); + me.make_ascii_uppercase(); + me + } + + /// Returns a vector containing a copy of this slice where each byte + /// is mapped to its ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase + #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[inline] + pub fn to_ascii_lowercase(&self) -> Vec { + let mut me = self.to_vec(); + me.make_ascii_lowercase(); + me + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Extension traits for slices over specific kinds of data +//////////////////////////////////////////////////////////////////////////////// + +/// Helper trait for [`[T]::concat`](slice::concat). +/// +/// Note: the `Item` type parameter is not used in this trait, +/// but it allows impls to be more generic. +/// Without it, we get this error: +/// +/// ```error +/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica +/// --> src/liballoc/slice.rs:608:6 +/// | +/// 608 | impl> Concat for [V] { +/// | ^ unconstrained type parameter +/// ``` +/// +/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls, +/// such that multiple `T` types would apply: +/// +/// ``` +/// # #[allow(dead_code)] +/// pub struct Foo(Vec, Vec); +/// +/// impl std::borrow::Borrow<[u32]> for Foo { +/// fn borrow(&self) -> &[u32] { &self.0 } +/// } +/// +/// impl std::borrow::Borrow<[String]> for Foo { +/// fn borrow(&self) -> &[String] { &self.1 } +/// } +/// ``` +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Concat { + #[unstable(feature = "slice_concat_trait", issue = "27747")] + /// The resulting type after concatenation + type Output; + + /// Implementation of [`[T]::concat`](slice::concat) + #[unstable(feature = "slice_concat_trait", issue = "27747")] + fn concat(slice: &Self) -> Self::Output; +} + +/// Helper trait for [`[T]::join`](slice::join) +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Join { + #[unstable(feature = "slice_concat_trait", issue = "27747")] + /// The resulting type after concatenation + type Output; + + /// Implementation of [`[T]::join`](slice::join) + #[unstable(feature = "slice_concat_trait", issue = "27747")] + fn join(slice: &Self, sep: Separator) -> Self::Output; +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Concat for [V] { + type Output = Vec; + + fn concat(slice: &Self) -> Vec { + let size = slice.iter().map(|slice| slice.borrow().len()).sum(); + let mut result = Vec::with_capacity(size); + for v in slice { + result.extend_from_slice(v.borrow()) + } + result + } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&T> for [V] { + type Output = Vec; + + fn join(slice: &Self, sep: &T) -> Vec { + let mut iter = slice.iter(); + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + let size = slice.iter().map(|v| v.borrow().len()).sum::() + slice.len() - 1; + let mut result = Vec::with_capacity(size); + result.extend_from_slice(first.borrow()); + + for v in iter { + result.push(sep.clone()); + result.extend_from_slice(v.borrow()) + } + result + } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&[T]> for [V] { + type Output = Vec; + + fn join(slice: &Self, sep: &[T]) -> Vec { + let mut iter = slice.iter(); + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + let size = + slice.iter().map(|v| v.borrow().len()).sum::() + sep.len() * (slice.len() - 1); + let mut result = Vec::with_capacity(size); + result.extend_from_slice(first.borrow()); + + for v in iter { + result.extend_from_slice(sep); + result.extend_from_slice(v.borrow()) + } + result + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Standard trait implementations for slices +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow<[T]> for Vec { + fn borrow(&self) -> &[T] { + &self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut<[T]> for Vec { + fn borrow_mut(&mut self) -> &mut [T] { + &mut self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for [T] { + type Owned = Vec; + #[cfg(not(test))] + fn to_owned(&self) -> Vec { + self.to_vec() + } + + #[cfg(test)] + fn to_owned(&self) -> Vec { + hack::to_vec(self, Global) + } + + fn clone_into(&self, target: &mut Vec) { + // drop anything in target that will not be overwritten + target.truncate(self.len()); + + // target.len <= self.len due to the truncate above, so the + // slices here are always in-bounds. + let (init, tail) = self.split_at(target.len()); + + // reuse the contained values' allocations/resources. + target.clone_from_slice(init); + target.extend_from_slice(tail); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Sorting +//////////////////////////////////////////////////////////////////////////////// + +/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted. +/// +/// This is the integral subroutine of insertion sort. +fn insert_head(v: &mut [T], is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + if v.len() >= 2 && is_less(&v[1], &v[0]) { + unsafe { + // There are three ways to implement insertion here: + // + // 1. Swap adjacent elements until the first one gets to its final destination. + // However, this way we copy data around more than is necessary. If elements are big + // structures (costly to copy), this method will be slow. + // + // 2. Iterate until the right place for the first element is found. Then shift the + // elements succeeding it to make room for it and finally place it into the + // remaining hole. This is a good method. + // + // 3. Copy the first element into a temporary variable. Iterate until the right place + // for it is found. As we go along, copy every traversed element into the slot + // preceding it. Finally, copy data from the temporary variable into the remaining + // hole. This method is very good. Benchmarks demonstrated slightly better + // performance than with the 2nd method. + // + // All methods were benchmarked, and the 3rd showed best results. So we chose that one. + let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0])); + + // Intermediate state of the insertion process is always tracked by `hole`, which + // serves two purposes: + // 1. Protects integrity of `v` from panics in `is_less`. + // 2. Fills the remaining hole in `v` in the end. + // + // Panic safety: + // + // If `is_less` panics at any point during the process, `hole` will get dropped and + // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it + // initially held exactly once. + let mut hole = InsertionHole { src: &mut *tmp, dest: &mut v[1] }; + ptr::copy_nonoverlapping(&v[1], &mut v[0], 1); + + for i in 2..v.len() { + if !is_less(&v[i], &*tmp) { + break; + } + ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1); + hole.dest = &mut v[i]; + } + // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`. + } + } + + // When dropped, copies from `src` into `dest`. + struct InsertionHole { + src: *mut T, + dest: *mut T, + } + + impl Drop for InsertionHole { + fn drop(&mut self) { + unsafe { + ptr::copy_nonoverlapping(self.src, self.dest, 1); + } + } + } +} + +/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `buf` as temporary storage, and +/// stores the result into `v[..]`. +/// +/// # Safety +/// +/// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough +/// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type. +unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + let v = v.as_mut_ptr(); + let (v_mid, v_end) = unsafe { (v.add(mid), v.add(len)) }; + + // The merge process first copies the shorter run into `buf`. Then it traces the newly copied + // run and the longer run forwards (or backwards), comparing their next unconsumed elements and + // copying the lesser (or greater) one into `v`. + // + // As soon as the shorter run is fully consumed, the process is done. If the longer run gets + // consumed first, then we must copy whatever is left of the shorter run into the remaining + // hole in `v`. + // + // Intermediate state of the process is always tracked by `hole`, which serves two purposes: + // 1. Protects integrity of `v` from panics in `is_less`. + // 2. Fills the remaining hole in `v` if the longer run gets consumed first. + // + // Panic safety: + // + // If `is_less` panics at any point during the process, `hole` will get dropped and fill the + // hole in `v` with the unconsumed range in `buf`, thus ensuring that `v` still holds every + // object it initially held exactly once. + let mut hole; + + if mid <= len - mid { + // The left run is shorter. + unsafe { + ptr::copy_nonoverlapping(v, buf, mid); + hole = MergeHole { start: buf, end: buf.add(mid), dest: v }; + } + + // Initially, these pointers point to the beginnings of their arrays. + let left = &mut hole.start; + let mut right = v_mid; + let out = &mut hole.dest; + + while *left < hole.end && right < v_end { + // Consume the lesser side. + // If equal, prefer the left run to maintain stability. + unsafe { + let to_copy = if is_less(&*right, &**left) { + get_and_increment(&mut right) + } else { + get_and_increment(left) + }; + ptr::copy_nonoverlapping(to_copy, get_and_increment(out), 1); + } + } + } else { + // The right run is shorter. + unsafe { + ptr::copy_nonoverlapping(v_mid, buf, len - mid); + hole = MergeHole { start: buf, end: buf.add(len - mid), dest: v_mid }; + } + + // Initially, these pointers point past the ends of their arrays. + let left = &mut hole.dest; + let right = &mut hole.end; + let mut out = v_end; + + while v < *left && buf < *right { + // Consume the greater side. + // If equal, prefer the right run to maintain stability. + unsafe { + let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) { + decrement_and_get(left) + } else { + decrement_and_get(right) + }; + ptr::copy_nonoverlapping(to_copy, decrement_and_get(&mut out), 1); + } + } + } + // Finally, `hole` gets dropped. If the shorter run was not fully consumed, whatever remains of + // it will now be copied into the hole in `v`. + + unsafe fn get_and_increment(ptr: &mut *mut T) -> *mut T { + let old = *ptr; + *ptr = unsafe { ptr.offset(1) }; + old + } + + unsafe fn decrement_and_get(ptr: &mut *mut T) -> *mut T { + *ptr = unsafe { ptr.offset(-1) }; + *ptr + } + + // When dropped, copies the range `start..end` into `dest..`. + struct MergeHole { + start: *mut T, + end: *mut T, + dest: *mut T, + } + + impl Drop for MergeHole { + fn drop(&mut self) { + // `T` is not a zero-sized type, so it's okay to divide by its size. + let len = (self.end as usize - self.start as usize) / mem::size_of::(); + unsafe { + ptr::copy_nonoverlapping(self.start, self.dest, len); + } + } + } +} + +/// This merge sort borrows some (but not all) ideas from TimSort, which is described in detail +/// [here](http://svn.python.org/projects/python/trunk/Objects/listsort.txt). +/// +/// The algorithm identifies strictly descending and non-descending subsequences, which are called +/// natural runs. There is a stack of pending runs yet to be merged. Each newly found run is pushed +/// onto the stack, and then some pairs of adjacent runs are merged until these two invariants are +/// satisfied: +/// +/// 1. for every `i` in `1..runs.len()`: `runs[i - 1].len > runs[i].len` +/// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` +/// +/// The invariants ensure that the total running time is *O*(*n* \* log(*n*)) worst-case. +fn merge_sort(v: &mut [T], mut is_less: F) +where + F: FnMut(&T, &T) -> bool, +{ + // Slices of up to this length get sorted using insertion sort. + const MAX_INSERTION: usize = 20; + // Very short runs are extended using insertion sort to span at least this many elements. + const MIN_RUN: usize = 10; + + // Sorting has no meaningful behavior on zero-sized types. + if size_of::() == 0 { + return; + } + + let len = v.len(); + + // Short arrays get sorted in-place via insertion sort to avoid allocations. + if len <= MAX_INSERTION { + if len >= 2 { + for i in (0..len - 1).rev() { + insert_head(&mut v[i..], &mut is_less); + } + } + return; + } + + // Allocate a buffer to use as scratch memory. We keep the length 0 so we can keep in it + // shallow copies of the contents of `v` without risking the dtors running on copies if + // `is_less` panics. When merging two sorted runs, this buffer holds a copy of the shorter run, + // which will always have length at most `len / 2`. + let mut buf = Vec::with_capacity(len / 2); + + // In order to identify natural runs in `v`, we traverse it backwards. That might seem like a + // strange decision, but consider the fact that merges more often go in the opposite direction + // (forwards). According to benchmarks, merging forwards is slightly faster than merging + // backwards. To conclude, identifying runs by traversing backwards improves performance. + let mut runs = vec![]; + let mut end = len; + while end > 0 { + // Find the next natural run, and reverse it if it's strictly descending. + let mut start = end - 1; + if start > 0 { + start -= 1; + unsafe { + if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) { + while start > 0 && is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) { + start -= 1; + } + v[start..end].reverse(); + } else { + while start > 0 && !is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) + { + start -= 1; + } + } + } + } + + // Insert some more elements into the run if it's too short. Insertion sort is faster than + // merge sort on short sequences, so this significantly improves performance. + while start > 0 && end - start < MIN_RUN { + start -= 1; + insert_head(&mut v[start..end], &mut is_less); + } + + // Push this run onto the stack. + runs.push(Run { start, len: end - start }); + end = start; + + // Merge some pairs of adjacent runs to satisfy the invariants. + while let Some(r) = collapse(&runs) { + let left = runs[r + 1]; + let right = runs[r]; + unsafe { + merge( + &mut v[left.start..right.start + right.len], + left.len, + buf.as_mut_ptr(), + &mut is_less, + ); + } + runs[r] = Run { start: left.start, len: left.len + right.len }; + runs.remove(r + 1); + } + } + + // Finally, exactly one run must remain in the stack. + debug_assert!(runs.len() == 1 && runs[0].start == 0 && runs[0].len == len); + + // Examines the stack of runs and identifies the next pair of runs to merge. More specifically, + // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the + // algorithm should continue building a new run instead, `None` is returned. + // + // TimSort is infamous for its buggy implementations, as described here: + // http://envisage-project.eu/timsort-specification-and-verification/ + // + // The gist of the story is: we must enforce the invariants on the top four runs on the stack. + // Enforcing them on just top three is not sufficient to ensure that the invariants will still + // hold for *all* runs in the stack. + // + // This function correctly checks invariants for the top four runs. Additionally, if the top + // run starts at index 0, it will always demand a merge operation until the stack is fully + // collapsed, in order to complete the sort. + #[inline] + fn collapse(runs: &[Run]) -> Option { + let n = runs.len(); + if n >= 2 + && (runs[n - 1].start == 0 + || runs[n - 2].len <= runs[n - 1].len + || (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len) + || (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len)) + { + if n >= 3 && runs[n - 3].len < runs[n - 1].len { Some(n - 3) } else { Some(n - 2) } + } else { + None + } + } + + #[derive(Clone, Copy)] + struct Run { + start: usize, + len: usize, + } +} +#![stable(feature = "wake_trait", since = "1.51.0")] +//! Types and Traits for working with asynchronous tasks. +use core::mem::ManuallyDrop; +use core::task::{RawWaker, RawWakerVTable, Waker}; + +use crate::sync::Arc; + +/// The implementation of waking a task on an executor. +/// +/// This trait can be used to create a [`Waker`]. An executor can define an +/// implementation of this trait, and use that to construct a Waker to pass +/// to the tasks that are executed on that executor. +/// +/// This trait is a memory-safe and ergonomic alternative to constructing a +/// [`RawWaker`]. It supports the common executor design in which the data used +/// to wake up a task is stored in an [`Arc`]. Some executors (especially +/// those for embedded systems) cannot use this API, which is why [`RawWaker`] +/// exists as an alternative for those systems. +/// +/// [arc]: ../../std/sync/struct.Arc.html +/// +/// # Examples +/// +/// A basic `block_on` function that takes a future and runs it to completion on +/// the current thread. +/// +/// **Note:** This example trades correctness for simplicity. In order to prevent +/// deadlocks, production-grade implementations will also need to handle +/// intermediate calls to `thread::unpark` as well as nested invocations. +/// +/// ```rust +/// use std::future::Future; +/// use std::sync::Arc; +/// use std::task::{Context, Poll, Wake}; +/// use std::thread::{self, Thread}; +/// +/// /// A waker that wakes up the current thread when called. +/// struct ThreadWaker(Thread); +/// +/// impl Wake for ThreadWaker { +/// fn wake(self: Arc) { +/// self.0.unpark(); +/// } +/// } +/// +/// /// Run a future to completion on the current thread. +/// fn block_on(fut: impl Future) -> T { +/// // Pin the future so it can be polled. +/// let mut fut = Box::pin(fut); +/// +/// // Create a new context to be passed to the future. +/// let t = thread::current(); +/// let waker = Arc::new(ThreadWaker(t)).into(); +/// let mut cx = Context::from_waker(&waker); +/// +/// // Run the future to completion. +/// loop { +/// match fut.as_mut().poll(&mut cx) { +/// Poll::Ready(res) => return res, +/// Poll::Pending => thread::park(), +/// } +/// } +/// } +/// +/// block_on(async { +/// println!("Hi from inside a future!"); +/// }); +/// ``` +#[stable(feature = "wake_trait", since = "1.51.0")] +pub trait Wake { + /// Wake this task. + #[stable(feature = "wake_trait", since = "1.51.0")] + fn wake(self: Arc); + + /// Wake this task without consuming the waker. + /// + /// If an executor supports a cheaper way to wake without consuming the + /// waker, it should override this method. By default, it clones the + /// [`Arc`] and calls [`wake`] on the clone. + /// + /// [`wake`]: Wake::wake + #[stable(feature = "wake_trait", since = "1.51.0")] + fn wake_by_ref(self: &Arc) { + self.clone().wake(); + } +} + +#[stable(feature = "wake_trait", since = "1.51.0")] +impl From> for Waker { + /// Use a `Wake`-able type as a `Waker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Arc) -> Waker { + // SAFETY: This is safe because raw_waker safely constructs + // a RawWaker from Arc. + unsafe { Waker::from_raw(raw_waker(waker)) } + } +} + +#[stable(feature = "wake_trait", since = "1.51.0")] +impl From> for RawWaker { + /// Use a `Wake`-able type as a `RawWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Arc) -> RawWaker { + raw_waker(waker) + } +} + +// NB: This private function for constructing a RawWaker is used, rather than +// inlining this into the `From> for RawWaker` impl, to ensure that +// the safety of `From> for Waker` does not depend on the correct +// trait dispatch - instead both impls call this function directly and +// explicitly. +#[inline(always)] +fn raw_waker(waker: Arc) -> RawWaker { + // Increment the reference count of the arc to clone it. + unsafe fn clone_waker(waker: *const ()) -> RawWaker { + unsafe { Arc::increment_strong_count(waker as *const W) }; + RawWaker::new( + waker as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) + } + + // Wake by value, moving the Arc into the Wake::wake function + unsafe fn wake(waker: *const ()) { + let waker = unsafe { Arc::from_raw(waker as *const W) }; + ::wake(waker); + } + + // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it + unsafe fn wake_by_ref(waker: *const ()) { + let waker = unsafe { ManuallyDrop::new(Arc::from_raw(waker as *const W)) }; + ::wake_by_ref(&waker); + } + + // Decrement the reference count of the Arc on drop + unsafe fn drop_waker(waker: *const ()) { + unsafe { Arc::decrement_strong_count(waker as *const W) }; + } + + RawWaker::new( + Arc::into_raw(waker) as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) +} +#![stable(feature = "rust1", since = "1.0.0")] + +//! Thread-safe reference-counting pointers. +//! +//! See the [`Arc`][Arc] documentation for more details. + +use core::any::Any; +use core::borrow; +use core::cmp::Ordering; +use core::convert::{From, TryFrom}; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::hint; +use core::intrinsics::abort; +use core::iter; +use core::marker::{PhantomData, Unpin, Unsize}; +use core::mem::{self, align_of_val_raw, size_of_val}; +use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +use core::pin::Pin; +use core::ptr::{self, NonNull}; +use core::slice::from_raw_parts_mut; +use core::sync::atomic; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; + +use crate::alloc::{ + box_free, handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw, +}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::rc::is_dangling; +use crate::string::String; +use crate::vec::Vec; + +#[cfg(test)] +mod tests; + +/// A soft limit on the amount of references that may be made to an `Arc`. +/// +/// Going above this limit will abort your program (although not +/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. +const MAX_REFCOUNT: usize = (isize::MAX) as usize; + +#[cfg(not(sanitize = "thread"))] +macro_rules! acquire { + ($x:expr) => { + atomic::fence(Acquire) + }; +} + +// ThreadSanitizer does not support memory fences. To avoid false positive +// reports in Arc / Weak implementation use atomic loads for synchronization +// instead. +#[cfg(sanitize = "thread")] +macro_rules! acquire { + ($x:expr) => { + $x.load(Acquire) + }; +} + +/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically +/// Reference Counted'. +/// +/// The type `Arc` provides shared ownership of a value of type `T`, +/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces +/// a new `Arc` instance, which points to the same allocation on the heap as the +/// source `Arc`, while increasing a reference count. When the last `Arc` +/// pointer to a given allocation is destroyed, the value stored in that allocation (often +/// referred to as "inner value") is also dropped. +/// +/// Shared references in Rust disallow mutation by default, and `Arc` is no +/// exception: you cannot generally obtain a mutable reference to something +/// inside an `Arc`. If you need to mutate through an `Arc`, use +/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic] +/// types. +/// +/// ## Thread Safety +/// +/// Unlike [`Rc`], `Arc` uses atomic operations for its reference +/// counting. This means that it is thread-safe. The disadvantage is that +/// atomic operations are more expensive than ordinary memory accesses. If you +/// are not sharing reference-counted allocations between threads, consider using +/// [`Rc`] for lower overhead. [`Rc`] is a safe default, because the +/// compiler will catch any attempt to send an [`Rc`] between threads. +/// However, a library might choose `Arc` in order to give library consumers +/// more flexibility. +/// +/// `Arc` will implement [`Send`] and [`Sync`] as long as the `T` implements +/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an +/// `Arc` to make it thread-safe? This may be a bit counter-intuitive at +/// first: after all, isn't the point of `Arc` thread safety? The key is +/// this: `Arc` makes it thread safe to have multiple ownership of the same +/// data, but it doesn't add thread safety to its data. Consider +/// `Arc<`[`RefCell`]`>`. [`RefCell`] isn't [`Sync`], and if `Arc` was always +/// [`Send`], `Arc<`[`RefCell`]`>` would be as well. But then we'd have a problem: +/// [`RefCell`] is not thread safe; it keeps track of the borrowing count using +/// non-atomic operations. +/// +/// In the end, this means that you may need to pair `Arc` with some sort of +/// [`std::sync`] type, usually [`Mutex`][mutex]. +/// +/// ## Breaking cycles with `Weak` +/// +/// The [`downgrade`][downgrade] method can be used to create a non-owning +/// [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d +/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has +/// already been dropped. In other words, `Weak` pointers do not keep the value +/// inside the allocation alive; however, they *do* keep the allocation +/// (the backing store for the value) alive. +/// +/// A cycle between `Arc` pointers will never be deallocated. For this reason, +/// [`Weak`] is used to break cycles. For example, a tree could have +/// strong `Arc` pointers from parent nodes to children, and [`Weak`] +/// pointers from children back to their parents. +/// +/// # Cloning references +/// +/// Creating a new reference from an existing reference-counted pointer is done using the +/// `Clone` trait implemented for [`Arc`][Arc] and [`Weak`][Weak]. +/// +/// ``` +/// use std::sync::Arc; +/// let foo = Arc::new(vec![1.0, 2.0, 3.0]); +/// // The two syntaxes below are equivalent. +/// let a = foo.clone(); +/// let b = Arc::clone(&foo); +/// // a, b, and foo are all Arcs that point to the same memory location +/// ``` +/// +/// ## `Deref` behavior +/// +/// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), +/// so you can call `T`'s methods on a value of type `Arc`. To avoid name +/// clashes with `T`'s methods, the methods of `Arc` itself are associated +/// functions, called using [fully qualified syntax]: +/// +/// ``` +/// use std::sync::Arc; +/// +/// let my_arc = Arc::new(()); +/// Arc::downgrade(&my_arc); +/// ``` +/// +/// `Arc`'s implementations of traits like `Clone` may also be called using +/// fully qualified syntax. Some people prefer to use fully qualified syntax, +/// while others prefer using method-call syntax. +/// +/// ``` +/// use std::sync::Arc; +/// +/// let arc = Arc::new(()); +/// // Method-call syntax +/// let arc2 = arc.clone(); +/// // Fully qualified syntax +/// let arc3 = Arc::clone(&arc); +/// ``` +/// +/// [`Weak`][Weak] does not auto-dereference to `T`, because the inner value may have +/// already been dropped. +/// +/// [`Rc`]: crate::rc::Rc +/// [clone]: Clone::clone +/// [mutex]: ../../std/sync/struct.Mutex.html +/// [rwlock]: ../../std/sync/struct.RwLock.html +/// [atomic]: core::sync::atomic +/// [`Send`]: core::marker::Send +/// [`Sync`]: core::marker::Sync +/// [deref]: core::ops::Deref +/// [downgrade]: Arc::downgrade +/// [upgrade]: Weak::upgrade +/// [`RefCell`]: core::cell::RefCell +/// [`std::sync`]: ../../std/sync/index.html +/// [`Arc::clone(&from)`]: Arc::clone +/// [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name +/// +/// # Examples +/// +/// Sharing some immutable data between threads: +/// +// Note that we **do not** run these tests here. The windows builders get super +// unhappy if a thread outlives the main thread and then exits at the same time +// (something deadlocks) so we just avoid this entirely by not running these +// tests. +/// ```no_run +/// use std::sync::Arc; +/// use std::thread; +/// +/// let five = Arc::new(5); +/// +/// for _ in 0..10 { +/// let five = Arc::clone(&five); +/// +/// thread::spawn(move || { +/// println!("{:?}", five); +/// }); +/// } +/// ``` +/// +/// Sharing a mutable [`AtomicUsize`]: +/// +/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize +/// +/// ```no_run +/// use std::sync::Arc; +/// use std::sync::atomic::{AtomicUsize, Ordering}; +/// use std::thread; +/// +/// let val = Arc::new(AtomicUsize::new(5)); +/// +/// for _ in 0..10 { +/// let val = Arc::clone(&val); +/// +/// thread::spawn(move || { +/// let v = val.fetch_add(1, Ordering::SeqCst); +/// println!("{:?}", v); +/// }); +/// } +/// ``` +/// +/// See the [`rc` documentation][rc_examples] for more examples of reference +/// counting in general. +/// +/// [rc_examples]: crate::rc#examples +#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Arc { + ptr: NonNull>, + phantom: PhantomData>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Arc {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Arc {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized> for Arc {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Arc {} + +impl Arc { + fn from_inner(ptr: NonNull>) -> Self { + Self { ptr, phantom: PhantomData } + } + + unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { + unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } + } +} + +/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the +/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [`Option`]`<`[`Arc`]`>`. +/// +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. +/// +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Arc`] pointers, since mutual owning references +/// would never allow either [`Arc`] to be dropped. For example, a tree could +/// have strong [`Arc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. +/// +/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`]. +/// +/// [`upgrade`]: Weak::upgrade +#[stable(feature = "arc_weak", since = "1.4.0")] +pub struct Weak { + // This is a `NonNull` to allow optimizing the size of this type in enums, + // but it is not necessarily a valid pointer. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real pointer + // will ever have because RcBox has alignment at least 2. + // This is only possible when `T: Sized`; unsized `T` never dangle. + ptr: NonNull>, +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Send for Weak {} +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Sync for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized> for Weak {} +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Weak {} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "(Weak)") + } +} + +// This is repr(C) to future-proof against possible field-reordering, which +// would interfere with otherwise safe [into|from]_raw() of transmutable +// inner types. +#[repr(C)] +struct ArcInner { + strong: atomic::AtomicUsize, + + // the value usize::MAX acts as a sentinel for temporarily "locking" the + // ability to upgrade weak pointers or downgrade strong ones; this is used + // to avoid races in `make_mut` and `get_mut`. + weak: atomic::AtomicUsize, + + data: T, +} + +unsafe impl Send for ArcInner {} +unsafe impl Sync for ArcInner {} + +impl Arc { + /// Constructs a new `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(data: T) -> Arc { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = box ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + }; + Self::from_inner(Box::leak(x).into()) + } + + /// Constructs a new `Arc` using a weak reference to itself. Attempting + /// to upgrade the weak reference before this function returns will result + /// in a `None` value. However, the weak reference may be cloned freely and + /// stored for use at a later time. + /// + /// # Examples + /// ``` + /// #![feature(arc_new_cyclic)] + /// #![allow(dead_code)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// struct Foo { + /// me: Weak, + /// } + /// + /// let foo = Arc::new_cyclic(|me| Foo { + /// me: me.clone(), + /// }); + /// ``` + #[inline] + #[unstable(feature = "arc_new_cyclic", issue = "75861")] + pub fn new_cyclic(data_fn: impl FnOnce(&Weak) -> T) -> Arc { + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let uninit_ptr: NonNull<_> = Box::leak(box ArcInner { + strong: atomic::AtomicUsize::new(0), + weak: atomic::AtomicUsize::new(1), + data: mem::MaybeUninit::::uninit(), + }) + .into(); + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + // Now we can properly initialize the inner value and turn our weak + // reference into a strong reference. + unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(ptr::addr_of_mut!((*inner).data), data); + + // The above write to the data field must be visible to any threads which + // observe a non-zero strong count. Therefore we need at least "Release" ordering + // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`. + // + // "Acquire" ordering is not required. When considering the possible behaviours + // of `data_fn` we only need to look at what it could do with a reference to a + // non-upgradeable `Weak`: + // - It can *clone* the `Weak`, increasing the weak reference count. + // - It can drop those clones, decreasing the weak reference count (but never to zero). + // + // These side effects do not impact us in any way, and no other side effects are + // possible with safe code alone. + let prev_value = (*inner).strong.fetch_add(1, Release); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + } + + let strong = Arc::from_inner(init_ptr); + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + mem::forget(weak); + strong + } + + /// Constructs a new `Arc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Arc> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + |mem| mem as *mut ArcInner>, + )) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Arc> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + |mem| mem as *mut ArcInner>, + )) + } + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `data` will be pinned in memory and unable to be moved. + #[stable(feature = "pin", since = "1.33.0")] + pub fn pin(data: T) -> Pin> { + unsafe { Pin::new_unchecked(Arc::new(data)) } + } + + /// Constructs a new `Arc`, returning an error if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// use std::sync::Arc; + /// + /// let five = Arc::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(data: T) -> Result, AllocError> { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = Box::try_new(ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data, + })?; + Ok(Self::from_inner(Box::leak(x).into())) + } + + /// Constructs a new `Arc` with uninitialized contents, returning an error + /// if allocation fails. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit, allocator_api)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit() -> Result>, AllocError> { + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate(layout), + |mem| mem as *mut ArcInner>, + )?)) + } + } + + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes, returning an error if allocation fails. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit, allocator_api)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed() -> Result>, AllocError> { + unsafe { + Ok(Arc::from_ptr(Arc::try_allocate_for_layout( + Layout::new::(), + |layout| Global.allocate_zeroed(layout), + |mem| mem as *mut ArcInner>, + )?)) + } + } + /// Returns the inner value, if the `Arc` has exactly one strong reference. + /// + /// Otherwise, an [`Err`] is returned with the same `Arc` that was + /// passed in. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// assert_eq!(Arc::try_unwrap(x), Ok(3)); + /// + /// let x = Arc::new(4); + /// let _y = Arc::clone(&x); + /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn try_unwrap(this: Self) -> Result { + if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() { + return Err(this); + } + + acquire!(this.inner().strong); + + unsafe { + let elem = ptr::read(&this.ptr.as_ref().data); + + // Make a weak pointer to clean up the implicit strong-weak reference + let _weak = Weak { ptr: this.ptr }; + mem::forget(this); + + Ok(elem) + } + } +} + +impl Arc<[T]> { + /// Constructs a new atomically reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } + } + + /// Constructs a new atomically reference-counted slice with uninitialized contents, with the memory being + /// filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// use std::sync::Arc; + /// + /// let values = Arc::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate_zeroed(layout), + |mem| { + ptr::slice_from_raw_parts_mut(mem as *mut T, len) + as *mut ArcInner<[mem::MaybeUninit]> + }, + )) + } + } +} + +impl Arc> { + /// Converts to `Arc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc { + Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl Arc<[mem::MaybeUninit]> { + /// Converts to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the inner value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + unsafe { Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } + } +} + +impl Arc { + /// Consumes the `Arc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw`]. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr = Self::as_ptr(&this); + mem::forget(this); + ptr + } + + /// Provides a raw pointer to the data. + /// + /// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for + /// as long as there are strong counts in the `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let y = Arc::clone(&x); + /// let x_ptr = Arc::as_ptr(&x); + /// assert_eq!(x_ptr, Arc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[stable(feature = "rc_as_ptr", since = "1.45.0")] + pub fn as_ptr(this: &Self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); + + // SAFETY: This cannot go through Deref::deref or RcBoxPtr::inner because + // this is required to retain raw/mut provenance such that e.g. `get_mut` can + // write through the pointer after the Rc is recovered through `from_raw`. + unsafe { ptr::addr_of_mut!((*ptr).data) } + } + + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to + /// [`Arc::into_raw`][into_raw] where `U` must have the same size and + /// alignment as `T`. This is trivially true if `U` is `T`. + /// Note that if `U` is not `T` but has the same size and alignment, this is + /// basically like transmuting references of different types. See + /// [`mem::transmute`][transmute] for more information on what + /// restrictions apply in this case. + /// + /// The user of `from_raw` has to make sure a specific value of `T` is only + /// dropped once. + /// + /// This function is unsafe because improper use may lead to memory unsafety, + /// even if the returned `Arc` is never accessed. + /// + /// [into_raw]: Arc::into_raw + /// [transmute]: core::mem::transmute + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let x_ptr = Arc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Arc` to prevent leak. + /// let x = Arc::from_raw(x_ptr); + /// assert_eq!(&*x, "hello"); + /// + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory-unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + unsafe { + let offset = data_offset(ptr); + + // Reverse the offset to find the original ArcInner. + let arc_ptr = (ptr as *mut ArcInner).set_ptr_value((ptr as *mut u8).offset(-offset)); + + Self::from_ptr(arc_ptr) + } + } + + /// Creates a new [`Weak`] pointer to this allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// ``` + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn downgrade(this: &Self) -> Weak { + // This Relaxed is OK because we're checking the value in the CAS + // below. + let mut cur = this.inner().weak.load(Relaxed); + + loop { + // check if the weak counter is currently "locked"; if so, spin. + if cur == usize::MAX { + hint::spin_loop(); + cur = this.inner().weak.load(Relaxed); + continue; + } + + // NOTE: this code currently ignores the possibility of overflow + // into usize::MAX; in general both Rc and Arc need to be adjusted + // to deal with overflow. + + // Unlike with Clone(), we need this to be an Acquire read to + // synchronize with the write coming from `is_unique`, so that the + // events prior to that write happen before this read. + match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { + Ok(_) => { + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr.as_ptr())); + return Weak { ptr: this.ptr }; + } + Err(old) => cur = old, + } + } + } + + /// Gets the number of [`Weak`] pointers to this allocation. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the weak count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _weak_five = Arc::downgrade(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` or `Weak` between threads. + /// assert_eq!(1, Arc::weak_count(&five)); + /// ``` + #[inline] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn weak_count(this: &Self) -> usize { + let cnt = this.inner().weak.load(SeqCst); + // If the weak count is currently locked, the value of the + // count was 0 just before taking the lock. + if cnt == usize::MAX { 0 } else { cnt - 1 } + } + + /// Gets the number of strong (`Arc`) pointers to this allocation. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the strong count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _also_five = Arc::clone(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// assert_eq!(2, Arc::strong_count(&five)); + /// ``` + #[inline] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn strong_count(this: &Self) -> usize { + this.inner().strong.load(SeqCst) + } + + /// Increments the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count(ptr); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] + pub unsafe fn increment_strong_count(ptr: *const T) { + // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + let arc = unsafe { mem::ManuallyDrop::new(Arc::::from_raw(ptr)) }; + // Now increase refcount, but don't drop new refcount either + let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); + } + + /// Decrements the strong reference count on the `Arc` associated with the + /// provided pointer by one. + /// + /// # Safety + /// + /// The pointer must have been obtained through `Arc::into_raw`, and the + /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) when invoking this method. This method can be used to release the final + /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been + /// released. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// unsafe { + /// let ptr = Arc::into_raw(five); + /// Arc::increment_strong_count(ptr); + /// + /// // Those assertions are deterministic because we haven't shared + /// // the `Arc` between threads. + /// let five = Arc::from_raw(ptr); + /// assert_eq!(2, Arc::strong_count(&five)); + /// Arc::decrement_strong_count(ptr); + /// assert_eq!(1, Arc::strong_count(&five)); + /// } + /// ``` + #[inline] + #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] + pub unsafe fn decrement_strong_count(ptr: *const T) { + unsafe { mem::drop(Arc::from_raw(ptr)) }; + } + + #[inline] + fn inner(&self) -> &ArcInner { + // This unsafety is ok because while this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` because the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. + unsafe { self.ptr.as_ref() } + } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + // Destroy the data at this time, even though we may not free the box + // allocation itself (there may still be weak pointers lying around). + unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) }; + + // Drop the weak ref collectively held by all strong references + drop(Weak { ptr: self.ptr }); + } + + #[inline] + #[stable(feature = "ptr_eq", since = "1.17.0")] + /// Returns `true` if the two `Arc`s point to the same allocation + /// (in a vein similar to [`ptr::eq`]). + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let same_five = Arc::clone(&five); + /// let other_five = Arc::new(5); + /// + /// assert!(Arc::ptr_eq(&five, &same_five)); + /// assert!(!Arc::ptr_eq(&five, &other_five)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + this.ptr.as_ptr() == other.ptr.as_ptr() + } +} + +impl Arc { + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + unsafe fn allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> *mut ArcInner { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + unsafe { + Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner) + .unwrap_or_else(|_| handle_alloc_error(layout)) + } + } + + /// Allocates an `ArcInner` with sufficient space for + /// a possibly-unsized inner value where the value has the layout provided, + /// returning an error if allocation fails. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner`. + unsafe fn try_allocate_for_layout( + value_layout: Layout, + allocate: impl FnOnce(Layout) -> Result, AllocError>, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, + ) -> Result<*mut ArcInner, AllocError> { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + + let ptr = allocate(layout)?; + + // Initialize the ArcInner + let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); + debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); + + unsafe { + ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); + } + + Ok(inner) + } + + /// Allocates an `ArcInner` with sufficient space for an unsized inner value. + unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { + // Allocate for the `ArcInner` using the given value. + unsafe { + Self::allocate_for_layout( + Layout::for_value(&*ptr), + |layout| Global.allocate(layout), + |mem| (ptr as *mut ArcInner).set_ptr_value(mem) as *mut ArcInner, + ) + } + } + + fn from_box(v: Box) -> Arc { + unsafe { + let (box_unique, alloc) = Box::into_unique(v); + let bptr = box_unique.as_ptr(); + + let value_size = size_of_val(&*bptr); + let ptr = Self::allocate_for_ptr(bptr); + + // Copy value as bytes + ptr::copy_nonoverlapping( + bptr as *const T as *const u8, + &mut (*ptr).data as *mut _ as *mut u8, + value_size, + ); + + // Free the allocation without dropping its contents + box_free(box_unique, alloc); + + Self::from_ptr(ptr) + } + } +} + +impl Arc<[T]> { + /// Allocates an `ArcInner<[T]>` with the given length. + unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { + unsafe { + Self::allocate_for_layout( + Layout::array::(len).unwrap(), + |layout| Global.allocate(layout), + |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>, + ) + } + } + + /// Copy elements from slice into newly allocated Arc<\[T\]> + /// + /// Unsafe because the caller must either take ownership or bind `T: Copy`. + unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { + unsafe { + let ptr = Self::allocate_for_slice(v.len()); + + ptr::copy_nonoverlapping(v.as_ptr(), &mut (*ptr).data as *mut [T] as *mut T, v.len()); + + Self::from_ptr(ptr) + } + } + + /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + unsafe fn from_iter_exact(iter: impl iter::Iterator, len: usize) -> Arc<[T]> { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new ArcInner will be dropped, then the memory freed. + struct Guard { + mem: NonNull, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl Drop for Guard { + fn drop(&mut self) { + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Global.deallocate(self.mem, self.layout); + } + } + } + + unsafe { + let ptr = Self::allocate_for_slice(len); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); + + // Pointer to first element + let elems = &mut (*ptr).data as *mut [T] as *mut T; + + let mut guard = Guard { mem: NonNull::new_unchecked(mem), elems, layout, n_elems: 0 }; + + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new ArcInner. + mem::forget(guard); + + Self::from_ptr(ptr) + } + } +} + +/// Specialization trait used for `From<&[T]>`. +trait ArcFromSlice { + fn from_slice(slice: &[T]) -> Self; +} + +impl ArcFromSlice for Arc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } + } +} + +impl ArcFromSlice for Arc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + unsafe { Arc::copy_from_slice(v) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Arc { + /// Makes a clone of the `Arc` pointer. + /// + /// This creates another pointer to the same allocation, increasing the + /// strong reference count. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let _ = Arc::clone(&five); + /// ``` + #[inline] + fn clone(&self) -> Arc { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object. + // + // As explained in the [Boost documentation][1], Increasing the + // reference counter can always be done with memory_order_relaxed: New + // references to an object can only be formed from an existing + // reference, and passing an existing reference from one thread to + // another must already provide any required synchronization. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + let old_size = self.inner().strong.fetch_add(1, Relaxed); + + // However we need to guard against massive refcounts in case someone + // is `mem::forget`ing Arcs. If we don't do this the count can overflow + // and users will use-after free. We racily saturate to `isize::MAX` on + // the assumption that there aren't ~2 billion threads incrementing + // the reference count at once. This branch will never be taken in + // any realistic program. + // + // We abort because such a program is incredibly degenerate, and we + // don't care to support it. + if old_size > MAX_REFCOUNT { + abort(); + } + + Self::from_inner(self.ptr) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Arc { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.inner().data + } +} + +#[unstable(feature = "receiver_trait", issue = "none")] +impl Receiver for Arc {} + +impl Arc { + /// Makes a mutable reference into the given `Arc`. + /// + /// If there are other `Arc` or [`Weak`] pointers to the same allocation, + /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value + /// to ensure unique ownership. This is also referred to as clone-on-write. + /// + /// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates + /// any remaining `Weak` pointers. + /// + /// See also [`get_mut`][get_mut], which will fail rather than cloning. + /// + /// [clone]: Clone::clone + /// [get_mut]: Arc::get_mut + /// [`Rc::make_mut`]: super::rc::Rc::make_mut + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(5); + /// + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = Arc::clone(&data); // Won't clone inner data + /// *Arc::make_mut(&mut data) += 1; // Clones inner data + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Now `data` and `other_data` point to different allocations. + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn make_mut(this: &mut Self) -> &mut T { + // Note that we hold both a strong reference and a weak reference. + // Thus, releasing our strong reference only will not, by itself, cause + // the memory to be deallocated. + // + // Use Acquire to ensure that we see any writes to `weak` that happen + // before release writes (i.e., decrements) to `strong`. Since we hold a + // weak count, there's no chance the ArcInner itself could be + // deallocated. + if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { + // Another strong pointer exists, so we must clone. + // Pre-allocate memory to allow writing the cloned value directly. + let mut arc = Self::new_uninit(); + unsafe { + let data = Arc::get_mut_unchecked(&mut arc); + (**this).write_clone_into_raw(data.as_mut_ptr()); + *this = arc.assume_init(); + } + } else if this.inner().weak.load(Relaxed) != 1 { + // Relaxed suffices in the above because this is fundamentally an + // optimization: we are always racing with weak pointers being + // dropped. Worst case, we end up allocated a new Arc unnecessarily. + + // We removed the last strong ref, but there are additional weak + // refs remaining. We'll move the contents to a new Arc, and + // invalidate the other weak refs. + + // Note that it is not possible for the read of `weak` to yield + // usize::MAX (i.e., locked), since the weak count can only be + // locked by a thread with a strong reference. + + // Materialize our own implicit weak pointer, so that it can clean + // up the ArcInner as needed. + let _weak = Weak { ptr: this.ptr }; + + // Can just steal the data, all that's left is Weaks + let mut arc = Self::new_uninit(); + unsafe { + let data = Arc::get_mut_unchecked(&mut arc); + data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1); + ptr::write(this, arc.assume_init()); + } + } else { + // We were the sole reference of either kind; bump back up the + // strong ref count. + this.inner().strong.store(1, Release); + } + + // As with `get_mut()`, the unsafety is ok because our reference was + // either unique to begin with, or became one upon cloning the contents. + unsafe { Self::get_mut_unchecked(this) } + } +} + +impl Arc { + /// Returns a mutable reference into the given `Arc`, if there are + /// no other `Arc` or [`Weak`] pointers to the same allocation. + /// + /// Returns [`None`] otherwise, because it is not safe to + /// mutate a shared value. + /// + /// See also [`make_mut`][make_mut], which will [`clone`][clone] + /// the inner value when there are other pointers. + /// + /// [make_mut]: Arc::make_mut + /// [clone]: Clone::clone + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(3); + /// *Arc::get_mut(&mut x).unwrap() = 4; + /// assert_eq!(*x, 4); + /// + /// let _y = Arc::clone(&x); + /// assert!(Arc::get_mut(&mut x).is_none()); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if this.is_unique() { + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + unsafe { Some(Arc::get_mut_unchecked(this)) } + } else { + None + } + } + + /// Returns a mutable reference into the given `Arc`, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: Arc::get_mut + /// + /// # Safety + /// + /// Any other `Arc` or [`Weak`] pointers to the same allocation must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Arc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + // We are careful to *not* create a reference covering the "count" fields, as + // this would alias with concurrent access to the reference counts (e.g. by `Weak`). + unsafe { &mut (*this.ptr.as_ptr()).data } + } + + /// Determine whether this is the unique reference (including weak refs) to + /// the underlying data. + /// + /// Note that this requires locking the weak ref count. + fn is_unique(&mut self) -> bool { + // lock the weak pointer count if we appear to be the sole weak pointer + // holder. + // + // The acquire label here ensures a happens-before relationship with any + // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements + // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded + // weak ref was never dropped, the CAS here will fail so we do not care to synchronize. + if self.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { + // This needs to be an `Acquire` to synchronize with the decrement of the `strong` + // counter in `drop` -- the only access that happens when any but the last reference + // is being dropped. + let unique = self.inner().strong.load(Acquire) == 1; + + // The release write here synchronizes with a read in `downgrade`, + // effectively preventing the above read of `strong` from happening + // after the write. + self.inner().weak.store(1, Release); // release the lock + unique + } else { + false + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { + /// Drops the `Arc`. + /// + /// This will decrement the strong reference count. If the strong reference + /// count reaches zero then the only other references (if any) are + /// [`Weak`], so we `drop` the inner value. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let foo2 = Arc::clone(&foo); + /// + /// drop(foo); // Doesn't print anything + /// drop(foo2); // Prints "dropped!" + /// ``` + #[inline] + fn drop(&mut self) { + // Because `fetch_sub` is already atomic, we do not need to synchronize + // with other threads unless we are going to delete the object. This + // same logic applies to the below `fetch_sub` to the `weak` count. + if self.inner().strong.fetch_sub(1, Release) != 1 { + return; + } + + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // In particular, while the contents of an Arc are usually immutable, it's + // possible to have interior writes to something like a Mutex. Since a + // Mutex is not acquired when it is deleted, we can't rely on its + // synchronization logic to make writes in thread A visible to a destructor + // running in thread B. + // + // Also note that the Acquire fence here could probably be replaced with an + // Acquire load, which could improve performance in highly-contended + // situations. See [2]. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + // [2]: (https://github.com/rust-lang/rust/pull/41714) + acquire!(self.inner().strong); + + unsafe { + self.drop_slow(); + } + } +} + +impl Arc { + #[inline] + #[stable(feature = "rc_downcast", since = "1.29.0")] + /// Attempt to downcast the `Arc` to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// use std::sync::Arc; + /// + /// fn print_if_string(value: Arc) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Arc::new(my_string)); + /// print_if_string(Arc::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Self> + where + T: Any + Send + Sync + 'static, + { + if (*self).is::() { + let ptr = self.ptr.cast::>(); + mem::forget(self); + Ok(Arc::from_inner(ptr)) + } else { + Err(self) + } + } +} + +impl Weak { + /// Constructs a new `Weak`, without allocating any memory. + /// Calling [`upgrade`] on the return value always gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[stable(feature = "downgraded_weak", since = "1.10.0")] + pub fn new() -> Weak { + Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0") } + } +} + +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a atomic::AtomicUsize, + strong: &'a atomic::AtomicUsize, +} + +impl Weak { + /// Returns a raw pointer to the object `T` pointed to by this `Weak`. + /// + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::ptr; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_ptr())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); + /// ``` + /// + /// [`null`]: core::ptr::null + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn as_ptr(&self) -> *const T { + let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); + + if is_dangling(ptr) { + // If the pointer is dangling, we return the sentinel directly. This cannot be + // a valid payload address, as the payload is at least as aligned as ArcInner (usize). + ptr as *const T + } else { + // SAFETY: if is_dangling returns false, then the pointer is dereferencable. + // The payload may be dropped at this point, and we have to maintain provenance, + // so use raw pointer manipulation. + unsafe { ptr::addr_of_mut!((*ptr).data) } + } + } + + /// Consumes the `Weak` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, while still preserving the ownership of + /// one weak reference (the weak count is not modified by this operation). It can be turned + /// back into the `Weak` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_ptr`] apply. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: Weak::from_raw + /// [`as_ptr`]: Weak::as_ptr + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub fn into_raw(self) -> *const T { + let result = self.as_ptr(); + mem::forget(self); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak`. + /// + /// It takes ownership of one weak reference (with the exception of pointers created by [`new`], + /// as these don't own anything; the method still works on them). + /// + /// # Safety + /// + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference. + /// + /// It is allowed for the strong count to be 0 at the time of calling this. Nevertheless, this + /// takes ownership of one weak reference currently represented as a raw pointer (the weak + /// count is not modified by this operation) and therefore it must be paired with a previous + /// call to [`into_raw`]. + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Arc::downgrade(&strong).into_raw(); + /// let raw_2 = Arc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`new`]: Weak::new + /// [`into_raw`]: Weak::into_raw + /// [`upgrade`]: Weak::upgrade + /// [`forget`]: std::mem::forget + #[stable(feature = "weak_into_raw", since = "1.45.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + // See Weak::as_ptr for context on how the input pointer is derived. + + let ptr = if is_dangling(ptr as *mut T) { + // This is a dangling Weak. + ptr as *mut ArcInner + } else { + // Otherwise, we're guaranteed the pointer came from a nondangling Weak. + // SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T. + let offset = unsafe { data_offset(ptr) }; + // Thus, we reverse the offset to get the whole RcBox. + // SAFETY: the pointer originated from a Weak, so this offset is safe. + unsafe { (ptr as *mut ArcInner).set_ptr_value((ptr as *mut u8).offset(-offset)) } + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } } + } +} + +impl Weak { + /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying + /// dropping of the inner value if successful. + /// + /// Returns [`None`] if the inner value has since been dropped. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// + /// let strong_five: Option> = weak_five.upgrade(); + /// assert!(strong_five.is_some()); + /// + /// // Destroy all strong pointers. + /// drop(strong_five); + /// drop(five); + /// + /// assert!(weak_five.upgrade().is_none()); + /// ``` + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn upgrade(&self) -> Option> { + // We use a CAS loop to increment the strong count instead of a + // fetch_add as this function should never take the reference count + // from zero to one. + let inner = self.inner()?; + + // Relaxed load because any write of 0 that we can observe + // leaves the field in a permanently zero state (so a + // "stale" read of 0 is fine), and any other value is + // confirmed via the CAS below. + let mut n = inner.strong.load(Relaxed); + + loop { + if n == 0 { + return None; + } + + // See comments in `Arc::clone` for why we do this (for `mem::forget`). + if n > MAX_REFCOUNT { + abort(); + } + + // Relaxed is fine for the failure case because we don't have any expectations about the new state. + // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner + // value can be initialized after `Weak` references have already been created. In that case, we + // expect to observe the fully initialized value. + match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) { + Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above + Err(old) => n = old, + } + } + } + + /// Gets the number of strong (`Arc`) pointers pointing to this allocation. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { inner.strong.load(SeqCst) } else { 0 } + } + + /// Gets an approximation of the number of `Weak` pointers pointing to this + /// allocation. + /// + /// If `self` was created using [`Weak::new`], or if there are no remaining + /// strong pointers, this will return 0. + /// + /// # Accuracy + /// + /// Due to implementation details, the returned value can be off by 1 in + /// either direction when other threads are manipulating any `Arc`s or + /// `Weak`s pointing to the same allocation. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { + self.inner() + .map(|inner| { + let weak = inner.weak.load(SeqCst); + let strong = inner.strong.load(SeqCst); + if strong == 0 { + 0 + } else { + // Since we observed that there was at least one strong pointer + // after reading the weak count, we know that the implicit weak + // reference (present whenever any strong references are alive) + // was still around when we observed the weak count, and can + // therefore safely subtract it. + weak - 1 + } + }) + .unwrap_or(0) + } + + /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, + /// (i.e., when this `Weak` was created by `Weak::new`). + #[inline] + fn inner(&self) -> Option> { + if is_dangling(self.ptr.as_ptr()) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Arc` + // is dropped, the data field will be dropped in-place). + Some(unsafe { + let ptr = self.ptr.as_ptr(); + WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } + }) + } + } + + /// Returns `true` if the two `Weak`s point to the same allocation (similar to + /// [`ptr::eq`]), or if both don't point to any allocation + /// (because they were created with `Weak::new()`). + /// + /// # Notes + /// + /// Since this compares pointers it means that `Weak::new()` will equal each + /// other, even though they don't point to any allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let first_rc = Arc::new(5); + /// let first = Arc::downgrade(&first_rc); + /// let second = Arc::downgrade(&first_rc); + /// + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Arc::new(5); + /// let third = Arc::downgrade(&third_rc); + /// + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// Comparing `Weak::new`. + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let first = Weak::new(); + /// let second = Weak::new(); + /// assert!(first.ptr_eq(&second)); + /// + /// let third_rc = Arc::new(()); + /// let third = Arc::downgrade(&third_rc); + /// assert!(!first.ptr_eq(&third)); + /// ``` + /// + /// [`ptr::eq`]: core::ptr::eq + #[inline] + #[stable(feature = "weak_ptr_eq", since = "1.39.0")] + pub fn ptr_eq(&self, other: &Self) -> bool { + self.ptr.as_ptr() == other.ptr.as_ptr() + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl Clone for Weak { + /// Makes a clone of the `Weak` pointer that points to the same allocation. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// let weak_five = Arc::downgrade(&Arc::new(5)); + /// + /// let _ = Weak::clone(&weak_five); + /// ``` + #[inline] + fn clone(&self) -> Weak { + let inner = if let Some(inner) = self.inner() { + inner + } else { + return Weak { ptr: self.ptr }; + }; + // See comments in Arc::clone() for why this is relaxed. This can use a + // fetch_add (ignoring the lock) because the weak count is only locked + // where are *no other* weak pointers in existence. (So we can't be + // running this code in that case). + let old_size = inner.weak.fetch_add(1, Relaxed); + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + abort(); + } + + Weak { ptr: self.ptr } + } +} + +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + /// Constructs a new `Weak`, without allocating memory. + /// Calling [`upgrade`] on the return value always + /// gives [`None`]. + /// + /// [`upgrade`]: Weak::upgrade + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Default::default(); + /// assert!(empty.upgrade().is_none()); + /// ``` + fn default() -> Weak { + Weak::new() + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl Drop for Weak { + /// Drops the `Weak` pointer. + /// + /// # Examples + /// + /// ``` + /// use std::sync::{Arc, Weak}; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let weak_foo = Arc::downgrade(&foo); + /// let other_weak_foo = Weak::clone(&weak_foo); + /// + /// drop(weak_foo); // Doesn't print anything + /// drop(foo); // Prints "dropped!" + /// + /// assert!(other_weak_foo.upgrade().is_none()); + /// ``` + fn drop(&mut self) { + // If we find out that we were the last weak pointer, then its time to + // deallocate the data entirely. See the discussion in Arc::drop() about + // the memory orderings + // + // It's not necessary to check for the locked state here, because the + // weak count can only be locked if there was precisely one weak ref, + // meaning that drop could only subsequently run ON that remaining weak + // ref, which can only happen after the lock is released. + let inner = if let Some(inner) = self.inner() { inner } else { return }; + + if inner.weak.fetch_sub(1, Release) == 1 { + acquire!(inner.weak); + unsafe { Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())) } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +trait ArcEqIdent { + fn eq(&self, other: &Arc) -> bool; + fn ne(&self, other: &Arc) -> bool; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + default fn eq(&self, other: &Arc) -> bool { + **self == **other + } + #[inline] + default fn ne(&self, other: &Arc) -> bool { + **self != **other + } +} + +/// We're doing this specialization here, and not as a more general optimization on `&T`, because it +/// would otherwise add a cost to all equality checks on refs. We assume that `Arc`s are used to +/// store large values, that are slow to clone, but also heavy to check for equality, causing this +/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to +/// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. +#[stable(feature = "rust1", since = "1.0.0")] +impl ArcEqIdent for Arc { + #[inline] + fn eq(&self, other: &Arc) -> bool { + Arc::ptr_eq(self, other) || **self == **other + } + + #[inline] + fn ne(&self, other: &Arc) -> bool { + !Arc::ptr_eq(self, other) && **self != **other + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Arc { + /// Equality for two `Arc`s. + /// + /// Two `Arc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same allocation are always equal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five == Arc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Arc) -> bool { + ArcEqIdent::eq(self, other) + } + + /// Inequality for two `Arc`s. + /// + /// Two `Arc`s are unequal if their inner values are unequal. + /// + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same value are never unequal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five != Arc::new(6)); + /// ``` + #[inline] + fn ne(&self, other: &Arc) -> bool { + ArcEqIdent::ne(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Arc { + /// Partial comparison for two `Arc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6))); + /// ``` + fn partial_cmp(&self, other: &Arc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `Arc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five < Arc::new(6)); + /// ``` + fn lt(&self, other: &Arc) -> bool { + *(*self) < *(*other) + } + + /// 'Less than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five <= Arc::new(5)); + /// ``` + fn le(&self, other: &Arc) -> bool { + *(*self) <= *(*other) + } + + /// Greater-than comparison for two `Arc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five > Arc::new(4)); + /// ``` + fn gt(&self, other: &Arc) -> bool { + *(*self) > *(*other) + } + + /// 'Greater than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five >= Arc::new(5)); + /// ``` + fn ge(&self, other: &Arc) -> bool { + *(*self) >= *(*other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Arc { + /// Comparison for two `Arc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6))); + /// ``` + fn cmp(&self, other: &Arc) -> Ordering { + (**self).cmp(&**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Arc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Arc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&**self as *const T), f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Arc { + /// Creates a new `Arc`, with the `Default` value for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc = Default::default(); + /// assert_eq!(*x, 0); + /// ``` + fn default() -> Arc { + Arc::new(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Arc { + fn hash(&self, state: &mut H) { + (**self).hash(state) + } +} + +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Arc { + fn from(t: T) -> Self { + Arc::new(t) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&[T]> for Arc<[T]> { + /// Allocate a reference-counted slice and fill it by cloning `v`'s items. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: &[i32] = &[1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: &[T]) -> Arc<[T]> { + >::from_slice(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<&str> for Arc { + /// Allocate a reference-counted `str` and copy `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let shared: Arc = Arc::from("eggplant"); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: &str) -> Arc { + let arc = Arc::<[u8]>::from(v.as_bytes()); + unsafe { Arc::from_raw(Arc::into_raw(arc) as *const str) } + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From for Arc { + /// Allocate a reference-counted `str` and copy `v` into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: String = "eggplant".to_owned(); + /// let shared: Arc = Arc::from(unique); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: String) -> Arc { + Arc::from(&v[..]) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Arc { + /// Move a boxed object to a new, reference-counted allocation. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: Box = Box::from("eggplant"); + /// let shared: Arc = Arc::from(unique); + /// assert_eq!("eggplant", &shared[..]); + /// ``` + #[inline] + fn from(v: Box) -> Arc { + Arc::from_box(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From> for Arc<[T]> { + /// Allocate a reference-counted slice and move `v`'s items into it. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let unique: Vec = vec![1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(unique); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(mut v: Vec) -> Arc<[T]> { + unsafe { + let arc = Arc::copy_from_slice(&v); + + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + + arc + } + } +} + +#[stable(feature = "shared_from_cow", since = "1.45.0")] +impl<'a, B> From> for Arc +where + B: ToOwned + ?Sized, + Arc: From<&'a B> + From, +{ + #[inline] + fn from(cow: Cow<'a, B>) -> Arc { + match cow { + Cow::Borrowed(s) => Arc::from(s), + Cow::Owned(s) => Arc::from(s), + } + } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Arc<[T; N]> { + type Error = Arc<[T]>; + + fn try_from(boxed_slice: Arc<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { Arc::from_raw(Arc::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl iter::FromIterator for Arc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Arc<[T]>` is done by first + /// collecting into a `Vec`. That is, when writing the following: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Arc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec` + /// and then it will allocate once for turning the `Vec` into the `Arc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Arc<[T]>`. For example: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::>()); + /// ``` + fn from_iter>(iter: I) -> Self { + ToArcSlice::to_arc_slice(iter.into_iter()) + } +} + +/// Specialization trait used for collecting into `Arc<[T]>`. +trait ToArcSlice: Iterator + Sized { + fn to_arc_slice(self) -> Arc<[T]>; +} + +impl> ToArcSlice for I { + default fn to_arc_slice(self) -> Arc<[T]> { + self.collect::>().into() + } +} + +impl> ToArcSlice for I { + fn to_arc_slice(self) -> Arc<[T]> { + // This is the case for a `TrustedLen` iterator. + let (low, high) = self.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, + high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + + unsafe { + // SAFETY: We need to ensure that the iterator has an exact length and we have. + Arc::from_iter_exact(self, low) + } + } else { + // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator + // length exceeding `usize::MAX`. + // The default implementation would collect into a vec which would panic. + // Thus we panic here immediately without invoking `Vec` code. + panic!("capacity overflow"); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl borrow::Borrow for Arc { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Arc { + fn as_ref(&self) -> &T { + &**self + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Arc {} + +/// Get the offset within an `ArcInner` for the payload behind a pointer. +/// +/// # Safety +/// +/// The pointer must point to (and have valid metadata for) a previously +/// valid instance of T, but the T is allowed to be dropped. +unsafe fn data_offset(ptr: *const T) -> isize { + // Align the unsized value to the end of the ArcInner. + // Because RcBox is repr(C), it will always be the last field in memory. + // SAFETY: since the only unsized types possible are slices, trait objects, + // and extern types, the input safety requirement is currently enough to + // satisfy the requirements of align_of_val_raw; this is an implementation + // detail of the language that may not be relied upon outside of std. + unsafe { data_offset_align(align_of_val_raw(ptr)) } +} + +#[inline] +fn data_offset_align(align: usize) -> isize { + let layout = Layout::new::>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} +//! Utilities for formatting and printing `String`s. +//! +//! This module contains the runtime support for the [`format!`] syntax extension. +//! This macro is implemented in the compiler to emit calls to this module in +//! order to format arguments at runtime into strings. +//! +//! # Usage +//! +//! The [`format!`] macro is intended to be familiar to those coming from C's +//! `printf`/`fprintf` functions or Python's `str.format` function. +//! +//! Some examples of the [`format!`] extension are: +//! +//! ``` +//! format!("Hello"); // => "Hello" +//! format!("Hello, {}!", "world"); // => "Hello, world!" +//! format!("The number is {}", 1); // => "The number is 1" +//! format!("{:?}", (3, 4)); // => "(3, 4)" +//! format!("{value}", value=4); // => "4" +//! format!("{} {}", 1, 2); // => "1 2" +//! format!("{:04}", 42); // => "0042" with leading zeros +//! format!("{:#?}", (100, 200)); // => "( +//! // 100, +//! // 200, +//! // )" +//! ``` +//! +//! From these, you can see that the first argument is a format string. It is +//! required by the compiler for this to be a string literal; it cannot be a +//! variable passed in (in order to perform validity checking). The compiler +//! will then parse the format string and determine if the list of arguments +//! provided is suitable to pass to this format string. +//! +//! To convert a single value to a string, use the [`to_string`] method. This +//! will use the [`Display`] formatting trait. +//! +//! ## Positional parameters +//! +//! Each formatting argument is allowed to specify which value argument it's +//! referencing, and if omitted it is assumed to be "the next argument". For +//! example, the format string `{} {} {}` would take three parameters, and they +//! would be formatted in the same order as they're given. The format string +//! `{2} {1} {0}`, however, would format arguments in reverse order. +//! +//! Things can get a little tricky once you start intermingling the two types of +//! positional specifiers. The "next argument" specifier can be thought of as an +//! iterator over the argument. Each time a "next argument" specifier is seen, +//! the iterator advances. This leads to behavior like this: +//! +//! ``` +//! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2" +//! ``` +//! +//! The internal iterator over the argument has not been advanced by the time +//! the first `{}` is seen, so it prints the first argument. Then upon reaching +//! the second `{}`, the iterator has advanced forward to the second argument. +//! Essentially, parameters that explicitly name their argument do not affect +//! parameters that do not name an argument in terms of positional specifiers. +//! +//! A format string is required to use all of its arguments, otherwise it is a +//! compile-time error. You may refer to the same argument more than once in the +//! format string. +//! +//! ## Named parameters +//! +//! Rust itself does not have a Python-like equivalent of named parameters to a +//! function, but the [`format!`] macro is a syntax extension that allows it to +//! leverage named parameters. Named parameters are listed at the end of the +//! argument list and have the syntax: +//! +//! ```text +//! identifier '=' expression +//! ``` +//! +//! For example, the following [`format!`] expressions all use named argument: +//! +//! ``` +//! format!("{argument}", argument = "test"); // => "test" +//! format!("{name} {}", 1, name = 2); // => "2 1" +//! format!("{a} {c} {b}", a="a", b='b', c=3); // => "a 3 b" +//! ``` +//! +//! It is not valid to put positional parameters (those without names) after +//! arguments that have names. Like with positional parameters, it is not +//! valid to provide named parameters that are unused by the format string. +//! +//! # Formatting Parameters +//! +//! Each argument being formatted can be transformed by a number of formatting +//! parameters (corresponding to `format_spec` in [the syntax](#syntax)). These +//! parameters affect the string representation of what's being formatted. +//! +//! ## Width +//! +//! ``` +//! // All of these print "Hello x !" +//! println!("Hello {:5}!", "x"); +//! println!("Hello {:1$}!", "x", 5); +//! println!("Hello {1:0$}!", 5, "x"); +//! println!("Hello {:width$}!", "x", width = 5); +//! ``` +//! +//! This is a parameter for the "minimum width" that the format should take up. +//! If the value's string does not fill up this many characters, then the +//! padding specified by fill/alignment will be used to take up the required +//! space (see below). +//! +//! The value for the width can also be provided as a [`usize`] in the list of +//! parameters by adding a postfix `$`, indicating that the second argument is +//! a [`usize`] specifying the width. +//! +//! Referring to an argument with the dollar syntax does not affect the "next +//! argument" counter, so it's usually a good idea to refer to arguments by +//! position, or use named arguments. +//! +//! ## Fill/Alignment +//! +//! ``` +//! assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); +//! assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!"); +//! assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !"); +//! assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!"); +//! ``` +//! +//! The optional fill character and alignment is provided normally in conjunction with the +//! [`width`](#width) parameter. It must be defined before `width`, right after the `:`. +//! This indicates that if the value being formatted is smaller than +//! `width` some extra characters will be printed around it. +//! Filling comes in the following variants for different alignments: +//! +//! * `[fill]<` - the argument is left-aligned in `width` columns +//! * `[fill]^` - the argument is center-aligned in `width` columns +//! * `[fill]>` - the argument is right-aligned in `width` columns +//! +//! The default [fill/alignment](#fillalignment) for non-numerics is a space and +//! left-aligned. The +//! default for numeric formatters is also a space character but with right-alignment. If +//! the `0` flag (see below) is specified for numerics, then the implicit fill character is +//! `0`. +//! +//! Note that alignment may not be implemented by some types. In particular, it +//! is not generally implemented for the `Debug` trait. A good way to ensure +//! padding is applied is to format your input, then pad this resulting string +//! to obtain your output: +//! +//! ``` +//! println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello Some("hi") !" +//! ``` +//! +//! ## Sign/`#`/`0` +//! +//! ``` +//! assert_eq!(format!("Hello {:+}!", 5), "Hello +5!"); +//! assert_eq!(format!("{:#x}!", 27), "0x1b!"); +//! assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!"); +//! assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!"); +//! assert_eq!(format!("{:#010x}!", 27), "0x0000001b!"); +//! ``` +//! +//! These are all flags altering the behavior of the formatter. +//! +//! * `+` - This is intended for numeric types and indicates that the sign +//! should always be printed. Positive signs are never printed by +//! default, and the negative sign is only printed by default for signed values. +//! This flag indicates that the correct sign (`+` or `-`) should always be printed. +//! * `-` - Currently not used +//! * `#` - This flag indicates that the "alternate" form of printing should +//! be used. The alternate forms are: +//! * `#?` - pretty-print the [`Debug`] formatting (adds linebreaks and indentation) +//! * `#x` - precedes the argument with a `0x` +//! * `#X` - precedes the argument with a `0x` +//! * `#b` - precedes the argument with a `0b` +//! * `#o` - precedes the argument with a `0o` +//! * `0` - This is used to indicate for integer formats that the padding to `width` should +//! both be done with a `0` character as well as be sign-aware. A format +//! like `{:08}` would yield `00000001` for the integer `1`, while the +//! same format would yield `-0000001` for the integer `-1`. Notice that +//! the negative version has one fewer zero than the positive version. +//! Note that padding zeros are always placed after the sign (if any) +//! and before the digits. When used together with the `#` flag, a similar +//! rule applies: padding zeros are inserted after the prefix but before +//! the digits. The prefix is included in the total width. +//! +//! ## Precision +//! +//! For non-numeric types, this can be considered a "maximum width". If the resulting string is +//! longer than this width, then it is truncated down to this many characters and that truncated +//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set. +//! +//! For integral types, this is ignored. +//! +//! For floating-point types, this indicates how many digits after the decimal point should be +//! printed. +//! +//! There are three possible ways to specify the desired `precision`: +//! +//! 1. An integer `.N`: +//! +//! the integer `N` itself is the precision. +//! +//! 2. An integer or name followed by dollar sign `.N$`: +//! +//! use format *argument* `N` (which must be a `usize`) as the precision. +//! +//! 3. An asterisk `.*`: +//! +//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the +//! first input holds the `usize` precision, and the second holds the value to print. Note that +//! in this case, if one uses the format string `{:.*}`, then the `` part refers +//! to the *value* to print, and the `precision` must come in the input preceding ``. +//! +//! For example, the following calls all print the same thing `Hello x is 0.01000`: +//! +//! ``` +//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)} +//! println!("Hello {0} is {1:.5}", "x", 0.01); +//! +//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)} +//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01); +//! +//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} +//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01); +//! +//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision +//! // specified in first of next two args (5)} +//! println!("Hello {} is {:.*}", "x", 5, 0.01); +//! +//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision +//! // specified in its predecessor (5)} +//! println!("Hello {} is {2:.*}", "x", 5, 0.01); +//! +//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified +//! // in arg "prec" (5)} +//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); +//! ``` +//! +//! While these: +//! +//! ``` +//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56); +//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56"); +//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56"); +//! ``` +//! +//! print three significantly different things: +//! +//! ```text +//! Hello, `1234.560` has 3 fractional digits +//! Hello, `123` has 3 characters +//! Hello, ` 123` has 3 right-aligned characters +//! ``` +//! +//! ## Localization +//! +//! In some programming languages, the behavior of string formatting functions +//! depends on the operating system's locale setting. The format functions +//! provided by Rust's standard library do not have any concept of locale and +//! will produce the same results on all systems regardless of user +//! configuration. +//! +//! For example, the following code will always print `1.5` even if the system +//! locale uses a decimal separator other than a dot. +//! +//! ``` +//! println!("The value is {}", 1.5); +//! ``` +//! +//! # Escaping +//! +//! The literal characters `{` and `}` may be included in a string by preceding +//! them with the same character. For example, the `{` character is escaped with +//! `{{` and the `}` character is escaped with `}}`. +//! +//! ``` +//! assert_eq!(format!("Hello {{}}"), "Hello {}"); +//! assert_eq!(format!("{{ Hello"), "{ Hello"); +//! ``` +//! +//! # Syntax +//! +//! To summarize, here you can find the full grammar of format strings. +//! The syntax for the formatting language used is drawn from other languages, +//! so it should not be too alien. Arguments are formatted with Python-like +//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like +//! `%`. The actual grammar for the formatting syntax is: +//! +//! ```text +//! format_string := text [ maybe_format text ] * +//! maybe_format := '{' '{' | '}' '}' | format +//! format := '{' [ argument ] [ ':' format_spec ] '}' +//! argument := integer | identifier +//! +//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type +//! fill := character +//! align := '<' | '^' | '>' +//! sign := '+' | '-' +//! width := count +//! precision := count | '*' +//! type := '' | '?' | 'x?' | 'X?' | identifier +//! count := parameter | integer +//! parameter := argument '$' +//! ``` +//! In the above grammar, `text` may not contain any `'{'` or `'}'` characters. +//! +//! # Formatting traits +//! +//! When requesting that an argument be formatted with a particular type, you +//! are actually requesting that an argument ascribes to a particular trait. +//! This allows multiple actual types to be formatted via `{:x}` (like [`i8`] as +//! well as [`isize`]). The current mapping of types to traits is: +//! +//! * *nothing* ⇒ [`Display`] +//! * `?` ⇒ [`Debug`] +//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers +//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers +//! * `o` ⇒ [`Octal`] +//! * `x` ⇒ [`LowerHex`] +//! * `X` ⇒ [`UpperHex`] +//! * `p` ⇒ [`Pointer`] +//! * `b` ⇒ [`Binary`] +//! * `e` ⇒ [`LowerExp`] +//! * `E` ⇒ [`UpperExp`] +//! +//! What this means is that any type of argument which implements the +//! [`fmt::Binary`][`Binary`] trait can then be formatted with `{:b}`. Implementations +//! are provided for these traits for a number of primitive types by the +//! standard library as well. If no format is specified (as in `{}` or `{:6}`), +//! then the format trait used is the [`Display`] trait. +//! +//! When implementing a format trait for your own type, you will have to +//! implement a method of the signature: +//! +//! ``` +//! # #![allow(dead_code)] +//! # use std::fmt; +//! # struct Foo; // our custom type +//! # impl fmt::Display for Foo { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! # write!(f, "testing, testing") +//! # } } +//! ``` +//! +//! Your type will be passed as `self` by-reference, and then the function +//! should emit output into the `f.buf` stream. It is up to each format trait +//! implementation to correctly adhere to the requested formatting parameters. +//! The values of these parameters will be listed in the fields of the +//! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also +//! provides some helper methods. +//! +//! Additionally, the return value of this function is [`fmt::Result`] which is a +//! type alias of [`Result`]`<(), `[`std::fmt::Error`]`>`. Formatting implementations +//! should ensure that they propagate errors from the [`Formatter`] (e.g., when +//! calling [`write!`]). However, they should never return errors spuriously. That +//! is, a formatting implementation must and may only return an error if the +//! passed-in [`Formatter`] returns an error. This is because, contrary to what +//! the function signature might suggest, string formatting is an infallible +//! operation. This function only returns a result because writing to the +//! underlying stream might fail and it must provide a way to propagate the fact +//! that an error has occurred back up the stack. +//! +//! An example of implementing the formatting traits would look +//! like: +//! +//! ``` +//! use std::fmt; +//! +//! #[derive(Debug)] +//! struct Vector2D { +//! x: isize, +//! y: isize, +//! } +//! +//! impl fmt::Display for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! // The `f` value implements the `Write` trait, which is what the +//! // write! macro is expecting. Note that this formatting ignores the +//! // various flags provided to format strings. +//! write!(f, "({}, {})", self.x, self.y) +//! } +//! } +//! +//! // Different traits allow different forms of output of a type. The meaning +//! // of this format is to print the magnitude of a vector. +//! impl fmt::Binary for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! let magnitude = (self.x * self.x + self.y * self.y) as f64; +//! let magnitude = magnitude.sqrt(); +//! +//! // Respect the formatting flags by using the helper method +//! // `pad_integral` on the Formatter object. See the method +//! // documentation for details, and the function `pad` can be used +//! // to pad strings. +//! let decimals = f.precision().unwrap_or(3); +//! let string = format!("{:.*}", decimals, magnitude); +//! f.pad_integral(true, "", &string) +//! } +//! } +//! +//! fn main() { +//! let myvector = Vector2D { x: 3, y: 4 }; +//! +//! println!("{}", myvector); // => "(3, 4)" +//! println!("{:?}", myvector); // => "Vector2D {x: 3, y:4}" +//! println!("{:10.3b}", myvector); // => " 5.000" +//! } +//! ``` +//! +//! ### `fmt::Display` vs `fmt::Debug` +//! +//! These two formatting traits have distinct purposes: +//! +//! - [`fmt::Display`][`Display`] implementations assert that the type can be faithfully +//! represented as a UTF-8 string at all times. It is **not** expected that +//! all types implement the [`Display`] trait. +//! - [`fmt::Debug`][`Debug`] implementations should be implemented for **all** public types. +//! Output will typically represent the internal state as faithfully as possible. +//! The purpose of the [`Debug`] trait is to facilitate debugging Rust code. In +//! most cases, using `#[derive(Debug)]` is sufficient and recommended. +//! +//! Some examples of the output from both traits: +//! +//! ``` +//! assert_eq!(format!("{} {:?}", 3, 4), "3 4"); +//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); +//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); +//! ``` +//! +//! # Related macros +//! +//! There are a number of related macros in the [`format!`] family. The ones that +//! are currently implemented are: +//! +//! ```ignore (only-for-syntax-highlight) +//! format! // described above +//! write! // first argument is a &mut io::Write, the destination +//! writeln! // same as write but appends a newline +//! print! // the format string is printed to the standard output +//! println! // same as print but appends a newline +//! eprint! // the format string is printed to the standard error +//! eprintln! // same as eprint but appends a newline +//! format_args! // described below. +//! ``` +//! +//! ### `write!` +//! +//! This and [`writeln!`] are two macros which are used to emit the format string +//! to a specified stream. This is used to prevent intermediate allocations of +//! format strings and instead directly write the output. Under the hood, this +//! function is actually invoking the [`write_fmt`] function defined on the +//! [`std::io::Write`] trait. Example usage is: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! use std::io::Write; +//! let mut w = Vec::new(); +//! write!(&mut w, "Hello {}!", "world"); +//! ``` +//! +//! ### `print!` +//! +//! This and [`println!`] emit their output to stdout. Similarly to the [`write!`] +//! macro, the goal of these macros is to avoid intermediate allocations when +//! printing output. Example usage is: +//! +//! ``` +//! print!("Hello {}!", "world"); +//! println!("I have a newline {}", "character at the end"); +//! ``` +//! ### `eprint!` +//! +//! The [`eprint!`] and [`eprintln!`] macros are identical to +//! [`print!`] and [`println!`], respectively, except they emit their +//! output to stderr. +//! +//! ### `format_args!` +//! +//! This is a curious macro used to safely pass around +//! an opaque object describing the format string. This object +//! does not require any heap allocations to create, and it only +//! references information on the stack. Under the hood, all of +//! the related macros are implemented in terms of this. First +//! off, some example usage is: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! use std::fmt; +//! use std::io::{self, Write}; +//! +//! let mut some_writer = io::stdout(); +//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); +//! +//! fn my_fmt_fn(args: fmt::Arguments) { +//! write!(&mut io::stdout(), "{}", args); +//! } +//! my_fmt_fn(format_args!(", or a {} too", "function")); +//! ``` +//! +//! The result of the [`format_args!`] macro is a value of type [`fmt::Arguments`]. +//! This structure can then be passed to the [`write`] and [`format`] functions +//! inside this module in order to process the format string. +//! The goal of this macro is to even further prevent intermediate allocations +//! when dealing with formatting strings. +//! +//! For example, a logging library could use the standard formatting syntax, but +//! it would internally pass around this structure until it has been determined +//! where output should go to. +//! +//! [`fmt::Result`]: Result +//! [`Result`]: core::result::Result +//! [`std::fmt::Error`]: Error +//! [`write!`]: core::write +//! [`write`]: core::write +//! [`format!`]: crate::format +//! [`to_string`]: crate::string::ToString +//! [`writeln!`]: core::writeln +//! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt +//! [`std::io::Write`]: ../../std/io/trait.Write.html +//! [`print!`]: ../../std/macro.print.html +//! [`println!`]: ../../std/macro.println.html +//! [`eprint!`]: ../../std/macro.eprint.html +//! [`eprintln!`]: ../../std/macro.eprintln.html +//! [`format_args!`]: core::format_args +//! [`fmt::Arguments`]: Arguments +//! [`format`]: crate::format + +#![stable(feature = "rust1", since = "1.0.0")] + +#[unstable(feature = "fmt_internals", issue = "none")] +pub use core::fmt::rt; +#[stable(feature = "fmt_flags_align", since = "1.28.0")] +pub use core::fmt::Alignment; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::Error; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{write, ArgumentV1, Arguments}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Binary, Octal}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Debug, Display}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{Formatter, Result, Write}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{LowerExp, UpperExp}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{LowerHex, Pointer, UpperHex}; + +use crate::string; + +/// The `format` function takes an [`Arguments`] struct and returns the resulting +/// formatted string. +/// +/// The [`Arguments`] instance can be created with the [`format_args!`] macro. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::fmt; +/// +/// let s = fmt::format(format_args!("Hello, {}!", "world")); +/// assert_eq!(s, "Hello, world!"); +/// ``` +/// +/// Please note that using [`format!`] might be preferable. +/// Example: +/// +/// ``` +/// let s = format!("Hello, {}!", "world"); +/// assert_eq!(s, "Hello, world!"); +/// ``` +/// +/// [`format_args!`]: core::format_args +/// [`format!`]: crate::format +#[stable(feature = "rust1", since = "1.0.0")] +pub fn format(args: Arguments<'_>) -> string::String { + let capacity = args.estimated_capacity(); + let mut output = string::String::with_capacity(capacity); + output.write_fmt(args).expect("a formatting trait implementation returned an error"); + output +} +use super::*; + +use std::boxed::Box; +use std::cell::RefCell; +use std::clone::Clone; +use std::convert::{From, TryInto}; +use std::mem::drop; +use std::option::Option::{self, None, Some}; +use std::result::Result::{Err, Ok}; + +#[test] +fn test_clone() { + let x = Rc::new(RefCell::new(5)); + let y = x.clone(); + *x.borrow_mut() = 20; + assert_eq!(*y.borrow(), 20); +} + +#[test] +fn test_simple() { + let x = Rc::new(5); + assert_eq!(*x, 5); +} + +#[test] +fn test_simple_clone() { + let x = Rc::new(5); + let y = x.clone(); + assert_eq!(*x, 5); + assert_eq!(*y, 5); +} + +#[test] +fn test_destructor() { + let x: Rc> = Rc::new(box 5); + assert_eq!(**x, 5); +} + +#[test] +fn test_live() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: RefCell>>, + } + + let a = Rc::new(Cycle { x: RefCell::new(None) }); + let b = Rc::downgrade(&a.clone()); + *a.x.borrow_mut() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn is_unique() { + let x = Rc::new(3); + assert!(Rc::is_unique(&x)); + let y = x.clone(); + assert!(!Rc::is_unique(&x)); + drop(y); + assert!(Rc::is_unique(&x)); + let w = Rc::downgrade(&x); + assert!(!Rc::is_unique(&x)); + drop(w); + assert!(Rc::is_unique(&x)); +} + +#[test] +fn test_strong_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + let b = w.upgrade().expect("upgrade of live rc failed"); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Rc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 1); + drop(w); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Rc::strong_count(&a) == 2); + assert!(Rc::weak_count(&a) == 0); + drop(c); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::::new()), 0); + assert_eq!(Weak::strong_count(&Weak::::new()), 0); + + let a = Rc::new(0); + let w = Rc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 1); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 2); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 2); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 1); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), 1); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), 0); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Rc::new(3); + assert_eq!(Rc::try_unwrap(x), Ok(3)); + let x = Rc::new(4); + let _y = x.clone(); + assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_from_raw() { + let x = Rc::new(box "hello"); + let y = x.clone(); + + let x_ptr = Rc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Rc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let rc: Rc = Rc::from("foo"); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(rc, rc2); + + let rc: Rc = Rc::new(123); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(rc2.to_string(), "123"); +} + +#[test] +fn into_from_weak_raw() { + let x = Rc::new(box "hello"); + let y = Rc::downgrade(&x); + + let y_ptr = Weak::into_raw(y); + unsafe { + assert_eq!(**y_ptr, "hello"); + + let y = Weak::from_raw(y_ptr); + let y_up = Weak::upgrade(&y).unwrap(); + assert_eq!(**y_up, "hello"); + drop(y_up); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_weak_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Rc = Rc::from("foo"); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert!(weak.ptr_eq(&weak2)); + + let arc: Rc = Rc::new(123); + let weak: Weak = Rc::downgrade(&arc); + + let ptr = Weak::into_raw(weak.clone()); + let weak2 = unsafe { Weak::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert!(weak.ptr_eq(&weak2)); +} + +#[test] +fn get_mut() { + let mut x = Rc::new(3); + *Rc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Rc::get_mut(&mut x).is_none()); + drop(y); + assert!(Rc::get_mut(&mut x).is_some()); + let _w = Rc::downgrade(&x); + assert!(Rc::get_mut(&mut x).is_none()); +} + +#[test] +fn test_cowrc_clone_make_unique() { + let mut cow0 = Rc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Rc::make_mut(&mut cow0)); + assert!(75 == *Rc::make_mut(&mut cow1)); + assert!(75 == *Rc::make_mut(&mut cow2)); + + *Rc::make_mut(&mut cow0) += 1; + *Rc::make_mut(&mut cow1) += 2; + *Rc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowrc_clone_unique2() { + let mut cow0 = Rc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowrc_clone_weak() { + let mut cow0 = Rc::new(75); + let cow1_weak = Rc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +#[test] +fn test_show() { + let foo = Rc::new(75); + assert_eq!(format!("{:?}", foo), "75"); +} + +#[test] +fn test_unsized() { + let foo: Rc<[i32]> = Rc::new([1, 2, 3]); + assert_eq!(foo, foo.clone()); +} + +#[test] +fn test_maybe_thin_unsized() { + // If/when custom thin DSTs exist, this test should be updated to use one + use std::ffi::{CStr, CString}; + + let x: Rc = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + assert_eq!(format!("{:?}", x), "\"swordfish\""); + let y: Weak = Rc::downgrade(&x); + drop(x); + + // At this point, the weak points to a dropped DST + assert!(y.upgrade().is_none()); + // But we still need to be able to get the alloc layout to drop. + // CStr has no drop glue, but custom DSTs might, and need to work. + drop(y); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_rc = Rc::from(foo); + assert!(123 == *foo_rc); +} + +#[test] +fn test_new_weak() { + let foo: Weak = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Rc::new(5); + let same_five = five.clone(); + let other_five = Rc::new(5); + + assert!(Rc::ptr_eq(&five, &same_five)); + assert!(!Rc::ptr_eq(&five, &other_five)); +} + +#[test] +fn test_from_str() { + let r: Rc = Rc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Rc<[X]> = Rc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = + &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; + + // Should panic, but not cause memory corruption + let _r: Rc<[Fail]> = Rc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box = box 123; + let r: Rc = Rc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Rc = Rc::from(s); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box = box 123; + let r: Rc = Rc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box = box (); + let r: Rc = Rc::from(b); + + assert_eq!(format!("{:?}", r), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Rc = Rc::new(i32::MAX); + let r2: Rc = Rc::new("abc"); + + assert!(r1.clone().downcast::().is_err()); + + let r1i32 = r1.downcast::(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Rc::new(i32::MAX)); + + assert!(r2.clone().downcast::().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Rc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} + +#[test] +fn test_rc_cyclic_with_zero_refs() { + struct ZeroRefs { + inner: Weak, + } + + let zero_refs = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + ZeroRefs { inner: Weak::new() } + }); + + assert_eq!(Rc::strong_count(&zero_refs), 1); + assert_eq!(Rc::weak_count(&zero_refs), 0); + assert_eq!(zero_refs.inner.strong_count(), 0); + assert_eq!(zero_refs.inner.weak_count(), 0); +} + +#[test] +fn test_rc_cyclic_with_one_ref() { + struct OneRef { + inner: Weak, + } + + let one_ref = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + OneRef { inner: inner.clone() } + }); + + assert_eq!(Rc::strong_count(&one_ref), 1); + assert_eq!(Rc::weak_count(&one_ref), 1); + + let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); + assert!(Rc::ptr_eq(&one_ref, &one_ref2)); + + assert_eq!(one_ref.inner.strong_count(), 2); + assert_eq!(one_ref.inner.weak_count(), 1); +} + +#[test] +fn test_rc_cyclic_with_two_ref() { + struct TwoRefs { + inner: Weak, + inner1: Weak, + } + + let two_refs = Rc::new_cyclic(|inner| { + assert_eq!(inner.strong_count(), 0); + assert!(inner.upgrade().is_none()); + TwoRefs { inner: inner.clone(), inner1: inner.clone() } + }); + + assert_eq!(Rc::strong_count(&two_refs), 1); + assert_eq!(Rc::weak_count(&two_refs), 2); + + let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap(); + assert!(Rc::ptr_eq(&two_refs, &two_ref3)); + + let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap(); + assert!(Rc::ptr_eq(&two_refs, &two_ref2)); + + assert_eq!(Rc::strong_count(&two_refs), 3); + assert_eq!(Rc::weak_count(&two_refs), 2); +} +//! A doubly-linked list with owned nodes. +//! +//! The `LinkedList` allows pushing and popping elements at either end +//! in constant time. +//! +//! NOTE: It is almost always better to use [`Vec`] or [`VecDeque`] because +//! array-based containers are generally faster, +//! more memory efficient, and make better use of CPU cache. +//! +//! [`Vec`]: crate::vec::Vec +//! [`VecDeque`]: super::vec_deque::VecDeque + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::Ordering; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::iter::{FromIterator, FusedIterator}; +use core::marker::PhantomData; +use core::mem; +use core::ptr::NonNull; + +use super::SpecExtend; +use crate::boxed::Box; + +#[cfg(test)] +mod tests; + +/// A doubly-linked list with owned nodes. +/// +/// The `LinkedList` allows pushing and popping elements at either end +/// in constant time. +/// +/// NOTE: It is almost always better to use `Vec` or `VecDeque` because +/// array-based containers are generally faster, +/// more memory efficient, and make better use of CPU cache. +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")] +pub struct LinkedList { + head: Option>>, + tail: Option>>, + len: usize, + marker: PhantomData>>, +} + +struct Node { + next: Option>>, + prev: Option>>, + element: T, +} + +/// An iterator over the elements of a `LinkedList`. +/// +/// This `struct` is created by [`LinkedList::iter()`]. See its +/// documentation for more. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + head: Option>>, + tail: Option>>, + len: usize, + marker: PhantomData<&'a Node>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.len).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { ..*self } + } +} + +/// A mutable iterator over the elements of a `LinkedList`. +/// +/// This `struct` is created by [`LinkedList::iter_mut()`]. See its +/// documentation for more. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, T: 'a> { + // We do *not* exclusively own the entire list here, references to node's `element` + // have been handed out by the iterator! So be careful when using this; the methods + // called must be aware that there can be aliasing pointers to `element`. + list: &'a mut LinkedList, + head: Option>>, + tail: Option>>, + len: usize, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IterMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IterMut").field(&self.list).field(&self.len).finish() + } +} + +/// An owning iterator over the elements of a `LinkedList`. +/// +/// This `struct` is created by the [`into_iter`] method on [`LinkedList`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: LinkedList::into_iter +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter { + list: LinkedList, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.list).finish() + } +} + +impl Node { + fn new(element: T) -> Self { + Node { next: None, prev: None, element } + } + + fn into_element(self: Box) -> T { + self.element + } +} + +// private methods +impl LinkedList { + /// Adds the given node to the front of the list. + #[inline] + fn push_front_node(&mut self, mut node: Box>) { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + unsafe { + node.next = self.head; + node.prev = None; + let node = Some(Box::leak(node).into()); + + match self.head { + None => self.tail = node, + // Not creating new mutable (unique!) references overlapping `element`. + Some(head) => (*head.as_ptr()).prev = node, + } + + self.head = node; + self.len += 1; + } + } + + /// Removes and returns the node at the front of the list. + #[inline] + fn pop_front_node(&mut self) -> Option>> { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + self.head.map(|node| unsafe { + let node = Box::from_raw(node.as_ptr()); + self.head = node.next; + + match self.head { + None => self.tail = None, + // Not creating new mutable (unique!) references overlapping `element`. + Some(head) => (*head.as_ptr()).prev = None, + } + + self.len -= 1; + node + }) + } + + /// Adds the given node to the back of the list. + #[inline] + fn push_back_node(&mut self, mut node: Box>) { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + unsafe { + node.next = None; + node.prev = self.tail; + let node = Some(Box::leak(node).into()); + + match self.tail { + None => self.head = node, + // Not creating new mutable (unique!) references overlapping `element`. + Some(tail) => (*tail.as_ptr()).next = node, + } + + self.tail = node; + self.len += 1; + } + } + + /// Removes and returns the node at the back of the list. + #[inline] + fn pop_back_node(&mut self) -> Option>> { + // This method takes care not to create mutable references to whole nodes, + // to maintain validity of aliasing pointers into `element`. + self.tail.map(|node| unsafe { + let node = Box::from_raw(node.as_ptr()); + self.tail = node.prev; + + match self.tail { + None => self.head = None, + // Not creating new mutable (unique!) references overlapping `element`. + Some(tail) => (*tail.as_ptr()).next = None, + } + + self.len -= 1; + node + }) + } + + /// Unlinks the specified node from the current list. + /// + /// Warning: this will not check that the provided node belongs to the current list. + /// + /// This method takes care not to create mutable references to `element`, to + /// maintain validity of aliasing pointers. + #[inline] + unsafe fn unlink_node(&mut self, mut node: NonNull>) { + let node = unsafe { node.as_mut() }; // this one is ours now, we can create an &mut. + + // Not creating new mutable (unique!) references overlapping `element`. + match node.prev { + Some(prev) => unsafe { (*prev.as_ptr()).next = node.next }, + // this node is the head node + None => self.head = node.next, + }; + + match node.next { + Some(next) => unsafe { (*next.as_ptr()).prev = node.prev }, + // this node is the tail node + None => self.tail = node.prev, + }; + + self.len -= 1; + } + + /// Splices a series of nodes between two existing nodes. + /// + /// Warning: this will not check that the provided node belongs to the two existing lists. + #[inline] + unsafe fn splice_nodes( + &mut self, + existing_prev: Option>>, + existing_next: Option>>, + mut splice_start: NonNull>, + mut splice_end: NonNull>, + splice_length: usize, + ) { + // This method takes care not to create multiple mutable references to whole nodes at the same time, + // to maintain validity of aliasing pointers into `element`. + if let Some(mut existing_prev) = existing_prev { + unsafe { + existing_prev.as_mut().next = Some(splice_start); + } + } else { + self.head = Some(splice_start); + } + if let Some(mut existing_next) = existing_next { + unsafe { + existing_next.as_mut().prev = Some(splice_end); + } + } else { + self.tail = Some(splice_end); + } + unsafe { + splice_start.as_mut().prev = existing_prev; + splice_end.as_mut().next = existing_next; + } + + self.len += splice_length; + } + + /// Detaches all nodes from a linked list as a series of nodes. + #[inline] + fn detach_all_nodes(mut self) -> Option<(NonNull>, NonNull>, usize)> { + let head = self.head.take(); + let tail = self.tail.take(); + let len = mem::replace(&mut self.len, 0); + if let Some(head) = head { + let tail = tail.unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() }); + Some((head, tail, len)) + } else { + None + } + } + + #[inline] + unsafe fn split_off_before_node( + &mut self, + split_node: Option>>, + at: usize, + ) -> Self { + // The split node is the new head node of the second part + if let Some(mut split_node) = split_node { + let first_part_head; + let first_part_tail; + unsafe { + first_part_tail = split_node.as_mut().prev.take(); + } + if let Some(mut tail) = first_part_tail { + unsafe { + tail.as_mut().next = None; + } + first_part_head = self.head; + } else { + first_part_head = None; + } + + let first_part = LinkedList { + head: first_part_head, + tail: first_part_tail, + len: at, + marker: PhantomData, + }; + + // Fix the head ptr of the second part + self.head = Some(split_node); + self.len = self.len - at; + + first_part + } else { + mem::replace(self, LinkedList::new()) + } + } + + #[inline] + unsafe fn split_off_after_node( + &mut self, + split_node: Option>>, + at: usize, + ) -> Self { + // The split node is the new tail node of the first part and owns + // the head of the second part. + if let Some(mut split_node) = split_node { + let second_part_head; + let second_part_tail; + unsafe { + second_part_head = split_node.as_mut().next.take(); + } + if let Some(mut head) = second_part_head { + unsafe { + head.as_mut().prev = None; + } + second_part_tail = self.tail; + } else { + second_part_tail = None; + } + + let second_part = LinkedList { + head: second_part_head, + tail: second_part_tail, + len: self.len - at, + marker: PhantomData, + }; + + // Fix the tail ptr of the first part + self.tail = Some(split_node); + self.len = at; + + second_part + } else { + mem::replace(self, LinkedList::new()) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for LinkedList { + /// Creates an empty `LinkedList`. + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl LinkedList { + /// Creates an empty `LinkedList`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let list: LinkedList = LinkedList::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn new() -> Self { + LinkedList { head: None, tail: None, len: 0, marker: PhantomData } + } + + /// Moves all elements from `other` to the end of the list. + /// + /// This reuses all the nodes from `other` and moves them into `self`. After + /// this operation, `other` becomes empty. + /// + /// This operation should compute in *O*(1) time and *O*(1) memory. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list1 = LinkedList::new(); + /// list1.push_back('a'); + /// + /// let mut list2 = LinkedList::new(); + /// list2.push_back('b'); + /// list2.push_back('c'); + /// + /// list1.append(&mut list2); + /// + /// let mut iter = list1.iter(); + /// assert_eq!(iter.next(), Some(&'a')); + /// assert_eq!(iter.next(), Some(&'b')); + /// assert_eq!(iter.next(), Some(&'c')); + /// assert!(iter.next().is_none()); + /// + /// assert!(list2.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn append(&mut self, other: &mut Self) { + match self.tail { + None => mem::swap(self, other), + Some(mut tail) => { + // `as_mut` is okay here because we have exclusive access to the entirety + // of both lists. + if let Some(mut other_head) = other.head.take() { + unsafe { + tail.as_mut().next = Some(other_head); + other_head.as_mut().prev = Some(tail); + } + + self.tail = other.tail.take(); + self.len += mem::replace(&mut other.len, 0); + } + } + } + } + + /// Moves all elements from `other` to the begin of the list. + #[unstable(feature = "linked_list_prepend", issue = "none")] + pub fn prepend(&mut self, other: &mut Self) { + match self.head { + None => mem::swap(self, other), + Some(mut head) => { + // `as_mut` is okay here because we have exclusive access to the entirety + // of both lists. + if let Some(mut other_tail) = other.tail.take() { + unsafe { + head.as_mut().prev = Some(other_tail); + other_tail.as_mut().next = Some(head); + } + + self.head = other.head.take(); + self.len += mem::replace(&mut other.len, 0); + } + } + } + } + + /// Provides a forward iterator. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list: LinkedList = LinkedList::new(); + /// + /// list.push_back(0); + /// list.push_back(1); + /// list.push_back(2); + /// + /// let mut iter = list.iter(); + /// assert_eq!(iter.next(), Some(&0)); + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { head: self.head, tail: self.tail, len: self.len, marker: PhantomData } + } + + /// Provides a forward iterator with mutable references. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list: LinkedList = LinkedList::new(); + /// + /// list.push_back(0); + /// list.push_back(1); + /// list.push_back(2); + /// + /// for element in list.iter_mut() { + /// *element += 10; + /// } + /// + /// let mut iter = list.iter(); + /// assert_eq!(iter.next(), Some(&10)); + /// assert_eq!(iter.next(), Some(&11)); + /// assert_eq!(iter.next(), Some(&12)); + /// assert_eq!(iter.next(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + IterMut { head: self.head, tail: self.tail, len: self.len, list: self } + } + + /// Provides a cursor at the front element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_front(&self) -> Cursor<'_, T> { + Cursor { index: 0, current: self.head, list: self } + } + + /// Provides a cursor with editing operations at the front element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> { + CursorMut { index: 0, current: self.head, list: self } + } + + /// Provides a cursor at the back element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_back(&self) -> Cursor<'_, T> { + Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } + } + + /// Provides a cursor with editing operations at the back element. + /// + /// The cursor is pointing to the "ghost" non-element if the list is empty. + #[inline] + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> { + CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } + } + + /// Returns `true` if the `LinkedList` is empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert!(dl.is_empty()); + /// + /// dl.push_front("foo"); + /// assert!(!dl.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.head.is_none() + } + + /// Returns the length of the `LinkedList`. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// assert_eq!(dl.len(), 1); + /// + /// dl.push_front(1); + /// assert_eq!(dl.len(), 2); + /// + /// dl.push_back(3); + /// assert_eq!(dl.len(), 3); + /// ``` + #[doc(alias = "length")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.len + } + + /// Removes all elements from the `LinkedList`. + /// + /// This operation should compute in *O*(*n*) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// dl.push_front(1); + /// assert_eq!(dl.len(), 2); + /// assert_eq!(dl.front(), Some(&1)); + /// + /// dl.clear(); + /// assert_eq!(dl.len(), 0); + /// assert_eq!(dl.front(), None); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + *self = Self::new(); + } + + /// Returns `true` if the `LinkedList` contains an element equal to the + /// given value. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut list: LinkedList = LinkedList::new(); + /// + /// list.push_back(0); + /// list.push_back(1); + /// list.push_back(2); + /// + /// assert_eq!(list.contains(&0), true); + /// assert_eq!(list.contains(&10), false); + /// ``` + #[stable(feature = "linked_list_contains", since = "1.12.0")] + pub fn contains(&self, x: &T) -> bool + where + T: PartialEq, + { + self.iter().any(|e| e == x) + } + + /// Provides a reference to the front element, or `None` if the list is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.front(), None); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front(), Some(&1)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn front(&self) -> Option<&T> { + unsafe { self.head.as_ref().map(|node| &node.as_ref().element) } + } + + /// Provides a mutable reference to the front element, or `None` if the list + /// is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.front(), None); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front(), Some(&1)); + /// + /// match dl.front_mut() { + /// None => {}, + /// Some(x) => *x = 5, + /// } + /// assert_eq!(dl.front(), Some(&5)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn front_mut(&mut self) -> Option<&mut T> { + unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) } + } + + /// Provides a reference to the back element, or `None` if the list is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.back(), None); + /// + /// dl.push_back(1); + /// assert_eq!(dl.back(), Some(&1)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back(&self) -> Option<&T> { + unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) } + } + + /// Provides a mutable reference to the back element, or `None` if the list + /// is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// assert_eq!(dl.back(), None); + /// + /// dl.push_back(1); + /// assert_eq!(dl.back(), Some(&1)); + /// + /// match dl.back_mut() { + /// None => {}, + /// Some(x) => *x = 5, + /// } + /// assert_eq!(dl.back(), Some(&5)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back_mut(&mut self) -> Option<&mut T> { + unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().element) } + } + + /// Adds an element first in the list. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// assert_eq!(dl.front().unwrap(), &2); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front().unwrap(), &1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_front(&mut self, elt: T) { + self.push_front_node(box Node::new(elt)); + } + + /// Removes the first element and returns it, or `None` if the list is + /// empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// assert_eq!(d.pop_front(), None); + /// + /// d.push_front(1); + /// d.push_front(3); + /// assert_eq!(d.pop_front(), Some(3)); + /// assert_eq!(d.pop_front(), Some(1)); + /// assert_eq!(d.pop_front(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_front(&mut self) -> Option { + self.pop_front_node().map(Node::into_element) + } + + /// Appends an element to the back of a list. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// d.push_back(1); + /// d.push_back(3); + /// assert_eq!(3, *d.back().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_back(&mut self, elt: T) { + self.push_back_node(box Node::new(elt)); + } + + /// Removes the last element from a list and returns it, or `None` if + /// it is empty. + /// + /// This operation should compute in *O*(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// assert_eq!(d.pop_back(), None); + /// d.push_back(1); + /// d.push_back(3); + /// assert_eq!(d.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option { + self.pop_back_node().map(Node::into_element) + } + + /// Splits the list into two at the given index. Returns everything after the given index, + /// including the index. + /// + /// This operation should compute in *O*(*n*) time. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// let mut split = d.split_off(2); + /// + /// assert_eq!(split.pop_front(), Some(1)); + /// assert_eq!(split.pop_front(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split_off(&mut self, at: usize) -> LinkedList { + let len = self.len(); + assert!(at <= len, "Cannot split off at a nonexistent index"); + if at == 0 { + return mem::take(self); + } else if at == len { + return Self::new(); + } + + // Below, we iterate towards the `i-1`th node, either from the start or the end, + // depending on which would be faster. + let split_node = if at - 1 <= len - 1 - (at - 1) { + let mut iter = self.iter_mut(); + // instead of skipping using .skip() (which creates a new struct), + // we skip manually so we can access the head field without + // depending on implementation details of Skip + for _ in 0..at - 1 { + iter.next(); + } + iter.head + } else { + // better off starting from the end + let mut iter = self.iter_mut(); + for _ in 0..len - 1 - (at - 1) { + iter.next_back(); + } + iter.tail + }; + unsafe { self.split_off_after_node(split_node, at) } + } + + /// Removes the element at the given index and returns it. + /// + /// This operation should compute in *O*(*n*) time. + /// + /// # Panics + /// Panics if at >= len + /// + /// # Examples + /// + /// ``` + /// #![feature(linked_list_remove)] + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// assert_eq!(d.remove(1), 2); + /// assert_eq!(d.remove(0), 3); + /// assert_eq!(d.remove(0), 1); + /// ``` + #[unstable(feature = "linked_list_remove", issue = "69210")] + pub fn remove(&mut self, at: usize) -> T { + let len = self.len(); + assert!(at < len, "Cannot remove at an index outside of the list bounds"); + + // Below, we iterate towards the node at the given index, either from + // the start or the end, depending on which would be faster. + let offset_from_end = len - at - 1; + if at <= offset_from_end { + let mut cursor = self.cursor_front_mut(); + for _ in 0..at { + cursor.move_next(); + } + cursor.remove_current().unwrap() + } else { + let mut cursor = self.cursor_back_mut(); + for _ in 0..offset_from_end { + cursor.move_prev(); + } + cursor.remove_current().unwrap() + } + } + + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the list and will not be yielded + /// by the iterator. + /// + /// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of + /// whether you choose to keep or remove it. + /// + /// # Examples + /// + /// Splitting a list into evens and odds, reusing the original list: + /// + /// ``` + /// #![feature(drain_filter)] + /// use std::collections::LinkedList; + /// + /// let mut numbers: LinkedList = LinkedList::new(); + /// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]); + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens.into_iter().collect::>(), vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] + pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F> + where + F: FnMut(&mut T) -> bool, + { + // avoid borrow issues. + let it = self.head; + let old_len = self.len; + + DrainFilter { list: self, it, pred: filter, idx: 0, old_len } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T> Drop for LinkedList { + fn drop(&mut self) { + struct DropGuard<'a, T>(&'a mut LinkedList); + + impl<'a, T> Drop for DropGuard<'a, T> { + fn drop(&mut self) { + // Continue the same loop we do below. This only runs when a destructor has + // panicked. If another one panics this will abort. + while self.0.pop_front_node().is_some() {} + } + } + + while let Some(node) = self.pop_front_node() { + let guard = DropGuard(self); + drop(node); + mem::forget(guard); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.len == 0 { + None + } else { + self.head.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &*node.as_ptr(); + self.len -= 1; + self.head = node.next; + &node.element + }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + if self.len == 0 { + None + } else { + self.tail.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &*node.as_ptr(); + self.len -= 1; + self.tail = node.prev; + &node.element + }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + if self.len == 0 { + None + } else { + self.head.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &mut *node.as_ptr(); + self.len -= 1; + self.head = node.next; + &mut node.element + }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + if self.len == 0 { + None + } else { + self.tail.map(|node| unsafe { + // Need an unbound lifetime to get 'a + let node = &mut *node.as_ptr(); + self.len -= 1; + self.tail = node.prev; + &mut node.element + }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, T> {} + +/// A cursor over a `LinkedList`. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. +/// +/// Cursors always rest between two elements in the list, and index in a logically circular way. +/// To accommodate this, there is a "ghost" non-element that yields `None` between the head and +/// tail of the list. +/// +/// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty. +#[unstable(feature = "linked_list_cursors", issue = "58533")] +pub struct Cursor<'a, T: 'a> { + index: usize, + current: Option>>, + list: &'a LinkedList, +} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +impl Clone for Cursor<'_, T> { + fn clone(&self) -> Self { + let Cursor { index, current, list } = *self; + Cursor { index, current, list } + } +} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +impl fmt::Debug for Cursor<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Cursor").field(&self.list).field(&self.index()).finish() + } +} + +/// A cursor over a `LinkedList` with editing operations. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the list during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying list. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always rest between two elements in the list, and index in a logically circular way. +/// To accommodate this, there is a "ghost" non-element that yields `None` between the head and +/// tail of the list. +#[unstable(feature = "linked_list_cursors", issue = "58533")] +pub struct CursorMut<'a, T: 'a> { + index: usize, + current: Option>>, + list: &'a mut LinkedList, +} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +impl fmt::Debug for CursorMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("CursorMut").field(&self.list).field(&self.index()).finish() + } +} + +impl<'a, T> Cursor<'a, T> { + /// Returns the cursor position index within the `LinkedList`. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn index(&self) -> Option { + let _ = self.current?; + Some(self.index) + } + + /// Moves the cursor to the next element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_next(&mut self) { + match self.current.take() { + // We had no current element; the cursor was sitting at the start position + // Next element should be the head of the list + None => { + self.current = self.list.head; + self.index = 0; + } + // We had a previous element, so let's go to its next + Some(current) => unsafe { + self.current = current.as_ref().next; + self.index += 1; + }, + } + } + + /// Moves the cursor to the previous element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_prev(&mut self) { + match self.current.take() { + // No current. We're at the start of the list. Yield None and jump to the end. + None => { + self.current = self.list.tail; + self.index = self.list.len().checked_sub(1).unwrap_or(0); + } + // Have a prev. Yield it and go to the previous element. + Some(current) => unsafe { + self.current = current.as_ref().prev; + self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len()); + }, + } + } + + /// Returns a reference to the element that the cursor is currently + /// pointing to. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn current(&self) -> Option<&'a T> { + unsafe { self.current.map(|current| &(*current.as_ptr()).element) } + } + + /// Returns a reference to the next element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this returns `None`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_next(&self) -> Option<&'a T> { + unsafe { + let next = match self.current { + None => self.list.head, + Some(current) => current.as_ref().next, + }; + next.map(|next| &(*next.as_ptr()).element) + } + } + + /// Returns a reference to the previous element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this returns `None`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_prev(&self) -> Option<&'a T> { + unsafe { + let prev = match self.current { + None => self.list.tail, + Some(current) => current.as_ref().prev, + }; + prev.map(|prev| &(*prev.as_ptr()).element) + } + } +} + +impl<'a, T> CursorMut<'a, T> { + /// Returns the cursor position index within the `LinkedList`. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn index(&self) -> Option { + let _ = self.current?; + Some(self.index) + } + + /// Moves the cursor to the next element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_next(&mut self) { + match self.current.take() { + // We had no current element; the cursor was sitting at the start position + // Next element should be the head of the list + None => { + self.current = self.list.head; + self.index = 0; + } + // We had a previous element, so let's go to its next + Some(current) => unsafe { + self.current = current.as_ref().next; + self.index += 1; + }, + } + } + + /// Moves the cursor to the previous element of the `LinkedList`. + /// + /// If the cursor is pointing to the "ghost" non-element then this will move it to + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this will move it to the "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn move_prev(&mut self) { + match self.current.take() { + // No current. We're at the start of the list. Yield None and jump to the end. + None => { + self.current = self.list.tail; + self.index = self.list.len().checked_sub(1).unwrap_or(0); + } + // Have a prev. Yield it and go to the previous element. + Some(current) => unsafe { + self.current = current.as_ref().prev; + self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len()); + }, + } + } + + /// Returns a reference to the element that the cursor is currently + /// pointing to. + /// + /// This returns `None` if the cursor is currently pointing to the + /// "ghost" non-element. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn current(&mut self) -> Option<&mut T> { + unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) } + } + + /// Returns a reference to the next element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the first element of the `LinkedList`. If it is pointing to the last + /// element of the `LinkedList` then this returns `None`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_next(&mut self) -> Option<&mut T> { + unsafe { + let next = match self.current { + None => self.list.head, + Some(current) => current.as_ref().next, + }; + next.map(|next| &mut (*next.as_ptr()).element) + } + } + + /// Returns a reference to the previous element. + /// + /// If the cursor is pointing to the "ghost" non-element then this returns + /// the last element of the `LinkedList`. If it is pointing to the first + /// element of the `LinkedList` then this returns `None`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn peek_prev(&mut self) -> Option<&mut T> { + unsafe { + let prev = match self.current { + None => self.list.tail, + Some(current) => current.as_ref().prev, + }; + prev.map(|prev| &mut (*prev.as_ptr()).element) + } + } + + /// Returns a read-only cursor pointing to the current element. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the + /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn as_cursor(&self) -> Cursor<'_, T> { + Cursor { list: self.list, current: self.current, index: self.index } + } +} + +// Now the list editing operations + +impl<'a, T> CursorMut<'a, T> { + /// Inserts a new element into the `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new element is + /// inserted at the front of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn insert_after(&mut self, item: T) { + unsafe { + let spliced_node = Box::leak(Box::new(Node::new(item))).into(); + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, spliced_node, spliced_node, 1); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts a new element into the `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new element is + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn insert_before(&mut self, item: T) { + unsafe { + let spliced_node = Box::leak(Box::new(Node::new(item))).into(); + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, spliced_node, spliced_node, 1); + self.index += 1; + } + } + + /// Removes the current element from the `LinkedList`. + /// + /// The element that was removed is returned, and the cursor is + /// moved to point to the next element in the `LinkedList`. + /// + /// If the cursor is currently pointing to the "ghost" non-element then no element + /// is removed and `None` is returned. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn remove_current(&mut self) -> Option { + let unlinked_node = self.current?; + unsafe { + self.current = unlinked_node.as_ref().next; + self.list.unlink_node(unlinked_node); + let unlinked_node = Box::from_raw(unlinked_node.as_ptr()); + Some(unlinked_node.element) + } + } + + /// Removes the current element from the `LinkedList` without deallocating the list node. + /// + /// The node that was removed is returned as a new `LinkedList` containing only this node. + /// The cursor is moved to point to the next element in the current `LinkedList`. + /// + /// If the cursor is currently pointing to the "ghost" non-element then no element + /// is removed and `None` is returned. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn remove_current_as_list(&mut self) -> Option> { + let mut unlinked_node = self.current?; + unsafe { + self.current = unlinked_node.as_ref().next; + self.list.unlink_node(unlinked_node); + + unlinked_node.as_mut().prev = None; + unlinked_node.as_mut().next = None; + Some(LinkedList { + head: Some(unlinked_node), + tail: Some(unlinked_node), + len: 1, + marker: PhantomData, + }) + } + } + + /// Inserts the elements from the given `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the start of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_after(&mut self, list: LinkedList) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts the elements from the given `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_before(&mut self, list: LinkedList) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len); + self.index += splice_len; + } + } + + /// Splits the list into two after the current element. This will return a + /// new list consisting of everything after the cursor, with the original + /// list retaining everything before. + /// + /// If the cursor is pointing at the "ghost" non-element then the entire contents + /// of the `LinkedList` are moved. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn split_after(&mut self) -> LinkedList { + let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 }; + if self.index == self.list.len { + // The "ghost" non-element's index has changed to 0. + self.index = 0; + } + unsafe { self.list.split_off_after_node(self.current, split_off_idx) } + } + + /// Splits the list into two before the current element. This will return a + /// new list consisting of everything before the cursor, with the original + /// list retaining everything after. + /// + /// If the cursor is pointing at the "ghost" non-element then the entire contents + /// of the `LinkedList` are moved. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn split_before(&mut self) -> LinkedList { + let split_off_idx = self.index; + self.index = 0; + unsafe { self.list.split_off_before_node(self.current, split_off_idx) } + } +} + +/// An iterator produced by calling `drain_filter` on LinkedList. +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +pub struct DrainFilter<'a, T: 'a, F: 'a> +where + F: FnMut(&mut T) -> bool, +{ + list: &'a mut LinkedList, + it: Option>>, + pred: F, + idx: usize, + old_len: usize, +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Iterator for DrainFilter<'_, T, F> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + while let Some(mut node) = self.it { + unsafe { + self.it = node.as_ref().next; + self.idx += 1; + + if (self.pred)(&mut node.as_mut().element) { + // `unlink_node` is okay with aliasing `element` references. + self.list.unlink_node(node); + return Some(Box::from_raw(node.as_ptr()).element); + } + } + } + + None + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Drop for DrainFilter<'_, T, F> +where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>) + where + F: FnMut(&mut T) -> bool; + + impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F> + where + F: FnMut(&mut T) -> bool, + { + fn drop(&mut self) { + self.0.for_each(drop); + } + } + + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl fmt::Debug for DrainFilter<'_, T, F> +where + F: FnMut(&mut T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("DrainFilter").field(&self.list).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.list.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.list.len, Some(self.list.len)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.list.pop_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for LinkedList { + fn from_iter>(iter: I) -> Self { + let mut list = Self::new(); + list.extend(iter); + list + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for LinkedList { + type Item = T; + type IntoIter = IntoIter; + + /// Consumes the list into an iterator yielding elements by value. + #[inline] + fn into_iter(self) -> IntoIter { + IntoIter { list: self } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a LinkedList { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a mut LinkedList { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for LinkedList { + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter); + } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.push_back(elem); + } +} + +impl SpecExtend for LinkedList { + default fn spec_extend(&mut self, iter: I) { + iter.into_iter().for_each(move |elt| self.push_back(elt)); + } +} + +impl SpecExtend> for LinkedList { + fn spec_extend(&mut self, ref mut other: LinkedList) { + self.append(other); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.push_back(elem); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for LinkedList { + fn eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().eq(other) + } + + fn ne(&self, other: &Self) -> bool { + self.len() != other.len() || self.iter().ne(other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for LinkedList { + fn partial_cmp(&self, other: &Self) -> Option { + self.iter().partial_cmp(other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for LinkedList { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.iter().cmp(other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for LinkedList { + fn clone(&self) -> Self { + self.iter().cloned().collect() + } + + fn clone_from(&mut self, other: &Self) { + let mut iter_other = other.iter(); + if self.len() > other.len() { + self.split_off(other.len()); + } + for (elem, elem_other) in self.iter_mut().zip(&mut iter_other) { + elem.clone_from(elem_other); + } + if !iter_other.is_empty() { + self.extend(iter_other.cloned()); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for LinkedList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for LinkedList { + fn hash(&self, state: &mut H) { + self.len().hash(state); + for elt in self { + elt.hash(state); + } + } +} + +// Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters. +#[allow(dead_code)] +fn assert_covariance() { + fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { + x + } + fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { + x + } + fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { + x + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IterMut<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IterMut<'_, T> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Send for Cursor<'_, T> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Sync for Cursor<'_, T> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Send for CursorMut<'_, T> {} + +#[unstable(feature = "linked_list_cursors", issue = "58533")] +unsafe impl Sync for CursorMut<'_, T> {} +use super::*; + +use std::thread; +use std::vec::Vec; + +use rand::{thread_rng, RngCore}; + +fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() +} + +pub fn check_links(list: &LinkedList) { + unsafe { + let mut len = 0; + let mut last_ptr: Option<&Node> = None; + let mut node_ptr: &Node; + match list.head { + None => { + // tail node should also be None. + assert!(list.tail.is_none()); + assert_eq!(0, list.len); + return; + } + Some(node) => node_ptr = &*node.as_ptr(), + } + loop { + match (last_ptr, node_ptr.prev) { + (None, None) => {} + (None, _) => panic!("prev link for head"), + (Some(p), Some(pptr)) => { + assert_eq!(p as *const Node, pptr.as_ptr() as *const Node); + } + _ => panic!("prev link is none, not good"), + } + match node_ptr.next { + Some(next) => { + last_ptr = Some(node_ptr); + node_ptr = &*next.as_ptr(); + len += 1; + } + None => { + len += 1; + break; + } + } + } + + // verify that the tail node points to the last node. + let tail = list.tail.as_ref().expect("some tail node").as_ref(); + assert_eq!(tail as *const Node, node_ptr as *const Node); + // check that len matches interior links. + assert_eq!(len, list.len); + } +} + +#[test] +fn test_append() { + // Empty to empty + { + let mut m = LinkedList::::new(); + let mut n = LinkedList::new(); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 0); + assert_eq!(n.len(), 0); + } + // Non-empty to empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + n.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + assert_eq!(n.len(), 0); + check_links(&m); + } + // Empty to non-empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + m.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + // Non-empty to non-empty + let v = vec![1, 2, 3, 4, 5]; + let u = vec![9, 8, 1, 2, 3, 4, 5]; + let mut m = list_from(&v); + let mut n = list_from(&u); + m.append(&mut n); + check_links(&m); + let mut sum = v; + sum.extend_from_slice(&u); + assert_eq!(sum.len(), m.len()); + for elt in sum { + assert_eq!(m.pop_front(), Some(elt)) + } + assert_eq!(n.len(), 0); + // Let's make sure it's working properly, since we + // did some direct changes to private members. + n.push_back(3); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(3)); + check_links(&n); +} + +#[test] +fn test_clone_from() { + // Short cloned from long + { + let v = vec![1, 2, 3, 4, 5]; + let u = vec![8, 7, 6, 2, 3, 4, 5]; + let mut m = list_from(&v); + let n = list_from(&u); + m.clone_from(&n); + check_links(&m); + assert_eq!(m, n); + for elt in u { + assert_eq!(m.pop_front(), Some(elt)) + } + } + // Long cloned from short + { + let v = vec![1, 2, 3, 4, 5]; + let u = vec![6, 7, 8]; + let mut m = list_from(&v); + let n = list_from(&u); + m.clone_from(&n); + check_links(&m); + assert_eq!(m, n); + for elt in u { + assert_eq!(m.pop_front(), Some(elt)) + } + } + // Two equal length lists + { + let v = vec![1, 2, 3, 4, 5]; + let u = vec![9, 8, 1, 2, 3]; + let mut m = list_from(&v); + let n = list_from(&u); + m.clone_from(&n); + check_links(&m); + assert_eq!(m, n); + for elt in u { + assert_eq!(m.pop_front(), Some(elt)) + } + } +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_send() { + let n = list_from(&[1, 2, 3]); + thread::spawn(move || { + check_links(&n); + let a: &[_] = &[&1, &2, &3]; + assert_eq!(a, &*n.iter().collect::>()); + }) + .join() + .ok() + .unwrap(); +} + +#[test] +fn test_fuzz() { + for _ in 0..25 { + fuzz_test(3); + fuzz_test(16); + #[cfg(not(miri))] // Miri is too slow + fuzz_test(189); + } +} + +#[test] +fn test_26021() { + // There was a bug in split_off that failed to null out the RHS's head's prev ptr. + // This caused the RHS's dtor to walk up into the LHS at drop and delete all of + // its nodes. + // + // https://github.com/rust-lang/rust/issues/26021 + let mut v1 = LinkedList::new(); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + let _ = v1.split_off(3); // Dropping this now should not cause laundry consumption + assert_eq!(v1.len(), 3); + + assert_eq!(v1.iter().len(), 3); + assert_eq!(v1.iter().collect::>().len(), 3); +} + +#[test] +fn test_split_off() { + let mut v1 = LinkedList::new(); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + + // test all splits + for ix in 0..1 + v1.len() { + let mut a = v1.clone(); + let b = a.split_off(ix); + check_links(&a); + check_links(&b); + a.extend(b); + assert_eq!(v1, a); + } +} + +fn fuzz_test(sz: i32) { + let mut m: LinkedList<_> = LinkedList::new(); + let mut v = vec![]; + for i in 0..sz { + check_links(&m); + let r: u8 = thread_rng().next_u32() as u8; + match r % 6 { + 0 => { + m.pop_back(); + v.pop(); + } + 1 => { + if !v.is_empty() { + m.pop_front(); + v.remove(0); + } + } + 2 | 4 => { + m.push_front(-i); + v.insert(0, -i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0; + for (a, &b) in m.into_iter().zip(&v) { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); +} + +#[test] +fn drain_filter_test() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.drain_filter(|v| *v < 4).collect::>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3]); + assert_eq!(m.into_iter().collect::>(), &[4, 5, 6]); +} + +#[test] +fn drain_to_empty_test() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.drain_filter(|_| true).collect::>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]); + assert_eq!(m.into_iter().collect::>(), &[]); +} + +#[test] +fn test_cursor_move_peek() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front(); + assert_eq!(cursor.current(), Some(&1)); + assert_eq!(cursor.peek_next(), Some(&2)); + assert_eq!(cursor.peek_prev(), None); + assert_eq!(cursor.index(), Some(0)); + cursor.move_prev(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&1)); + assert_eq!(cursor.peek_prev(), Some(&6)); + assert_eq!(cursor.index(), None); + cursor.move_next(); + cursor.move_next(); + assert_eq!(cursor.current(), Some(&2)); + assert_eq!(cursor.peek_next(), Some(&3)); + assert_eq!(cursor.peek_prev(), Some(&1)); + assert_eq!(cursor.index(), Some(1)); + + let mut cursor = m.cursor_back(); + assert_eq!(cursor.current(), Some(&6)); + assert_eq!(cursor.peek_next(), None); + assert_eq!(cursor.peek_prev(), Some(&5)); + assert_eq!(cursor.index(), Some(5)); + cursor.move_next(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&1)); + assert_eq!(cursor.peek_prev(), Some(&6)); + assert_eq!(cursor.index(), None); + cursor.move_prev(); + cursor.move_prev(); + assert_eq!(cursor.current(), Some(&5)); + assert_eq!(cursor.peek_next(), Some(&6)); + assert_eq!(cursor.peek_prev(), Some(&4)); + assert_eq!(cursor.index(), Some(4)); + + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + assert_eq!(cursor.current(), Some(&mut 1)); + assert_eq!(cursor.peek_next(), Some(&mut 2)); + assert_eq!(cursor.peek_prev(), None); + assert_eq!(cursor.index(), Some(0)); + cursor.move_prev(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&mut 1)); + assert_eq!(cursor.peek_prev(), Some(&mut 6)); + assert_eq!(cursor.index(), None); + cursor.move_next(); + cursor.move_next(); + assert_eq!(cursor.current(), Some(&mut 2)); + assert_eq!(cursor.peek_next(), Some(&mut 3)); + assert_eq!(cursor.peek_prev(), Some(&mut 1)); + assert_eq!(cursor.index(), Some(1)); + let mut cursor2 = cursor.as_cursor(); + assert_eq!(cursor2.current(), Some(&2)); + assert_eq!(cursor2.index(), Some(1)); + cursor2.move_next(); + assert_eq!(cursor2.current(), Some(&3)); + assert_eq!(cursor2.index(), Some(2)); + assert_eq!(cursor.current(), Some(&mut 2)); + assert_eq!(cursor.index(), Some(1)); + + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_back_mut(); + assert_eq!(cursor.current(), Some(&mut 6)); + assert_eq!(cursor.peek_next(), None); + assert_eq!(cursor.peek_prev(), Some(&mut 5)); + assert_eq!(cursor.index(), Some(5)); + cursor.move_next(); + assert_eq!(cursor.current(), None); + assert_eq!(cursor.peek_next(), Some(&mut 1)); + assert_eq!(cursor.peek_prev(), Some(&mut 6)); + assert_eq!(cursor.index(), None); + cursor.move_prev(); + cursor.move_prev(); + assert_eq!(cursor.current(), Some(&mut 5)); + assert_eq!(cursor.peek_next(), Some(&mut 6)); + assert_eq!(cursor.peek_prev(), Some(&mut 4)); + assert_eq!(cursor.index(), Some(4)); + let mut cursor2 = cursor.as_cursor(); + assert_eq!(cursor2.current(), Some(&5)); + assert_eq!(cursor2.index(), Some(4)); + cursor2.move_prev(); + assert_eq!(cursor2.current(), Some(&4)); + assert_eq!(cursor2.index(), Some(3)); + assert_eq!(cursor.current(), Some(&mut 5)); + assert_eq!(cursor.index(), Some(4)); +} + +#[test] +fn test_cursor_mut_insert() { + let mut m: LinkedList = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + cursor.insert_before(7); + cursor.insert_after(8); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[7, 1, 8, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + cursor.move_prev(); + cursor.insert_before(9); + cursor.insert_after(10); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[10, 7, 1, 8, 2, 3, 4, 5, 6, 9]); + let mut cursor = m.cursor_front_mut(); + cursor.move_prev(); + assert_eq!(cursor.remove_current(), None); + cursor.move_next(); + cursor.move_next(); + assert_eq!(cursor.remove_current(), Some(7)); + cursor.move_prev(); + cursor.move_prev(); + cursor.move_prev(); + assert_eq!(cursor.remove_current(), Some(9)); + cursor.move_next(); + assert_eq!(cursor.remove_current(), Some(10)); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[1, 8, 2, 3, 4, 5, 6]); + let mut cursor = m.cursor_front_mut(); + let mut p: LinkedList = LinkedList::new(); + p.extend(&[100, 101, 102, 103]); + let mut q: LinkedList = LinkedList::new(); + q.extend(&[200, 201, 202, 203]); + cursor.splice_after(p); + cursor.splice_before(q); + check_links(&m); + assert_eq!( + m.iter().cloned().collect::>(), + &[200, 201, 202, 203, 1, 100, 101, 102, 103, 8, 2, 3, 4, 5, 6] + ); + let mut cursor = m.cursor_front_mut(); + cursor.move_prev(); + let tmp = cursor.split_before(); + assert_eq!(m.into_iter().collect::>(), &[]); + m = tmp; + let mut cursor = m.cursor_front_mut(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + cursor.move_next(); + let tmp = cursor.split_after(); + assert_eq!(tmp.into_iter().collect::>(), &[102, 103, 8, 2, 3, 4, 5, 6]); + check_links(&m); + assert_eq!(m.iter().cloned().collect::>(), &[200, 201, 202, 203, 1, 100, 101]); +} +use super::merge_iter::MergeIterInner; +use super::node::{self, Root}; +use core::iter::FusedIterator; + +impl Root { + /// Appends all key-value pairs from the union of two ascending iterators, + /// incrementing a `length` variable along the way. The latter makes it + /// easier for the caller to avoid a leak when a drop handler panicks. + /// + /// If both iterators produce the same key, this method drops the pair from + /// the left iterator and appends the pair from the right iterator. + /// + /// If you want the tree to end up in a strictly ascending order, like for + /// a `BTreeMap`, both iterators should produce keys in strictly ascending + /// order, each greater than all keys in the tree, including any keys + /// already in the tree upon entry. + pub fn append_from_sorted_iters(&mut self, left: I, right: I, length: &mut usize) + where + K: Ord, + I: Iterator + FusedIterator, + { + // We prepare to merge `left` and `right` into a sorted sequence in linear time. + let iter = MergeIter(MergeIterInner::new(left, right)); + + // Meanwhile, we build a tree from the sorted sequence in linear time. + self.bulk_push(iter, length) + } + + /// Pushes all key-value pairs to the end of the tree, incrementing a + /// `length` variable along the way. The latter makes it easier for the + /// caller to avoid a leak when the iterator panicks. + pub fn bulk_push(&mut self, iter: I, length: &mut usize) + where + I: Iterator, + { + let mut cur_node = self.borrow_mut().last_leaf_edge().into_node(); + // Iterate through all key-value pairs, pushing them into nodes at the right level. + for (key, value) in iter { + // Try to push key-value pair into the current leaf node. + if cur_node.len() < node::CAPACITY { + cur_node.push(key, value); + } else { + // No space left, go up and push there. + let mut open_node; + let mut test_node = cur_node.forget_type(); + loop { + match test_node.ascend() { + Ok(parent) => { + let parent = parent.into_node(); + if parent.len() < node::CAPACITY { + // Found a node with space left, push here. + open_node = parent; + break; + } else { + // Go up again. + test_node = parent.forget_type(); + } + } + Err(_) => { + // We are at the top, create a new root node and push there. + open_node = self.push_internal_level(); + break; + } + } + } + + // Push key-value pair and new right subtree. + let tree_height = open_node.height() - 1; + let mut right_tree = Root::new(); + for _ in 0..tree_height { + right_tree.push_internal_level(); + } + open_node.push(key, value, right_tree); + + // Go down to the right-most leaf again. + cur_node = open_node.forget_type().last_leaf_edge().into_node(); + } + + // Increment length every iteration, to make sure the map drops + // the appended elements even if advancing the iterator panicks. + *length += 1; + } + self.fix_right_border_of_plentiful(); + } +} + +// An iterator for merging two sorted sequences into one +struct MergeIter>(MergeIterInner); + +impl Iterator for MergeIter +where + I: Iterator + FusedIterator, +{ + type Item = (K, V); + + /// If two keys are equal, returns the key-value pair from the right source. + fn next(&mut self) -> Option<(K, V)> { + let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0)); + b_next.or(a_next) + } +} +use crate::fmt::Debug; +use std::cmp::Ordering; +use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + +/// A blueprint for crash test dummy instances that monitor particular events. +/// Some instances may be configured to panic at some point. +/// Events are `clone`, `drop` or some anonymous `query`. +/// +/// Crash test dummies are identified and ordered by an id, so they can be used +/// as keys in a BTreeMap. The implementation intentionally uses does not rely +/// on anything defined in the crate, apart from the `Debug` trait. +#[derive(Debug)] +pub struct CrashTestDummy { + id: usize, + cloned: AtomicUsize, + dropped: AtomicUsize, + queried: AtomicUsize, +} + +impl CrashTestDummy { + /// Creates a crash test dummy design. The `id` determines order and equality of instances. + pub fn new(id: usize) -> CrashTestDummy { + CrashTestDummy { + id, + cloned: AtomicUsize::new(0), + dropped: AtomicUsize::new(0), + queried: AtomicUsize::new(0), + } + } + + /// Creates an instance of a crash test dummy that records what events it experiences + /// and optionally panics. + pub fn spawn(&self, panic: Panic) -> Instance<'_> { + Instance { origin: self, panic } + } + + /// Returns how many times instances of the dummy have been cloned. + pub fn cloned(&self) -> usize { + self.cloned.load(SeqCst) + } + + /// Returns how many times instances of the dummy have been dropped. + pub fn dropped(&self) -> usize { + self.dropped.load(SeqCst) + } + + /// Returns how many times instances of the dummy have had their `query` member invoked. + pub fn queried(&self) -> usize { + self.queried.load(SeqCst) + } +} + +#[derive(Debug)] +pub struct Instance<'a> { + origin: &'a CrashTestDummy, + panic: Panic, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Panic { + Never, + InClone, + InDrop, + InQuery, +} + +impl Instance<'_> { + pub fn id(&self) -> usize { + self.origin.id + } + + /// Some anonymous query, the result of which is already given. + pub fn query(&self, result: R) -> R { + self.origin.queried.fetch_add(1, SeqCst); + if self.panic == Panic::InQuery { + panic!("panic in `query`"); + } + result + } +} + +impl Clone for Instance<'_> { + fn clone(&self) -> Self { + self.origin.cloned.fetch_add(1, SeqCst); + if self.panic == Panic::InClone { + panic!("panic in `clone`"); + } + Self { origin: self.origin, panic: Panic::Never } + } +} + +impl Drop for Instance<'_> { + fn drop(&mut self) { + self.origin.dropped.fetch_add(1, SeqCst); + if self.panic == Panic::InDrop { + panic!("panic in `drop`"); + } + } +} + +impl PartialOrd for Instance<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.id().partial_cmp(&other.id()) + } +} + +impl Ord for Instance<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.id().cmp(&other.id()) + } +} + +impl PartialEq for Instance<'_> { + fn eq(&self, other: &Self) -> bool { + self.id().eq(&other.id()) + } +} + +impl Eq for Instance<'_> {} +/// XorShiftRng +pub struct DeterministicRng { + count: usize, + x: u32, + y: u32, + z: u32, + w: u32, +} + +impl DeterministicRng { + pub fn new() -> Self { + DeterministicRng { count: 0, x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } + } + + /// Guarantees that each returned number is unique. + pub fn next(&mut self) -> u32 { + self.count += 1; + assert!(self.count <= 70029); + let x = self.x; + let t = x ^ (x << 11); + self.x = self.y; + self.y = self.z; + self.z = self.w; + let w_ = self.w; + self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); + self.w + } +} +use std::cell::Cell; +use std::cmp::Ordering::{self, *}; +use std::ptr; + +// Minimal type with an `Ord` implementation violating transitivity. +#[derive(Debug)] +pub enum Cyclic3 { + A, + B, + C, +} +use Cyclic3::*; + +impl PartialOrd for Cyclic3 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Cyclic3 { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (A, A) | (B, B) | (C, C) => Equal, + (A, B) | (B, C) | (C, A) => Less, + (A, C) | (B, A) | (C, B) => Greater, + } + } +} + +impl PartialEq for Cyclic3 { + fn eq(&self, other: &Self) -> bool { + self.cmp(&other) == Equal + } +} + +impl Eq for Cyclic3 {} + +// Controls the ordering of values wrapped by `Governed`. +#[derive(Debug)] +pub struct Governor { + flipped: Cell, +} + +impl Governor { + pub fn new() -> Self { + Governor { flipped: Cell::new(false) } + } + + pub fn flip(&self) { + self.flipped.set(!self.flipped.get()); + } +} + +// Type with an `Ord` implementation that forms a total order at any moment +// (assuming that `T` respects total order), but can suddenly be made to invert +// that total order. +#[derive(Debug)] +pub struct Governed<'a, T>(pub T, pub &'a Governor); + +impl PartialOrd for Governed<'_, T> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Governed<'_, T> { + fn cmp(&self, other: &Self) -> Ordering { + assert!(ptr::eq(self.1, other.1)); + let ord = self.0.cmp(&other.0); + if self.1.flipped.get() { ord.reverse() } else { ord } + } +} + +impl PartialEq for Governed<'_, T> { + fn eq(&self, other: &Self) -> bool { + assert!(ptr::eq(self.1, other.1)); + self.0.eq(&other.0) + } +} + +impl Eq for Governed<'_, T> {} +pub mod crash_test; +pub mod ord_chaos; +pub mod rng; +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::ops::{Bound, RangeBounds}; + +use super::node::{marker, ForceResult::*, Handle, NodeRef}; + +use SearchBound::*; +use SearchResult::*; + +pub enum SearchBound { + /// An inclusive bound to look for, just like `Bound::Included(T)`. + Included(T), + /// An exclusive bound to look for, just like `Bound::Excluded(T)`. + Excluded(T), + /// An unconditional inclusive bound, just like `Bound::Unbounded`. + AllIncluded, + /// An unconditional exclusive bound. + AllExcluded, +} + +impl SearchBound { + pub fn from_range(range_bound: Bound) -> Self { + match range_bound { + Bound::Included(t) => Included(t), + Bound::Excluded(t) => Excluded(t), + Bound::Unbounded => AllIncluded, + } + } +} + +pub enum SearchResult { + Found(Handle, marker::KV>), + GoDown(Handle, marker::Edge>), +} + +pub enum IndexResult { + KV(usize), + Edge(usize), +} + +impl NodeRef { + /// Looks up a given key in a (sub)tree headed by the node, recursively. + /// Returns a `Found` with the handle of the matching KV, if any. Otherwise, + /// returns a `GoDown` with the handle of the leaf edge where the key belongs. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + pub fn search_tree( + mut self, + key: &Q, + ) -> SearchResult + where + Q: Ord, + K: Borrow, + { + loop { + self = match self.search_node(key) { + Found(handle) => return Found(handle), + GoDown(handle) => match handle.force() { + Leaf(leaf) => return GoDown(leaf), + Internal(internal) => internal.descend(), + }, + } + } + } + + /// Descends to the nearest node where the edge matching the lower bound + /// of the range is different from the edge matching the upper bound, i.e., + /// the nearest node that has at least one key contained in the range. + /// + /// If found, returns an `Ok` with that node, the strictly ascending pair of + /// edge indices in the node delimiting the range, and the corresponding + /// pair of bounds for continuing the search in the child nodes, in case + /// the node is internal. + /// + /// If not found, returns an `Err` with the leaf edge matching the entire + /// range. + /// + /// As a diagnostic service, panics if the range specifies impossible bounds. + /// + /// The result is meaningful only if the tree is ordered by key. + pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>( + mut self, + range: &'r R, + ) -> Result< + ( + NodeRef, + usize, + usize, + SearchBound<&'r Q>, + SearchBound<&'r Q>, + ), + Handle, marker::Edge>, + > + where + Q: Ord, + K: Borrow, + R: RangeBounds, + { + // Inlining these variables should be avoided. We assume the bounds reported by `range` + // remain the same, but an adversarial implementation could change between calls (#81138). + let (start, end) = (range.start_bound(), range.end_bound()); + match (start, end) { + (Bound::Excluded(s), Bound::Excluded(e)) if s == e => { + panic!("range start and end are equal and excluded in BTreeMap") + } + (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e)) + if s > e => + { + panic!("range start is greater than range end in BTreeMap") + } + _ => {} + } + let mut lower_bound = SearchBound::from_range(start); + let mut upper_bound = SearchBound::from_range(end); + loop { + let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound); + let (upper_edge_idx, upper_child_bound) = + unsafe { self.find_upper_bound_index(upper_bound, lower_edge_idx) }; + if lower_edge_idx < upper_edge_idx { + return Ok(( + self, + lower_edge_idx, + upper_edge_idx, + lower_child_bound, + upper_child_bound, + )); + } + debug_assert_eq!(lower_edge_idx, upper_edge_idx); + let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) }; + match common_edge.force() { + Leaf(common_edge) => return Err(common_edge), + Internal(common_edge) => { + self = common_edge.descend(); + lower_bound = lower_child_bound; + upper_bound = upper_child_bound; + } + } + } + } + + /// Finds an edge in the node delimiting the lower bound of a range. + /// Also returns the lower bound to be used for continuing the search in + /// the matching child node, if `self` is an internal node. + /// + /// The result is meaningful only if the tree is ordered by key. + pub fn find_lower_bound_edge<'r, Q>( + self, + bound: SearchBound<&'r Q>, + ) -> (Handle, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + let (edge_idx, bound) = self.find_lower_bound_index(bound); + let edge = unsafe { Handle::new_edge(self, edge_idx) }; + (edge, bound) + } + + /// Clone of `find_lower_bound_edge` for the upper bound. + pub fn find_upper_bound_edge<'r, Q>( + self, + bound: SearchBound<&'r Q>, + ) -> (Handle, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) }; + let edge = unsafe { Handle::new_edge(self, edge_idx) }; + (edge, bound) + } +} + +impl NodeRef { + /// Looks up a given key in the node, without recursion. + /// Returns a `Found` with the handle of the matching KV, if any. Otherwise, + /// returns a `GoDown` with the handle of the edge where the key might be found + /// (if the node is internal) or where the key can be inserted. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + pub fn search_node(self, key: &Q) -> SearchResult + where + Q: Ord, + K: Borrow, + { + match unsafe { self.find_key_index(key, 0) } { + IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }), + IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }), + } + } + + /// Returns either the KV index in the node at which the key (or an equivalent) + /// exists, or the edge index where the key belongs, starting from a particular index. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_key_index(&self, key: &Q, start_index: usize) -> IndexResult + where + Q: Ord, + K: Borrow, + { + let node = self.reborrow(); + let keys = node.keys(); + debug_assert!(start_index <= keys.len()); + for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() { + match key.cmp(k.borrow()) { + Ordering::Greater => {} + Ordering::Equal => return IndexResult::KV(start_index + offset), + Ordering::Less => return IndexResult::Edge(start_index + offset), + } + } + IndexResult::Edge(keys.len()) + } + + /// Finds an edge index in the node delimiting the lower bound of a range. + /// Also returns the lower bound to be used for continuing the search in + /// the matching child node, if `self` is an internal node. + /// + /// The result is meaningful only if the tree is ordered by key. + fn find_lower_bound_index<'r, Q>( + &self, + bound: SearchBound<&'r Q>, + ) -> (usize, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + match bound { + Included(key) => match unsafe { self.find_key_index(key, 0) } { + IndexResult::KV(idx) => (idx, AllExcluded), + IndexResult::Edge(idx) => (idx, bound), + }, + Excluded(key) => match unsafe { self.find_key_index(key, 0) } { + IndexResult::KV(idx) => (idx + 1, AllIncluded), + IndexResult::Edge(idx) => (idx, bound), + }, + AllIncluded => (0, AllIncluded), + AllExcluded => (self.len(), AllExcluded), + } + } + + /// Mirror image of `find_lower_bound_index` for the upper bound, + /// with an additional parameter to skip part of the key array. + /// + /// # Safety + /// `start_index` must be a valid edge index for the node. + unsafe fn find_upper_bound_index<'r, Q>( + &self, + bound: SearchBound<&'r Q>, + start_index: usize, + ) -> (usize, SearchBound<&'r Q>) + where + Q: ?Sized + Ord, + K: Borrow, + { + match bound { + Included(key) => match unsafe { self.find_key_index(key, start_index) } { + IndexResult::KV(idx) => (idx + 1, AllExcluded), + IndexResult::Edge(idx) => (idx, bound), + }, + Excluded(key) => match unsafe { self.find_key_index(key, start_index) } { + IndexResult::KV(idx) => (idx, AllIncluded), + IndexResult::Edge(idx) => (idx, bound), + }, + AllIncluded => (self.len(), AllIncluded), + AllExcluded => (start_index, AllExcluded), + } + } +} +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::hash::{Hash, Hasher}; +use core::iter::{FromIterator, FusedIterator}; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop}; +use core::ops::{Index, RangeBounds}; +use core::ptr; + +use super::borrow::DormantMutRef; +use super::navigate::LeafRange; +use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root}; +use super::search::SearchResult::*; + +mod entry; +pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry}; +use Entry::*; + +/// Minimum number of elements in nodes that are not a root. +/// We might temporarily have fewer elements during methods. +pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; + +// A tree in a `BTreeMap` is a tree in the `node` module with additional invariants: +// - Keys must appear in ascending order (according to the key's type). +// - If the root node is internal, it must contain at least 1 element. +// - Every non-root node contains at least MIN_LEN elements. +// +// An empty map may be represented both by the absence of a root node or by a +// root node that is an empty leaf. + +/// A map based on a [B-Tree]. +/// +/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing +/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal +/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of +/// comparisons necessary to find an element (log2n). However, in practice the way this +/// is done is *very* inefficient for modern computer architectures. In particular, every element +/// is stored in its own individually heap-allocated node. This means that every single insertion +/// triggers a heap-allocation, and every single comparison should be a cache-miss. Since these +/// are both notably expensive things to do in practice, we are forced to at very least reconsider +/// the BST strategy. +/// +/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing +/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in +/// searches. However, this does mean that searches will have to do *more* comparisons on average. +/// The precise number of comparisons depends on the node search strategy used. For optimal cache +/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search +/// the node using binary search. As a compromise, one could also perform a linear search +/// that initially only checks every ith element for some choice of i. +/// +/// Currently, our implementation simply performs naive linear search. This provides excellent +/// performance on *small* nodes of elements which are cheap to compare. However in the future we +/// would like to further explore choosing the optimal search strategy based on the choice of B, +/// and possibly other factors. Using linear search, searching for a random element is expected +/// to take O(B * log(n)) comparisons, which is generally worse than a BST. In practice, +/// however, performance is excellent. +/// +/// It is a logic error for a key to be modified in such a way that the key's ordering relative to +/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is +/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. +/// The behavior resulting from such a logic error is not specified, but will not result in +/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and +/// non-termination. +/// +/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree +/// [`Cell`]: core::cell::Cell +/// [`RefCell`]: core::cell::RefCell +/// +/// # Examples +/// +/// ``` +/// use std::collections::BTreeMap; +/// +/// // type inference lets us omit an explicit type signature (which +/// // would be `BTreeMap<&str, &str>` in this example). +/// let mut movie_reviews = BTreeMap::new(); +/// +/// // review some movies. +/// movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); +/// movie_reviews.insert("Pulp Fiction", "Masterpiece."); +/// movie_reviews.insert("The Godfather", "Very enjoyable."); +/// movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); +/// +/// // check for a specific one. +/// if !movie_reviews.contains_key("Les Misérables") { +/// println!("We've got {} reviews, but Les Misérables ain't one.", +/// movie_reviews.len()); +/// } +/// +/// // oops, this review has a lot of spelling mistakes, let's delete it. +/// movie_reviews.remove("The Blues Brothers"); +/// +/// // look up the values associated with some keys. +/// let to_find = ["Up!", "Office Space"]; +/// for movie in &to_find { +/// match movie_reviews.get(movie) { +/// Some(review) => println!("{}: {}", movie, review), +/// None => println!("{} is unreviewed.", movie) +/// } +/// } +/// +/// // Look up the value for a key (will panic if the key is not found). +/// println!("Movie review: {}", movie_reviews["Office Space"]); +/// +/// // iterate over everything. +/// for (movie, review) in &movie_reviews { +/// println!("{}: \"{}\"", movie, review); +/// } +/// ``` +/// +/// `BTreeMap` also implements an [`Entry API`], which allows for more complex +/// methods of getting, setting, updating and removing keys and their values: +/// +/// [`Entry API`]: BTreeMap::entry +/// +/// ``` +/// use std::collections::BTreeMap; +/// +/// // type inference lets us omit an explicit type signature (which +/// // would be `BTreeMap<&str, u8>` in this example). +/// let mut player_stats = BTreeMap::new(); +/// +/// fn random_stat_buff() -> u8 { +/// // could actually return some random value here - let's just return +/// // some fixed value for now +/// 42 +/// } +/// +/// // insert a key only if it doesn't already exist +/// player_stats.entry("health").or_insert(100); +/// +/// // insert a key using a function that provides a new value only if it +/// // doesn't already exist +/// player_stats.entry("defence").or_insert_with(random_stat_buff); +/// +/// // update a key, guarding against the key possibly not being set +/// let stat = player_stats.entry("attack").or_insert(100); +/// *stat += random_stat_buff(); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")] +pub struct BTreeMap { + root: Option>, + length: usize, +} + +#[stable(feature = "btree_drop", since = "1.7.0")] +unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap { + fn drop(&mut self) { + if let Some(root) = self.root.take() { + Dropper { front: root.into_dying().first_leaf_edge(), remaining_length: self.length }; + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BTreeMap { + fn clone(&self) -> BTreeMap { + fn clone_subtree<'a, K: Clone, V: Clone>( + node: NodeRef, K, V, marker::LeafOrInternal>, + ) -> BTreeMap + where + K: 'a, + V: 'a, + { + match node.force() { + Leaf(leaf) => { + let mut out_tree = BTreeMap { root: Some(Root::new()), length: 0 }; + + { + let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped + let mut out_node = match root.borrow_mut().force() { + Leaf(leaf) => leaf, + Internal(_) => unreachable!(), + }; + + let mut in_edge = leaf.first_edge(); + while let Ok(kv) = in_edge.right_kv() { + let (k, v) = kv.into_kv(); + in_edge = kv.right_edge(); + + out_node.push(k.clone(), v.clone()); + out_tree.length += 1; + } + } + + out_tree + } + Internal(internal) => { + let mut out_tree = clone_subtree(internal.first_edge().descend()); + + { + let out_root = BTreeMap::ensure_is_owned(&mut out_tree.root); + let mut out_node = out_root.push_internal_level(); + let mut in_edge = internal.first_edge(); + while let Ok(kv) = in_edge.right_kv() { + let (k, v) = kv.into_kv(); + in_edge = kv.right_edge(); + + let k = (*k).clone(); + let v = (*v).clone(); + let subtree = clone_subtree(in_edge.descend()); + + // We can't destructure subtree directly + // because BTreeMap implements Drop + let (subroot, sublength) = unsafe { + let subtree = ManuallyDrop::new(subtree); + let root = ptr::read(&subtree.root); + let length = subtree.length; + (root, length) + }; + + out_node.push(k, v, subroot.unwrap_or_else(Root::new)); + out_tree.length += 1 + sublength; + } + } + + out_tree + } + } + } + + if self.is_empty() { + // Ideally we'd call `BTreeMap::new` here, but that has the `K: + // Ord` constraint, which this method lacks. + BTreeMap { root: None, length: 0 } + } else { + clone_subtree(self.root.as_ref().unwrap().reborrow()) // unwrap succeeds because not empty + } + } +} + +impl super::Recover for BTreeMap +where + K: Borrow + Ord, + Q: Ord, +{ + type Key = K; + + fn get(&self, key: &Q) -> Option<&K> { + let root_node = self.root.as_ref()?.reborrow(); + match root_node.search_tree(key) { + Found(handle) => Some(handle.into_kv().0), + GoDown(_) => None, + } + } + + fn take(&mut self, key: &Q) -> Option { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + match root_node.search_tree(key) { + Found(handle) => { + Some(OccupiedEntry { handle, dormant_map, _marker: PhantomData }.remove_kv().0) + } + GoDown(_) => None, + } + } + + fn replace(&mut self, key: K) -> Option { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut(); + match root_node.search_tree::(&key) { + Found(mut kv) => Some(mem::replace(kv.key_mut(), key)), + GoDown(handle) => { + VacantEntry { key, handle, dormant_map, _marker: PhantomData }.insert(()); + None + } + } + } +} + +/// An iterator over the entries of a `BTreeMap`. +/// +/// This `struct` is created by the [`iter`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`iter`]: BTreeMap::iter +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, K: 'a, V: 'a> { + range: Range<'a, K, V>, + length: usize, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A mutable iterator over the entries of a `BTreeMap`. +/// +/// This `struct` is created by the [`iter_mut`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`iter_mut`]: BTreeMap::iter_mut +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct IterMut<'a, K: 'a, V: 'a> { + range: RangeMut<'a, K, V>, + length: usize, +} + +/// An owning iterator over the entries of a `BTreeMap`. +/// +/// This `struct` is created by the [`into_iter`] method on [`BTreeMap`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: IntoIterator::into_iter +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter { + range: LeafRange, + length: usize, +} + +impl IntoIter { + /// Returns an iterator of references over the remaining items. + #[inline] + pub(super) fn iter(&self) -> Iter<'_, K, V> { + let range = Range { inner: self.range.reborrow() }; + Iter { range: range, length: self.length } + } +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +/// A simplified version of `IntoIter` that is not double-ended and has only one +/// purpose: to drop the remainder of an `IntoIter`. Therefore it also serves to +/// drop an entire tree without the need to first look up a `back` leaf edge. +struct Dropper { + front: Handle, marker::Edge>, + remaining_length: usize, +} + +/// An iterator over the keys of a `BTreeMap`. +/// +/// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`keys`]: BTreeMap::keys +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Keys<'a, K: 'a, V: 'a> { + inner: Iter<'a, K, V>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Keys<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// An iterator over the values of a `BTreeMap`. +/// +/// This `struct` is created by the [`values`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`values`]: BTreeMap::values +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Values<'a, K: 'a, V: 'a> { + inner: Iter<'a, K, V>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Values<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A mutable iterator over the values of a `BTreeMap`. +/// +/// This `struct` is created by the [`values_mut`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`values_mut`]: BTreeMap::values_mut +#[stable(feature = "map_values_mut", since = "1.10.0")] +pub struct ValuesMut<'a, K: 'a, V: 'a> { + inner: IterMut<'a, K, V>, +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl fmt::Debug for ValuesMut<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.inner.iter().map(|(_, val)| val)).finish() + } +} + +/// An owning iterator over the keys of a `BTreeMap`. +/// +/// This `struct` is created by the [`into_keys`] method on [`BTreeMap`]. +/// See its documentation for more. +/// +/// [`into_keys`]: BTreeMap::into_keys +#[unstable(feature = "map_into_keys_values", issue = "75294")] +pub struct IntoKeys { + inner: IntoIter, +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl fmt::Debug for IntoKeys { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.inner.iter().map(|(key, _)| key)).finish() + } +} + +/// An owning iterator over the values of a `BTreeMap`. +/// +/// This `struct` is created by the [`into_values`] method on [`BTreeMap`]. +/// See its documentation for more. +/// +/// [`into_values`]: BTreeMap::into_values +#[unstable(feature = "map_into_keys_values", issue = "75294")] +pub struct IntoValues { + inner: IntoIter, +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl fmt::Debug for IntoValues { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.inner.iter().map(|(_, val)| val)).finish() + } +} + +/// An iterator over a sub-range of entries in a `BTreeMap`. +/// +/// This `struct` is created by the [`range`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`range`]: BTreeMap::range +#[stable(feature = "btree_range", since = "1.17.0")] +pub struct Range<'a, K: 'a, V: 'a> { + inner: LeafRange, K, V>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Range<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A mutable iterator over a sub-range of entries in a `BTreeMap`. +/// +/// This `struct` is created by the [`range_mut`] method on [`BTreeMap`]. See its +/// documentation for more. +/// +/// [`range_mut`]: BTreeMap::range_mut +#[stable(feature = "btree_range", since = "1.17.0")] +pub struct RangeMut<'a, K: 'a, V: 'a> { + inner: LeafRange, K, V>, + + // Be invariant in `K` and `V` + _marker: PhantomData<&'a mut (K, V)>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for RangeMut<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let range = Range { inner: self.inner.reborrow() }; + f.debug_list().entries(range).finish() + } +} + +impl BTreeMap { + /// Makes a new, empty `BTreeMap`. + /// + /// Does not allocate anything on its own. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// + /// // entries can now be inserted into the empty map + /// map.insert(1, "a"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn new() -> BTreeMap + where + K: Ord, + { + BTreeMap { root: None, length: 0 } + } + + /// Clears the map, removing all elements. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + *self = BTreeMap { root: None, length: 0 }; + } + + /// Returns a reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get(&1), Some(&"a")); + /// assert_eq!(map.get(&2), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self, key: &Q) -> Option<&V> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + match root_node.search_tree(key) { + Found(handle) => Some(handle.into_kv().1), + GoDown(_) => None, + } + } + + /// Returns the key-value pair corresponding to the supplied key. + /// + /// The supplied key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); + /// assert_eq!(map.get_key_value(&2), None); + /// ``` + #[stable(feature = "map_get_key_value", since = "1.40.0")] + pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + match root_node.search_tree(k) { + Found(handle) => Some(handle.into_kv()), + GoDown(_) => None, + } + } + + /// Returns the first key-value pair in the map. + /// The key in this pair is the minimum key in the map. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.first_key_value(), None); + /// map.insert(1, "b"); + /// map.insert(2, "a"); + /// assert_eq!(map.first_key_value(), Some((&1, &"b"))); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn first_key_value(&self) -> Option<(&K, &V)> + where + K: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv) + } + + /// Returns the first entry in the map for in-place manipulation. + /// The key of this entry is the minimum key in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// if let Some(mut entry) = map.first_entry() { + /// if *entry.key() > 0 { + /// entry.insert("first"); + /// } + /// } + /// assert_eq!(*map.get(&1).unwrap(), "first"); + /// assert_eq!(*map.get(&2).unwrap(), "b"); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn first_entry(&mut self) -> Option> + where + K: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + let kv = root_node.first_leaf_edge().right_kv().ok()?; + Some(OccupiedEntry { handle: kv.forget_node_type(), dormant_map, _marker: PhantomData }) + } + + /// Removes and returns the first element in the map. + /// The key of this element is the minimum key that was in the map. + /// + /// # Examples + /// + /// Draining elements in ascending order, while keeping a usable map each iteration. + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// while let Some((key, _val)) = map.pop_first() { + /// assert!(map.iter().all(|(k, _v)| *k > key)); + /// } + /// assert!(map.is_empty()); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn pop_first(&mut self) -> Option<(K, V)> + where + K: Ord, + { + self.first_entry().map(|entry| entry.remove_entry()) + } + + /// Returns the last key-value pair in the map. + /// The key in this pair is the maximum key in the map. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "b"); + /// map.insert(2, "a"); + /// assert_eq!(map.last_key_value(), Some((&2, &"a"))); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn last_key_value(&self) -> Option<(&K, &V)> + where + K: Ord, + { + let root_node = self.root.as_ref()?.reborrow(); + root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv) + } + + /// Returns the last entry in the map for in-place manipulation. + /// The key of this entry is the maximum key in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// if let Some(mut entry) = map.last_entry() { + /// if *entry.key() > 0 { + /// entry.insert("last"); + /// } + /// } + /// assert_eq!(*map.get(&1).unwrap(), "a"); + /// assert_eq!(*map.get(&2).unwrap(), "last"); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn last_entry(&mut self) -> Option> + where + K: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + let kv = root_node.last_leaf_edge().left_kv().ok()?; + Some(OccupiedEntry { handle: kv.forget_node_type(), dormant_map, _marker: PhantomData }) + } + + /// Removes and returns the last element in the map. + /// The key of this element is the maximum key that was in the map. + /// + /// # Examples + /// + /// Draining elements in descending order, while keeping a usable map each iteration. + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// while let Some((key, _val)) = map.pop_last() { + /// assert!(map.iter().all(|(k, _v)| *k < key)); + /// } + /// assert!(map.is_empty()); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn pop_last(&mut self) -> Option<(K, V)> + where + K: Ord, + { + self.last_entry().map(|entry| entry.remove_entry()) + } + + /// Returns `true` if the map contains a value for the specified key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains_key(&self, key: &Q) -> bool + where + K: Borrow + Ord, + Q: Ord, + { + self.get(key).is_some() + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// if let Some(x) = map.get_mut(&1) { + /// *x = "b"; + /// } + /// assert_eq!(map[&1], "b"); + /// ``` + // See `get` for implementation notes, this is basically a copy-paste with mut's added + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where + K: Borrow + Ord, + Q: Ord, + { + let root_node = self.root.as_mut()?.borrow_mut(); + match root_node.search_tree(key) { + Found(handle) => Some(handle.into_val_mut()), + GoDown(_) => None, + } + } + + /// Inserts a key-value pair into the map. + /// + /// If the map did not have this key present, `None` is returned. + /// + /// If the map did have this key present, the value is updated, and the old + /// value is returned. The key is not updated, though; this matters for + /// types that can be `==` without being identical. See the [module-level + /// documentation] for more. + /// + /// [module-level documentation]: index.html#insert-and-complex-keys + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.insert(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.insert(37, "c"), Some("b")); + /// assert_eq!(map[&37], "c"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, key: K, value: V) -> Option + where + K: Ord, + { + match self.entry(key) { + Occupied(mut entry) => Some(entry.insert(value)), + Vacant(entry) => { + entry.insert(value); + None + } + } + } + + /// Tries to insert a key-value pair into the map, and returns + /// a mutable reference to the value in the entry. + /// + /// If the map already had this key present, nothing is updated, and + /// an error containing the occupied entry and the value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_try_insert)] + /// + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.try_insert(37, "a").unwrap(), &"a"); + /// + /// let err = map.try_insert(37, "b").unwrap_err(); + /// assert_eq!(err.entry.key(), &37); + /// assert_eq!(err.entry.get(), &"a"); + /// assert_eq!(err.value, "b"); + /// ``` + #[unstable(feature = "map_try_insert", issue = "82766")] + pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V>> + where + K: Ord, + { + match self.entry(key) { + Occupied(entry) => Err(OccupiedError { entry, value }), + Vacant(entry) => Ok(entry.insert(value)), + } + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove(&1), Some("a")); + /// assert_eq!(map.remove(&1), None); + /// ``` + #[doc(alias = "delete")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, key: &Q) -> Option + where + K: Borrow + Ord, + Q: Ord, + { + self.remove_entry(key).map(|(_, v)| v) + } + + /// Removes a key from the map, returning the stored key and value if the key + /// was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove_entry(&1), Some((1, "a"))); + /// assert_eq!(map.remove_entry(&1), None); + /// ``` + #[stable(feature = "btreemap_remove_entry", since = "1.45.0")] + pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow + Ord, + Q: Ord, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = map.root.as_mut()?.borrow_mut(); + match root_node.search_tree(key) { + Found(handle) => { + Some(OccupiedEntry { handle, dormant_map, _marker: PhantomData }.remove_entry()) + } + GoDown(_) => None, + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap = (0..8).map(|x| (x, x*10)).collect(); + /// // Keep only the elements with even-numbered keys. + /// map.retain(|&k, _| k % 2 == 0); + /// assert!(map.into_iter().eq(vec![(0, 0), (2, 20), (4, 40), (6, 60)])); + /// ``` + #[inline] + #[stable(feature = "btree_retain", since = "1.53.0")] + pub fn retain(&mut self, mut f: F) + where + K: Ord, + F: FnMut(&K, &mut V) -> bool, + { + self.drain_filter(|k, v| !f(k, v)); + } + + /// Moves all elements from `other` into `Self`, leaving `other` empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// a.insert(3, "c"); + /// + /// let mut b = BTreeMap::new(); + /// b.insert(3, "d"); + /// b.insert(4, "e"); + /// b.insert(5, "f"); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 5); + /// assert_eq!(b.len(), 0); + /// + /// assert_eq!(a[&1], "a"); + /// assert_eq!(a[&2], "b"); + /// assert_eq!(a[&3], "d"); + /// assert_eq!(a[&4], "e"); + /// assert_eq!(a[&5], "f"); + /// ``` + #[stable(feature = "btree_append", since = "1.11.0")] + pub fn append(&mut self, other: &mut Self) + where + K: Ord, + { + // Do we have to append anything at all? + if other.is_empty() { + return; + } + + // We can just swap `self` and `other` if `self` is empty. + if self.is_empty() { + mem::swap(self, other); + return; + } + + let self_iter = mem::take(self).into_iter(); + let other_iter = mem::take(other).into_iter(); + let root = BTreeMap::ensure_is_owned(&mut self.root); + root.append_from_sorted_iters(self_iter, other_iter, &mut self.length) + } + + /// Constructs a double-ended iterator over a sub-range of elements in the map. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. + /// + /// # Panics + /// + /// Panics if range `start > end`. + /// Panics if range `start == end` and both bounds are `Excluded`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::ops::Bound::Included; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(3, "a"); + /// map.insert(5, "b"); + /// map.insert(8, "c"); + /// for (&key, &value) in map.range((Included(&4), Included(&8))) { + /// println!("{}: {}", key, value); + /// } + /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); + /// ``` + #[stable(feature = "btree_range", since = "1.17.0")] + pub fn range(&self, range: R) -> Range<'_, K, V> + where + T: Ord, + K: Borrow + Ord, + R: RangeBounds, + { + if let Some(root) = &self.root { + Range { inner: root.reborrow().range_search(range) } + } else { + Range { inner: LeafRange::none() } + } + } + + /// Constructs a mutable double-ended iterator over a sub-range of elements in the map. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. + /// + /// # Panics + /// + /// Panics if range `start > end`. + /// Panics if range `start == end` and both bounds are `Excluded`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"] + /// .iter() + /// .map(|&s| (s, 0)) + /// .collect(); + /// for (_, balance) in map.range_mut("B".."Cheryl") { + /// *balance += 100; + /// } + /// for (name, balance) in &map { + /// println!("{} => {}", name, balance); + /// } + /// ``` + #[stable(feature = "btree_range", since = "1.17.0")] + pub fn range_mut(&mut self, range: R) -> RangeMut<'_, K, V> + where + T: Ord, + K: Borrow + Ord, + R: RangeBounds, + { + if let Some(root) = &mut self.root { + RangeMut { inner: root.borrow_valmut().range_search(range), _marker: PhantomData } + } else { + RangeMut { inner: LeafRange::none(), _marker: PhantomData } + } + } + + /// Gets the given key's corresponding entry in the map for in-place manipulation. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut count: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// // count the number of occurrences of letters in the vec + /// for x in vec!["a", "b", "a", "c", "a", "b"] { + /// *count.entry(x).or_insert(0) += 1; + /// } + /// + /// assert_eq!(count["a"], 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn entry(&mut self, key: K) -> Entry<'_, K, V> + where + K: Ord, + { + // FIXME(@porglezomp) Avoid allocating if we don't insert + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut(); + match root_node.search_tree(&key) { + Found(handle) => Occupied(OccupiedEntry { handle, dormant_map, _marker: PhantomData }), + GoDown(handle) => { + Vacant(VacantEntry { key, handle, dormant_map, _marker: PhantomData }) + } + } + } + + /// Splits the collection into two at the given key. Returns everything after the given key, + /// including the key. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// a.insert(3, "c"); + /// a.insert(17, "d"); + /// a.insert(41, "e"); + /// + /// let b = a.split_off(&3); + /// + /// assert_eq!(a.len(), 2); + /// assert_eq!(b.len(), 3); + /// + /// assert_eq!(a[&1], "a"); + /// assert_eq!(a[&2], "b"); + /// + /// assert_eq!(b[&3], "c"); + /// assert_eq!(b[&17], "d"); + /// assert_eq!(b[&41], "e"); + /// ``` + #[stable(feature = "btree_split_off", since = "1.11.0")] + pub fn split_off(&mut self, key: &Q) -> Self + where + K: Borrow + Ord, + { + if self.is_empty() { + return Self::new(); + } + + let total_num = self.len(); + let left_root = self.root.as_mut().unwrap(); // unwrap succeeds because not empty + + let right_root = left_root.split_off(key); + + let (new_left_len, right_len) = Root::calc_split_length(total_num, &left_root, &right_root); + self.length = new_left_len; + + BTreeMap { root: Some(right_root), length: right_len } + } + + /// Creates an iterator that visits all elements (key-value pairs) in + /// ascending key order and uses a closure to determine if an element should + /// be removed. If the closure returns `true`, the element is removed from + /// the map and yielded. If the closure returns `false`, or panics, the + /// element remains in the map and will not be yielded. + /// + /// The iterator also lets you mutate the value of each element in the + /// closure, regardless of whether you choose to keep or remove it. + /// + /// If the iterator is only partially consumed or not consumed at all, each + /// of the remaining elements is still subjected to the closure, which may + /// change its value and, by returning `true`, have the element removed and + /// dropped. + /// + /// It is unspecified how many more elements will be subjected to the + /// closure if a panic occurs in the closure, or a panic occurs while + /// dropping an element, or if the `DrainFilter` value is leaked. + /// + /// # Examples + /// + /// Splitting a map into even and odd keys, reusing the original map: + /// + /// ``` + /// #![feature(btree_drain_filter)] + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap = (0..8).map(|x| (x, x)).collect(); + /// let evens: BTreeMap<_, _> = map.drain_filter(|k, _v| k % 2 == 0).collect(); + /// let odds = map; + /// assert_eq!(evens.keys().copied().collect::>(), vec![0, 2, 4, 6]); + /// assert_eq!(odds.keys().copied().collect::>(), vec![1, 3, 5, 7]); + /// ``` + #[unstable(feature = "btree_drain_filter", issue = "70530")] + pub fn drain_filter(&mut self, pred: F) -> DrainFilter<'_, K, V, F> + where + K: Ord, + F: FnMut(&K, &mut V) -> bool, + { + DrainFilter { pred, inner: self.drain_filter_inner() } + } + + pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> + where + K: Ord, + { + if let Some(root) = self.root.as_mut() { + let (root, dormant_root) = DormantMutRef::new(root); + let front = root.borrow_mut().first_leaf_edge(); + DrainFilterInner { + length: &mut self.length, + dormant_root: Some(dormant_root), + cur_leaf_edge: Some(front), + } + } else { + DrainFilterInner { length: &mut self.length, dormant_root: None, cur_leaf_edge: None } + } + } + + /// Creates a consuming iterator visiting all the keys, in sorted order. + /// The map cannot be used after calling this. + /// The iterator element type is `K`. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_into_keys_values)] + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(2, "b"); + /// a.insert(1, "a"); + /// + /// let keys: Vec = a.into_keys().collect(); + /// assert_eq!(keys, [1, 2]); + /// ``` + #[inline] + #[unstable(feature = "map_into_keys_values", issue = "75294")] + pub fn into_keys(self) -> IntoKeys { + IntoKeys { inner: self.into_iter() } + } + + /// Creates a consuming iterator visiting all the values, in order by key. + /// The map cannot be used after calling this. + /// The iterator element type is `V`. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_into_keys_values)] + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "hello"); + /// a.insert(2, "goodbye"); + /// + /// let values: Vec<&str> = a.into_values().collect(); + /// assert_eq!(values, ["hello", "goodbye"]); + /// ``` + #[inline] + #[unstable(feature = "map_into_keys_values", issue = "75294")] + pub fn into_values(self) -> IntoValues { + IntoValues { inner: self.into_iter() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> IntoIterator for &'a BTreeMap { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + + fn into_iter(self) -> Iter<'a, K, V> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_unchecked() }) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.length, Some(self.length)) + } + + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_back_unchecked() }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, K, V> { + fn len(&self) -> usize { + self.length + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, K, V> { + fn clone(&self) -> Self { + Iter { range: self.range.clone(), length: self.length } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> IntoIterator for &'a mut BTreeMap { + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + + fn into_iter(self) -> IterMut<'a, K, V> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_unchecked() }) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.length, Some(self.length)) + } + + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a mut V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K: 'a, V: 'a> DoubleEndedIterator for IterMut<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.next_back_unchecked() }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, K, V> { + fn len(&self) -> usize { + self.length + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, K, V> {} + +impl<'a, K, V> IterMut<'a, K, V> { + /// Returns an iterator of references over the remaining items. + #[inline] + pub(super) fn iter(&self) -> Iter<'_, K, V> { + Iter { range: self.range.iter(), length: self.length } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BTreeMap { + type Item = (K, V); + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + let mut me = ManuallyDrop::new(self); + if let Some(root) = me.root.take() { + let full_range = root.into_dying().full_range(); + + IntoIter { range: full_range, length: me.length } + } else { + IntoIter { range: LeafRange::none(), length: 0 } + } + } +} + +impl Drop for Dropper { + fn drop(&mut self) { + // Similar to advancing a non-fusing iterator. + fn next_or_end(this: &mut Dropper) -> Option<(K, V)> { + if this.remaining_length == 0 { + unsafe { ptr::read(&this.front).deallocating_end() } + None + } else { + this.remaining_length -= 1; + Some(unsafe { this.front.deallocating_next_unchecked() }) + } + } + + struct DropGuard<'a, K, V>(&'a mut Dropper); + + impl<'a, K, V> Drop for DropGuard<'a, K, V> { + fn drop(&mut self) { + // Continue the same loop we perform below. This only runs when unwinding, so we + // don't have to care about panics this time (they'll abort). + while let Some(_pair) = next_or_end(&mut self.0) {} + } + } + + while let Some(pair) = next_or_end(self) { + let guard = DropGuard(self); + drop(pair); + mem::forget(guard); + } + } +} + +#[stable(feature = "btree_drop", since = "1.7.0")] +impl Drop for IntoIter { + fn drop(&mut self) { + if let Some(front) = self.range.front.take() { + Dropper { front, remaining_length: self.length }; + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = (K, V); + + fn next(&mut self) -> Option<(K, V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.front.as_mut().unwrap().deallocating_next_unchecked() }) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.length, Some(self.length)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option<(K, V)> { + if self.length == 0 { + None + } else { + self.length -= 1; + Some(unsafe { self.range.back.as_mut().unwrap().deallocating_next_back_unchecked() }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.length + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> Iterator for Keys<'a, K, V> { + type Item = &'a K; + + fn next(&mut self) -> Option<&'a K> { + self.inner.next().map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option<&'a K> { + self.next_back() + } + + fn min(mut self) -> Option<&'a K> { + self.next() + } + + fn max(mut self) -> Option<&'a K> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { + fn next_back(&mut self) -> Option<&'a K> { + self.inner.next_back().map(|(k, _)| k) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Keys<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Keys<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Keys<'_, K, V> { + fn clone(&self) -> Self { + Keys { inner: self.inner.clone() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> Iterator for Values<'a, K, V> { + type Item = &'a V; + + fn next(&mut self) -> Option<&'a V> { + self.inner.next().map(|(_, v)| v) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option<&'a V> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { + fn next_back(&mut self) -> Option<&'a V> { + self.inner.next_back().map(|(_, v)| v) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Values<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Values<'_, K, V> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Values<'_, K, V> { + fn clone(&self) -> Self { + Values { inner: self.inner.clone() } + } +} + +/// An iterator produced by calling `drain_filter` on BTreeMap. +#[unstable(feature = "btree_drain_filter", issue = "70530")] +pub struct DrainFilter<'a, K, V, F> +where + K: 'a, + V: 'a, + F: 'a + FnMut(&K, &mut V) -> bool, +{ + pred: F, + inner: DrainFilterInner<'a, K, V>, +} +/// Most of the implementation of DrainFilter are generic over the type +/// of the predicate, thus also serving for BTreeSet::DrainFilter. +pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> { + /// Reference to the length field in the borrowed map, updated live. + length: &'a mut usize, + /// Buried reference to the root field in the borrowed map. + /// Wrapped in `Option` to allow drop handler to `take` it. + dormant_root: Option>>, + /// Contains a leaf edge preceding the next element to be returned, or the last leaf edge. + /// Empty if the map has no root, if iteration went beyond the last leaf edge, + /// or if a panic occurred in the predicate. + cur_leaf_edge: Option, K, V, marker::Leaf>, marker::Edge>>, +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl Drop for DrainFilter<'_, K, V, F> +where + F: FnMut(&K, &mut V) -> bool, +{ + fn drop(&mut self) { + self.for_each(drop); + } +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl fmt::Debug for DrainFilter<'_, K, V, F> +where + K: fmt::Debug, + V: fmt::Debug, + F: FnMut(&K, &mut V) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("DrainFilter").field(&self.inner.peek()).finish() + } +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl Iterator for DrainFilter<'_, K, V, F> +where + F: FnMut(&K, &mut V) -> bool, +{ + type Item = (K, V); + + fn next(&mut self) -> Option<(K, V)> { + self.inner.next(&mut self.pred) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> { + /// Allow Debug implementations to predict the next element. + pub(super) fn peek(&self) -> Option<(&K, &V)> { + let edge = self.cur_leaf_edge.as_ref()?; + edge.reborrow().next_kv().ok().map(Handle::into_kv) + } + + /// Implementation of a typical `DrainFilter::next` method, given the predicate. + pub(super) fn next(&mut self, pred: &mut F) -> Option<(K, V)> + where + F: FnMut(&K, &mut V) -> bool, + { + while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() { + let (k, v) = kv.kv_mut(); + if pred(k, v) { + *self.length -= 1; + let (kv, pos) = kv.remove_kv_tracking(|| { + // SAFETY: we will touch the root in a way that will not + // invalidate the position returned. + let root = unsafe { self.dormant_root.take().unwrap().awaken() }; + root.pop_internal_level(); + self.dormant_root = Some(DormantMutRef::new(root).1); + }); + self.cur_leaf_edge = Some(pos); + return Some(kv); + } + self.cur_leaf_edge = Some(kv.next_leaf_edge()); + } + None + } + + /// Implementation of a typical `DrainFilter::size_hint` method. + pub(super) fn size_hint(&self) -> (usize, Option) { + // In most of the btree iterators, `self.length` is the number of elements + // yet to be visited. Here, it includes elements that were visited and that + // the predicate decided not to drain. Making this upper bound more accurate + // requires maintaining an extra field and is not worth while. + (0, Some(*self.length)) + } +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> Iterator for Range<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) } + } + + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { + type Item = &'a mut V; + + fn next(&mut self) -> Option<&'a mut V> { + self.inner.next().map(|(_, v)| v) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option<&'a mut V> { + self.next_back() + } +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { + fn next_back(&mut self) -> Option<&'a mut V> { + self.inner.next_back().map(|(_, v)| v) + } +} + +#[stable(feature = "map_values_mut", since = "1.10.0")] +impl ExactSizeIterator for ValuesMut<'_, K, V> { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for ValuesMut<'_, K, V> {} + +impl<'a, K, V> Range<'a, K, V> { + unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() } + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl Iterator for IntoKeys { + type Item = K; + + fn next(&mut self) -> Option { + self.inner.next().map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option { + self.next_back() + } + + fn min(mut self) -> Option { + self.next() + } + + fn max(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl DoubleEndedIterator for IntoKeys { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|(k, _)| k) + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl ExactSizeIterator for IntoKeys { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl FusedIterator for IntoKeys {} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl Iterator for IntoValues { + type Item = V; + + fn next(&mut self) -> Option { + self.inner.next().map(|(_, v)| v) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn last(mut self) -> Option { + self.next_back() + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl DoubleEndedIterator for IntoValues { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|(_, v)| v) + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl ExactSizeIterator for IntoValues { + fn len(&self) -> usize { + self.inner.len() + } +} + +#[unstable(feature = "map_into_keys_values", issue = "75294")] +impl FusedIterator for IntoValues {} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a V)> { + if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) } + } +} + +impl<'a, K, V> Range<'a, K, V> { + unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Range<'_, K, V> {} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl Clone for Range<'_, K, V> { + fn clone(&self) -> Self { + Range { inner: LeafRange { front: self.inner.front, back: self.inner.back } } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> Iterator for RangeMut<'a, K, V> { + type Item = (&'a K, &'a mut V); + + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) } + } + + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } + + fn min(mut self) -> Option<(&'a K, &'a mut V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } +} + +impl<'a, K, V> RangeMut<'a, K, V> { + unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() } + } + + /// Returns an iterator of references over the remaining items. + #[inline] + pub(super) fn iter(&self) -> Range<'_, K, V> { + Range { inner: self.inner.reborrow() } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { + fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { + if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) } + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for RangeMut<'_, K, V> {} + +impl<'a, K, V> RangeMut<'a, K, V> { + unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator<(K, V)> for BTreeMap { + fn from_iter>(iter: T) -> BTreeMap { + let mut map = BTreeMap::new(); + map.extend(iter); + map + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend<(K, V)> for BTreeMap { + #[inline] + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(move |(k, v)| { + self.insert(k, v); + }); + } + + #[inline] + fn extend_one(&mut self, (k, v): (K, V)) { + self.insert(k, v); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); + } + + #[inline] + fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { + self.insert(k, v); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for BTreeMap { + fn hash(&self, state: &mut H) { + for elt in self { + elt.hash(state); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for BTreeMap { + /// Creates an empty `BTreeMap`. + fn default() -> BTreeMap { + BTreeMap::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for BTreeMap { + fn eq(&self, other: &BTreeMap) -> bool { + self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a == b) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for BTreeMap {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for BTreeMap { + #[inline] + fn partial_cmp(&self, other: &BTreeMap) -> Option { + self.iter().partial_cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for BTreeMap { + #[inline] + fn cmp(&self, other: &BTreeMap) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for BTreeMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Index<&Q> for BTreeMap +where + K: Borrow + Ord, + Q: Ord, +{ + type Output = V; + + /// Returns a reference to the value corresponding to the supplied key. + /// + /// # Panics + /// + /// Panics if the key is not present in the `BTreeMap`. + #[inline] + fn index(&self, key: &Q) -> &V { + self.get(key).expect("no entry found for key") + } +} + +impl BTreeMap { + /// Gets an iterator over the entries of the map, sorted by key. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(3, "c"); + /// map.insert(2, "b"); + /// map.insert(1, "a"); + /// + /// for (key, value) in map.iter() { + /// println!("{}: {}", key, value); + /// } + /// + /// let (first_key, first_value) = map.iter().next().unwrap(); + /// assert_eq!((*first_key, *first_value), (1, "a")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, K, V> { + if let Some(root) = &self.root { + let full_range = root.reborrow().full_range(); + + Iter { range: Range { inner: full_range }, length: self.length } + } else { + Iter { range: Range { inner: LeafRange::none() }, length: 0 } + } + } + + /// Gets a mutable iterator over the entries of the map, sorted by key. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert("a", 1); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// // add 10 to the value if the key isn't "a" + /// for (key, value) in map.iter_mut() { + /// if key != &"a" { + /// *value += 10; + /// } + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + if let Some(root) = &mut self.root { + let full_range = root.borrow_valmut().full_range(); + + IterMut { + range: RangeMut { inner: full_range, _marker: PhantomData }, + length: self.length, + } + } else { + IterMut { + range: RangeMut { inner: LeafRange::none(), _marker: PhantomData }, + length: 0, + } + } + } + + /// Gets an iterator over the keys of the map, in sorted order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(2, "b"); + /// a.insert(1, "a"); + /// + /// let keys: Vec<_> = a.keys().cloned().collect(); + /// assert_eq!(keys, [1, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn keys(&self) -> Keys<'_, K, V> { + Keys { inner: self.iter() } + } + + /// Gets an iterator over the values of the map, in order by key. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, "hello"); + /// a.insert(2, "goodbye"); + /// + /// let values: Vec<&str> = a.values().cloned().collect(); + /// assert_eq!(values, ["hello", "goodbye"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn values(&self) -> Values<'_, K, V> { + Values { inner: self.iter() } + } + + /// Gets a mutable iterator over the values of the map, in order by key. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// a.insert(1, String::from("hello")); + /// a.insert(2, String::from("goodbye")); + /// + /// for value in a.values_mut() { + /// value.push_str("!"); + /// } + /// + /// let values: Vec = a.values().cloned().collect(); + /// assert_eq!(values, [String::from("hello!"), + /// String::from("goodbye!")]); + /// ``` + #[stable(feature = "map_values_mut", since = "1.10.0")] + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + ValuesMut { inner: self.iter_mut() } + } + + /// Returns the number of elements in the map. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + #[doc(alias = "length")] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn len(&self) -> usize { + self.length + } + + /// Returns `true` if the map contains no elements. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut a = BTreeMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1, "a"); + /// assert!(!a.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// If the root node is the empty (non-allocated) root node, allocate our + /// own node. Is an associated function to avoid borrowing the entire BTreeMap. + fn ensure_is_owned(root: &mut Option>) -> &mut Root { + root.get_or_insert_with(Root::new) + } +} + +#[cfg(test)] +mod tests; +use core::marker::PhantomData; +use core::ptr::NonNull; + +/// Models a reborrow of some unique reference, when you know that the reborrow +/// and all its descendants (i.e., all pointers and references derived from it) +/// will not be used any more at some point, after which you want to use the +/// original unique reference again. +/// +/// The borrow checker usually handles this stacking of borrows for you, but +/// some control flows that accomplish this stacking are too complicated for +/// the compiler to follow. A `DormantMutRef` allows you to check borrowing +/// yourself, while still expressing its stacked nature, and encapsulating +/// the raw pointer code needed to do this without undefined behavior. +pub struct DormantMutRef<'a, T> { + ptr: NonNull, + _marker: PhantomData<&'a mut T>, +} + +unsafe impl<'a, T> Sync for DormantMutRef<'a, T> where &'a mut T: Sync {} +unsafe impl<'a, T> Send for DormantMutRef<'a, T> where &'a mut T: Send {} + +impl<'a, T> DormantMutRef<'a, T> { + /// Capture a unique borrow, and immediately reborrow it. For the compiler, + /// the lifetime of the new reference is the same as the lifetime of the + /// original reference, but you promise to use it for a shorter period. + pub fn new(t: &'a mut T) -> (&'a mut T, Self) { + let ptr = NonNull::from(t); + // SAFETY: we hold the borrow throughout 'a via `_marker`, and we expose + // only this reference, so it is unique. + let new_ref = unsafe { &mut *ptr.as_ptr() }; + (new_ref, Self { ptr, _marker: PhantomData }) + } + + /// Revert to the unique borrow initially captured. + /// + /// # Safety + /// + /// The reborrow must have ended, i.e., the reference returned by `new` and + /// all pointers and references derived from it, must not be used anymore. + pub unsafe fn awaken(self) -> &'a mut T { + // SAFETY: our own safety conditions imply this reference is again unique. + unsafe { &mut *self.ptr.as_ptr() } + } +} + +#[cfg(test)] +mod tests; +use core::intrinsics; +use core::mem; +use core::ptr; + +/// This replaces the value behind the `v` unique reference by calling the +/// relevant function. +/// +/// If a panic occurs in the `change` closure, the entire process will be aborted. +#[allow(dead_code)] // keep as illustration and for future use +#[inline] +pub fn take_mut(v: &mut T, change: impl FnOnce(T) -> T) { + replace(v, |value| (change(value), ())) +} + +/// This replaces the value behind the `v` unique reference by calling the +/// relevant function, and returns a result obtained along the way. +/// +/// If a panic occurs in the `change` closure, the entire process will be aborted. +#[inline] +pub fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { + struct PanicGuard; + impl Drop for PanicGuard { + fn drop(&mut self) { + intrinsics::abort() + } + } + let guard = PanicGuard; + let value = unsafe { ptr::read(v) }; + let (new_value, ret) = change(value); + unsafe { + ptr::write(v, new_value); + } + mem::forget(guard); + ret +} +use super::node::{ForceResult::*, Root}; +use super::search::SearchResult::*; +use core::borrow::Borrow; + +impl Root { + /// Calculates the length of both trees that result from splitting up + /// a given number of distinct key-value pairs. + pub fn calc_split_length( + total_num: usize, + root_a: &Root, + root_b: &Root, + ) -> (usize, usize) { + let (length_a, length_b); + if root_a.height() < root_b.height() { + length_a = root_a.reborrow().calc_length(); + length_b = total_num - length_a; + debug_assert_eq!(length_b, root_b.reborrow().calc_length()); + } else { + length_b = root_b.reborrow().calc_length(); + length_a = total_num - length_b; + debug_assert_eq!(length_a, root_a.reborrow().calc_length()); + } + (length_a, length_b) + } + + /// Split off a tree with key-value pairs at and after the given key. + /// The result is meaningful only if the tree is ordered by key, + /// and if the ordering of `Q` corresponds to that of `K`. + /// If `self` respects all `BTreeMap` tree invariants, then both + /// `self` and the returned tree will respect those invariants. + pub fn split_off(&mut self, key: &Q) -> Self + where + K: Borrow, + { + let left_root = self; + let mut right_root = Root::new_pillar(left_root.height()); + let mut left_node = left_root.borrow_mut(); + let mut right_node = right_root.borrow_mut(); + + loop { + let mut split_edge = match left_node.search_node(key) { + // key is going to the right tree + Found(kv) => kv.left_edge(), + GoDown(edge) => edge, + }; + + split_edge.move_suffix(&mut right_node); + + match (split_edge.force(), right_node.force()) { + (Internal(edge), Internal(node)) => { + left_node = edge.descend(); + right_node = node.first_edge().descend(); + } + (Leaf(_), Leaf(_)) => break, + _ => unreachable!(), + } + } + + left_root.fix_right_border(); + right_root.fix_left_border(); + right_root + } + + /// Creates a tree consisting of empty nodes. + fn new_pillar(height: usize) -> Self { + let mut root = Root::new(); + for _ in 0..height { + root.push_internal_level(); + } + root + } +} +// This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface +// to TreeMap + +use core::borrow::Borrow; +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::cmp::{max, min}; +use core::fmt::{self, Debug}; +use core::iter::{FromIterator, FusedIterator, Peekable}; +use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub}; + +use super::map::{BTreeMap, Keys}; +use super::merge_iter::MergeIterInner; +use super::Recover; + +// FIXME(conventions): implement bounded iterators + +/// A set based on a B-Tree. +/// +/// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance +/// benefits and drawbacks. +/// +/// It is a logic error for an item to be modified in such a way that the item's ordering relative +/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is +/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. +/// The behavior resulting from such a logic error is not specified, but will not result in +/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and +/// non-termination. +/// +/// [`Ord`]: core::cmp::Ord +/// [`Cell`]: core::cell::Cell +/// [`RefCell`]: core::cell::RefCell +/// +/// # Examples +/// +/// ``` +/// use std::collections::BTreeSet; +/// +/// // Type inference lets us omit an explicit type signature (which +/// // would be `BTreeSet<&str>` in this example). +/// let mut books = BTreeSet::new(); +/// +/// // Add some books. +/// books.insert("A Dance With Dragons"); +/// books.insert("To Kill a Mockingbird"); +/// books.insert("The Odyssey"); +/// books.insert("The Great Gatsby"); +/// +/// // Check for a specific one. +/// if !books.contains("The Winds of Winter") { +/// println!("We have {} books, but The Winds of Winter ain't one.", +/// books.len()); +/// } +/// +/// // Remove a book. +/// books.remove("The Odyssey"); +/// +/// // Iterate over everything. +/// for book in &books { +/// println!("{}", book); +/// } +/// ``` +#[derive(Hash, PartialEq, Eq, Ord, PartialOrd)] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")] +pub struct BTreeSet { + map: BTreeMap, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BTreeSet { + fn clone(&self) -> Self { + BTreeSet { map: self.map.clone() } + } + + fn clone_from(&mut self, other: &Self) { + self.map.clone_from(&other.map); + } +} + +/// An iterator over the items of a `BTreeSet`. +/// +/// This `struct` is created by the [`iter`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`iter`]: BTreeSet::iter +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + iter: Keys<'a, T, ()>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.iter.clone()).finish() + } +} + +/// An owning iterator over the items of a `BTreeSet`. +/// +/// This `struct` is created by the [`into_iter`] method on [`BTreeSet`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: BTreeSet#method.into_iter +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] +pub struct IntoIter { + iter: super::map::IntoIter, +} + +/// An iterator over a sub-range of items in a `BTreeSet`. +/// +/// This `struct` is created by the [`range`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`range`]: BTreeSet::range +#[derive(Debug)] +#[stable(feature = "btree_range", since = "1.17.0")] +pub struct Range<'a, T: 'a> { + iter: super::map::Range<'a, T, ()>, +} + +/// A lazy iterator producing elements in the difference of `BTreeSet`s. +/// +/// This `struct` is created by the [`difference`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`difference`]: BTreeSet::difference +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Difference<'a, T: 'a> { + inner: DifferenceInner<'a, T>, +} +#[derive(Debug)] +enum DifferenceInner<'a, T: 'a> { + Stitch { + // iterate all of `self` and some of `other`, spotting matches along the way + self_iter: Iter<'a, T>, + other_iter: Peekable>, + }, + Search { + // iterate `self`, look up in `other` + self_iter: Iter<'a, T>, + other_set: &'a BTreeSet, + }, + Iterate(Iter<'a, T>), // simply produce all values in `self` +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Difference<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Difference").field(&self.inner).finish() + } +} + +/// A lazy iterator producing elements in the symmetric difference of `BTreeSet`s. +/// +/// This `struct` is created by the [`symmetric_difference`] method on +/// [`BTreeSet`]. See its documentation for more. +/// +/// [`symmetric_difference`]: BTreeSet::symmetric_difference +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for SymmetricDifference<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SymmetricDifference").field(&self.0).finish() + } +} + +/// A lazy iterator producing elements in the intersection of `BTreeSet`s. +/// +/// This `struct` is created by the [`intersection`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`intersection`]: BTreeSet::intersection +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Intersection<'a, T: 'a> { + inner: IntersectionInner<'a, T>, +} +#[derive(Debug)] +enum IntersectionInner<'a, T: 'a> { + Stitch { + // iterate similarly sized sets jointly, spotting matches along the way + a: Iter<'a, T>, + b: Iter<'a, T>, + }, + Search { + // iterate a small set, look up in the large set + small_iter: Iter<'a, T>, + large_set: &'a BTreeSet, + }, + Answer(Option<&'a T>), // return a specific value or emptiness +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Intersection<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Intersection").field(&self.inner).finish() + } +} + +/// A lazy iterator producing elements in the union of `BTreeSet`s. +/// +/// This `struct` is created by the [`union`] method on [`BTreeSet`]. +/// See its documentation for more. +/// +/// [`union`]: BTreeSet::union +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Union<'a, T: 'a>(MergeIterInner>); + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Union<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Union").field(&self.0).finish() + } +} + +// This constant is used by functions that compare two sets. +// It estimates the relative size at which searching performs better +// than iterating, based on the benchmarks in +// https://github.com/ssomers/rust_bench_btreeset_intersection. +// It's used to divide rather than multiply sizes, to rule out overflow, +// and it's a power of two to make that division cheap. +const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16; + +impl BTreeSet { + /// Makes a new, empty `BTreeSet`. + /// + /// Does not allocate anything on its own. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet = BTreeSet::new(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn new() -> BTreeSet + where + T: Ord, + { + BTreeSet { map: BTreeMap::new() } + } + + /// Constructs a double-ended iterator over a sub-range of elements in the set. + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will + /// yield elements from min (inclusive) to max (exclusive). + /// The range may also be entered as `(Bound, Bound)`, so for example + /// `range((Excluded(4), Included(10)))` will yield a left-exclusive, right-inclusive + /// range from 4 to 10. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// use std::ops::Bound::Included; + /// + /// let mut set = BTreeSet::new(); + /// set.insert(3); + /// set.insert(5); + /// set.insert(8); + /// for &elem in set.range((Included(&4), Included(&8))) { + /// println!("{}", elem); + /// } + /// assert_eq!(Some(&5), set.range(4..).next()); + /// ``` + #[stable(feature = "btree_range", since = "1.17.0")] + pub fn range(&self, range: R) -> Range<'_, T> + where + K: Ord, + T: Borrow + Ord, + R: RangeBounds, + { + Range { iter: self.map.range(range) } + } + + /// Visits the values representing the difference, + /// i.e., the values that are in `self` but not in `other`, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// b.insert(3); + /// + /// let diff: Vec<_> = a.difference(&b).cloned().collect(); + /// assert_eq!(diff, [1]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> + where + T: Ord, + { + let (self_min, self_max) = + if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { + (self_min, self_max) + } else { + return Difference { inner: DifferenceInner::Iterate(self.iter()) }; + }; + let (other_min, other_max) = + if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { + (other_min, other_max) + } else { + return Difference { inner: DifferenceInner::Iterate(self.iter()) }; + }; + Difference { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), + (Equal, _) => { + let mut self_iter = self.iter(); + self_iter.next(); + DifferenceInner::Iterate(self_iter) + } + (_, Equal) => { + let mut self_iter = self.iter(); + self_iter.next_back(); + DifferenceInner::Iterate(self_iter) + } + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + DifferenceInner::Search { self_iter: self.iter(), other_set: other } + } + _ => DifferenceInner::Stitch { + self_iter: self.iter(), + other_iter: other.iter().peekable(), + }, + }, + } + } + + /// Visits the values representing the symmetric difference, + /// i.e., the values that are in `self` or in `other` but not in both, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// b.insert(3); + /// + /// let sym_diff: Vec<_> = a.symmetric_difference(&b).cloned().collect(); + /// assert_eq!(sym_diff, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet) -> SymmetricDifference<'a, T> + where + T: Ord, + { + SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) + } + + /// Visits the values representing the intersection, + /// i.e., the values that are both in `self` and `other`, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// b.insert(3); + /// + /// let intersection: Vec<_> = a.intersection(&b).cloned().collect(); + /// assert_eq!(intersection, [2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> + where + T: Ord, + { + let (self_min, self_max) = + if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { + (self_min, self_max) + } else { + return Intersection { inner: IntersectionInner::Answer(None) }; + }; + let (other_min, other_max) = + if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { + (other_min, other_max) + } else { + return Intersection { inner: IntersectionInner::Answer(None) }; + }; + Intersection { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => IntersectionInner::Answer(None), + (Equal, _) => IntersectionInner::Answer(Some(self_min)), + (_, Equal) => IntersectionInner::Answer(Some(self_max)), + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { small_iter: self.iter(), large_set: other } + } + _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { small_iter: other.iter(), large_set: self } + } + _ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() }, + }, + } + } + + /// Visits the values representing the union, + /// i.e., all the values in `self` or `other`, without duplicates, + /// in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(2); + /// + /// let union: Vec<_> = a.union(&b).cloned().collect(); + /// assert_eq!(union, [1, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> + where + T: Ord, + { + Union(MergeIterInner::new(self.iter(), other.iter())) + } + + /// Clears the set, removing all values. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut v = BTreeSet::new(); + /// v.insert(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.map.clear() + } + + /// Returns `true` if the set contains a value. + /// + /// The value may be any borrowed form of the set's value type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the value type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn contains(&self, value: &Q) -> bool + where + T: Borrow + Ord, + Q: Ord, + { + self.map.contains_key(value) + } + + /// Returns a reference to the value in the set, if any, that is equal to the given value. + /// + /// The value may be any borrowed form of the set's value type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the value type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// assert_eq!(set.get(&2), Some(&2)); + /// assert_eq!(set.get(&4), None); + /// ``` + #[stable(feature = "set_recovery", since = "1.9.0")] + pub fn get(&self, value: &Q) -> Option<&T> + where + T: Borrow + Ord, + Q: Ord, + { + Recover::get(&self.map, value) + } + + /// Returns `true` if `self` has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut b = BTreeSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_disjoint(&self, other: &BTreeSet) -> bool + where + T: Ord, + { + self.intersection(other).next().is_none() + } + + /// Returns `true` if the set is a subset of another, + /// i.e., `other` contains at least all the values in `self`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_subset(&self, other: &BTreeSet) -> bool + where + T: Ord, + { + // Same result as self.difference(other).next().is_none() + // but the code below is faster (hugely in some cases). + if self.len() > other.len() { + return false; + } + let (self_min, self_max) = + if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { + (self_min, self_max) + } else { + return true; // self is empty + }; + let (other_min, other_max) = + if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { + (other_min, other_max) + } else { + return false; // other is empty + }; + let mut self_iter = self.iter(); + match self_min.cmp(other_min) { + Less => return false, + Equal => { + self_iter.next(); + } + Greater => (), + } + match self_max.cmp(other_max) { + Greater => return false, + Equal => { + self_iter.next_back(); + } + Less => (), + } + if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + for next in self_iter { + if !other.contains(next) { + return false; + } + } + } else { + let mut other_iter = other.iter(); + other_iter.next(); + other_iter.next_back(); + let mut self_next = self_iter.next(); + while let Some(self1) = self_next { + match other_iter.next().map_or(Less, |other1| self1.cmp(other1)) { + Less => return false, + Equal => self_next = self_iter.next(), + Greater => (), + } + } + } + true + } + + /// Returns `true` if the set is a superset of another, + /// i.e., `self` contains at least all the values in `other`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect(); + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_superset(&self, other: &BTreeSet) -> bool + where + T: Ord, + { + other.is_subset(self) + } + + /// Returns a reference to the first value in the set, if any. + /// This value is always the minimum of all values in the set. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.first(), None); + /// set.insert(1); + /// assert_eq!(set.first(), Some(&1)); + /// set.insert(2); + /// assert_eq!(set.first(), Some(&1)); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn first(&self) -> Option<&T> + where + T: Ord, + { + self.map.first_key_value().map(|(k, _)| k) + } + + /// Returns a reference to the last value in the set, if any. + /// This value is always the maximum of all values in the set. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.last(), None); + /// set.insert(1); + /// assert_eq!(set.last(), Some(&1)); + /// set.insert(2); + /// assert_eq!(set.last(), Some(&2)); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn last(&self) -> Option<&T> + where + T: Ord, + { + self.map.last_key_value().map(|(k, _)| k) + } + + /// Removes the first value from the set and returns it, if any. + /// The first value is always the minimum value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(1); + /// while let Some(n) = set.pop_first() { + /// assert_eq!(n, 1); + /// } + /// assert!(set.is_empty()); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn pop_first(&mut self) -> Option + where + T: Ord, + { + self.map.pop_first().map(|kv| kv.0) + } + + /// Removes the last value from the set and returns it, if any. + /// The last value is always the maximum value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(1); + /// while let Some(n) = set.pop_last() { + /// assert_eq!(n, 1); + /// } + /// assert!(set.is_empty()); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn pop_last(&mut self) -> Option + where + T: Ord, + { + self.map.pop_last().map(|kv| kv.0) + } + + /// Adds a value to the set. + /// + /// If the set did not have this value present, `true` is returned. + /// + /// If the set did have this value present, `false` is returned, and the + /// entry is not updated. See the [module-level documentation] for more. + /// + /// [module-level documentation]: index.html#insert-and-complex-keys + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.len(), 1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, value: T) -> bool + where + T: Ord, + { + self.map.insert(value, ()).is_none() + } + + /// Adds a value to the set, replacing the existing value, if any, that is equal to the given + /// one. Returns the replaced value. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// set.insert(Vec::::new()); + /// + /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0); + /// set.replace(Vec::with_capacity(10)); + /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); + /// ``` + #[stable(feature = "set_recovery", since = "1.9.0")] + pub fn replace(&mut self, value: T) -> Option + where + T: Ord, + { + Recover::replace(&mut self.map, value) + } + + /// Removes a value from the set. Returns whether the value was + /// present in the set. + /// + /// The value may be any borrowed form of the set's value type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the value type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(2); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + #[doc(alias = "delete")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, value: &Q) -> bool + where + T: Borrow + Ord, + Q: Ord, + { + self.map.remove(value).is_some() + } + + /// Removes and returns the value in the set, if any, that is equal to the given one. + /// + /// The value may be any borrowed form of the set's value type, + /// but the ordering on the borrowed form *must* match the + /// ordering on the value type. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// assert_eq!(set.take(&2), Some(2)); + /// assert_eq!(set.take(&2), None); + /// ``` + #[stable(feature = "set_recovery", since = "1.9.0")] + pub fn take(&mut self, value: &Q) -> Option + where + T: Borrow + Ord, + Q: Ord, + { + Recover::take(&mut self.map, value) + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let xs = [1, 2, 3, 4, 5, 6]; + /// let mut set: BTreeSet = xs.iter().cloned().collect(); + /// // Keep only the even numbers. + /// set.retain(|&k| k % 2 == 0); + /// assert!(set.iter().eq([2, 4, 6].iter())); + /// ``` + #[stable(feature = "btree_retain", since = "1.53.0")] + pub fn retain(&mut self, mut f: F) + where + T: Ord, + F: FnMut(&T) -> bool, + { + self.drain_filter(|v| !f(v)); + } + + /// Moves all elements from `other` into `Self`, leaving `other` empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// a.insert(3); + /// + /// let mut b = BTreeSet::new(); + /// b.insert(3); + /// b.insert(4); + /// b.insert(5); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 5); + /// assert_eq!(b.len(), 0); + /// + /// assert!(a.contains(&1)); + /// assert!(a.contains(&2)); + /// assert!(a.contains(&3)); + /// assert!(a.contains(&4)); + /// assert!(a.contains(&5)); + /// ``` + #[stable(feature = "btree_append", since = "1.11.0")] + pub fn append(&mut self, other: &mut Self) + where + T: Ord, + { + self.map.append(&mut other.map); + } + + /// Splits the collection into two at the given key. Returns everything after the given key, + /// including the key. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut a = BTreeSet::new(); + /// a.insert(1); + /// a.insert(2); + /// a.insert(3); + /// a.insert(17); + /// a.insert(41); + /// + /// let b = a.split_off(&3); + /// + /// assert_eq!(a.len(), 2); + /// assert_eq!(b.len(), 3); + /// + /// assert!(a.contains(&1)); + /// assert!(a.contains(&2)); + /// + /// assert!(b.contains(&3)); + /// assert!(b.contains(&17)); + /// assert!(b.contains(&41)); + /// ``` + #[stable(feature = "btree_split_off", since = "1.11.0")] + pub fn split_off(&mut self, key: &Q) -> Self + where + T: Borrow + Ord, + { + BTreeSet { map: self.map.split_off(key) } + } + + /// Creates an iterator which uses a closure to determine if a value should be removed. + /// + /// If the closure returns true, then the value is removed and yielded. + /// If the closure returns false, the value will remain in the list and will not be yielded + /// by the iterator. + /// + /// If the iterator is only partially consumed or not consumed at all, each of the remaining + /// values will still be subjected to the closure and removed and dropped if it returns true. + /// + /// It is unspecified how many more values will be subjected to the closure + /// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the + /// `DrainFilter` itself is leaked. + /// + /// # Examples + /// + /// Splitting a set into even and odd values, reusing the original set: + /// + /// ``` + /// #![feature(btree_drain_filter)] + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet = (0..8).collect(); + /// let evens: BTreeSet<_> = set.drain_filter(|v| v % 2 == 0).collect(); + /// let odds = set; + /// assert_eq!(evens.into_iter().collect::>(), vec![0, 2, 4, 6]); + /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 7]); + /// ``` + #[unstable(feature = "btree_drain_filter", issue = "70530")] + pub fn drain_filter<'a, F>(&'a mut self, pred: F) -> DrainFilter<'a, T, F> + where + T: Ord, + F: 'a + FnMut(&T) -> bool, + { + DrainFilter { pred, inner: self.map.drain_filter_inner() } + } + + /// Gets an iterator that visits the values in the `BTreeSet` in ascending order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [1, 2, 3].iter().cloned().collect(); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); + /// ``` + /// + /// Values returned by the iterator are returned in ascending order: + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [3, 1, 2].iter().cloned().collect(); + /// let mut set_iter = set.iter(); + /// assert_eq!(set_iter.next(), Some(&1)); + /// assert_eq!(set_iter.next(), Some(&2)); + /// assert_eq!(set_iter.next(), Some(&3)); + /// assert_eq!(set_iter.next(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { iter: self.map.keys() } + } + + /// Returns the number of elements in the set. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut v = BTreeSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1); + /// assert_eq!(v.len(), 1); + /// ``` + #[doc(alias = "length")] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn len(&self) -> usize { + self.map.len() + } + + /// Returns `true` if the set contains no elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut v = BTreeSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1); + /// assert!(!v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for BTreeSet { + fn from_iter>(iter: I) -> BTreeSet { + let mut set = BTreeSet::new(); + set.extend(iter); + set + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BTreeSet { + type Item = T; + type IntoIter = IntoIter; + + /// Gets an iterator for moving out the `BTreeSet`'s contents. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); + /// + /// let v: Vec<_> = set.into_iter().collect(); + /// assert_eq!(v, [1, 2, 3, 4]); + /// ``` + fn into_iter(self) -> IntoIter { + IntoIter { iter: self.map.into_iter() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a BTreeSet { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +/// An iterator produced by calling `drain_filter` on BTreeSet. +#[unstable(feature = "btree_drain_filter", issue = "70530")] +pub struct DrainFilter<'a, T, F> +where + T: 'a, + F: 'a + FnMut(&T) -> bool, +{ + pred: F, + inner: super::map::DrainFilterInner<'a, T, ()>, +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl Drop for DrainFilter<'_, T, F> +where + F: FnMut(&T) -> bool, +{ + fn drop(&mut self) { + self.for_each(drop); + } +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl fmt::Debug for DrainFilter<'_, T, F> +where + T: fmt::Debug, + F: FnMut(&T) -> bool, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("DrainFilter").field(&self.inner.peek().map(|(k, _)| k)).finish() + } +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl<'a, T, F> Iterator for DrainFilter<'_, T, F> +where + F: 'a + FnMut(&T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + let pred = &mut self.pred; + let mut mapped_pred = |k: &T, _v: &mut ()| pred(k); + self.inner.next(&mut mapped_pred).map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[unstable(feature = "btree_drain_filter", issue = "70530")] +impl FusedIterator for DrainFilter<'_, T, F> where F: FnMut(&T) -> bool {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for BTreeSet { + #[inline] + fn extend>(&mut self, iter: Iter) { + iter.into_iter().for_each(move |elem| { + self.insert(elem); + }); + } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.insert(elem); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.insert(elem); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for BTreeSet { + /// Creates an empty `BTreeSet`. + fn default() -> BTreeSet { + BTreeSet::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Sub<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the difference of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); + /// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect(); + /// + /// let result = &a - &b; + /// let result_vec: Vec<_> = result.into_iter().collect(); + /// assert_eq!(result_vec, [1, 2]); + /// ``` + fn sub(self, rhs: &BTreeSet) -> BTreeSet { + self.difference(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BitXor<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); + /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect(); + /// + /// let result = &a ^ &b; + /// let result_vec: Vec<_> = result.into_iter().collect(); + /// assert_eq!(result_vec, [1, 4]); + /// ``` + fn bitxor(self, rhs: &BTreeSet) -> BTreeSet { + self.symmetric_difference(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BitAnd<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the intersection of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); + /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect(); + /// + /// let result = &a & &b; + /// let result_vec: Vec<_> = result.into_iter().collect(); + /// assert_eq!(result_vec, [2, 3]); + /// ``` + fn bitand(self, rhs: &BTreeSet) -> BTreeSet { + self.intersection(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BitOr<&BTreeSet> for &BTreeSet { + type Output = BTreeSet; + + /// Returns the union of `self` and `rhs` as a new `BTreeSet`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); + /// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect(); + /// + /// let result = &a | &b; + /// let result_vec: Vec<_> = result.into_iter().collect(); + /// assert_eq!(result_vec, [1, 2, 3, 4, 5]); + /// ``` + fn bitor(self, rhs: &BTreeSet) -> BTreeSet { + self.union(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for BTreeSet { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_set().entries(self.iter()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { iter: self.iter.clone() } + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + fn last(mut self) -> Option<&'a T> { + self.next_back() + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } + + fn max(mut self) -> Option<&'a T> { + self.next_back() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + fn next_back(&mut self) -> Option<&'a T> { + self.iter.next_back() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn len(&self) -> usize { + self.iter.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + fn next(&mut self) -> Option { + self.iter.next().map(|(k, _)| k) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|(k, _)| k) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.iter.len() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl Clone for Range<'_, T> { + fn clone(&self) -> Self { + Range { iter: self.iter.clone() } + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, T> Iterator for Range<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + self.iter.next().map(|(k, _)| k) + } + + fn last(mut self) -> Option<&'a T> { + self.next_back() + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } + + fn max(mut self) -> Option<&'a T> { + self.next_back() + } +} + +#[stable(feature = "btree_range", since = "1.17.0")] +impl<'a, T> DoubleEndedIterator for Range<'a, T> { + fn next_back(&mut self) -> Option<&'a T> { + self.iter.next_back().map(|(k, _)| k) + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Range<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Difference<'_, T> { + fn clone(&self) -> Self { + Difference { + inner: match &self.inner { + DifferenceInner::Stitch { self_iter, other_iter } => DifferenceInner::Stitch { + self_iter: self_iter.clone(), + other_iter: other_iter.clone(), + }, + DifferenceInner::Search { self_iter, other_set } => { + DifferenceInner::Search { self_iter: self_iter.clone(), other_set } + } + DifferenceInner::Iterate(iter) => DifferenceInner::Iterate(iter.clone()), + }, + } + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord> Iterator for Difference<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + match &mut self.inner { + DifferenceInner::Stitch { self_iter, other_iter } => { + let mut self_next = self_iter.next()?; + loop { + match other_iter.peek().map_or(Less, |other_next| self_next.cmp(other_next)) { + Less => return Some(self_next), + Equal => { + self_next = self_iter.next()?; + other_iter.next(); + } + Greater => { + other_iter.next(); + } + } + } + } + DifferenceInner::Search { self_iter, other_set } => loop { + let self_next = self_iter.next()?; + if !other_set.contains(&self_next) { + return Some(self_next); + } + }, + DifferenceInner::Iterate(iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + let (self_len, other_len) = match &self.inner { + DifferenceInner::Stitch { self_iter, other_iter } => { + (self_iter.len(), other_iter.len()) + } + DifferenceInner::Search { self_iter, other_set } => (self_iter.len(), other_set.len()), + DifferenceInner::Iterate(iter) => (iter.len(), 0), + }; + (self_len.saturating_sub(other_len), Some(self_len)) + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Difference<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SymmetricDifference<'_, T> { + fn clone(&self) -> Self { + SymmetricDifference(self.0.clone()) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + loop { + let (a_next, b_next) = self.0.nexts(Self::Item::cmp); + if a_next.and(b_next).is_none() { + return a_next.or(b_next); + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let (a_len, b_len) = self.0.lens(); + // No checked_add, because even if a and b refer to the same set, + // and T is an empty type, the storage overhead of sets limits + // the number of elements to less than half the range of usize. + (0, Some(a_len + b_len)) + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for SymmetricDifference<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Intersection<'_, T> { + fn clone(&self) -> Self { + Intersection { + inner: match &self.inner { + IntersectionInner::Stitch { a, b } => { + IntersectionInner::Stitch { a: a.clone(), b: b.clone() } + } + IntersectionInner::Search { small_iter, large_set } => { + IntersectionInner::Search { small_iter: small_iter.clone(), large_set } + } + IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer), + }, + } + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord> Iterator for Intersection<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + match &mut self.inner { + IntersectionInner::Stitch { a, b } => { + let mut a_next = a.next()?; + let mut b_next = b.next()?; + loop { + match a_next.cmp(b_next) { + Less => a_next = a.next()?, + Greater => b_next = b.next()?, + Equal => return Some(a_next), + } + } + } + IntersectionInner::Search { small_iter, large_set } => loop { + let small_next = small_iter.next()?; + if large_set.contains(&small_next) { + return Some(small_next); + } + }, + IntersectionInner::Answer(answer) => answer.take(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match &self.inner { + IntersectionInner::Stitch { a, b } => (0, Some(min(a.len(), b.len()))), + IntersectionInner::Search { small_iter, .. } => (0, Some(small_iter.len())), + IntersectionInner::Answer(None) => (0, Some(0)), + IntersectionInner::Answer(Some(_)) => (1, Some(1)), + } + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Intersection<'_, T> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Union<'_, T> { + fn clone(&self) -> Self { + Union(self.0.clone()) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Ord> Iterator for Union<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { + let (a_next, b_next) = self.0.nexts(Self::Item::cmp); + a_next.or(b_next) + } + + fn size_hint(&self) -> (usize, Option) { + let (a_len, b_len) = self.0.lens(); + // No checked_add - see SymmetricDifference::size_hint. + (max(a_len, b_len), Some(a_len + b_len)) + } + + fn min(mut self) -> Option<&'a T> { + self.next() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Union<'_, T> {} + +#[cfg(test)] +mod tests; +use core::borrow::Borrow; +use core::ops::RangeBounds; +use core::ptr; + +use super::node::{marker, ForceResult::*, Handle, NodeRef}; + +pub struct LeafRange { + pub front: Option, marker::Edge>>, + pub back: Option, marker::Edge>>, +} + +impl LeafRange { + pub fn none() -> Self { + LeafRange { front: None, back: None } + } + + pub fn is_empty(&self) -> bool { + self.front == self.back + } + + /// Temporarily takes out another, immutable equivalent of the same range. + pub fn reborrow(&self) -> LeafRange, K, V> { + LeafRange { + front: self.front.as_ref().map(|f| f.reborrow()), + back: self.back.as_ref().map(|b| b.reborrow()), + } + } +} + +impl NodeRef { + /// Finds the distinct leaf edges delimiting a specified range in a tree. + /// + /// If such distinct edges exist, returns them in ascending order, meaning + /// that a non-zero number of calls to `next_unchecked` on the `front` of + /// the result and/or calls to `next_back_unchecked` on the `back` of the + /// result will eventually reach the same edge. + /// + /// If there are no such edges, i.e., if the tree contains no key within + /// the range, returns a pair of empty options. + /// + /// # Safety + /// Unless `BorrowType` is `Immut`, do not use the handles to visit the same + /// KV twice. + unsafe fn find_leaf_edges_spanning_range( + self, + range: R, + ) -> LeafRange + where + Q: Ord, + K: Borrow, + R: RangeBounds, + { + match self.search_tree_for_bifurcation(&range) { + Err(_) => LeafRange::none(), + Ok(( + node, + lower_edge_idx, + upper_edge_idx, + mut lower_child_bound, + mut upper_child_bound, + )) => { + let mut lower_edge = unsafe { Handle::new_edge(ptr::read(&node), lower_edge_idx) }; + let mut upper_edge = unsafe { Handle::new_edge(node, upper_edge_idx) }; + loop { + match (lower_edge.force(), upper_edge.force()) { + (Leaf(f), Leaf(b)) => return LeafRange { front: Some(f), back: Some(b) }, + (Internal(f), Internal(b)) => { + (lower_edge, lower_child_bound) = + f.descend().find_lower_bound_edge(lower_child_bound); + (upper_edge, upper_child_bound) = + b.descend().find_upper_bound_edge(upper_child_bound); + } + _ => unreachable!("BTreeMap has different depths"), + } + } + } + } + } +} + +/// Equivalent to `(root1.first_leaf_edge(), root2.last_leaf_edge())` but more efficient. +fn full_range( + root1: NodeRef, + root2: NodeRef, +) -> LeafRange { + let mut min_node = root1; + let mut max_node = root2; + loop { + let front = min_node.first_edge(); + let back = max_node.last_edge(); + match (front.force(), back.force()) { + (Leaf(f), Leaf(b)) => { + return LeafRange { front: Some(f), back: Some(b) }; + } + (Internal(min_int), Internal(max_int)) => { + min_node = min_int.descend(); + max_node = max_int.descend(); + } + _ => unreachable!("BTreeMap has different depths"), + }; + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Finds the pair of leaf edges delimiting a specific range in a tree. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + pub fn range_search(self, range: R) -> LeafRange, K, V> + where + Q: ?Sized + Ord, + K: Borrow, + R: RangeBounds, + { + // SAFETY: our borrow type is immutable. + unsafe { self.find_leaf_edges_spanning_range(range) } + } + + /// Finds the pair of leaf edges delimiting an entire tree. + pub fn full_range(self) -> LeafRange, K, V> { + full_range(self, self) + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Splits a unique reference into a pair of leaf edges delimiting a specified range. + /// The result are non-unique references allowing (some) mutation, which must be used + /// carefully. + /// + /// The result is meaningful only if the tree is ordered by key, like the tree + /// in a `BTreeMap` is. + /// + /// # Safety + /// Do not use the duplicate handles to visit the same KV twice. + pub fn range_search(self, range: R) -> LeafRange, K, V> + where + Q: ?Sized + Ord, + K: Borrow, + R: RangeBounds, + { + unsafe { self.find_leaf_edges_spanning_range(range) } + } + + /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree. + /// The results are non-unique references allowing mutation (of values only), so must be used + /// with care. + pub fn full_range(self) -> LeafRange, K, V> { + // We duplicate the root NodeRef here -- we will never visit the same KV + // twice, and never end up with overlapping value references. + let self2 = unsafe { ptr::read(&self) }; + full_range(self, self2) + } +} + +impl NodeRef { + /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree. + /// The results are non-unique references allowing massively destructive mutation, so must be + /// used with the utmost care. + pub fn full_range(self) -> LeafRange { + // We duplicate the root NodeRef here -- we will never access it in a way + // that overlaps references obtained from the root. + let self2 = unsafe { ptr::read(&self) }; + full_range(self, self2) + } +} + +impl + Handle, marker::Edge> +{ + /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the right side, which is either in the same leaf node or in an ancestor node. + /// If the leaf edge is the last one in the tree, returns [`Result::Err`] with the root node. + pub fn next_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.right_kv() { + Ok(kv) => return Ok(kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge.forget_node_type(), + Err(root) => return Err(root), + }, + } + } + } + + /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the left side, which is either in the same leaf node or in an ancestor node. + /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node. + pub fn next_back_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.left_kv() { + Ok(kv) => return Ok(kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge.forget_node_type(), + Err(root) => return Err(root), + }, + } + } + } +} + +impl + Handle, marker::Edge> +{ + /// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the right side, which is either in the same internal node or in an ancestor node. + /// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node. + pub fn next_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self; + loop { + edge = match edge.right_kv() { + Ok(internal_kv) => return Ok(internal_kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge, + Err(root) => return Err(root), + }, + } + } + } +} + +impl Handle, marker::Edge> { + /// Given a leaf edge handle into a dying tree, returns the next leaf edge + /// on the right side, and the key-value pair in between, which is either + /// in the same leaf node, in an ancestor node, or non-existent. + /// + /// This method also deallocates any node(s) it reaches the end of. This + /// implies that if no more key-value pair exists, the entire remainder of + /// the tree will have been deallocated and there is nothing left to return. + /// + /// # Safety + /// The given edge must not have been previously returned by counterpart + /// `deallocating_next_back`. + unsafe fn deallocating_next(self) -> Option<(Self, (K, V))> { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.right_kv() { + Ok(kv) => { + let k = unsafe { ptr::read(kv.reborrow().into_kv().0) }; + let v = unsafe { ptr::read(kv.reborrow().into_kv().1) }; + return Some((kv.next_leaf_edge(), (k, v))); + } + Err(last_edge) => match unsafe { last_edge.into_node().deallocate_and_ascend() } { + Some(parent_edge) => parent_edge.forget_node_type(), + None => return None, + }, + } + } + } + + /// Given a leaf edge handle into a dying tree, returns the next leaf edge + /// on the left side, and the key-value pair in between, which is either + /// in the same leaf node, in an ancestor node, or non-existent. + /// + /// This method also deallocates any node(s) it reaches the end of. This + /// implies that if no more key-value pair exists, the entire remainder of + /// the tree will have been deallocated and there is nothing left to return. + /// + /// # Safety + /// The given edge must not have been previously returned by counterpart + /// `deallocating_next`. + unsafe fn deallocating_next_back(self) -> Option<(Self, (K, V))> { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.left_kv() { + Ok(kv) => { + let k = unsafe { ptr::read(kv.reborrow().into_kv().0) }; + let v = unsafe { ptr::read(kv.reborrow().into_kv().1) }; + return Some((kv.next_back_leaf_edge(), (k, v))); + } + Err(last_edge) => match unsafe { last_edge.into_node().deallocate_and_ascend() } { + Some(parent_edge) => parent_edge.forget_node_type(), + None => return None, + }, + } + } + } + + /// Deallocates a pile of nodes from the leaf up to the root. + /// This is the only way to deallocate the remainder of a tree after + /// `deallocating_next` and `deallocating_next_back` have been nibbling at + /// both sides of the tree, and have hit the same edge. As it is intended + /// only to be called when all keys and values have been returned, + /// no cleanup is done on any of the keys or values. + pub fn deallocating_end(self) { + let mut edge = self.forget_node_type(); + while let Some(parent_edge) = unsafe { edge.into_node().deallocate_and_ascend() } { + edge = parent_edge.forget_node_type(); + } + } +} + +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Moves the leaf edge handle to the next leaf edge and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv(); + let kv = unsafe { kv.ok().unwrap_unchecked() }; + (kv.next_leaf_edge(), kv.into_kv()) + }) + } + + /// Moves the leaf edge handle to the previous leaf edge and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv(); + let kv = unsafe { kv.ok().unwrap_unchecked() }; + (kv.next_back_leaf_edge(), kv.into_kv()) + }) + } +} + +impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Moves the leaf edge handle to the next leaf edge and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + let kv = super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv(); + let kv = unsafe { kv.ok().unwrap_unchecked() }; + (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv) + }); + // Doing this last is faster, according to benchmarks. + kv.into_kv_valmut() + } + + /// Moves the leaf edge handle to the previous leaf and returns references to the + /// key and value in between. + /// + /// # Safety + /// There must be another KV in the direction travelled. + pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + let kv = super::mem::replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv(); + let kv = unsafe { kv.ok().unwrap_unchecked() }; + (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv) + }); + // Doing this last is faster, according to benchmarks. + kv.into_kv_valmut() + } +} + +impl Handle, marker::Edge> { + /// Moves the leaf edge handle to the next leaf edge and returns the key and value + /// in between, deallocating any node left behind while leaving the corresponding + /// edge in its parent node dangling. + /// + /// # Safety + /// - There must be another KV in the direction travelled. + /// - That KV was not previously returned by counterpart `next_back_unchecked` + /// on any copy of the handles being used to traverse the tree. + /// + /// The only safe way to proceed with the updated handle is to compare it, drop it, + /// call this method again subject to its safety conditions, or call counterpart + /// `next_back_unchecked` subject to its safety conditions. + pub unsafe fn deallocating_next_unchecked(&mut self) -> (K, V) { + super::mem::replace(self, |leaf_edge| unsafe { + leaf_edge.deallocating_next().unwrap_unchecked() + }) + } + + /// Moves the leaf edge handle to the previous leaf edge and returns the key and value + /// in between, deallocating any node left behind while leaving the corresponding + /// edge in its parent node dangling. + /// + /// # Safety + /// - There must be another KV in the direction travelled. + /// - That leaf edge was not previously returned by counterpart `next_unchecked` + /// on any copy of the handles being used to traverse the tree. + /// + /// The only safe way to proceed with the updated handle is to compare it, drop it, + /// call this method again subject to its safety conditions, or call counterpart + /// `next_unchecked` subject to its safety conditions. + pub unsafe fn deallocating_next_back_unchecked(&mut self) -> (K, V) { + super::mem::replace(self, |leaf_edge| unsafe { + leaf_edge.deallocating_next_back().unwrap_unchecked() + }) + } +} + +impl NodeRef { + /// Returns the leftmost leaf edge in or underneath a node - in other words, the edge + /// you need first when navigating forward (or last when navigating backward). + #[inline] + pub fn first_leaf_edge(self) -> Handle, marker::Edge> { + let mut node = self; + loop { + match node.force() { + Leaf(leaf) => return leaf.first_edge(), + Internal(internal) => node = internal.first_edge().descend(), + } + } + } + + /// Returns the rightmost leaf edge in or underneath a node - in other words, the edge + /// you need last when navigating forward (or first when navigating backward). + #[inline] + pub fn last_leaf_edge(self) -> Handle, marker::Edge> { + let mut node = self; + loop { + match node.force() { + Leaf(leaf) => return leaf.last_edge(), + Internal(internal) => node = internal.last_edge().descend(), + } + } + } +} + +pub enum Position { + Leaf(NodeRef), + Internal(NodeRef), + InternalKV(Handle, marker::KV>), +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Visits leaf nodes and internal KVs in order of ascending keys, and also + /// visits internal nodes as a whole in a depth first order, meaning that + /// internal nodes precede their individual KVs and their child nodes. + pub fn visit_nodes_in_order(self, mut visit: F) + where + F: FnMut(Position, K, V>), + { + match self.force() { + Leaf(leaf) => visit(Position::Leaf(leaf)), + Internal(internal) => { + visit(Position::Internal(internal)); + let mut edge = internal.first_edge(); + loop { + edge = match edge.descend().force() { + Leaf(leaf) => { + visit(Position::Leaf(leaf)); + match edge.next_kv() { + Ok(kv) => { + visit(Position::InternalKV(kv)); + kv.right_edge() + } + Err(_) => return, + } + } + Internal(internal) => { + visit(Position::Internal(internal)); + internal.first_edge() + } + } + } + } + } + } + + /// Calculates the number of elements in a (sub)tree. + pub fn calc_length(self) -> usize { + let mut result = 0; + self.visit_nodes_in_order(|pos| match pos { + Position::Leaf(node) => result += node.len(), + Position::Internal(node) => result += node.len(), + Position::InternalKV(_) => (), + }); + result + } +} + +impl + Handle, marker::KV> +{ + /// Returns the leaf edge closest to a KV for forward navigation. + pub fn next_leaf_edge(self) -> Handle, marker::Edge> { + match self.force() { + Leaf(leaf_kv) => leaf_kv.right_edge(), + Internal(internal_kv) => { + let next_internal_edge = internal_kv.right_edge(); + next_internal_edge.descend().first_leaf_edge() + } + } + } + + /// Returns the leaf edge closest to a KV for backward navigation. + pub fn next_back_leaf_edge( + self, + ) -> Handle, marker::Edge> { + match self.force() { + Leaf(leaf_kv) => leaf_kv.left_edge(), + Internal(internal_kv) => { + let next_internal_edge = internal_kv.left_edge(); + next_internal_edge.descend().last_leaf_edge() + } + } + } +} +mod append; +mod borrow; +mod fix; +pub mod map; +mod mem; +mod merge_iter; +mod navigate; +mod node; +mod remove; +mod search; +pub mod set; +mod split; + +#[doc(hidden)] +trait Recover { + type Key; + + fn get(&self, key: &Q) -> Option<&Self::Key>; + fn take(&mut self, key: &Q) -> Option; + fn replace(&mut self, key: Self::Key) -> Option; +} + +#[cfg(test)] +mod testing; +use super::super::testing::crash_test::{CrashTestDummy, Panic}; +use super::super::testing::rng::DeterministicRng; +use super::*; +use crate::vec::Vec; +use std::cmp::Ordering; +use std::iter::FromIterator; +use std::panic::{catch_unwind, AssertUnwindSafe}; + +#[test] +fn test_clone_eq() { + let mut m = BTreeSet::new(); + + m.insert(1); + m.insert(2); + + assert_eq!(m.clone(), m); +} + +#[allow(dead_code)] +fn test_const() { + const SET: &'static BTreeSet<()> = &BTreeSet::new(); + const LEN: usize = SET.len(); + const IS_EMPTY: bool = SET.is_empty(); +} + +#[test] +fn test_iter_min_max() { + let mut a = BTreeSet::new(); + assert_eq!(a.iter().min(), None); + assert_eq!(a.iter().max(), None); + assert_eq!(a.range(..).min(), None); + assert_eq!(a.range(..).max(), None); + assert_eq!(a.difference(&BTreeSet::new()).min(), None); + assert_eq!(a.difference(&BTreeSet::new()).max(), None); + assert_eq!(a.intersection(&a).min(), None); + assert_eq!(a.intersection(&a).max(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None); + assert_eq!(a.union(&a).min(), None); + assert_eq!(a.union(&a).max(), None); + a.insert(1); + a.insert(2); + assert_eq!(a.iter().min(), Some(&1)); + assert_eq!(a.iter().max(), Some(&2)); + assert_eq!(a.range(..).min(), Some(&1)); + assert_eq!(a.range(..).max(), Some(&2)); + assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1)); + assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.intersection(&a).min(), Some(&1)); + assert_eq!(a.intersection(&a).max(), Some(&2)); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1)); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.union(&a).min(), Some(&1)); + assert_eq!(a.union(&a).max(), Some(&2)); +} + +fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) +where + F: FnOnce(&BTreeSet, &BTreeSet, &mut dyn FnMut(&i32) -> bool) -> bool, +{ + let mut set_a = BTreeSet::new(); + let mut set_b = BTreeSet::new(); + + for x in a { + assert!(set_a.insert(*x)) + } + for y in b { + assert!(set_b.insert(*y)) + } + + let mut i = 0; + f(&set_a, &set_b, &mut |&x| { + if i < expected.len() { + assert_eq!(x, expected[i]); + } + i += 1; + true + }); + assert_eq!(i, expected.len()); +} + +#[test] +fn test_intersection() { + fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection(&[], &[], &[]); + check_intersection(&[1, 2, 3], &[], &[]); + check_intersection(&[], &[1, 2, 3], &[]); + check_intersection(&[2], &[1, 2, 3], &[2]); + check_intersection(&[1, 2, 3], &[2], &[2]); + check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = (0..100).collect::>(); + check_intersection(&[], &large, &[]); + check_intersection(&large, &[], &[]); + check_intersection(&[-1], &large, &[]); + check_intersection(&large, &[-1], &[]); + check_intersection(&[0], &large, &[0]); + check_intersection(&large, &[0], &[0]); + check_intersection(&[99], &large, &[99]); + check_intersection(&large, &[99], &[99]); + check_intersection(&[100], &large, &[]); + check_intersection(&large, &[100], &[]); + check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]); +} + +#[test] +fn test_intersection_size_hint() { + let x: BTreeSet = [3, 4].iter().copied().collect(); + let y: BTreeSet = [1, 2, 3].iter().copied().collect(); + let mut iter = x.intersection(&y); + assert_eq!(iter.size_hint(), (1, Some(1))); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + iter = y.intersection(&y); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (0, Some(2))); +} + +#[test] +fn test_difference() { + fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference(&[], &[], &[]); + check_difference(&[1, 12], &[], &[1, 12]); + check_difference(&[], &[1, 2, 3, 9], &[]); + check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]); + check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]); + check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]); + check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]); + check_difference( + &[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 34, 38, 39, 50], + &[11, 22, 33, 40, 42], + ); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = (0..100).collect::>(); + check_difference(&[], &large, &[]); + check_difference(&[-1], &large, &[-1]); + check_difference(&[0], &large, &[]); + check_difference(&[99], &large, &[]); + check_difference(&[100], &large, &[100]); + check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]); + check_difference(&large, &[], &large); + check_difference(&large, &[-1], &large); + check_difference(&large, &[100], &large); +} + +#[test] +fn test_difference_size_hint() { + let s246: BTreeSet = [2, 4, 6].iter().copied().collect(); + let s23456: BTreeSet = (2..=6).collect(); + let mut iter = s246.difference(&s23456); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), None); + + let s12345: BTreeSet = (1..=5).collect(); + iter = s246.difference(&s12345); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&6)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + let s34567: BTreeSet = (3..=7).collect(); + iter = s246.difference(&s34567); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (0, Some(2))); + assert_eq!(iter.next(), None); + + let s1: BTreeSet = (-9..=1).collect(); + iter = s246.difference(&s1); + assert_eq!(iter.size_hint(), (3, Some(3))); + + let s2: BTreeSet = (-9..=2).collect(); + iter = s246.difference(&s2); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(&4)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s23: BTreeSet = (2..=3).collect(); + iter = s246.difference(&s23); + assert_eq!(iter.size_hint(), (1, Some(3))); + assert_eq!(iter.next(), Some(&4)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s4: BTreeSet = (4..=4).collect(); + iter = s246.difference(&s4); + assert_eq!(iter.size_hint(), (2, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(2))); + assert_eq!(iter.next(), Some(&6)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + let s56: BTreeSet = (5..=6).collect(); + iter = s246.difference(&s56); + assert_eq!(iter.size_hint(), (1, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (0, Some(2))); + + let s6: BTreeSet = (6..=19).collect(); + iter = s246.difference(&s6); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s7: BTreeSet = (7..=19).collect(); + iter = s246.difference(&s7); + assert_eq!(iter.size_hint(), (3, Some(3))); +} + +#[test] +fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference(&[], &[], &[]); + check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); + check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); + check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]); +} + +#[test] +fn test_symmetric_difference_size_hint() { + let x: BTreeSet = [2, 4].iter().copied().collect(); + let y: BTreeSet = [1, 2, 3].iter().copied().collect(); + let mut iter = x.symmetric_difference(&y); + assert_eq!(iter.size_hint(), (0, Some(5))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (0, Some(4))); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.size_hint(), (0, Some(1))); +} + +#[test] +fn test_union() { + fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union(&[], &[], &[]); + check_union(&[1, 2, 3], &[2], &[1, 2, 3]); + check_union(&[2], &[1, 2, 3], &[1, 2, 3]); + check_union( + &[1, 3, 5, 9, 11, 16, 19, 24], + &[-2, 1, 5, 9, 13, 19], + &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24], + ); +} + +#[test] +fn test_union_size_hint() { + let x: BTreeSet = [2, 4].iter().copied().collect(); + let y: BTreeSet = [1, 2, 3].iter().copied().collect(); + let mut iter = x.union(&y); + assert_eq!(iter.size_hint(), (3, Some(5))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (2, Some(4))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(2))); +} + +#[test] +// Only tests the simple function definition with respect to intersection +fn test_is_disjoint() { + let one = [1].iter().collect::>(); + let two = [2].iter().collect::>(); + assert!(one.is_disjoint(&two)); +} + +#[test] +// Also implicitly tests the trivial function definition of is_superset +fn test_is_subset() { + fn is_subset(a: &[i32], b: &[i32]) -> bool { + let set_a = a.iter().collect::>(); + let set_b = b.iter().collect::>(); + set_a.is_subset(&set_b) + } + + assert_eq!(is_subset(&[], &[]), true); + assert_eq!(is_subset(&[], &[1, 2]), true); + assert_eq!(is_subset(&[0], &[1, 2]), false); + assert_eq!(is_subset(&[1], &[1, 2]), true); + assert_eq!(is_subset(&[2], &[1, 2]), true); + assert_eq!(is_subset(&[3], &[1, 2]), false); + assert_eq!(is_subset(&[1, 2], &[1]), false); + assert_eq!(is_subset(&[1, 2], &[1, 2]), true); + assert_eq!(is_subset(&[1, 2], &[2, 3]), false); + assert_eq!( + is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]), + true + ); + assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = (0..100).collect::>(); + assert_eq!(is_subset(&[], &large), true); + assert_eq!(is_subset(&large, &[]), false); + assert_eq!(is_subset(&[-1], &large), false); + assert_eq!(is_subset(&[0], &large), true); + assert_eq!(is_subset(&[1, 2], &large), true); + assert_eq!(is_subset(&[99, 100], &large), false); +} + +#[test] +fn test_retain() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut set: BTreeSet = xs.iter().cloned().collect(); + set.retain(|&k| k % 2 == 0); + assert_eq!(set.len(), 3); + assert!(set.contains(&2)); + assert!(set.contains(&4)); + assert!(set.contains(&6)); +} + +#[test] +fn test_drain_filter() { + let mut x: BTreeSet<_> = [1].iter().copied().collect(); + let mut y: BTreeSet<_> = [1].iter().copied().collect(); + + x.drain_filter(|_| true); + y.drain_filter(|_| false); + assert_eq!(x.len(), 0); + assert_eq!(y.len(), 1); +} + +#[test] +fn test_drain_filter_drop_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut set = BTreeSet::new(); + set.insert(a.spawn(Panic::Never)); + set.insert(b.spawn(Panic::InDrop)); + set.insert(c.spawn(Panic::Never)); + + catch_unwind(move || drop(set.drain_filter(|dummy| dummy.query(true)))).ok(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_drain_filter_pred_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut set = BTreeSet::new(); + set.insert(a.spawn(Panic::Never)); + set.insert(b.spawn(Panic::InQuery)); + set.insert(c.spawn(Panic::InQuery)); + + catch_unwind(AssertUnwindSafe(|| drop(set.drain_filter(|dummy| dummy.query(true))))).ok(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(set.len(), 2); + assert_eq!(set.first().unwrap().id(), 1); + assert_eq!(set.last().unwrap().id(), 2); +} + +#[test] +fn test_clear() { + let mut x = BTreeSet::new(); + x.insert(1); + + x.clear(); + assert!(x.is_empty()); +} + +#[test] +fn test_zip() { + let mut x = BTreeSet::new(); + x.insert(5); + x.insert(12); + x.insert(11); + + let mut y = BTreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = x.iter().zip(&y); + + assert_eq!(z.next().unwrap(), (&5, &("bar"))); + assert_eq!(z.next().unwrap(), (&11, &("foo"))); + assert!(z.next().is_none()); +} + +#[test] +fn test_from_iter() { + let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set: BTreeSet<_> = xs.iter().cloned().collect(); + + for x in &xs { + assert!(set.contains(x)); + } +} + +#[test] +fn test_show() { + let mut set = BTreeSet::new(); + let empty = BTreeSet::::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{:?}", set); + + assert_eq!(set_str, "{1, 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} + +#[test] +fn test_extend_ref() { + let mut a = BTreeSet::new(); + a.insert(1); + + a.extend(&[2, 3, 4]); + + assert_eq!(a.len(), 4); + assert!(a.contains(&1)); + assert!(a.contains(&2)); + assert!(a.contains(&3)); + assert!(a.contains(&4)); + + let mut b = BTreeSet::new(); + b.insert(5); + b.insert(6); + + a.extend(&b); + + assert_eq!(a.len(), 6); + assert!(a.contains(&1)); + assert!(a.contains(&2)); + assert!(a.contains(&3)); + assert!(a.contains(&4)); + assert!(a.contains(&5)); + assert!(a.contains(&6)); +} + +#[test] +fn test_recovery() { + #[derive(Debug)] + struct Foo(&'static str, i32); + + impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl Eq for Foo {} + + impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } + } + + impl Ord for Foo { + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } + } + + let mut s = BTreeSet::new(); + assert_eq!(s.replace(Foo("a", 1)), None); + assert_eq!(s.len(), 1); + assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); + assert_eq!(s.len(), 1); + + { + let mut it = s.iter(); + assert_eq!(it.next(), Some(&Foo("a", 2))); + assert_eq!(it.next(), None); + } + + assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2))); + assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2))); + assert_eq!(s.len(), 0); + + assert_eq!(s.get(&Foo("a", 1)), None); + assert_eq!(s.take(&Foo("a", 1)), None); + + assert_eq!(s.iter().next(), None); +} + +#[allow(dead_code)] +fn test_variance() { + fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { + v + } + fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { + v + } + fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { + v + } + fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { + v + } + // not applied to Difference, Intersection, SymmetricDifference, Union +} + +#[allow(dead_code)] +fn test_sync() { + fn set(v: &BTreeSet) -> impl Sync + '_ { + v + } + + fn iter(v: &BTreeSet) -> impl Sync + '_ { + v.iter() + } + + fn into_iter(v: BTreeSet) -> impl Sync { + v.into_iter() + } + + fn range(v: &BTreeSet) -> impl Sync + '_ { + v.range(..) + } + + fn drain_filter(v: &mut BTreeSet) -> impl Sync + '_ { + v.drain_filter(|_| false) + } + + fn difference(v: &BTreeSet) -> impl Sync + '_ { + v.difference(&v) + } + + fn intersection(v: &BTreeSet) -> impl Sync + '_ { + v.intersection(&v) + } + + fn symmetric_difference(v: &BTreeSet) -> impl Sync + '_ { + v.symmetric_difference(&v) + } + + fn union(v: &BTreeSet) -> impl Sync + '_ { + v.union(&v) + } +} + +#[allow(dead_code)] +fn test_send() { + fn set(v: BTreeSet) -> impl Send { + v + } + + fn iter(v: &BTreeSet) -> impl Send + '_ { + v.iter() + } + + fn into_iter(v: BTreeSet) -> impl Send { + v.into_iter() + } + + fn range(v: &BTreeSet) -> impl Send + '_ { + v.range(..) + } + + fn drain_filter(v: &mut BTreeSet) -> impl Send + '_ { + v.drain_filter(|_| false) + } + + fn difference(v: &BTreeSet) -> impl Send + '_ { + v.difference(&v) + } + + fn intersection(v: &BTreeSet) -> impl Send + '_ { + v.intersection(&v) + } + + fn symmetric_difference(v: &BTreeSet) -> impl Send + '_ { + v.symmetric_difference(&v) + } + + fn union(v: &BTreeSet) -> impl Send + '_ { + v.union(&v) + } +} + +#[allow(dead_code)] +fn test_ord_absence() { + fn set(mut set: BTreeSet) { + set.is_empty(); + set.len(); + set.clear(); + set.iter(); + set.into_iter(); + } + + fn set_debug(set: BTreeSet) { + format!("{:?}", set); + format!("{:?}", set.iter()); + format!("{:?}", set.into_iter()); + } + + fn set_clone(mut set: BTreeSet) { + set.clone_from(&set.clone()); + } +} + +#[test] +fn test_append() { + let mut a = BTreeSet::new(); + a.insert(1); + a.insert(2); + a.insert(3); + + let mut b = BTreeSet::new(); + b.insert(3); + b.insert(4); + b.insert(5); + + a.append(&mut b); + + assert_eq!(a.len(), 5); + assert_eq!(b.len(), 0); + + assert_eq!(a.contains(&1), true); + assert_eq!(a.contains(&2), true); + assert_eq!(a.contains(&3), true); + assert_eq!(a.contains(&4), true); + assert_eq!(a.contains(&5), true); +} + +#[test] +fn test_first_last() { + let mut a = BTreeSet::new(); + assert_eq!(a.first(), None); + assert_eq!(a.last(), None); + a.insert(1); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&1)); + a.insert(2); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&2)); + for i in 3..=12 { + a.insert(i); + } + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&12)); + assert_eq!(a.pop_first(), Some(1)); + assert_eq!(a.pop_last(), Some(12)); + assert_eq!(a.pop_first(), Some(2)); + assert_eq!(a.pop_last(), Some(11)); + assert_eq!(a.pop_first(), Some(3)); + assert_eq!(a.pop_last(), Some(10)); + assert_eq!(a.pop_first(), Some(4)); + assert_eq!(a.pop_first(), Some(5)); + assert_eq!(a.pop_first(), Some(6)); + assert_eq!(a.pop_first(), Some(7)); + assert_eq!(a.pop_first(), Some(8)); + assert_eq!(a.clone().pop_last(), Some(9)); + assert_eq!(a.pop_first(), Some(9)); + assert_eq!(a.pop_first(), None); + assert_eq!(a.pop_last(), None); +} + +// Unlike the function with the same name in map/tests, returns no values. +// Which also means it returns different predetermined pseudo-random keys, +// and the test cases using this function explore slightly different trees. +fn rand_data(len: usize) -> Vec { + let mut rng = DeterministicRng::new(); + Vec::from_iter((0..len).map(|_| rng.next())) +} + +#[test] +fn test_split_off_empty_right() { + let mut data = rand_data(173); + + let mut set = BTreeSet::from_iter(data.clone()); + let right = set.split_off(&(data.iter().max().unwrap() + 1)); + + data.sort(); + assert!(set.into_iter().eq(data)); + assert!(right.into_iter().eq(None)); +} + +#[test] +fn test_split_off_empty_left() { + let mut data = rand_data(314); + + let mut set = BTreeSet::from_iter(data.clone()); + let right = set.split_off(data.iter().min().unwrap()); + + data.sort(); + assert!(set.into_iter().eq(None)); + assert!(right.into_iter().eq(data)); +} + +#[test] +fn test_split_off_large_random_sorted() { + // Miri is too slow + let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; + // special case with maximum height. + data.sort(); + + let mut set = BTreeSet::from_iter(data.clone()); + let key = data[data.len() / 2]; + let right = set.split_off(&key); + + assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key))); + assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key))); +} +use super::DormantMutRef; + +#[test] +fn test_borrow() { + let mut data = 1; + let mut stack = vec![]; + let mut rr = &mut data; + for factor in [2, 3, 7].iter() { + let (r, dormant_r) = DormantMutRef::new(rr); + rr = r; + assert_eq!(*rr, 1); + stack.push((factor, dormant_r)); + } + while let Some((factor, dormant_r)) = stack.pop() { + let r = unsafe { dormant_r.awaken() }; + *r *= factor; + } + assert_eq!(data, 42); +} +use core::fmt::{self, Debug}; +use core::marker::PhantomData; +use core::mem; + +use super::super::borrow::DormantMutRef; +use super::super::node::{marker, Handle, InsertResult::*, NodeRef}; +use super::BTreeMap; + +use Entry::*; + +/// A view into a single entry in a map, which may either be vacant or occupied. +/// +/// This `enum` is constructed from the [`entry`] method on [`BTreeMap`]. +/// +/// [`entry`]: BTreeMap::entry +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Entry<'a, K: 'a, V: 'a> { + /// A vacant entry. + #[stable(feature = "rust1", since = "1.0.0")] + Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), + + /// An occupied entry. + #[stable(feature = "rust1", since = "1.0.0")] + Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), +} + +#[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for Entry<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), + Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), + } + } +} + +/// A view into a vacant entry in a `BTreeMap`. +/// It is part of the [`Entry`] enum. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct VacantEntry<'a, K: 'a, V: 'a> { + pub(super) key: K, + pub(super) handle: Handle, K, V, marker::Leaf>, marker::Edge>, + pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, + + // Be invariant in `K` and `V` + pub(super) _marker: PhantomData<&'a mut (K, V)>, +} + +#[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for VacantEntry<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("VacantEntry").field(self.key()).finish() + } +} + +/// A view into an occupied entry in a `BTreeMap`. +/// It is part of the [`Entry`] enum. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct OccupiedEntry<'a, K: 'a, V: 'a> { + pub(super) handle: Handle, K, V, marker::LeafOrInternal>, marker::KV>, + pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, + + // Be invariant in `K` and `V` + pub(super) _marker: PhantomData<&'a mut (K, V)>, +} + +#[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for OccupiedEntry<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedEntry").field("key", self.key()).field("value", self.get()).finish() + } +} + +/// The error returned by [`try_insert`](BTreeMap::try_insert) when the key already exists. +/// +/// Contains the occupied entry, and the value that was not inserted. +#[unstable(feature = "map_try_insert", issue = "82766")] +pub struct OccupiedError<'a, K: 'a, V: 'a> { + /// The entry in the map that was already occupied. + pub entry: OccupiedEntry<'a, K, V>, + /// The value which was not inserted, because the entry was already occupied. + pub value: V, +} + +#[unstable(feature = "map_try_insert", issue = "82766")] +impl Debug for OccupiedError<'_, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedError") + .field("key", self.entry.key()) + .field("old_value", self.entry.get()) + .field("new_value", &self.value) + .finish() + } +} + +#[unstable(feature = "map_try_insert", issue = "82766")] +impl<'a, K: Debug + Ord, V: Debug> fmt::Display for OccupiedError<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "failed to insert {:?}, key {:?} already exists with value {:?}", + self.value, + self.entry.key(), + self.entry.get(), + ) + } +} + +impl<'a, K: Ord, V> Entry<'a, K, V> { + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, String> = BTreeMap::new(); + /// let s = "hoho".to_string(); + /// + /// map.entry("poneyland").or_insert_with(|| s); + /// + /// assert_eq!(map["poneyland"], "hoho".to_string()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `.entry(key)` method call. + /// + /// The reference to the moved key is provided so that cloning or copying the key is + /// unnecessary, unlike with `.or_insert_with(|| ... )`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); + /// + /// assert_eq!(map["poneyland"], 9); + /// ``` + #[inline] + #[stable(feature = "or_insert_with_key", since = "1.50.0")] + pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => { + let value = default(entry.key()); + entry.insert(value) + } + } + } + + /// Returns a reference to this entry's key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[stable(feature = "map_entry_keys", since = "1.10.0")] + pub fn key(&self) -> &K { + match *self { + Occupied(ref entry) => entry.key(), + Vacant(ref entry) => entry.key(), + } + } + + /// Provides in-place mutable access to an occupied entry before any + /// potential inserts into the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("poneyland") + /// .and_modify(|e| { *e += 1 }) + /// .or_insert(42); + /// assert_eq!(map["poneyland"], 42); + /// + /// map.entry("poneyland") + /// .and_modify(|e| { *e += 1 }) + /// .or_insert(42); + /// assert_eq!(map["poneyland"], 43); + /// ``` + #[stable(feature = "entry_and_modify", since = "1.26.0")] + pub fn and_modify(self, f: F) -> Self + where + F: FnOnce(&mut V), + { + match self { + Occupied(mut entry) => { + f(entry.get_mut()); + Occupied(entry) + } + Vacant(entry) => Vacant(entry), + } + } +} + +impl<'a, K: Ord, V: Default> Entry<'a, K, V> { + #[stable(feature = "entry_or_default", since = "1.28.0")] + /// Ensures a value is in the entry by inserting the default value if empty, + /// and returns a mutable reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, Option> = BTreeMap::new(); + /// map.entry("poneyland").or_default(); + /// + /// assert_eq!(map["poneyland"], None); + /// ``` + pub fn or_default(self) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(Default::default()), + } + } +} + +impl<'a, K: Ord, V> VacantEntry<'a, K, V> { + /// Gets a reference to the key that would be used when inserting a value + /// through the VacantEntry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[stable(feature = "map_entry_keys", since = "1.10.0")] + pub fn key(&self) -> &K { + &self.key + } + + /// Take ownership of the key. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// if let Entry::Vacant(v) = map.entry("poneyland") { + /// v.into_key(); + /// } + /// ``` + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn into_key(self) -> K { + self.key + } + + /// Sets the value of the entry with the `VacantEntry`'s key, + /// and returns a mutable reference to it. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, u32> = BTreeMap::new(); + /// + /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// o.insert(37); + /// } + /// assert_eq!(map["poneyland"], 37); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(self, value: V) -> &'a mut V { + let out_ptr = match self.handle.insert_recursing(self.key, value) { + (Fit(_), val_ptr) => { + // SAFETY: We have consumed self.handle and the handle returned. + let map = unsafe { self.dormant_map.awaken() }; + map.length += 1; + val_ptr + } + (Split(ins), val_ptr) => { + drop(ins.left); + // SAFETY: We have consumed self.handle and the reference returned. + let map = unsafe { self.dormant_map.awaken() }; + let root = map.root.as_mut().unwrap(); + root.push_internal_level().push(ins.kv.0, ins.kv.1, ins.right); + map.length += 1; + val_ptr + } + }; + // Now that we have finished growing the tree using borrowed references, + // dereference the pointer to a part of it, that we picked up along the way. + unsafe { &mut *out_ptr } + } +} + +impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { + /// Gets a reference to the key in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); + /// ``` + #[stable(feature = "map_entry_keys", since = "1.10.0")] + pub fn key(&self) -> &K { + self.handle.reborrow().into_kv().0 + } + + /// Take ownership of the key and value from the map. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// // We delete the entry from the map. + /// o.remove_entry(); + /// } + /// + /// // If now try to get the value, it will panic: + /// // println!("{}", map["poneyland"]); + /// ``` + #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + pub fn remove_entry(self) -> (K, V) { + self.remove_kv() + } + + /// Gets a reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// assert_eq!(o.get(), &12); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self) -> &V { + self.handle.reborrow().into_kv().1 + } + + /// Gets a mutable reference to the value in the entry. + /// + /// If you need a reference to the `OccupiedEntry` that may outlive the + /// destruction of the `Entry` value, see [`into_mut`]. + /// + /// [`into_mut`]: OccupiedEntry::into_mut + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// if let Entry::Occupied(mut o) = map.entry("poneyland") { + /// *o.get_mut() += 10; + /// assert_eq!(*o.get(), 22); + /// + /// // We can use the same Entry multiple times. + /// *o.get_mut() += 2; + /// } + /// assert_eq!(map["poneyland"], 24); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self) -> &mut V { + self.handle.kv_mut().1 + } + + /// Converts the entry into a mutable reference to its value. + /// + /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`]. + /// + /// [`get_mut`]: OccupiedEntry::get_mut + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// assert_eq!(map["poneyland"], 12); + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// *o.into_mut() += 10; + /// } + /// assert_eq!(map["poneyland"], 22); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_mut(self) -> &'a mut V { + self.handle.into_val_mut() + } + + /// Sets the value of the entry with the `OccupiedEntry`'s key, + /// and returns the entry's old value. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(mut o) = map.entry("poneyland") { + /// assert_eq!(o.insert(15), 12); + /// } + /// assert_eq!(map["poneyland"], 15); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, value: V) -> V { + mem::replace(self.get_mut(), value) + } + + /// Takes the value of the entry out of the map, and returns it. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BTreeMap; + /// use std::collections::btree_map::Entry; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// map.entry("poneyland").or_insert(12); + /// + /// if let Entry::Occupied(o) = map.entry("poneyland") { + /// assert_eq!(o.remove(), 12); + /// } + /// // If we try to get "poneyland"'s value, it'll panic: + /// // println!("{}", map["poneyland"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(self) -> V { + self.remove_kv().1 + } + + // Body of `remove_entry`, probably separate because the name reflects the returned pair. + pub(super) fn remove_kv(self) -> (K, V) { + let mut emptied_internal_root = false; + let (old_kv, _) = self.handle.remove_kv_tracking(|| emptied_internal_root = true); + // SAFETY: we consumed the intermediate root borrow, `self.handle`. + let map = unsafe { self.dormant_map.awaken() }; + map.length -= 1; + if emptied_internal_root { + let root = map.root.as_mut().unwrap(); + root.pop_internal_level(); + } + old_kv + } +} +use super::super::testing::crash_test::{CrashTestDummy, Panic}; +use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor}; +use super::super::testing::rng::DeterministicRng; +use super::Entry::{Occupied, Vacant}; +use super::*; +use crate::boxed::Box; +use crate::fmt::Debug; +use crate::rc::Rc; +use crate::string::{String, ToString}; +use crate::vec::Vec; +use std::cmp::Ordering; +use std::convert::TryFrom; +use std::iter::{self, FromIterator}; +use std::mem; +use std::ops::Bound::{self, Excluded, Included, Unbounded}; +use std::ops::RangeBounds; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + +// Capacity of a tree with a single level, +// i.e., a tree who's root is a leaf node at height 0. +const NODE_CAPACITY: usize = node::CAPACITY; + +// Minimum number of elements to insert, to guarantee a tree with 2 levels, +// i.e., a tree who's root is an internal node at height 1, with edges to leaf nodes. +// It's not the minimum size: removing an element from such a tree does not always reduce height. +const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1; + +// Minimum number of elements to insert in ascending order, to guarantee a tree with 3 levels, +// i.e., a tree who's root is an internal node at height 2, with edges to more internal nodes. +// It's not the minimum size: removing an element from such a tree does not always reduce height. +const MIN_INSERTS_HEIGHT_2: usize = 89; + +// Gathers all references from a mutable iterator and makes sure Miri notices if +// using them is dangerous. +fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator) { + // Gather all those references. + let mut refs: Vec<&mut T> = iter.collect(); + // Use them all. Twice, to be sure we got all interleavings. + for r in refs.iter_mut() { + mem::swap(dummy, r); + } + for r in refs { + mem::swap(dummy, r); + } +} + +impl BTreeMap { + // Panics if the map (or the code navigating it) is corrupted. + fn check_invariants(&self) { + if let Some(root) = &self.root { + let root_node = root.reborrow(); + + // Check the back pointers top-down, before we attempt to rely on + // more serious navigation code. + assert!(root_node.ascend().is_err()); + root_node.assert_back_pointers(); + + // Check consistency of `length` with what navigation code encounters. + assert_eq!(self.length, root_node.calc_length()); + + // Lastly, check the invariant causing the least harm. + root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 }); + } else { + assert_eq!(self.length, 0); + } + + // Check that `assert_strictly_ascending` will encounter all keys. + assert_eq!(self.length, self.keys().count()); + } + + // Panics if the map is corrupted or if the keys are not in strictly + // ascending order, in the current opinion of the `Ord` implementation. + // If the `Ord` implementation violates transitivity, this method does not + // guarantee that all keys are unique, just that adjacent keys are unique. + fn check(&self) + where + K: Debug + Ord, + { + self.check_invariants(); + self.assert_strictly_ascending(); + } + + // Returns the height of the root, if any. + fn height(&self) -> Option { + self.root.as_ref().map(node::Root::height) + } + + fn dump_keys(&self) -> String + where + K: Debug, + { + if let Some(root) = self.root.as_ref() { + root.reborrow().dump_keys() + } else { + String::from("not yet allocated") + } + } + + // Panics if the keys are not in strictly ascending order. + fn assert_strictly_ascending(&self) + where + K: Debug + Ord, + { + let mut keys = self.keys(); + if let Some(mut previous) = keys.next() { + for next in keys { + assert!(previous < next, "{:?} >= {:?}", previous, next); + previous = next; + } + } + } + + // Transform the tree to minimize wasted space, obtaining fewer nodes that + // are mostly filled up to their capacity. The same compact tree could have + // been obtained by inserting keys in a shrewd order. + fn compact(&mut self) + where + K: Ord, + { + let iter = mem::take(self).into_iter(); + let root = BTreeMap::ensure_is_owned(&mut self.root); + root.bulk_push(iter, &mut self.length); + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + fn assert_min_len(self, min_len: usize) { + assert!(self.len() >= min_len, "node len {} < {}", self.len(), min_len); + if let node::ForceResult::Internal(node) = self.force() { + for idx in 0..=node.len() { + let edge = unsafe { Handle::new_edge(node, idx) }; + edge.descend().assert_min_len(MIN_LEN); + } + } + } +} + +// Tests our value of MIN_INSERTS_HEIGHT_2. Failure may mean you just need to +// adapt that value to match a change in node::CAPACITY or the choices made +// during insertion, otherwise other test cases may fail or be less useful. +#[test] +fn test_levels() { + let mut map = BTreeMap::new(); + map.check(); + assert_eq!(map.height(), None); + assert_eq!(map.len(), 0); + + map.insert(0, ()); + while map.height() == Some(0) { + let last_key = *map.last_key_value().unwrap().0; + map.insert(last_key + 1, ()); + } + map.check(); + // Structure: + // - 1 element in internal root node with 2 children + // - 6 elements in left leaf child + // - 5 elements in right leaf child + assert_eq!(map.height(), Some(1)); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1, "{}", map.dump_keys()); + + while map.height() == Some(1) { + let last_key = *map.last_key_value().unwrap().0; + map.insert(last_key + 1, ()); + } + map.check(); + // Structure: + // - 1 element in internal root node with 2 children + // - 6 elements in left internal child with 7 grandchildren + // - 42 elements in left child's 7 grandchildren with 6 elements each + // - 5 elements in right internal child with 6 grandchildren + // - 30 elements in right child's 5 first grandchildren with 6 elements each + // - 5 elements in right child's last grandchild + assert_eq!(map.height(), Some(2)); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2, "{}", map.dump_keys()); +} + +// Ensures the testing infrastructure usually notices order violations. +#[test] +#[should_panic] +fn test_check_ord_chaos() { + let gov = Governor::new(); + let map: BTreeMap<_, _> = (0..2).map(|i| (Governed(i, &gov), ())).collect(); + gov.flip(); + map.check(); +} + +// Ensures the testing infrastructure doesn't always mind order violations. +#[test] +fn test_check_invariants_ord_chaos() { + let gov = Governor::new(); + let map: BTreeMap<_, _> = (0..2).map(|i| (Governed(i, &gov), ())).collect(); + gov.flip(); + map.check_invariants(); +} + +#[test] +fn test_basic_large() { + let mut map = BTreeMap::new(); + // Miri is too slow + let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 }; + let size = size + (size % 2); // round up to even number + assert_eq!(map.len(), 0); + + for i in 0..size { + assert_eq!(map.insert(i, 10 * i), None); + assert_eq!(map.len(), i + 1); + } + + assert_eq!(map.first_key_value(), Some((&0, &0))); + assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1))))); + assert_eq!(map.first_entry().unwrap().key(), &0); + assert_eq!(map.last_entry().unwrap().key(), &(size - 1)); + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i * 10)); + } + + for i in size..size * 2 { + assert_eq!(map.get(&i), None); + } + + for i in 0..size { + assert_eq!(map.insert(i, 100 * i), Some(10 * i)); + assert_eq!(map.len(), size); + } + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i * 100)); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(i * 2)), Some(i * 200)); + assert_eq!(map.len(), size - i - 1); + } + + for i in 0..size / 2 { + assert_eq!(map.get(&(2 * i)), None); + assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100)); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(2 * i)), None); + assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); + assert_eq!(map.len(), size / 2 - i - 1); + } + map.check(); +} + +#[test] +fn test_basic_small() { + let mut map = BTreeMap::new(); + // Empty, root is absent (None): + assert_eq!(map.remove(&1), None); + assert_eq!(map.len(), 0); + assert_eq!(map.get(&1), None); + assert_eq!(map.get_mut(&1), None); + assert_eq!(map.first_key_value(), None); + assert_eq!(map.last_key_value(), None); + assert_eq!(map.keys().count(), 0); + assert_eq!(map.values().count(), 0); + assert_eq!(map.range(..).next(), None); + assert_eq!(map.range(..1).next(), None); + assert_eq!(map.range(1..).next(), None); + assert_eq!(map.range(1..=1).next(), None); + assert_eq!(map.range(1..2).next(), None); + assert_eq!(map.height(), None); + assert_eq!(map.insert(1, 1), None); + assert_eq!(map.height(), Some(0)); + map.check(); + + // 1 key-value pair: + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), Some(&1)); + assert_eq!(map.get_mut(&1), Some(&mut 1)); + assert_eq!(map.first_key_value(), Some((&1, &1))); + assert_eq!(map.last_key_value(), Some((&1, &1))); + assert_eq!(map.keys().collect::>(), vec![&1]); + assert_eq!(map.values().collect::>(), vec![&1]); + assert_eq!(map.insert(1, 2), Some(1)); + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), Some(&2)); + assert_eq!(map.get_mut(&1), Some(&mut 2)); + assert_eq!(map.first_key_value(), Some((&1, &2))); + assert_eq!(map.last_key_value(), Some((&1, &2))); + assert_eq!(map.keys().collect::>(), vec![&1]); + assert_eq!(map.values().collect::>(), vec![&2]); + assert_eq!(map.insert(2, 4), None); + assert_eq!(map.height(), Some(0)); + map.check(); + + // 2 key-value pairs: + assert_eq!(map.len(), 2); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.get_mut(&2), Some(&mut 4)); + assert_eq!(map.first_key_value(), Some((&1, &2))); + assert_eq!(map.last_key_value(), Some((&2, &4))); + assert_eq!(map.keys().collect::>(), vec![&1, &2]); + assert_eq!(map.values().collect::>(), vec![&2, &4]); + assert_eq!(map.remove(&1), Some(2)); + assert_eq!(map.height(), Some(0)); + map.check(); + + // 1 key-value pair: + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), None); + assert_eq!(map.get_mut(&1), None); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.get_mut(&2), Some(&mut 4)); + assert_eq!(map.first_key_value(), Some((&2, &4))); + assert_eq!(map.last_key_value(), Some((&2, &4))); + assert_eq!(map.keys().collect::>(), vec![&2]); + assert_eq!(map.values().collect::>(), vec![&4]); + assert_eq!(map.remove(&2), Some(4)); + assert_eq!(map.height(), Some(0)); + map.check(); + + // Empty but root is owned (Some(...)): + assert_eq!(map.len(), 0); + assert_eq!(map.get(&1), None); + assert_eq!(map.get_mut(&1), None); + assert_eq!(map.first_key_value(), None); + assert_eq!(map.last_key_value(), None); + assert_eq!(map.keys().count(), 0); + assert_eq!(map.values().count(), 0); + assert_eq!(map.range(..).next(), None); + assert_eq!(map.range(..1).next(), None); + assert_eq!(map.range(1..).next(), None); + assert_eq!(map.range(1..=1).next(), None); + assert_eq!(map.range(1..2).next(), None); + assert_eq!(map.remove(&1), None); + assert_eq!(map.height(), Some(0)); + map.check(); +} + +#[test] +fn test_iter() { + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; + + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) + where + T: Iterator, + { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_iter_rev() { + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; + + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) + where + T: Iterator, + { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().rev().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter().rev()); +} + +// Specifically tests iter_mut's ability to mutate the value of pairs in-line. +fn do_test_iter_mut_mutation(size: usize) +where + T: Copy + Debug + Ord + TryFrom, + >::Error: Debug, +{ + let zero = T::try_from(0).unwrap(); + let mut map: BTreeMap = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect(); + + // Forward and backward iteration sees enough pairs (also tested elsewhere) + assert_eq!(map.iter_mut().count(), size); + assert_eq!(map.iter_mut().rev().count(), size); + + // Iterate forwards, trying to mutate to unique values + for (i, (k, v)) in map.iter_mut().enumerate() { + assert_eq!(*k, T::try_from(i).unwrap()); + assert_eq!(*v, zero); + *v = T::try_from(i + 1).unwrap(); + } + + // Iterate backwards, checking that mutations succeeded and trying to mutate again + for (i, (k, v)) in map.iter_mut().rev().enumerate() { + assert_eq!(*k, T::try_from(size - i - 1).unwrap()); + assert_eq!(*v, T::try_from(size - i).unwrap()); + *v = T::try_from(2 * size - i).unwrap(); + } + + // Check that backward mutations succeeded + for (i, (k, v)) in map.iter_mut().enumerate() { + assert_eq!(*k, T::try_from(i).unwrap()); + assert_eq!(*v, T::try_from(size + i + 1).unwrap()); + } + map.check(); +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(align(32))] +struct Align32(usize); + +impl TryFrom for Align32 { + type Error = (); + + fn try_from(s: usize) -> Result { + Ok(Align32(s)) + } +} + +#[test] +fn test_iter_mut_mutation() { + // Check many alignments and trees with roots at various heights. + do_test_iter_mut_mutation::(0); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); + do_test_iter_mut_mutation::(1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_1); + do_test_iter_mut_mutation::(MIN_INSERTS_HEIGHT_2); +} + +#[test] +fn test_values_mut() { + let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect(); + test_all_refs(&mut 13, a.values_mut()); + a.check(); +} + +#[test] +fn test_values_mut_mutation() { + let mut a = BTreeMap::new(); + a.insert(1, String::from("hello")); + a.insert(2, String::from("goodbye")); + + for value in a.values_mut() { + value.push_str("!"); + } + + let values: Vec = a.values().cloned().collect(); + assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]); + a.check(); +} + +#[test] +fn test_iter_entering_root_twice() { + let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect(); + let mut it = map.iter_mut(); + let front = it.next().unwrap(); + let back = it.next_back().unwrap(); + assert_eq!(front, (&0, &mut 0)); + assert_eq!(back, (&1, &mut 1)); + *front.1 = 24; + *back.1 = 42; + assert_eq!(front, (&0, &mut 24)); + assert_eq!(back, (&1, &mut 42)); + assert_eq!(it.next(), None); + assert_eq!(it.next_back(), None); + map.check(); +} + +#[test] +fn test_iter_descending_to_same_node_twice() { + let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect(); + let mut it = map.iter_mut(); + // Descend into first child. + let front = it.next().unwrap(); + // Descend into first child again, after running through second child. + while it.next_back().is_some() {} + // Check immutable access. + assert_eq!(front, (&0, &mut 0)); + // Perform mutable access. + *front.1 = 42; + map.check(); +} + +#[test] +fn test_iter_mixed() { + // Miri is too slow + let size = if cfg!(miri) { 200 } else { 10000 }; + + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) + where + T: Iterator + DoubleEndedIterator, + { + for i in 0..size / 4 { + assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); + assert_eq!(iter.next().unwrap(), (i, i)); + assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); + } + for i in size / 4..size * 3 / 4 { + assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_iter_min_max() { + let mut a = BTreeMap::new(); + assert_eq!(a.iter().min(), None); + assert_eq!(a.iter().max(), None); + assert_eq!(a.iter_mut().min(), None); + assert_eq!(a.iter_mut().max(), None); + assert_eq!(a.range(..).min(), None); + assert_eq!(a.range(..).max(), None); + assert_eq!(a.range_mut(..).min(), None); + assert_eq!(a.range_mut(..).max(), None); + assert_eq!(a.keys().min(), None); + assert_eq!(a.keys().max(), None); + assert_eq!(a.values().min(), None); + assert_eq!(a.values().max(), None); + assert_eq!(a.values_mut().min(), None); + assert_eq!(a.values_mut().max(), None); + a.insert(1, 42); + a.insert(2, 24); + assert_eq!(a.iter().min(), Some((&1, &42))); + assert_eq!(a.iter().max(), Some((&2, &24))); + assert_eq!(a.iter_mut().min(), Some((&1, &mut 42))); + assert_eq!(a.iter_mut().max(), Some((&2, &mut 24))); + assert_eq!(a.range(..).min(), Some((&1, &42))); + assert_eq!(a.range(..).max(), Some((&2, &24))); + assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42))); + assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24))); + assert_eq!(a.keys().min(), Some(&1)); + assert_eq!(a.keys().max(), Some(&2)); + assert_eq!(a.values().min(), Some(&24)); + assert_eq!(a.values().max(), Some(&42)); + assert_eq!(a.values_mut().min(), Some(&mut 24)); + assert_eq!(a.values_mut().max(), Some(&mut 42)); + a.check(); +} + +fn range_keys(map: &BTreeMap, range: impl RangeBounds) -> Vec { + map.range(range) + .map(|(&k, &v)| { + assert_eq!(k, v); + k + }) + .collect() +} + +#[test] +fn test_range_small() { + let size = 4; + + let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect(); + let all: Vec<_> = (1..=size).collect(); + let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); + assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size))), all); + assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size))), all); + assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); + assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); + assert_eq!(range_keys(&map, ..), all); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(1), Included(1))), first); + assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); + assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); + assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); + assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size))), last); + assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); + assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); + + assert_eq!(range_keys(&map, ..3), vec![1, 2]); + assert_eq!(range_keys(&map, 3..), vec![3, 4]); + assert_eq!(range_keys(&map, 2..=3), vec![2, 3]); +} + +#[test] +fn test_range_height_1() { + // Tests tree with a root and 2 leaves. The single key in the root node is + // close to the middle among the keys. + + let map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i)).collect(); + let middle = MIN_INSERTS_HEIGHT_1 as i32 / 2; + for root in middle - 2..=middle + 2 { + assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]); + assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]); + assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]); + + assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]); + assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]); + assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]); + assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]); + } +} + +#[test] +fn test_range_large() { + let size = 200; + + let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect(); + let all: Vec<_> = (1..=size).collect(); + let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); + assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size))), all); + assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size))), all); + assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); + assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); + assert_eq!(range_keys(&map, ..), all); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(1), Included(1))), first); + assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); + assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); + assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); + assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size))), last); + assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); + assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); + + fn check<'a, L, R>(lhs: L, rhs: R) + where + L: IntoIterator, + R: IntoIterator, + { + let lhs: Vec<_> = lhs.into_iter().collect(); + let rhs: Vec<_> = rhs.into_iter().collect(); + assert_eq!(lhs, rhs); + } + + check(map.range(..=100), map.range(..101)); + check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); + check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]); +} + +#[test] +fn test_range_inclusive_max_value() { + let max = usize::MAX; + let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect(); + + assert_eq!(map.range(max..=max).collect::>(), &[(&max, &0)]); +} + +#[test] +fn test_range_equal_empty_cases() { + let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); + assert_eq!(map.range((Included(2), Excluded(2))).next(), None); + assert_eq!(map.range((Excluded(2), Included(2))).next(), None); +} + +#[test] +#[should_panic] +fn test_range_equal_excluded() { + let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); + map.range((Excluded(2), Excluded(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_1() { + let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); + map.range((Included(3), Included(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_2() { + let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); + map.range((Included(3), Excluded(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_3() { + let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); + map.range((Excluded(3), Included(2))); +} + +#[test] +#[should_panic] +fn test_range_backwards_4() { + let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); + map.range((Excluded(3), Excluded(2))); +} + +#[test] +fn test_range_finding_ill_order_in_map() { + let mut map = BTreeMap::new(); + map.insert(Cyclic3::B, ()); + // Lacking static_assert, call `range` conditionally, to emphasise that + // we cause a different panic than `test_range_backwards_1` does. + // A more refined `should_panic` would be welcome. + if Cyclic3::C < Cyclic3::A { + map.range(Cyclic3::C..=Cyclic3::A); + } +} + +#[test] +fn test_range_finding_ill_order_in_range_ord() { + // Has proper order the first time asked, then flips around. + struct EvilTwin(i32); + + impl PartialOrd for EvilTwin { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } + } + + static COMPARES: AtomicUsize = AtomicUsize::new(0); + impl Ord for EvilTwin { + fn cmp(&self, other: &Self) -> Ordering { + let ord = self.0.cmp(&other.0); + if COMPARES.fetch_add(1, SeqCst) > 0 { ord.reverse() } else { ord } + } + } + + impl PartialEq for EvilTwin { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } + } + + impl Eq for EvilTwin {} + + #[derive(PartialEq, Eq, PartialOrd, Ord)] + struct CompositeKey(i32, EvilTwin); + + impl Borrow for CompositeKey { + fn borrow(&self) -> &EvilTwin { + &self.1 + } + } + + let map = (0..12).map(|i| (CompositeKey(i, EvilTwin(i)), ())).collect::>(); + map.range(EvilTwin(5)..=EvilTwin(7)); +} + +#[test] +fn test_range_1000() { + // Miri is too slow + let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 }; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { + let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v)); + let mut pairs = (0..size).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + test(&map, size, Included(&0), Excluded(&size)); + test(&map, size, Unbounded, Excluded(&size)); + test(&map, size, Included(&0), Included(&(size - 1))); + test(&map, size, Unbounded, Included(&(size - 1))); + test(&map, size, Included(&0), Unbounded); + test(&map, size, Unbounded, Unbounded); +} + +#[test] +fn test_range_borrowed_key() { + let mut map = BTreeMap::new(); + map.insert("aardvark".to_string(), 1); + map.insert("baboon".to_string(), 2); + map.insert("coyote".to_string(), 3); + map.insert("dingo".to_string(), 4); + // NOTE: would like to use simply "b".."d" here... + let mut iter = map.range::((Included("b"), Excluded("d"))); + assert_eq!(iter.next(), Some((&"baboon".to_string(), &2))); + assert_eq!(iter.next(), Some((&"coyote".to_string(), &3))); + assert_eq!(iter.next(), None); +} + +#[test] +fn test_range() { + let size = 200; + // Miri is too slow + let step = if cfg!(miri) { 66 } else { 1 }; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + for i in (0..size).step_by(step) { + for j in (i..size).step_by(step) { + let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); + let mut pairs = (i..=j).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } +} + +#[test] +fn test_range_mut() { + let size = 200; + // Miri is too slow + let step = if cfg!(miri) { 66 } else { 1 }; + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + for i in (0..size).step_by(step) { + for j in (i..size).step_by(step) { + let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); + let mut pairs = (i..=j).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } + map.check(); +} + +#[test] +fn test_retain() { + let mut map: BTreeMap = (0..100).map(|x| (x, x * 10)).collect(); + + map.retain(|&k, _| k % 2 == 0); + assert_eq!(map.len(), 50); + assert_eq!(map[&2], 20); + assert_eq!(map[&4], 40); + assert_eq!(map[&6], 60); +} + +mod test_drain_filter { + use super::*; + + #[test] + fn empty() { + let mut map: BTreeMap = BTreeMap::new(); + map.drain_filter(|_, _| unreachable!("there's nothing to decide on")); + assert!(map.is_empty()); + map.check(); + } + + // Explicitly consumes the iterator, where most test cases drop it instantly. + #[test] + fn consumed_keeping_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + assert!(map.drain_filter(|_, _| false).eq(iter::empty())); + map.check(); + } + + // Explicitly consumes the iterator, where most test cases drop it instantly. + #[test] + fn consumed_removing_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + assert!(map.drain_filter(|_, _| true).eq(pairs)); + assert!(map.is_empty()); + map.check(); + } + + // Explicitly consumes the iterator and modifies values through it. + #[test] + fn mutating_and_keeping() { + let pairs = (0..3).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + assert!( + map.drain_filter(|_, v| { + *v += 6; + false + }) + .eq(iter::empty()) + ); + assert!(map.keys().copied().eq(0..3)); + assert!(map.values().copied().eq(6..9)); + map.check(); + } + + // Explicitly consumes the iterator and modifies values through it. + #[test] + fn mutating_and_removing() { + let pairs = (0..3).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + assert!( + map.drain_filter(|_, v| { + *v += 6; + true + }) + .eq((0..3).map(|i| (i, i + 6))) + ); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn underfull_keeping_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + map.drain_filter(|_, _| false); + assert!(map.keys().copied().eq(0..3)); + map.check(); + } + + #[test] + fn underfull_removing_one() { + let pairs = (0..3).map(|i| (i, i)); + for doomed in 0..3 { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i == doomed); + assert_eq!(map.len(), 2); + map.check(); + } + } + + #[test] + fn underfull_keeping_one() { + let pairs = (0..3).map(|i| (i, i)); + for sacred in 0..3 { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i != sacred); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn underfull_removing_all() { + let pairs = (0..3).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + map.drain_filter(|_, _| true); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn height_0_keeping_all() { + let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + map.drain_filter(|_, _| false); + assert!(map.keys().copied().eq(0..NODE_CAPACITY)); + map.check(); + } + + #[test] + fn height_0_removing_one() { + let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); + for doomed in 0..NODE_CAPACITY { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i == doomed); + assert_eq!(map.len(), NODE_CAPACITY - 1); + map.check(); + } + } + + #[test] + fn height_0_keeping_one() { + let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); + for sacred in 0..NODE_CAPACITY { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i != sacred); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn height_0_removing_all() { + let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + map.drain_filter(|_, _| true); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn height_0_keeping_half() { + let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect(); + assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8); + assert_eq!(map.len(), 8); + map.check(); + } + + #[test] + fn height_1_removing_all() { + let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + map.drain_filter(|_, _| true); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn height_1_removing_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); + for doomed in 0..MIN_INSERTS_HEIGHT_1 { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i == doomed); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1); + map.check(); + } + } + + #[test] + fn height_1_keeping_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); + for sacred in 0..MIN_INSERTS_HEIGHT_1 { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i != sacred); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn height_2_removing_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i == doomed); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); + map.check(); + } + } + + #[test] + fn height_2_keeping_one() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { + let mut map: BTreeMap<_, _> = pairs.clone().collect(); + map.drain_filter(|i, _| *i != sacred); + assert!(map.keys().copied().eq(sacred..=sacred)); + map.check(); + } + } + + #[test] + fn height_2_removing_all() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + let mut map: BTreeMap<_, _> = pairs.collect(); + map.drain_filter(|_, _| true); + assert!(map.is_empty()); + map.check(); + } + + #[test] + fn drop_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InDrop), ()); + map.insert(c.spawn(Panic::Never), ()); + + catch_unwind(move || drop(map.drain_filter(|dummy, _| dummy.query(true)))).unwrap_err(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); + } + + #[test] + fn pred_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InQuery), ()); + map.insert(c.spawn(Panic::InQuery), ()); + + catch_unwind(AssertUnwindSafe(|| drop(map.drain_filter(|dummy, _| dummy.query(true))))) + .unwrap_err(); + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(map.len(), 2); + assert_eq!(map.first_entry().unwrap().key().id(), 1); + assert_eq!(map.last_entry().unwrap().key().id(), 2); + map.check(); + } + + // Same as above, but attempt to use the iterator again after the panic in the predicate + #[test] + fn pred_panic_reuse() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InQuery), ()); + map.insert(c.spawn(Panic::InQuery), ()); + + { + let mut it = map.drain_filter(|dummy, _| dummy.query(true)); + catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); + // Iterator behaviour after a panic is explicitly unspecified, + // so this is just the current implementation: + let result = catch_unwind(AssertUnwindSafe(|| it.next())); + assert!(matches!(result, Ok(None))); + } + + assert_eq!(a.queried(), 1); + assert_eq!(b.queried(), 1); + assert_eq!(c.queried(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(map.len(), 2); + assert_eq!(map.first_entry().unwrap().key().id(), 1); + assert_eq!(map.last_entry().unwrap().key().id(), 2); + map.check(); + } +} + +#[test] +fn test_borrow() { + // make sure these compile -- using the Borrow trait + { + let mut map = BTreeMap::new(); + map.insert("0".to_string(), 1); + assert_eq!(map["0"], 1); + } + + { + let mut map = BTreeMap::new(); + map.insert(Box::new(0), 1); + assert_eq!(map[&0], 1); + } + + { + let mut map = BTreeMap::new(); + map.insert(Box::new([0, 1]) as Box<[i32]>, 1); + assert_eq!(map[&[0, 1][..]], 1); + } + + { + let mut map = BTreeMap::new(); + map.insert(Rc::new(0), 1); + assert_eq!(map[&0], 1); + } + + #[allow(dead_code)] + fn get(v: &BTreeMap, ()>, t: &T) { + v.get(t); + } + + #[allow(dead_code)] + fn get_mut(v: &mut BTreeMap, ()>, t: &T) { + v.get_mut(t); + } + + #[allow(dead_code)] + fn get_key_value(v: &BTreeMap, ()>, t: &T) { + v.get_key_value(t); + } + + #[allow(dead_code)] + fn contains_key(v: &BTreeMap, ()>, t: &T) { + v.contains_key(t); + } + + #[allow(dead_code)] + fn range(v: &BTreeMap, ()>, t: T) { + v.range(t..); + } + + #[allow(dead_code)] + fn range_mut(v: &mut BTreeMap, ()>, t: T) { + v.range_mut(t..); + } + + #[allow(dead_code)] + fn remove(v: &mut BTreeMap, ()>, t: &T) { + v.remove(t); + } + + #[allow(dead_code)] + fn remove_entry(v: &mut BTreeMap, ()>, t: &T) { + v.remove_entry(t); + } + + #[allow(dead_code)] + fn split_off(v: &mut BTreeMap, ()>, t: &T) { + v.split_off(t); + } +} + +#[test] +fn test_entry() { + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + *v *= 10; + } + } + assert_eq!(map.get(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + map.check(); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get(&3), None); + assert_eq!(map.len(), 5); + map.check(); + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); + map.check(); +} + +#[test] +fn test_extend_ref() { + let mut a = BTreeMap::new(); + a.insert(1, "one"); + let mut b = BTreeMap::new(); + b.insert(2, "two"); + b.insert(3, "three"); + + a.extend(&b); + + assert_eq!(a.len(), 3); + assert_eq!(a[&1], "one"); + assert_eq!(a[&2], "two"); + assert_eq!(a[&3], "three"); + a.check(); +} + +#[test] +fn test_zst() { + let mut m = BTreeMap::new(); + assert_eq!(m.len(), 0); + + assert_eq!(m.insert((), ()), None); + assert_eq!(m.len(), 1); + + assert_eq!(m.insert((), ()), Some(())); + assert_eq!(m.len(), 1); + assert_eq!(m.iter().count(), 1); + + m.clear(); + assert_eq!(m.len(), 0); + + for _ in 0..100 { + m.insert((), ()); + } + + assert_eq!(m.len(), 1); + assert_eq!(m.iter().count(), 1); + m.check(); +} + +// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings +// do not cause segfaults when used with zero-sized values. All other map behavior is +// undefined. +#[test] +fn test_bad_zst() { + #[derive(Clone, Copy, Debug)] + struct Bad; + + impl PartialEq for Bad { + fn eq(&self, _: &Self) -> bool { + false + } + } + + impl Eq for Bad {} + + impl PartialOrd for Bad { + fn partial_cmp(&self, _: &Self) -> Option { + Some(Ordering::Less) + } + } + + impl Ord for Bad { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Less + } + } + + let mut m = BTreeMap::new(); + + for _ in 0..100 { + m.insert(Bad, Bad); + } + m.check(); +} + +#[test] +fn test_clear() { + let mut map = BTreeMap::new(); + for &len in &[MIN_INSERTS_HEIGHT_1, MIN_INSERTS_HEIGHT_2, 0, NODE_CAPACITY] { + for i in 0..len { + map.insert(i, ()); + } + assert_eq!(map.len(), len); + map.clear(); + map.check(); + assert!(map.is_empty()); + } +} + +#[test] +fn test_clear_drop_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InDrop), ()); + map.insert(c.spawn(Panic::Never), ()); + + catch_unwind(AssertUnwindSafe(|| map.clear())).unwrap_err(); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); + assert_eq!(map.len(), 0); + + drop(map); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_clone() { + let mut map = BTreeMap::new(); + let size = MIN_INSERTS_HEIGHT_1; + assert_eq!(map.len(), 0); + + for i in 0..size { + assert_eq!(map.insert(i, 10 * i), None); + assert_eq!(map.len(), i + 1); + map.check(); + assert_eq!(map, map.clone()); + } + + for i in 0..size { + assert_eq!(map.insert(i, 100 * i), Some(10 * i)); + assert_eq!(map.len(), size); + map.check(); + assert_eq!(map, map.clone()); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(i * 2)), Some(i * 200)); + assert_eq!(map.len(), size - i - 1); + map.check(); + assert_eq!(map, map.clone()); + } + + for i in 0..size / 2 { + assert_eq!(map.remove(&(2 * i)), None); + assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); + assert_eq!(map.len(), size / 2 - i - 1); + map.check(); + assert_eq!(map, map.clone()); + } + + // Test a tree with 2 semi-full levels and a tree with 3 levels. + map = (1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect(); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); + assert_eq!(map, map.clone()); + map.insert(0, 0); + assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2); + assert_eq!(map, map.clone()); + map.check(); +} + +#[test] +fn test_clone_panic_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + + let mut map = BTreeMap::new(); + map.insert(a.spawn(Panic::Never), ()); + map.insert(b.spawn(Panic::InClone), ()); + map.insert(c.spawn(Panic::Never), ()); + + catch_unwind(|| map.clone()).unwrap_err(); + assert_eq!(a.cloned(), 1); + assert_eq!(b.cloned(), 1); + assert_eq!(c.cloned(), 0); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 0); + assert_eq!(map.len(), 3); + + drop(map); + assert_eq!(a.cloned(), 1); + assert_eq!(b.cloned(), 1); + assert_eq!(c.cloned(), 0); + assert_eq!(a.dropped(), 2); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_clone_from() { + let mut map1 = BTreeMap::new(); + let max_size = MIN_INSERTS_HEIGHT_1; + + // Range to max_size inclusive, because i is the size of map1 being tested. + for i in 0..=max_size { + let mut map2 = BTreeMap::new(); + for j in 0..i { + let mut map1_copy = map2.clone(); + map1_copy.clone_from(&map1); // small cloned from large + assert_eq!(map1_copy, map1); + let mut map2_copy = map1.clone(); + map2_copy.clone_from(&map2); // large cloned from small + assert_eq!(map2_copy, map2); + map2.insert(100 * j + 1, 2 * j + 1); + } + map2.clone_from(&map1); // same length + map2.check(); + assert_eq!(map2, map1); + map1.insert(i, 10 * i); + map1.check(); + } +} + +#[allow(dead_code)] +fn test_variance() { + fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { + v + } + fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> { + v + } + + fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> { + v + } + fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> { + v + } + + fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> { + v + } + fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> { + v + } + + fn into_keys_key<'new>(v: IntoKeys<&'static str, ()>) -> IntoKeys<&'new str, ()> { + v + } + fn into_keys_val<'new>(v: IntoKeys<(), &'static str>) -> IntoKeys<(), &'new str> { + v + } + + fn into_values_key<'new>(v: IntoValues<&'static str, ()>) -> IntoValues<&'new str, ()> { + v + } + fn into_values_val<'new>(v: IntoValues<(), &'static str>) -> IntoValues<(), &'new str> { + v + } + + fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> { + v + } + fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> { + v + } + + fn keys_key<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { + v + } + fn keys_val<'a, 'new>(v: Keys<'a, (), &'static str>) -> Keys<'a, (), &'new str> { + v + } + + fn values_key<'a, 'new>(v: Values<'a, &'static str, ()>) -> Values<'a, &'new str, ()> { + v + } + fn values_val<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { + v + } +} + +#[allow(dead_code)] +fn test_sync() { + fn map(v: &BTreeMap) -> impl Sync + '_ { + v + } + + fn into_iter(v: BTreeMap) -> impl Sync { + v.into_iter() + } + + fn into_keys(v: BTreeMap) -> impl Sync { + v.into_keys() + } + + fn into_values(v: BTreeMap) -> impl Sync { + v.into_values() + } + + fn drain_filter(v: &mut BTreeMap) -> impl Sync + '_ { + v.drain_filter(|_, _| false) + } + + fn iter(v: &BTreeMap) -> impl Sync + '_ { + v.iter() + } + + fn iter_mut(v: &mut BTreeMap) -> impl Sync + '_ { + v.iter_mut() + } + + fn keys(v: &BTreeMap) -> impl Sync + '_ { + v.keys() + } + + fn values(v: &BTreeMap) -> impl Sync + '_ { + v.values() + } + + fn values_mut(v: &mut BTreeMap) -> impl Sync + '_ { + v.values_mut() + } + + fn range(v: &BTreeMap) -> impl Sync + '_ { + v.range(..) + } + + fn range_mut(v: &mut BTreeMap) -> impl Sync + '_ { + v.range_mut(..) + } + + fn entry(v: &mut BTreeMap) -> impl Sync + '_ { + v.entry(Default::default()) + } + + fn occupied_entry(v: &mut BTreeMap) -> impl Sync + '_ { + match v.entry(Default::default()) { + Occupied(entry) => entry, + _ => unreachable!(), + } + } + + fn vacant_entry(v: &mut BTreeMap) -> impl Sync + '_ { + match v.entry(Default::default()) { + Vacant(entry) => entry, + _ => unreachable!(), + } + } +} + +#[allow(dead_code)] +fn test_send() { + fn map(v: BTreeMap) -> impl Send { + v + } + + fn into_iter(v: BTreeMap) -> impl Send { + v.into_iter() + } + + fn into_keys(v: BTreeMap) -> impl Send { + v.into_keys() + } + + fn into_values(v: BTreeMap) -> impl Send { + v.into_values() + } + + fn drain_filter(v: &mut BTreeMap) -> impl Send + '_ { + v.drain_filter(|_, _| false) + } + + fn iter(v: &BTreeMap) -> impl Send + '_ { + v.iter() + } + + fn iter_mut(v: &mut BTreeMap) -> impl Send + '_ { + v.iter_mut() + } + + fn keys(v: &BTreeMap) -> impl Send + '_ { + v.keys() + } + + fn values(v: &BTreeMap) -> impl Send + '_ { + v.values() + } + + fn values_mut(v: &mut BTreeMap) -> impl Send + '_ { + v.values_mut() + } + + fn range(v: &BTreeMap) -> impl Send + '_ { + v.range(..) + } + + fn range_mut(v: &mut BTreeMap) -> impl Send + '_ { + v.range_mut(..) + } + + fn entry(v: &mut BTreeMap) -> impl Send + '_ { + v.entry(Default::default()) + } + + fn occupied_entry(v: &mut BTreeMap) -> impl Send + '_ { + match v.entry(Default::default()) { + Occupied(entry) => entry, + _ => unreachable!(), + } + } + + fn vacant_entry(v: &mut BTreeMap) -> impl Send + '_ { + match v.entry(Default::default()) { + Vacant(entry) => entry, + _ => unreachable!(), + } + } +} + +#[allow(dead_code)] +fn test_ord_absence() { + fn map(mut map: BTreeMap) { + map.is_empty(); + map.len(); + map.clear(); + map.iter(); + map.iter_mut(); + map.keys(); + map.values(); + map.values_mut(); + if true { + map.into_values(); + } else if true { + map.into_iter(); + } else { + map.into_keys(); + } + } + + fn map_debug(mut map: BTreeMap) { + format!("{:?}", map); + format!("{:?}", map.iter()); + format!("{:?}", map.iter_mut()); + format!("{:?}", map.keys()); + format!("{:?}", map.values()); + format!("{:?}", map.values_mut()); + if true { + format!("{:?}", map.into_iter()); + } else if true { + format!("{:?}", map.into_keys()); + } else { + format!("{:?}", map.into_values()); + } + } + + fn map_clone(mut map: BTreeMap) { + map.clone_from(&map.clone()); + } +} + +#[allow(dead_code)] +fn test_const() { + const MAP: &'static BTreeMap<(), ()> = &BTreeMap::new(); + const LEN: usize = MAP.len(); + const IS_EMPTY: bool = MAP.is_empty(); +} + +#[test] +fn test_occupied_entry_key() { + let mut a = BTreeMap::new(); + let key = "hello there"; + let value = "value goes here"; + assert!(a.is_empty()); + a.insert(key, value); + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + + match a.entry(key) { + Vacant(_) => panic!(), + Occupied(e) => assert_eq!(key, *e.key()), + } + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + a.check(); +} + +#[test] +fn test_vacant_entry_key() { + let mut a = BTreeMap::new(); + let key = "hello there"; + let value = "value goes here"; + + assert!(a.is_empty()); + match a.entry(key) { + Occupied(_) => panic!(), + Vacant(e) => { + assert_eq!(key, *e.key()); + e.insert(value); + } + } + assert_eq!(a.len(), 1); + assert_eq!(a[key], value); + a.check(); +} + +#[test] +fn test_first_last_entry() { + let mut a = BTreeMap::new(); + assert!(a.first_entry().is_none()); + assert!(a.last_entry().is_none()); + a.insert(1, 42); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &1); + a.insert(2, 24); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &2); + a.insert(0, 6); + assert_eq!(a.first_entry().unwrap().key(), &0); + assert_eq!(a.last_entry().unwrap().key(), &2); + let (k1, v1) = a.first_entry().unwrap().remove_entry(); + assert_eq!(k1, 0); + assert_eq!(v1, 6); + let (k2, v2) = a.last_entry().unwrap().remove_entry(); + assert_eq!(k2, 2); + assert_eq!(v2, 24); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &1); + a.check(); +} + +#[test] +fn test_insert_into_full_height_0() { + let size = NODE_CAPACITY; + for pos in 0..=size { + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i * 2 + 1, ())).collect(); + assert!(map.insert(pos * 2, ()).is_none()); + map.check(); + } +} + +#[test] +fn test_insert_into_full_height_1() { + let size = NODE_CAPACITY + 1 + NODE_CAPACITY; + for pos in 0..=size { + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i * 2 + 1, ())).collect(); + map.compact(); + let root_node = map.root.as_ref().unwrap().reborrow(); + assert_eq!(root_node.len(), 1); + assert_eq!(root_node.first_leaf_edge().into_node().len(), NODE_CAPACITY); + assert_eq!(root_node.last_leaf_edge().into_node().len(), NODE_CAPACITY); + + assert!(map.insert(pos * 2, ()).is_none()); + map.check(); + } +} + +macro_rules! create_append_test { + ($name:ident, $len:expr) => { + #[test] + fn $name() { + let mut a = BTreeMap::new(); + for i in 0..8 { + a.insert(i, i); + } + + let mut b = BTreeMap::new(); + for i in 5..$len { + b.insert(i, 2 * i); + } + + a.append(&mut b); + + assert_eq!(a.len(), $len); + assert_eq!(b.len(), 0); + + for i in 0..$len { + if i < 5 { + assert_eq!(a[&i], i); + } else { + assert_eq!(a[&i], 2 * i); + } + } + + a.check(); + assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1))); + assert_eq!(a.insert($len - 1, 20), None); + a.check(); + } + }; +} + +// These are mostly for testing the algorithm that "fixes" the right edge after insertion. +// Single node. +create_append_test!(test_append_9, 9); +// Two leafs that don't need fixing. +create_append_test!(test_append_17, 17); +// Two leafs where the second one ends up underfull and needs stealing at the end. +create_append_test!(test_append_14, 14); +// Two leafs where the second one ends up empty because the insertion finished at the root. +create_append_test!(test_append_12, 12); +// Three levels; insertion finished at the root. +create_append_test!(test_append_144, 144); +// Three levels; insertion finished at leaf while there is an empty node on the second level. +create_append_test!(test_append_145, 145); +// Tests for several randomly chosen sizes. +create_append_test!(test_append_170, 170); +create_append_test!(test_append_181, 181); +#[cfg(not(miri))] // Miri is too slow +create_append_test!(test_append_239, 239); +#[cfg(not(miri))] // Miri is too slow +create_append_test!(test_append_1700, 1700); + +#[test] +fn test_append_drop_leak() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut left = BTreeMap::new(); + let mut right = BTreeMap::new(); + left.insert(a.spawn(Panic::Never), ()); + left.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during append + left.insert(c.spawn(Panic::Never), ()); + right.insert(b.spawn(Panic::Never), ()); + right.insert(c.spawn(Panic::Never), ()); + + catch_unwind(move || left.append(&mut right)).unwrap_err(); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); // should be 2 were it not for Rust issue #47949 + assert_eq!(c.dropped(), 2); +} + +#[test] +fn test_append_ord_chaos() { + let mut map1 = BTreeMap::new(); + map1.insert(Cyclic3::A, ()); + map1.insert(Cyclic3::B, ()); + let mut map2 = BTreeMap::new(); + map2.insert(Cyclic3::A, ()); + map2.insert(Cyclic3::B, ()); + map2.insert(Cyclic3::C, ()); // lands first, before A + map2.insert(Cyclic3::B, ()); // lands first, before C + map1.check(); + map2.check(); // keys are not unique but still strictly ascending + assert_eq!(map1.len(), 2); + assert_eq!(map2.len(), 4); + map1.append(&mut map2); + assert_eq!(map1.len(), 5); + assert_eq!(map2.len(), 0); + map1.check(); + map2.check(); +} + +fn rand_data(len: usize) -> Vec<(u32, u32)> { + let mut rng = DeterministicRng::new(); + Vec::from_iter((0..len).map(|_| (rng.next(), rng.next()))) +} + +#[test] +fn test_split_off_empty_right() { + let mut data = rand_data(173); + + let mut map = BTreeMap::from_iter(data.clone()); + let right = map.split_off(&(data.iter().max().unwrap().0 + 1)); + map.check(); + right.check(); + + data.sort(); + assert!(map.into_iter().eq(data)); + assert!(right.into_iter().eq(None)); +} + +#[test] +fn test_split_off_empty_left() { + let mut data = rand_data(314); + + let mut map = BTreeMap::from_iter(data.clone()); + let right = map.split_off(&data.iter().min().unwrap().0); + map.check(); + right.check(); + + data.sort(); + assert!(map.into_iter().eq(None)); + assert!(right.into_iter().eq(data)); +} + +// In a tree with 3 levels, if all but a part of the first leaf node is split off, +// make sure fix_top eliminates both top levels. +#[test] +fn test_split_off_tiny_left_height_2() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + let mut left: BTreeMap<_, _> = pairs.clone().collect(); + let right = left.split_off(&1); + left.check(); + right.check(); + assert_eq!(left.len(), 1); + assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1); + assert_eq!(*left.first_key_value().unwrap().0, 0); + assert_eq!(*right.first_key_value().unwrap().0, 1); +} + +// In a tree with 3 levels, if only part of the last leaf node is split off, +// make sure fix_top eliminates both top levels. +#[test] +fn test_split_off_tiny_right_height_2() { + let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); + let last = MIN_INSERTS_HEIGHT_2 - 1; + let mut left: BTreeMap<_, _> = pairs.clone().collect(); + assert_eq!(*left.last_key_value().unwrap().0, last); + let right = left.split_off(&last); + left.check(); + right.check(); + assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1); + assert_eq!(right.len(), 1); + assert_eq!(*left.last_key_value().unwrap().0, last - 1); + assert_eq!(*right.last_key_value().unwrap().0, last); +} + +#[test] +fn test_split_off_halfway() { + let mut rng = DeterministicRng::new(); + for &len in &[NODE_CAPACITY, 25, 50, 75, 100] { + let mut data = Vec::from_iter((0..len).map(|_| (rng.next(), ()))); + // Insertion in non-ascending order creates some variation in node length. + let mut map = BTreeMap::from_iter(data.iter().copied()); + data.sort(); + let small_keys = data.iter().take(len / 2).map(|kv| kv.0); + let large_keys = data.iter().skip(len / 2).map(|kv| kv.0); + let split_key = large_keys.clone().next().unwrap(); + let right = map.split_off(&split_key); + map.check(); + right.check(); + assert!(map.keys().copied().eq(small_keys)); + assert!(right.keys().copied().eq(large_keys)); + } +} + +#[test] +fn test_split_off_large_random_sorted() { + // Miri is too slow + let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; + // special case with maximum height. + data.sort(); + + let mut map = BTreeMap::from_iter(data.clone()); + let key = data[data.len() / 2].0; + let right = map.split_off(&key); + map.check(); + right.check(); + + assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key))); + assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key))); +} + +#[test] +fn test_into_iter_drop_leak_height_0() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let d = CrashTestDummy::new(3); + let e = CrashTestDummy::new(4); + let mut map = BTreeMap::new(); + map.insert("a", a.spawn(Panic::Never)); + map.insert("b", b.spawn(Panic::Never)); + map.insert("c", c.spawn(Panic::Never)); + map.insert("d", d.spawn(Panic::InDrop)); + map.insert("e", e.spawn(Panic::Never)); + + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); + assert_eq!(d.dropped(), 1); + assert_eq!(e.dropped(), 1); +} + +#[test] +fn test_into_iter_drop_leak_height_1() { + let size = MIN_INSERTS_HEIGHT_1; + for panic_point in vec![0, 1, size - 2, size - 1] { + let dummies: Vec<_> = (0..size).map(|i| CrashTestDummy::new(i)).collect(); + let map: BTreeMap<_, _> = (0..size) + .map(|i| { + let panic = if i == panic_point { Panic::InDrop } else { Panic::Never }; + (dummies[i].spawn(Panic::Never), dummies[i].spawn(panic)) + }) + .collect(); + catch_unwind(move || drop(map.into_iter())).unwrap_err(); + for i in 0..size { + assert_eq!(dummies[i].dropped(), 2); + } + } +} + +#[test] +fn test_into_keys() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map: BTreeMap<_, _> = vec.into_iter().collect(); + let keys: Vec<_> = map.into_keys().collect(); + + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); +} + +#[test] +fn test_into_values() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map: BTreeMap<_, _> = vec.into_iter().collect(); + let values: Vec<_> = map.into_values().collect(); + + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); +} + +#[test] +fn test_insert_remove_intertwined() { + let loops = if cfg!(miri) { 100 } else { 1_000_000 }; + let mut map = BTreeMap::new(); + let mut i = 1; + let offset = 165; // somewhat arbitrarily chosen to cover some code paths + for _ in 0..loops { + i = (i + offset) & 0xFF; + map.insert(i, i); + map.remove(&(0xFF - i)); + } + map.check(); +} + +#[test] +fn test_insert_remove_intertwined_ord_chaos() { + let loops = if cfg!(miri) { 100 } else { 1_000_000 }; + let gov = Governor::new(); + let mut map = BTreeMap::new(); + let mut i = 1; + let offset = 165; // more arbitrarily copied from above + for _ in 0..loops { + i = (i + offset) & 0xFF; + map.insert(Governed(i, &gov), ()); + map.remove(&Governed(0xFF - i, &gov)); + gov.flip(); + } + map.check_invariants(); +} +use super::map::MIN_LEN; +use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef}; + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { + /// Removes a key-value pair from the tree, and returns that pair, as well as + /// the leaf edge corresponding to that former pair. It's possible this empties + /// a root node that is internal, which the caller should pop from the map + /// holding the tree. The caller should also decrement the map's length. + pub fn remove_kv_tracking( + self, + handle_emptied_internal_root: F, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + match self.force() { + Leaf(node) => node.remove_leaf_kv(handle_emptied_internal_root), + Internal(node) => node.remove_internal_kv(handle_emptied_internal_root), + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::KV> { + fn remove_leaf_kv( + self, + handle_emptied_internal_root: F, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + let (old_kv, mut pos) = self.remove(); + let len = pos.reborrow().into_node().len(); + if len < MIN_LEN { + let idx = pos.idx(); + // We have to temporarily forget the child type, because there is no + // distinct node type for the immediate parents of a leaf. + let new_pos = match pos.into_node().forget_type().choose_parent_kv() { + Ok(Left(left_parent_kv)) => { + debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1); + if left_parent_kv.can_merge() { + left_parent_kv.merge_tracking_child_edge(Right(idx)) + } else { + debug_assert!(left_parent_kv.left_child_len() > MIN_LEN); + left_parent_kv.steal_left(idx) + } + } + Ok(Right(right_parent_kv)) => { + debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1); + if right_parent_kv.can_merge() { + right_parent_kv.merge_tracking_child_edge(Left(idx)) + } else { + debug_assert!(right_parent_kv.right_child_len() > MIN_LEN); + right_parent_kv.steal_right(idx) + } + } + Err(pos) => unsafe { Handle::new_edge(pos, idx) }, + }; + // SAFETY: `new_pos` is the leaf we started from or a sibling. + pos = unsafe { new_pos.cast_to_leaf_unchecked() }; + + // Only if we merged, the parent (if any) has shrunk, but skipping + // the following step otherwise does not pay off in benchmarks. + // + // SAFETY: We won't destroy or rearrange the leaf where `pos` is at + // by handling its parent recursively; at worst we will destroy or + // rearrange the parent through the grandparent, thus change the + // link to the parent inside the leaf. + if let Ok(parent) = unsafe { pos.reborrow_mut() }.into_node().ascend() { + if !parent.into_node().forget_type().fix_node_and_affected_ancestors() { + handle_emptied_internal_root(); + } + } + } + (old_kv, pos) + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::KV> { + fn remove_internal_kv( + self, + handle_emptied_internal_root: F, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + // Remove an adjacent KV from its leaf and then put it back in place of + // the element we were asked to remove. Prefer the left adjacent KV, + // for the reasons listed in `choose_parent_kv`. + let left_leaf_kv = self.left_edge().descend().last_leaf_edge().left_kv(); + let left_leaf_kv = unsafe { left_leaf_kv.ok().unwrap_unchecked() }; + let (left_kv, left_hole) = left_leaf_kv.remove_leaf_kv(handle_emptied_internal_root); + + // The internal node may have been stolen from or merged. Go back right + // to find where the original KV ended up. + let mut internal = unsafe { left_hole.next_kv().ok().unwrap_unchecked() }; + let old_kv = internal.replace_kv(left_kv.0, left_kv.1); + let pos = internal.next_leaf_edge(); + (old_kv, pos) + } +} +use core::cmp::Ordering; +use core::fmt::{self, Debug}; +use core::iter::FusedIterator; + +/// Core of an iterator that merges the output of two strictly ascending iterators, +/// for instance a union or a symmetric difference. +pub struct MergeIterInner { + a: I, + b: I, + peeked: Option>, +} + +/// Benchmarks faster than wrapping both iterators in a Peekable, +/// probably because we can afford to impose a FusedIterator bound. +#[derive(Clone, Debug)] +enum Peeked { + A(I::Item), + B(I::Item), +} + +impl Clone for MergeIterInner +where + I: Clone, + I::Item: Clone, +{ + fn clone(&self) -> Self { + Self { a: self.a.clone(), b: self.b.clone(), peeked: self.peeked.clone() } + } +} + +impl Debug for MergeIterInner +where + I: Debug, + I::Item: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("MergeIterInner").field(&self.a).field(&self.b).field(&self.peeked).finish() + } +} + +impl MergeIterInner { + /// Creates a new core for an iterator merging a pair of sources. + pub fn new(a: I, b: I) -> Self { + MergeIterInner { a, b, peeked: None } + } + + /// Returns the next pair of items stemming from the pair of sources + /// being merged. If both returned options contain a value, that value + /// is equal and occurs in both sources. If one of the returned options + /// contains a value, that value doesn't occur in the other source (or + /// the sources are not strictly ascending). If neither returned option + /// contains a value, iteration has finished and subsequent calls will + /// return the same empty pair. + pub fn nexts Ordering>( + &mut self, + cmp: Cmp, + ) -> (Option, Option) + where + I: FusedIterator, + { + let mut a_next; + let mut b_next; + match self.peeked.take() { + Some(Peeked::A(next)) => { + a_next = Some(next); + b_next = self.b.next(); + } + Some(Peeked::B(next)) => { + b_next = Some(next); + a_next = self.a.next(); + } + None => { + a_next = self.a.next(); + b_next = self.b.next(); + } + } + if let (Some(ref a1), Some(ref b1)) = (&a_next, &b_next) { + match cmp(a1, b1) { + Ordering::Less => self.peeked = b_next.take().map(Peeked::B), + Ordering::Greater => self.peeked = a_next.take().map(Peeked::A), + Ordering::Equal => (), + } + } + (a_next, b_next) + } + + /// Returns a pair of upper bounds for the `size_hint` of the final iterator. + pub fn lens(&self) -> (usize, usize) + where + I: ExactSizeIterator, + { + match self.peeked { + Some(Peeked::A(_)) => (1 + self.a.len(), self.b.len()), + Some(Peeked::B(_)) => (self.a.len(), 1 + self.b.len()), + _ => (self.a.len(), self.b.len()), + } + } +} +// This is an attempt at an implementation following the ideal +// +// ``` +// struct BTreeMap { +// height: usize, +// root: Option>> +// } +// +// struct Node { +// keys: [K; 2 * B - 1], +// vals: [V; 2 * B - 1], +// edges: [if height > 0 { Box> } else { () }; 2 * B], +// parent: Option<(NonNull>, u16)>, +// len: u16, +// } +// ``` +// +// Since Rust doesn't actually have dependent types and polymorphic recursion, +// we make do with lots of unsafety. + +// A major goal of this module is to avoid complexity by treating the tree as a generic (if +// weirdly shaped) container and avoiding dealing with most of the B-Tree invariants. As such, +// this module doesn't care whether the entries are sorted, which nodes can be underfull, or +// even what underfull means. However, we do rely on a few invariants: +// +// - Trees must have uniform depth/height. This means that every path down to a leaf from a +// given node has exactly the same length. +// - A node of length `n` has `n` keys, `n` values, and `n + 1` edges. +// This implies that even an empty node has at least one edge. +// For a leaf node, "having an edge" only means we can identify a position in the node, +// since leaf edges are empty and need no data representation. In an internal node, +// an edge both identifies a position and contains a pointer to a child node. + +use core::marker::PhantomData; +use core::mem::{self, MaybeUninit}; +use core::ptr::{self, NonNull}; +use core::slice::SliceIndex; + +use crate::alloc::{Allocator, Global, Layout}; +use crate::boxed::Box; + +const B: usize = 6; +pub const CAPACITY: usize = 2 * B - 1; +pub const MIN_LEN_AFTER_SPLIT: usize = B - 1; +const KV_IDX_CENTER: usize = B - 1; +const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1; +const EDGE_IDX_RIGHT_OF_CENTER: usize = B; + +/// The underlying representation of leaf nodes and part of the representation of internal nodes. +struct LeafNode { + /// We want to be covariant in `K` and `V`. + parent: Option>>, + + /// This node's index into the parent node's `edges` array. + /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`. + /// This is only guaranteed to be initialized when `parent` is non-null. + parent_idx: MaybeUninit, + + /// The number of keys and values this node stores. + len: u16, + + /// The arrays storing the actual data of the node. Only the first `len` elements of each + /// array are initialized and valid. + keys: [MaybeUninit; CAPACITY], + vals: [MaybeUninit; CAPACITY], +} + +impl LeafNode { + /// Initializes a new `LeafNode` in-place. + unsafe fn init(this: *mut Self) { + // As a general policy, we leave fields uninitialized if they can be, as this should + // be both slightly faster and easier to track in Valgrind. + unsafe { + // parent_idx, keys, and vals are all MaybeUninit + ptr::addr_of_mut!((*this).parent).write(None); + ptr::addr_of_mut!((*this).len).write(0); + } + } + + /// Creates a new boxed `LeafNode`. + fn new() -> Box { + unsafe { + let mut leaf = Box::new_uninit(); + LeafNode::init(leaf.as_mut_ptr()); + leaf.assume_init() + } + } +} + +/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden +/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an +/// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the +/// node, allowing code to act on leaf and internal nodes generically without having to even check +/// which of the two a pointer is pointing at. This property is enabled by the use of `repr(C)`. +#[repr(C)] +// gdb_providers.py uses this type name for introspection. +struct InternalNode { + data: LeafNode, + + /// The pointers to the children of this node. `len + 1` of these are considered + /// initialized and valid, except that near the end, while the tree is held + /// through borrow type `Dying`, some of these pointers are dangling. + edges: [MaybeUninit>; 2 * B], +} + +impl InternalNode { + /// Creates a new boxed `InternalNode`. + /// + /// # Safety + /// An invariant of internal nodes is that they have at least one + /// initialized and valid edge. This function does not set up + /// such an edge. + unsafe fn new() -> Box { + unsafe { + let mut node = Box::::new_uninit(); + // We only need to initialize the data; the edges are MaybeUninit. + LeafNode::init(ptr::addr_of_mut!((*node.as_mut_ptr()).data)); + node.assume_init() + } + } +} + +/// A managed, non-null pointer to a node. This is either an owned pointer to +/// `LeafNode` or an owned pointer to `InternalNode`. +/// +/// However, `BoxedNode` contains no information as to which of the two types +/// of nodes it actually contains, and, partially due to this lack of information, +/// is not a separate type and has no destructor. +type BoxedNode = NonNull>; + +// N.B. `NodeRef` is always covariant in `K` and `V`, even when the `BorrowType` +// is `Mut`. This is technically wrong, but cannot result in any unsafety due to +// internal use of `NodeRef` because we stay completely generic over `K` and `V`. +// However, whenever a public type wraps `NodeRef`, make sure that it has the +// correct variance. +/// +/// A reference to a node. +/// +/// This type has a number of parameters that controls how it acts: +/// - `BorrowType`: A dummy type that describes the kind of borrow and carries a lifetime. +/// - When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`. +/// - When this is `ValMut<'a>`, the `NodeRef` acts roughly like `&'a Node` +/// with respect to keys and tree structure, but also allows many +/// mutable references to values throughout the tree to coexist. +/// - When this is `Mut<'a>`, the `NodeRef` acts roughly like `&'a mut Node`, +/// although insert methods allow a mutable pointer to a value to coexist. +/// - When this is `Owned`, the `NodeRef` acts roughly like `Box`, +/// but does not have a destructor, and must be cleaned up manually. +/// - When this is `Dying`, the `NodeRef` still acts roughly like `Box`, +/// but has methods to destroy the tree bit by bit, and ordinary methods, +/// while not marked as unsafe to call, can invoke UB if called incorrectly. +/// Since any `NodeRef` allows navigating through the tree, `BorrowType` +/// effectively applies to the entire tree, not just to the node itself. +/// - `K` and `V`: These are the types of keys and values stored in the nodes. +/// - `Type`: This can be `Leaf`, `Internal`, or `LeafOrInternal`. When this is +/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the +/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the +/// `NodeRef` could be pointing to either type of node. +/// `Type` is named `NodeType` when used outside `NodeRef`. +/// +/// Both `BorrowType` and `NodeType` restrict what methods we implement, to +/// exploit static type safety. There are limitations in the way we can apply +/// such restrictions: +/// - For each type parameter, we can only define a method either generically +/// or for one particular type. For example, we cannot define a method like +/// `into_kv` generically for all `BorrowType`, or once for all types that +/// carry a lifetime, because we want it to return `&'a` references. +/// Therefore, we define it only for the least powerful type `Immut<'a>`. +/// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`. +/// Therefore, we have to explicitly call `reborrow` on a more powerfull +/// `NodeRef` in order to reach a method like `into_kv`. +/// +/// All methods on `NodeRef` that return some kind of reference, either: +/// - Take `self` by value, and return the lifetime carried by `BorrowType`. +/// Sometimes, to invoke such a method, we need to call `reborrow_mut`. +/// - Take `self` by reference, and (implicitly) return that reference's +/// lifetime, instead of the lifetime carried by `BorrowType`. That way, +/// the borrow checker guarantees that the `NodeRef` remains borrowed as long +/// as the returned reference is used. +/// The methods supporting insert bend this rule by returning a raw pointer, +/// i.e., a reference without any lifetime. +pub struct NodeRef { + /// The number of levels that the node and the level of leaves are apart, a + /// constant of the node that cannot be entirely described by `Type`, and that + /// the node itself does not store. We only need to store the height of the root + /// node, and derive every other node's height from it. + /// Must be zero if `Type` is `Leaf` and non-zero if `Type` is `Internal`. + height: usize, + /// The pointer to the leaf or internal node. The definition of `InternalNode` + /// ensures that the pointer is valid either way. + node: NonNull>, + _marker: PhantomData<(BorrowType, Type)>, +} + +/// The root node of an owned tree. +/// +/// Note that this does not have a destructor, and must be cleaned up manually. +pub type Root = NodeRef; + +impl<'a, K: 'a, V: 'a, Type> Copy for NodeRef, K, V, Type> {} +impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef, K, V, Type> { + fn clone(&self) -> Self { + *self + } +} + +unsafe impl Sync for NodeRef {} + +unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef, K, V, Type> {} +unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef, K, V, Type> {} +unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef, K, V, Type> {} +unsafe impl Send for NodeRef {} +unsafe impl Send for NodeRef {} + +impl NodeRef { + fn new_leaf() -> Self { + Self::from_new_leaf(LeafNode::new()) + } + + fn from_new_leaf(leaf: Box>) -> Self { + NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } + } +} + +impl NodeRef { + fn new_internal(child: Root) -> Self { + let mut new_node = unsafe { InternalNode::new() }; + new_node.edges[0].write(child.node); + unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } + } + + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal(internal: Box>, height: usize) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { height, node, _marker: PhantomData }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } +} + +impl NodeRef { + /// Unpack a node reference that was packed as `NodeRef::parent`. + fn from_internal(node: NonNull>, height: usize) -> Self { + debug_assert!(height > 0); + NodeRef { height, node: node.cast(), _marker: PhantomData } + } +} + +impl NodeRef { + /// Exposes the data of an internal node. + /// + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_internal_ptr(this: &Self) -> *mut InternalNode { + // SAFETY: the static node type is `Internal`. + this.node.as_ptr() as *mut InternalNode + } +} + +impl<'a, K, V> NodeRef, K, V, marker::Internal> { + /// Borrows exclusive access to the data of an internal node. + fn as_internal_mut(&mut self) -> &mut InternalNode { + let ptr = Self::as_internal_ptr(self); + unsafe { &mut *ptr } + } +} + +impl NodeRef { + /// Finds the length of the node. This is the number of keys or values. + /// The number of edges is `len() + 1`. + /// Note that, despite being safe, calling this function can have the side effect + /// of invalidating mutable references that unsafe code has created. + pub fn len(&self) -> usize { + // Crucially, we only access the `len` field here. If BorrowType is marker::ValMut, + // there might be outstanding mutable references to values that we must not invalidate. + unsafe { usize::from((*Self::as_leaf_ptr(self)).len) } + } + + /// Returns the number of levels that the node and leaves are apart. Zero + /// height means the node is a leaf itself. If you picture trees with the + /// root on top, the number says at which elevation the node appears. + /// If you picture trees with leaves on top, the number says how high + /// the tree extends above the node. + pub fn height(&self) -> usize { + self.height + } + + /// Temporarily takes out another, immutable reference to the same node. + pub fn reborrow(&self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Exposes the leaf portion of any leaf or internal node. + /// + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_leaf_ptr(this: &Self) -> *mut LeafNode { + // The node must be valid for at least the LeafNode portion. + // This is not a reference in the NodeRef type because we don't know if + // it should be unique or shared. + this.node.as_ptr() + } +} + +impl NodeRef { + /// Finds the parent of the current node. Returns `Ok(handle)` if the current + /// node actually has a parent, where `handle` points to the edge of the parent + /// that points to the current node. Returns `Err(self)` if the current node has + /// no parent, giving back the original `NodeRef`. + /// + /// The method name assumes you picture trees with the root node on top. + /// + /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should + /// both, upon success, do nothing. + pub fn ascend( + self, + ) -> Result, marker::Edge>, Self> { + assert!(BorrowType::PERMITS_TRAVERSAL); + // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, + // there might be outstanding mutable references to values that we must not invalidate. + let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); + unsafe { (*leaf_ptr).parent } + .as_ref() + .map(|parent| Handle { + node: NodeRef::from_internal(*parent, self.height + 1), + idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) }, + _marker: PhantomData, + }) + .ok_or(self) + } + + pub fn first_edge(self) -> Handle { + unsafe { Handle::new_edge(self, 0) } + } + + pub fn last_edge(self) -> Handle { + let len = self.len(); + unsafe { Handle::new_edge(self, len) } + } + + /// Note that `self` must be nonempty. + pub fn first_kv(self) -> Handle { + let len = self.len(); + assert!(len > 0); + unsafe { Handle::new_kv(self, 0) } + } + + /// Note that `self` must be nonempty. + pub fn last_kv(self) -> Handle { + let len = self.len(); + assert!(len > 0); + unsafe { Handle::new_kv(self, len - 1) } + } +} + +impl NodeRef { + /// Could be a public implementation of PartialEq, but only used in this module. + fn eq(&self, other: &Self) -> bool { + let Self { node, height, _marker } = self; + if node.eq(&other.node) { + debug_assert_eq!(*height, other.height); + true + } else { + false + } + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { + /// Exposes the leaf portion of any leaf or internal node in an immutable tree. + fn into_leaf(self) -> &'a LeafNode { + let ptr = Self::as_leaf_ptr(&self); + // SAFETY: there can be no mutable references into this tree borrowed as `Immut`. + unsafe { &*ptr } + } + + /// Borrows a view into the keys stored in the node. + pub fn keys(&self) -> &[K] { + let leaf = self.into_leaf(); + unsafe { + MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len))) + } + } +} + +impl NodeRef { + /// Similar to `ascend`, gets a reference to a node's parent node, but also + /// deallocates the current node in the process. This is unsafe because the + /// current node will still be accessible despite being deallocated. + pub unsafe fn deallocate_and_ascend( + self, + ) -> Option, marker::Edge>> { + let height = self.height; + let node = self.node; + let ret = self.ascend().ok(); + unsafe { + Global.deallocate( + node.cast(), + if height > 0 { + Layout::new::>() + } else { + Layout::new::>() + }, + ); + } + ret + } +} + +impl<'a, K, V, Type> NodeRef, K, V, Type> { + /// Temporarily takes out another, mutable reference to the same node. Beware, as + /// this method is very dangerous, doubly so since it may not immediately appear + /// dangerous. + /// + /// Because mutable pointers can roam anywhere around the tree, the returned + /// pointer can easily be used to make the original pointer dangling, out of + /// bounds, or invalid under stacked borrow rules. + // FIXME(@gereeter) consider adding yet another type parameter to `NodeRef` + // that restricts the use of navigation methods on reborrowed pointers, + // preventing this unsafety. + unsafe fn reborrow_mut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Borrows exclusive access to the leaf portion of any leaf or internal node. + fn as_leaf_mut(&mut self) -> &mut LeafNode { + let ptr = Self::as_leaf_ptr(self); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } + } + + /// Offers exclusive access to the leaf portion of any leaf or internal node. + fn into_leaf_mut(mut self) -> &'a mut LeafNode { + let ptr = Self::as_leaf_ptr(&mut self); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { + /// Borrows exclusive access to an element of the key storage area. + /// + /// # Safety + /// `index` is in bounds of 0..CAPACITY + unsafe fn key_area_mut(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the key slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_leaf_mut().keys.as_mut_slice().get_unchecked_mut(index) } + } + + /// Borrows exclusive access to an element or slice of the node's value storage area. + /// + /// # Safety + /// `index` is in bounds of 0..CAPACITY + unsafe fn val_area_mut(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the value slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_leaf_mut().vals.as_mut_slice().get_unchecked_mut(index) } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { + /// Borrows exclusive access to an element or slice of the node's storage area for edge contents. + /// + /// # Safety + /// `index` is in bounds of 0..CAPACITY + 1 + unsafe fn edge_area_mut(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit>], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the edge slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_internal_mut().edges.as_mut_slice().get_unchecked_mut(index) } + } +} + +impl<'a, K, V, Type> NodeRef, K, V, Type> { + /// # Safety + /// - The node has more than `idx` initialized elements. + unsafe fn into_key_val_mut_at(mut self, idx: usize) -> (&'a K, &'a mut V) { + // We only create a reference to the one element we are interested in, + // to avoid aliasing with outstanding references to other elements, + // in particular, those returned to the caller in earlier iterations. + let leaf = Self::as_leaf_ptr(&mut self); + let keys = unsafe { ptr::addr_of!((*leaf).keys) }; + let vals = unsafe { ptr::addr_of_mut!((*leaf).vals) }; + // We must coerce to unsized array pointers because of Rust issue #74679. + let keys: *const [_] = keys; + let vals: *mut [_] = vals; + let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() }; + let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() }; + (key, val) + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { + /// Borrows exclusive access to the length of the node. + pub fn len_mut(&mut self) -> &mut u16 { + &mut self.as_leaf_mut().len + } +} + +impl<'a, K, V> NodeRef, K, V, marker::Internal> { + /// # Safety + /// Every item returned by `range` is a valid edge index for the node. + unsafe fn correct_childrens_parent_links>(&mut self, range: R) { + for i in range { + debug_assert!(i <= self.len()); + unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); + } + } + + fn correct_all_childrens_parent_links(&mut self) { + let len = self.len(); + unsafe { self.correct_childrens_parent_links(0..=len) }; + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Sets the node's link to its parent edge, + /// without invalidating other references to the node. + fn set_parent_link(&mut self, parent: NonNull>, parent_idx: usize) { + let leaf = Self::as_leaf_ptr(self); + unsafe { (*leaf).parent = Some(parent) }; + unsafe { (*leaf).parent_idx.write(parent_idx as u16) }; + } +} + +impl NodeRef { + /// Clears the root's link to its parent edge. + fn clear_parent_link(&mut self) { + let mut root_node = self.borrow_mut(); + let leaf = root_node.as_leaf_mut(); + leaf.parent = None; + } +} + +impl NodeRef { + /// Returns a new owned tree, with its own root node that is initially empty. + pub fn new() -> Self { + NodeRef::new_leaf().forget_type() + } + + /// Adds a new internal node with a single edge pointing to the previous root node, + /// make that new node the root node, and return it. This increases the height by 1 + /// and is the opposite of `pop_internal_level`. + pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { + super::mem::take_mut(self, |old_root| NodeRef::new_internal(old_root).forget_type()); + + // `self.borrow_mut()`, except that we just forgot we're internal now: + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Removes the internal root node, using its first child as the new root node. + /// As it is intended only to be called when the root node has only one child, + /// no cleanup is done on any of the keys, values and other children. + /// This decreases the height by 1 and is the opposite of `push_internal_level`. + /// + /// Requires exclusive access to the `Root` object but not to the root node; + /// it will not invalidate other handles or references to the root node. + /// + /// Panics if there is no internal level, i.e., if the root node is a leaf. + pub fn pop_internal_level(&mut self) { + assert!(self.height > 0); + + let top = self.node; + + // SAFETY: we asserted to be internal. + let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; + // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. + let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; + // SAFETY: the first edge is always initialized. + self.node = unsafe { internal_node.edges[0].assume_init_read() }; + self.height -= 1; + self.clear_parent_link(); + + unsafe { + Global.deallocate(top.cast(), Layout::new::>()); + } + } +} + +impl NodeRef { + /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe + /// because the return value cannot be used to destroy the root, and there + /// cannot be other references to the tree. + pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Slightly mutably borrows the owned root node. + pub fn borrow_valmut(&mut self) -> NodeRef, K, V, Type> { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Irreversibly transitions to a reference that permits traversal and offers + /// destructive methods and little else. + pub fn into_dying(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { + /// Adds a key-value pair to the end of the node. + pub fn push(&mut self, key: K, val: V) { + let len = self.len_mut(); + let idx = usize::from(*len); + assert!(idx < CAPACITY); + *len += 1; + unsafe { + self.key_area_mut(idx).write(key); + self.val_area_mut(idx).write(val); + } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { + /// Adds a key-value pair, and an edge to go to the right of that pair, + /// to the end of the node. + pub fn push(&mut self, key: K, val: V, edge: Root) { + assert!(edge.height == self.height - 1); + + let len = self.len_mut(); + let idx = usize::from(*len); + assert!(idx < CAPACITY); + *len += 1; + unsafe { + self.key_area_mut(idx).write(key); + self.val_area_mut(idx).write(val); + self.edge_area_mut(idx + 1).write(edge.node); + Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); + } + } +} + +impl NodeRef { + /// Removes any static information asserting that this node is a `Leaf` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Removes any static information asserting that this node is an `Internal` node. + pub fn forget_type(self) -> NodeRef { + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +impl NodeRef { + /// Checks whether a node is an `Internal` node or a `Leaf` node. + pub fn force( + self, + ) -> ForceResult< + NodeRef, + NodeRef, + > { + if self.height == 0 { + ForceResult::Leaf(NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + }) + } else { + ForceResult::Internal(NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + }) + } + } +} + +impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { + /// Unsafely asserts to the compiler the static information that this node is a `Leaf`. + unsafe fn cast_to_leaf_unchecked(self) -> NodeRef, K, V, marker::Leaf> { + debug_assert!(self.height == 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } + + /// Unsafely asserts to the compiler the static information that this node is an `Internal`. + unsafe fn cast_to_internal_unchecked(self) -> NodeRef, K, V, marker::Internal> { + debug_assert!(self.height > 0); + NodeRef { height: self.height, node: self.node, _marker: PhantomData } + } +} + +/// A reference to a specific key-value pair or edge within a node. The `Node` parameter +/// must be a `NodeRef`, while the `Type` can either be `KV` (signifying a handle on a key-value +/// pair) or `Edge` (signifying a handle on an edge). +/// +/// Note that even `Leaf` nodes can have `Edge` handles. Instead of representing a pointer to +/// a child node, these represent the spaces where child pointers would go between the key-value +/// pairs. For example, in a node with length 2, there would be 3 possible edge locations - one +/// to the left of the node, one between the two pairs, and one at the right of the node. +pub struct Handle { + node: Node, + idx: usize, + _marker: PhantomData, +} + +impl Copy for Handle {} +// We don't need the full generality of `#[derive(Clone)]`, as the only time `Node` will be +// `Clone`able is when it is an immutable reference and therefore `Copy`. +impl Clone for Handle { + fn clone(&self) -> Self { + *self + } +} + +impl Handle { + /// Retrieves the node that contains the edge or key-value pair this handle points to. + pub fn into_node(self) -> Node { + self.node + } + + /// Returns the position of this handle in the node. + pub fn idx(&self) -> usize { + self.idx + } +} + +impl Handle, marker::KV> { + /// Creates a new handle to a key-value pair in `node`. + /// Unsafe because the caller must ensure that `idx < node.len()`. + pub unsafe fn new_kv(node: NodeRef, idx: usize) -> Self { + debug_assert!(idx < node.len()); + + Handle { node, idx, _marker: PhantomData } + } + + pub fn left_edge(self) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node, self.idx) } + } + + pub fn right_edge(self) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node, self.idx + 1) } + } +} + +impl PartialEq + for Handle, HandleType> +{ + fn eq(&self, other: &Self) -> bool { + let Self { node, idx, _marker } = self; + node.eq(&other.node) && *idx == other.idx + } +} + +impl + Handle, HandleType> +{ + /// Temporarily takes out another, immutable handle on the same location. + pub fn reborrow(&self) -> Handle, K, V, NodeType>, HandleType> { + // We can't use Handle::new_kv or Handle::new_edge because we don't know our type + Handle { node: self.node.reborrow(), idx: self.idx, _marker: PhantomData } + } +} + +impl<'a, K, V, NodeType, HandleType> Handle, K, V, NodeType>, HandleType> { + /// Temporarily takes out another, mutable handle on the same location. Beware, as + /// this method is very dangerous, doubly so since it may not immediately appear + /// dangerous. + /// + /// For details, see `NodeRef::reborrow_mut`. + pub unsafe fn reborrow_mut( + &mut self, + ) -> Handle, K, V, NodeType>, HandleType> { + // We can't use Handle::new_kv or Handle::new_edge because we don't know our type + Handle { node: unsafe { self.node.reborrow_mut() }, idx: self.idx, _marker: PhantomData } + } +} + +impl Handle, marker::Edge> { + /// Creates a new handle to an edge in `node`. + /// Unsafe because the caller must ensure that `idx <= node.len()`. + pub unsafe fn new_edge(node: NodeRef, idx: usize) -> Self { + debug_assert!(idx <= node.len()); + + Handle { node, idx, _marker: PhantomData } + } + + pub fn left_kv(self) -> Result, marker::KV>, Self> { + if self.idx > 0 { + Ok(unsafe { Handle::new_kv(self.node, self.idx - 1) }) + } else { + Err(self) + } + } + + pub fn right_kv(self) -> Result, marker::KV>, Self> { + if self.idx < self.node.len() { + Ok(unsafe { Handle::new_kv(self.node, self.idx) }) + } else { + Err(self) + } + } +} + +pub enum LeftOrRight { + Left(T), + Right(T), +} + +/// Given an edge index where we want to insert into a node filled to capacity, +/// computes a sensible KV index of a split point and where to perform the insertion. +/// The goal of the split point is for its key and value to end up in a parent node; +/// the keys, values and edges to the left of the split point become the left child; +/// the keys, values and edges to the right of the split point become the right child. +fn splitpoint(edge_idx: usize) -> (usize, LeftOrRight) { + debug_assert!(edge_idx <= CAPACITY); + // Rust issue #74834 tries to explain these symmetric rules. + match edge_idx { + 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, LeftOrRight::Left(edge_idx)), + EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, LeftOrRight::Left(edge_idx)), + EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, LeftOrRight::Right(0)), + _ => (KV_IDX_CENTER + 1, LeftOrRight::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))), + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key-value pair between the key-value pairs to the right and left of + /// this edge. This method assumes that there is enough space in the node for the new + /// pair to fit. + /// + /// The returned pointer points to the inserted value. + fn insert_fit(&mut self, key: K, val: V) -> *mut V { + debug_assert!(self.node.len() < CAPACITY); + let new_len = self.node.len() + 1; + + unsafe { + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); + *self.node.len_mut() = new_len as u16; + + self.node.val_area_mut(self.idx).assume_init_mut() + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key-value pair between the key-value pairs to the right and left of + /// this edge. This method splits the node if there isn't enough room. + /// + /// The returned pointer points to the inserted value. + fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *mut V) { + if self.node.len() < CAPACITY { + let val_ptr = self.insert_fit(key, val); + let kv = unsafe { Handle::new_kv(self.node, self.idx) }; + (InsertResult::Fit(kv), val_ptr) + } else { + let (middle_kv_idx, insertion) = splitpoint(self.idx); + let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; + let mut result = middle.split(); + let mut insertion_edge = match insertion { + LeftOrRight::Left(insert_idx) => unsafe { + Handle::new_edge(result.left.reborrow_mut(), insert_idx) + }, + LeftOrRight::Right(insert_idx) => unsafe { + Handle::new_edge(result.right.borrow_mut(), insert_idx) + }, + }; + let val_ptr = insertion_edge.insert_fit(key, val); + (InsertResult::Split(result), val_ptr) + } + } +} + +impl<'a, K, V> Handle, K, V, marker::Internal>, marker::Edge> { + /// Fixes the parent pointer and index in the child node that this edge + /// links to. This is useful when the ordering of edges has been changed, + fn correct_parent_link(self) { + // Create backpointer without invalidating other references to the node. + let ptr = unsafe { NonNull::new_unchecked(NodeRef::as_internal_ptr(&self.node)) }; + let idx = self.idx; + let mut child = self.descend(); + child.set_parent_link(ptr, idx); + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::Edge> { + /// Inserts a new key-value pair and an edge that will go to the right of that new pair + /// between this edge and the key-value pair to the right of this edge. This method assumes + /// that there is enough space in the node for the new pair to fit. + fn insert_fit(&mut self, key: K, val: V, edge: Root) { + debug_assert!(self.node.len() < CAPACITY); + debug_assert!(edge.height == self.node.height - 1); + let new_len = self.node.len() + 1; + + unsafe { + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); + slice_insert(self.node.edge_area_mut(..new_len + 1), self.idx + 1, edge.node); + *self.node.len_mut() = new_len as u16; + + self.node.correct_childrens_parent_links(self.idx + 1..new_len + 1); + } + } + + /// Inserts a new key-value pair and an edge that will go to the right of that new pair + /// between this edge and the key-value pair to the right of this edge. This method splits + /// the node if there isn't enough room. + fn insert( + mut self, + key: K, + val: V, + edge: Root, + ) -> InsertResult<'a, K, V, marker::Internal> { + assert!(edge.height == self.node.height - 1); + + if self.node.len() < CAPACITY { + self.insert_fit(key, val, edge); + let kv = unsafe { Handle::new_kv(self.node, self.idx) }; + InsertResult::Fit(kv) + } else { + let (middle_kv_idx, insertion) = splitpoint(self.idx); + let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; + let mut result = middle.split(); + let mut insertion_edge = match insertion { + LeftOrRight::Left(insert_idx) => unsafe { + Handle::new_edge(result.left.reborrow_mut(), insert_idx) + }, + LeftOrRight::Right(insert_idx) => unsafe { + Handle::new_edge(result.right.borrow_mut(), insert_idx) + }, + }; + insertion_edge.insert_fit(key, val, edge); + InsertResult::Split(result) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::Edge> { + /// Inserts a new key-value pair between the key-value pairs to the right and left of + /// this edge. This method splits the node if there isn't enough room, and tries to + /// insert the split off portion into the parent node recursively, until the root is reached. + /// + /// If the returned result is a `Fit`, its handle's node can be this edge's node or an ancestor. + /// If the returned result is a `Split`, the `left` field will be the root node. + /// The returned pointer points to the inserted value. + pub fn insert_recursing( + self, + key: K, + value: V, + ) -> (InsertResult<'a, K, V, marker::LeafOrInternal>, *mut V) { + let (mut split, val_ptr) = match self.insert(key, value) { + (InsertResult::Fit(handle), ptr) => { + return (InsertResult::Fit(handle.forget_node_type()), ptr); + } + (InsertResult::Split(split), val_ptr) => (split.forget_node_type(), val_ptr), + }; + + loop { + split = match split.left.ascend() { + Ok(parent) => match parent.insert(split.kv.0, split.kv.1, split.right) { + InsertResult::Fit(handle) => { + return (InsertResult::Fit(handle.forget_node_type()), val_ptr); + } + InsertResult::Split(split) => split.forget_node_type(), + }, + Err(root) => { + return (InsertResult::Split(SplitResult { left: root, ..split }), val_ptr); + } + }; + } + } +} + +impl + Handle, marker::Edge> +{ + /// Finds the node pointed to by this edge. + /// + /// The method name assumes you picture trees with the root node on top. + /// + /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should + /// both, upon success, do nothing. + pub fn descend(self) -> NodeRef { + assert!(BorrowType::PERMITS_TRAVERSAL); + // We need to use raw pointers to nodes because, if BorrowType is + // marker::ValMut, there might be outstanding mutable references to + // values that we must not invalidate. There's no worry accessing the + // height field because that value is copied. Beware that, once the + // node pointer is dereferenced, we access the edges array with a + // reference (Rust issue #73987) and invalidate any other references + // to or inside the array, should any be around. + let parent_ptr = NodeRef::as_internal_ptr(&self.node); + let node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() }; + NodeRef { node, height: self.node.height - 1, _marker: PhantomData } + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn into_kv(self) -> (&'a K, &'a V) { + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.into_leaf(); + let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() }; + let v = unsafe { leaf.vals.get_unchecked(self.idx).assume_init_ref() }; + (k, v) + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn key_mut(&mut self) -> &mut K { + unsafe { self.node.key_area_mut(self.idx).assume_init_mut() } + } + + pub fn into_val_mut(self) -> &'a mut V { + debug_assert!(self.idx < self.node.len()); + let leaf = self.node.into_leaf_mut(); + unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() } + } +} + +impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn into_kv_valmut(self) -> (&'a K, &'a mut V) { + unsafe { self.node.into_key_val_mut_at(self.idx) } + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn kv_mut(&mut self) -> (&mut K, &mut V) { + debug_assert!(self.idx < self.node.len()); + // We cannot call separate key and value methods, because calling the second one + // invalidates the reference returned by the first. + unsafe { + let leaf = self.node.as_leaf_mut(); + let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_mut(); + let val = leaf.vals.get_unchecked_mut(self.idx).assume_init_mut(); + (key, val) + } + } + + /// Replace the key and value that the KV handle refers to. + pub fn replace_kv(&mut self, k: K, v: V) -> (K, V) { + let (key, val) = self.kv_mut(); + (mem::replace(key, k), mem::replace(val, v)) + } +} + +impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + /// Helps implementations of `split` for a particular `NodeType`, + /// by taking care of leaf data. + fn split_leaf_data(&mut self, new_node: &mut LeafNode) -> (K, V) { + debug_assert!(self.idx < self.node.len()); + let old_len = self.node.len(); + let new_len = old_len - self.idx - 1; + new_node.len = new_len as u16; + unsafe { + let k = self.node.key_area_mut(self.idx).assume_init_read(); + let v = self.node.val_area_mut(self.idx).assume_init_read(); + + move_to_slice( + self.node.key_area_mut(self.idx + 1..old_len), + &mut new_node.keys[..new_len], + ); + move_to_slice( + self.node.val_area_mut(self.idx + 1..old_len), + &mut new_node.vals[..new_len], + ); + + *self.node.len_mut() = self.idx as u16; + (k, v) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, marker::KV> { + /// Splits the underlying node into three parts: + /// + /// - The node is truncated to only contain the key-value pairs to the left of + /// this handle. + /// - The key and value pointed to by this handle are extracted. + /// - All the key-value pairs to the right of this handle are put into a newly + /// allocated node. + pub fn split(mut self) -> SplitResult<'a, K, V, marker::Leaf> { + let mut new_node = LeafNode::new(); + + let kv = self.split_leaf_data(&mut new_node); + + let right = NodeRef::from_new_leaf(new_node); + SplitResult { left: self.node, kv, right } + } + + /// Removes the key-value pair pointed to by this handle and returns it, along with the edge + /// that the key-value pair collapsed into. + pub fn remove( + mut self, + ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + let old_len = self.node.len(); + unsafe { + let k = slice_remove(self.node.key_area_mut(..old_len), self.idx); + let v = slice_remove(self.node.val_area_mut(..old_len), self.idx); + *self.node.len_mut() = (old_len - 1) as u16; + ((k, v), self.left_edge()) + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::KV> { + /// Splits the underlying node into three parts: + /// + /// - The node is truncated to only contain the edges and key-value pairs to the + /// left of this handle. + /// - The key and value pointed to by this handle are extracted. + /// - All the edges and key-value pairs to the right of this handle are put into + /// a newly allocated node. + pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> { + let old_len = self.node.len(); + unsafe { + let mut new_node = InternalNode::new(); + let kv = self.split_leaf_data(&mut new_node.data); + let new_len = usize::from(new_node.data.len); + move_to_slice( + self.node.edge_area_mut(self.idx + 1..old_len + 1), + &mut new_node.edges[..new_len + 1], + ); + + let height = self.node.height; + let right = NodeRef::from_new_internal(new_node, height); + + SplitResult { left: self.node, kv, right } + } + } +} + +/// Represents a session for evaluating and performing a balancing operation +/// around an internal key-value pair. +pub struct BalancingContext<'a, K, V> { + parent: Handle, K, V, marker::Internal>, marker::KV>, + left_child: NodeRef, K, V, marker::LeafOrInternal>, + right_child: NodeRef, K, V, marker::LeafOrInternal>, +} + +impl<'a, K, V> Handle, K, V, marker::Internal>, marker::KV> { + pub fn consider_for_balancing(self) -> BalancingContext<'a, K, V> { + let self1 = unsafe { ptr::read(&self) }; + let self2 = unsafe { ptr::read(&self) }; + BalancingContext { + parent: self, + left_child: self1.left_edge().descend(), + right_child: self2.right_edge().descend(), + } + } +} + +impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { + /// Chooses a balancing context involving the node as a child, thus between + /// the KV immediately to the left or to the right in the parent node. + /// Returns an `Err` if there is no parent. + /// Panics if the parent is empty. + /// + /// Prefers the left side, to be optimal if the given node is somehow + /// underfull, meaning here only that it has fewer elements than its left + /// sibling and than its right sibling, if they exist. In that case, + /// merging with the left sibling is faster, since we only need to move + /// the node's N elements, instead of shifting them to the right and moving + /// more than N elements in front. Stealing from the left sibling is also + /// typically faster, since we only need to shift the node's N elements to + /// the right, instead of shifting at least N of the sibling's elements to + /// the left. + pub fn choose_parent_kv(self) -> Result>, Self> { + match unsafe { ptr::read(&self) }.ascend() { + Ok(parent_edge) => match parent_edge.left_kv() { + Ok(left_parent_kv) => Ok(LeftOrRight::Left(BalancingContext { + parent: unsafe { ptr::read(&left_parent_kv) }, + left_child: left_parent_kv.left_edge().descend(), + right_child: self, + })), + Err(parent_edge) => match parent_edge.right_kv() { + Ok(right_parent_kv) => Ok(LeftOrRight::Right(BalancingContext { + parent: unsafe { ptr::read(&right_parent_kv) }, + left_child: self, + right_child: right_parent_kv.right_edge().descend(), + })), + Err(_) => unreachable!("empty internal node"), + }, + }, + Err(root) => Err(root), + } + } +} + +impl<'a, K, V> BalancingContext<'a, K, V> { + pub fn left_child_len(&self) -> usize { + self.left_child.len() + } + + pub fn right_child_len(&self) -> usize { + self.right_child.len() + } + + pub fn into_left_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + self.left_child + } + + pub fn into_right_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + self.right_child + } + + /// Returns whether merging is possible, i.e., whether there is enough room + /// in a node to combine the central KV with both adjacent child nodes. + pub fn can_merge(&self) -> bool { + self.left_child.len() + 1 + self.right_child.len() <= CAPACITY + } +} + +impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { + /// Performs a merge and lets a closure decide what to return. + fn do_merge< + F: FnOnce( + NodeRef, K, V, marker::Internal>, + NodeRef, K, V, marker::LeafOrInternal>, + ) -> R, + R, + >( + self, + result: F, + ) -> R { + let Handle { node: mut parent_node, idx: parent_idx, _marker } = self.parent; + let old_parent_len = parent_node.len(); + let mut left_node = self.left_child; + let old_left_len = left_node.len(); + let mut right_node = self.right_child; + let right_len = right_node.len(); + let new_left_len = old_left_len + 1 + right_len; + + assert!(new_left_len <= CAPACITY); + + unsafe { + *left_node.len_mut() = new_left_len as u16; + + let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx); + left_node.key_area_mut(old_left_len).write(parent_key); + move_to_slice( + right_node.key_area_mut(..right_len), + left_node.key_area_mut(old_left_len + 1..new_left_len), + ); + + let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx); + left_node.val_area_mut(old_left_len).write(parent_val); + move_to_slice( + right_node.val_area_mut(..right_len), + left_node.val_area_mut(old_left_len + 1..new_left_len), + ); + + slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1); + parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); + *parent_node.len_mut() -= 1; + + if parent_node.height > 1 { + // SAFETY: the height of the nodes being merged is one below the height + // of the node of this edge, thus above zero, so they are internal. + let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked(); + let mut right_node = right_node.cast_to_internal_unchecked(); + move_to_slice( + right_node.edge_area_mut(..right_len + 1), + left_node.edge_area_mut(old_left_len + 1..new_left_len + 1), + ); + + left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1); + + Global.deallocate(right_node.node.cast(), Layout::new::>()); + } else { + Global.deallocate(right_node.node.cast(), Layout::new::>()); + } + } + result(parent_node, left_node) + } + + /// Merges the parent's key-value pair and both adjacent child nodes into + /// the left child node and returns the shrunk parent node. + /// + /// Panics unless we `.can_merge()`. + pub fn merge_tracking_parent(self) -> NodeRef, K, V, marker::Internal> { + self.do_merge(|parent, _child| parent) + } + + /// Merges the parent's key-value pair and both adjacent child nodes into + /// the left child node and returns that child node. + /// + /// Panics unless we `.can_merge()`. + pub fn merge_tracking_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + self.do_merge(|_parent, child| child) + } + + /// Merges the parent's key-value pair and both adjacent child nodes into + /// the left child node and returns the edge handle in that child node + /// where the tracked child edge ended up, + /// + /// Panics unless we `.can_merge()`. + pub fn merge_tracking_child_edge( + self, + track_edge_idx: LeftOrRight, + ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + let old_left_len = self.left_child.len(); + let right_len = self.right_child.len(); + assert!(match track_edge_idx { + LeftOrRight::Left(idx) => idx <= old_left_len, + LeftOrRight::Right(idx) => idx <= right_len, + }); + let child = self.merge_tracking_child(); + let new_idx = match track_edge_idx { + LeftOrRight::Left(idx) => idx, + LeftOrRight::Right(idx) => old_left_len + 1 + idx, + }; + unsafe { Handle::new_edge(child, new_idx) } + } + + /// Removes a key-value pair from the left child and places it in the key-value storage + /// of the parent, while pushing the old parent key-value pair into the right child. + /// Returns a handle to the edge in the right child corresponding to where the original + /// edge specified by `track_right_edge_idx` ended up. + pub fn steal_left( + mut self, + track_right_edge_idx: usize, + ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + self.bulk_steal_left(1); + unsafe { Handle::new_edge(self.right_child, 1 + track_right_edge_idx) } + } + + /// Removes a key-value pair from the right child and places it in the key-value storage + /// of the parent, while pushing the old parent key-value pair onto the left child. + /// Returns a handle to the edge in the left child specified by `track_left_edge_idx`, + /// which didn't move. + pub fn steal_right( + mut self, + track_left_edge_idx: usize, + ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + self.bulk_steal_right(1); + unsafe { Handle::new_edge(self.left_child, track_left_edge_idx) } + } + + /// This does stealing similar to `steal_left` but steals multiple elements at once. + pub fn bulk_steal_left(&mut self, count: usize) { + assert!(count > 0); + unsafe { + let left_node = &mut self.left_child; + let old_left_len = left_node.len(); + let right_node = &mut self.right_child; + let old_right_len = right_node.len(); + + // Make sure that we may steal safely. + assert!(old_right_len + count <= CAPACITY); + assert!(old_left_len >= count); + + let new_left_len = old_left_len - count; + let new_right_len = old_right_len + count; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; + + // Move leaf data. + { + // Make room for stolen elements in the right child. + slice_shr(right_node.key_area_mut(..new_right_len), count); + slice_shr(right_node.val_area_mut(..new_right_len), count); + + // Move elements from the left child to the right one. + move_to_slice( + left_node.key_area_mut(new_left_len + 1..old_left_len), + right_node.key_area_mut(..count - 1), + ); + move_to_slice( + left_node.val_area_mut(new_left_len + 1..old_left_len), + right_node.val_area_mut(..count - 1), + ); + + // Move the left-most stolen pair to the parent. + let k = left_node.key_area_mut(new_left_len).assume_init_read(); + let v = left_node.val_area_mut(new_left_len).assume_init_read(); + let (k, v) = self.parent.replace_kv(k, v); + + // Move parent's key-value pair to the right child. + right_node.key_area_mut(count - 1).write(k); + right_node.val_area_mut(count - 1).write(v); + } + + match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { + (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => { + // Make room for stolen edges. + slice_shr(right.edge_area_mut(..new_right_len + 1), count); + + // Steal edges. + move_to_slice( + left.edge_area_mut(new_left_len + 1..old_left_len + 1), + right.edge_area_mut(..count), + ); + + right.correct_childrens_parent_links(0..new_right_len + 1); + } + (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} + _ => unreachable!(), + } + } + } + + /// The symmetric clone of `bulk_steal_left`. + pub fn bulk_steal_right(&mut self, count: usize) { + assert!(count > 0); + unsafe { + let left_node = &mut self.left_child; + let old_left_len = left_node.len(); + let right_node = &mut self.right_child; + let old_right_len = right_node.len(); + + // Make sure that we may steal safely. + assert!(old_left_len + count <= CAPACITY); + assert!(old_right_len >= count); + + let new_left_len = old_left_len + count; + let new_right_len = old_right_len - count; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; + + // Move leaf data. + { + // Move the right-most stolen pair to the parent. + let k = right_node.key_area_mut(count - 1).assume_init_read(); + let v = right_node.val_area_mut(count - 1).assume_init_read(); + let (k, v) = self.parent.replace_kv(k, v); + + // Move parent's key-value pair to the left child. + left_node.key_area_mut(old_left_len).write(k); + left_node.val_area_mut(old_left_len).write(v); + + // Move elements from the right child to the left one. + move_to_slice( + right_node.key_area_mut(..count - 1), + left_node.key_area_mut(old_left_len + 1..new_left_len), + ); + move_to_slice( + right_node.val_area_mut(..count - 1), + left_node.val_area_mut(old_left_len + 1..new_left_len), + ); + + // Fill gap where stolen elements used to be. + slice_shl(right_node.key_area_mut(..old_right_len), count); + slice_shl(right_node.val_area_mut(..old_right_len), count); + } + + match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { + (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => { + // Steal edges. + move_to_slice( + right.edge_area_mut(..count), + left.edge_area_mut(old_left_len + 1..new_left_len + 1), + ); + + // Fill gap where stolen edges used to be. + slice_shl(right.edge_area_mut(..old_right_len + 1), count); + + left.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1); + right.correct_childrens_parent_links(0..new_right_len + 1); + } + (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} + _ => unreachable!(), + } + } + } +} + +impl Handle, marker::Edge> { + pub fn forget_node_type( + self, + ) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } + } +} + +impl Handle, marker::Edge> { + pub fn forget_node_type( + self, + ) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } + } +} + +impl Handle, marker::KV> { + pub fn forget_node_type( + self, + ) -> Handle, marker::KV> { + unsafe { Handle::new_kv(self.node.forget_type(), self.idx) } + } +} + +impl Handle, marker::KV> { + pub fn forget_node_type( + self, + ) -> Handle, marker::KV> { + unsafe { Handle::new_kv(self.node.forget_type(), self.idx) } + } +} + +impl Handle, Type> { + /// Checks whether the underlying node is an `Internal` node or a `Leaf` node. + pub fn force( + self, + ) -> ForceResult< + Handle, Type>, + Handle, Type>, + > { + match self.node.force() { + ForceResult::Leaf(node) => { + ForceResult::Leaf(Handle { node, idx: self.idx, _marker: PhantomData }) + } + ForceResult::Internal(node) => { + ForceResult::Internal(Handle { node, idx: self.idx, _marker: PhantomData }) + } + } + } +} + +impl<'a, K, V, Type> Handle, K, V, marker::LeafOrInternal>, Type> { + /// Unsafely asserts to the compiler the static information that the handle's node is a `Leaf`. + pub unsafe fn cast_to_leaf_unchecked( + self, + ) -> Handle, K, V, marker::Leaf>, Type> { + let node = unsafe { self.node.cast_to_leaf_unchecked() }; + Handle { node, idx: self.idx, _marker: PhantomData } + } +} + +impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + /// Move the suffix after `self` from one node to another one. `right` must be empty. + /// The first edge of `right` remains unchanged. + pub fn move_suffix( + &mut self, + right: &mut NodeRef, K, V, marker::LeafOrInternal>, + ) { + unsafe { + let new_left_len = self.idx; + let mut left_node = self.reborrow_mut().into_node(); + let old_left_len = left_node.len(); + + let new_right_len = old_left_len - new_left_len; + let mut right_node = right.reborrow_mut(); + + assert!(right_node.len() == 0); + assert!(left_node.height == right_node.height); + + if new_right_len > 0 { + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; + + move_to_slice( + left_node.key_area_mut(new_left_len..old_left_len), + right_node.key_area_mut(..new_right_len), + ); + move_to_slice( + left_node.val_area_mut(new_left_len..old_left_len), + right_node.val_area_mut(..new_right_len), + ); + match (left_node.force(), right_node.force()) { + (ForceResult::Internal(mut left), ForceResult::Internal(mut right)) => { + move_to_slice( + left.edge_area_mut(new_left_len + 1..old_left_len + 1), + right.edge_area_mut(1..new_right_len + 1), + ); + right.correct_childrens_parent_links(1..new_right_len + 1); + } + (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} + _ => unreachable!(), + } + } + } + } +} + +pub enum ForceResult { + Leaf(Leaf), + Internal(Internal), +} + +/// Result of insertion, when a node needed to expand beyond its capacity. +pub struct SplitResult<'a, K, V, NodeType> { + // Altered node in existing tree with elements and edges that belong to the left of `kv`. + pub left: NodeRef, K, V, NodeType>, + // Some key and value split off, to be inserted elsewhere. + pub kv: (K, V), + // Owned, unattached, new node with elements and edges that belong to the right of `kv`. + pub right: NodeRef, +} + +impl<'a, K, V> SplitResult<'a, K, V, marker::Leaf> { + pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> { + SplitResult { left: self.left.forget_type(), kv: self.kv, right: self.right.forget_type() } + } +} + +impl<'a, K, V> SplitResult<'a, K, V, marker::Internal> { + pub fn forget_node_type(self) -> SplitResult<'a, K, V, marker::LeafOrInternal> { + SplitResult { left: self.left.forget_type(), kv: self.kv, right: self.right.forget_type() } + } +} + +pub enum InsertResult<'a, K, V, NodeType> { + Fit(Handle, K, V, NodeType>, marker::KV>), + Split(SplitResult<'a, K, V, NodeType>), +} + +pub mod marker { + use core::marker::PhantomData; + + pub enum Leaf {} + pub enum Internal {} + pub enum LeafOrInternal {} + + pub enum Owned {} + pub enum Dying {} + pub struct Immut<'a>(PhantomData<&'a ()>); + pub struct Mut<'a>(PhantomData<&'a mut ()>); + pub struct ValMut<'a>(PhantomData<&'a mut ()>); + + pub trait BorrowType { + // Whether node references of this borrow type allow traversing + // to other nodes in the tree. + const PERMITS_TRAVERSAL: bool = true; + } + impl BorrowType for Owned { + // Traversal isn't needede, it happens using the result of `borrow_mut`. + // By disabling traversal, and only creating new references to roots, + // we know that every reference of the `Owned` type is to a root node. + const PERMITS_TRAVERSAL: bool = false; + } + impl BorrowType for Dying {} + impl<'a> BorrowType for Immut<'a> {} + impl<'a> BorrowType for Mut<'a> {} + impl<'a> BorrowType for ValMut<'a> {} + + pub enum KV {} + pub enum Edge {} +} + +/// Inserts a value into a slice of initialized elements followed by one uninitialized element. +/// +/// # Safety +/// The slice has more than `idx` elements. +unsafe fn slice_insert(slice: &mut [MaybeUninit], idx: usize, val: T) { + unsafe { + let len = slice.len(); + debug_assert!(len > idx); + let slice_ptr = slice.as_mut_ptr(); + if len > idx + 1 { + ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx - 1); + } + (*slice_ptr.add(idx)).write(val); + } +} + +/// Removes and returns a value from a slice of all initialized elements, leaving behind one +/// trailing uninitialized element. +/// +/// # Safety +/// The slice has more than `idx` elements. +unsafe fn slice_remove(slice: &mut [MaybeUninit], idx: usize) -> T { + unsafe { + let len = slice.len(); + debug_assert!(idx < len); + let slice_ptr = slice.as_mut_ptr(); + let ret = (*slice_ptr.add(idx)).assume_init_read(); + ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); + ret + } +} + +/// Shifts the elements in a slice `distance` positions to the left. +/// +/// # Safety +/// The slice has at least `distance` elements. +unsafe fn slice_shl(slice: &mut [MaybeUninit], distance: usize) { + unsafe { + let slice_ptr = slice.as_mut_ptr(); + ptr::copy(slice_ptr.add(distance), slice_ptr, slice.len() - distance); + } +} + +/// Shifts the elements in a slice `distance` positions to the right. +/// +/// # Safety +/// The slice has at least `distance` elements. +unsafe fn slice_shr(slice: &mut [MaybeUninit], distance: usize) { + unsafe { + let slice_ptr = slice.as_mut_ptr(); + ptr::copy(slice_ptr, slice_ptr.add(distance), slice.len() - distance); + } +} + +/// Moves all values from a slice of initialized elements to a slice +/// of uninitialized elements, leaving behind `src` as all uninitialized. +/// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`. +fn move_to_slice(src: &mut [MaybeUninit], dst: &mut [MaybeUninit]) { + assert!(src.len() == dst.len()); + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()); + } +} + +#[cfg(test)] +mod tests; +use super::super::navigate; +use super::*; +use crate::fmt::Debug; +use crate::string::String; + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + // Asserts that the back pointer in each reachable node points to its parent. + pub fn assert_back_pointers(self) { + if let ForceResult::Internal(node) = self.force() { + for idx in 0..=node.len() { + let edge = unsafe { Handle::new_edge(node, idx) }; + let child = edge.descend(); + assert!(child.ascend().ok() == Some(edge)); + child.assert_back_pointers(); + } + } + } + + // Renders a multi-line display of the keys in order and in tree hierarchy, + // picturing the tree growing sideways from its root on the left to its + // leaves on the right. + pub fn dump_keys(self) -> String + where + K: Debug, + { + let mut result = String::new(); + self.visit_nodes_in_order(|pos| match pos { + navigate::Position::Leaf(leaf) => { + let depth = self.height(); + let indent = " ".repeat(depth); + result += &format!("\n{}{:?}", indent, leaf.keys()); + } + navigate::Position::Internal(_) => {} + navigate::Position::InternalKV(kv) => { + let depth = self.height() - kv.into_node().height(); + let indent = " ".repeat(depth); + result += &format!("\n{}{:?}", indent, kv.into_kv().0); + } + }); + result + } +} + +#[test] +fn test_splitpoint() { + for idx in 0..=CAPACITY { + let (middle_kv_idx, insertion) = splitpoint(idx); + + // Simulate performing the split: + let mut left_len = middle_kv_idx; + let mut right_len = CAPACITY - middle_kv_idx - 1; + match insertion { + LeftOrRight::Left(edge_idx) => { + assert!(edge_idx <= left_len); + left_len += 1; + } + LeftOrRight::Right(edge_idx) => { + assert!(edge_idx <= right_len); + right_len += 1; + } + } + assert!(left_len >= MIN_LEN_AFTER_SPLIT); + assert!(right_len >= MIN_LEN_AFTER_SPLIT); + assert!(left_len + right_len == CAPACITY); + } +} + +#[test] +fn test_partial_eq() { + let mut root1 = NodeRef::new_leaf(); + root1.borrow_mut().push(1, ()); + let mut root1 = NodeRef::new_internal(root1.forget_type()).forget_type(); + let root2 = Root::new(); + root1.reborrow().assert_back_pointers(); + root2.reborrow().assert_back_pointers(); + + let leaf_edge_1a = root1.reborrow().first_leaf_edge().forget_node_type(); + let leaf_edge_1b = root1.reborrow().last_leaf_edge().forget_node_type(); + let top_edge_1 = root1.reborrow().first_edge(); + let top_edge_2 = root2.reborrow().first_edge(); + + assert!(leaf_edge_1a == leaf_edge_1a); + assert!(leaf_edge_1a != leaf_edge_1b); + assert!(leaf_edge_1a != top_edge_1); + assert!(leaf_edge_1a != top_edge_2); + assert!(top_edge_1 == top_edge_1); + assert!(top_edge_1 != top_edge_2); + + root1.pop_internal_level(); + unsafe { root1.into_dying().deallocate_and_ascend() }; + unsafe { root2.into_dying().deallocate_and_ascend() }; +} + +#[test] +#[cfg(target_arch = "x86_64")] +fn test_sizes() { + assert_eq!(core::mem::size_of::>(), 16); + assert_eq!(core::mem::size_of::>(), 16 + CAPACITY * 2 * 8); + assert_eq!(core::mem::size_of::>(), 16 + (CAPACITY + 1) * 8); + assert_eq!(core::mem::size_of::>(), 16 + (CAPACITY * 3 + 1) * 8); +} +use super::map::MIN_LEN; +use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef, Root}; + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Stocks up a possibly underfull node by merging with or stealing from a + /// sibling. If succesful but at the cost of shrinking the parent node, + /// returns that shrunk parent node. Returns an `Err` if the node is + /// an empty root. + fn fix_node_through_parent( + self, + ) -> Result, K, V, marker::Internal>>, Self> { + let len = self.len(); + if len >= MIN_LEN { + Ok(None) + } else { + match self.choose_parent_kv() { + Ok(Left(mut left_parent_kv)) => { + if left_parent_kv.can_merge() { + let parent = left_parent_kv.merge_tracking_parent(); + Ok(Some(parent)) + } else { + left_parent_kv.bulk_steal_left(MIN_LEN - len); + Ok(None) + } + } + Ok(Right(mut right_parent_kv)) => { + if right_parent_kv.can_merge() { + let parent = right_parent_kv.merge_tracking_parent(); + Ok(Some(parent)) + } else { + right_parent_kv.bulk_steal_right(MIN_LEN - len); + Ok(None) + } + } + Err(root) => { + if len > 0 { + Ok(None) + } else { + Err(root) + } + } + } + } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { + /// Stocks up a possibly underfull node, and if that causes its parent node + /// to shrink, stocks up the parent, recursively. + /// Returns `true` if it fixed the tree, `false` if it couldn't because the + /// root node became empty. + /// + /// This method does not expect ancestors to already be underfull upon entry + /// and panics if it encounters an empty ancestor. + pub fn fix_node_and_affected_ancestors(mut self) -> bool { + loop { + match self.fix_node_through_parent() { + Ok(Some(parent)) => self = parent.forget_type(), + Ok(None) => return true, + Err(_) => return false, + } + } + } +} + +impl Root { + /// Removes empty levels on the top, but keeps an empty leaf if the entire tree is empty. + pub fn fix_top(&mut self) { + while self.height() > 0 && self.len() == 0 { + self.pop_internal_level(); + } + } + + /// Stocks up or merge away any underfull nodes on the right border of the + /// tree. The other nodes, those that are not the root nor a rightmost edge, + /// must already have at least MIN_LEN elements. + pub fn fix_right_border(&mut self) { + self.fix_top(); + if self.len() > 0 { + self.borrow_mut().last_kv().fix_right_border_of_right_edge(); + self.fix_top(); + } + } + + /// The symmetric clone of `fix_right_border`. + pub fn fix_left_border(&mut self) { + self.fix_top(); + if self.len() > 0 { + self.borrow_mut().first_kv().fix_left_border_of_left_edge(); + self.fix_top(); + } + } + + /// Stock up any underfull nodes on the right border of the tree. + /// The other nodes, those that are not the root nor a rightmost edge, + /// must be prepared to have up to MIN_LEN elements stolen. + pub fn fix_right_border_of_plentiful(&mut self) { + let mut cur_node = self.borrow_mut(); + while let Internal(internal) = cur_node.force() { + // Check if right-most child is underfull. + let mut last_kv = internal.last_kv().consider_for_balancing(); + debug_assert!(last_kv.left_child_len() >= MIN_LEN * 2); + let right_child_len = last_kv.right_child_len(); + if right_child_len < MIN_LEN { + // We need to steal. + last_kv.bulk_steal_left(MIN_LEN - right_child_len); + } + + // Go further down. + cur_node = last_kv.into_right_child(); + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { + fn fix_left_border_of_left_edge(mut self) { + while let Internal(internal_kv) = self.force() { + self = internal_kv.fix_left_child().first_kv(); + debug_assert!(self.reborrow().into_node().len() > MIN_LEN); + } + } + + fn fix_right_border_of_right_edge(mut self) { + while let Internal(internal_kv) = self.force() { + self = internal_kv.fix_right_child().last_kv(); + debug_assert!(self.reborrow().into_node().len() > MIN_LEN); + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, marker::KV> { + /// Stocks up the left child, assuming the right child isn't underfull, and + /// provisions an extra element to allow merging its children in turn + /// without becoming underfull. + /// Returns the left child. + fn fix_left_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + let mut internal_kv = self.consider_for_balancing(); + let left_len = internal_kv.left_child_len(); + debug_assert!(internal_kv.right_child_len() >= MIN_LEN); + if internal_kv.can_merge() { + internal_kv.merge_tracking_child() + } else { + // `MIN_LEN + 1` to avoid readjust if merge happens on the next level. + let count = (MIN_LEN + 1).saturating_sub(left_len); + if count > 0 { + internal_kv.bulk_steal_right(count); + } + internal_kv.into_left_child() + } + } + + /// Stocks up the right child, assuming the left child isn't underfull, and + /// provisions an extra element to allow merging its children in turn + /// without becoming underfull. + /// Returns wherever the right child ended up. + fn fix_right_child(self) -> NodeRef, K, V, marker::LeafOrInternal> { + let mut internal_kv = self.consider_for_balancing(); + let right_len = internal_kv.right_child_len(); + debug_assert!(internal_kv.left_child_len() >= MIN_LEN); + if internal_kv.can_merge() { + internal_kv.merge_tracking_child() + } else { + // `MIN_LEN + 1` to avoid readjust if merge happens on the next level. + let count = (MIN_LEN + 1).saturating_sub(right_len); + if count > 0 { + internal_kv.bulk_steal_left(count); + } + internal_kv.into_right_child() + } + } +} +//! Collection types. + +#![stable(feature = "rust1", since = "1.0.0")] + +pub mod binary_heap; +mod btree; +pub mod linked_list; +pub mod vec_deque; + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_map { + //! A map based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::btree::map::*; +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_set { + //! A set based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::btree::set::*; +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use binary_heap::BinaryHeap; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use btree_map::BTreeMap; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use btree_set::BTreeSet; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use linked_list::LinkedList; + +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use vec_deque::VecDeque; + +use crate::alloc::{Layout, LayoutError}; +use core::fmt::Display; + +/// The error type for `try_reserve` methods. +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +pub enum TryReserveError { + /// Error due to the computed capacity exceeding the collection's maximum + /// (usually `isize::MAX` bytes). + CapacityOverflow, + + /// The memory allocator returned an error + AllocError { + /// The layout of allocation request that failed + layout: Layout, + + #[doc(hidden)] + #[unstable( + feature = "container_error_extra", + issue = "none", + reason = "\ + Enable exposing the allocator’s custom error value \ + if an associated type is added in the future: \ + https://github.com/rust-lang/wg-allocators/issues/23" + )] + non_exhaustive: (), + }, +} + +#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +impl From for TryReserveError { + #[inline] + fn from(_: LayoutError) -> Self { + TryReserveError::CapacityOverflow + } +} + +#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +impl Display for TryReserveError { + fn fmt( + &self, + fmt: &mut core::fmt::Formatter<'_>, + ) -> core::result::Result<(), core::fmt::Error> { + fmt.write_str("memory allocation failed")?; + let reason = match &self { + TryReserveError::CapacityOverflow => { + " because the computed capacity exceeded the collection's maximum" + } + TryReserveError::AllocError { .. } => " because the memory allocator returned a error", + }; + fmt.write_str(reason) + } +} + +/// An intermediate trait for specialization of `Extend`. +#[doc(hidden)] +trait SpecExtend { + /// Extends `self` with the contents of the given iterator. + fn spec_extend(&mut self, iter: I); +} +use core::fmt; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; + +use super::VecDeque; + +/// An owning iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`into_iter`] method on [`VecDeque`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: VecDeque::into_iter +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter { + pub(crate) inner: VecDeque, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.inner).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.inner.len(); + (len, Some(len)) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even + // multiple repeated reads of the same index would be safe and the + // values are !Drop, thus won't suffer from double drops. + unsafe { + let idx = self.inner.wrap_add(self.inner.tail, idx); + self.inner.buffer_read(idx) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.pop_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.inner.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +// T: Copy as approximation for !Drop since get_unchecked does not update the pointers +// and thus we can't implement drop-handling +unsafe impl TrustedRandomAccess for IntoIter +where + T: Copy, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { + #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] + impl PartialEq<$rhs> for $lhs + where + A: PartialEq, + $($constraints)* + { + fn eq(&self, other: &$rhs) -> bool { + if self.len() != other.len() { + return false; + } + let (sa, sb) = self.as_slices(); + let (oa, ob) = other[..].split_at(sa.len()); + sa == oa && sb == ob + } + } + } +} +use core::iter::FusedIterator; +use core::ptr::{self, NonNull}; +use core::{fmt, mem}; + +use super::{count, Iter, VecDeque}; + +/// A draining iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its +/// documentation for more. +/// +/// [`drain`]: VecDeque::drain +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain<'a, T: 'a> { + pub(crate) after_tail: usize, + pub(crate) after_head: usize, + pub(crate) iter: Iter<'a, T>, + pub(crate) deque: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain") + .field(&self.after_tail) + .field(&self.after_head) + .field(&self.iter) + .finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T> { + fn drop(&mut self) { + struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); + + impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { + fn drop(&mut self) { + self.0.for_each(drop); + + let source_deque = unsafe { self.0.deque.as_mut() }; + + // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head + // + // T t h H + // [. . . o o x x o o . . .] + // + let orig_tail = source_deque.tail; + let drain_tail = source_deque.head; + let drain_head = self.0.after_tail; + let orig_head = self.0.after_head; + + let tail_len = count(orig_tail, drain_tail, source_deque.cap()); + let head_len = count(drain_head, orig_head, source_deque.cap()); + + // Restore the original head value + source_deque.head = orig_head; + + match (tail_len, head_len) { + (0, 0) => { + source_deque.head = 0; + source_deque.tail = 0; + } + (0, _) => { + source_deque.tail = drain_head; + } + (_, 0) => { + source_deque.head = drain_tail; + } + _ => unsafe { + if tail_len <= head_len { + source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); + source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); + } else { + source_deque.head = source_deque.wrap_add(drain_tail, head_len); + source_deque.wrap_copy(drain_tail, drain_head, head_len); + } + }, + } + } + } + + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt) }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T> {} +use core::ptr::{self}; + +/// Returns the two slices that cover the `VecDeque`'s valid range +pub trait RingSlices: Sized { + fn slice(self, from: usize, to: usize) -> Self; + fn split_at(self, i: usize) -> (Self, Self); + + fn ring_slices(buf: Self, head: usize, tail: usize) -> (Self, Self) { + let contiguous = tail <= head; + if contiguous { + let (empty, buf) = buf.split_at(0); + (buf.slice(tail, head), empty) + } else { + let (mid, right) = buf.split_at(tail); + let (left, _) = mid.split_at(head); + (right, left) + } + } +} + +impl RingSlices for &[T] { + fn slice(self, from: usize, to: usize) -> Self { + &self[from..to] + } + fn split_at(self, i: usize) -> (Self, Self) { + (*self).split_at(i) + } +} + +impl RingSlices for &mut [T] { + fn slice(self, from: usize, to: usize) -> Self { + &mut self[from..to] + } + fn split_at(self, i: usize) -> (Self, Self) { + (*self).split_at_mut(i) + } +} + +impl RingSlices for *mut [T] { + fn slice(self, from: usize, to: usize) -> Self { + assert!(from <= to && to < self.len()); + // Not using `get_unchecked_mut` to keep this a safe operation. + let len = to - from; + ptr::slice_from_raw_parts_mut(self.as_mut_ptr().wrapping_add(from), len) + } + + fn split_at(self, mid: usize) -> (Self, Self) { + let len = self.len(); + let ptr = self.as_mut_ptr(); + assert!(mid <= len); + ( + ptr::slice_from_raw_parts_mut(ptr, mid), + ptr::slice_from_raw_parts_mut(ptr.wrapping_add(mid), len - mid), + ) + } +} +use core::array; +use core::cmp::{self}; +use core::mem::replace; + +use super::VecDeque; + +/// PairSlices pairs up equal length slice parts of two deques +/// +/// For example, given deques "A" and "B" with the following division into slices: +/// +/// A: [0 1 2] [3 4 5] +/// B: [a b] [c d e] +/// +/// It produces the following sequence of matching slices: +/// +/// ([0 1], [a b]) +/// (\[2\], \[c\]) +/// ([3 4], [d e]) +/// +/// and the uneven remainder of either A or B is skipped. +pub struct PairSlices<'a, 'b, T> { + pub(crate) a0: &'a mut [T], + pub(crate) a1: &'a mut [T], + pub(crate) b0: &'b [T], + pub(crate) b1: &'b [T], +} + +impl<'a, 'b, T> PairSlices<'a, 'b, T> { + pub fn from(to: &'a mut VecDeque, from: &'b VecDeque) -> Self { + let (a0, a1) = to.as_mut_slices(); + let (b0, b1) = from.as_slices(); + PairSlices { a0, a1, b0, b1 } + } + + pub fn has_remainder(&self) -> bool { + !self.b0.is_empty() + } + + pub fn remainder(self) -> impl Iterator { + array::IntoIter::new([self.b0, self.b1]) + } +} + +impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T> { + type Item = (&'a mut [T], &'b [T]); + fn next(&mut self) -> Option { + // Get next part length + let part = cmp::min(self.a0.len(), self.b0.len()); + if part == 0 { + return None; + } + let (p0, p1) = replace(&mut self.a0, &mut []).split_at_mut(part); + let (q0, q1) = self.b0.split_at(part); + + // Move a1 into a0, if it's empty (and b1, b0 the same way). + self.a0 = p1; + self.b0 = q1; + if self.a0.is_empty() { + self.a0 = replace(&mut self.a1, &mut []); + } + if self.b0.is_empty() { + self.b0 = replace(&mut self.b1, &[]); + } + Some((p0, q0)) + } +} +//! A double-ended queue implemented with a growable ring buffer. +//! +//! This queue has *O*(1) amortized inserts and removals from both ends of the +//! container. It also has *O*(1) indexing like a vector. The contained elements +//! are not required to be copyable, and the queue will be sendable if the +//! contained type is sendable. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::{self, Ordering}; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::iter::{repeat_with, FromIterator}; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop}; +use core::ops::{Index, IndexMut, Range, RangeBounds}; +use core::ptr::{self, NonNull}; +use core::slice; + +use crate::collections::TryReserveError; +use crate::raw_vec::RawVec; +use crate::vec::Vec; + +#[macro_use] +mod macros; + +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::iter_mut::IterMut; + +mod iter_mut; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::into_iter::IntoIter; + +mod into_iter; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::iter::Iter; + +mod iter; + +use self::pair_slices::PairSlices; + +mod pair_slices; + +use self::ring_slices::RingSlices; + +mod ring_slices; + +#[cfg(test)] +mod tests; + +const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 +const MINIMUM_CAPACITY: usize = 1; // 2 - 1 + +const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two + +/// A double-ended queue implemented with a growable ring buffer. +/// +/// The "default" usage of this type as a queue is to use [`push_back`] to add to +/// the queue, and [`pop_front`] to remove from the queue. [`extend`] and [`append`] +/// push onto the back in this manner, and iterating over `VecDeque` goes front +/// to back. +/// +/// Since `VecDeque` is a ring buffer, its elements are not necessarily contiguous +/// in memory. If you want to access the elements as a single slice, such as for +/// efficient sorting, you can use [`make_contiguous`]. It rotates the `VecDeque` +/// so that its elements do not wrap, and returns a mutable slice to the +/// now-contiguous element sequence. +/// +/// [`push_back`]: VecDeque::push_back +/// [`pop_front`]: VecDeque::pop_front +/// [`extend`]: VecDeque::extend +/// [`append`]: VecDeque::append +/// [`make_contiguous`]: VecDeque::make_contiguous +#[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct VecDeque { + // tail and head are pointers into the buffer. Tail always points + // to the first element that could be read, Head always points + // to where data should be written. + // If tail == head the buffer is empty. The length of the ringbuffer + // is defined as the distance between the two. + tail: usize, + head: usize, + buf: RawVec, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for VecDeque { + fn clone(&self) -> VecDeque { + self.iter().cloned().collect() + } + + fn clone_from(&mut self, other: &Self) { + self.truncate(other.len()); + + let mut iter = PairSlices::from(self, other); + while let Some((dst, src)) = iter.next() { + dst.clone_from_slice(&src); + } + + if iter.has_remainder() { + for remainder in iter.remainder() { + self.extend(remainder.iter().cloned()); + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T> Drop for VecDeque { + fn drop(&mut self) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + + let (front, back) = self.as_mut_slices(); + unsafe { + let _back_dropper = Dropper(back); + // use drop for [T] + ptr::drop_in_place(front); + } + // RawVec handles deallocation + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for VecDeque { + /// Creates an empty `VecDeque`. + #[inline] + fn default() -> VecDeque { + VecDeque::new() + } +} + +impl VecDeque { + /// Marginally more convenient + #[inline] + fn ptr(&self) -> *mut T { + self.buf.ptr() + } + + /// Marginally more convenient + #[inline] + fn cap(&self) -> usize { + if mem::size_of::() == 0 { + // For zero sized types, we are always at maximum capacity + MAXIMUM_ZST_CAPACITY + } else { + self.buf.capacity() + } + } + + /// Turn ptr into a slice + #[inline] + unsafe fn buffer_as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr(), self.cap()) } + } + + /// Turn ptr into a mut slice + #[inline] + unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.ptr(), self.cap()) } + } + + /// Moves an element out of the buffer + #[inline] + unsafe fn buffer_read(&mut self, off: usize) -> T { + unsafe { ptr::read(self.ptr().add(off)) } + } + + /// Writes an element into the buffer, moving it. + #[inline] + unsafe fn buffer_write(&mut self, off: usize, value: T) { + unsafe { + ptr::write(self.ptr().add(off), value); + } + } + + /// Returns `true` if the buffer is at full capacity. + #[inline] + fn is_full(&self) -> bool { + self.cap() - self.len() == 1 + } + + /// Returns the index in the underlying buffer for a given logical element + /// index. + #[inline] + fn wrap_index(&self, idx: usize) -> usize { + wrap_index(idx, self.cap()) + } + + /// Returns the index in the underlying buffer for a given logical element + /// index + addend. + #[inline] + fn wrap_add(&self, idx: usize, addend: usize) -> usize { + wrap_index(idx.wrapping_add(addend), self.cap()) + } + + /// Returns the index in the underlying buffer for a given logical element + /// index - subtrahend. + #[inline] + fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize { + wrap_index(idx.wrapping_sub(subtrahend), self.cap()) + } + + /// Copies a contiguous block of memory len long from src to dst + #[inline] + unsafe fn copy(&self, dst: usize, src: usize, len: usize) { + debug_assert!( + dst + len <= self.cap(), + "cpy dst={} src={} len={} cap={}", + dst, + src, + len, + self.cap() + ); + debug_assert!( + src + len <= self.cap(), + "cpy dst={} src={} len={} cap={}", + dst, + src, + len, + self.cap() + ); + unsafe { + ptr::copy(self.ptr().add(src), self.ptr().add(dst), len); + } + } + + /// Copies a contiguous block of memory len long from src to dst + #[inline] + unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) { + debug_assert!( + dst + len <= self.cap(), + "cno dst={} src={} len={} cap={}", + dst, + src, + len, + self.cap() + ); + debug_assert!( + src + len <= self.cap(), + "cno dst={} src={} len={} cap={}", + dst, + src, + len, + self.cap() + ); + unsafe { + ptr::copy_nonoverlapping(self.ptr().add(src), self.ptr().add(dst), len); + } + } + + /// Copies a potentially wrapping block of memory len long from src to dest. + /// (abs(dst - src) + len) must be no larger than cap() (There must be at + /// most one continuous overlapping region between src and dest). + unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) { + #[allow(dead_code)] + fn diff(a: usize, b: usize) -> usize { + if a <= b { b - a } else { a - b } + } + debug_assert!( + cmp::min(diff(dst, src), self.cap() - diff(dst, src)) + len <= self.cap(), + "wrc dst={} src={} len={} cap={}", + dst, + src, + len, + self.cap() + ); + + if src == dst || len == 0 { + return; + } + + let dst_after_src = self.wrap_sub(dst, src) < len; + + let src_pre_wrap_len = self.cap() - src; + let dst_pre_wrap_len = self.cap() - dst; + let src_wraps = src_pre_wrap_len < len; + let dst_wraps = dst_pre_wrap_len < len; + + match (dst_after_src, src_wraps, dst_wraps) { + (_, false, false) => { + // src doesn't wrap, dst doesn't wrap + // + // S . . . + // 1 [_ _ A A B B C C _] + // 2 [_ _ A A A A B B _] + // D . . . + // + unsafe { + self.copy(dst, src, len); + } + } + (false, false, true) => { + // dst before src, src doesn't wrap, dst wraps + // + // S . . . + // 1 [A A B B _ _ _ C C] + // 2 [A A B B _ _ _ A A] + // 3 [B B B B _ _ _ A A] + // . . D . + // + unsafe { + self.copy(dst, src, dst_pre_wrap_len); + self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); + } + } + (true, false, true) => { + // src before dst, src doesn't wrap, dst wraps + // + // S . . . + // 1 [C C _ _ _ A A B B] + // 2 [B B _ _ _ A A B B] + // 3 [B B _ _ _ A A A A] + // . . D . + // + unsafe { + self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len); + self.copy(dst, src, dst_pre_wrap_len); + } + } + (false, true, false) => { + // dst before src, src wraps, dst doesn't wrap + // + // . . S . + // 1 [C C _ _ _ A A B B] + // 2 [C C _ _ _ B B B B] + // 3 [C C _ _ _ B B C C] + // D . . . + // + unsafe { + self.copy(dst, src, src_pre_wrap_len); + self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); + } + } + (true, true, false) => { + // src before dst, src wraps, dst doesn't wrap + // + // . . S . + // 1 [A A B B _ _ _ C C] + // 2 [A A A A _ _ _ C C] + // 3 [C C A A _ _ _ C C] + // D . . . + // + unsafe { + self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len); + self.copy(dst, src, src_pre_wrap_len); + } + } + (false, true, true) => { + // dst before src, src wraps, dst wraps + // + // . . . S . + // 1 [A B C D _ E F G H] + // 2 [A B C D _ E G H H] + // 3 [A B C D _ E G H A] + // 4 [B C C D _ E G H A] + // . . D . . + // + debug_assert!(dst_pre_wrap_len > src_pre_wrap_len); + let delta = dst_pre_wrap_len - src_pre_wrap_len; + unsafe { + self.copy(dst, src, src_pre_wrap_len); + self.copy(dst + src_pre_wrap_len, 0, delta); + self.copy(0, delta, len - dst_pre_wrap_len); + } + } + (true, true, true) => { + // src before dst, src wraps, dst wraps + // + // . . S . . + // 1 [A B C D _ E F G H] + // 2 [A A B D _ E F G H] + // 3 [H A B D _ E F G H] + // 4 [H A B D _ E F F G] + // . . . D . + // + debug_assert!(src_pre_wrap_len > dst_pre_wrap_len); + let delta = src_pre_wrap_len - dst_pre_wrap_len; + unsafe { + self.copy(delta, 0, len - src_pre_wrap_len); + self.copy(0, self.cap() - delta, delta); + self.copy(dst, src, dst_pre_wrap_len); + } + } + } + } + + /// Frobs the head and tail sections around to handle the fact that we + /// just reallocated. Unsafe because it trusts old_capacity. + #[inline] + unsafe fn handle_capacity_increase(&mut self, old_capacity: usize) { + let new_capacity = self.cap(); + + // Move the shortest contiguous section of the ring buffer + // T H + // [o o o o o o o . ] + // T H + // A [o o o o o o o . . . . . . . . . ] + // H T + // [o o . o o o o o ] + // T H + // B [. . . o o o o o o o . . . . . . ] + // H T + // [o o o o o . o o ] + // H T + // C [o o o o o . . . . . . . . . o o ] + + if self.tail <= self.head { + // A + // Nop + } else if self.head < old_capacity - self.tail { + // B + unsafe { + self.copy_nonoverlapping(old_capacity, 0, self.head); + } + self.head += old_capacity; + debug_assert!(self.head > self.tail); + } else { + // C + let new_tail = new_capacity - (old_capacity - self.tail); + unsafe { + self.copy_nonoverlapping(new_tail, self.tail, old_capacity - self.tail); + } + self.tail = new_tail; + debug_assert!(self.head < self.tail); + } + debug_assert!(self.head < self.cap()); + debug_assert!(self.tail < self.cap()); + debug_assert!(self.cap().count_ones() == 1); + } +} + +impl VecDeque { + /// Creates an empty `VecDeque`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let vector: VecDeque = VecDeque::new(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> VecDeque { + VecDeque::with_capacity(INITIAL_CAPACITY) + } + + /// Creates an empty `VecDeque` with space for at least `capacity` elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let vector: VecDeque = VecDeque::with_capacity(10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> VecDeque { + // +1 since the ringbuffer always leaves one space empty + let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + assert!(cap > capacity, "capacity overflow"); + + VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity(cap) } + } + + /// Provides a reference to the element at the given index. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(3); + /// buf.push_back(4); + /// buf.push_back(5); + /// assert_eq!(buf.get(1), Some(&4)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self, index: usize) -> Option<&T> { + if index < self.len() { + let idx = self.wrap_add(self.tail, index); + unsafe { Some(&*self.ptr().add(idx)) } + } else { + None + } + } + + /// Provides a mutable reference to the element at the given index. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(3); + /// buf.push_back(4); + /// buf.push_back(5); + /// if let Some(elem) = buf.get_mut(1) { + /// *elem = 7; + /// } + /// + /// assert_eq!(buf[1], 7); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + if index < self.len() { + let idx = self.wrap_add(self.tail, index); + unsafe { Some(&mut *self.ptr().add(idx)) } + } else { + None + } + } + + /// Swaps elements at indices `i` and `j`. + /// + /// `i` and `j` may be equal. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if either index is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(3); + /// buf.push_back(4); + /// buf.push_back(5); + /// assert_eq!(buf, [3, 4, 5]); + /// buf.swap(0, 2); + /// assert_eq!(buf, [5, 4, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn swap(&mut self, i: usize, j: usize) { + assert!(i < self.len()); + assert!(j < self.len()); + let ri = self.wrap_add(self.tail, i); + let rj = self.wrap_add(self.tail, j); + unsafe { ptr::swap(self.ptr().add(ri), self.ptr().add(rj)) } + } + + /// Returns the number of elements the `VecDeque` can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let buf: VecDeque = VecDeque::with_capacity(10); + /// assert!(buf.capacity() >= 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.cap() - 1 + } + + /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the + /// given `VecDeque`. Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it requests. Therefore + /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future + /// insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque = vec![1].into_iter().collect(); + /// buf.reserve_exact(10); + /// assert!(buf.capacity() >= 11); + /// ``` + /// + /// [`reserve`]: VecDeque::reserve + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.reserve(additional); + } + + /// Reserves capacity for at least `additional` more elements to be inserted in the given + /// `VecDeque`. The collection may reserve more space to avoid frequent reallocations. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque = vec![1].into_iter().collect(); + /// buf.reserve(10); + /// assert!(buf.capacity() >= 11); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + let old_cap = self.cap(); + let used_cap = self.len() + 1; + let new_cap = used_cap + .checked_add(additional) + .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) + .expect("capacity overflow"); + + if new_cap > old_cap { + self.buf.reserve_exact(used_cap, new_cap - used_cap); + unsafe { + self.handle_capacity_increase(old_cap); + } + } + } + + /// Tries to reserve the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `VecDeque`. After calling `try_reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows `usize`, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// use std::collections::VecDeque; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = VecDeque::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM(Out-Of-Memory) in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.try_reserve(additional) + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `VecDeque`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows `usize`, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// use std::collections::VecDeque; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = VecDeque::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + let old_cap = self.cap(); + let used_cap = self.len() + 1; + let new_cap = used_cap + .checked_add(additional) + .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) + .ok_or(TryReserveError::CapacityOverflow)?; + + if new_cap > old_cap { + self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; + unsafe { + self.handle_capacity_increase(old_cap); + } + } + Ok(()) + } + + /// Shrinks the capacity of the `VecDeque` as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator may still inform the + /// `VecDeque` that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to_fit(); + /// assert!(buf.capacity() >= 4); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn shrink_to_fit(&mut self) { + self.shrink_to(0); + } + + /// Shrinks the capacity of the `VecDeque` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to(6); + /// assert!(buf.capacity() >= 6); + /// buf.shrink_to(0); + /// assert!(buf.capacity() >= 4); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] + pub fn shrink_to(&mut self, min_capacity: usize) { + let min_capacity = cmp::min(min_capacity, self.capacity()); + // We don't have to worry about an overflow as neither `self.len()` nor `self.capacity()` + // can ever be `usize::MAX`. +1 as the ringbuffer always leaves one space empty. + let target_cap = cmp::max(cmp::max(min_capacity, self.len()) + 1, MINIMUM_CAPACITY + 1) + .next_power_of_two(); + + if target_cap < self.cap() { + // There are three cases of interest: + // All elements are out of desired bounds + // Elements are contiguous, and head is out of desired bounds + // Elements are discontiguous, and tail is out of desired bounds + // + // At all other times, element positions are unaffected. + // + // Indicates that elements at the head should be moved. + let head_outside = self.head == 0 || self.head >= target_cap; + // Move elements from out of desired bounds (positions after target_cap) + if self.tail >= target_cap && head_outside { + // T H + // [. . . . . . . . o o o o o o o . ] + // T H + // [o o o o o o o . ] + unsafe { + self.copy_nonoverlapping(0, self.tail, self.len()); + } + self.head = self.len(); + self.tail = 0; + } else if self.tail != 0 && self.tail < target_cap && head_outside { + // T H + // [. . . o o o o o o o . . . . . . ] + // H T + // [o o . o o o o o ] + let len = self.wrap_sub(self.head, target_cap); + unsafe { + self.copy_nonoverlapping(0, target_cap, len); + } + self.head = len; + debug_assert!(self.head < self.tail); + } else if self.tail >= target_cap { + // H T + // [o o o o o . . . . . . . . . o o ] + // H T + // [o o o o o . o o ] + debug_assert!(self.wrap_sub(self.head, 1) < target_cap); + let len = self.cap() - self.tail; + let new_tail = target_cap - len; + unsafe { + self.copy_nonoverlapping(new_tail, self.tail, len); + } + self.tail = new_tail; + debug_assert!(self.head < self.tail); + } + + self.buf.shrink_to_fit(target_cap); + + debug_assert!(self.head < self.cap()); + debug_assert!(self.tail < self.cap()); + debug_assert!(self.cap().count_ones() == 1); + } + } + + /// Shortens the `VecDeque`, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the `VecDeque`'s current length, this has no + /// effect. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// buf.truncate(1); + /// assert_eq!(buf, [5]); + /// ``` + #[stable(feature = "deque_extras", since = "1.16.0")] + pub fn truncate(&mut self, len: usize) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + + // Safe because: + // + // * Any slice passed to `drop_in_place` is valid; the second case has + // `len <= front.len()` and returning on `len > self.len()` ensures + // `begin <= back.len()` in the first case + // * The head of the VecDeque is moved before calling `drop_in_place`, + // so no value is dropped twice if `drop_in_place` panics + unsafe { + if len > self.len() { + return; + } + let num_dropped = self.len() - len; + let (front, back) = self.as_mut_slices(); + if len > front.len() { + let begin = len - front.len(); + let drop_back = back.get_unchecked_mut(begin..) as *mut _; + self.head = self.wrap_sub(self.head, num_dropped); + ptr::drop_in_place(drop_back); + } else { + let drop_back = back as *mut _; + let drop_front = front.get_unchecked_mut(len..) as *mut _; + self.head = self.wrap_sub(self.head, num_dropped); + + // Make sure the second half is dropped even when a destructor + // in the first one panics. + let _back_dropper = Dropper(&mut *drop_back); + ptr::drop_in_place(drop_front); + } + } + } + + /// Returns a front-to-back iterator. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(3); + /// buf.push_back(4); + /// let b: &[_] = &[&5, &3, &4]; + /// let c: Vec<&i32> = buf.iter().collect(); + /// assert_eq!(&c[..], b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { tail: self.tail, head: self.head, ring: unsafe { self.buffer_as_slice() } } + } + + /// Returns a front-to-back iterator that returns mutable references. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(3); + /// buf.push_back(4); + /// for num in buf.iter_mut() { + /// *num = *num - 2; + /// } + /// let b: &[_] = &[&mut 3, &mut 1, &mut 2]; + /// assert_eq!(&buf.iter_mut().collect::>()[..], b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut<'_, T> { + // SAFETY: The internal `IterMut` safety invariant is established because the + // `ring` we create is a dereferencable slice for lifetime '_. + IterMut { + tail: self.tail, + head: self.head, + ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()), + phantom: PhantomData, + } + } + + /// Returns a pair of slices which contain, in order, the contents of the + /// `VecDeque`. + /// + /// If [`make_contiguous`] was previously called, all elements of the + /// `VecDeque` will be in the first slice and the second slice will be empty. + /// + /// [`make_contiguous`]: VecDeque::make_contiguous + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut vector = VecDeque::new(); + /// + /// vector.push_back(0); + /// vector.push_back(1); + /// vector.push_back(2); + /// + /// assert_eq!(vector.as_slices(), (&[0, 1, 2][..], &[][..])); + /// + /// vector.push_front(10); + /// vector.push_front(9); + /// + /// assert_eq!(vector.as_slices(), (&[9, 10][..], &[0, 1, 2][..])); + /// ``` + #[inline] + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn as_slices(&self) -> (&[T], &[T]) { + unsafe { + let buf = self.buffer_as_slice(); + RingSlices::ring_slices(buf, self.head, self.tail) + } + } + + /// Returns a pair of slices which contain, in order, the contents of the + /// `VecDeque`. + /// + /// If [`make_contiguous`] was previously called, all elements of the + /// `VecDeque` will be in the first slice and the second slice will be empty. + /// + /// [`make_contiguous`]: VecDeque::make_contiguous + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut vector = VecDeque::new(); + /// + /// vector.push_back(0); + /// vector.push_back(1); + /// + /// vector.push_front(10); + /// vector.push_front(9); + /// + /// vector.as_mut_slices().0[0] = 42; + /// vector.as_mut_slices().1[0] = 24; + /// assert_eq!(vector.as_slices(), (&[42, 10][..], &[24, 1][..])); + /// ``` + #[inline] + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) { + unsafe { + let head = self.head; + let tail = self.tail; + let buf = self.buffer_as_mut_slice(); + RingSlices::ring_slices(buf, head, tail) + } + } + + /// Returns the number of elements in the `VecDeque`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut v = VecDeque::new(); + /// assert_eq!(v.len(), 0); + /// v.push_back(1); + /// assert_eq!(v.len(), 1); + /// ``` + #[doc(alias = "length")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + count(self.tail, self.head, self.cap()) + } + + /// Returns `true` if the `VecDeque` is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut v = VecDeque::new(); + /// assert!(v.is_empty()); + /// v.push_front(1); + /// assert!(!v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.tail == self.head + } + + fn range_tail_head(&self, range: R) -> (usize, usize) + where + R: RangeBounds, + { + let Range { start, end } = slice::range(range, ..self.len()); + let tail = self.wrap_add(self.tail, start); + let head = self.wrap_add(self.tail, end); + (tail, head) + } + + /// Creates an iterator that covers the specified range in the `VecDeque`. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + /// let range = v.range(2..).copied().collect::>(); + /// assert_eq!(range, [3]); + /// + /// // A full range covers all contents + /// let all = v.range(..); + /// assert_eq!(all.len(), 3); + /// ``` + #[inline] + #[stable(feature = "deque_range", since = "1.51.0")] + pub fn range(&self, range: R) -> Iter<'_, T> + where + R: RangeBounds, + { + let (tail, head) = self.range_tail_head(range); + Iter { + tail, + head, + // The shared reference we have in &self is maintained in the '_ of Iter. + ring: unsafe { self.buffer_as_slice() }, + } + } + + /// Creates an iterator that covers the specified mutable range in the `VecDeque`. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + /// for v in v.range_mut(2..) { + /// *v *= 2; + /// } + /// assert_eq!(v, vec![1, 2, 6]); + /// + /// // A full range covers all contents + /// for v in v.range_mut(..) { + /// *v *= 2; + /// } + /// assert_eq!(v, vec![2, 4, 12]); + /// ``` + #[inline] + #[stable(feature = "deque_range", since = "1.51.0")] + pub fn range_mut(&mut self, range: R) -> IterMut<'_, T> + where + R: RangeBounds, + { + let (tail, head) = self.range_tail_head(range); + + // SAFETY: The internal `IterMut` safety invariant is established because the + // `ring` we create is a dereferencable slice for lifetime '_. + IterMut { + tail, + head, + ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()), + phantom: PhantomData, + } + } + + /// Creates a draining iterator that removes the specified range in the + /// `VecDeque` and yields the removed items. + /// + /// Note 1: The element range is removed even if the iterator is not + /// consumed until the end. + /// + /// Note 2: It is unspecified how many elements are removed from the deque, + /// if the `Drain` value is not dropped, but the borrow it holds expires + /// (e.g., due to `mem::forget`). + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + /// let drained = v.drain(2..).collect::>(); + /// assert_eq!(drained, [3]); + /// assert_eq!(v, [1, 2]); + /// + /// // A full range clears all contents + /// v.drain(..); + /// assert!(v.is_empty()); + /// ``` + #[inline] + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, T> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, the source deque is shortened to + // make sure no uninitialized or moved-from elements are accessible at + // all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, the remaining data will be copied back to cover the hole, + // and the head/tail values will be restored correctly. + // + let (drain_tail, drain_head) = self.range_tail_head(range); + + // The deque's elements are parted into three segments: + // * self.tail -> drain_tail + // * drain_tail -> drain_head + // * drain_head -> self.head + // + // T = self.tail; H = self.head; t = drain_tail; h = drain_head + // + // We store drain_tail as self.head, and drain_head and self.head as + // after_tail and after_head respectively on the Drain. This also + // truncates the effective array such that if the Drain is leaked, we + // have forgotten about the potentially moved values after the start of + // the drain. + // + // T t h H + // [. . . o o x x o o . . .] + // + let head = self.head; + + // "forget" about the values after the start of the drain until after + // the drain is complete and the Drain destructor is run. + self.head = drain_tail; + + Drain { + deque: NonNull::from(&mut *self), + after_tail: drain_head, + after_head: head, + iter: Iter { + tail: drain_tail, + head: drain_head, + // Crucially, we only create shared references from `self` here and read from + // it. We do not write to `self` nor reborrow to a mutable reference. + // Hence the raw pointer we created above, for `deque`, remains valid. + ring: unsafe { self.buffer_as_slice() }, + }, + } + } + + /// Clears the `VecDeque`, removing all values. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut v = VecDeque::new(); + /// v.push_back(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn clear(&mut self) { + self.truncate(0); + } + + /// Returns `true` if the `VecDeque` contains an element equal to the + /// given value. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut vector: VecDeque = VecDeque::new(); + /// + /// vector.push_back(0); + /// vector.push_back(1); + /// + /// assert_eq!(vector.contains(&1), true); + /// assert_eq!(vector.contains(&10), false); + /// ``` + #[stable(feature = "vec_deque_contains", since = "1.12.0")] + pub fn contains(&self, x: &T) -> bool + where + T: PartialEq, + { + let (a, b) = self.as_slices(); + a.contains(x) || b.contains(x) + } + + /// Provides a reference to the front element, or `None` if the `VecDeque` is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.front(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// assert_eq!(d.front(), Some(&1)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn front(&self) -> Option<&T> { + self.get(0) + } + + /// Provides a mutable reference to the front element, or `None` if the + /// `VecDeque` is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.front_mut(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// match d.front_mut() { + /// Some(x) => *x = 9, + /// None => (), + /// } + /// assert_eq!(d.front(), Some(&9)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn front_mut(&mut self) -> Option<&mut T> { + self.get_mut(0) + } + + /// Provides a reference to the back element, or `None` if the `VecDeque` is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.back(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// assert_eq!(d.back(), Some(&2)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back(&self) -> Option<&T> { + self.get(self.len().wrapping_sub(1)) + } + + /// Provides a mutable reference to the back element, or `None` if the + /// `VecDeque` is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// assert_eq!(d.back(), None); + /// + /// d.push_back(1); + /// d.push_back(2); + /// match d.back_mut() { + /// Some(x) => *x = 9, + /// None => (), + /// } + /// assert_eq!(d.back(), Some(&9)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn back_mut(&mut self) -> Option<&mut T> { + self.get_mut(self.len().wrapping_sub(1)) + } + + /// Removes the first element and returns it, or `None` if the `VecDeque` is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// d.push_back(1); + /// d.push_back(2); + /// + /// assert_eq!(d.pop_front(), Some(1)); + /// assert_eq!(d.pop_front(), Some(2)); + /// assert_eq!(d.pop_front(), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_front(&mut self) -> Option { + if self.is_empty() { + None + } else { + let tail = self.tail; + self.tail = self.wrap_add(self.tail, 1); + unsafe { Some(self.buffer_read(tail)) } + } + } + + /// Removes the last element from the `VecDeque` and returns it, or `None` if + /// it is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.pop_back(), None); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(buf.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option { + if self.is_empty() { + None + } else { + self.head = self.wrap_sub(self.head, 1); + let head = self.head; + unsafe { Some(self.buffer_read(head)) } + } + } + + /// Prepends an element to the `VecDeque`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut d = VecDeque::new(); + /// d.push_front(1); + /// d.push_front(2); + /// assert_eq!(d.front(), Some(&2)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_front(&mut self, value: T) { + if self.is_full() { + self.grow(); + } + + self.tail = self.wrap_sub(self.tail, 1); + let tail = self.tail; + unsafe { + self.buffer_write(tail, value); + } + } + + /// Appends an element to the back of the `VecDeque`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(3, *buf.back().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_back(&mut self, value: T) { + if self.is_full() { + self.grow(); + } + + let head = self.head; + self.head = self.wrap_add(self.head, 1); + unsafe { self.buffer_write(head, value) } + } + + #[inline] + fn is_contiguous(&self) -> bool { + // FIXME: Should we consider `head == 0` to mean + // that `self` is contiguous? + self.tail <= self.head + } + + /// Removes an element from anywhere in the `VecDeque` and returns it, + /// replacing it with the first element. + /// + /// This does not preserve ordering, but is *O*(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.swap_remove_front(0), None); + /// buf.push_back(1); + /// buf.push_back(2); + /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); + /// + /// assert_eq!(buf.swap_remove_front(2), Some(3)); + /// assert_eq!(buf, [2, 1]); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn swap_remove_front(&mut self, index: usize) -> Option { + let length = self.len(); + if length > 0 && index < length && index != 0 { + self.swap(index, 0); + } else if index >= length { + return None; + } + self.pop_front() + } + + /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the + /// last element. + /// + /// This does not preserve ordering, but is *O*(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.swap_remove_back(0), None); + /// buf.push_back(1); + /// buf.push_back(2); + /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); + /// + /// assert_eq!(buf.swap_remove_back(0), Some(1)); + /// assert_eq!(buf, [3, 2]); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn swap_remove_back(&mut self, index: usize) -> Option { + let length = self.len(); + if length > 0 && index < length - 1 { + self.swap(index, length - 1); + } else if index >= length { + return None; + } + self.pop_back() + } + + /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices + /// greater than or equal to `index` towards the back. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if `index` is greater than `VecDeque`'s length + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut vec_deque = VecDeque::new(); + /// vec_deque.push_back('a'); + /// vec_deque.push_back('b'); + /// vec_deque.push_back('c'); + /// assert_eq!(vec_deque, &['a', 'b', 'c']); + /// + /// vec_deque.insert(1, 'd'); + /// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']); + /// ``` + #[stable(feature = "deque_extras_15", since = "1.5.0")] + pub fn insert(&mut self, index: usize, value: T) { + assert!(index <= self.len(), "index out of bounds"); + if self.is_full() { + self.grow(); + } + + // Move the least number of elements in the ring buffer and insert + // the given object + // + // At most len/2 - 1 elements will be moved. O(min(n, n-i)) + // + // There are three main cases: + // Elements are contiguous + // - special case when tail is 0 + // Elements are discontiguous and the insert is in the tail section + // Elements are discontiguous and the insert is in the head section + // + // For each of those there are two more cases: + // Insert is closer to tail + // Insert is closer to head + // + // Key: H - self.head + // T - self.tail + // o - Valid element + // I - Insertion element + // A - The element that should be after the insertion point + // M - Indicates element was moved + + let idx = self.wrap_add(self.tail, index); + + let distance_to_tail = index; + let distance_to_head = self.len() - index; + + let contiguous = self.is_contiguous(); + + match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) { + (true, true, _) if index == 0 => { + // push_front + // + // T + // I H + // [A o o o o o o . . . . . . . . .] + // + // H T + // [A o o o o o o o . . . . . I] + // + + self.tail = self.wrap_sub(self.tail, 1); + } + (true, true, _) => { + unsafe { + // contiguous, insert closer to tail: + // + // T I H + // [. . . o o A o o o o . . . . . .] + // + // T H + // [. . o o I A o o o o . . . . . .] + // M M + // + // contiguous, insert closer to tail and tail is 0: + // + // + // T I H + // [o o A o o o o . . . . . . . . .] + // + // H T + // [o I A o o o o o . . . . . . . o] + // M M + + let new_tail = self.wrap_sub(self.tail, 1); + + self.copy(new_tail, self.tail, 1); + // Already moved the tail, so we only copy `index - 1` elements. + self.copy(self.tail, self.tail + 1, index - 1); + + self.tail = new_tail; + } + } + (true, false, _) => { + unsafe { + // contiguous, insert closer to head: + // + // T I H + // [. . . o o o o A o o . . . . . .] + // + // T H + // [. . . o o o o I A o o . . . . .] + // M M M + + self.copy(idx + 1, idx, self.head - idx); + self.head = self.wrap_add(self.head, 1); + } + } + (false, true, true) => { + unsafe { + // discontiguous, insert closer to tail, tail section: + // + // H T I + // [o o o o o o . . . . . o o A o o] + // + // H T + // [o o o o o o . . . . o o I A o o] + // M M + + self.copy(self.tail - 1, self.tail, index); + self.tail -= 1; + } + } + (false, false, true) => { + unsafe { + // discontiguous, insert closer to head, tail section: + // + // H T I + // [o o . . . . . . . o o o o o A o] + // + // H T + // [o o o . . . . . . o o o o o I A] + // M M M M + + // copy elements up to new head + self.copy(1, 0, self.head); + + // copy last element into empty spot at bottom of buffer + self.copy(0, self.cap() - 1, 1); + + // move elements from idx to end forward not including ^ element + self.copy(idx + 1, idx, self.cap() - 1 - idx); + + self.head += 1; + } + } + (false, true, false) if idx == 0 => { + unsafe { + // discontiguous, insert is closer to tail, head section, + // and is at index zero in the internal buffer: + // + // I H T + // [A o o o o o o o o o . . . o o o] + // + // H T + // [A o o o o o o o o o . . o o o I] + // M M M + + // copy elements up to new tail + self.copy(self.tail - 1, self.tail, self.cap() - self.tail); + + // copy last element into empty spot at bottom of buffer + self.copy(self.cap() - 1, 0, 1); + + self.tail -= 1; + } + } + (false, true, false) => { + unsafe { + // discontiguous, insert closer to tail, head section: + // + // I H T + // [o o o A o o o o o o . . . o o o] + // + // H T + // [o o I A o o o o o o . . o o o o] + // M M M M M M + + // copy elements up to new tail + self.copy(self.tail - 1, self.tail, self.cap() - self.tail); + + // copy last element into empty spot at bottom of buffer + self.copy(self.cap() - 1, 0, 1); + + // move elements from idx-1 to end forward not including ^ element + self.copy(0, 1, idx - 1); + + self.tail -= 1; + } + } + (false, false, false) => { + unsafe { + // discontiguous, insert closer to head, head section: + // + // I H T + // [o o o o A o o . . . . . . o o o] + // + // H T + // [o o o o I A o o . . . . . o o o] + // M M M + + self.copy(idx + 1, idx, self.head - idx); + self.head += 1; + } + } + } + + // tail might've been changed so we need to recalculate + let new_idx = self.wrap_add(self.tail, index); + unsafe { + self.buffer_write(new_idx, value); + } + } + + /// Removes and returns the element at `index` from the `VecDeque`. + /// Whichever end is closer to the removal point will be moved to make + /// room, and all the affected elements will be moved to new positions. + /// Returns `None` if `index` is out of bounds. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(1); + /// buf.push_back(2); + /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); + /// + /// assert_eq!(buf.remove(1), Some(2)); + /// assert_eq!(buf, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, index: usize) -> Option { + if self.is_empty() || self.len() <= index { + return None; + } + + // There are three main cases: + // Elements are contiguous + // Elements are discontiguous and the removal is in the tail section + // Elements are discontiguous and the removal is in the head section + // - special case when elements are technically contiguous, + // but self.head = 0 + // + // For each of those there are two more cases: + // Insert is closer to tail + // Insert is closer to head + // + // Key: H - self.head + // T - self.tail + // o - Valid element + // x - Element marked for removal + // R - Indicates element that is being removed + // M - Indicates element was moved + + let idx = self.wrap_add(self.tail, index); + + let elem = unsafe { Some(self.buffer_read(idx)) }; + + let distance_to_tail = index; + let distance_to_head = self.len() - index; + + let contiguous = self.is_contiguous(); + + match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) { + (true, true, _) => { + unsafe { + // contiguous, remove closer to tail: + // + // T R H + // [. . . o o x o o o o . . . . . .] + // + // T H + // [. . . . o o o o o o . . . . . .] + // M M + + self.copy(self.tail + 1, self.tail, index); + self.tail += 1; + } + } + (true, false, _) => { + unsafe { + // contiguous, remove closer to head: + // + // T R H + // [. . . o o o o x o o . . . . . .] + // + // T H + // [. . . o o o o o o . . . . . . .] + // M M + + self.copy(idx, idx + 1, self.head - idx - 1); + self.head -= 1; + } + } + (false, true, true) => { + unsafe { + // discontiguous, remove closer to tail, tail section: + // + // H T R + // [o o o o o o . . . . . o o x o o] + // + // H T + // [o o o o o o . . . . . . o o o o] + // M M + + self.copy(self.tail + 1, self.tail, index); + self.tail = self.wrap_add(self.tail, 1); + } + } + (false, false, false) => { + unsafe { + // discontiguous, remove closer to head, head section: + // + // R H T + // [o o o o x o o . . . . . . o o o] + // + // H T + // [o o o o o o . . . . . . . o o o] + // M M + + self.copy(idx, idx + 1, self.head - idx - 1); + self.head -= 1; + } + } + (false, false, true) => { + unsafe { + // discontiguous, remove closer to head, tail section: + // + // H T R + // [o o o . . . . . . o o o o o x o] + // + // H T + // [o o . . . . . . . o o o o o o o] + // M M M M + // + // or quasi-discontiguous, remove next to head, tail section: + // + // H T R + // [. . . . . . . . . o o o o o x o] + // + // T H + // [. . . . . . . . . o o o o o o .] + // M + + // draw in elements in the tail section + self.copy(idx, idx + 1, self.cap() - idx - 1); + + // Prevents underflow. + if self.head != 0 { + // copy first element into empty spot + self.copy(self.cap() - 1, 0, 1); + + // move elements in the head section backwards + self.copy(0, 1, self.head - 1); + } + + self.head = self.wrap_sub(self.head, 1); + } + } + (false, true, false) => { + unsafe { + // discontiguous, remove closer to tail, head section: + // + // R H T + // [o o x o o o o o o o . . . o o o] + // + // H T + // [o o o o o o o o o o . . . . o o] + // M M M M M + + // draw in elements up to idx + self.copy(1, 0, idx); + + // copy last element into empty spot + self.copy(0, self.cap() - 1, 1); + + // move elements from tail to end forward, excluding the last one + self.copy(self.tail + 1, self.tail, self.cap() - self.tail - 1); + + self.tail = self.wrap_add(self.tail, 1); + } + } + } + + elem + } + + /// Splits the `VecDeque` into two at the given index. + /// + /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`, + /// and the returned `VecDeque` contains elements `[at, len)`. + /// + /// Note that the capacity of `self` does not change. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + /// let buf2 = buf.split_off(1); + /// assert_eq!(buf, [1]); + /// assert_eq!(buf2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + pub fn split_off(&mut self, at: usize) -> Self { + let len = self.len(); + assert!(at <= len, "`at` out of bounds"); + + let other_len = len - at; + let mut other = VecDeque::with_capacity(other_len); + + unsafe { + let (first_half, second_half) = self.as_slices(); + + let first_len = first_half.len(); + let second_len = second_half.len(); + if at < first_len { + // `at` lies in the first half. + let amount_in_first = first_len - at; + + ptr::copy_nonoverlapping(first_half.as_ptr().add(at), other.ptr(), amount_in_first); + + // just take all of the second half. + ptr::copy_nonoverlapping( + second_half.as_ptr(), + other.ptr().add(amount_in_first), + second_len, + ); + } else { + // `at` lies in the second half, need to factor in the elements we skipped + // in the first half. + let offset = at - first_len; + let amount_in_second = second_len - offset; + ptr::copy_nonoverlapping( + second_half.as_ptr().add(offset), + other.ptr(), + amount_in_second, + ); + } + } + + // Cleanup where the ends of the buffers are + self.head = self.wrap_sub(self.head, other_len); + other.head = other.wrap_index(other_len); + + other + } + + /// Moves all the elements of `other` into `self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the new number of elements in self overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = vec![1, 2].into_iter().collect(); + /// let mut buf2: VecDeque<_> = vec![3, 4].into_iter().collect(); + /// buf.append(&mut buf2); + /// assert_eq!(buf, [1, 2, 3, 4]); + /// assert_eq!(buf2, []); + /// ``` + #[inline] + #[stable(feature = "append", since = "1.4.0")] + pub fn append(&mut self, other: &mut Self) { + // naive impl + self.extend(other.drain(..)); + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns false. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..5); + /// buf.retain(|&x| x % 2 == 0); + /// assert_eq!(buf, [2, 4]); + /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..6); + /// + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// buf.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(buf, [2, 3, 5]); + /// ``` + #[stable(feature = "vec_deque_retain", since = "1.4.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + let len = self.len(); + let mut del = 0; + for i in 0..len { + if !f(&self[i]) { + del += 1; + } else if del > 0 { + self.swap(i - del, i); + } + } + if del > 0 { + self.truncate(len - del); + } + } + + // This may panic or abort + #[inline(never)] + fn grow(&mut self) { + if self.is_full() { + let old_cap = self.cap(); + // Double the buffer size. + self.buf.reserve_exact(old_cap, old_cap); + assert!(self.cap() == old_cap * 2); + unsafe { + self.handle_capacity_increase(old_cap); + } + debug_assert!(!self.is_full()); + } + } + + /// Modifies the `VecDeque` in-place so that `len()` is equal to `new_len`, + /// either by removing excess elements from the back or by appending + /// elements generated by calling `generator` to the back. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// + /// buf.resize_with(5, Default::default); + /// assert_eq!(buf, [5, 10, 15, 0, 0]); + /// + /// buf.resize_with(2, || unreachable!()); + /// assert_eq!(buf, [5, 10]); + /// + /// let mut state = 100; + /// buf.resize_with(5, || { state += 1; state }); + /// assert_eq!(buf, [5, 10, 101, 102, 103]); + /// ``` + #[stable(feature = "vec_resize_with", since = "1.33.0")] + pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) { + let len = self.len(); + + if new_len > len { + self.extend(repeat_with(generator).take(new_len - len)) + } else { + self.truncate(new_len); + } + } + + /// Rearranges the internal storage of this deque so it is one contiguous + /// slice, which is then returned. + /// + /// This method does not allocate and does not change the order of the + /// inserted elements. As it returns a mutable slice, this can be used to + /// sort a deque. + /// + /// Once the internal storage is contiguous, the [`as_slices`] and + /// [`as_mut_slices`] methods will return the entire contents of the + /// `VecDeque` in a single slice. + /// + /// [`as_slices`]: VecDeque::as_slices + /// [`as_mut_slices`]: VecDeque::as_mut_slices + /// + /// # Examples + /// + /// Sorting the content of a deque. + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// + /// buf.push_back(2); + /// buf.push_back(1); + /// buf.push_front(3); + /// + /// // sorting the deque + /// buf.make_contiguous().sort(); + /// assert_eq!(buf.as_slices(), (&[1, 2, 3] as &[_], &[] as &[_])); + /// + /// // sorting it in reverse order + /// buf.make_contiguous().sort_by(|a, b| b.cmp(a)); + /// assert_eq!(buf.as_slices(), (&[3, 2, 1] as &[_], &[] as &[_])); + /// ``` + /// + /// Getting immutable access to the contiguous slice. + /// + /// ```rust + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// + /// buf.push_back(2); + /// buf.push_back(1); + /// buf.push_front(3); + /// + /// buf.make_contiguous(); + /// if let (slice, &[]) = buf.as_slices() { + /// // we can now be sure that `slice` contains all elements of the deque, + /// // while still having immutable access to `buf`. + /// assert_eq!(buf.len(), slice.len()); + /// assert_eq!(slice, &[3, 2, 1] as &[_]); + /// } + /// ``` + #[stable(feature = "deque_make_contiguous", since = "1.48.0")] + pub fn make_contiguous(&mut self) -> &mut [T] { + if self.is_contiguous() { + let tail = self.tail; + let head = self.head; + return unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 }; + } + + let buf = self.buf.ptr(); + let cap = self.cap(); + let len = self.len(); + + let free = self.tail - self.head; + let tail_len = cap - self.tail; + + if free >= tail_len { + // there is enough free space to copy the tail in one go, + // this means that we first shift the head backwards, and then + // copy the tail to the correct position. + // + // from: DEFGH....ABC + // to: ABCDEFGH.... + unsafe { + ptr::copy(buf, buf.add(tail_len), self.head); + // ...DEFGH.ABC + ptr::copy_nonoverlapping(buf.add(self.tail), buf, tail_len); + // ABCDEFGH.... + + self.tail = 0; + self.head = len; + } + } else if free > self.head { + // FIXME: We currently do not consider ....ABCDEFGH + // to be contiguous because `head` would be `0` in this + // case. While we probably want to change this it + // isn't trivial as a few places expect `is_contiguous` + // to mean that we can just slice using `buf[tail..head]`. + + // there is enough free space to copy the head in one go, + // this means that we first shift the tail forwards, and then + // copy the head to the correct position. + // + // from: FGH....ABCDE + // to: ...ABCDEFGH. + unsafe { + ptr::copy(buf.add(self.tail), buf.add(self.head), tail_len); + // FGHABCDE.... + ptr::copy_nonoverlapping(buf, buf.add(self.head + tail_len), self.head); + // ...ABCDEFGH. + + self.tail = self.head; + self.head = self.wrap_add(self.tail, len); + } + } else { + // free is smaller than both head and tail, + // this means we have to slowly "swap" the tail and the head. + // + // from: EFGHI...ABCD or HIJK.ABCDEFG + // to: ABCDEFGHI... or ABCDEFGHIJK. + let mut left_edge: usize = 0; + let mut right_edge: usize = self.tail; + unsafe { + // The general problem looks like this + // GHIJKLM...ABCDEF - before any swaps + // ABCDEFM...GHIJKL - after 1 pass of swaps + // ABCDEFGHIJM...KL - swap until the left edge reaches the temp store + // - then restart the algorithm with a new (smaller) store + // Sometimes the temp store is reached when the right edge is at the end + // of the buffer - this means we've hit the right order with fewer swaps! + // E.g + // EF..ABCD + // ABCDEF.. - after four only swaps we've finished + while left_edge < len && right_edge != cap { + let mut right_offset = 0; + for i in left_edge..right_edge { + right_offset = (i - left_edge) % (cap - right_edge); + let src: isize = (right_edge + right_offset) as isize; + ptr::swap(buf.add(i), buf.offset(src)); + } + let n_ops = right_edge - left_edge; + left_edge += n_ops; + right_edge += right_offset + 1; + } + + self.tail = 0; + self.head = len; + } + } + + let tail = self.tail; + let head = self.head; + unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 } + } + + /// Rotates the double-ended queue `mid` places to the left. + /// + /// Equivalently, + /// - Rotates item `mid` into the first position. + /// - Pops the first `mid` items and pushes them to the end. + /// - Rotates `len() - mid` places to the right. + /// + /// # Panics + /// + /// If `mid` is greater than `len()`. Note that `mid == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `*O*(min(mid, len() - mid))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_left(3); + /// assert_eq!(buf, [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]); + /// + /// for i in 1..10 { + /// assert_eq!(i * 3 % 10, buf[0]); + /// buf.rotate_left(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] + pub fn rotate_left(&mut self, mid: usize) { + assert!(mid <= self.len()); + let k = self.len() - mid; + if mid <= k { + unsafe { self.rotate_left_inner(mid) } + } else { + unsafe { self.rotate_right_inner(k) } + } + } + + /// Rotates the double-ended queue `k` places to the right. + /// + /// Equivalently, + /// - Rotates the first item into position `k`. + /// - Pops the last `k` items and pushes them to the front. + /// - Rotates `len() - k` places to the left. + /// + /// # Panics + /// + /// If `k` is greater than `len()`. Note that `k == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `*O*(min(k, len() - k))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_right(3); + /// assert_eq!(buf, [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]); + /// + /// for i in 1..10 { + /// assert_eq!(0, buf[i * 3 % 10]); + /// buf.rotate_right(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] + pub fn rotate_right(&mut self, k: usize) { + assert!(k <= self.len()); + let mid = self.len() - k; + if k <= mid { + unsafe { self.rotate_right_inner(k) } + } else { + unsafe { self.rotate_left_inner(mid) } + } + } + + // SAFETY: the following two methods require that the rotation amount + // be less than half the length of the deque. + // + // `wrap_copy` requires that `min(x, cap() - x) + copy_len <= cap()`, + // but than `min` is never more than half the capacity, regardless of x, + // so it's sound to call here because we're calling with something + // less than half the length, which is never above half the capacity. + + unsafe fn rotate_left_inner(&mut self, mid: usize) { + debug_assert!(mid * 2 <= self.len()); + unsafe { + self.wrap_copy(self.head, self.tail, mid); + } + self.head = self.wrap_add(self.head, mid); + self.tail = self.wrap_add(self.tail, mid); + } + + unsafe fn rotate_right_inner(&mut self, k: usize) { + debug_assert!(k * 2 <= self.len()); + self.head = self.wrap_sub(self.head, k); + self.tail = self.wrap_sub(self.tail, k); + unsafe { + self.wrap_copy(self.tail, self.head, k); + } + } + + /// Binary searches this sorted `VecDeque` for a given element. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. If the value is not found then + /// [`Result::Err`] is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// [`partition_point`]: VecDeque::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// #![feature(vecdeque_binary_search)] + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// + /// assert_eq!(deque.binary_search(&13), Ok(9)); + /// assert_eq!(deque.binary_search(&4), Err(7)); + /// assert_eq!(deque.binary_search(&100), Err(13)); + /// let r = deque.binary_search(&1); + /// assert!(matches!(r, Ok(1..=4))); + /// ``` + /// + /// If you want to insert an item to a sorted `VecDeque`, while maintaining + /// sort order: + /// + /// ``` + /// #![feature(vecdeque_binary_search)] + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// let num = 42; + /// let idx = deque.binary_search(&num).unwrap_or_else(|x| x); + /// deque.insert(idx, num); + /// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); + /// ``` + #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + #[inline] + pub fn binary_search(&self, x: &T) -> Result + where + T: Ord, + { + self.binary_search_by(|e| e.cmp(x)) + } + + /// Binary searches this sorted `VecDeque` with a comparator function. + /// + /// The comparator function should implement an order consistent + /// with the sort order of the underlying `VecDeque`, returning an + /// order code that indicates whether its argument is `Less`, + /// `Equal` or `Greater` than the desired target. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. If the value is not found then + /// [`Result::Err`] is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`]. + /// + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// [`partition_point`]: VecDeque::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements. The first is found, with a + /// uniquely determined position; the second and third are not + /// found; the fourth could match any position in `[1, 4]`. + /// + /// ``` + /// #![feature(vecdeque_binary_search)] + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into(); + /// + /// assert_eq!(deque.binary_search_by(|x| x.cmp(&13)), Ok(9)); + /// assert_eq!(deque.binary_search_by(|x| x.cmp(&4)), Err(7)); + /// assert_eq!(deque.binary_search_by(|x| x.cmp(&100)), Err(13)); + /// let r = deque.binary_search_by(|x| x.cmp(&1)); + /// assert!(matches!(r, Ok(1..=4))); + /// ``` + #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result + where + F: FnMut(&'a T) -> Ordering, + { + let (front, back) = self.as_slices(); + let cmp_back = back.first().map(|elem| f(elem)); + + if let Some(Ordering::Equal) = cmp_back { + Ok(front.len()) + } else if let Some(Ordering::Less) = cmp_back { + back.binary_search_by(f).map(|idx| idx + front.len()).map_err(|idx| idx + front.len()) + } else { + front.binary_search_by(f) + } + } + + /// Binary searches this sorted `VecDeque` with a key extraction function. + /// + /// Assumes that the `VecDeque` is sorted by the key, for instance with + /// [`make_contiguous().sort_by_key()`] using the same key extraction function. + /// + /// If the value is found then [`Result::Ok`] is returned, containing the + /// index of the matching element. If there are multiple matches, then any + /// one of the matches could be returned. If the value is not found then + /// [`Result::Err`] is returned, containing the index where a matching + /// element could be inserted while maintaining sorted order. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`]. + /// + /// [`make_contiguous().sort_by_key()`]: VecDeque::make_contiguous + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`partition_point`]: VecDeque::partition_point + /// + /// # Examples + /// + /// Looks up a series of four elements in a slice of pairs sorted by + /// their second elements. The first is found, with a uniquely + /// determined position; the second and third are not found; the + /// fourth could match any position in `[1, 4]`. + /// + /// ``` + /// #![feature(vecdeque_binary_search)] + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1), + /// (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13), + /// (1, 21), (2, 34), (4, 55)].into(); + /// + /// assert_eq!(deque.binary_search_by_key(&13, |&(a, b)| b), Ok(9)); + /// assert_eq!(deque.binary_search_by_key(&4, |&(a, b)| b), Err(7)); + /// assert_eq!(deque.binary_search_by_key(&100, |&(a, b)| b), Err(13)); + /// let r = deque.binary_search_by_key(&1, |&(a, b)| b); + /// assert!(matches!(r, Ok(1..=4))); + /// ``` + #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + #[inline] + pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result + where + F: FnMut(&'a T) -> B, + B: Ord, + { + self.binary_search_by(|k| f(k).cmp(b)) + } + + /// Returns the index of the partition point according to the given predicate + /// (the index of the first element of the second partition). + /// + /// The deque is assumed to be partitioned according to the given predicate. + /// This means that all elements for which the predicate returns true are at the start of the deque + /// and all elements for which the predicate returns false are at the end. + /// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0 + /// (all odd numbers are at the start, all even at the end). + /// + /// If this deque is not partitioned, the returned result is unspecified and meaningless, + /// as this method performs a kind of binary search. + /// + /// See also [`binary_search`], [`binary_search_by`], and [`binary_search_by_key`]. + /// + /// [`binary_search`]: VecDeque::binary_search + /// [`binary_search_by`]: VecDeque::binary_search_by + /// [`binary_search_by_key`]: VecDeque::binary_search_by_key + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_binary_search)] + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque<_> = vec![1, 2, 3, 3, 5, 6, 7].into(); + /// let i = deque.partition_point(|&x| x < 5); + /// + /// assert_eq!(i, 4); + /// assert!(deque.iter().take(i).all(|&x| x < 5)); + /// assert!(deque.iter().skip(i).all(|&x| !(x < 5))); + /// ``` + #[unstable(feature = "vecdeque_binary_search", issue = "78021")] + pub fn partition_point

(&self, mut pred: P) -> usize + where + P: FnMut(&T) -> bool, + { + let (front, back) = self.as_slices(); + + if let Some(true) = back.first().map(|v| pred(v)) { + back.partition_point(pred) + front.len() + } else { + front.partition_point(pred) + } + } +} + +impl VecDeque { + /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len, + /// either by removing excess elements from the back or by appending clones of `value` + /// to the back. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// + /// buf.resize(2, 0); + /// assert_eq!(buf, [5, 10]); + /// + /// buf.resize(5, 20); + /// assert_eq!(buf, [5, 10, 20, 20, 20]); + /// ``` + #[stable(feature = "deque_extras", since = "1.16.0")] + pub fn resize(&mut self, new_len: usize, value: T) { + self.resize_with(new_len, || value.clone()); + } +} + +/// Returns the index in the underlying buffer for a given logical element index. +#[inline] +fn wrap_index(index: usize, size: usize) -> usize { + // size is always a power of 2 + debug_assert!(size.is_power_of_two()); + index & (size - 1) +} + +/// Calculate the number of elements left to be read in the buffer +#[inline] +fn count(tail: usize, head: usize, size: usize) -> usize { + // size is always a power of 2 + (head.wrapping_sub(tail)) & (size - 1) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for VecDeque { + fn eq(&self, other: &VecDeque) -> bool { + if self.len() != other.len() { + return false; + } + let (sa, sb) = self.as_slices(); + let (oa, ob) = other.as_slices(); + if sa.len() == oa.len() { + sa == oa && sb == ob + } else if sa.len() < oa.len() { + // Always divisible in three sections, for example: + // self: [a b c|d e f] + // other: [0 1 2 3|4 5] + // front = 3, mid = 1, + // [a b c] == [0 1 2] && [d] == [3] && [e f] == [4 5] + let front = sa.len(); + let mid = oa.len() - front; + + let (oa_front, oa_mid) = oa.split_at(front); + let (sb_mid, sb_back) = sb.split_at(mid); + debug_assert_eq!(sa.len(), oa_front.len()); + debug_assert_eq!(sb_mid.len(), oa_mid.len()); + debug_assert_eq!(sb_back.len(), ob.len()); + sa == oa_front && sb_mid == oa_mid && sb_back == ob + } else { + let front = oa.len(); + let mid = sa.len() - front; + + let (sa_front, sa_mid) = sa.split_at(front); + let (ob_mid, ob_back) = ob.split_at(mid); + debug_assert_eq!(sa_front.len(), oa.len()); + debug_assert_eq!(sa_mid.len(), ob_mid.len()); + debug_assert_eq!(sb.len(), ob_back.len()); + sa_front == oa && sa_mid == ob_mid && sb == ob_back + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for VecDeque {} + +__impl_slice_eq1! { [] VecDeque, Vec, } +__impl_slice_eq1! { [] VecDeque, &[B], } +__impl_slice_eq1! { [] VecDeque, &mut [B], } +__impl_slice_eq1! { [const N: usize] VecDeque, [B; N], } +__impl_slice_eq1! { [const N: usize] VecDeque, &[B; N], } +__impl_slice_eq1! { [const N: usize] VecDeque, &mut [B; N], } + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for VecDeque { + fn partial_cmp(&self, other: &VecDeque) -> Option { + self.iter().partial_cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for VecDeque { + #[inline] + fn cmp(&self, other: &VecDeque) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for VecDeque { + fn hash(&self, state: &mut H) { + self.len().hash(state); + // It's not possible to use Hash::hash_slice on slices + // returned by as_slices method as their length can vary + // in otherwise identical deques. + // + // Hasher only guarantees equivalence for the exact same + // set of calls to its methods. + self.iter().for_each(|elem| elem.hash(state)); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Index for VecDeque { + type Output = A; + + #[inline] + fn index(&self, index: usize) -> &A { + self.get(index).expect("Out of bounds access") + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IndexMut for VecDeque { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut A { + self.get_mut(index).expect("Out of bounds access") + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for VecDeque { + fn from_iter>(iter: T) -> VecDeque { + let iterator = iter.into_iter(); + let (lower, _) = iterator.size_hint(); + let mut deq = VecDeque::with_capacity(lower); + deq.extend(iterator); + deq + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for VecDeque { + type Item = T; + type IntoIter = IntoIter; + + /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by + /// value. + fn into_iter(self) -> IntoIter { + IntoIter { inner: self } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a VecDeque { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a mut VecDeque { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for VecDeque { + fn extend>(&mut self, iter: T) { + // This function should be the moral equivalent of: + // + // for item in iter.into_iter() { + // self.push_back(item); + // } + let mut iter = iter.into_iter(); + while let Some(element) = iter.next() { + if self.len() == self.capacity() { + let (lower, _) = iter.size_hint(); + self.reserve(lower.saturating_add(1)); + } + + let head = self.head; + self.head = self.wrap_add(self.head, 1); + unsafe { + self.buffer_write(head, element); + } + } + } + + #[inline] + fn extend_one(&mut self, elem: A) { + self.push_back(elem); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &elem: &T) { + self.push_back(elem); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for VecDeque { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self).finish() + } +} + +#[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] +impl From> for VecDeque { + /// Turn a [`Vec`] into a [`VecDeque`]. + /// + /// [`Vec`]: crate::vec::Vec + /// [`VecDeque`]: crate::collections::VecDeque + /// + /// This avoids reallocating where possible, but the conditions for that are + /// strict, and subject to change, and so shouldn't be relied upon unless the + /// `Vec` came from `From>` and hasn't been reallocated. + fn from(mut other: Vec) -> Self { + let len = other.len(); + if mem::size_of::() == 0 { + // There's no actual allocation for ZSTs to worry about capacity, + // but `VecDeque` can't handle as much length as `Vec`. + assert!(len < MAXIMUM_ZST_CAPACITY, "capacity overflow"); + } else { + // We need to resize if the capacity is not a power of two, too small or + // doesn't have at least one free space. We do this while it's still in + // the `Vec` so the items will drop on panic. + let min_cap = cmp::max(MINIMUM_CAPACITY, len) + 1; + let cap = cmp::max(min_cap, other.capacity()).next_power_of_two(); + if other.capacity() != cap { + other.reserve_exact(cap - len); + } + } + + unsafe { + let (other_buf, len, capacity) = other.into_raw_parts(); + let buf = RawVec::from_raw_parts(other_buf, capacity); + VecDeque { tail: 0, head: len, buf } + } + } +} + +#[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] +impl From> for Vec { + /// Turn a [`VecDeque`] into a [`Vec`]. + /// + /// [`Vec`]: crate::vec::Vec + /// [`VecDeque`]: crate::collections::VecDeque + /// + /// This never needs to re-allocate, but does need to do *O*(*n*) data movement if + /// the circular buffer doesn't happen to be at the beginning of the allocation. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// // This one is *O*(1). + /// let deque: VecDeque<_> = (1..5).collect(); + /// let ptr = deque.as_slices().0.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// + /// // This one needs data rearranging. + /// let mut deque: VecDeque<_> = (1..5).collect(); + /// deque.push_front(9); + /// deque.push_front(8); + /// let ptr = deque.as_slices().1.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// ``` + fn from(mut other: VecDeque) -> Self { + other.make_contiguous(); + + unsafe { + let other = ManuallyDrop::new(other); + let buf = other.buf.ptr(); + let len = other.len(); + let cap = other.cap(); + + if other.tail != 0 { + ptr::copy(buf.add(other.tail), buf, len); + } + Vec::from_raw_parts(buf, len, cap) + } + } +} +use core::fmt; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; +use core::ops::Try; + +use super::{count, wrap_index, RingSlices}; + +/// An iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`iter`] method on [`super::VecDeque`]. See its +/// documentation for more. +/// +/// [`iter`]: super::VecDeque::iter +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + pub(crate) ring: &'a [T], + pub(crate) tail: usize, + pub(crate) head: usize, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + f.debug_tuple("Iter").field(&front).field(&back).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { ring: self.ring, tail: self.tail, head: self.head } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + unsafe { Some(self.ring.get_unchecked(tail)) } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = count(self.tail, self.head, self.ring.len()); + (len, Some(len)) + } + + fn fold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = front.iter().fold(accum, &mut f); + back.iter().fold(accum, &mut f) + } + + fn try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let (mut iter, final_res); + if self.tail <= self.head { + // single slice self.ring[self.tail..self.head] + iter = self.ring[self.tail..self.head].iter(); + final_res = iter.try_fold(init, &mut f); + } else { + // two slices: self.ring[self.tail..], self.ring[..self.head] + let (front, back) = self.ring.split_at(self.tail); + let mut back_iter = back.iter(); + let res = back_iter.try_fold(init, &mut f); + let len = self.ring.len(); + self.tail = (self.ring.len() - back_iter.len()) & (len - 1); + iter = front[..self.head].iter(); + final_res = iter.try_fold(res?, &mut f); + } + self.tail = self.head - iter.len(); + final_res + } + + fn nth(&mut self, n: usize) -> Option { + if n >= count(self.tail, self.head, self.ring.len()) { + self.tail = self.head; + None + } else { + self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); + self.next() + } + } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); + self.ring.get_unchecked(idx) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + if self.tail == self.head { + return None; + } + self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); + unsafe { Some(self.ring.get_unchecked(self.head)) } + } + + fn rfold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = back.iter().rfold(accum, &mut f); + front.iter().rfold(accum, &mut f) + } + + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let (mut iter, final_res); + if self.tail <= self.head { + // single slice self.ring[self.tail..self.head] + iter = self.ring[self.tail..self.head].iter(); + final_res = iter.try_rfold(init, &mut f); + } else { + // two slices: self.ring[self.tail..], self.ring[..self.head] + let (front, back) = self.ring.split_at(self.tail); + let mut front_iter = front[..self.head].iter(); + let res = front_iter.try_rfold(init, &mut f); + self.head = front_iter.len(); + iter = back.iter(); + final_res = iter.try_rfold(res?, &mut f); + } + self.head = self.tail + iter.len(); + final_res + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn is_empty(&self) -> bool { + self.head == self.tail + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Iter<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for Iter<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} +use super::*; + +#[bench] +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks +fn bench_push_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_back(i); + } + deq.head = 0; + deq.tail = 0; + }) +} + +#[bench] +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks +fn bench_push_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_front(i); + } + deq.head = 0; + deq.tail = 0; + }) +} + +#[bench] +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks +fn bench_pop_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_back()); + } + }) +} + +#[bench] +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks +fn bench_pop_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_front()); + } + }) +} + +#[test] +fn test_swap_front_back_remove() { + fn test(back: bool) { + // This test checks that every single combination of tail position and length is tested. + // Capacity 15 should be large enough to cover every case. + let mut tester = VecDeque::with_capacity(15); + let usable_cap = tester.capacity(); + let final_len = usable_cap / 2; + + for len in 0..final_len { + let expected: VecDeque<_> = + if back { (0..len).collect() } else { (0..len).rev().collect() }; + for tail_pos in 0..usable_cap { + tester.tail = tail_pos; + tester.head = tail_pos; + if back { + for i in 0..len * 2 { + tester.push_front(i); + } + for i in 0..len { + assert_eq!(tester.swap_remove_back(i), Some(len * 2 - 1 - i)); + } + } else { + for i in 0..len * 2 { + tester.push_back(i); + } + for i in 0..len { + let idx = tester.len() - 1 - i; + assert_eq!(tester.swap_remove_front(idx), Some(len * 2 - 1 - i)); + } + } + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } + } + test(true); + test(false); +} + +#[test] +fn test_insert() { + // This test checks that every single combination of tail position, length, and + // insertion position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* insertion + let minlen = if cfg!(miri) { cap - 1 } else { 1 }; // Miri is too slow + for len in minlen..cap { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::>(); + for tail_pos in 0..cap { + for to_insert in 0..len { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i != to_insert { + tester.push_back(i); + } + } + tester.insert(to_insert, to_insert); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } + } +} + +#[test] +fn make_contiguous_big_tail() { + let mut tester = VecDeque::with_capacity(15); + + for i in 0..3 { + tester.push_back(i); + } + + for i in 3..10 { + tester.push_front(i); + } + + // 012......9876543 + assert_eq!(tester.capacity(), 15); + assert_eq!((&[9, 8, 7, 6, 5, 4, 3] as &[_], &[0, 1, 2] as &[_]), tester.as_slices()); + + let expected_start = tester.head; + tester.make_contiguous(); + assert_eq!(tester.tail, expected_start); + assert_eq!((&[9, 8, 7, 6, 5, 4, 3, 0, 1, 2] as &[_], &[] as &[_]), tester.as_slices()); +} + +#[test] +fn make_contiguous_big_head() { + let mut tester = VecDeque::with_capacity(15); + + for i in 0..8 { + tester.push_back(i); + } + + for i in 8..10 { + tester.push_front(i); + } + + // 01234567......98 + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.tail, expected_start); + assert_eq!((&[9, 8, 0, 1, 2, 3, 4, 5, 6, 7] as &[_], &[] as &[_]), tester.as_slices()); +} + +#[test] +fn make_contiguous_small_free() { + let mut tester = VecDeque::with_capacity(15); + + for i in 'A' as u8..'I' as u8 { + tester.push_back(i as char); + } + + for i in 'I' as u8..'N' as u8 { + tester.push_front(i as char); + } + + // ABCDEFGH...MLKJI + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.tail, expected_start); + assert_eq!( + (&['M', 'L', 'K', 'J', 'I', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] as &[_], &[] as &[_]), + tester.as_slices() + ); + + tester.clear(); + for i in 'I' as u8..'N' as u8 { + tester.push_back(i as char); + } + + for i in 'A' as u8..'I' as u8 { + tester.push_front(i as char); + } + + // IJKLM...HGFEDCBA + let expected_start = 0; + tester.make_contiguous(); + assert_eq!(tester.tail, expected_start); + assert_eq!( + (&['H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'I', 'J', 'K', 'L', 'M'] as &[_], &[] as &[_]), + tester.as_slices() + ); +} + +#[test] +fn make_contiguous_head_to_end() { + let mut dq = VecDeque::with_capacity(3); + dq.push_front('B'); + dq.push_front('A'); + dq.push_back('C'); + dq.make_contiguous(); + let expected_tail = 0; + let expected_head = 3; + assert_eq!(expected_tail, dq.tail); + assert_eq!(expected_head, dq.head); + assert_eq!((&['A', 'B', 'C'] as &[_], &[] as &[_]), dq.as_slices()); +} + +#[test] +fn make_contiguous_head_to_end_2() { + // Another test case for #79808, taken from #80293. + + let mut dq = VecDeque::from_iter(0..6); + dq.pop_front(); + dq.pop_front(); + dq.push_back(6); + dq.push_back(7); + dq.push_back(8); + dq.make_contiguous(); + let collected: Vec<_> = dq.iter().copied().collect(); + assert_eq!(dq.as_slices(), (&collected[..], &[] as &[_])); +} + +#[test] +fn test_remove() { + // This test checks that every single combination of tail position, length, and + // removal position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* removal + let minlen = if cfg!(miri) { cap - 2 } else { 0 }; // Miri is too slow + for len in minlen..cap - 1 { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::>(); + for tail_pos in 0..cap { + for to_remove in 0..=len { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i == to_remove { + tester.push_back(1234); + } + tester.push_back(i); + } + if to_remove == len { + tester.push_back(1234); + } + tester.remove(to_remove); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } + } +} + +#[test] +fn test_range() { + let mut tester: VecDeque = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + let minlen = if cfg!(miri) { cap - 1 } else { 0 }; // Miri is too slow + for len in minlen..=cap { + for tail in 0..=cap { + for start in 0..=len { + for end in start..=len { + tester.tail = tail; + tester.head = tail; + for i in 0..len { + tester.push_back(i); + } + + // Check that we iterate over the correct values + let range: VecDeque<_> = tester.range(start..end).copied().collect(); + let expected: VecDeque<_> = (start..end).collect(); + assert_eq!(range, expected); + } + } + } + } +} + +#[test] +fn test_range_mut() { + let mut tester: VecDeque = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + for len in 0..=cap { + for tail in 0..=cap { + for start in 0..=len { + for end in start..=len { + tester.tail = tail; + tester.head = tail; + for i in 0..len { + tester.push_back(i); + } + + let head_was = tester.head; + let tail_was = tester.tail; + + // Check that we iterate over the correct values + let range: VecDeque<_> = tester.range_mut(start..end).map(|v| *v).collect(); + let expected: VecDeque<_> = (start..end).collect(); + assert_eq!(range, expected); + + // We shouldn't have changed the capacity or made the + // head or tail out of bounds + assert_eq!(tester.capacity(), cap); + assert_eq!(tester.tail, tail_was); + assert_eq!(tester.head, head_was); + } + } + } + } +} + +#[test] +fn test_drain() { + let mut tester: VecDeque = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + for len in 0..=cap { + for tail in 0..=cap { + for drain_start in 0..=len { + for drain_end in drain_start..=len { + tester.tail = tail; + tester.head = tail; + for i in 0..len { + tester.push_back(i); + } + + // Check that we drain the correct values + let drained: VecDeque<_> = tester.drain(drain_start..drain_end).collect(); + let drained_expected: VecDeque<_> = (drain_start..drain_end).collect(); + assert_eq!(drained, drained_expected); + + // We shouldn't have changed the capacity or made the + // head or tail out of bounds + assert_eq!(tester.capacity(), cap); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + + // We should see the correct values in the VecDeque + let expected: VecDeque<_> = (0..drain_start).chain(drain_end..len).collect(); + assert_eq!(expected, tester); + } + } + } + } +} + +#[test] +fn test_shrink_to_fit() { + // This test checks that every single combination of head and tail position, + // is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + tester.reserve(63); + let max_cap = tester.capacity(); + + for len in 0..=cap { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::>(); + for tail_pos in 0..=max_cap { + tester.tail = tail_pos; + tester.head = tail_pos; + tester.reserve(63); + for i in 0..len { + tester.push_back(i); + } + tester.shrink_to_fit(); + assert!(tester.capacity() <= cap); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } +} + +#[test] +fn test_split_off() { + // This test checks that every single combination of tail position, length, and + // split position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *before* splitting + let minlen = if cfg!(miri) { cap - 1 } else { 0 }; // Miri is too slow + for len in minlen..cap { + // index to split at + for at in 0..=len { + // 0, 1, 2, .., at - 1 (may be empty) + let expected_self = (0..).take(at).collect::>(); + // at, at + 1, .., len - 1 (may be empty) + let expected_other = (at..).take(len - at).collect::>(); + + for tail_pos in 0..cap { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + tester.push_back(i); + } + let result = tester.split_off(at); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert!(result.tail < result.cap()); + assert!(result.head < result.cap()); + assert_eq!(tester, expected_self); + assert_eq!(result, expected_other); + } + } + } +} + +#[test] +fn test_from_vec() { + use crate::vec::Vec; + for cap in 0..35 { + for len in 0..=cap { + let mut vec = Vec::with_capacity(cap); + vec.extend(0..len); + + let vd = VecDeque::from(vec.clone()); + assert!(vd.cap().is_power_of_two()); + assert_eq!(vd.len(), vec.len()); + assert!(vd.into_iter().eq(vec)); + } + } + + let vec = Vec::from([(); MAXIMUM_ZST_CAPACITY - 1]); + let vd = VecDeque::from(vec.clone()); + assert!(vd.cap().is_power_of_two()); + assert_eq!(vd.len(), vec.len()); +} + +#[test] +#[should_panic = "capacity overflow"] +fn test_from_vec_zst_overflow() { + use crate::vec::Vec; + let vec = Vec::from([(); MAXIMUM_ZST_CAPACITY]); + let vd = VecDeque::from(vec.clone()); // no room for +1 + assert!(vd.cap().is_power_of_two()); + assert_eq!(vd.len(), vec.len()); +} + +#[test] +fn test_vec_from_vecdeque() { + use crate::vec::Vec; + + fn create_vec_and_test_convert(capacity: usize, offset: usize, len: usize) { + let mut vd = VecDeque::with_capacity(capacity); + for _ in 0..offset { + vd.push_back(0); + vd.pop_front(); + } + vd.extend(0..len); + + let vec: Vec<_> = Vec::from(vd.clone()); + assert_eq!(vec.len(), vd.len()); + assert!(vec.into_iter().eq(vd)); + } + + // Miri is too slow + let max_pwr = if cfg!(miri) { 5 } else { 7 }; + + for cap_pwr in 0..max_pwr { + // Make capacity as a (2^x)-1, so that the ring size is 2^x + let cap = (2i32.pow(cap_pwr) - 1) as usize; + + // In these cases there is enough free space to solve it with copies + for len in 0..((cap + 1) / 2) { + // Test contiguous cases + for offset in 0..(cap - len) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at end of buffer is bigger than block at start + for offset in (cap - len)..(cap - (len / 2)) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at start of buffer is bigger than block at end + for offset in (cap - (len / 2))..cap { + create_vec_and_test_convert(cap, offset, len) + } + } + + // Now there's not (necessarily) space to straighten the ring with simple copies, + // the ring will use swapping when: + // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len)) + // right block size > free space && left block size > free space + for len in ((cap + 1) / 2)..cap { + // Test contiguous cases + for offset in 0..(cap - len) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at end of buffer is bigger than block at start + for offset in (cap - len)..(cap - (len / 2)) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at start of buffer is bigger than block at end + for offset in (cap - (len / 2))..cap { + create_vec_and_test_convert(cap, offset, len) + } + } + } +} + +#[test] +fn test_clone_from() { + let m = vec![1; 8]; + let n = vec![2; 12]; + let limit = if cfg!(miri) { 4 } else { 8 }; // Miri is too slow + for pfv in 0..limit { + for pfu in 0..limit { + for longer in 0..2 { + let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) }; + let mut v = VecDeque::from(vr.clone()); + for _ in 0..pfv { + v.push_front(1); + } + let mut u = VecDeque::from(ur.clone()); + for _ in 0..pfu { + u.push_front(2); + } + v.clone_from(&u); + assert_eq!(&v, &u); + } + } + } +} + +#[test] +fn test_vec_deque_truncate_drop() { + static mut DROPS: u32 = 0; + #[derive(Clone)] + struct Elem(i32); + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; + for push_front in 0..=v.len() { + let v = v.clone(); + let mut tester = VecDeque::with_capacity(5); + for (index, elem) in v.into_iter().enumerate() { + if index < push_front { + tester.push_front(elem); + } else { + tester.push_back(elem); + } + } + assert_eq!(unsafe { DROPS }, 0); + tester.truncate(3); + assert_eq!(unsafe { DROPS }, 2); + tester.truncate(0); + assert_eq!(unsafe { DROPS }, 5); + unsafe { + DROPS = 0; + } + } +} + +#[test] +fn issue_53529() { + use crate::boxed::Box; + + let mut dst = VecDeque::new(); + dst.push_front(Box::new(1)); + dst.push_front(Box::new(2)); + assert_eq!(*dst.pop_back().unwrap(), 1); + + let mut src = VecDeque::new(); + src.push_front(Box::new(2)); + dst.append(&mut src); + for a in dst { + assert_eq!(*a, 2); + } +} + +#[test] +fn issue_80303() { + use core::iter; + use core::num::Wrapping; + + // This is a valid, albeit rather bad hash function implementation. + struct SimpleHasher(Wrapping); + + impl Hasher for SimpleHasher { + fn finish(&self) -> u64 { + self.0.0 + } + + fn write(&mut self, bytes: &[u8]) { + // This particular implementation hashes value 24 in addition to bytes. + // Such an implementation is valid as Hasher only guarantees equivalence + // for the exact same set of calls to its methods. + for &v in iter::once(&24).chain(bytes) { + self.0 = Wrapping(31) * self.0 + Wrapping(u64::from(v)); + } + } + } + + fn hash_code(value: impl Hash) -> u64 { + let mut hasher = SimpleHasher(Wrapping(1)); + value.hash(&mut hasher); + hasher.finish() + } + + // This creates two deques for which values returned by as_slices + // method differ. + let vda: VecDeque = (0..10).collect(); + let mut vdb = VecDeque::with_capacity(10); + vdb.extend(5..10); + (0..5).rev().for_each(|elem| vdb.push_front(elem)); + assert_ne!(vda.as_slices(), vdb.as_slices()); + assert_eq!(vda, vdb); + assert_eq!(hash_code(vda), hash_code(vdb)); +} +use core::fmt; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; +use core::marker::PhantomData; + +use super::{count, wrap_index, RingSlices}; + +/// A mutable iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`iter_mut`] method on [`super::VecDeque`]. See its +/// documentation for more. +/// +/// [`iter_mut`]: super::VecDeque::iter_mut +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, T: 'a> { + // Internal safety invariant: the entire slice is dereferencable. + pub(crate) ring: *mut [T], + pub(crate) tail: usize, + pub(crate) head: usize, + pub(crate) phantom: PhantomData<&'a mut [T]>, +} + +// SAFETY: we do nothing thread-local and there is no interior mutability, +// so the usual structural `Send`/`Sync` apply. +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IterMut<'_, T> {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IterMut<'_, T> {} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IterMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + // SAFETY: these are the elements we have not handed out yet, so aliasing is fine. + // The `IterMut` invariant also ensures everything is dereferencable. + let (front, back) = unsafe { (&*front, &*back) }; + f.debug_tuple("IterMut").field(&front).field(&back).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + + unsafe { + let elem = self.ring.get_unchecked_mut(tail); + Some(&mut *elem) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = count(self.tail, self.head, self.ring.len()); + (len, Some(len)) + } + + fn fold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + // SAFETY: these are the elements we have not handed out yet, so aliasing is fine. + // The `IterMut` invariant also ensures everything is dereferencable. + let (front, back) = unsafe { (&mut *front, &mut *back) }; + accum = front.iter_mut().fold(accum, &mut f); + back.iter_mut().fold(accum, &mut f) + } + + fn nth(&mut self, n: usize) -> Option { + if n >= count(self.tail, self.head, self.ring.len()) { + self.tail = self.head; + None + } else { + self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); + self.next() + } + } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); + &mut *self.ring.get_unchecked_mut(idx) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); + + unsafe { + let elem = self.ring.get_unchecked_mut(self.head); + Some(&mut *elem) + } + } + + fn rfold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + // SAFETY: these are the elements we have not handed out yet, so aliasing is fine. + // The `IterMut` invariant also ensures everything is dereferencable. + let (front, back) = unsafe { (&mut *front, &mut *back) }; + accum = back.iter_mut().rfold(accum, &mut f); + front.iter_mut().rfold(accum, &mut f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, T> { + fn is_empty(&self) -> bool { + self.head == self.tail + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IterMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for IterMut<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} +//! A priority queue implemented with a binary heap. +//! +//! Insertion and popping the largest element have *O*(log(*n*)) time complexity. +//! Checking the largest element is *O*(1). Converting a vector to a binary heap +//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be +//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* \* log(*n*)) +//! in-place heapsort. +//! +//! # Examples +//! +//! This is a larger example that implements [Dijkstra's algorithm][dijkstra] +//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph]. +//! It shows how to use [`BinaryHeap`] with custom types. +//! +//! [dijkstra]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm +//! [sssp]: https://en.wikipedia.org/wiki/Shortest_path_problem +//! [dir_graph]: https://en.wikipedia.org/wiki/Directed_graph +//! +//! ``` +//! use std::cmp::Ordering; +//! use std::collections::BinaryHeap; +//! +//! #[derive(Copy, Clone, Eq, PartialEq)] +//! struct State { +//! cost: usize, +//! position: usize, +//! } +//! +//! // The priority queue depends on `Ord`. +//! // Explicitly implement the trait so the queue becomes a min-heap +//! // instead of a max-heap. +//! impl Ord for State { +//! fn cmp(&self, other: &Self) -> Ordering { +//! // Notice that the we flip the ordering on costs. +//! // In case of a tie we compare positions - this step is necessary +//! // to make implementations of `PartialEq` and `Ord` consistent. +//! other.cost.cmp(&self.cost) +//! .then_with(|| self.position.cmp(&other.position)) +//! } +//! } +//! +//! // `PartialOrd` needs to be implemented as well. +//! impl PartialOrd for State { +//! fn partial_cmp(&self, other: &Self) -> Option { +//! Some(self.cmp(other)) +//! } +//! } +//! +//! // Each node is represented as an `usize`, for a shorter implementation. +//! struct Edge { +//! node: usize, +//! cost: usize, +//! } +//! +//! // Dijkstra's shortest path algorithm. +//! +//! // Start at `start` and use `dist` to track the current shortest distance +//! // to each node. This implementation isn't memory-efficient as it may leave duplicate +//! // nodes in the queue. It also uses `usize::MAX` as a sentinel value, +//! // for a simpler implementation. +//! fn shortest_path(adj_list: &Vec>, start: usize, goal: usize) -> Option { +//! // dist[node] = current shortest distance from `start` to `node` +//! let mut dist: Vec<_> = (0..adj_list.len()).map(|_| usize::MAX).collect(); +//! +//! let mut heap = BinaryHeap::new(); +//! +//! // We're at `start`, with a zero cost +//! dist[start] = 0; +//! heap.push(State { cost: 0, position: start }); +//! +//! // Examine the frontier with lower cost nodes first (min-heap) +//! while let Some(State { cost, position }) = heap.pop() { +//! // Alternatively we could have continued to find all shortest paths +//! if position == goal { return Some(cost); } +//! +//! // Important as we may have already found a better way +//! if cost > dist[position] { continue; } +//! +//! // For each node we can reach, see if we can find a way with +//! // a lower cost going through this node +//! for edge in &adj_list[position] { +//! let next = State { cost: cost + edge.cost, position: edge.node }; +//! +//! // If so, add it to the frontier and continue +//! if next.cost < dist[next.position] { +//! heap.push(next); +//! // Relaxation, we have now found a better way +//! dist[next.position] = next.cost; +//! } +//! } +//! } +//! +//! // Goal not reachable +//! None +//! } +//! +//! fn main() { +//! // This is the directed graph we're going to use. +//! // The node numbers correspond to the different states, +//! // and the edge weights symbolize the cost of moving +//! // from one node to another. +//! // Note that the edges are one-way. +//! // +//! // 7 +//! // +-----------------+ +//! // | | +//! // v 1 2 | 2 +//! // 0 -----> 1 -----> 3 ---> 4 +//! // | ^ ^ ^ +//! // | | 1 | | +//! // | | | 3 | 1 +//! // +------> 2 -------+ | +//! // 10 | | +//! // +---------------+ +//! // +//! // The graph is represented as an adjacency list where each index, +//! // corresponding to a node value, has a list of outgoing edges. +//! // Chosen for its efficiency. +//! let graph = vec![ +//! // Node 0 +//! vec![Edge { node: 2, cost: 10 }, +//! Edge { node: 1, cost: 1 }], +//! // Node 1 +//! vec![Edge { node: 3, cost: 2 }], +//! // Node 2 +//! vec![Edge { node: 1, cost: 1 }, +//! Edge { node: 3, cost: 3 }, +//! Edge { node: 4, cost: 1 }], +//! // Node 3 +//! vec![Edge { node: 0, cost: 7 }, +//! Edge { node: 4, cost: 2 }], +//! // Node 4 +//! vec![]]; +//! +//! assert_eq!(shortest_path(&graph, 0, 1), Some(1)); +//! assert_eq!(shortest_path(&graph, 0, 3), Some(3)); +//! assert_eq!(shortest_path(&graph, 3, 0), Some(7)); +//! assert_eq!(shortest_path(&graph, 0, 4), Some(5)); +//! assert_eq!(shortest_path(&graph, 4, 0), None); +//! } +//! ``` + +#![allow(missing_docs)] +#![stable(feature = "rust1", since = "1.0.0")] + +use core::fmt; +use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; +use core::mem::{self, swap, ManuallyDrop}; +use core::ops::{Deref, DerefMut}; +use core::ptr; + +use crate::slice; +use crate::vec::{self, AsIntoIter, Vec}; + +use super::SpecExtend; + +/// A priority queue implemented with a binary heap. +/// +/// This will be a max-heap. +/// +/// It is a logic error for an item to be modified in such a way that the +/// item's ordering relative to any other item, as determined by the `Ord` +/// trait, changes while it is in the heap. This is normally only possible +/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. The +/// behavior resulting from such a logic error is not specified, but will +/// not result in undefined behavior. This could include panics, incorrect +/// results, aborts, memory leaks, and non-termination. +/// +/// # Examples +/// +/// ``` +/// use std::collections::BinaryHeap; +/// +/// // Type inference lets us omit an explicit type signature (which +/// // would be `BinaryHeap` in this example). +/// let mut heap = BinaryHeap::new(); +/// +/// // We can use peek to look at the next item in the heap. In this case, +/// // there's no items in there yet so we get None. +/// assert_eq!(heap.peek(), None); +/// +/// // Let's add some scores... +/// heap.push(1); +/// heap.push(5); +/// heap.push(2); +/// +/// // Now peek shows the most important item in the heap. +/// assert_eq!(heap.peek(), Some(&5)); +/// +/// // We can check the length of a heap. +/// assert_eq!(heap.len(), 3); +/// +/// // We can iterate over the items in the heap, although they are returned in +/// // a random order. +/// for x in &heap { +/// println!("{}", x); +/// } +/// +/// // If we instead pop these scores, they should come back in order. +/// assert_eq!(heap.pop(), Some(5)); +/// assert_eq!(heap.pop(), Some(2)); +/// assert_eq!(heap.pop(), Some(1)); +/// assert_eq!(heap.pop(), None); +/// +/// // We can clear the heap of any remaining items. +/// heap.clear(); +/// +/// // The heap should now be empty. +/// assert!(heap.is_empty()) +/// ``` +/// +/// ## Min-heap +/// +/// Either `std::cmp::Reverse` or a custom `Ord` implementation can be used to +/// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest +/// value instead of the greatest one. +/// +/// ``` +/// use std::collections::BinaryHeap; +/// use std::cmp::Reverse; +/// +/// let mut heap = BinaryHeap::new(); +/// +/// // Wrap values in `Reverse` +/// heap.push(Reverse(1)); +/// heap.push(Reverse(5)); +/// heap.push(Reverse(2)); +/// +/// // If we pop these scores now, they should come back in the reverse order. +/// assert_eq!(heap.pop(), Some(Reverse(1))); +/// assert_eq!(heap.pop(), Some(Reverse(2))); +/// assert_eq!(heap.pop(), Some(Reverse(5))); +/// assert_eq!(heap.pop(), None); +/// ``` +/// +/// # Time complexity +/// +/// | [push] | [pop] | [peek]/[peek\_mut] | +/// |--------|-----------|--------------------| +/// | O(1)~ | *O*(log(*n*)) | *O*(1) | +/// +/// The value for `push` is an expected cost; the method documentation gives a +/// more detailed analysis. +/// +/// [push]: BinaryHeap::push +/// [pop]: BinaryHeap::pop +/// [peek]: BinaryHeap::peek +/// [peek\_mut]: BinaryHeap::peek_mut +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")] +pub struct BinaryHeap { + data: Vec, +} + +/// Structure wrapping a mutable reference to the greatest item on a +/// `BinaryHeap`. +/// +/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See +/// its documentation for more. +/// +/// [`peek_mut`]: BinaryHeap::peek_mut +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +pub struct PeekMut<'a, T: 'a + Ord> { + heap: &'a mut BinaryHeap, + sift: bool, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for PeekMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish() + } +} + +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +impl Drop for PeekMut<'_, T> { + fn drop(&mut self) { + if self.sift { + // SAFETY: PeekMut is only instantiated for non-empty heaps. + unsafe { self.heap.sift_down(0) }; + } + } +} + +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +impl Deref for PeekMut<'_, T> { + type Target = T; + fn deref(&self) -> &T { + debug_assert!(!self.heap.is_empty()); + // SAFE: PeekMut is only instantiated for non-empty heaps + unsafe { self.heap.data.get_unchecked(0) } + } +} + +#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] +impl DerefMut for PeekMut<'_, T> { + fn deref_mut(&mut self) -> &mut T { + debug_assert!(!self.heap.is_empty()); + self.sift = true; + // SAFE: PeekMut is only instantiated for non-empty heaps + unsafe { self.heap.data.get_unchecked_mut(0) } + } +} + +impl<'a, T: Ord> PeekMut<'a, T> { + /// Removes the peeked value from the heap and returns it. + #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")] + pub fn pop(mut this: PeekMut<'a, T>) -> T { + let value = this.heap.pop().unwrap(); + this.sift = false; + value + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BinaryHeap { + fn clone(&self) -> Self { + BinaryHeap { data: self.data.clone() } + } + + fn clone_from(&mut self, source: &Self) { + self.data.clone_from(&source.data); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for BinaryHeap { + /// Creates an empty `BinaryHeap`. + #[inline] + fn default() -> BinaryHeap { + BinaryHeap::new() + } +} + +#[stable(feature = "binaryheap_debug", since = "1.4.0")] +impl fmt::Debug for BinaryHeap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +impl BinaryHeap { + /// Creates an empty `BinaryHeap` as a max-heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> BinaryHeap { + BinaryHeap { data: vec![] } + } + + /// Creates an empty `BinaryHeap` with a specific capacity. + /// This preallocates enough memory for `capacity` elements, + /// so that the `BinaryHeap` does not have to be reallocated + /// until it contains at least that many values. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::with_capacity(10); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> BinaryHeap { + BinaryHeap { data: Vec::with_capacity(capacity) } + } + + /// Returns a mutable reference to the greatest item in the binary heap, or + /// `None` if it is empty. + /// + /// Note: If the `PeekMut` value is leaked, the heap may be in an + /// inconsistent state. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// assert!(heap.peek_mut().is_none()); + /// + /// heap.push(1); + /// heap.push(5); + /// heap.push(2); + /// { + /// let mut val = heap.peek_mut().unwrap(); + /// *val = 0; + /// } + /// assert_eq!(heap.peek(), Some(&2)); + /// ``` + /// + /// # Time complexity + /// + /// If the item is modified then the worst case time complexity is *O*(log(*n*)), + /// otherwise it's *O*(1). + #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] + pub fn peek_mut(&mut self) -> Option> { + if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: false }) } + } + + /// Removes the greatest item from the binary heap and returns it, or `None` if it + /// is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from(vec![1, 3]); + /// + /// assert_eq!(heap.pop(), Some(3)); + /// assert_eq!(heap.pop(), Some(1)); + /// assert_eq!(heap.pop(), None); + /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)). + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + self.data.pop().map(|mut item| { + if !self.is_empty() { + swap(&mut item, &mut self.data[0]); + // SAFETY: !self.is_empty() means that self.len() > 0 + unsafe { self.sift_down_to_bottom(0) }; + } + item + }) + } + + /// Pushes an item onto the binary heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.push(3); + /// heap.push(5); + /// heap.push(1); + /// + /// assert_eq!(heap.len(), 3); + /// assert_eq!(heap.peek(), Some(&5)); + /// ``` + /// + /// # Time complexity + /// + /// The expected cost of `push`, averaged over every possible ordering of + /// the elements being pushed, and over a sufficiently large number of + /// pushes, is *O*(1). This is the most meaningful cost metric when pushing + /// elements that are *not* already in any sorted pattern. + /// + /// The time complexity degrades if elements are pushed in predominantly + /// ascending order. In the worst case, elements are pushed in ascending + /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap + /// containing *n* elements. + /// + /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case + /// occurs when capacity is exhausted and needs a resize. The resize cost + /// has been amortized in the previous figures. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, item: T) { + let old_len = self.len(); + self.data.push(item); + // SAFETY: Since we pushed a new item it means that + // old_len = self.len() - 1 < self.len() + unsafe { self.sift_up(0, old_len) }; + } + + /// Consumes the `BinaryHeap` and returns a vector in sorted + /// (ascending) order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::from(vec![1, 2, 4, 5, 7]); + /// heap.push(6); + /// heap.push(3); + /// + /// let vec = heap.into_sorted_vec(); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]); + /// ``` + #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] + pub fn into_sorted_vec(mut self) -> Vec { + let mut end = self.len(); + while end > 1 { + end -= 1; + // SAFETY: `end` goes from `self.len() - 1` to 1 (both included), + // so it's always a valid index to access. + // It is safe to access index 0 (i.e. `ptr`), because + // 1 <= end < self.len(), which means self.len() >= 2. + unsafe { + let ptr = self.data.as_mut_ptr(); + ptr::swap(ptr, ptr.add(end)); + } + // SAFETY: `end` goes from `self.len() - 1` to 1 (both included) so: + // 0 < 1 <= end <= self.len() - 1 < self.len() + // Which means 0 < end and end < self.len(). + unsafe { self.sift_down_range(0, end) }; + } + self.into_vec() + } + + // The implementations of sift_up and sift_down use unsafe blocks in + // order to move an element out of the vector (leaving behind a + // hole), shift along the others and move the removed element back into the + // vector at the final location of the hole. + // The `Hole` type is used to represent this, and make sure + // the hole is filled back at the end of its scope, even on panic. + // Using a hole reduces the constant factor compared to using swaps, + // which involves twice as many moves. + + /// # Safety + /// + /// The caller must guarantee that `pos < self.len()`. + unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize { + // Take out the value at `pos` and create a hole. + // SAFETY: The caller guarantees that pos < self.len() + let mut hole = unsafe { Hole::new(&mut self.data, pos) }; + + while hole.pos() > start { + let parent = (hole.pos() - 1) / 2; + + // SAFETY: hole.pos() > start >= 0, which means hole.pos() > 0 + // and so hole.pos() - 1 can't underflow. + // This guarantees that parent < hole.pos() so + // it's a valid index and also != hole.pos(). + if hole.element() <= unsafe { hole.get(parent) } { + break; + } + + // SAFETY: Same as above + unsafe { hole.move_to(parent) }; + } + + hole.pos() + } + + /// Take an element at `pos` and move it down the heap, + /// while its children are larger. + /// + /// # Safety + /// + /// The caller must guarantee that `pos < end <= self.len()`. + unsafe fn sift_down_range(&mut self, pos: usize, end: usize) { + // SAFETY: The caller guarantees that pos < end <= self.len(). + let mut hole = unsafe { Hole::new(&mut self.data, pos) }; + let mut child = 2 * hole.pos() + 1; + + // Loop invariant: child == 2 * hole.pos() + 1. + while child <= end.saturating_sub(2) { + // compare with the greater of the two children + // SAFETY: child < end - 1 < self.len() and + // child + 1 < end <= self.len(), so they're valid indexes. + // child == 2 * hole.pos() + 1 != hole.pos() and + // child + 1 == 2 * hole.pos() + 2 != hole.pos(). + // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow + // if T is a ZST + child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize; + + // if we are already in order, stop. + // SAFETY: child is now either the old child or the old child+1 + // We already proven that both are < self.len() and != hole.pos() + if hole.element() >= unsafe { hole.get(child) } { + return; + } + + // SAFETY: same as above. + unsafe { hole.move_to(child) }; + child = 2 * hole.pos() + 1; + } + + // SAFETY: && short circuit, which means that in the + // second condition it's already true that child == end - 1 < self.len(). + if child == end - 1 && hole.element() < unsafe { hole.get(child) } { + // SAFETY: child is already proven to be a valid index and + // child == 2 * hole.pos() + 1 != hole.pos(). + unsafe { hole.move_to(child) }; + } + } + + /// # Safety + /// + /// The caller must guarantee that `pos < self.len()`. + unsafe fn sift_down(&mut self, pos: usize) { + let len = self.len(); + // SAFETY: pos < len is guaranteed by the caller and + // obviously len = self.len() <= self.len(). + unsafe { self.sift_down_range(pos, len) }; + } + + /// Take an element at `pos` and move it all the way down the heap, + /// then sift it up to its position. + /// + /// Note: This is faster when the element is known to be large / should + /// be closer to the bottom. + /// + /// # Safety + /// + /// The caller must guarantee that `pos < self.len()`. + unsafe fn sift_down_to_bottom(&mut self, mut pos: usize) { + let end = self.len(); + let start = pos; + + // SAFETY: The caller guarantees that pos < self.len(). + let mut hole = unsafe { Hole::new(&mut self.data, pos) }; + let mut child = 2 * hole.pos() + 1; + + // Loop invariant: child == 2 * hole.pos() + 1. + while child <= end.saturating_sub(2) { + // SAFETY: child < end - 1 < self.len() and + // child + 1 < end <= self.len(), so they're valid indexes. + // child == 2 * hole.pos() + 1 != hole.pos() and + // child + 1 == 2 * hole.pos() + 2 != hole.pos(). + // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow + // if T is a ZST + child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize; + + // SAFETY: Same as above + unsafe { hole.move_to(child) }; + child = 2 * hole.pos() + 1; + } + + if child == end - 1 { + // SAFETY: child == end - 1 < self.len(), so it's a valid index + // and child == 2 * hole.pos() + 1 != hole.pos(). + unsafe { hole.move_to(child) }; + } + pos = hole.pos(); + drop(hole); + + // SAFETY: pos is the position in the hole and was already proven + // to be a valid index. + unsafe { self.sift_up(start, pos) }; + } + + /// Rebuild assuming data[0..start] is still a proper heap. + fn rebuild_tail(&mut self, start: usize) { + if start == self.len() { + return; + } + + let tail_len = self.len() - start; + + #[inline(always)] + fn log2_fast(x: usize) -> usize { + (usize::BITS - x.leading_zeros() - 1) as usize + } + + // `rebuild` takes O(self.len()) operations + // and about 2 * self.len() comparisons in the worst case + // while repeating `sift_up` takes O(tail_len * log(start)) operations + // and about 1 * tail_len * log_2(start) comparisons in the worst case, + // assuming start >= tail_len. For larger heaps, the crossover point + // no longer follows this reasoning and was determined empirically. + let better_to_rebuild = if start < tail_len { + true + } else if self.len() <= 2048 { + 2 * self.len() < tail_len * log2_fast(start) + } else { + 2 * self.len() < tail_len * 11 + }; + + if better_to_rebuild { + self.rebuild(); + } else { + for i in start..self.len() { + // SAFETY: The index `i` is always less than self.len(). + unsafe { self.sift_up(0, i) }; + } + } + } + + fn rebuild(&mut self) { + let mut n = self.len() / 2; + while n > 0 { + n -= 1; + // SAFETY: n starts from self.len() / 2 and goes down to 0. + // The only case when !(n < self.len()) is if + // self.len() == 0, but it's ruled out by the loop condition. + unsafe { self.sift_down(n) }; + } + } + + /// Moves all the elements of `other` into `self`, leaving `other` empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let v = vec![-10, 1, 2, 3, 3]; + /// let mut a = BinaryHeap::from(v); + /// + /// let v = vec![-20, 5, 43]; + /// let mut b = BinaryHeap::from(v); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); + /// assert!(b.is_empty()); + /// ``` + #[stable(feature = "binary_heap_append", since = "1.11.0")] + pub fn append(&mut self, other: &mut Self) { + if self.len() < other.len() { + swap(self, other); + } + + let start = self.data.len(); + + self.data.append(&mut other.data); + + self.rebuild_tail(start); + } + + /// Returns an iterator which retrieves elements in heap order. + /// The retrieved elements are removed from the original heap. + /// The remaining elements will be removed on drop in heap order. + /// + /// Note: + /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`. + /// You should use the latter for most cases. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_drain_sorted)] + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]); + /// assert_eq!(heap.len(), 5); + /// + /// drop(heap.drain_sorted()); // removes all elements in heap order + /// assert_eq!(heap.len(), 0); + /// ``` + #[inline] + #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] + pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> { + DrainSorted { inner: self } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns + /// `false`. The elements are visited in unsorted (and unspecified) order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_retain)] + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::from(vec![-10, -5, 1, 2, 4, 13]); + /// + /// heap.retain(|x| x % 2 == 0); // only keep even numbers + /// + /// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4]) + /// ``` + #[unstable(feature = "binary_heap_retain", issue = "71503")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + let mut first_removed = self.len(); + let mut i = 0; + self.data.retain(|e| { + let keep = f(e); + if !keep && i < first_removed { + first_removed = i; + } + i += 1; + keep + }); + // data[0..first_removed] is untouched, so we only need to rebuild the tail: + self.rebuild_tail(first_removed); + } +} + +impl BinaryHeap { + /// Returns an iterator visiting all values in the underlying vector, in + /// arbitrary order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in heap.iter() { + /// println!("{}", x); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter<'_, T> { + Iter { iter: self.data.iter() } + } + + /// Returns an iterator which retrieves elements in heap order. + /// This method consumes the original heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_into_iter_sorted)] + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(heap.into_iter_sorted().take(2).collect::>(), vec![5, 4]); + /// ``` + #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] + pub fn into_iter_sorted(self) -> IntoIterSorted { + IntoIterSorted { inner: self } + } + + /// Returns the greatest item in the binary heap, or `None` if it is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// assert_eq!(heap.peek(), None); + /// + /// heap.push(1); + /// heap.push(5); + /// heap.push(2); + /// assert_eq!(heap.peek(), Some(&5)); + /// + /// ``` + /// + /// # Time complexity + /// + /// Cost is *O*(1) in the worst case. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn peek(&self) -> Option<&T> { + self.data.get(0) + } + + /// Returns the number of elements the binary heap can hold without reallocating. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::with_capacity(100); + /// assert!(heap.capacity() >= 100); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.data.capacity() + } + + /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the + /// given `BinaryHeap`. Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it requests. Therefore + /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future + /// insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.reserve_exact(100); + /// assert!(heap.capacity() >= 100); + /// heap.push(4); + /// ``` + /// + /// [`reserve`]: BinaryHeap::reserve + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.data.reserve_exact(additional); + } + + /// Reserves capacity for at least `additional` more elements to be inserted in the + /// `BinaryHeap`. The collection may reserve more space to avoid frequent reallocations. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// heap.reserve(100); + /// assert!(heap.capacity() >= 100); + /// heap.push(4); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.data.reserve(additional); + } + + /// Discards as much additional capacity as possible. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to_fit(); + /// assert!(heap.capacity() == 0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + self.data.shrink_to_fit(); + } + + /// Discards capacity with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to(10); + /// assert!(heap.capacity() >= 10); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.data.shrink_to(min_capacity) + } + + /// Returns a slice of all values in the underlying vector, in arbitrary + /// order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_as_slice)] + /// use std::collections::BinaryHeap; + /// use std::io::{self, Write}; + /// + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]); + /// + /// io::sink().write(heap.as_slice()).unwrap(); + /// ``` + #[unstable(feature = "binary_heap_as_slice", issue = "83659")] + pub fn as_slice(&self) -> &[T] { + self.data.as_slice() + } + + /// Consumes the `BinaryHeap` and returns the underlying vector + /// in arbitrary order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]); + /// let vec = heap.into_vec(); + /// + /// // Will print in some order + /// for x in vec { + /// println!("{}", x); + /// } + /// ``` + #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] + pub fn into_vec(self) -> Vec { + self.into() + } + + /// Returns the length of the binary heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from(vec![1, 3]); + /// + /// assert_eq!(heap.len(), 2); + /// ``` + #[doc(alias = "length")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.data.len() + } + + /// Checks if the binary heap is empty. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new(); + /// + /// assert!(heap.is_empty()); + /// + /// heap.push(3); + /// heap.push(5); + /// heap.push(1); + /// + /// assert!(!heap.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears the binary heap, returning an iterator over the removed elements. + /// + /// The elements are removed in arbitrary order. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from(vec![1, 3]); + /// + /// assert!(!heap.is_empty()); + /// + /// for x in heap.drain() { + /// println!("{}", x); + /// } + /// + /// assert!(heap.is_empty()); + /// ``` + #[inline] + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self) -> Drain<'_, T> { + Drain { iter: self.data.drain(..) } + } + + /// Drops all items from the binary heap. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from(vec![1, 3]); + /// + /// assert!(!heap.is_empty()); + /// + /// heap.clear(); + /// + /// assert!(heap.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.drain(); + } +} + +/// Hole represents a hole in a slice i.e., an index without valid value +/// (because it was moved from or duplicated). +/// In drop, `Hole` will restore the slice by filling the hole +/// position with the value that was originally removed. +struct Hole<'a, T: 'a> { + data: &'a mut [T], + elt: ManuallyDrop, + pos: usize, +} + +impl<'a, T> Hole<'a, T> { + /// Create a new `Hole` at index `pos`. + /// + /// Unsafe because pos must be within the data slice. + #[inline] + unsafe fn new(data: &'a mut [T], pos: usize) -> Self { + debug_assert!(pos < data.len()); + // SAFE: pos should be inside the slice + let elt = unsafe { ptr::read(data.get_unchecked(pos)) }; + Hole { data, elt: ManuallyDrop::new(elt), pos } + } + + #[inline] + fn pos(&self) -> usize { + self.pos + } + + /// Returns a reference to the element removed. + #[inline] + fn element(&self) -> &T { + &self.elt + } + + /// Returns a reference to the element at `index`. + /// + /// Unsafe because index must be within the data slice and not equal to pos. + #[inline] + unsafe fn get(&self, index: usize) -> &T { + debug_assert!(index != self.pos); + debug_assert!(index < self.data.len()); + unsafe { self.data.get_unchecked(index) } + } + + /// Move hole to new location + /// + /// Unsafe because index must be within the data slice and not equal to pos. + #[inline] + unsafe fn move_to(&mut self, index: usize) { + debug_assert!(index != self.pos); + debug_assert!(index < self.data.len()); + unsafe { + let ptr = self.data.as_mut_ptr(); + let index_ptr: *const _ = ptr.add(index); + let hole_ptr = ptr.add(self.pos); + ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1); + } + self.pos = index; + } +} + +impl Drop for Hole<'_, T> { + #[inline] + fn drop(&mut self) { + // fill the hole again + unsafe { + let pos = self.pos; + ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1); + } + } +} + +/// An iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::iter()`]. See its +/// documentation for more. +/// +/// [`iter`]: BinaryHeap::iter +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + iter: slice::Iter<'a, T>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Iter").field(&self.iter.as_slice()).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { iter: self.iter.clone() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + + #[inline] + fn last(self) -> Option<&'a T> { + self.iter.last() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + self.iter.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +/// An owning iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::into_iter()`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: BinaryHeap::into_iter +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] +pub struct IntoIter { + iter: vec::IntoIter, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for IntoIter { + type Source = IntoIter; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for IntoIter {} + +impl AsIntoIter for IntoIter { + type Item = I; + + fn as_into_iter(&mut self) -> &mut vec::IntoIter { + &mut self.iter + } +} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +#[derive(Clone, Debug)] +pub struct IntoIterSorted { + inner: BinaryHeap, +} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +impl Iterator for IntoIterSorted { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = self.inner.len(); + (exact, Some(exact)) + } +} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +impl ExactSizeIterator for IntoIterSorted {} + +#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] +impl FusedIterator for IntoIterSorted {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIterSorted {} + +/// A draining iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::drain()`]. See its +/// documentation for more. +/// +/// [`drain`]: BinaryHeap::drain +#[stable(feature = "drain", since = "1.6.0")] +#[derive(Debug)] +pub struct Drain<'a, T: 'a> { + iter: vec::Drain<'a, T>, +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T> {} + +/// A draining iterator over the elements of a `BinaryHeap`. +/// +/// This `struct` is created by [`BinaryHeap::drain_sorted()`]. See its +/// documentation for more. +/// +/// [`drain_sorted`]: BinaryHeap::drain_sorted +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +#[derive(Debug)] +pub struct DrainSorted<'a, T: Ord> { + inner: &'a mut BinaryHeap, +} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl<'a, T: Ord> Drop for DrainSorted<'a, T> { + /// Removes heap elements in heap order. + fn drop(&mut self) { + struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>); + + impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> { + fn drop(&mut self) { + while self.0.inner.pop().is_some() {} + } + } + + while let Some(item) = self.inner.pop() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + } +} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl Iterator for DrainSorted<'_, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = self.inner.len(); + (exact, Some(exact)) + } +} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl ExactSizeIterator for DrainSorted<'_, T> {} + +#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] +impl FusedIterator for DrainSorted<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for DrainSorted<'_, T> {} + +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] +impl From> for BinaryHeap { + /// Converts a `Vec` into a `BinaryHeap`. + /// + /// This conversion happens in-place, and has *O*(*n*) time complexity. + fn from(vec: Vec) -> BinaryHeap { + let mut heap = BinaryHeap { data: vec }; + heap.rebuild(); + heap + } +} + +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] +impl From> for Vec { + /// Converts a `BinaryHeap` into a `Vec`. + /// + /// This conversion requires no data movement or allocation, and has + /// constant time complexity. + fn from(heap: BinaryHeap) -> Vec { + heap.data + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for BinaryHeap { + fn from_iter>(iter: I) -> BinaryHeap { + BinaryHeap::from(iter.into_iter().collect::>()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BinaryHeap { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the binary heap in arbitrary order. The binary heap cannot be used + /// after calling this. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from(vec![1, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in heap.into_iter() { + /// // x has type i32, not &i32 + /// println!("{}", x); + /// } + /// ``` + fn into_iter(self) -> IntoIter { + IntoIter { iter: self.data.into_iter() } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a BinaryHeap { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for BinaryHeap { + #[inline] + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter); + } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +impl> SpecExtend for BinaryHeap { + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter.into_iter()); + } +} + +impl SpecExtend> for BinaryHeap { + fn spec_extend(&mut self, ref mut other: BinaryHeap) { + self.append(other); + } +} + +impl BinaryHeap { + fn extend_desugared>(&mut self, iter: I) { + let iterator = iter.into_iter(); + let (lower, _) = iterator.size_hint(); + + self.reserve(lower); + + iterator.for_each(move |elem| self.push(elem)); + } +} + +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap { + fn extend>(&mut self, iter: I) { + self.extend(iter.into_iter().cloned()); + } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} +use crate::alloc::{Allocator, Global}; +use crate::raw_vec::RawVec; +use core::fmt; +use core::intrinsics::arith_offset; +use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess}; +use core::marker::PhantomData; +use core::mem::{self}; +use core::ptr::{self, NonNull}; +use core::slice::{self}; + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec) +/// (provided by the [`IntoIterator`] trait). +/// +/// # Example +/// +/// ``` +/// let v = vec![0, 1, 2]; +/// let iter: std::vec::IntoIter<_> = v.into_iter(); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + pub(super) buf: NonNull, + pub(super) phantom: PhantomData, + pub(super) cap: usize, + pub(super) alloc: A, + pub(super) ptr: *const T, + pub(super) end: *const T, +} + +#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// let _ = into_iter.next().unwrap(); + /// assert_eq!(into_iter.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr, self.len()) } + } + + /// Returns the remaining items of this iterator as a mutable slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// into_iter.as_mut_slice()[2] = 'z'; + /// assert_eq!(into_iter.next().unwrap(), 'a'); + /// assert_eq!(into_iter.next().unwrap(), 'b'); + /// assert_eq!(into_iter.next().unwrap(), 'z'); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { &mut *self.as_raw_mut_slice() } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + &self.alloc + } + + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) + } + + /// Drops remaining elements and relinquishes the backing allocation. + /// + /// This is roughly equivalent to the following, but more efficient + /// + /// ``` + /// # let mut into_iter = Vec::::with_capacity(10).into_iter(); + /// (&mut into_iter).for_each(core::mem::drop); + /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); } + /// ``` + pub(super) fn forget_allocation_drop_remaining(&mut self) { + let remaining = self.as_raw_mut_slice(); + + // overwrite the individual fields instead of creating a new + // struct and then overwriting &mut self. + // this creates less assembly + self.cap = 0; + self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.ptr = self.buf.as_ptr(); + self.end = self.buf.as_ptr(); + + unsafe { + ptr::drop_in_place(remaining); + } + } +} + +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl AsRef<[T]> for IntoIter { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IntoIter {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.ptr as *const _ == self.end { + None + } else if mem::size_of::() == 0 { + // purposefully don't use 'ptr.offset' because for + // vectors with 0-size elements this would return the + // same pointer. + self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + let old = self.ptr; + self.ptr = unsafe { self.ptr.offset(1) }; + + Some(unsafe { ptr::read(old) }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = if mem::size_of::() == 0 { + (self.end as usize).wrapping_sub(self.ptr as usize) + } else { + unsafe { self.end.offset_from(self.ptr) as usize } + }; + (exact, Some(exact)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: the caller must guarantee that `i` is in bounds of the + // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` + // is guaranteed to pointer to an element of the `Vec` and + // thus guaranteed to be valid to dereference. + // + // Also note the implementation of `Self: TrustedRandomAccess` requires + // that `T: Copy` so reading elements from the buffer doesn't invalidate + // them for `Drop`. + unsafe { + if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if self.end == self.ptr { + None + } else if mem::size_of::() == 0 { + // See above for why 'ptr.offset' isn't used + self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + self.end = unsafe { self.end.offset(-1) }; + + Some(unsafe { ptr::read(self.end) }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.ptr == self.end + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr +// and thus we can't implement drop-handling +unsafe impl TrustedRandomAccess for IntoIter +where + T: Copy, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + +#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] +impl Clone for IntoIter { + #[cfg(not(test))] + fn clone(&self) -> Self { + self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + } + #[cfg(test)] + fn clone(&self) -> Self { + crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { + fn drop(&mut self) { + struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T, A> { + fn drop(&mut self) { + unsafe { + // `IntoIter::alloc` is not used anymore after this + let alloc = ptr::read(&self.0.alloc); + // RawVec handles deallocation + let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + } + } + } + + let guard = DropGuard(self); + // destroy the remaining elements + unsafe { + ptr::drop_in_place(guard.0.as_raw_mut_slice()); + } + // now `guard` will be dropped and do the rest + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for IntoIter {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for IntoIter { + type Source = Self; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} + +// internal helper trait for in-place iteration specialization. +#[rustc_specialization_trait] +pub(crate) trait AsIntoIter { + type Item; + fn as_into_iter(&mut self) -> &mut IntoIter; +} + +impl AsIntoIter for IntoIter { + type Item = T; + + fn as_into_iter(&mut self) -> &mut IntoIter { + self + } +} +use crate::alloc::Allocator; +use core::iter::TrustedLen; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{IntoIter, SetLenOnDrop, Vec}; + +// Specialization trait used for Vec::extend +pub(super) trait SpecExtend { + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for Vec +where + I: Iterator, +{ + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter) + } +} + +impl SpecExtend for Vec +where + I: TrustedLen, +{ + default fn spec_extend(&mut self, iterator: I) { + // This is the case for a TrustedLen iterator. + let (low, high) = iterator.size_hint(); + if let Some(additional) = high { + debug_assert_eq!( + low, + additional, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + self.reserve(additional); + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + let mut local_len = SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + }); + } + } else { + // Per TrustedLen contract a `None` upper bound means that the iterator length + // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway. + // Since the other branch already panics eagerly (via `reserve()`) we do the same here. + // This avoids additional codegen for a fallback code path which would eventually + // panic anyway. + panic!("capacity overflow"); + } + } +} + +impl SpecExtend> for Vec { + fn spec_extend(&mut self, mut iterator: IntoIter) { + unsafe { + self.append_elements(iterator.as_slice() as _); + } + iterator.ptr = iterator.end; + } +} + +impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.cloned()) + } +} + +impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec +where + T: Copy, +{ + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice = iterator.as_slice(); + unsafe { self.append_elements(slice) }; + } +} +use crate::alloc::Allocator; +use crate::raw_vec::RawVec; +use core::ptr::{self}; + +use super::{ExtendElement, IsZero, Vec}; + +// Specialization trait used for Vec::from_elem +pub(super) trait SpecFromElem: Sized { + fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; +} + +impl SpecFromElem for T { + default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +impl SpecFromElem for i8 { + #[inline] + fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for u8 { + #[inline] + fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for T { + #[inline] + fn from_elem(elem: T, n: usize, alloc: A) -> Vec { + if elem.is_zero() { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} +use crate::alloc::{Allocator, Global}; +use core::fmt; +use core::iter::{FusedIterator, TrustedLen}; +use core::mem::{self}; +use core::ptr::{self, NonNull}; +use core::slice::{self}; + +use super::Vec; + +/// A draining iterator for `Vec`. +/// +/// This `struct` is created by [`Vec::drain`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::Drain<_> = v.drain(..); +/// ``` +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + /// Index of tail to preserve + pub(super) tail_start: usize, + /// Length of tail + pub(super) tail_len: usize, + /// Current remaining range to remove + pub(super) iter: slice::Iter<'a, T>, + pub(super) vec: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() + } +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!['a', 'b', 'c']; + /// let mut drain = vec.drain(..); + /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] + pub fn as_slice(&self) -> &[T] { + self.iter.as_slice() + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + unsafe { self.vec.as_ref().allocator() } + } +} + +#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] +impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + /// Continues dropping the remaining elements in the `Drain`, then moves back the + /// un-`Drain`ed elements to restore the original `Vec`. + struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + + impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + // Continue the same loop we have below. If the loop already finished, this does + // nothing. + self.0.for_each(drop); + + if self.0.tail_len > 0 { + unsafe { + let source_vec = self.0.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.0.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.0.tail_len); + } + source_vec.set_len(start + self.0.tail_len); + } + } + } + } + + // exhaust self first + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + // Drop a `DropGuard` to move back the non-drained tail of `self`. + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} +use core::iter::TrustedLen; +use core::ptr::{self}; + +use super::{SpecExtend, Vec}; + +/// Another specialization trait for Vec::from_iter +/// necessary to manually prioritize overlapping specializations +/// see [`SpecFromIter`](super::SpecFromIter) for details. +pub(super) trait SpecFromIterNested { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIterNested for Vec +where + I: Iterator, +{ + default fn from_iter(mut iterator: I) -> Self { + // Unroll the first iteration, as the vector is going to be + // expanded on this iteration in every case when the iterable is not + // empty, but the loop in extend_desugared() is not going to see the + // vector being full in the few subsequent loop iterations. + // So we get better branch prediction. + let mut vector = match iterator.next() { + None => return Vec::new(), + Some(element) => { + let (lower, _) = iterator.size_hint(); + let mut vector = Vec::with_capacity(lower.saturating_add(1)); + unsafe { + ptr::write(vector.as_mut_ptr(), element); + vector.set_len(1); + } + vector + } + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + as SpecExtend>::spec_extend(&mut vector, iterator); + vector + } +} + +impl SpecFromIterNested for Vec +where + I: TrustedLen, +{ + fn from_iter(iterator: I) -> Self { + let mut vector = match iterator.size_hint() { + (_, Some(upper)) => Vec::with_capacity(upper), + // TrustedLen contract guarantees that `size_hint() == (_, None)` means that there + // are more than `usize::MAX` elements. + // Since the previous branch would eagerly panic if the capacity is too large + // (via `with_capacity`) we do the same here. + _ => panic!("capacity overflow"), + }; + // reuse extend specialization for TrustedLen + vector.spec_extend(iterator); + vector + } +} +use crate::boxed::Box; + +#[rustc_specialization_trait] +pub(super) unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { + ($t:ty, $is_zero:expr) => { + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + $is_zero(*self) + } + } + }; +} + +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(bool, |x| x == false); +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. +// For fat pointers, the bytes that would be the pointer metadata in the `Some` +// variant are padding in the `None` variant, so ignoring them and +// zero-initializing instead is ok. +// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of +// `SpecFromElem`. + +unsafe impl IsZero for Option<&T> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +unsafe impl IsZero for Option> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} +use core::mem::ManuallyDrop; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; + +/// Specialization trait used for Vec::from_iter +/// +/// ## The delegation graph: +/// +/// ```text +/// +-------------+ +/// |FromIterator | +/// +-+-----------+ +/// | +/// v +/// +-+-------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)----------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | SourceIterMarker---fallback-+ | | | +/// | slice::Iter | | | +/// | Iterator | +---------------------+ +/// +---------------------------------+ +/// ``` +pub(super) trait SpecFromIter { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIter for Vec +where + I: Iterator, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIterNested::from_iter(iterator) + } +} + +impl SpecFromIter> for Vec { + fn from_iter(iterator: IntoIter) -> Self { + // A common case is passing a vector into a function which immediately + // re-collects into a vector. We can short circuit this if the IntoIter + // has not been advanced at all. + // When it has been advanced We can also reuse the memory and move the data to the front. + // But we only do so when the resulting Vec wouldn't have more unused capacity + // than creating it through the generic FromIterator implementation would. That limitation + // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. + // But it is a conservative choice. + let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; + if !has_advanced || iterator.len() >= iterator.cap / 2 { + unsafe { + let it = ManuallyDrop::new(iterator); + if has_advanced { + ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); + } + return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); + } + } + + let mut vec = Vec::new(); + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vec.spec_extend(iterator); + vec + } +} + +impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIter::from_iter(iterator.cloned()) + } +} + +// This utilizes `iterator.as_slice().to_vec()` since spec_extend +// must take more steps to reason about the final capacity + length +// and thus do more work. `to_vec()` directly allocates the correct amount +// and fills it exactly. +impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { + #[cfg(not(test))] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + iterator.as_slice().to_vec() + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + crate::slice::to_vec(iterator.as_slice(), crate::alloc::Global) + } +} +use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccess}; +use core::mem::{self, ManuallyDrop}; +use core::ptr::{self}; + +use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; + +/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the +/// source allocation, i.e. executing the pipeline in place. +/// +/// The SourceIter parent trait is necessary for the specializing function to access the allocation +/// which is to be reused. But it is not sufficient for the specialization to be valid. See +/// additional bounds on the impl. +#[rustc_unsafe_specialization_marker] +pub(super) trait SourceIterMarker: SourceIter {} + +// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of +// Adapter>> (all owned by core/std). Additional bounds +// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other +// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). +// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which +// several other specializations already depend on. +impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} + +impl SpecFromIter for Vec +where + I: Iterator + SourceIterMarker, +{ + default fn from_iter(mut iterator: I) -> Self { + // Additional requirements which cannot expressed via trait bounds. We rely on const eval + // instead: + // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic + // b) size match as required by Alloc contract + // c) alignments match as required by Alloc contract + if mem::size_of::() == 0 + || mem::size_of::() + != mem::size_of::<<::Source as AsIntoIter>::Item>() + || mem::align_of::() + != mem::align_of::<<::Source as AsIntoIter>::Item>() + { + // fallback to more generic implementations + return SpecFromIterNested::from_iter(iterator); + } + + let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { + let inner = iterator.as_inner().as_into_iter(); + ( + inner.buf.as_ptr(), + inner.ptr, + inner.buf.as_ptr() as *mut T, + inner.end as *const T, + inner.cap, + ) + }; + + let len = SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end); + + let src = unsafe { iterator.as_inner().as_into_iter() }; + // check if SourceIter contract was upheld + // caveat: if they weren't we may not even make it to this point + debug_assert_eq!(src_buf, src.buf.as_ptr()); + // check InPlaceIterable contract. This is only possible if the iterator advanced the + // source pointer at all. If it uses unchecked access via TrustedRandomAccess + // then the source pointer will stay in its initial position and we can't use it as reference + if src.ptr != src_ptr { + debug_assert!( + unsafe { dst_buf.add(len) as *const _ } <= src.ptr, + "InPlaceIterable contract violation, write pointer advanced beyond read pointer" + ); + } + + // drop any remaining values at the tail of the source + // but prevent drop of the allocation itself once IntoIter goes out of scope + // if the drop panics then we also leak any elements collected into dst_buf + src.forget_allocation_drop_remaining(); + + let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) }; + + vec + } +} + +fn write_in_place_with_drop( + src_end: *const T, +) -> impl FnMut(InPlaceDrop, T) -> Result, !> { + move |mut sink, item| { + unsafe { + // the InPlaceIterable contract cannot be verified precisely here since + // try_fold has an exclusive reference to the source pointer + // all we can do is check if it's still in range + debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); + ptr::write(sink.dst, item); + sink.dst = sink.dst.add(1); + } + Ok(sink) + } +} + +/// Helper trait to hold specialized implementations of the in-place iterate-collect loop +trait SpecInPlaceCollect: Iterator { + /// Collects an iterator (`self`) into the destination buffer (`dst`) and returns the number of items + /// collected. `end` is the last writable element of the allocation and used for bounds checks. + fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize; +} + +impl SpecInPlaceCollect for I +where + I: Iterator, +{ + #[inline] + default fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = + self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).unwrap(); + // iteration succeeded, don't drop head + unsafe { ManuallyDrop::new(sink).dst.offset_from(dst_buf) as usize } + } +} + +impl SpecInPlaceCollect for I +where + I: Iterator + TrustedRandomAccess, +{ + #[inline] + fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + let len = self.size(); + let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + for i in 0..len { + // Safety: InplaceIterable contract guarantees that for every element we read + // one slot in the underlying storage will have been freed up and we can immediately + // write back the result. + unsafe { + let dst = dst_buf.offset(i as isize); + debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); + ptr::write(dst, self.__iterator_get_unchecked(i)); + drop_guard.dst = dst.add(1); + } + } + mem::forget(drop_guard); + len + } +} +//! A contiguous growable array type with heap-allocated contents, written +//! `Vec`. +//! +//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and +//! `O(1)` pop (from the end). +//! +//! Vectors ensure they never allocate more than `isize::MAX` bytes. +//! +//! # Examples +//! +//! You can explicitly create a [`Vec`] with [`Vec::new`]: +//! +//! ``` +//! let v: Vec = Vec::new(); +//! ``` +//! +//! ...or by using the [`vec!`] macro: +//! +//! ``` +//! let v: Vec = vec![]; +//! +//! let v = vec![1, 2, 3, 4, 5]; +//! +//! let v = vec![0; 10]; // ten zeroes +//! ``` +//! +//! You can [`push`] values onto the end of a vector (which will grow the vector +//! as needed): +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! v.push(3); +//! ``` +//! +//! Popping values works in much the same way: +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! let two = v.pop(); +//! ``` +//! +//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits): +//! +//! ``` +//! let mut v = vec![1, 2, 3]; +//! let three = v[2]; +//! v[1] = v[1] + 5; +//! ``` +//! +//! [`push`]: Vec::push + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::{self, Ordering}; +use core::convert::TryFrom; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::intrinsics::{arith_offset, assume}; +use core::iter::{self, FromIterator}; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::ops::{self, Index, IndexMut, Range, RangeBounds}; +use core::ptr::{self, NonNull}; +use core::slice::{self, SliceIndex}; + +use crate::alloc::{Allocator, Global}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::raw_vec::RawVec; + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +pub use self::drain_filter::DrainFilter; + +mod drain_filter; + +#[stable(feature = "vec_splice", since = "1.21.0")] +pub use self::splice::Splice; + +mod splice; + +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + +mod cow; + +pub(crate) use self::into_iter::AsIntoIter; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::into_iter::IntoIter; + +mod into_iter; + +use self::is_zero::IsZero; + +mod is_zero; + +mod source_iter_marker; + +mod partial_eq; + +use self::spec_from_elem::SpecFromElem; + +mod spec_from_elem; + +use self::set_len_on_drop::SetLenOnDrop; + +mod set_len_on_drop; + +use self::in_place_drop::InPlaceDrop; + +mod in_place_drop; + +use self::spec_from_iter_nested::SpecFromIterNested; + +mod spec_from_iter_nested; + +use self::spec_from_iter::SpecFromIter; + +mod spec_from_iter; + +use self::spec_extend::SpecExtend; + +mod spec_extend; + +/// A contiguous growable array type, written as `Vec` and pronounced 'vector'. +/// +/// # Examples +/// +/// ``` +/// let mut vec = Vec::new(); +/// vec.push(1); +/// vec.push(2); +/// +/// assert_eq!(vec.len(), 2); +/// assert_eq!(vec[0], 1); +/// +/// assert_eq!(vec.pop(), Some(2)); +/// assert_eq!(vec.len(), 1); +/// +/// vec[0] = 7; +/// assert_eq!(vec[0], 7); +/// +/// vec.extend([1, 2, 3].iter().copied()); +/// +/// for x in &vec { +/// println!("{}", x); +/// } +/// assert_eq!(vec, [7, 1, 2, 3]); +/// ``` +/// +/// The [`vec!`] macro is provided to make initialization more convenient: +/// +/// ``` +/// let mut vec = vec![1, 2, 3]; +/// vec.push(4); +/// assert_eq!(vec, [1, 2, 3, 4]); +/// ``` +/// +/// It can also initialize each element of a `Vec` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: +/// +/// ``` +/// let vec = vec![0; 5]; +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec = Vec::with_capacity(5); +/// vec.resize(5, 0); +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// ``` +/// +/// For more information, see +/// [Capacity and Reallocation](#capacity-and-reallocation). +/// +/// Use a `Vec` as an efficient stack: +/// +/// ``` +/// let mut stack = Vec::new(); +/// +/// stack.push(1); +/// stack.push(2); +/// stack.push(3); +/// +/// while let Some(top) = stack.pop() { +/// // Prints 3, 2, 1 +/// println!("{}", top); +/// } +/// ``` +/// +/// # Indexing +/// +/// The `Vec` type allows to access values by index, because it implements the +/// [`Index`] trait. An example will be more explicit: +/// +/// ``` +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[1]); // it will display '2' +/// ``` +/// +/// However be careful: if you try to access an index which isn't in the `Vec`, +/// your software will panic! You cannot do this: +/// +/// ```should_panic +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[6]); // it will panic! +/// ``` +/// +/// Use [`get`] and [`get_mut`] if you want to check whether the index is in +/// the `Vec`. +/// +/// # Slicing +/// +/// A `Vec` can be mutable. On the other hand, slices are read-only objects. +/// To get a [slice][prim@slice], use [`&`]. Example: +/// +/// ``` +/// fn read_slice(slice: &[usize]) { +/// // ... +/// } +/// +/// let v = vec![0, 1]; +/// read_slice(&v); +/// +/// // ... and that's all! +/// // you can also do it like this: +/// let u: &[usize] = &v; +/// // or like this: +/// let u: &[_] = &v; +/// ``` +/// +/// In Rust, it's more common to pass slices as arguments rather than vectors +/// when you just want to provide read access. The same goes for [`String`] and +/// [`&str`]. +/// +/// # Capacity and reallocation +/// +/// The capacity of a vector is the amount of space allocated for any future +/// elements that will be added onto the vector. This is not to be confused with +/// the *length* of a vector, which specifies the number of actual elements +/// within the vector. If a vector's length exceeds its capacity, its capacity +/// will automatically be increased, but its elements will have to be +/// reallocated. +/// +/// For example, a vector with capacity 10 and length 0 would be an empty vector +/// with space for 10 more elements. Pushing 10 or fewer elements onto the +/// vector will not change its capacity or cause reallocation to occur. However, +/// if the vector's length is increased to 11, it will have to reallocate, which +/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity`] +/// whenever possible to specify how big the vector is expected to get. +/// +/// # Guarantees +/// +/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees +/// about its design. This ensures that it's as low-overhead as possible in +/// the general case, and can be correctly manipulated in primitive ways +/// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. +/// If additional type parameters are added (e.g., to support custom allocators), +/// overriding their defaults may change the behavior. +/// +/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) +/// triplet. No more, no less. The order of these fields is completely +/// unspecified, and you should use the appropriate methods to modify these. +/// The pointer will never be null, so this type is null-pointer-optimized. +/// +/// However, the pointer might not actually point to allocated memory. In particular, +/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], +/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] +/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized +/// types inside a `Vec`, it will not allocate space for them. *Note that in this case +/// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation +/// details are very subtle — if you intend to allocate memory using a `Vec` +/// and use it for something else (either to pass to unsafe code, or to build your +/// own memory-backed collection), be sure to deallocate this memory by using +/// `from_raw_parts` to recover the `Vec` and then dropping it. +/// +/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap +/// (as defined by the allocator Rust is configured to use by default), and its +/// pointer points to [`len`] initialized, contiguous elements in order (what +/// you would see if you coerced it to a slice), followed by [`capacity`]` - +/// `[`len`] logically uninitialized, contiguous elements. +/// +/// A vector containing the elements `'a'` and `'b'` with capacity 4 can be +/// visualized as below. The top part is the `Vec` struct, it contains a +/// pointer to the head of the allocation in the heap, length and capacity. +/// The bottom part is the allocation on the heap, a contiguous memory block. +/// +/// ```text +/// ptr len capacity +/// +--------+--------+--------+ +/// | 0x0123 | 2 | 4 | +/// +--------+--------+--------+ +/// | +/// v +/// Heap +--------+--------+--------+--------+ +/// | 'a' | 'b' | uninit | uninit | +/// +--------+--------+--------+--------+ +/// ``` +/// +/// - **uninit** represents memory that is not initialized, see [`MaybeUninit`]. +/// - Note: the ABI is not stable and `Vec` makes no guarantees about its memory +/// layout (including the order of fields). +/// +/// `Vec` will never perform a "small optimization" where elements are actually +/// stored on the stack for two reasons: +/// +/// * It would make it more difficult for unsafe code to correctly manipulate +/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were +/// only moved, and it would be more difficult to determine if a `Vec` had +/// actually allocated memory. +/// +/// * It would penalize the general case, incurring an additional branch +/// on every access. +/// +/// `Vec` will never automatically shrink itself, even if completely empty. This +/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` +/// and then filling it back up to the same [`len`] should incur no calls to +/// the allocator. If you wish to free up unused memory, use +/// [`shrink_to_fit`] or [`shrink_to`]. +/// +/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is +/// sufficient. [`push`] and [`insert`] *will* (re)allocate if +/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely +/// accurate, and can be relied on. It can even be used to manually free the memory +/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even +/// when not necessary. +/// +/// `Vec` does not guarantee any particular growth strategy when reallocating +/// when full, nor when [`reserve`] is called. The current strategy is basic +/// and it may prove desirable to use a non-constant growth factor. Whatever +/// strategy is used will of course guarantee *O*(1) amortized [`push`]. +/// +/// `vec![x; n]`, `vec![a, b, c, d]`, and +/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` +/// with exactly the requested capacity. If [`len`]` == `[`capacity`], +/// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to +/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. +/// +/// `Vec` will not specifically overwrite any data that is removed from it, +/// but also won't specifically preserve it. Its uninitialized memory is +/// scratch space that it may use however it wants. It will generally just do +/// whatever is most efficient or otherwise easy to implement. Do not rely on +/// removed data to be erased for security purposes. Even if you drop a `Vec`, its +/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory +/// first, that might not actually happen because the optimizer does not consider +/// this a side-effect that must be preserved. There is one case which we will +/// not break, however: using `unsafe` code to write to the excess capacity, +/// and then increasing the length to match, is always valid. +/// +/// Currently, `Vec` does not guarantee the order in which elements are dropped. +/// The order has changed in the past and may change again. +/// +/// [`get`]: ../../std/vec/struct.Vec.html#method.get +/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut +/// [`String`]: crate::string::String +/// [`&str`]: type@str +/// [`shrink_to_fit`]: Vec::shrink_to_fit +/// [`shrink_to`]: Vec::shrink_to +/// [`capacity`]: Vec::capacity +/// [`mem::size_of::`]: core::mem::size_of +/// [`len`]: Vec::len +/// [`push`]: Vec::push +/// [`insert`]: Vec::insert +/// [`reserve`]: Vec::reserve +/// [`MaybeUninit`]: core::mem::MaybeUninit +/// [owned slice]: Box +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] +pub struct Vec { + buf: RawVec, + len: usize, +} + +//////////////////////////////////////////////////////////////////////////////// +// Inherent methods +//////////////////////////////////////////////////////////////////////////////// + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// let mut vec: Vec = Vec::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn new() -> Self { + Vec { buf: RawVec::NEW, len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// ``` + #[inline] + #[doc(alias = "malloc")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } + + /// Creates a `Vec` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// use std::mem; + /// + /// let v = vec![1, 2, 3]; + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } + } +} + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// # #[allow(unused_mut)] + /// let mut vec: Vec = Vec::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + Vec { buf: RawVec::new_in(alloc), len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity with the provided + /// allocator. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut vec = Vec::with_capacity_in(10, System); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } + } + + /// Creates a `Vec` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// use std::ptr; + /// use std::mem; + /// + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// let alloc = v.allocator(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { + unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: Vec::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of the vector (in elements), + /// the allocated capacity of the data (in elements), and the allocator. These are the same + /// arguments in the same order as the arguments to [`from_raw_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts_in`]: Vec::from_raw_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, vec_into_raw_parts)] + /// + /// use std::alloc::System; + /// + /// let mut v: Vec = Vec::new_in(System); + /// v.push(-1); + /// v.push(0); + /// v.push(1); + /// + /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts_in(ptr, len, cap, alloc) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { + let mut me = ManuallyDrop::new(self); + let len = me.len(); + let capacity = me.capacity(); + let ptr = me.as_mut_ptr(); + let alloc = unsafe { ptr::read(me.allocator()) }; + (ptr, len, capacity, alloc) + } + + /// Returns the number of elements the vector can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// let vec: Vec = Vec::with_capacity(10); + /// assert_eq!(vec.capacity(), 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.buf.capacity() + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[doc(alias = "realloc")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.buf.reserve(self.len, additional); + } + + /// Reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve_exact(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[doc(alias = "realloc")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.buf.reserve_exact(self.len, additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[doc(alias = "realloc")] + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve(self.len, additional) + } + + /// Tries to reserve the minimum capacity for exactly `additional` + /// elements to be inserted in the given `Vec`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[doc(alias = "realloc")] + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve_exact(self.len, additional) + } + + /// Shrinks the capacity of the vector as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator + /// may still inform the vector that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to_fit(); + /// assert!(vec.capacity() >= 3); + /// ``` + #[doc(alias = "realloc")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + // The capacity is never less than the length, and there's nothing to do when + // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` + // by only calling it with a greater capacity. + if self.capacity() > self.len { + self.buf.shrink_to_fit(self.len); + } + } + + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[doc(alias = "realloc")] + #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] + pub fn shrink_to(&mut self, min_capacity: usize) { + if self.capacity() > min_capacity { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + } + + /// Converts the vector into [`Box<[T]>`][owned slice]. + /// + /// Note that this will drop any excess capacity. + /// + /// [owned slice]: Box + /// + /// # Examples + /// + /// ``` + /// let v = vec![1, 2, 3]; + /// + /// let slice = v.into_boxed_slice(); + /// ``` + /// + /// Any excess capacity is removed: + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// + /// assert_eq!(vec.capacity(), 10); + /// let slice = vec.into_boxed_slice(); + /// assert_eq!(slice.into_vec().capacity(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_boxed_slice(mut self) -> Box<[T], A> { + unsafe { + self.shrink_to_fit(); + let me = ManuallyDrop::new(self); + let buf = ptr::read(&me.buf); + let len = me.len(); + buf.into_box(len).assume_init() + } + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector's current length, this has no + /// effect. + /// + /// The [`drain`] method can emulate `truncate`, but causes the excess + /// elements to be returned instead of dropped. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// Truncating a five element vector to two elements: + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// vec.truncate(2); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// No truncation occurs when `len` is greater than the vector's current + /// length: + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(8); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + /// + /// Truncating when `len == 0` is equivalent to calling the [`clear`] + /// method. + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(0); + /// assert_eq!(vec, []); + /// ``` + /// + /// [`clear`]: Vec::clear + /// [`drain`]: Vec::drain + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, len: usize) { + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + // Note: It's intentional that this is `>` and not `>=`. + // Changing it to `>=` has negative performance + // implications in some cases. See #78884 for more. + if len > self.len { + return; + } + let remaining_len = self.len - len; + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + self.len = len; + ptr::drop_in_place(s); + } + } + + /// Extracts a slice containing the entire vector. + /// + /// Equivalent to `&s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Write}; + /// let buffer = vec![1, 2, 3, 5, 8]; + /// io::sink().write(buffer.as_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Extracts a mutable slice of the entire vector. + /// + /// Equivalent to `&mut s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Read}; + /// let mut buffer = vec![0; 3]; + /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self + } + + /// Returns a raw pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// # Examples + /// + /// ``` + /// let x = vec![1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + assume(!ptr.is_null()); + } + ptr + } + + /// Returns an unsafe mutable pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity(size); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// *x_ptr.add(i) = i as i32; + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + assume(!ptr.is_null()); + } + ptr + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.buf.allocator() + } + + /// Forces the length of the vector to `new_len`. + /// + /// This is a low-level operation that maintains none of the normal + /// invariants of the type. Normally changing the length of a vector + /// is done using one of the safe operations instead, such as + /// [`truncate`], [`resize`], [`extend`], or [`clear`]. + /// + /// [`truncate`]: Vec::truncate + /// [`resize`]: Vec::resize + /// [`extend`]: Extend::extend + /// [`clear`]: Vec::clear + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Vec::capacity + /// + /// # Examples + /// + /// This method can be useful for situations in which the vector + /// is serving as a buffer for other code, particularly over FFI: + /// + /// ```no_run + /// # #![allow(dead_code)] + /// # // This is just a minimal skeleton for the doc example; + /// # // don't use this as a starting point for a real library. + /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void } + /// # const Z_OK: i32 = 0; + /// # extern "C" { + /// # fn deflateGetDictionary( + /// # strm: *mut std::ffi::c_void, + /// # dictionary: *mut u8, + /// # dictLength: *mut usize, + /// # ) -> i32; + /// # } + /// # impl StreamWrapper { + /// pub fn get_dictionary(&self) -> Option> { + /// // Per the FFI method's docs, "32768 bytes is always enough". + /// let mut dict = Vec::with_capacity(32_768); + /// let mut dict_length = 0; + /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: + /// // 1. `dict_length` elements were initialized. + /// // 2. `dict_length` <= the capacity (32_768) + /// // which makes `set_len` safe to call. + /// unsafe { + /// // Make the FFI call... + /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); + /// if r == Z_OK { + /// // ...and update the length to what was initialized. + /// dict.set_len(dict_length); + /// Some(dict) + /// } else { + /// None + /// } + /// } + /// } + /// # } + /// ``` + /// + /// While the following example is sound, there is a memory leak since + /// the inner vectors were not freed prior to the `set_len` call: + /// + /// ``` + /// let mut vec = vec![vec![1, 0, 0], + /// vec![0, 1, 0], + /// vec![0, 0, 1]]; + /// // SAFETY: + /// // 1. `old_len..0` is empty so no elements need to be initialized. + /// // 2. `0 <= capacity` always holds whatever `capacity` is. + /// unsafe { + /// vec.set_len(0); + /// } + /// ``` + /// + /// Normally, here, one would use [`clear`] instead to correctly drop + /// the contents and thus not leak memory. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn set_len(&mut self, new_len: usize) { + debug_assert!(new_len <= self.capacity()); + + self.len = new_len; + } + + /// Removes an element from the vector and returns it. + /// + /// The removed element is replaced by the last element of the vector. + /// + /// This does not preserve ordering, but is O(1). + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec!["foo", "bar", "baz", "qux"]; + /// + /// assert_eq!(v.swap_remove(1), "bar"); + /// assert_eq!(v, ["foo", "qux", "baz"]); + /// + /// assert_eq!(v.swap_remove(0), "foo"); + /// assert_eq!(v, ["baz", "qux"]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn swap_remove(&mut self, index: usize) -> T { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("swap_remove index (is {}) should be < len (is {})", index, len); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // We replace self[index] with the last element. Note that if the + // bounds check above succeeds there must be a last element (which + // can be self[index] itself). + let last = ptr::read(self.as_ptr().add(len - 1)); + let hole = self.as_mut_ptr().add(index); + self.set_len(len - 1); + ptr::replace(hole, last) + } + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.insert(1, 4); + /// assert_eq!(vec, [1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, index: usize, element: T) { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("insertion index (is {}) should be <= len (is {})", index, len); + } + + let len = self.len(); + if index > len { + assert_failed(index, len); + } + + // space for the new element + if len == self.buf.capacity() { + self.reserve(1); + } + + unsafe { + // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().add(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, index: usize) -> T { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("removal index (is {}) should be < len (is {})", index, len); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + + // Shift everything down to fill in that spot. + ptr::copy(ptr.offset(1), ptr, len - index - 1); + } + self.set_len(len - 1); + ret + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain(|&x| x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + /// + /// Because the elements are visited exactly once in the original order, + /// external state may be used to decide which elements to keep. + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut iter = keep.iter(); + /// vec.retain(|_| *iter.next().unwrap()); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + let original_len = self.len(); + // Avoid double drop if the drop guard is not executed, + // since we may make some holes during the process. + unsafe { self.set_len(0) }; + + // Vec: [Kept, Kept, Hole, Hole, Hole, Hole, Unchecked, Unchecked] + // |<- processed len ->| ^- next to check + // |<- deleted cnt ->| + // |<- original_len ->| + // Kept: Elements which predicate returns true on. + // Hole: Moved or dropped element slot. + // Unchecked: Unchecked valid elements. + // + // This drop guard will be invoked when predicate or `drop` of element panicked. + // It shifts unchecked elements to cover holes and `set_len` to the correct length. + // In cases when predicate and `drop` never panick, it will be optimized out. + struct BackshiftOnDrop<'a, T, A: Allocator> { + v: &'a mut Vec, + processed_len: usize, + deleted_cnt: usize, + original_len: usize, + } + + impl Drop for BackshiftOnDrop<'_, T, A> { + fn drop(&mut self) { + if self.deleted_cnt > 0 { + // SAFETY: Trailing unchecked items must be valid since we never touch them. + unsafe { + ptr::copy( + self.v.as_ptr().add(self.processed_len), + self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), + self.original_len - self.processed_len, + ); + } + } + // SAFETY: After filling holes, all items are in contiguous memory. + unsafe { + self.v.set_len(self.original_len - self.deleted_cnt); + } + } + } + + let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; + + while g.processed_len < original_len { + // SAFETY: Unchecked element must be valid. + let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; + if !f(cur) { + // Advance early to avoid double drop if `drop_in_place` panicked. + g.processed_len += 1; + g.deleted_cnt += 1; + // SAFETY: We never touch this element again after dropped. + unsafe { ptr::drop_in_place(cur) }; + // We already advanced the counter. + continue; + } + if g.deleted_cnt > 0 { + // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. + // We use copy for move, and never touch this element again. + unsafe { + let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + g.processed_len += 1; + } + + // All item are processed. This can be optimized to `set_len` by LLVM. + drop(g); + } + + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![10, 20, 21, 30, 20]; + /// + /// vec.dedup_by_key(|i| *i / 10); + /// + /// assert_eq!(vec, [10, 20, 30, 20]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + #[inline] + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.dedup_by(|a, b| key(a) == key(b)) + } + + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. + /// + /// The `same_bucket` function is passed references to two elements from the vector and + /// must determine if the elements compare equal. The elements are passed in opposite order + /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; + /// + /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + /// + /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + pub fn dedup_by(&mut self, mut same_bucket: F) + where + F: FnMut(&mut T, &mut T) -> bool, + { + let len = self.len(); + if len <= 1 { + return; + } + + /* INVARIANT: vec.len() > read >= write > write-1 >= 0 */ + struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> { + /* Offset of the element we want to check if it is duplicate */ + read: usize, + + /* Offset of the place where we want to place the non-duplicate + * when we find it. */ + write: usize, + + /* The Vec that would need correction if `same_bucket` panicked */ + vec: &'a mut Vec, + } + + impl<'a, T, A: core::alloc::Allocator> Drop for FillGapOnDrop<'a, T, A> { + fn drop(&mut self) { + /* This code gets executed when `same_bucket` panics */ + + /* SAFETY: invariant guarantees that `read - write` + * and `len - read` never overflow and that the copy is always + * in-bounds. */ + unsafe { + let ptr = self.vec.as_mut_ptr(); + let len = self.vec.len(); + + /* How many items were left when `same_bucket` paniced. + * Basically vec[read..].len() */ + let items_left = len.wrapping_sub(self.read); + + /* Pointer to first item in vec[write..write+items_left] slice */ + let dropped_ptr = ptr.add(self.write); + /* Pointer to first item in vec[read..] slice */ + let valid_ptr = ptr.add(self.read); + + /* Copy `vec[read..]` to `vec[write..write+items_left]`. + * The slices can overlap, so `copy_nonoverlapping` cannot be used */ + ptr::copy(valid_ptr, dropped_ptr, items_left); + + /* How many items have been already dropped + * Basically vec[read..write].len() */ + let dropped = self.read.wrapping_sub(self.write); + + self.vec.set_len(len - dropped); + } + } + } + + let mut gap = FillGapOnDrop { read: 1, write: 1, vec: self }; + let ptr = gap.vec.as_mut_ptr(); + + /* Drop items while going through Vec, it should be more efficient than + * doing slice partition_dedup + truncate */ + + /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr + * are always in-bounds and read_ptr never aliases prev_ptr */ + unsafe { + while gap.read < len { + let read_ptr = ptr.add(gap.read); + let prev_ptr = ptr.add(gap.write.wrapping_sub(1)); + + if same_bucket(&mut *read_ptr, &mut *prev_ptr) { + /* We have found duplicate, drop it in-place */ + ptr::drop_in_place(read_ptr); + } else { + let write_ptr = ptr.add(gap.write); + + /* Because `read_ptr` can be equal to `write_ptr`, we either + * have to use `copy` or conditional `copy_nonoverlapping`. + * Looks like the first option is faster. */ + ptr::copy(read_ptr, write_ptr, 1); + + /* We have filled that place, so go further */ + gap.write += 1; + } + + gap.read += 1; + } + + /* Technically we could let `gap` clean up with its Drop, but + * when `same_bucket` is guaranteed to not panic, this bloats a little + * the codegen, so we just do it manually */ + gap.vec.set_len(gap.write); + mem::forget(gap); + } + } + + /// Appends an element to the back of a collection. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2]; + /// vec.push(3); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, value: T) { + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if self.len == self.buf.capacity() { + self.reserve(1); + } + unsafe { + let end = self.as_mut_ptr().add(self.len); + ptr::write(end, value); + self.len += 1; + } + } + + /// Removes the last element from a vector and returns it, or [`None`] if it + /// is empty. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// assert_eq!(vec.pop(), Some(3)); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + unsafe { + self.len -= 1; + Some(ptr::read(self.as_ptr().add(self.len()))) + } + } + } + + /// Moves all the elements of `other` into `Self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the number of elements in the vector overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let mut vec2 = vec![4, 5, 6]; + /// vec.append(&mut vec2); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); + /// ``` + #[inline] + #[stable(feature = "append", since = "1.4.0")] + pub fn append(&mut self, other: &mut Self) { + unsafe { + self.append_elements(other.as_slice() as _); + other.set_len(0); + } + } + + /// Appends elements to `Self` from other buffer. + #[inline] + unsafe fn append_elements(&mut self, other: *const [T]) { + let count = unsafe { (*other).len() }; + self.reserve(count); + let len = self.len(); + unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; + self.len += count; + } + + /// Creates a draining iterator that removes the specified range in the vector + /// and yields the removed items. + /// + /// When the iterator **is** dropped, all elements in the range are removed + /// from the vector, even if the iterator was not fully consumed. If the + /// iterator **is not** dropped (with [`mem::forget`] for example), it is + /// unspecified how many elements are removed. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let u: Vec<_> = v.drain(1..).collect(); + /// assert_eq!(v, &[1]); + /// assert_eq!(u, &[2, 3]); + /// + /// // A full range clears the vector + /// v.drain(..); + /// assert_eq!(v, &[]); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let Range { start, end } = slice::range(range, ..len); + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + self.set_len(start); + // Use the borrow in the IterMut to indicate borrowing behavior of the + // whole Drain iterator (like &mut T). + let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); + Drain { + tail_start: end, + tail_len: len - end, + iter: range_slice.iter(), + vec: NonNull::from(self), + } + } + } + + /// Clears the vector, removing all values. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// + /// v.clear(); + /// + /// assert!(v.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.truncate(0) + } + + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. + /// + /// # Examples + /// + /// ``` + /// let a = vec![1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[doc(alias = "length")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the vector contains no elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = Vec::new(); + /// assert!(v.is_empty()); + /// + /// v.push(1); + /// assert!(!v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let vec2 = vec.split_off(1); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + pub fn split_off(&mut self, at: usize) -> Self + where + A: Clone, + { + #[cold] + #[inline(never)] + fn assert_failed(at: usize, len: usize) -> ! { + panic!("`at` split index (is {}) should be <= len (is {})", at, len); + } + + if at > self.len() { + assert_failed(at, self.len()); + } + + if at == 0 { + // the new vector can take over the original buffer and avoid the copy + return mem::replace( + self, + Vec::with_capacity_in(self.capacity(), self.allocator().clone()), + ); + } + + let other_len = self.len - at; + let mut other = Vec::with_capacity_in(other_len, self.allocator().clone()); + + // Unsafely `set_len` and copy items to `other`. + unsafe { + self.set_len(at); + other.set_len(other_len); + + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); + } + other + } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with the result of + /// calling the closure `f`. The return values from `f` will end up + /// in the `Vec` in the order they have been generated. + /// + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses a closure to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`Vec::resize`]. If you + /// want to use the [`Default`] trait to generate values, you can + /// pass [`Default::default`] as the second argument. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_with(5, Default::default); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![]; + /// let mut p = 1; + /// vec.resize_with(4, || { p *= 2; p }); + /// assert_eq!(vec, [2, 4, 8, 16]); + /// ``` + #[stable(feature = "vec_resize_with", since = "1.33.0")] + pub fn resize_with(&mut self, new_len: usize, f: F) + where + F: FnMut() -> T, + { + let len = self.len(); + if new_len > len { + self.extend_with(new_len - len, ExtendFunc(f)); + } else { + self.truncate(new_len); + } + } + + /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, + /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime + /// `'a`. If the type has only static references, or none at all, then this + /// may be chosen to be `'static`. + /// + /// This function is similar to the [`leak`][Box::leak] function on [`Box`] + /// except that there is no way to recover the leaked memory. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = x.leak(); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); + /// ``` + #[stable(feature = "vec_leak", since = "1.47.0")] + #[inline] + pub fn leak<'a>(self) -> &'a mut [T] + where + A: 'a, + { + Box::leak(self.into_boxed_slice()) + } + + /// Returns the remaining spare capacity of the vector as a slice of + /// `MaybeUninit`. + /// + /// The returned slice can be used to fill the vector with data (e.g. by + /// reading from a file) before marking the data as initialized using the + /// [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_spare_capacity, maybe_uninit_extra)] + /// + /// // Allocate vector big enough for 10 elements. + /// let mut v = Vec::with_capacity(10); + /// + /// // Fill in the first 3 elements. + /// let uninit = v.spare_capacity_mut(); + /// uninit[0].write(0); + /// uninit[1].write(1); + /// uninit[2].write(2); + /// + /// // Mark the first 3 elements of the vector as being initialized. + /// unsafe { + /// v.set_len(3); + /// } + /// + /// assert_eq!(&v, &[0, 1, 2]); + /// ``` + #[unstable(feature = "vec_spare_capacity", issue = "75017")] + #[inline] + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + // Note: + // This method is not implemented in terms of `split_at_spare_mut`, + // to prevent invalidation of pointers to the buffer. + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len) as *mut MaybeUninit, + self.buf.capacity() - self.len, + ) + } + } + + /// Returns vector content as a slice of `T`, along with the remaining spare + /// capacity of the vector as a slice of `MaybeUninit`. + /// + /// The returned spare capacity slice can be used to fill the vector with data + /// (e.g. by reading from a file) before marking the data as initialized using + /// the [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// Note that this is a low-level API, which should be used with care for + /// optimization purposes. If you need to append data to a `Vec` + /// you can use [`push`], [`extend`], [`extend_from_slice`], + /// [`extend_from_within`], [`insert`], [`append`], [`resize`] or + /// [`resize_with`], depending on your exact needs. + /// + /// [`push`]: Vec::push + /// [`extend`]: Vec::extend + /// [`extend_from_slice`]: Vec::extend_from_slice + /// [`extend_from_within`]: Vec::extend_from_within + /// [`insert`]: Vec::insert + /// [`append`]: Vec::append + /// [`resize`]: Vec::resize + /// [`resize_with`]: Vec::resize_with + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_split_at_spare, maybe_uninit_extra)] + /// + /// let mut v = vec![1, 1, 2]; + /// + /// // Reserve additional space big enough for 10 elements. + /// v.reserve(10); + /// + /// let (init, uninit) = v.split_at_spare_mut(); + /// let sum = init.iter().copied().sum::(); + /// + /// // Fill in the next 4 elements. + /// uninit[0].write(sum); + /// uninit[1].write(sum * 2); + /// uninit[2].write(sum * 3); + /// uninit[3].write(sum * 4); + /// + /// // Mark the 4 elements of the vector as being initialized. + /// unsafe { + /// let len = v.len(); + /// v.set_len(len + 4); + /// } + /// + /// assert_eq!(&v, &[1, 1, 2, 4, 8, 12, 16]); + /// ``` + #[unstable(feature = "vec_split_at_spare", issue = "81944")] + #[inline] + pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit]) { + // SAFETY: + // - len is ignored and so never changed + let (init, spare, _) = unsafe { self.split_at_spare_mut_with_len() }; + (init, spare) + } + + /// Safety: changing returned .2 (&mut usize) is considered the same as calling `.set_len(_)`. + /// + /// This method provides unique access to all vec parts at once in `extend_from_within`. + unsafe fn split_at_spare_mut_with_len( + &mut self, + ) -> (&mut [T], &mut [MaybeUninit], &mut usize) { + let Range { start: ptr, end: spare_ptr } = self.as_mut_ptr_range(); + let spare_ptr = spare_ptr.cast::>(); + let spare_len = self.buf.capacity() - self.len; + + // SAFETY: + // - `ptr` is guaranteed to be valid for `len` elements + // - `spare_ptr` is pointing one element past the buffer, so it doesn't overlap with `initialized` + unsafe { + let initialized = slice::from_raw_parts_mut(ptr, self.len); + let spare = slice::from_raw_parts_mut(spare_ptr, spare_len); + + (initialized, spare, &mut self.len) + } + } +} + +impl Vec { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `value`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method requires `T` to implement [`Clone`], + /// in order to be able to clone the passed value. + /// If you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`Vec::resize_with`]. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["hello"]; + /// vec.resize(3, "world"); + /// assert_eq!(vec, ["hello", "world", "world"]); + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.resize(2, 0); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[stable(feature = "vec_resize", since = "1.5.0")] + pub fn resize(&mut self, new_len: usize, value: T) { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, ExtendElement(value)) + } else { + self.truncate(new_len); + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` vector is traversed in-order. + /// + /// Note that this function is same as [`extend`] except that it is + /// specialized to work with slices instead. If and when Rust gets + /// specialization this function will likely be deprecated (but still + /// available). + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.extend_from_slice(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// [`extend`]: Vec::extend + #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] + pub fn extend_from_slice(&mut self, other: &[T]) { + self.spec_extend(other.iter()) + } + + /// Copies elements from `src` range to the end of the vector. + /// + /// ## Examples + /// + /// ``` + /// let mut vec = vec![0, 1, 2, 3, 4]; + /// + /// vec.extend_from_within(2..); + /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]); + /// + /// vec.extend_from_within(..2); + /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]); + /// + /// vec.extend_from_within(4..8); + /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); + /// ``` + #[stable(feature = "vec_extend_from_within", since = "1.53.0")] + pub fn extend_from_within(&mut self, src: R) + where + R: RangeBounds, + { + let range = slice::range(src, ..self.len()); + self.reserve(range.len()); + + // SAFETY: + // - `slice::range` guarantees that the given range is valid for indexing self + unsafe { + self.spec_extend_from_within(range); + } + } +} + +// This code generalizes `extend_with_{element,default}`. +trait ExtendWith { + fn next(&mut self) -> T; + fn last(self) -> T; +} + +struct ExtendElement(T); +impl ExtendWith for ExtendElement { + fn next(&mut self) -> T { + self.0.clone() + } + fn last(self) -> T { + self.0 + } +} + +struct ExtendDefault; +impl ExtendWith for ExtendDefault { + fn next(&mut self) -> T { + Default::default() + } + fn last(self) -> T { + Default::default() + } +} + +struct ExtendFunc(F); +impl T> ExtendWith for ExtendFunc { + fn next(&mut self) -> T { + (self.0)() + } + fn last(mut self) -> T { + (self.0)() + } +} + +impl Vec { + /// Extend the vector by `n` values, using the given generator. + fn extend_with>(&mut self, n: usize, mut value: E) { + self.reserve(n); + + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + // Use SetLenOnDrop to work around bug where compiler + // may not realize the store through `ptr` through self.set_len() + // don't alias. + let mut local_len = SetLenOnDrop::new(&mut self.len); + + // Write all elements except the last one + for _ in 1..n { + ptr::write(ptr, value.next()); + ptr = ptr.offset(1); + // Increment the length in every step in case next() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly + ptr::write(ptr, value.last()); + local_len.increment_len(1); + } + + // len set by scope guard + } + } +} + +impl Vec { + /// Removes consecutive repeated elements in the vector according to the + /// [`PartialEq`] trait implementation. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 2, 3, 2]; + /// + /// vec.dedup(); + /// + /// assert_eq!(vec, [1, 2, 3, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn dedup(&mut self) { + self.dedup_by(|a, b| a == b) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Internal methods and functions +//////////////////////////////////////////////////////////////////////////////// + +#[doc(hidden)] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn from_elem(elem: T, n: usize) -> Vec { + ::from_elem(elem, n, Global) +} + +#[doc(hidden)] +#[unstable(feature = "allocator_api", issue = "32838")] +pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { + ::from_elem(elem, n, alloc) +} + +trait ExtendFromWithinSpec { + /// # Safety + /// + /// - `src` needs to be valid index + /// - `self.capacity() - self.len()` must be `>= src.len()` + unsafe fn spec_extend_from_within(&mut self, src: Range); +} + +impl ExtendFromWithinSpec for Vec { + default unsafe fn spec_extend_from_within(&mut self, src: Range) { + // SAFETY: + // - len is increased only after initializing elements + let (this, spare, len) = unsafe { self.split_at_spare_mut_with_len() }; + + // SAFETY: + // - caller guaratees that src is a valid index + let to_clone = unsafe { this.get_unchecked(src) }; + + iter::zip(to_clone, spare) + .map(|(src, dst)| dst.write(src.clone())) + // Note: + // - Element was just initialized with `MaybeUninit::write`, so it's ok to increase len + // - len is increased after each element to prevent leaks (see issue #82533) + .for_each(|_| *len += 1); + } +} + +impl ExtendFromWithinSpec for Vec { + unsafe fn spec_extend_from_within(&mut self, src: Range) { + let count = src.len(); + { + let (init, spare) = self.split_at_spare_mut(); + + // SAFETY: + // - caller guaratees that `src` is a valid index + let source = unsafe { init.get_unchecked(src) }; + + // SAFETY: + // - Both pointers are created from unique slice references (`&mut [_]`) + // so they are valid and do not overlap. + // - Elements are :Copy so it's OK to to copy them, without doing + // anything with the original values + // - `count` is equal to the len of `source`, so source is valid for + // `count` reads + // - `.reserve(count)` guarantees that `spare.len() >= count` so spare + // is valid for `count` writes + unsafe { ptr::copy_nonoverlapping(source.as_ptr(), spare.as_mut_ptr() as _, count) }; + } + + // SAFETY: + // - The elements were just initialized by `copy_nonoverlapping` + self.len += count; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Common trait implementations for Vec +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for Vec { + type Target = [T]; + + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Vec { + #[cfg(not(test))] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + <[T]>::to_vec_in(&**self, alloc) + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + crate::slice::to_vec(&**self, alloc) + } + + fn clone_from(&mut self, other: &Self) { + // drop anything that will not be overwritten + self.truncate(other.len()); + + // self.len <= other.len due to the truncate above, so the + // slices here are always in-bounds. + let (init, tail) = other.split_at(self.len()); + + // reuse the contained values' allocations/resources. + self.clone_from_slice(init); + self.extend_from_slice(tail); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Vec { + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> Index for Vec { + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(&**self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> IndexMut for Vec { + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(&mut **self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for Vec { + #[inline] + fn from_iter>(iter: I) -> Vec { + >::from_iter(iter.into_iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Vec { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + unsafe { + let mut me = ManuallyDrop::new(self); + let alloc = ptr::read(me.allocator()); + let begin = me.as_mut_ptr(); + let end = if mem::size_of::() == 0 { + arith_offset(begin as *const i8, me.len() as isize) as *const T + } else { + begin.add(me.len()) as *const T + }; + let cap = me.buf.capacity(); + IntoIter { + buf: NonNull::new_unchecked(begin), + phantom: PhantomData, + cap, + alloc, + ptr: begin, + end, + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a Vec { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + + fn into_iter(self) -> slice::IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for Vec { + #[inline] + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter.into_iter()) + } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +impl Vec { + // leaf method to which various SpecFrom/SpecExtend implementations delegate when + // they have no further optimizations to apply + fn extend_desugared>(&mut self, mut iterator: I) { + // This is the case for a general iterator. + // + // This function should be the moral equivalent of: + // + // for item in iterator { + // self.push(item); + // } + while let Some(element) = iterator.next() { + let len = self.len(); + if len == self.capacity() { + let (lower, _) = iterator.size_hint(); + self.reserve(lower.saturating_add(1)); + } + unsafe { + ptr::write(self.as_mut_ptr().add(len), element); + // NB can't overflow since we would have had to alloc the address space + self.set_len(len + 1); + } + } + } + + /// Creates a splicing iterator that replaces the specified range in the vector + /// with the given `replace_with` iterator and yields the removed items. + /// `replace_with` does not need to be the same length as `range`. + /// + /// `range` is removed even if the iterator is not consumed until the end. + /// + /// It is unspecified how many elements are removed from the vector + /// if the `Splice` value is leaked. + /// + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. + /// + /// This is optimal if: + /// + /// * The tail (elements in the vector after `range`) is empty, + /// * or `replace_with` yields fewer or equal elements than `range`’s length + /// * or the lower bound of its `size_hint()` is exact. + /// + /// Otherwise, a temporary vector is allocated and the tail is moved twice. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let new = [7, 8]; + /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect(); + /// assert_eq!(v, &[7, 8, 3]); + /// assert_eq!(u, &[1, 2]); + /// ``` + #[inline] + #[stable(feature = "vec_splice", since = "1.21.0")] + pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> + where + R: RangeBounds, + I: IntoIterator, + { + Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } + } + + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the vector and will not be yielded + /// by the iterator. + /// + /// Using this method is equivalent to the following code: + /// + /// ``` + /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; + /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; + /// let mut i = 0; + /// while i < vec.len() { + /// if some_predicate(&mut vec[i]) { + /// let val = vec.remove(i); + /// // your code here + /// } else { + /// i += 1; + /// } + /// } + /// + /// # assert_eq!(vec, vec![1, 4, 5]); + /// ``` + /// + /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// + /// Note that `drain_filter` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// # Examples + /// + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` + /// #![feature(drain_filter)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] + pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { + self.set_len(0); + } + + DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } + } +} + +/// Extend implementation that copies elements out of references before pushing them onto the Vec. +/// +/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to +/// append the entire slice at once. +/// +/// [`copy_from_slice`]: slice::copy_from_slice +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { + fn extend>(&mut self, iter: I) { + self.spec_extend(iter.into_iter()) + } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Vec { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Vec {} + +/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Vec { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { + fn drop(&mut self) { + unsafe { + // use drop for [T] + // use a raw slice to refer to the elements of the vector as weakest necessary type; + // could avoid questions of validity in certain cases + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) + } + // RawVec handles deallocation + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Vec { + /// Creates an empty `Vec`. + fn default() -> Vec { + Vec::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Vec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef> for Vec { + fn as_ref(&self) -> &Vec { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut> for Vec { + fn as_mut(&mut self) -> &mut Vec { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for Vec { + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut<[T]> for Vec { + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&[T]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); + /// ``` + #[cfg(not(test))] + fn from(s: &[T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &[T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[stable(feature = "vec_from_mut", since = "1.19.0")] +impl From<&mut [T]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); + /// ``` + #[cfg(not(test))] + fn from(s: &mut [T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &mut [T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[stable(feature = "vec_from_array", since = "1.44.0")] +impl From<[T; N]> for Vec { + #[cfg(not(test))] + fn from(s: [T; N]) -> Vec { + <[T]>::into_vec(box s) + } + /// Allocate a `Vec` and move `s`'s items into it. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); + /// ``` + #[cfg(test)] + fn from(s: [T; N]) -> Vec { + crate::slice::into_vec(box s) + } +} + +#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] +impl<'a, T> From> for Vec +where + [T]: ToOwned>, +{ + /// Convert a clone-on-write slice into a vector. + /// + /// If `s` already owns a `Vec`, it will be returned directly. + /// If `s` is borrowing a slice, a new `Vec` will be allocated and + /// filled by cloning `s`'s items into it. + /// + /// # Examples + /// + /// ``` + /// # use std::borrow::Cow; + /// let o: Cow<[i32]> = Cow::Owned(vec![1, 2, 3]); + /// let b: Cow<[i32]> = Cow::Borrowed(&[1, 2, 3]); + /// assert_eq!(Vec::from(o), Vec::from(b)); + /// ``` + fn from(s: Cow<'a, [T]>) -> Vec { + s.into_owned() + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "vec_from_box", since = "1.18.0")] +impl From> for Vec { + /// Convert a boxed slice into a vector by transferring ownership of + /// the existing heap allocation. + /// + /// # Examples + /// + /// ``` + /// let b: Box<[i32]> = vec![1, 2, 3].into_boxed_slice(); + /// assert_eq!(Vec::from(b), vec![1, 2, 3]); + /// ``` + fn from(s: Box<[T], A>) -> Self { + s.into_vec() + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "box_from_vec", since = "1.20.0")] +impl From> for Box<[T], A> { + /// Convert a vector into a boxed slice. + /// + /// If `v` has excess capacity, its items will be moved into a + /// newly-allocated buffer with exactly the right capacity. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Box::from(vec![1, 2, 3]), vec![1, 2, 3].into_boxed_slice()); + /// ``` + fn from(v: Vec) -> Self { + v.into_boxed_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for Vec { + /// Allocate a `Vec` and fill it with a UTF-8 string. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from("123"), vec![b'1', b'2', b'3']); + /// ``` + fn from(s: &str) -> Vec { + From::from(s.as_bytes()) + } +} + +#[stable(feature = "array_try_from_vec", since = "1.48.0")] +impl TryFrom> for [T; N] { + type Error = Vec; + + /// Gets the entire contents of the `Vec` as an array, + /// if its size exactly matches that of the requested array. + /// + /// # Examples + /// + /// ``` + /// use std::convert::TryInto; + /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); + /// assert_eq!(>::new().try_into(), Ok([])); + /// ``` + /// + /// If the length doesn't match, the input comes back in `Err`: + /// ``` + /// use std::convert::TryInto; + /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); + /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + /// ``` + /// + /// If you're fine with just getting a prefix of the `Vec`, + /// you can call [`.truncate(N)`](Vec::truncate) first. + /// ``` + /// use std::convert::TryInto; + /// let mut v = String::from("hello world").into_bytes(); + /// v.sort(); + /// v.truncate(2); + /// let [a, b]: [_; 2] = v.try_into().unwrap(); + /// assert_eq!(a, b' '); + /// assert_eq!(b, b'd'); + /// ``` + fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { + if vec.len() != N { + return Err(vec); + } + + // SAFETY: `.set_len(0)` is always sound. + unsafe { vec.set_len(0) }; + + // SAFETY: A `Vec`'s pointer is always aligned properly, and + // the alignment the array needs is the same as the items. + // We checked earlier that we have sufficient items. + // The items will not double-drop as the `set_len` + // tells the `Vec` not to also drop them. + let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; + Ok(array) + } +} +// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +// +// The idea is: The length field in SetLenOnDrop is a local variable +// that the optimizer will see does not alias with any stores through the Vec's data +// pointer. This is a workaround for alias analysis issue #32155 +pub(super) struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + pub(super) fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { local_len: *len, len } + } + + #[inline] + pub(super) fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } +} + +impl Drop for SetLenOnDrop<'_> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} +use crate::alloc::{Allocator, Global}; +use core::ptr::{self}; +use core::slice::{self}; + +use super::Vec; + +/// An iterator which uses a closure to determine if an element should be removed. +/// +/// This struct is created by [`Vec::drain_filter`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// #![feature(drain_filter)] +/// +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); +/// ``` +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +#[derive(Debug)] +pub struct DrainFilter< + 'a, + T, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where + F: FnMut(&mut T) -> bool, +{ + pub(super) vec: &'a mut Vec, + /// The index of the item that will be inspected by the next call to `next`. + pub(super) idx: usize, + /// The number of items that have been drained (removed) thus far. + pub(super) del: usize, + /// The original length of `vec` prior to draining. + pub(super) old_len: usize, + /// The filter test predicate. + pub(super) pred: F, + /// A flag that indicates a panic has occurred in the filter test predicate. + /// This is used as a hint in the drop implementation to prevent consumption + /// of the remainder of the `DrainFilter`. Any unprocessed items will be + /// backshifted in the `vec`, but no further items will be dropped or + /// tested by the filter predicate. + pub(super) panic_flag: bool, +} + +impl DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.vec.allocator() + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Iterator for DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + unsafe { + while self.idx < self.old_len { + let i = self.idx; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + self.panic_flag = true; + let drained = (self.pred)(&mut v[i]); + self.panic_flag = false; + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.idx += 1; + if drained { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + let del = self.del; + let src: *const T = &v[i]; + let dst: *mut T = &mut v[i - del]; + ptr::copy_nonoverlapping(src, dst, 1); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Drop for DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> + where + F: FnMut(&mut T) -> bool, + { + drain: &'b mut DrainFilter<'a, T, F, A>, + } + + impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + fn drop(&mut self) { + unsafe { + if self.drain.idx < self.drain.old_len && self.drain.del > 0 { + // This is a pretty messed up state, and there isn't really an + // obviously right thing to do. We don't want to keep trying + // to execute `pred`, so we just backshift all the unprocessed + // elements and tell the vec that they still exist. The backshift + // is required to prevent a double-drop of the last successfully + // drained item prior to a panic in the predicate. + let ptr = self.drain.vec.as_mut_ptr(); + let src = ptr.add(self.drain.idx); + let dst = src.sub(self.drain.del); + let tail_len = self.drain.old_len - self.drain.idx; + src.copy_to(dst, tail_len); + } + self.drain.vec.set_len(self.drain.old_len - self.drain.del); + } + } + } + + let backshift = BackshiftOnDrop { drain: self }; + + // Attempt to consume any remaining elements if the filter predicate + // has not yet panicked. We'll backshift any remaining elements + // whether we've already panicked or if the consumption here panics. + if !backshift.drain.panic_flag { + backshift.drain.for_each(drop); + } + } +} +use crate::borrow::Cow; +use core::iter::FromIterator; + +use super::Vec; + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + fn from(s: &'a [T]) -> Cow<'a, [T]> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From> for Cow<'a, [T]> { + fn from(v: Vec) -> Cow<'a, [T]> { + Cow::Owned(v) + } +} + +#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] +impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { + fn from(v: &'a Vec) -> Cow<'a, [T]> { + Cow::Borrowed(v.as_slice()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> FromIterator for Cow<'a, [T]> +where + T: Clone, +{ + fn from_iter>(it: I) -> Cow<'a, [T]> { + Cow::Owned(FromIterator::from_iter(it)) + } +} +use crate::alloc::Allocator; +use crate::borrow::Cow; + +use super::Vec; + +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($ty: $bound)? + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } + } + } +} + +__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } + +// NOTE: some less important impls are omitted to reduce code bloat +// FIXME(Centril): Reconsider this? +//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } +use crate::alloc::{Allocator, Global}; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{Drain, Vec}; + +/// A splicing iterator for `Vec`. +/// +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let new = [7, 8]; +/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); +/// ``` +#[derive(Debug)] +#[stable(feature = "vec_splice", since = "1.21.0")] +pub struct Splice< + 'a, + I: Iterator + 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + pub(super) drain: Drain<'a, I::Item, A>, + pub(super) replace_with: I, +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Iterator for Splice<'_, I, A> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.drain.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.drain.size_hint() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl DoubleEndedIterator for Splice<'_, I, A> { + fn next_back(&mut self) -> Option { + self.drain.next_back() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl ExactSizeIterator for Splice<'_, I, A> {} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Drop for Splice<'_, I, A> { + fn drop(&mut self) { + self.drain.by_ref().for_each(drop); + + unsafe { + if self.drain.tail_len == 0 { + self.drain.vec.as_mut().extend(self.replace_with.by_ref()); + return; + } + + // First fill the range left by drain(). + if !self.drain.fill(&mut self.replace_with) { + return; + } + + // There may be more elements. Use the lower bound as an estimate. + // FIXME: Is the upper bound a better guess? Or something else? + let (lower_bound, _upper_bound) = self.replace_with.size_hint(); + if lower_bound > 0 { + self.drain.move_tail(lower_bound); + if !self.drain.fill(&mut self.replace_with) { + return; + } + } + + // Collect any remaining elements. + // This is a zero-length vector which does not allocate if `lower_bound` was exact. + let mut collected = self.replace_with.by_ref().collect::>().into_iter(); + // Now we have an exact count. + if collected.len() > 0 { + self.drain.move_tail(collected.len()); + let filled = self.drain.fill(&mut collected); + debug_assert!(filled); + debug_assert_eq!(collected.len(), 0); + } + } + // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. + } +} + +/// Private helper methods for `Splice::drop` +impl Drain<'_, T, A> { + /// The range from `self.vec.len` to `self.tail_start` contains elements + /// that have been moved out. + /// Fill that range as much as possible with new elements from the `replace_with` iterator. + /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) + unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + let vec = unsafe { self.vec.as_mut() }; + let range_start = vec.len; + let range_end = self.tail_start; + let range_slice = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) + }; + + for place in range_slice { + if let Some(new_item) = replace_with.next() { + unsafe { ptr::write(place, new_item) }; + vec.len += 1; + } else { + return false; + } + } + true + } + + /// Makes room for inserting more elements before the tail. + unsafe fn move_tail(&mut self, additional: usize) { + let vec = unsafe { self.vec.as_mut() }; + let len = self.tail_start + self.tail_len; + vec.buf.reserve(len, additional); + + let new_tail_start = self.tail_start + additional; + unsafe { + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + } + self.tail_start = new_tail_start; + } +} +use core::ptr::{self}; +use core::slice::{self}; + +// A helper struct for in-place iteration that drops the destination slice of iteration, +// i.e. the head. The source slice (the tail) is dropped by IntoIter. +pub(super) struct InPlaceDrop { + pub(super) inner: *mut T, + pub(super) dst: *mut T, +} + +impl InPlaceDrop { + fn len(&self) -> usize { + unsafe { self.dst.offset_from(self.inner) as usize } + } +} + +impl Drop for InPlaceDrop { + #[inline] + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); + } + } +} +//! The alloc Prelude +//! +//! The purpose of this module is to alleviate imports of commonly-used +//! items of the `alloc` crate by adding a glob import to the top of modules: +//! +//! ``` +//! # #![allow(unused_imports)] +//! #![feature(alloc_prelude)] +//! extern crate alloc; +//! use alloc::prelude::v1::*; +//! ``` + +#![unstable(feature = "alloc_prelude", issue = "58935")] + +pub mod v1; +//! The first version of the prelude of `alloc` crate. +//! +//! See the [module-level documentation](../index.html) for more. + +#![unstable(feature = "alloc_prelude", issue = "58935")] + +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::borrow::ToOwned; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::boxed::Box; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::string::{String, ToString}; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::vec::Vec; +use super::*; + +extern crate test; +use crate::boxed::Box; +use test::Bencher; + +#[test] +fn allocate_zeroed() { + unsafe { + let layout = Layout::from_size_align(1024, 1).unwrap(); + let ptr = + Global.allocate_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout)); + + let mut i = ptr.as_non_null_ptr().as_ptr(); + let end = i.add(layout.size()); + while i < end { + assert_eq!(*i, 0); + i = i.offset(1); + } + Global.deallocate(ptr.as_non_null_ptr(), layout); + } +} + +#[bench] +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks +fn alloc_owned_small(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = box 10; + }) +} +//! A pointer type for heap allocation. +//! +//! [`Box`], casually referred to as a 'box', provides the simplest form of +//! heap allocation in Rust. Boxes provide ownership for this allocation, and +//! drop their contents when they go out of scope. Boxes also ensure that they +//! never allocate more than `isize::MAX` bytes. +//! +//! # Examples +//! +//! Move a value from the stack to the heap by creating a [`Box`]: +//! +//! ``` +//! let val: u8 = 5; +//! let boxed: Box = Box::new(val); +//! ``` +//! +//! Move a value from a [`Box`] back to the stack by [dereferencing]: +//! +//! ``` +//! let boxed: Box = Box::new(5); +//! let val: u8 = *boxed; +//! ``` +//! +//! Creating a recursive data structure: +//! +//! ``` +//! #[derive(Debug)] +//! enum List { +//! Cons(T, Box>), +//! Nil, +//! } +//! +//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); +//! println!("{:?}", list); +//! ``` +//! +//! This will print `Cons(1, Cons(2, Nil))`. +//! +//! Recursive structures must be boxed, because if the definition of `Cons` +//! looked like this: +//! +//! ```compile_fail,E0072 +//! # enum List { +//! Cons(T, List), +//! # } +//! ``` +//! +//! It wouldn't work. This is because the size of a `List` depends on how many +//! elements are in the list, and so we don't know how much memory to allocate +//! for a `Cons`. By introducing a [`Box`], which has a defined size, we know how +//! big `Cons` needs to be. +//! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for +//! its allocation. It is valid to convert both ways between a [`Box`] and a +//! raw pointer allocated with the [`Global`] allocator, given that the +//! [`Layout`] used with the allocator is correct for the type. More precisely, +//! a `value: *mut T` that has been allocated with the [`Global`] allocator +//! with `Layout::for_value(&*value)` may be converted into a box using +//! [`Box::::from_raw(value)`]. Conversely, the memory backing a `value: *mut +//! T` obtained from [`Box::::into_raw`] may be deallocated using the +//! [`Global`] allocator with [`Layout::for_value(&*value)`]. +//! +//! For zero-sized values, the `Box` pointer still has to be [valid] for reads +//! and writes and sufficiently aligned. In particular, casting any aligned +//! non-zero integer literal to a raw pointer produces a valid pointer, but a +//! pointer pointing into previously allocated memory that since got freed is +//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot +//! be used is to use [`ptr::NonNull::dangling`]. +//! +//! So long as `T: Sized`, a `Box` is guaranteed to be represented +//! as a single pointer and is also ABI-compatible with C pointers +//! (i.e. the C type `T*`). This means that if you have extern "C" +//! Rust functions that will be called from C, you can define those +//! Rust functions using `Box` types, and use `T*` as corresponding +//! type on the C side. As an example, consider this C header which +//! declares functions that create and destroy some kind of `Foo` +//! value: +//! +//! ```c +//! /* C header */ +//! +//! /* Returns ownership to the caller */ +//! struct Foo* foo_new(void); +//! +//! /* Takes ownership from the caller; no-op when invoked with NULL */ +//! void foo_delete(struct Foo*); +//! ``` +//! +//! These two functions might be implemented in Rust as follows. Here, the +//! `struct Foo*` type from C is translated to `Box`, which captures +//! the ownership constraints. Note also that the nullable argument to +//! `foo_delete` is represented in Rust as `Option>`, since `Box` +//! cannot be null. +//! +//! ``` +//! #[repr(C)] +//! pub struct Foo; +//! +//! #[no_mangle] +//! pub extern "C" fn foo_new() -> Box { +//! Box::new(Foo) +//! } +//! +//! #[no_mangle] +//! pub extern "C" fn foo_delete(_: Option>) {} +//! ``` +//! +//! Even though `Box` has the same representation and C ABI as a C pointer, +//! this does not mean that you can convert an arbitrary `T*` into a `Box` +//! and expect things to work. `Box` values will always be fully aligned, +//! non-null pointers. Moreover, the destructor for `Box` will attempt to +//! free the value with the global allocator. In general, the best practice +//! is to only use `Box` for pointers that originated from the global +//! allocator. +//! +//! **Important.** At least at present, you should avoid using +//! `Box` types for functions that are defined in C but invoked +//! from Rust. In those cases, you should directly mirror the C types +//! as closely as possible. Using types like `Box` where the C +//! definition is just using `T*` can lead to undefined behavior, as +//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198]. +//! +//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198 +//! [dereferencing]: core::ops::Deref +//! [`Box::::from_raw(value)`]: Box::from_raw +//! [`Global`]: crate::alloc::Global +//! [`Layout`]: crate::alloc::Layout +//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value +//! [valid]: ptr#safety + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::any::Any; +use core::borrow; +use core::cmp::Ordering; +use core::convert::{From, TryFrom}; +use core::fmt; +use core::future::Future; +use core::hash::{Hash, Hasher}; +use core::iter::{FromIterator, FusedIterator, Iterator}; +use core::marker::{Unpin, Unsize}; +use core::mem; +use core::ops::{ + CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, +}; +use core::pin::Pin; +use core::ptr::{self, Unique}; +use core::stream::Stream; +use core::task::{Context, Poll}; + +use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout, WriteCloneIntoRaw}; +use crate::borrow::Cow; +use crate::raw_vec::RawVec; +use crate::str::from_boxed_utf8_unchecked; +use crate::vec::Vec; + +/// A pointer type for heap allocation. +/// +/// See the [module-level documentation](../../std/boxed/index.html) for more. +#[lang = "owned_box"] +#[fundamental] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Box< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +>(Unique, A); + +impl Box { + /// Allocates memory on the heap and then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// let five = Box::new(5); + /// ``` + #[inline(always)] + #[doc(alias = "alloc")] + #[doc(alias = "malloc")] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(x: T) -> Self { + box x + } + + /// Constructs a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn new_uninit() -> Box> { + Self::new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let zero = Box::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[inline] + #[doc(alias = "calloc")] + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Box> { + Self::new_zeroed_in(Global) + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn pin(x: T) -> Pin> { + (box x).into() + } + + /// Allocates memory on the heap then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// let five = Box::try_new(5)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new(x: T) -> Result { + Self::try_new_in(x, Global) + } + + /// Constructs a new box with uninitialized contents on the heap, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// let mut five = Box::::try_new_uninit()?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_uninit() -> Result>, AllocError> { + Box::try_new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes on the heap + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// let zero = Box::::try_new_zeroed()?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub fn try_new_zeroed() -> Result>, AllocError> { + Box::try_new_zeroed_in(Global) + } +} + +impl Box { + /// Allocates memory in the given allocator then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let five = Box::new_in(5, System); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn new_in(x: T, alloc: A) -> Self { + let mut boxed = Self::new_uninit_in(alloc); + unsafe { + boxed.as_mut_ptr().write(x); + boxed.assume_init() + } + } + + /// Allocates memory in the given allocator then places `x` into it, + /// returning an error if the allocation fails + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let five = Box::try_new_in(5, System)?; + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_in(x: T, alloc: A) -> Result { + let mut boxed = Self::try_new_uninit_in(alloc)?; + unsafe { + boxed.as_mut_ptr().write(x); + Ok(boxed.assume_init()) + } + } + + /// Constructs a new box with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::::new_uninit_in(System); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_in(alloc: A) -> Box, A> { + let layout = Layout::new::>(); + // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. + // That would make code size bigger. + match Box::try_new_uninit_in(alloc) { + Ok(m) => m, + Err(_) => handle_alloc_error(layout), + } + } + + /// Constructs a new box with uninitialized contents in the provided allocator, + /// returning an error if the allocation fails + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::::try_new_uninit_in(System)?; + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + let layout = Layout::new::>(); + let ptr = alloc.allocate(layout)?.cast(); + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let zero = Box::::new_zeroed_in(System); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_in(alloc: A) -> Box, A> { + let layout = Layout::new::>(); + // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. + // That would make code size bigger. + match Box::try_new_zeroed_in(alloc) { + Ok(m) => m, + Err(_) => handle_alloc_error(layout), + } + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes in the provided allocator, + /// returning an error if the allocation fails, + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let zero = Box::::try_new_zeroed_in(System)?; + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0); + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + let layout = Layout::new::>(); + let ptr = alloc.allocate_zeroed(layout)?.cast(); + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline(always)] + pub fn pin_in(x: T, alloc: A) -> Pin + where + A: 'static, + { + Self::new_in(x, alloc).into() + } + + /// Converts a `Box` into a `Box<[T]>` + /// + /// This conversion does not allocate on the heap and happens in place. + #[unstable(feature = "box_into_boxed_slice", issue = "71582")] + pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_allocator(boxed); + unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } + } + + /// Consumes the `Box`, returning the wrapped value. + /// + /// # Examples + /// + /// ``` + /// #![feature(box_into_inner)] + /// + /// let c = Box::new(5); + /// + /// assert_eq!(Box::into_inner(c), 5); + /// ``` + #[unstable(feature = "box_into_inner", issue = "80437")] + #[inline] + pub fn into_inner(boxed: Self) -> T { + *boxed + } +} + +impl Box<[T]> { + /// Constructs a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { + unsafe { RawVec::with_capacity(len).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let values = Box::<[u32]>::new_zeroed_slice(3); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { + unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } + } +} + +impl Box<[T], A> { + /// Constructs a new boxed slice with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut values = Box::<[u32], _>::new_uninit_slice_in(3, System); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents in the provided allocator, + /// with the memory being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let values = Box::<[u32], _>::new_zeroed_slice_in(3, System); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } + } +} + +impl Box, A> { + /// Converts to `Box`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five: Box = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box { + let (raw, alloc) = Box::into_raw_with_allocator(self); + unsafe { Box::from_raw_in(raw as *mut T, alloc) } + } +} + +impl Box<[mem::MaybeUninit], A> { + /// Converts to `Box<[T], A>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_allocator(self); + unsafe { Box::from_raw_in(raw as *mut [T], alloc) } + } +} + +impl Box { + /// Constructs a box from a raw pointer. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// The safety conditions are described in the [memory layout] section. + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw`]: + /// ``` + /// let x = Box::new(5); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; + /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// use std::alloc::{alloc, Layout}; + /// + /// unsafe { + /// let ptr = alloc(Layout::new::()) as *mut i32; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); + /// let x = Box::from_raw(ptr); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[stable(feature = "box_raw", since = "1.4.0")] + #[inline] + pub unsafe fn from_raw(raw: *mut T) -> Self { + unsafe { Self::from_raw_in(raw, Global) } + } +} + +impl Box { + /// Constructs a box from a raw pointer in the given allocator. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw_with_allocator`]: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, slice_ptr_get)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// + /// unsafe { + /// let ptr = System.allocate(Layout::new::())?.as_mut_ptr() as *mut i32; + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); + /// let x = Box::from_raw_in(ptr, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + Box(unsafe { Unique::new_unchecked(raw) }, alloc) + } + + /// Consumes the `Box`, returning a wrapped raw pointer. + /// + /// The pointer will be properly aligned and non-null. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw`] function, allowing the `Box` destructor to perform + /// the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// for automatic cleanup: + /// ``` + /// let x = Box::new(String::from("Hello")); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// use std::alloc::{dealloc, Layout}; + /// use std::ptr; + /// + /// let x = Box::new(String::from("Hello")); + /// let p = Box::into_raw(x); + /// unsafe { + /// ptr::drop_in_place(p); + /// dealloc(p as *mut u8, Layout::new::()); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[stable(feature = "box_raw", since = "1.4.0")] + #[inline] + pub fn into_raw(b: Self) -> *mut T { + Self::into_raw_with_allocator(b).0 + } + + /// Consumes the `Box`, returning a wrapped raw pointer and the allocator. + /// + /// The pointer will be properly aligned and non-null. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform + /// the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`] + /// for automatic cleanup: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::{Allocator, Layout, System}; + /// use std::ptr::{self, NonNull}; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (ptr, alloc) = Box::into_raw_with_allocator(x); + /// unsafe { + /// ptr::drop_in_place(ptr); + /// let non_null = NonNull::new_unchecked(ptr); + /// alloc.deallocate(non_null.cast(), Layout::new::()); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { + let (leaked, alloc) = Box::into_unique(b); + (leaked.as_ptr(), alloc) + } + + #[unstable( + feature = "ptr_internals", + issue = "none", + reason = "use `Box::leak(b).into()` or `Unique::from(Box::leak(b))` instead" + )] + #[inline] + #[doc(hidden)] + pub fn into_unique(b: Self) -> (Unique, A) { + // Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a + // raw pointer for the type system. Turning it directly into a raw pointer would not be + // recognized as "releasing" the unique pointer to permit aliased raw accesses, + // so all raw pointer methods have to go through `Box::leak`. Turning *that* to a raw pointer + // behaves correctly. + let alloc = unsafe { ptr::read(&b.1) }; + (Unique::from(Box::leak(b)), alloc) + } + + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This + /// is so that there is no conflict with a method on the inner type. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(b: &Self) -> &A { + &b.1 + } + + /// Consumes and leaks the `Box`, returning a mutable reference, + /// `&'a mut T`. Note that the type `T` must outlive the chosen lifetime + /// `'a`. If the type has only static references, or none at all, then this + /// may be chosen to be `'static`. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. If this is not acceptable, the reference should first be wrapped + /// with the [`Box::from_raw`] function producing a `Box`. This `Box` can + /// then be dropped which will properly destroy `T` and release the + /// allocated memory. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::leak(b)` instead of `b.leak()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// let x = Box::new(41); + /// let static_ref: &'static mut usize = Box::leak(x); + /// *static_ref += 1; + /// assert_eq!(*static_ref, 42); + /// ``` + /// + /// Unsized data: + /// + /// ``` + /// let x = vec![1, 2, 3].into_boxed_slice(); + /// let static_ref = Box::leak(x); + /// static_ref[0] = 4; + /// assert_eq!(*static_ref, [4, 2, 3]); + /// ``` + #[stable(feature = "box_leak", since = "1.26.0")] + #[inline] + pub fn leak<'a>(b: Self) -> &'a mut T + where + A: 'a, + { + unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() } + } + + /// Converts a `Box` into a `Pin>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// This is also available via [`From`]. + #[unstable(feature = "box_into_pin", issue = "62370")] + pub fn into_pin(boxed: Self) -> Pin + where + A: 'static, + { + // It's not possible to move or replace the insides of a `Pin>` + // when `T: !Unpin`, so it's safe to pin it directly without any + // additional requirements. + unsafe { Pin::new_unchecked(boxed) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { + fn drop(&mut self) { + // FIXME: Do nothing, drop is currently performed by compiler. + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Box { + /// Creates a `Box`, with the `Default` value for T. + fn default() -> Self { + box T::default() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Box<[T]> { + fn default() -> Self { + Box::<[T; 0]>::new([]) + } +} + +#[stable(feature = "default_box_extra", since = "1.17.0")] +impl Default for Box { + fn default() -> Self { + unsafe { from_boxed_utf8_unchecked(Default::default()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Box { + /// Returns a new box with a `clone()` of this box's contents. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let y = x.clone(); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // But they are unique objects + /// assert_ne!(&*x as *const i32, &*y as *const i32); + /// ``` + #[inline] + fn clone(&self) -> Self { + // Pre-allocate memory to allow writing the cloned value directly. + let mut boxed = Self::new_uninit_in(self.1.clone()); + unsafe { + (**self).write_clone_into_raw(boxed.as_mut_ptr()); + boxed.assume_init() + } + } + + /// Copies `source`'s contents into `self` without creating a new allocation. + /// + /// # Examples + /// + /// ``` + /// let x = Box::new(5); + /// let mut y = Box::new(10); + /// let yp: *const i32 = &*y; + /// + /// y.clone_from(&x); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no allocation occurred + /// assert_eq!(yp, &*y); + /// ``` + #[inline] + fn clone_from(&mut self, source: &Self) { + (**self).clone_from(&(**source)); + } +} + +#[stable(feature = "box_slice_clone", since = "1.3.0")] +impl Clone for Box { + fn clone(&self) -> Self { + // this makes a copy of the data + let buf: Box<[u8]> = self.as_bytes().into(); + unsafe { from_boxed_utf8_unchecked(buf) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Box { + #[inline] + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(&**self, &**other) + } + #[inline] + fn ne(&self, other: &Self) -> bool { + PartialEq::ne(&**self, &**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Box { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } + #[inline] + fn lt(&self, other: &Self) -> bool { + PartialOrd::lt(&**self, &**other) + } + #[inline] + fn le(&self, other: &Self) -> bool { + PartialOrd::le(&**self, &**other) + } + #[inline] + fn ge(&self, other: &Self) -> bool { + PartialOrd::ge(&**self, &**other) + } + #[inline] + fn gt(&self, other: &Self) -> bool { + PartialOrd::gt(&**self, &**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Box { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Box {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Box { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +#[stable(feature = "indirect_hasher_impl", since = "1.22.0")] +impl Hasher for Box { + fn finish(&self) -> u64 { + (**self).finish() + } + fn write(&mut self, bytes: &[u8]) { + (**self).write(bytes) + } + fn write_u8(&mut self, i: u8) { + (**self).write_u8(i) + } + fn write_u16(&mut self, i: u16) { + (**self).write_u16(i) + } + fn write_u32(&mut self, i: u32) { + (**self).write_u32(i) + } + fn write_u64(&mut self, i: u64) { + (**self).write_u64(i) + } + fn write_u128(&mut self, i: u128) { + (**self).write_u128(i) + } + fn write_usize(&mut self, i: usize) { + (**self).write_usize(i) + } + fn write_i8(&mut self, i: i8) { + (**self).write_i8(i) + } + fn write_i16(&mut self, i: i16) { + (**self).write_i16(i) + } + fn write_i32(&mut self, i: i32) { + (**self).write_i32(i) + } + fn write_i64(&mut self, i: i64) { + (**self).write_i64(i) + } + fn write_i128(&mut self, i: i128) { + (**self).write_i128(i) + } + fn write_isize(&mut self, i: isize) { + (**self).write_isize(i) + } +} + +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Box { + /// Converts a generic type `T` into a `Box` + /// + /// The conversion allocates on the heap and moves `t` + /// from the stack into it. + /// + /// # Examples + /// ```rust + /// let x = 5; + /// let boxed = Box::new(5); + /// + /// assert_eq!(Box::from(x), boxed); + /// ``` + fn from(t: T) -> Self { + Box::new(t) + } +} + +#[stable(feature = "pin", since = "1.33.0")] +impl From> for Pin> +where + A: 'static, +{ + /// Converts a `Box` into a `Pin>` + /// + /// This conversion does not allocate on the heap and happens in place. + fn from(boxed: Box) -> Self { + Box::into_pin(boxed) + } +} + +#[stable(feature = "box_from_slice", since = "1.17.0")] +impl From<&[T]> for Box<[T]> { + /// Converts a `&[T]` into a `Box<[T]>` + /// + /// This conversion allocates on the heap + /// and performs a copy of `slice`. + /// + /// # Examples + /// ```rust + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice: Box<[u8]> = Box::from(slice); + /// + /// println!("{:?}", boxed_slice); + /// ``` + fn from(slice: &[T]) -> Box<[T]> { + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box(slice.len()).assume_init() + } + } +} + +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box<[T]> { + #[inline] + fn from(cow: Cow<'_, [T]>) -> Box<[T]> { + match cow { + Cow::Borrowed(slice) => Box::from(slice), + Cow::Owned(slice) => Box::from(slice), + } + } +} + +#[stable(feature = "box_from_slice", since = "1.17.0")] +impl From<&str> for Box { + /// Converts a `&str` into a `Box` + /// + /// This conversion allocates on the heap + /// and performs a copy of `s`. + /// + /// # Examples + /// ```rust + /// let boxed: Box = Box::from("hello"); + /// println!("{}", boxed); + /// ``` + #[inline] + fn from(s: &str) -> Box { + unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } + } +} + +#[stable(feature = "box_from_cow", since = "1.45.0")] +impl From> for Box { + #[inline] + fn from(cow: Cow<'_, str>) -> Box { + match cow { + Cow::Borrowed(s) => Box::from(s), + Cow::Owned(s) => Box::from(s), + } + } +} + +#[stable(feature = "boxed_str_conv", since = "1.19.0")] +impl From> for Box<[u8], A> { + /// Converts a `Box` into a `Box<[u8]>` + /// + /// This conversion does not allocate on the heap and happens in place. + /// + /// # Examples + /// ```rust + /// // create a Box which will be used to create a Box<[u8]> + /// let boxed: Box = Box::from("hello"); + /// let boxed_str: Box<[u8]> = Box::from(boxed); + /// + /// // create a &[u8] which will be used to create a Box<[u8]> + /// let slice: &[u8] = &[104, 101, 108, 108, 111]; + /// let boxed_slice = Box::from(slice); + /// + /// assert_eq!(boxed_slice, boxed_str); + /// ``` + #[inline] + fn from(s: Box) -> Self { + let (raw, alloc) = Box::into_raw_with_allocator(s); + unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } + } +} + +#[stable(feature = "box_from_array", since = "1.45.0")] +impl From<[T; N]> for Box<[T]> { + /// Converts a `[T; N]` into a `Box<[T]>` + /// + /// This conversion moves the array to newly heap-allocated memory. + /// + /// # Examples + /// ```rust + /// let boxed: Box<[u8]> = Box::from([4, 2]); + /// println!("{:?}", boxed); + /// ``` + fn from(array: [T; N]) -> Box<[T]> { + box array + } +} + +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] +impl TryFrom> for Box<[T; N]> { + type Error = Box<[T]>; + + fn try_from(boxed_slice: Box<[T]>) -> Result { + if boxed_slice.len() == N { + Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + +impl Box { + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + /// Attempt to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Self> { + if self.is::() { + unsafe { + let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); + Ok(Box::from_raw_in(raw as *mut T, alloc)) + } + } else { + Err(self) + } + } +} + +impl Box { + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + /// Attempt to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Self> { + if self.is::() { + unsafe { + let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); + Ok(Box::from_raw_in(raw as *mut T, alloc)) + } + } else { + Err(self) + } + } +} + +impl Box { + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] + /// Attempt to downcast the box to a concrete type. + /// + /// # Examples + /// + /// ``` + /// use std::any::Any; + /// + /// fn print_if_string(value: Box) { + /// if let Ok(string) = value.downcast::() { + /// println!("String ({}): {}", string.len(), string); + /// } + /// } + /// + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); + /// ``` + pub fn downcast(self) -> Result, Self> { + if self.is::() { + unsafe { + let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = + Box::into_raw_with_allocator(self); + Ok(Box::from_raw_in(raw as *mut T, alloc)) + } + } else { + Err(self) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Box { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // It's not possible to extract the inner Uniq directly from the Box, + // instead we cast it to a *const which aliases the Unique + let ptr: *const T = &**self; + fmt::Pointer::fmt(&ptr, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Box { + type Target = T; + + fn deref(&self) -> &T { + &**self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DerefMut for Box { + fn deref_mut(&mut self) -> &mut T { + &mut **self + } +} + +#[unstable(feature = "receiver_trait", issue = "none")] +impl Receiver for Box {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Box { + type Item = I::Item; + fn next(&mut self) -> Option { + (**self).next() + } + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } + fn nth(&mut self, n: usize) -> Option { + (**self).nth(n) + } + fn last(self) -> Option { + BoxIter::last(self) + } +} + +trait BoxIter { + type Item; + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + default fn last(self) -> Option { + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) + } +} + +/// Specialization for sized `I`s that uses `I`s implementation of `last()` +/// instead of the default. +#[stable(feature = "rust1", since = "1.0.0")] +impl BoxIter for Box { + fn last(self) -> Option { + (*self).last() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Box { + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Box { + fn len(&self) -> usize { + (**self).len() + } + fn is_empty(&self) -> bool { + (**self).is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Box {} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnOnce for Box { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + >::call_once(*self, args) + } +} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> FnMut for Box { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + >::call_mut(self, args) + } +} + +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +impl + ?Sized, A: Allocator> Fn for Box { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + >::call(self, args) + } +} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} + +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for Box {} + +#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] +impl FromIterator for Box<[I]> { + fn from_iter>(iter: T) -> Self { + iter.into_iter().collect::>().into_boxed_slice() + } +} + +#[stable(feature = "box_slice_clone", since = "1.3.0")] +impl Clone for Box<[T], A> { + fn clone(&self) -> Self { + let alloc = Box::allocator(self).clone(); + self.to_vec_in(alloc).into_boxed_slice() + } + + fn clone_from(&mut self, other: &Self) { + if self.len() == other.len() { + self.clone_from_slice(&other); + } else { + *self = other.clone(); + } + } +} + +#[stable(feature = "box_borrow", since = "1.1.0")] +impl borrow::Borrow for Box { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(feature = "box_borrow", since = "1.1.0")] +impl borrow::BorrowMut for Box { + fn borrow_mut(&mut self) -> &mut T { + &mut **self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Box { + fn as_ref(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsMut for Box { + fn as_mut(&mut self) -> &mut T { + &mut **self + } +} + +/* Nota bene + * + * We could have chosen not to add this impl, and instead have written a + * function of Pin> to Pin. Such a function would not be sound, + * because Box implements Unpin even when T does not, as a result of + * this impl. + * + * We chose this API instead of the alternative for a few reasons: + * - Logically, it is helpful to understand pinning in regard to the + * memory region being pointed to. For this reason none of the + * standard library pointer types support projecting through a pin + * (Box is the only pointer type in std for which this would be + * safe.) + * - It is in practice very useful to have Box be unconditionally + * Unpin because of trait objects, for which the structural auto + * trait functionality does not apply (e.g., Box would + * otherwise not be Unpin). + * + * Another type with the same semantics as Box but only a conditional + * implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and + * could have a method to project a Pin from it. + */ +#[stable(feature = "pin", since = "1.33.0")] +impl Unpin for Box where A: 'static {} + +#[unstable(feature = "generator_trait", issue = "43122")] +impl + Unpin, R, A: Allocator> Generator for Box +where + A: 'static, +{ + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState { + G::resume(Pin::new(&mut *self), arg) + } +} + +#[unstable(feature = "generator_trait", issue = "43122")] +impl, R, A: Allocator> Generator for Pin> +where + A: 'static, +{ + type Yield = G::Yield; + type Return = G::Return; + + fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState { + G::resume((*self).as_mut(), arg) + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl Future for Box +where + A: 'static, +{ + type Output = F::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + F::poll(Pin::new(&mut *self), cx) + } +} + +#[unstable(feature = "async_stream", issue = "79024")] +impl Stream for Box { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut **self).poll_next(cx) + } + + fn size_hint(&self) -> (usize, Option) { + (**self).size_hint() + } +} +use super::*; +use std::cell::Cell; + +#[test] +fn allocator_param() { + use crate::alloc::AllocError; + + // Writing a test of integration between third-party + // allocators and `RawVec` is a little tricky because the `RawVec` + // API does not expose fallible allocation methods, so we + // cannot check what happens when allocator is exhausted + // (beyond detecting a panic). + // + // Instead, this just checks that the `RawVec` methods do at + // least go through the Allocator API when it reserves + // storage. + + // A dumb allocator that consumes a fixed amount of fuel + // before allocation attempts start failing. + struct BoundedAlloc { + fuel: Cell, + } + unsafe impl Allocator for BoundedAlloc { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + let size = layout.size(); + if size > self.fuel.get() { + return Err(AllocError); + } + match Global.allocate(layout) { + ok @ Ok(_) => { + self.fuel.set(self.fuel.get() - size); + ok + } + err @ Err(_) => err, + } + } + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + unsafe { Global.deallocate(ptr, layout) } + } + } + + let a = BoundedAlloc { fuel: Cell::new(500) }; + let mut v: RawVec = RawVec::with_capacity_in(50, a); + assert_eq!(v.alloc.fuel.get(), 450); + v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel) + assert_eq!(v.alloc.fuel.get(), 250); +} + +#[test] +fn reserve_does_not_overallocate() { + { + let mut v: RawVec = RawVec::new(); + // First, `reserve` allocates like `reserve_exact`. + v.reserve(0, 9); + assert_eq!(9, v.capacity()); + } + + { + let mut v: RawVec = RawVec::new(); + v.reserve(0, 7); + assert_eq!(7, v.capacity()); + // 97 is more than double of 7, so `reserve` should work + // like `reserve_exact`. + v.reserve(7, 90); + assert_eq!(97, v.capacity()); + } + + { + let mut v: RawVec = RawVec::new(); + v.reserve(0, 12); + assert_eq!(12, v.capacity()); + v.reserve(12, 3); + // 3 is less than half of 12, so `reserve` must grow + // exponentially. At the time of writing this test grow + // factor is 2, so new capacity is 24, however, grow factor + // of 1.5 is OK too. Hence `>= 18` in assert. + assert!(v.capacity() >= 12 + 12 / 2); + } +} +//! Test for `boxed` mod. + +use core::any::Any; +use core::clone::Clone; +use core::convert::TryInto; +use core::ops::Deref; +use core::result::Result::{Err, Ok}; + +use std::boxed::Box; + +#[test] +fn test_owned_clone() { + let a = Box::new(5); + let b: Box = a.clone(); + assert!(a == b); +} + +#[derive(PartialEq, Eq)] +struct Test; + +#[test] +fn any_move() { + let a = Box::new(8) as Box; + let b = Box::new(Test) as Box; + + match a.downcast::() { + Ok(a) => { + assert!(a == Box::new(8)); + } + Err(..) => panic!(), + } + match b.downcast::() { + Ok(a) => { + assert!(a == Box::new(Test)); + } + Err(..) => panic!(), + } + + let a = Box::new(8) as Box; + let b = Box::new(Test) as Box; + + assert!(a.downcast::>().is_err()); + assert!(b.downcast::>().is_err()); +} + +#[test] +fn test_show() { + let a = Box::new(8) as Box; + let b = Box::new(Test) as Box; + let a_str = format!("{:?}", a); + let b_str = format!("{:?}", b); + assert_eq!(a_str, "Any { .. }"); + assert_eq!(b_str, "Any { .. }"); + + static EIGHT: usize = 8; + static TEST: Test = Test; + let a = &EIGHT as &dyn Any; + let b = &TEST as &dyn Any; + let s = format!("{:?}", a); + assert_eq!(s, "Any { .. }"); + let s = format!("{:?}", b); + assert_eq!(s, "Any { .. }"); +} + +#[test] +fn deref() { + fn homura>(_: T) {} + homura(Box::new(765)); +} + +#[test] +fn raw_sized() { + let x = Box::new(17); + let p = Box::into_raw(x); + unsafe { + assert_eq!(17, *p); + *p = 19; + let y = Box::from_raw(p); + assert_eq!(19, *y); + } +} + +#[test] +fn raw_trait() { + trait Foo { + fn get(&self) -> u32; + fn set(&mut self, value: u32); + } + + struct Bar(u32); + + impl Foo for Bar { + fn get(&self) -> u32 { + self.0 + } + + fn set(&mut self, value: u32) { + self.0 = value; + } + } + + let x: Box = Box::new(Bar(17)); + let p = Box::into_raw(x); + unsafe { + assert_eq!(17, (*p).get()); + (*p).set(19); + let y: Box = Box::from_raw(p); + assert_eq!(19, y.get()); + } +} + +#[test] +fn f64_slice() { + let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY]; + let boxed: Box<[f64]> = Box::from(slice); + assert_eq!(&*boxed, slice) +} + +#[test] +fn i64_slice() { + let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX]; + let boxed: Box<[i64]> = Box::from(slice); + assert_eq!(&*boxed, slice) +} + +#[test] +fn str_slice() { + let s = "Hello, world!"; + let boxed: Box = Box::from(s); + assert_eq!(&*boxed, s) +} + +#[test] +fn boxed_slice_from_iter() { + let iter = 0..100; + let boxed: Box<[u32]> = iter.collect(); + assert_eq!(boxed.len(), 100); + assert_eq!(boxed[7], 7); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Box<[u32]> = v.into_boxed_slice(); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/bench/data/opensubtitles/README.md b/bench/data/opensubtitles/README.md new file mode 100644 index 0000000..8038503 --- /dev/null +++ b/bench/data/opensubtitles/README.md @@ -0,0 +1,12 @@ +These were downloaded and derived from the Open Subtitles data set: +https://opus.nlpl.eu/OpenSubtitles-v2018.php + +The specific way in which they were modified has been lost to time, but it's +likely they were just a simple truncation based on target file sizes for +various benchmarks. + +The main reason why we have them is that it gives us a way to test similar +inputs on non-ASCII text. Normally this wouldn't matter for a substring search +implementation, but because of the heuristics used to pick a priori determined +"rare bytes" to base a prefilter on, it's possible for this heuristic to do +more poorly on non-ASCII text than one might expect. diff --git a/bench/data/opensubtitles/en-huge.txt b/bench/data/opensubtitles/en-huge.txt new file mode 100644 index 0000000..a076946 --- /dev/null +++ b/bench/data/opensubtitles/en-huge.txt @@ -0,0 +1,22927 @@ +Now you can tell 'em. +What for are you mixing in? +Maybe I don't like to see kids get hurt. +Break any bones, son? +He's got a knife behind his collar! +- There's a stirrup. +You want a lift? +- No. +- Why not? +- I'm beholden to you, mister. +Couldn't we just leave it that way? +- Morning. +- Morning. +- Put him up? +- For how long? +- I wouldn't know. +- It'll be two bits for oats. +- Ain't I seen you before? +- Depends on where you've been. +- I follow the railroad, mostly. +- Could be you've seen me. +- It'll be four bits if he stays the night. +- Fair enough. +Morning. +Did a man ride in today - tall, sort of heavyset? +- You mean him, Mr Renner? +- Not him. +This one had a scar. +Along his cheek? +No, sir. +I don't see no man with a scar. +I guess maybe I can have some apple pie and coffee. +I guess you could have eggs with bacon if you wanted eggs with bacon. +- Hello, Charlie. +- Hello, Grant. +It's good to see you, Charlie. +It's awful good to see you. +It's good to see you too. +- I'll get the eggs. +- No, get the pie. +I can pay for the pie. +You're a very stubborn man. +Apple pie is not for breakfast. +It is if you like apple pie. +Now I need a fork. +- Working here long? +- About three weeks. +How's the Utica Kid? +He was well... when I saw him last. +When was that? +- Good morning. +- Morning. +Well, business is early and Pete is late. +The lunches. +Are they fixed? +Why do I ask? +The lunches are always fixed. +Why? +Because you fix them. +Charlie, I'll make you an omelette like only Pete can make an omelette. +Very bad. +Come on around, sit down, have a cup of coffee. +Pete had that place in Santa Fe, remember? +Are you running a shoe store on the side? +Those are box lunches for the work train. +Money, money, money. +Pete knows how to make it. +He follows the railroad. +I guess a lot of people follow the railroad. +You and Pete. +The Utica Kid. +I asked when you saw him last. +They've lost three payrolls. +Now when did you see him last? +- Charlie, where did I put my apron? +- It's under here. +You must be nice fella. +If Charlie sits with you, you must be nice fella. +I make omelette for you too. +We were talking about the Utica Kid. +He can wait. +Ben Kimball's in town. +They put his car on the siding yesterday. +- I know. +- His wife is with him. +Is she? +I often wondered what Verna was like. +I saw her last night. +All fine silk and feathers. +She's soft and beautiful. +And I can understand now. +Can you? +How long are you gonna be in town? +- That depends on Ben Kimball. +- You working for the railroad again? +- If I am? +- That would be good. +Playing the accordion's not for you, not for a living. +You belong to the railroad and it belongs to you. +There were a lot of things that used to belong to me and somehow I lost them. +Two omelettes a-comin' up. +- Do you like eggs? +- No. +That's too bad. +You got an omelette coming up. +Well, somebody's gotta eat them. +Come on. +That means you. +- Could you put it in a box? +- An omelette? +I'll be hungrier when I get to end of track. +Maybe it will go down easy. +Easy or not, it goes down right now. +I can't pay for it. +Then you can help me sell lunches at the station. +Any more arguments? +Come in. +- You want to see me, Ben? +- I certainly do. +Hello, Grant. +Sit down. +All right, Jeff. +Renner, go to Pete's and get one breakfast and a jug of coffee. +- You haven't eaten yet? +- I've eaten. +Just get coffee. +Hot. +- How's everything been going? +- I make a living. +- Playing an accordion? +- That's right. +Want me to play a tune for you? +There's other jobs besides railroading. +Well, Colorado may be big in miles. +It's kinda short on people. +So when a man gets fired the way I was fired the story gets around. +Well, I'm... +I'm sorry. +- No, I like to make music. +- And it keeps you near the railroad. +If someone needs information about a payroll, you can sell it. +You know it's a funny thing. +I don't like you either. +- Is that why you sent for me? +- No. +And keep out of this. +Have it your way. +But I don't trust him now any more than I did when I sent him after the Utica Kid. +I sent you after a thief and you gave him a horse to get away on. +- I told you to keep shut. +- Let him talk. +I'm not wearing a gun. +I'll be honest with you. +He'd talk the same if I was. +- It's been nice seeing you. +- Grant. +I'm sure Jeff didn't mean to be rude. +Sometimes he has a blunt way of putting things. +Unfortunately, Ben isn't much better. +It's not unfortunate. +It just gets things said in a hurry. +Too much of a hurry. +They forgot to ask you if you'd work for the railroad again. +Would you? +Yes, I would. +Not to give you a short answer. +- It's the answer I wanted. +- Sit down, Grant. +Do you remember Whitey Harbin? +Used to work down in Arizona and New Mexico. +- Yeah. +- Well, he's moved into Colorado. +I thought he favoured stage lines and banks. +So did we. +But he's learned about railroad payrolls +- and he's grabbed three in a row. +- Where do I fit in? +They're making up a supply train in the yard. +I want you to ride it. +- With $10,000 in your pocket. +- Why me? +Quite frankly, because no one would suspect you of carrying a payroll. +I sure don't look like $10,000, do I? +Are you building a bridge you don't need? +The money's here. +Why not bring the men in on Saturday and pay them off in town? +And lose half the crew? +Turn them loose in a mining town, they'll go up the hills looking for gold. +It won't work. +And we have to finish this section before snow comes. +That's a pretty big gamble on a man who gave his horse to a thief! +Yes. +You might as well know the deck's stacked against you. +A boxcar will be hooked to the train. +I'll be one of the men in it. +- When did this happen? +- Last week. +- Renner, did you know? +- Yes. +- Why didn't you tell me? +- I told him not to. +- Why? +- Everything we plan gets back to Whitey. +- You think I'd tell him? +- You might trust the wrong people. +- If he takes the job, I'm sure of it. +- And if I don't take it? +Then Jeff will be sitting in Ben's chair. +Oh, I wouldn't like that. +Uh-uh. +So I'll take the job on one condition. +If I make the delivery I get his job. +You made a deal. +Thank you. +Wait a minute. +It's getting cold up in the hills. +This coat has always been too long for me. +Thanks. +Well. +I thought you didn't like him. +He said that. +I said I didn't trust him. +And I still don't. +Grant. +Are you surprised Ben sent for you? +I was until I talked to him. +He seems to have changed. +You're right. +He doesn't belong in a private car with clerks, figures and pressure from the office. +He belongs at the end of track, running a gang and building a railroad. +- He's a working stiff like you. +- Yes, but he can dream a little too. +Colorado wouldn't have a railroad if he hadn't sold them on the idea. +For his sake, I wish he hadn't. +He was happy at end of track but they kicked him upstairs and sent us to Chicago. +- And now he needs a little help. +- That's why he sent for you. +Oh, I may have had something to do with it. +Why? +There was a time when you were interested in me. +I was more than interested in you. +I wanted to marry you. +Times when I'm sorry you didn't. +Aren't you? +No. +A man likes to know his woman will back him when he's down and you didn't. +Ben called me a thief and you went right along with him. +It's as simple as that. +Grant. +For old times' sake. +For old times' sake? +Just that and nothing more? +Perhaps just a little more. +We want to be sure that payroll goes through, don't we? +I don't know. +Maybe Jeff is right. +His type seldom changes. +And if we've made a mistake, it's the finish of everything. +Then why not cut this car into the supply train? +If we're all playing showdown, I'd like to see the cards when they fall. +- Thank you. +I hope you have a nice trip. +- Thank you. +- Ma'am, is that all? +- Mm-hm. +- Here's your lunch. +You've earned it. +- Thanks. +- Mister, are you going to end of track? +- Yes. +Could you stake me to a ticket? +I can ride half fare if I'm with an adult. +- And you're an adult. +- Well, sometimes I wonder. +All right. +You can come along. +We'll ride with the other fellas with no money. +- On the flatcar? +- Go on. +Climb aboard. +Plenty of fresh air. +Do you good, make you grow. +Are you sure he didn't come while I was away? +Ain't nobody been here but the man riding the sorrel. +- What colour horse your man riding? +- How should I know? +It's extremely important that I see him. +They've cut in Mr Kimball's car. +Barley! +A man told you to put his horse up... +Don't start that too. +That there sorrel is the only horse what come in. +That there sorrel is the horse I want. +He belongs to my friend Grant McLaine. +McLaine? +That's who it is. +I knew him as a troubleshooter in Santa Fe before he went bad. +- He didn't go bad. +- What'll you do with his horse? +- Ride him! +I'll change, you saddle him. +- All right. +Hey, Pilgrim! +Come here! +Don't go getting your liver all upset. +- Once you miss 'em, they stay missed. +- It's none of your business. +- Could be. +You wanting to get on that car? +- If I am? +- I can take you to where it's going. +- On one of these? +They'll get you to end of track before the train does. +- That's ridiculous. +- $100 aging yours I'm right. +- You've got a bet. +- And you got stuck. +Here. +I'll let you ride Flap Ears. +- You can smoke inside, mister. +- I can smoke where I want. +You can burn too if it pleases you but it'll still cost you four bits. +- For what? +- Travelling first-class. +Otherwise ride the flats. +- You play that? +- Yeah, I play it. +- When? +- When? +Whenever somebody throws a dime in my hat. +- I ain't got a dime. +- This one's on me. +- Been up here before? +- Part way. +- What takes you to end of track? +- A job. +Figured I'd get one at Junction City. +They told me the foremen do the hiring. +You're a little small for swinging a sledge. +- I can carry water. +- Yeah, you can carry water. +- Very important job. +- Hey! +- What are you doing here? +- He's with me, Pick. +- Where did you get him? +- Somebody threw him away. +Don't you throw him away. +He'll get lost in the mountains. +Who tells the men who build railroads how to get through the mountains? +- The river. +- Huh? +They just follow the river. +- Who told you that? +- I guess my dad was the first. +He had a little song about it. +# Follow the river +# The river knows the way +# Hearts can go astray +# It happens every day +# Follow the river +# Wherever you may be +# Follow the river back to me # +Wouldn't you wanna be knowing about Concho? +- Who's Concho? +- The man you roped. +Do you wanna know? +Not unless you wanna tell me. +I ought to tell you. +He's fast with a gun. +Only know two men who are faster. +Which two men would they be? +Whitey Harbin for one. +I run away from Whitey. +That's why Concho was after me. +You're one of Whitey's men? +No. +I was in Montrose. +Whitey and his bunch were robbing a bank. +I was just in the road watching. +Whitey was all for killing me but the other fellow wouldn't let him. +He swung me up into the saddle and said, +"You ain't killing a kid. +Not while I ride with you." +- Whitey, he backed down. +- Cos the fella's faster with a gun? +Like lightning. +This other fella, does he have a name? +He's got a name. +The Utica Kid. +I'd have stayed with the bunch if he was boss. +- But he's not? +- Not yet. +Always he's shoving pins into Whitey, laughing at him, driving him crazy. +Even crazier than he is! +Someday Whitey will crack and he'll lose. +Is this the fresh air you were talking about? +How come them fellas can ride inside? +Well, it's the old story of good and evil. +If you spend all your money on whiskey, you have none left for a ticket. +Don't drink. +Then you'd have six bits when you need it. +That's very true. +Tell you what, maybe I have six bits. +Yeah. +What do you say we go in and spend it? +Come on. +Guess I wasn't tough enough to follow the river that way. +Sometimes it isn't easy travelling upstream. +- That will be a dollar. +- That'll be six bits. +I'm the adult. +Here. +Hold on to that. +- Don't worry about Concho. +- You would if... +Oh, no, come on. +Sit down. +We can both worry together if you want to tell me about it. +- It's nothing. +- And if it was, you'd rather not say. +All right. +I broke with Whitey. +Doesn't mean I have to talk. +No, you don't have to talk. +I even broke with the Utica Kid. +- Hi, Utica. +- Put him away, Howdy. +Sure. +Come on. +It's a pretty good rig. +Too good for the guy that owned it. +Remember that draw you taught me? +It worked. +He went down with his gun in the leather. +- And now you're an "in case" man. +- In case? +Yeah. +In case you miss six times with one, you draw the other. +- If you have time. +- I'll have time. +Call it. +Draw! +You better learn to draw that one before you fool around with the other. +About three inches high, Whitey. +You better take another look at that skull. +Next time it could be yours. +Don't soft-foot up behind me! +It makes me nervous! +So I notice. +What else did you notice? +Did you see Concho? +- Did you see him? +- He wasn't on the trail. +Did I ask you where he wasn't? +I asked you did you see him? +- I would've said so. +- Not straight out you wouldn't. +Because you're a funny man. +You've always gotta be laughing inside. +Well, go ahead, laugh. +But get this, Kid. +I'm a better gun than you. +Or would you like to try? +It's an interesting thought, but I'm afraid of you, Whitey. +You ain't afraid of me. +And in your feet, where your brains are, you think maybe you're just a bit faster. +And you know something? +It could be. +Before you break up completely, you mind putting a name on this? +It's just a little old wedge. +But when you put it through the latch of a boxcar, you can't open the door from the inside. +Now, you ask me, who would want to open the door of a boxcar from the inside? +- Jeff Kurth and a dozen gunmen. +- How would you know? +I was sleeping up there when Concho told you. +You better learn how to snore! +You wouldn't know how to shoot a man in the back. +I'll learn. +What'll it be, gents? +We got Old Grandpa, Old Grandma, Old Uncle Tom. +- And Old Empty. +- You ain't funny, Latigo. +Who could be funny, sweating it out in here? +Get away, boy. +You're too young for whiskey even if we had plenty. +Don't get fancy. +You ain't talking to Joey. +Speaking of Joey, you didn't happen to spot him along the trail, did you? +I'll take a shot of that Old Flannelmouth. +- Did you see him? +- No. +Did he leave any sign? +A little. +He was headed toward Junction City. +But you didn't follow him? +Joey always was a nuisance. +I was for dropping him in the river. +- Why didn't you? +- And get my brains shot out? +You've got to find a better reason to kill me. +Suppose Concho didn't catch up with Joey in town and suppose the kid talked? +- He won't talk. +- Maybe not, but Concho ain't back. +Unless he gets back, we won't know where they're carrying the money. +That's right. +Maybe it'd be smart to let this one go through. +Why? +We've grabbed three in a row. +Let's give them a breather. +That makes sense. +I go along with Utica. +You and me both. +We ought to let this one go through. +It ain't going through! +Why not? +You're the one who taught me about payrolls and now I like them. +- So do I. +- I'll buy that. +A man can get saddle-sore looking for a bank to take. +- I'm with Whitey. +- Me too. +What about you, Torgenson? +I got no complaints. +You call it, I'll play it. +Looks like you've been outvoted. +Or do you want a recount? +- Right now, I'd rather have a drink. +- Suit yourself. +If I can't buy a fight, I'll buy a drink. +Fill 'em up. +Sorry, the bar is closed. +On account of we're fresh out of whiskey. +Either get this floor fixed or get a new bartender. +When do we make the hit? +Any time you're ready. +She was halfway up the grade when I left. +Why didn't you tell me? +Why didn't you ask me? +Funny man! +Mount up! +Settle down. +It's only another job. +But if you was boss, we wouldn't do it. +If I was boss we wouldn't do it. +You ain't boss! +# So I bought myself a shovel and I bought myself a pick +# And I laid a little track along the bullfrog crick +# Then I built a locomotive out of 20 empty cans +# And I tooted on the whistle and the darned thing ran +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# Something's gotta take you there and gotta bring you back +# You can't go any distance in a buggy or a hack # +Throw some ropes around them timbers. +We'll pull it down. +Torgenson! +- OK, John. +- Hurry it up, Jubilee! +- Boy, they're pushing her fast today. +- Yeah! +Maybe they heard I needed a quick ten thousand. +- That water tower your idea? +- What's wrong with it? +Any self-respecting Injun could walk away with it. +Funny man! +He knows everything about everything. +Let's get down and lock the barn door. +We've stopped! +Whitey's making his hit! +- McLaine sold us out! +- No, Ben. +They didn't learn it from Grant. +Leary! +- A hold-up! +- They did it again! +Stop your moaning and hold on to your hat! +They won't stop old Tommy Shannon with a tank full of water. +That's no way to treat railroad property, Mr Shannon. +Take your hand off the throttle and reach for the brake! +All right. +Sit down and behave! +Come over here. +Open the safe! +- Ha! +- Move in! +Same as last time! +- We thought you were lost or drunk. +- There ain't nothing in there. +Jubilee! +How are you making out? +Try to talk your way out of this! +- I'm sorry I missed out with Renner. +- Never mind. +Where's the money? +- It's not in the safe. +- Then where is it? +It could be going to Junction City with Jeff's men. +That's not true. +Renner told us Jeff wouldn't carry the payroll! +That's a help. +Least we know who didn't carry it. +Funny man! +When you get through laughing, see what's in that red car. +Sure. +Glad to. +As soon as I pick up my horse. +He's worth more than anything I'm gonna find on this train. +Get those pilgrims out. +Maybe one of them is carrying it. +Hit the other cars! +See if you can find it. +Outside! +All of you! +Is this what you wanted to tell me? +Have a look inside, Latigo! +If that's McLaine... +No, Ben. +Put it away. +You may as well be comfortable. +- Be my guest. +- Gladly. +Do you mind if I ask the name of my host? +No, I don't mind. +Would the payroll be in there? +No. +Why not take a look, just to be sure? +Boy, is this stuff mellow. +Bottled in bond too. +- I forgot. +Ladies is always first. +- Thank you, no. +See for yourself. +Hello, Joey. +What are you doing here? +Getting robbed! +Don't bother. +None of them's got more than two dollars. +Whitey! +There ain't no payroll in there. +How come you missed out? +- I had a little trouble. +- Now, ain't that too bad? +- Maybe I ought to give you a little more. +- Whitey! +Kimball's back there with his wife. +You just got lucky! +Put them back in the car! +Get aboard! +Go on. +Good little boys don't run away. +This time you'll learn! +- Where's the payroll? +- The man says he doesn't know. +I can help him remember. +Take her outside. +Take her outside yourself. +I'm afraid of women. +They scream and scratch, and sometimes step on your toes. +Don't say no to me. +Not when I got a gun in my hand. +I won't. +Unless I'm holding one too. +- Outside. +- If you want the payroll... +You'll have to wait for the next work train. +We decided not to send it through on this one. +Oh? +I don't mind waiting. +I'll be at Pay Load. +You can bring it to me. +Then I'll take 12 hours' start, you get your wife back. +See what happens when you don't carry your brains in your feet? +I ought to make you walk. +Jubilee, lead them out. +Step up with Latigo. +What about Joey? +You gonna leave him here? +He'll ride with me. +Or would you like to? +Settle down. +We're getting $10,000 for the lady, remember? +Which one do I ride with? +Which one do you think? +Take her to the end of track, Mr Shannon! +Here's a stirrup. +Give you a lift? +I'll take that box. +Don't crowd the cantle. +You'll ride easier. +Whoa, mules! +Must have got tired of making the climb and started home. +- Come on, boy! +- Just a minute. +There's a mining town near here. +It used to be called Pay Load. +It's still called Pay Load but nobody lives there. +- It's over beyond that far hill. +- Which hill? +- You see the first hill? +- Yes. +See the second one? +There's a third hill. +Pay Load's behind that. +- How much do you want for this mule? +- $50. +Flap Ears, when you unload this piker, you come on home to mother. +- Get outta there! +- Gah! +Welshing on a bet! +Never could understand them railroad people. +Come on! +Come on! +- Mr Kimball. +- Come over to the telegraph shack. +- Before you pass. +Did you bring the payroll? +- Not now! +- Did you bring it? +- I didn't. +- Now what? +- The end of the railroad. +- Shut up, Feeney. +- Let go of me or I'll push this down your throat! +Who wants your man? +I don't want none of 'em! +They're all broke! +- See you in Denver. +- I'm off to Denver too. +- So am I! +- Nobody goes without orders from Kimball! +- I'm leaving. +- You are not. +You'll take no joyride in this town with them painted hussies. +We've waited this long. +Another night won't hurt us. +But if the money's not here in the morning, out we go! +Get back to work! +We're beat, Mr Kimball. +Without the pay, the gang will go to Junction City. +- I know. +- Any word from Jeff? +He's in Junction City. +Says the car held to the grade all the way. +He and his men will be after Whitey in... +They will not! +Tell him to stay right where he is until further orders. +Yes, sir. +Wonder if he thinks that's private property. +If he tries to divide that like he cuts up the loot, there's gonna be shooting. +- Your laundry? +- Sandwiches. +Do you want one? +No. +Where did you get them? +Junction City. +A girl in a restaurant gave them to me. +- Was she pretty? +- Mm-hm. +- Think you could get me a date? +- She's not that kind of a girl. +Any of you boys win enough to buy a drink? +- You ain't got a drink. +- I got a drink. +- I thought you was fresh out. +- I was till we made the hit. +While you looked for the payroll that wasn't there, I had important business. +Come on, fill her up. +Latigo ought to be running this bunch. +We might not eat, but we'd sure drink. +Ha ha! +You're a funny man. +Why don't you laugh? +- Am I supposed to? +- Not if you're smart. +- I think you're smart. +- And what else do you think? +That you made a mistake. +She'll only bring you trouble and guns. +Since when is $10,000 trouble? +That's exactly what you're worth. +You're very flattering. +But I'm inclined to agree with you. +Don't make a habit of it. +Latigo, I want a drink! +And you've got a few habits I don't like either. +Settle down. +Do you see what she's up to? +I can see you. +And what I see I don't like too good. +- I guess you could use one. +- Thank you, no. +- It's the best. +I got it off your own bar. +- You drink it. +Sorry, lady, I don't drink. +I'm studying to be a bartender. +- Don't you drink? +- Not alone. +Suppose I join you? +- Do you mind? +- And if I do? +Don't push it. +For a little while you're gonna need me and I'm gonna need you. +I watched you walk. +I could swear we've met before. +Could you? +Funny little things you do. +Like when you smile. +Strange. +I seem to recognise all your mannerisms, if you know what that means. +- I know what that means. +- Do you? +I'm supposed to fight Whitey over you. +With a little luck we'd kill each other. +- It's an interesting thought. +- What's interesting? +- She is. +- You're so right. +I may not send you back. +Not until you've helped me spend the ten thousand. +- You mind if we join the party? +- Yes! +You shouldn't, cos if you guess wrong you ain't gonna hang alone. +You like another drink? +- Thanks, I still have this one. +- Drink them both. +Anybody want to start the dance? +With only one girl? +Get back to the bar where you belong. +Let's all get back to the bar, where we belong. +- You almost got your wish. +- One of them. +- The other? +- To know your name. +His name? +He's the Utica Kid. +I don't like it either. +My family used to call me Lee. +Why don't you? +You're supposed to be outside. +Come out with your hands up. +- What are you doing here? +- I want to see the Utica Kid. +- Who are you? +- A friend of his. +Funny thing, he never told me about no girlfriend. +Is there any reason why he should? +- What's your name? +- Charlie Drew. +And you can put that gun away. +Or do I look dangerous? +Not exactly. +Give me that rope. +- When'd you get here? +- Just before they rode in. +Utica pulled the job off right on schedule. +I suppose you've known it was going to happen for quite some time. +No, I haven't. +Utica doesn't talk to me about jobs. +Not this kind. +- Did he ever have any other kind? +- He will have. +Soon. +Then why don't you hold out? +Why don't you keep away till he stops being a thief? +I told him that's what I'd do. +He just looked at me and smiled. +He said, "I wonder if you can." +Tonight he has his answer. +You're here. +Yes, but only to tell him that you're... +Only to tell him I'm in town and might come looking for him. +I want to keep him alive. +I want to keep you alive. +- You know what he can do with a gun. +- I know. +- Well, then, why? +- Because of a little thing called self-respect. +Maybe you wouldn't understand anything about that. +For five years I've played that thing for nickels and dimes thrown into a hat. +For five years the Utica Kid has been laughing. +I may have been wrong, Charlie, but I'm not gonna make the same mistake twice. +Grant... +When you see him will you tell him that I'm here? +Leave it alone! +So all she'll bring is trouble and guns, huh? +Did you bring the money with you? +No. +- How soon do we get it? +- I wouldn't know about that. +You should! +$10,000 is a lot of money. +And that's what he wants for me. +Well, I'd say he was selling out cheap. +Never mind what you'd say. +What did Kimball say? +If you don't know about the money, why did he send you? +He didn't send me. +I came on my own. +Why? +- Ask him. +- Well? +I wouldn't know. +Then again, maybe I would. +You were right the first time. +I can walk quiet at night and I'm a pretty good gun. +I'd like to join up with you. +You see, when a man gets fired off the railroad, he has a little trouble finding a job. +And when he can't find a job, he gets hungry. +I've been hungry for the last five years. +Haven't I? +- How would he know? +- I'm his brother. +- His brother? +- His younger brother. +Five years ago he was a troubleshooter for Kimball. +I lifted the feed herd and he came after me. +Then gave you a horse to get away. +But not until I'd heard all about good and evil. +I didn't buy what he had to sell then. +I'm not buying it now. +- So you don't want him in, huh? +- No. +Funny thing. +I want him in. +- Any objections? +- It ain't that simple, Whitey. +There's a personal deal between me and him. +- About what? +- He got in my way. +That's right. +Oh, yeah, I remember you. +You're the man that fights kids. +Which way do you want it? +Get up, come on, get up! +Now one of you give him his gun. +All right, Harbin, you're the boss around here. +You call it. +I might just do that. +Well, I ain't gonna take him alone. +Then maybe you'd better move along. +Any further objections? +- Yeah. +- Now ain't that wonderful? +- I'd be happy to call it. +- You may get the chance. +You mind if the Utica Kid and me have a little talk? +Not at all. +Call me when you're ready. +I think you ought to know I'm working for the railroad again. +I figured as much. +- Troubleshooter? +- Tonight I was carrying the payroll. +- Where did you hide it? +- I gave it to the boy. +It's in that shoe box. +Now all you have to do is go in and tell Whitey. +You're gambling I won't? +- Same old story of good and evil. +- Same old story. +You lose, Grant. +Yeah, I kind of figured that when you laughed. +I'll give you the same break you gave me. +Ten-minute start, then I tell Whitey I sent you away. +I go, that money goes with me. +So does Kimball's wife. +- No. +- Wait a minute, Lee. +Hear me out on this. +If I leave here, that boy goes with me too. +Joey? +Why do you want him? +Maybe for the good of his soul. +It's been a long time since you heard that word, hasn't it? +Mother and Dad used to bring it up once in a while when we were kids. +You were just about Joey's age. +He thinks a lot of you, doesn't he? +- He wants to grow up to be just like you. +- He may make it, with practice. +Soon he'll be holding the horses while you and Whitey hit a bank. +There's another kid lying in the barn. +He got the start that way too, huh? +- You didn't kill Howdy? +- I didn't hurt him. +- And you're not going to hurt Joey. +- How could I do that? +It's not hard. +It's not hard. +Not when he takes your road. +Or haven't you stopped to look at it? +Why bother? +I picked it, I'll ride it. +Lee, I'm asking you again. +Give Joey a chance. +No. +You've got ten minutes. +I won't need them. +Charlie's in there waiting for you. +Think about her. +She's been following you for five years too. +She's got a reason. +Or didn't I tell you I'm gonna marry her? +How much of that did you hear? +Just what I wanted to hear. +That you're gonna marry me. +When? +We're gonna have a lot of money, Charlie. +$10,000. +You can have pretty new dresses and pretty new shoes. +And a brand-new husband. +- Tomorrow. +- No. +Right now! +If you want me, take me away right now. +Please, please take me. +Why the sudden hurry? +Has my big brother been telling you the story of good and evil? +Don't laugh at him. +Why not? +Why mustn't I laugh at him? +Maybe it would be better if... if you tried to be a little more like him. +Now isn't that just great? +Now I get it from you! +Ever since I was a kid that's all I can remember. +"Why don't you be more like your brother? +Why can't you be more like Grant?" +I don't want to be like him. +I don't want any part of him. +- That's not true. +- Yeah, it's true! +You don't know what it's like to be the kid brother. +Everything you do is wrong. +Everything you try. +Until one day I tried a gun. +Fit my hand real good. +And I wasn't the kid brother any more. +It's a good gun. +It's gonna get us everything we always wanted. +But I don't want it. +Not that way. +Why must you steal? +Because I like to steal. +I like to see what people will do when I take it away from them. +What happens when something is taken away from you? +Nobody's gonna take anything away from me. +Charlie, I'm asking you to marry me. +No. +Grant was right. +You'll never change. +And he calls me a thief? +Joey. +Go on. +Play some more. +It's been a long time since I heard an accordion. +Any tune in particular? +Or would this do? +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# You gotta have an engine and you gotta have a track +# Oh, you can't get far without a railroad +# There are tracks across the prairie +# Where the buzzard builds his nest +# There are tracks across the Rockies +# To the Golden West # +How does it go from there? +How does it go from there, Lee? +Everybody will be neighbours +In this little dream of mine +Take you clear across the country +On the Bullfrog Line +# Oh, you can't get far without a railroad +- # You can't get far without a railroad # +- Gentlemen! +- Renner! +- Didn't you know he was working for me? +- I've come for my thousand dollars. +- What thousand dollars? +Your memory is quite short. +I supplied you with information about a certain boxcar. +I was prepared to supply you with information about the payroll. +- Concho did not keep the appointment. +- So? +So ten per cent of the payroll is mine. +Sorry to disappoint you but we missed the payroll. +Missed the payroll? +In that case I'm prepared to make a better deal. +For $2,000, I can tell you where the money is. +You made a deal. +Ben Kimball hired a man to carry it. +I might never have located this place if I hadn't heard that man's accordion. +He has the money. +Ask him! +Joey! +Come here, Joey! +Grant! +McLaine, there's a woman with you! +- That's right. +- Send her out before we come get you. +Here, hurry! +Come on, Charlie. +He's in the clear. +He's riding away. +Yeah, he's riding. +After me. +- What are we stopping for? +- We're going to the mill, the short way. +Get down to the mill! +Come on! +Take cover! +Here. +There's a mine shaft at the end of these cables. +It runs clear through the mountains. +On the other side, about half a mile, is the railroad! +It's two hours to the end of track. +I have to send you out one at a time. +Come on, Verna. +- Tell Ben he'll get his payroll somehow. +- I'll tell him more than that. +You'll get that money even if you had to kill your own brother? +The next ore bucket that comes down, pull it around and jump in. +I'll cover for you. +It's clear, Charlie. +Get out! +See if you can reach him from over there. +He can't stand them off, not alone. +You figuring to help? +Grant! +Look out! +He's real good. +Only one better gun in Colorado. +Charlie! +Get over here! +- I thought I told you to get out. +- I'm staying right here. +All right. +Now you get back inside and I'll cover for you. +Thanks, Charlie. +Lee, not the kid! +You take care of the kid. +I'll see if I can keep them pinned down. +Would you mind if I play big brother just this one time? +- Shoots high. +- You or the gun? +- Joey all right? +- He's all right. +That makes you a winner. +Go ahead and make a sucker out of the kid. +Tell him all about good and evil. +Put him to work on the railroad. +Things get tough, he can always play the accordion for nickels and dimes. +Sounds like old times, Lee. +Welcome home. +Don't give me that big brother grin. +- Up there! +- Get him! +I count mine. +There's one left. +He hit you hard, Lee. +Not half as hard as you did with that Bullfrog Line. +That was Dad's favourite tune and you know it. +I know it. +You and your stinking accordion! +Charlie. +Charlie? +You and Joey get the horses. +What...? +I'll take care of my brother. +Here's your money. +Pay 'em off, Tim. +Thank you, Grant. +Looks like you won yourself a job. +Mine. +No, it won't fit. +Not nearly as well as your coat. +Want your old job back? +Thanks. +All right, Joey. +Get a bucket and start carrying water. +We're at end of track. +Now go on. +# Sometimes I feel like I could jump over the moon +# And tell the sky above +# Does it matter how full the moon +# When you've an empty heart +# Follow the river +# Wherever you may be +# Follow the river back to me +# Follow the river +# The river knows the way +# Come to me, I pray +# I miss you more each day +# Follow the river +# Wherever you may be +# Follow the river back to me +# Sometimes I feel like I could jump over the moon +# And tell the sky above +# Does it matter how full the moon +# When you've an empty heart +# Bring back the great love +# The love that once we knew +# Make my dreams come true +# The dream I had with you +# Follow the river +# Wherever you may be +# Follow the river back to me +# Follow the river +# Wherever you may be +# Follow the river back to me # +(Man) I'd better get back to work. +Don't lose all your matches. +- Hello, Mac. +- Hi, Click. +Howdy, folks. +- Hi. +- Hello. +Welcome home, man. +Come sit down and give us a tune. +- We'll pay you with promises. +- A man can't eat promises. +He can't lose them at cards either. +McLaine! +- No, indeed he can't. +- Where have you been and why? +They were laying track in Wyoming. +Needed a troubleshooter. +- Didn't need me. +- That's too bad. +You can pick up a few nickels and dimes playing your accordion. +That's right, Tim. +What's this? +Playing cards with matches? +When's payday? +Tomorrow, if they get the money past Whitey Harbin. +Which they won't. +He's tapped that pay train three times up. +They'll get it past him or get no more steel before snow. +- O'Brien, shut your mouth! +- My sentiments exactly. +Day shift and night shift, night shift and day shift. +No money in a month. +My patience is ended. +So is their railroad. +Am I right? +- You are right! +- McLaine. +Please play me a peaceful tune or I'll have a revolution on my hands. +I see what you mean. +Are they giving you trouble? +Lucky you're not with the railroad. +Tis a weary man you'd be today if you were troubleshooting for us. +Could be you're right, Tim. +(# Folk tune) +Come on, pretty lady. +Give us a dance! +I dare you, Mr Feeney. +Where's the wife? +Come on! +Big Ed, are you through to Junction City? +This is for Kimball. +As per your instructions, this is to advise you that Grant McLaine is here at end of track. +You don't need that last. +Just say he's here. +Get away from him! +Get away from him! +Dancing, is it? +Let me... +Get back into your tent where you belong, you painted women. +You and your railroad. +Bringing the likes of this among decent folk. +For two cents I'd take me old man back to Junction City and be through with you. +If you had two cents! +They're at it again. +You can't mix wives and women, even to build a railroad. +Stop this shilly-shally music and give me a jig I can dance to. +Give us a jig, I said. +You watch your feet. +They're heavy. +And so is my fist. +Do I get a jig or do you lose your teeth? +Not now, Mac, not now. +He's not bad. +He's just a fool. +Consider yourself lucky. +Five years ago you'd have got a bullet between the eyes. +I've seen him kill men that could eat you without salt. +Play what you please. +(# Lively jig) +- You asked for a jig, now dance to it! +- Here I go, Feeney! +Hee-hee! +Up Garryowen! +# I was farming in Missouri I was getting tired of that +# So I bought myself a satchel and a stovepipe hat +# And I headed for the station gonna travel all about +# But there wasn't any station and I soon found out +# That you can't get far without a railroad +# You can't get far without a railroad +# Something's gotta take you there and gotta bring you back +# Oh, you can't go any distance in a buggy or a hack +# You can't get far without a railroad +# You can't get far without a railroad +# You gotta have an engine and you gotta have a track +# Oh, you can't get far without a railroad # +I haven't heard that one. +Where does it come from? +Dad used to play it when it got too rough around the house. +Pretty soon us kids would stop fighting and start dancing. +The man makes fine music. +Are we gonna let them use it all up? +Go on with you! +Clarence Feeney, stop looking at them painted hussies and give your wife a dance. +- Go away, woman, I'm tired. +- Tired, is it? +This is my day for dancing or fighting. +Which will you have? +Darling. +Nice work. +I'll give you five dollars tomorrow. +If Whitey lets the pay train through. +Three times is enough. +He won't hit it again. +Oh, don't bet on it. +He's a strange man, this Whitey Harbin. +He's got the big boss plenty worried. +Speaking of Kimball, he wants to see you. +- How would he know where I am? +- I told him. +Here. +You read it. +I'm afraid if I stop the music, Mrs Feeney'll hit me with something. +"Report to me at once in Junction City. +Urgent. +Ben Kimball." +- Maybe he'll give you... +- Another chance? +No. +That's not his way. +- But you will see him? +- Not till they've finished their dance. +- You old hag, I'll... +- Painted hussy! +(Groaning) +Let go of me! +Let go! +Let her go, I said! +(Woman screams) +(Groaning) +(Stops playing) +(Shouting) +(Screaming) +- Hold this. +- Right. +And this is the tune your father used to play to keep peace in the house? +I must have squeezed out a few wrong notes. +Yeah. +- Thanks, Tim. +- Goodbye, Mac. +(Woman screeches) +- Too late for coffee, mister? +- (Woman) Howdy. +I think there's a few warm dregs left. +- Oh. +Howdy, ma'am. +- Step down. +Much obliged. +- They keeping you busy? +- Yep. +Packing out the ore and packing in the vittles. +Them miners can eat more beans than they raise in all of Boston. +- Now they want me to bring in a mill. +- All at once? +No, just a few pieces at a time. +They got tired of waiting for the railroad to reach them. +Between you and me, I don't think it will before snow. +You're hoping it won't? +- First I was. +- Uh-huh. +Figured it'd put me out of business. +It won't. +- It won't? +- No. +It's a funny thing about gold. +There's always some jackass will find it where the railroad ain't. +Then he'll send for me and a few more jackasses to bring in his grub and pack out his ore! +Them crazy miners! +Look at the waste of that good machinery. +Two miles of cable and buckets to go with it. +Last week they up and left the whole thing! +Did the vein pinch out or did they hit low grade? +They didn't hit nothing but blue sky. +Uh-huh. +- This was mighty fine coffee, Mrs... +- Miss Vittles. +Miss Vittles. +I sure appreciate it. +- I got a long ride ahead of me. +- You heading for Junction City too? +Yes, ma'am. +But I'm kind of in a hurry. +I ain't looking for company. +Ten jackasses in a bunch is enough. +- I can save you a trip round the mountain. +- How's that? +Like I told you, the boys hit a good vein, followed it through the mountain. +Last week they busted out on the far side and there wasn't nothing there but blue sky. +Makes a mighty fine short cut into town. +- It sure does. +- Still think I'm crazy? +- I think you're real pretty. +- Ah! +- You going to spend time in these hills? +- Yes, ma'am. +When snow comes you're gonna need a woman. +Or a warm coat, else you'll freeze your knees. +Well, I can't rightly afford a warm coat. +So long, Miss Vittles. +People wonder what a calf feels when he gets roped. +Now you can tell 'em. +What for are you mixing in? +Maybe I don't like to see kids get hurt. +Break any bones, son? +He's got a knife behind his collar! +- There's a stirrup. +You want a lift? +- No. +- Why not? +- I'm beholden to you, mister. +Couldn't we just leave it that way? +- Morning. +- Morning. +- Put him up? +- For how long? +- I wouldn't know. +- It'll be two bits for oats. +- Ain't I seen you before? +- Depends on where you've been. +- I follow the railroad, mostly. +- Could be you've seen me. +- It'll be four bits if he stays the night. +- Fair enough. +Morning. +Did a man ride in today - tall, sort of heavyset? +- You mean him, Mr Renner? +- Not him. +This one had a scar. +Along his cheek? +No, sir. +I don't see no man with a scar. +I guess maybe I can have some apple pie and coffee. +I guess you could have eggs with bacon if you wanted eggs with bacon. +- Hello, Charlie. +- Hello, Grant. +It's good to see you, Charlie. +It's awful good to see you. +It's good to see you too. +- I'll get the eggs. +- No, get the pie. +I can pay for the pie. +You're a very stubborn man. +Apple pie is not for breakfast. +It is if you like apple pie. +Now I need a fork. +- Working here long? +- About three weeks. +How's the Utica Kid? +He was well... when I saw him last. +When was that? +- Good morning. +- Morning. +Well, business is early and Pete is late. +The lunches. +Are they fixed? +Why do I ask? +The lunches are always fixed. +Why? +Because you fix them. +Charlie, I'll make you an omelette like only Pete can make an omelette. +Very bad. +Come on around, sit down, have a cup of coffee. +Pete had that place in Santa Fe, remember? +Are you running a shoe store on the side? +Those are box lunches for the work train. +Money, money, money. +Pete knows how to make it. +He follows the railroad. +I guess a lot of people follow the railroad. +You and Pete. +The Utica Kid. +I asked when you saw him last. +They've lost three payrolls. +Now when did you see him last? +- Charlie, where did I put my apron? +- It's under here. +You must be nice fella. +If Charlie sits with you, you must be nice fella. +I make omelette for you too. +We were talking about the Utica Kid. +He can wait. +Ben Kimball's in town. +They put his car on the siding yesterday. +- I know. +- His wife is with him. +Is she? +I often wondered what Verna was like. +I saw her last night. +All fine silk and feathers. +She's soft and beautiful. +And I can understand now. +Can you? +How long are you gonna be in town? +- That depends on Ben Kimball. +- You working for the railroad again? +- If I am? +- That would be good. +Playing the accordion's not for you, not for a living. +You belong to the railroad and it belongs to you. +There were a lot of things that used to belong to me and somehow I lost them. +(Pete) Two omelettes a-comin' up. +- Do you like eggs? +- No. +That's too bad. +You got an omelette coming up. +Well, somebody's gotta eat them. +Come on. +That means you. +- Could you put it in a box? +- An omelette? +I'll be hungrier when I get to end of track. +Maybe it will go down easy. +Easy or not, it goes down right now. +I can't pay for it. +Then you can help me sell lunches at the station. +Any more arguments? +(Train rattling) +(Train whistle) +(Knocking) +Come in. +- You want to see me, Ben? +- I certainly do. +Hello, Grant. +Sit down. +All right, Jeff. +Renner, go to Pete's and get one breakfast and a jug of coffee. +- You haven't eaten yet? +- I've eaten. +Just get coffee. +Hot. +- How's everything been going? +- I make a living. +- Playing an accordion? +- That's right. +Want me to play a tune for you? +There's other jobs besides railroading. +Well, Colorado may be big in miles. +It's kinda short on people. +So when a man gets fired the way I was fired the story gets around. +Well, I'm... +I'm sorry. +- No, I like to make music. +- And it keeps you near the railroad. +If someone needs information about a payroll, you can sell it. +You know it's a funny thing. +I don't like you either. +- Is that why you sent for me? +- No. +And keep out of this. +Have it your way. +But I don't trust him now any more than I did when I sent him after the Utica Kid. +I sent you after a thief and you gave him a horse to get away on. +- I told you to keep shut. +- Let him talk. +I'm not wearing a gun. +I'll be honest with you. +He'd talk the same if I was. +- It's been nice seeing you. +- (Woman) Grant. +I'm sure Jeff didn't mean to be rude. +Sometimes he has a blunt way of putting things. +Unfortunately, Ben isn't much better. +It's not unfortunate. +It just gets things said in a hurry. +Too much of a hurry. +They forgot to ask you if you'd work for the railroad again. +Would you? +Yes, I would. +Not to give you a short answer. +- It's the answer I wanted. +- Sit down, Grant. +Do you remember Whitey Harbin? +Used to work down in Arizona and New Mexico. +- Yeah. +- Well, he's moved into Colorado. +I thought he favoured stage lines and banks. +So did we. +But he's learned about railroad payrolls +- and he's grabbed three in a row. +- Where do I fit in? +They're making up a supply train in the yard. +I want you to ride it. +- With $10,000 in your pocket. +- Why me? +Quite frankly, because no one would suspect you of carrying a payroll. +I sure don't look like $10,000, do I? +Are you building a bridge you don't need? +The money's here. +Why not bring the men in on Saturday and pay them off in town? +And lose half the crew? +Turn them loose in a mining town, they'll go up the hills looking for gold. +It won't work. +And we have to finish this section before snow comes. +That's a pretty big gamble on a man who gave his horse to a thief! +Yes. +You might as well know the deck's stacked against you. +A boxcar will be hooked to the train. +I'll be one of the men in it. +- When did this happen? +- Last week. +- Renner, did you know? +- Yes. +- Why didn't you tell me? +- I told him not to. +- Why? +- Everything we plan gets back to Whitey. +- You think I'd tell him? +- You might trust the wrong people. +- If he takes the job, I'm sure of it. +- And if I don't take it? +Then Jeff will be sitting in Ben's chair. +Oh, I wouldn't like that. +Uh-uh. +So I'll take the job on one condition. +If I make the delivery I get his job. +You made a deal. +Thank you. +Wait a minute. +It's getting cold up in the hills. +This coat has always been too long for me. +Thanks. +Well. +I thought you didn't like him. +He said that. +I said I didn't trust him. +And I still don't. +(Verna) Grant. +Are you surprised Ben sent for you? +I was until I talked to him. +He seems to have changed. +You're right. +He doesn't belong in a private car with clerks, figures and pressure from the office. +He belongs at the end of track, running a gang and building a railroad. +- He's a working stiff like you. +- Yes, but he can dream a little too. +Colorado wouldn't have a railroad if he hadn't sold them on the idea. +For his sake, I wish he hadn't. +He was happy at end of track but they kicked him upstairs and sent us to Chicago. +- And now he needs a little help. +- That's why he sent for you. +Oh, I may have had something to do with it. +Why? +There was a time when you were interested in me. +I was more than interested in you. +I wanted to marry you. +Times when I'm sorry you didn't. +Aren't you? +No. +A man likes to know his woman will back him when he's down and you didn't. +Ben called me a thief and you went right along with him. +It's as simple as that. +Grant. +For old times' sake. +For old times' sake? +Just that and nothing more? +Perhaps just a little more. +We want to be sure that payroll goes through, don't we? +I don't know. +Maybe Jeff is right. +His type seldom changes. +And if we've made a mistake, it's the finish of everything. +Then why not cut this car into the supply train? +If we're all playing showdown, I'd like to see the cards when they fall. +- Thank you. +I hope you have a nice trip. +- Thank you. +(Train whistle) +- Ma'am, is that all? +- Mm-hm. +- Here's your lunch. +You've earned it. +- Thanks. +- Mister, are you going to end of track? +- Yes. +Could you stake me to a ticket? +I can ride half fare if I'm with an adult. +- And you're an adult. +- Well, sometimes I wonder. +All right. +You can come along. +We'll ride with the other fellas with no money. +- On the flatcar? +- Go on. +Climb aboard. +Plenty of fresh air. +Do you good, make you grow. +(Clunking) +(Train whistle) +Are you sure he didn't come while I was away? +Ain't nobody been here but the man riding the sorrel. +- What colour horse your man riding? +- How should I know? +It's extremely important that I see him. +They've cut in Mr Kimball's car. +Barley! +A man told you to put his horse up... +Don't start that too. +That there sorrel is the only horse what come in. +That there sorrel is the horse I want. +He belongs to my friend Grant McLaine. +McLaine? +That's who it is. +I knew him as a troubleshooter in Santa Fe before he went bad. +- He didn't go bad. +- What'll you do with his horse? +- Ride him! +I'll change, you saddle him. +- All right. +(Train chugging) +(Train whistle) +Hey, Pilgrim! +Come here! +Don't go getting your liver all upset. +- Once you miss 'em, they stay missed. +- It's none of your business. +- Could be. +You wanting to get on that car? +- If I am? +- I can take you to where it's going. +- On one of these? +They'll get you to end of track before the train does. +- That's ridiculous. +- $100 aging yours I'm right. +- You've got a bet. +- And you got stuck. +Here. +I'll let you ride Flap Ears. +- You can smoke inside, mister. +- I can smoke where I want. +You can burn too if it pleases you but it'll still cost you four bits. +- For what? +- Travelling first-class. +Otherwise ride the flats. +(Discordant notes) +- You play that? +- Yeah, I play it. +- When? +- When? +Whenever somebody throws a dime in my hat. +- I ain't got a dime. +- This one's on me. +(# Folk tune) +- Been up here before? +- Part way. +- What takes you to end of track? +- A job. +Figured I'd get one at Junction City. +They told me the foremen do the hiring. +You're a little small for swinging a sledge. +- I can carry water. +- Yeah, you can carry water. +- Very important job. +- (Man) Hey! +- What are you doing here? +- He's with me, Pick. +- Where did you get him? +- Somebody threw him away. +Don't you throw him away. +He'll get lost in the mountains. +Who tells the men who build railroads how to get through the mountains? +- The river. +- Huh? +They just follow the river. +- Who told you that? +- I guess my dad was the first. +He had a little song about it. +# Follow the river +# The river knows the way +# Hearts can go astray +# It happens every day +# Follow the river +# Wherever you may be +# Follow the river back to me # +Wouldn't you wanna be knowing about Concho? +- Who's Concho? +- The man you roped. +Do you wanna know? +Not unless you wanna tell me. +I ought to tell you. +He's fast with a gun. +Only know two men who are faster. +Which two men would they be? +Whitey Harbin for one. +I run away from Whitey. +That's why Concho was after me. +You're one of Whitey's men? +No. +I was in Montrose. +Whitey and his bunch were robbing a bank. +I was just in the road watching. +Whitey was all for killing me but the other fellow wouldn't let him. +He swung me up into the saddle and said, +"You ain't killing a kid. +Not while I ride with you." +- Whitey, he backed down. +- Cos the fella's faster with a gun? +Like lightning. +This other fella, does he have a name? +He's got a name. +The Utica Kid. +I'd have stayed with the bunch if he was boss. +- But he's not? +- Not yet. +Always he's shoving pins into Whitey, laughing at him, driving him crazy. +Even crazier than he is! +Someday Whitey will crack and he'll lose. +(Train whistle) +Is this the fresh air you were talking about? +How come them fellas can ride inside? +Well, it's the old story of good and evil. +If you spend all your money on whiskey, you have none left for a ticket. +Don't drink. +Then you'd have six bits when you need it. +That's very true. +Tell you what, maybe I have six bits. +Yeah. +What do you say we go in and spend it? +Come on. +Guess I wasn't tough enough to follow the river that way. +Sometimes it isn't easy travelling upstream. +- That will be a dollar. +- That'll be six bits. +I'm the adult. +Here. +Hold on to that. +- Don't worry about Concho. +- You would if... +Oh, no, come on. +Sit down. +We can both worry together if you want to tell me about it. +- It's nothing. +- And if it was, you'd rather not say. +All right. +I broke with Whitey. +Doesn't mean I have to talk. +No, you don't have to talk. +I even broke with the Utica Kid. +- Hi, Utica. +- Put him away, Howdy. +Sure. +Come on. +It's a pretty good rig. +Too good for the guy that owned it. +Remember that draw you taught me? +It worked. +He went down with his gun in the leather. +- And now you're an "in case" man. +- In case? +Yeah. +In case you miss six times with one, you draw the other. +- If you have time. +- I'll have time. +Call it. +Draw! +You better learn to draw that one before you fool around with the other. +(Clanking) +(Horse whinnies) +About three inches high, Whitey. +You better take another look at that skull. +Next time it could be yours. +Don't soft-foot up behind me! +It makes me nervous! +So I notice. +What else did you notice? +Did you see Concho? +- Did you see him? +- He wasn't on the trail. +Did I ask you where he wasn't? +I asked you did you see him? +- I would've said so. +- Not straight out you wouldn't. +Because you're a funny man. +You've always gotta be laughing inside. +Well, go ahead, laugh. +But get this, Kid. +I'm a better gun than you. +Or would you like to try? +It's an interesting thought, but I'm afraid of you, Whitey. +(Laughs) You ain't afraid of me. +And in your feet, where your brains are, you think maybe you're just a bit faster. +And you know something? +(Laughs) It could be. +Before you break up completely, you mind putting a name on this? +It's just a little old wedge. +But when you put it through the latch of a boxcar, you can't open the door from the inside. +Now, you ask me, who would want to open the door of a boxcar from the inside? +- Jeff Kurth and a dozen gunmen. +- How would you know? +I was sleeping up there when Concho told you. +You better learn how to snore! +You wouldn't know how to shoot a man in the back. +I'll learn. +What'll it be, gents? +We got Old Grandpa, Old Grandma, Old Uncle Tom. +- And Old Empty. +- You ain't funny, Latigo. +Who could be funny, sweating it out in here? +Get away, boy. +You're too young for whiskey even if we had plenty. +Don't get fancy. +You ain't talking to Joey. +Speaking of Joey, you didn't happen to spot him along the trail, did you? +I'll take a shot of that Old Flannelmouth. +- Did you see him? +- No. +Did he leave any sign? +A little. +He was headed toward Junction City. +But you didn't follow him? +Joey always was a nuisance. +I was for dropping him in the river. +- Why didn't you? +- And get my brains shot out? +You've got to find a better reason to kill me. +Suppose Concho didn't catch up with Joey in town and suppose the kid talked? +- He won't talk. +- Maybe not, but Concho ain't back. +Unless he gets back, we won't know where they're carrying the money. +That's right. +Maybe it'd be smart to let this one go through. +Why? +We've grabbed three in a row. +Let's give them a breather. +That makes sense. +I go along with Utica. +You and me both. +We ought to let this one go through. +It ain't going through! +Why not? +You're the one who taught me about payrolls and now I like them. +- So do I. +- I'll buy that. +A man can get saddle-sore looking for a bank to take. +- I'm with Whitey. +- Me too. +What about you, Torgenson? +I got no complaints. +You call it, I'll play it. +Looks like you've been outvoted. +Or do you want a recount? +- Right now, I'd rather have a drink. +- Suit yourself. +If I can't buy a fight, I'll buy a drink. +Fill 'em up. +Sorry, the bar is closed. +On account of we're fresh out of whiskey. +Either get this floor fixed or get a new bartender. +When do we make the hit? +Any time you're ready. +She was halfway up the grade when I left. +Why didn't you tell me? +Why didn't you ask me? +Funny man! +Mount up! +Settle down. +It's only another job. +But if you was boss, we wouldn't do it. +If I was boss we wouldn't do it. +You ain't boss! +# So I bought myself a shovel and I bought myself a pick +# And I laid a little track along the bullfrog crick +# Then I built a locomotive out of 20 empty cans +# And I tooted on the whistle and the darned thing ran +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# Something's gotta take you there and gotta bring you back +# You can't go any distance in a buggy or a hack # +(Train whistle) +Throw some ropes around them timbers. +We'll pull it down. +Torgenson! +- OK, John. +- Hurry it up, Jubilee! +- Boy, they're pushing her fast today. +- Yeah! +Maybe they heard I needed a quick ten thousand. +- That water tower your idea? +- What's wrong with it? +Any self-respecting Injun could walk away with it. +Funny man! +He knows everything about everything. +Let's get down and lock the barn door. +- (Neighing) +- We've stopped! +Whitey's making his hit! +- McLaine sold us out! +- No, Ben. +They didn't learn it from Grant. +Leary! +- A hold-up! +- They did it again! +Stop your moaning and hold on to your hat! +They won't stop old Tommy Shannon with a tank full of water. +That's no way to treat railroad property, Mr Shannon. +Take your hand off the throttle and reach for the brake! +All right. +Sit down and behave! +Come over here. +Open the safe! +- Ha! +- Move in! +Same as last time! +- We thought you were lost or drunk. +- There ain't nothing in there. +(Man) Jubilee! +How are you making out? +Try to talk your way out of this! +- I'm sorry I missed out with Renner. +- Never mind. +Where's the money? +- It's not in the safe. +- Then where is it? +It could be going to Junction City with Jeff's men. +That's not true. +Renner told us Jeff wouldn't carry the payroll! +That's a help. +Least we know who didn't carry it. +Funny man! +When you get through laughing, see what's in that red car. +Sure. +Glad to. +As soon as I pick up my horse. +He's worth more than anything I'm gonna find on this train. +Get those pilgrims out. +Maybe one of them is carrying it. +Hit the other cars! +See if you can find it. +Outside! +All of you! +Is this what you wanted to tell me? +Have a look inside, Latigo! +If that's McLaine... +No, Ben. +Put it away. +You may as well be comfortable. +- Be my guest. +- Gladly. +Do you mind if I ask the name of my host? +No, I don't mind. +Would the payroll be in there? +No. +Why not take a look, just to be sure? +Boy, is this stuff mellow. +Bottled in bond too. +- I forgot. +Ladies is always first. +- Thank you, no. +See for yourself. +Hello, Joey. +What are you doing here? +Getting robbed! +Don't bother. +None of them's got more than two dollars. +Whitey! +There ain't no payroll in there. +How come you missed out? +- I had a little trouble. +- Now, ain't that too bad? +- Maybe I ought to give you a little more. +- Whitey! +Kimball's back there with his wife. +(Laughs) +You just got lucky! +Put them back in the car! +(Concho) Get aboard! +Go on. +Good little boys don't run away. +This time you'll learn! +- Where's the payroll? +- The man says he doesn't know. +I can help him remember. +Take her outside. +Take her outside yourself. +I'm afraid of women. +They scream and scratch, and sometimes step on your toes. +Don't say no to me. +Not when I got a gun in my hand. +I won't. +Unless I'm holding one too. +- Outside. +- If you want the payroll... +You'll have to wait for the next work train. +We decided not to send it through on this one. +Oh? +I don't mind waiting. +I'll be at Pay Load. +You can bring it to me. +Then I'll take 12 hours' start, you get your wife back. +See what happens when you don't carry your brains in your feet? +I ought to make you walk. +Jubilee, lead them out. +Step up with Latigo. +(Concho) What about Joey? +You gonna leave him here? +He'll ride with me. +Or would you like to? +Settle down. +We're getting $10,000 for the lady, remember? +Which one do I ride with? +(Laughs) Which one do you think? +Take her to the end of track, Mr Shannon! +(Train whistle) +Here's a stirrup. +Give you a lift? +I'll take that box. +Don't crowd the cantle. +You'll ride easier. +Whoa, mules! +Must have got tired of making the climb and started home. +- Come on, boy! +- Just a minute. +There's a mining town near here. +It used to be called Pay Load. +It's still called Pay Load but nobody lives there. +- It's over beyond that far hill. +- Which hill? +- You see the first hill? +- Yes. +See the second one? +There's a third hill. +Pay Load's behind that. +- How much do you want for this mule? +- $50. +Flap Ears, when you unload this piker, you come on home to mother. +- Get outta there! +- Gah! +Welshing on a bet! +Never could understand them railroad people. +Come on! +Come on! +(Train whistle) +- Mr Kimball. +- Come over to the telegraph shack. +- Before you pass. +Did you bring the payroll? +- Not now! +- Did you bring it? +- I didn't. +- Now what? +- The end of the railroad. +- Shut up, Feeney. +- Let go of me or I'll push this down your throat! +Who wants your man? +I don't want none of 'em! +They're all broke! +- See you in Denver. +- I'm off to Denver too. +- So am I! +- Nobody goes without orders from Kimball! +- I'm leaving. +- You are not. +You'll take no joyride in this town with them painted hussies. +We've waited this long. +Another night won't hurt us. +But if the money's not here in the morning, out we go! +Get back to work! +(Clicking) +We're beat, Mr Kimball. +Without the pay, the gang will go to Junction City. +- I know. +- Any word from Jeff? +He's in Junction City. +Says the car held to the grade all the way. +He and his men will be after Whitey in... +They will not! +Tell him to stay right where he is until further orders. +Yes, sir. +Wonder if he thinks that's private property. +If he tries to divide that like he cuts up the loot, there's gonna be shooting. +- Your laundry? +- Sandwiches. +Do you want one? +No. +Where did you get them? +Junction City. +A girl in a restaurant gave them to me. +- Was she pretty? +- Mm-hm. +- Think you could get me a date? +- She's not that kind of a girl. +Any of you boys win enough to buy a drink? +- You ain't got a drink. +- I got a drink. +(Clamouring) +- I thought you was fresh out. +- I was till we made the hit. +While you looked for the payroll that wasn't there, I had important business. +(Man) Come on, fill her up. +Latigo ought to be running this bunch. +We might not eat, but we'd sure drink. +Ha ha! +You're a funny man. +Why don't you laugh? +- Am I supposed to? +- Not if you're smart. +- I think you're smart. +- And what else do you think? +That you made a mistake. +She'll only bring you trouble and guns. +Since when is $10,000 trouble? +That's exactly what you're worth. +You're very flattering. +But I'm inclined to agree with you. +Don't make a habit of it. +Latigo, I want a drink! +And you've got a few habits I don't like either. +Settle down. +Do you see what she's up to? +I can see you. +And what I see I don't like too good. +- I guess you could use one. +- Thank you, no. +- It's the best. +I got it off your own bar. +- You drink it. +Sorry, lady, I don't drink. +I'm studying to be a bartender. +- Don't you drink? +- Not alone. +Suppose I join you? +- Do you mind? +- And if I do? +Don't push it. +For a little while you're gonna need me and I'm gonna need you. +I watched you walk. +I could swear we've met before. +Could you? +Funny little things you do. +Like when you smile. +Strange. +I seem to recognise all your mannerisms, if you know what that means. +- I know what that means. +- Do you? +I'm supposed to fight Whitey over you. +With a little luck we'd kill each other. +- It's an interesting thought. +- What's interesting? +- She is. +- You're so right. (Laughs) +I may not send you back. +Not until you've helped me spend the ten thousand. +- You mind if we join the party? +- Yes! +You shouldn't, cos if you guess wrong you ain't gonna hang alone. +You like another drink? +- Thanks, I still have this one. +- Drink them both. +Anybody want to start the dance? +With only one girl? +Get back to the bar where you belong. +Let's all get back to the bar, where we belong. +- You almost got your wish. +- One of them. +- The other? +- To know your name. +His name? +He's the Utica Kid. +I don't like it either. +My family used to call me Lee. +Why don't you? +You're supposed to be outside. +(Horse whinnies) +Come out with your hands up. +- What are you doing here? +- I want to see the Utica Kid. +- Who are you? +- A friend of his. +Funny thing, he never told me about no girlfriend. +(Charlie) Is there any reason why he should? +- What's your name? +- Charlie Drew. +And you can put that gun away. +Or do I look dangerous? +Not exactly. +(Charlie yelps) +Give me that rope. +- When'd you get here? +- Just before they rode in. +Utica pulled the job off right on schedule. +I suppose you've known it was going to happen for quite some time. +No, I haven't. +Utica doesn't talk to me about jobs. +Not this kind. +- Did he ever have any other kind? +- He will have. +Soon. +Then why don't you hold out? +Why don't you keep away till he stops being a thief? +I told him that's what I'd do. +He just looked at me and smiled. +He said, "I wonder if you can." +Tonight he has his answer. +You're here. +Yes, but only to tell him that you're... +Only to tell him I'm in town and might come looking for him. +I want to keep him alive. +I want to keep you alive. +- You know what he can do with a gun. +- I know. +- Well, then, why? +- Because of a little thing called self-respect. +Maybe you wouldn't understand anything about that. +For five years I've played that thing for nickels and dimes thrown into a hat. +For five years the Utica Kid has been laughing. +I may have been wrong, Charlie, but I'm not gonna make the same mistake twice. +Grant... +When you see him will you tell him that I'm here? +Leave it alone! +So all she'll bring is trouble and guns, huh? +Did you bring the money with you? +No. +- How soon do we get it? +- I wouldn't know about that. +You should! +$10,000 is a lot of money. +And that's what he wants for me. +Well, I'd say he was selling out cheap. +Never mind what you'd say. +What did Kimball say? +If you don't know about the money, why did he send you? +He didn't send me. +I came on my own. +Why? +- Ask him. +- Well? +I wouldn't know. +Then again, maybe I would. +You were right the first time. +I can walk quiet at night and I'm a pretty good gun. +I'd like to join up with you. +You see, when a man gets fired off the railroad, he has a little trouble finding a job. +And when he can't find a job, he gets hungry. +I've been hungry for the last five years. +Haven't I? +- (Whitey) How would he know? +- I'm his brother. +- His brother? +- His younger brother. +Five years ago he was a troubleshooter for Kimball. +I lifted the feed herd and he came after me. +Then gave you a horse to get away. +But not until I'd heard all about good and evil. +I didn't buy what he had to sell then. +I'm not buying it now. +- (Whitey) So you don't want him in, huh? +- No. +Funny thing. +I want him in. +- Any objections? +- It ain't that simple, Whitey. +There's a personal deal between me and him. +- About what? +- He got in my way. +That's right. +Oh, yeah, I remember you. +You're the man that fights kids. +Which way do you want it? +Get up, come on, get up! +Now one of you give him his gun. +All right, Harbin, you're the boss around here. +You call it. +I might just do that. +Well, I ain't gonna take him alone. +Then maybe you'd better move along. +Any further objections? +- Yeah. +- (Whitey) Now ain't that wonderful? +- I'd be happy to call it. +- You may get the chance. +You mind if the Utica Kid and me have a little talk? +Not at all. +Call me when you're ready. +I think you ought to know I'm working for the railroad again. +I figured as much. +- Troubleshooter? +- Tonight I was carrying the payroll. +- Where did you hide it? +- I gave it to the boy. +It's in that shoe box. +(Laughs) +Now all you have to do is go in and tell Whitey. +You're gambling I won't? +- Same old story of good and evil. +- Same old story. +You lose, Grant. +Yeah, I kind of figured that when you laughed. +I'll give you the same break you gave me. +Ten-minute start, then I tell Whitey I sent you away. +I go, that money goes with me. +So does Kimball's wife. +- No. +- Wait a minute, Lee. +Hear me out on this. +If I leave here, that boy goes with me too. +Joey? +Why do you want him? +Maybe for the good of his soul. +It's been a long time since you heard that word, hasn't it? +Mother and Dad used to bring it up once in a while when we were kids. +You were just about Joey's age. +He thinks a lot of you, doesn't he? +- He wants to grow up to be just like you. +- He may make it, with practice. +Soon he'll be holding the horses while you and Whitey hit a bank. +There's another kid lying in the barn. +He got the start that way too, huh? +- You didn't kill Howdy? +- I didn't hurt him. +- And you're not going to hurt Joey. +- How could I do that? +It's not hard. +It's not hard. +Not when he takes your road. +Or haven't you stopped to look at it? +Why bother? +I picked it, I'll ride it. +Lee, I'm asking you again. +Give Joey a chance. +No. +You've got ten minutes. +I won't need them. +Charlie's in there waiting for you. +Think about her. +She's been following you for five years too. +She's got a reason. +Or didn't I tell you I'm gonna marry her? +How much of that did you hear? +Just what I wanted to hear. +That you're gonna marry me. +When? +We're gonna have a lot of money, Charlie. +$10,000. +You can have pretty new dresses and pretty new shoes. +And a brand-new husband. +- Tomorrow. +- No. +Right now! +If you want me, take me away right now. +Please, please take me. +Why the sudden hurry? +Has my big brother been telling you the story of good and evil? +Don't laugh at him. +Why not? +Why mustn't I laugh at him? +Maybe it would be better if... if you tried to be a little more like him. +Now isn't that just great? +Now I get it from you! +Ever since I was a kid that's all I can remember. +"Why don't you be more like your brother? +Why can't you be more like Grant?" +I don't want to be like him. +I don't want any part of him. +- That's not true. +- Yeah, it's true! +You don't know what it's like to be the kid brother. +Everything you do is wrong. +Everything you try. +Until one day I tried a gun. +Fit my hand real good. +And I wasn't the kid brother any more. +It's a good gun. +It's gonna get us everything we always wanted. +But I don't want it. +Not that way. +Why must you steal? +Because I like to steal. +I like to see what people will do when I take it away from them. +What happens when something is taken away from you? +Nobody's gonna take anything away from me. +Charlie, I'm asking you to marry me. +No. +Grant was right. +You'll never change. +And he calls me a thief? +Joey. +Go on. +Play some more. +It's been a long time since I heard an accordion. +Any tune in particular? +Or would this do? +(# You Can't Get Far Without A Railroad) +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# You gotta have an engine and you gotta have a track +# Oh, you can't get far without a railroad +# There are tracks across the prairie +# Where the buzzard builds his nest +# There are tracks across the Rockies +# To the Golden West # +How does it go from there? +How does it go from there, Lee? +Everybody will be neighbours +In this little dream of mine +Take you clear across the country +On the Bullfrog Line +# Oh, you can't get far without a railroad +- # You can't get far without a railroad # +- Gentlemen! +- Renner! +- Didn't you know he was working for me? +- I've come for my thousand dollars. +- What thousand dollars? +Your memory is quite short. +I supplied you with information about a certain boxcar. +I was prepared to supply you with information about the payroll. +- Concho did not keep the appointment. +- So? +So ten per cent of the payroll is mine. +Sorry to disappoint you but we missed the payroll. +Missed the payroll? +In that case I'm prepared to make a better deal. +For $2,000, I can tell you where the money is. +You made a deal. +Ben Kimball hired a man to carry it. +I might never have located this place if I hadn't heard that man's accordion. +He has the money. +Ask him! +Joey! +Come here, Joey! +(Verna) Grant! +(Whitey) McLaine, there's a woman with you! +- That's right. +- Send her out before we come get you. +Here, hurry! +Come on, Charlie. +He's in the clear. +He's riding away. +Yeah, he's riding. +After me. +- (Man) What are we stopping for? +- We're going to the mill, the short way. +Get down to the mill! +Come on! +Take cover! +Here. +There's a mine shaft at the end of these cables. +It runs clear through the mountains. +On the other side, about half a mile, is the railroad! +It's two hours to the end of track. +I have to send you out one at a time. +Come on, Verna. +- Tell Ben he'll get his payroll somehow. +- I'll tell him more than that. +You'll get that money even if you had to kill your own brother? +The next ore bucket that comes down, pull it around and jump in. +I'll cover for you. +It's clear, Charlie. +Get out! +See if you can reach him from over there. +He can't stand them off, not alone. +You figuring to help? +Grant! +Look out! +He's real good. +Only one better gun in Colorado. +Charlie! +Get over here! +- I thought I told you to get out. +- I'm staying right here. +All right. +Now you get back inside and I'll cover for you. +Thanks, Charlie. +Lee, not the kid! +You take care of the kid. +I'll see if I can keep them pinned down. +Would you mind if I play big brother just this one time? +- Shoots high. +- You or the gun? +- Joey all right? +- He's all right. +That makes you a winner. +Go ahead and make a sucker out of the kid. +Tell him all about good and evil. +Put him to work on the railroad. +Things get tough, he can always play the accordion for nickels and dimes. +Sounds like old times, Lee. +Welcome home. +Don't give me that big brother grin. +- Up there! +- Get him! +(Clicks) +I count mine. +There's one left. +He hit you hard, Lee. +Not half as hard as you did with that Bullfrog Line. +That was Dad's favourite tune and you know it. +I know it. +You and your stinking accordion! +Charlie. +Charlie? +You and Joey get the horses. +What...? +I'll take care of my brother. +(Train whistle) +Here's your money. +Pay 'em off, Tim. +Thank you, Grant. +Looks like you won yourself a job. +Mine. +No, it won't fit. +Not nearly as well as your coat. +Want your old job back? +Thanks. +All right, Joey. +Get a bucket and start carrying water. +We're at end of track. +Now go on. +# Sometimes I feel like I could jump over the moon +# And tell the sky above +# Does it matter how full the moon +# When you've an empty heart +# Follow the river +# Wherever you may be +# Follow the river back to me +♪ Follow the river ♪ +♪ The river knows the way ♪ +♪ Come to me, I pray ♪ +♪ I miss you more each day ♪ +♪ Follow the river ♪ +♪ Wherever you may be ♪ +♪ Follow the river back to me ♪ +♪ Sometimes I feel like ♪ +♪ I could jump over the moon ♪ +♪ And tell the sky above ♪ +♪ Does it matter how full the moon ♪ +♪ When you've an empty heart ♪ +♪ Bring back the great love ♪ +♪ The love that once we knew ♪ +♪ Make my dreams come true ♪ +♪ The dream I had with you ♪ +♪ Follow the river ♪ +♪ Wherever you may be ♪ +♪ Follow the river back to me ♪ +♪ Follow the river ♪ +♪ Wherever you may be ♪ +♪ Follow the river back to me ♪ +I'd better get back to work. +Don't lose all your matches. +- Hello, Mac. +- Hi, Click. +Howdy, folks. +- Hi. +- Hello. +Welcome home, man. +Come sit down and give us a tune. +- We'll pay you with promises. +- A man can't eat promises. +He can't lose them at cards either. +McLaine! +- No, indeed he can't. +- Where have you been and why? +They were laying track in Wyoming. +Needed a troubleshooter. +- Didn't need me. +- That's too bad. +You can pick up a few nickels and dimes playing your accordion. +That's right, Tim. +What's this? +Playing cards with matches? +When's payday? +Tomorrow, if they get the money past Whitey Harbin. +Which they won't. +He's tapped that pay train three times up. +They'll get it past him or get no more steel before snow. +- O'Brien, shut your mouth! +- My sentiments exactly. +Day shift and night shift, night shift and day shift. +No money in a month. +My patience is ended. +So is their rail road. +Am I right? +- You are right! +- McLaine. +Please play me a peaceful tune or I'll have a revolution on my hands. +I see what you mean. +Are they giving you trouble? +Lucky you're not with the rail road. +Tis a weary man you'd be today if you were troubleshooting for us. +Could be you're right, Tim. +Come on, pretty lady. +Give us a dance! +I dare you, Mr Feeney. +Where's the wife? +Come on! +Big Ed, are you through to Junction City? +This is for Kimball. +As per your instructions, this is to advise you that Grant McLaine is here at end of track. +You don't need that last. +Just say he's here. +Get away from him! +Get away from him! +Dancing, is it? +Let me... +Get back into your tent where you belong, you painted women. +You and your rail road. +Bringing the likes of this among decent folk. +For two cents I'd take me old man back to Junction City and be through with you. +If you had two cents! +They're at it again. +You can't mix wives and women, even to build a rail road. +Stop this shilly-shally music and give me a jig I can dance to. +Give us a jig, I said. +You watch your feet. +They're heavy. +And so is my fist. +Do I get a jig or do you lose your teeth? +Not now, Mac, not now. +He's not bad. +He's just a fool. +Consider yourself lucky. +Five years ago you'd have got a bullet between the eyes. +I've seen him kill men that could eat you without salt. +Play what you please. +- You asked for a jig, now dance to it! +- Here I go, Feeney! +Hee-hee! +UP Garryowen! +♪ I was farming in Missouri ♪ +I was getting tired of that ♪ +♪ So I bought myself a satchel ♪ +♪ and a stovepipe hat ♪ +♪ And I headed for the station ♪ +♪ gonna travel all about ♪ +♪ But there wasn't any station ♪ +♪ and I soon found out +♪ That you can't get far without a rail road ♪ +♪ You can't get far without a rail road ♪ +♪ Something's gotta take you there ♪ +♪ and gotta bring you back ♪ +♪ Oh, you can't go any distance ♪ +♪ in a buggy or a hack +♪ You can't get far without a rail road ♪ +♪ You can't get far without a rail road ♪ +♪ You gotta have an engine ♪ +♪ and you gotta have a track ♪ +♪ Oh, you can't get far without a rail road ♪ +I haven't heard that one. +Where does it come from? +Dad used to play it when it got too rough around the house. +Pretty soon us kids would stop fighting and start dancing. +The man makes fine music. +Are we gonna let them use it all up? +Go on with you! +Clarence Feeney, stop looking at them painted hussies and give your wife a dance. +- Go away, woman, I'm tired. +- Tired, is it? +This is my day for dancing or fighting. +Which will you have? +Darling. +Nice work. +I'll give you five dollars tomorrow. +If Whitey lets the pay train through. +Three times is enough. +He won't hit it again. +Oh, don't bet on it. +He's a strange man, this Whitey Harbin. +He's got the big boss plenty worried. +Speaking of Kimball, he wants to see you. +- How would he know where I am? +- I told him. +Here. +You read it. +I'm afraid if I stop the music, +Mrs Feeney'll hit me with something. +"Report to me at once in Junction City. +Urgent. +Ben Kimball." +- Maybe he'll give you... +- Another chance? +No. +That's not his way. +- But you will see him? +- Not till they've finished their dance. +- You old hag, I'll... +- Painted hussy! +Let go of me! +Let go! +Let her go, I said! +- Hold this. +- Right. +And this is the tune your father used to play to keep peace in the house? +I must have squeezed out a few wrong notes. +Yeah. +- Thanks, Tim. +- Goodbye, Mac. +- Too late for coffee, mister? +- Howdy. +I think there's a few warm dregs left. +- Oh. +Howdy, ma'am. +- Step down. +Much obliged. +- They keeping you busy? +- Yep. +Packing out the ore and packing in the vittles. +Them miners can eat more beans than they raise in all of Boston. +- Now they want me to bring in a mill. +- All at once? +No, just a few pieces at a time. +They got tired of waiting for the rail road to reach them. +Between you and me, I don't think it will before snow. +You're hoping it won't? +First I was. +Figured it'd put me out of business. +It won't. +- It won't? +- No. +It's a funny thing about gold. +There's always some jackass will find it where the rail road ain't. +Then he'll send for me and a few more jackasses to bring in his grub and pack out his ore! +Them crazy miners! +Look at the waste of that good machinery. +Two miles of cable and buckets to go with it. +Last week they up and left the whole thing! +Did the vein pinch out or did they hit low grade? +They didn't hit nothing but blue sky. +- This was mighty fine coffee, Mrs... +- Miss Vittles. +Miss Vittles. +I sure appreciate it. +- I got a long ride ahead of me. +- You heading for Junction City too? +Yes, ma'am. +But I'm kind of in a hurry. +I ain't looking for company. +Ten jackasses in a bunch is enough. +- I can save you a trip round the mountain. +- How's that? +Like I told you, the boys hit a good vein, followed it through the mountain. +Last week they busted out on the far side and there wasn't nothing there but blue sky. +Makes a mighty fine shod cut into town. +- It sure does. +- Still think I'm crazy? +I think you're real pretty. +- You going to spend time in these hills? +- Yes, ma'am. +When snow comes you're gonna need a woman. +Or a warm coat, else you'll freeze your knees. +Well, I can't rightly afford a warm coat. +So long, Miss Vittles. +People wonder what a calf feels when he gets roped. +Now you can tell 'em. +What for are you mixing in? +Maybe I don't like to see kids get hurt Break any bones, son? +He's got a knife behind his collar! +- There's a stirrup. +You want a lift? +- No. +- Why not? +- I'm beholden to you, mister. +Couldn't we just leave it that way? +- Morning. +- Morning. +- Put him up? +- For how long? +- I wouldn't know. +- It'll be two bits for oats. +- Ain't I seen you before? +- Depends on where you've been. +- I follow the rail road, mostly. +- Could be you've seen me. +- It'll be four bits if he stays the night. +- Fair enough. +Morning. +Did a man ride in today - tall, son of heavyset? +- You mean him, Mr Renner? +- Not him. +This one had a scar. +Along his cheek? +No, sir. +I don't see no man with a scar. +I guess maybe I can have some apple pie and coffee. +I guess you could have eggs with bacon if you wanted eggs with bacon. +- Hello, Charlie. +- Hello, Grant. +It's good to see you, Charlie. +It's awful good to see you. +It's good to see you too. +- I'll get the eggs. +- No, get the pie. +I can pay for the pie. +You're a very stubborn man. +Apple pie is not for breakfast. +It is if you like apple pie. +Now I need a fork. +- Working here long? +- About three weeks. +How's the Utica Kid? +He was well... when I saw him last. +When was that? +- Good morning. +- Morning. +Well, business is early and Pete is late. +The lunches. +Are they fixed? +Why do I ask? +The lunches are always fixed. +Why? +Because you fix them. +Charlie, I'll make you an omelette like only Pete can make an omelette. +Very bad. +Come on around, sit down, have a cup of coffee. +Pete had that place in Santa Fe, remember? +Are you running a shoe store on the side? +Those are box lunches for the work train. +Money, money, money. +Pete knows how to make it. +He follows the rail road. +I guess a lot of people follow the rail road. +You and Pete. +The Utica Kid. +I asked when you saw him last. +They've lost three payrolls. +Now when did you see him last? +- Charlie, where did I put my apron? +- It's under here. +You must be nice fella. +If Charlie sits with you, you must be nice fella. +I make omelette for you too. +We were talking about the Utica Kid. +He can wait. +Ben Kimball's in town. +They put his car on the siding yesterday. +- I know. +- His wife is with him. +Is she? +I often wondered what Verna was like. +I saw her last night. +All fine silk and feathers. +She's soft and beautiful. +And I can understand now. +Can you? +How long are you gonna be in town? +- That depends on Ben Kimball. +- You working for the rail road again? +- if I am? +- That would be good. +Playing the accordion's not for you, not for a living. +You belong to the rail road and it belongs to you. +There were a lot of things that used to belong to me and somehow I lost them. +Two omelettes a-comin' up. +- Do you like eggs? +- No. +That's too bad. +You got an omelette coming up. +Well, somebody's gotta eat them. +Come on. +That means you. +- Could you put it in a box? +- An omelette? +I'll be hungrier when I get to end of track. +Maybe it will go down easy. +Easy or not, it goes down right now. +I can't pay for it. +Then you can help me sell lunches at the station. +Any more arguments? +Come in. +- You want to see me, Ben? +- I certainly do. +Hello, Grant. +Sit down. +All right, Jeff. +Renner, go to Pete's and get one breakfast and a jug of coffee. +- You haven't eaten yet? +- I've eaten. +Just get coffee. +Hot. +- How's everything been going? +- I make a living. +- Playing an accordion? +- That's right. +Want me to play a tune for you? +There's other jobs besides railroading. +Well, Colorado may be big in miles. +It's kinda shod on people. +So when a man gets fired the way I was fired the story gets around. +Well, I'm... +I'm sorry. +- No, I like to make music. +- And it keeps you near the rail road. +If someone needs information about a payroll, you can sell it. +You know it's a funny thing. +I don't like you either. +- Is that why you sent for me? +- No. +And keep out of this. +Have it your way. +But I don't trust him now any more than I did when I sent him after the Utica Kid. +I sent you after a thief and you gave him a horse to get away on. +- I told you to keep shut. +- Let him talk. +I'm not wearing a gun. +I'll be honest with you. +He'd talk the same if I was. +- It's been nice seeing you. +- Grant. +I'm sure Jeff didn't mean to be rude. +Sometimes he has a blunt way of putting things. +Unfortunately, Ben isn't much better. +It's not unfortunate. +It just gets things said in a hurry. +Too much of a hurry. +They forgot to ask you if you'd work for the rail road again. +Would you? +Yes, I would. +Not to give you a short answer. +- It's the answer I wanted. +- Sit down, Grant. +Do you remember Whitey Harbin? +Used to work down in Arizona and New Mexico. +- Yeah. +- Well, he's moved into Colorado. +I thought he favoured stage lines and banks. +So did we. +But he's learned about rail road payrolls +- and he's grabbed three in a row. +- Where do I fit in? +They're making up a supply train in the yard. +I want you to ride it. +- With $10,000 in your pocket. +- Why me? +Quite frankly, because no one would suspect you of carrying a payroll. +I sure don't look like $10,000, do I? +Are you building a bridge you don't need? +The money's here. +Why not bring the men in on Saturday and pay them off in town? +And lose half the crew? +Turn them loose in a mining town, they'll go up the hills looking for gold. +It won't work. +And we have to finish this section before snow comes. +That's a pretty big gamble on a man who gave his horse to a thief! +Yes. +You might as well know the deck's stacked against you. +A boxcar will be hooked to the train. +I'll be one of the men in it. +- When did this happen? +- Last week. +- Renner, did you know? +- Yes. +- Why didn't you tell me? +- I told him not to. +- Why? +- Everything we plan gets back to Whitey. +- You think I'd tell him? +- You might trust the wrong people. +- If he takes the job, I'm sure of it. +- And if I don't take it? +Then Jeff will be sitting in Ben's chair. +Oh, I wouldn't like that. +So I'll take the job on one condition. +If I make the delivery I get his job. +You made a deal. +Thank you. +Wait a minute. +It's getting cold up in the hills. +This coat has always been too long for me. +Thanks. +Well. +I thought you didn't like him. +He said that. +I said I didn't trust him. +And I still don't. +Grant. +Are you surprised Ben sent for you? +I was until I talked to him. +He seems to have changed. +You're right. +He doesn't belong in a private car with clerks, figures and pressure from the office. +He belongs at the end of track, running a gang and building a rail road. +- He's a working stiff like you. +- Yes, but he can dream a little too. +Colorado wouldn't have a rail road if he hadn't sold them on the idea. +For his sake, I wish he hadn't. +He was happy at end of track but they kicked him upstairs and sent us to Chicago. +- And now he needs a little help. +- That's why he sent for you. +Oh, I may have had something to do with it. +Why? +There was a time when you were interested in me. +I was more than interested in you. +I wanted to marry you. +Times when I'm sorry you didn't. +Aren't you? +No. +A man likes to know his woman will back him when he's down and you didn't. +Ben called me a thief and you went right along with him. +It's as simple as that. +Grant. +For old times' sake. +For old times' sake? +Just that and nothing more? +Perhaps just a little more. +We want to be sure that payroll goes through, don't we? +I don't know. +Maybe Jeff is right. +His type seldom changes. +And if we've made a mistake, it's the finish of everything. +Then why not cut this car into the supply train? +If we're all playing showdown, I'd like to see the cards when they fall. +- Thank you. +I hope you have a nice trip. +- Thank you. +Ma'am, is that all? +- Here's your lunch. +You've earned it. +- Thanks. +- Mister, are you going to end of track? +- Yes. +Could you stake me to a ticket? +I can ride half fare if I'm with an adult. +- And you're an adult. +- Well, sometimes I wonder. +All right. +You can come along. +We'll ride with the other fellas with no money. +- On the flatcar? +- Go on. +Climb aboard. +Plenty of fresh air. +Do you good, make you grow. +Are you sure he didn't come while I was away? +Ain't nobody been here but the man riding the sorrel. +- What color horse your man riding? +- How should I know? +It's extremely important that I see him. +They've cut in Mr Kimball's car. +Barley! +A man told you to put his horse up... +Don't start that too. +That there sorrel is the only horse what come in. +That there sorrel is the horse I want. +He belongs to my friend Grant McLaine. +McLaine? +That's who it is. +I knew him as a troubleshooter in Santa Fe before he went bad. +- He didn't go bad. +- What'll you do with his horse? +- Ride him! +I'll change, you saddle him. +- All right. +Hey, Pilgrim! +Come here! +Don't go getting your liver all upset. +- Once you miss 'em, they stay missed. +- It's none of your business. +- Could be. +You wanting to get on that car? +- If I am? +- I can take you to where it's going. +- On one of these? +They'll get you to end of track before the train does. +- That's ridiculous. +- $100 again yours I'm right. +- You've got a bet. +- And you got stuck. +Here. +I'll let you ride Flap Ears. +- You can smoke inside, mister. +- I can smoke where I want. +You can burn too if it pleases you but it'll still cost you four bits. +- For what? +- Traveling first-class. +Otherwise ride the flats. +- You play that? +- Yeah, I play it. +- When? +- When? +Whenever somebody throws a dime in my hat. +- I ain't got a dime. +- This one's on me. +- Been up here before? +- Pad way. +- What takes you to end of track? +- A job. +Figured I'd get one at Junction City. +They told me the foremen do the hiring. +You're a little small for swinging a sledge. +- I can carry water. +- Yeah, you can carry water. +- Very important job. +- Hey! +- What are you doing here? +- He's with me, Pick. +- Where did you get him? +- Somebody threw him away. +Don't you throw him away. +He'll get lost in the mountains. +Who tells the men who build rail roads how to get through the mountains? +The river. +They just follow the river. +- Who told you that? +- I guess my dad was the first. +He had a little song about it. +♪ Follow the river ♪ +♪ The river knows the way ♪ +♪ Heads can go astray ♪ +♪ It happens every day ♪ +♪ Follow the river ♪ +♪ Wherever you may be ♪ +♪ Follow the river back to me ♪ +Wouldn't you wanna be knowing about Concho? +- Who's Concho? +- The man you roped. +Do you wanna know? +Not unless you wanna tell me. +I ought to tell you. +He's fast with a gun. +Only know two men who are faster. +Which two men would they be? +Whitey Harbin for one. +I run away from Whitey. +That's why Concho was after me. +You're one of Whitey's men? +No. +I was in Montrose. +Whitey and his bunch were robbing a bank. +I was just in the road watching. +Whitey was all for killing me but the other fellow wouldn't let him. +He swung me up into the saddle and said, +"You ain't killing a kid. +Not while I ride with you." +- Whitey, he backed down. +- Cos the fella's faster with a gun? +Like lightning. +This other fella, does he have a name? +He's got a name. +The Utica Kid. +I'd have stayed with the bunch if he was boss. +- But he's not? +- Not yet. +Always he's shoving pins into Whitey, laughing at him, driving him crazy. +Even crazier than he is! +Someday Whitey will crack and he'll lose. +Is this the fresh air you were talking about? +How come them fellas can ride inside? +Well, it's the old story of good and evil. +If you spend all your money on whiskey, you have none left for a ticket. +Don't drink. +Then you'd have six bits when you need it. +That's very true. +Tell you what, maybe I have six bits. +Yeah. +What do you say we go in and spend it? +Come on. +Guess I wasn't tough enough to follow the river that way. +Sometimes it isn't easy traveling upstream. +- That will be a dollar. +- That'll be six bits. +I'm the adult. +Here. +Hold on to that. +- Don't worry about Concho. +- You would if... +Oh, no, come on. +Sit down. +We can both worry together if you want to tell me about it. +- It's nothing. +- And if it was, you'd rather not say. +All right. +I broke with Whitey. +Doesn't mean I have to talk. +No, you don't have to talk. +I even broke with the Utica Kid. +- Hi, Utica. +- Put him away, Howdy. +Sure. +Come on. +It's a pretty good rig. +Too good for the guy that owned it. +Remember that draw you taught me? +It worked. +He went down with his gun in the leather. +- And now you're an "in case" man. +- In case? +Yeah. +In case you miss six times with one, you draw the other. +- If you have time. +- I'll have time. +Call it. +Draw! +You better learn to draw that one before you fool around with the other. +About three inches high, Whitey. +You better take another look at that skull. +Next time it could be yours. +Don't soft-foot up behind me! +It makes me nervous! +So I notice. +What else did you notice? +Did you see Concho? +- Did you see him? +- He wasn't on the trail. +Did I ask you where he wasn't? +I asked you did you see him? +- I would've said so. +- Not straight out you wouldn't. +Because you're a funny man. +You've always gotta be laughing inside. +Well, go ahead, laugh. +But get this, Kid. +I'm a better gun than you. +Or would you like to try? +It's an interesting thought, but I'm afraid of you, Whitey. +You ain't afraid of me. +And in your feet, where your brains are, you think maybe you're just a bit faster. +And you know something? +It could be. +Before you break up completely, you mind putting a name on this? +It's just a little old wedge. +But when you put it through the latch of a boxcar, you can't open the door from the inside. +Now, you ask me, who would want to open the door of a boxcar from the inside? +- Jeff Kurth and a dozen gunmen. +- How would you know? +I was sleeping up there when Concho told you. +You better learn how to snore! +You wouldn't know how to shoot a man in the back. +I'll learn. +What'll it be, gents? +We got Old Grandpa, Old Grandma, Old Uncle Tom. +- And Old Empty. +- You ain't funny, Latigo. +Who could be funny, sweating it out in here? +Get away, boy. +You're too young for whiskey even if we had plenty. +Don't get fancy. +You ain't talking to Joey. +Speaking of Joey, you didn't happen to spot him along the trail, did you? +I'll take a shot of that Old Flannelmouth. +- Did you see him? +- No. +Did he leave any sign? +A little. +He was headed toward Junction City. +But you didn't follow him? +Joey always was a nuisance. +I was for dropping him in the river. +- Why didn't you? +- And get my brains shot out? +You've got to find a better reason to kill me. +Suppose Concho didn't catch up with Joey in town and suppose the kid talked? +- He won't talk. +- Maybe not, but Concho ain't back. +Unless he gets back, we won't know where they're carrying the money. +That's right. +Maybe it'd be smart to let this one go through. +Why? +We've grabbed three in a row. +Let's give them a breather. +That makes sense. +I go along with Utica. +You and me both. +We ought to let this one go through. +It ain't going through! +Why not? +You're the one who taught me about payrolls and now I like them. +- So do I. +- I'll buy that. +A man can get saddle-sore looking for a bank to take. +- I'm with Whitey. +- Me too. +What about you, Torgenson? +I got no complaints. +You call it, I'll play it. +Looks like you've been outvoted. +Or do you want a recount? +- Right now, I'd rather have a drink. +- Suit yourself. +If I can't buy a fight, I'll buy a drink. +Fill 'em up. +Sorry, the bar is closed. +On account of we're fresh out of whiskey. +Either get this floor fixed or get a new bartender. +When do we make the hit? +Any time you're ready. +She was halfway up the grade when I left. +Why didn't you tell me? +Why didn't you ask me? +Funny man! +Mount up! +Settle down. +It's only another job. +But if you was boss, we wouldn't do it. +If I was boss we wouldn't do it. +You ain't boss! +♪ So I bought myself a shovel ♪ +♪ and I bought myself a pick ♪ +♪ And I laid a little track along the bullfrog crick ♪ +♪ Then I built a locomotive out of 20 empty cans ♪ +♪ And I tooted on the whistle ♪ +♪ and the darned thing ran ♪ +♪ Oh, you can't get far without a rail road ♪ +♪ You can't get far without a rail road ♪ +♪ Somethings gotta take you there ♪ +♪ and gotta bring you back ♪ +♪ You can't go any distance ♪ +♪ in a buggy or a hack ♪ +Throw some ropes around them timbers. +We'll pull it down. +Torgenson! +- OK, John. +- Hurry it up, Jubilee! +- Boy, they're pushing her fast today. +- Yeah! +Maybe they heard I needed a quick ten thousand. +- That water tower your idea? +- What's wrong with it? +Any self-respecting injun could walk away with it. +Funny man! +He knows everything about everything. +Let's get down and lock the barn door. +We've stopped! +Whitey's making his hit! +- McLaine sold us out! +- No, Ben. +They didn't learn it from Grant. +Leary! +- A hold-up! +- They did it again! +Stop your moaning and hold on to your hat! +They won't stop old Tommy Shannon with a tank full of water. +That's no way to treat rail road property, Mr Shannon. +Take your hand off the throttle and reach for the brake! +All right. +Sit down and behave! +Come over here. +Open the safe! +- Ha! +- Move in! +Same as last time! +- We thought you were lost or drunk. +- There ain't nothing in there. +Jubilee! +How are you making out? +Try to talk your way out of this! +- I'm sorry I missed out with Renner. +- Never mind. +Where's the money? +- It's not in the safe. +- Then where is it? +It could be going to Junction City with Jeff's men. +That's not true. +Renner told us Jeff wouldn't carry the payroll! +That's a help. +Least we know who didn't carry it. +Funny man! +When you get through laughing, see what's in that red car. +Sure. +Glad to. +As soon as I pick up my horse. +He's worth more than anything I'm gonna find on this train. +Get those pilgrims out. +Maybe one of them is carrying it. +Hit the other cars! +See if you can find it. +Outside! +All of you! +Is this what you wanted to tell me? +Have a look inside, Latigo! +If that's McLaine... +No, Ben. +Put it away. +You may as well be comfortable. +- Be my guest. +- Gladly. +Do you mind if I ask the name of my host? +No, I don't mind. +Would the payroll be in there? +No. +Why not take a look, just to be sure? +Boy, is this stuff mellow. +Bottled in bond too. +- I forgot. +Ladies is always first. +- Thank you, no. +See for yourself. +Hello, Joey. +What are you doing here? +Getting robbed! +Don't bother. +None of them's got more than two dollars. +Whitey! +There ain't no payroll in there. +How come you missed out? +- I had a little trouble. +- Now, ain't that too bad? +- Maybe I ought to give you a little more. +- Whitey! +Kimball's back there with his wife. +You just got lucky! +Put them back in the car! +Get aboard! +Go on. +Good little boys don't run away. +This time you'll learn! +- Where's the payroll? +- The man says he doesn't know. +I can help him remember. +Take her outside. +Take her outside yourself. +I'm afraid of women. +They scream and scratch, and sometimes step on your toes. +Don't say no to me. +Not when I got a gun in my hand. +I won't. +Unless I'm holding one too. +- Outside. +- If you want the payroll... +You'll have to wait for the next work train. +We decided not to send it through on this one. +Oh? +I don't mind waiting. +I'll be at Pay Load. +You can bring it to me. +Then I'll take 12 hours start, you get your wife back. +See what happens when you don't carry your brains in your feet? +I ought to make you walk. +Jubilee, lead them out. +Step up with Latigo. +What about Joey? +You gonna leave him here? +He'll ride with me. +Or would you like to? +Settle down. +We're getting $10,000 for the lady, remember? +Which one do I ride with? +Which one do you think? +Take her to the end of track, Mr Shannon! +Here's a stirrup. +Give you a lift? +I'll take that box. +Don't crowd the cantle. +You'll ride easier. +Whoa, mules! +Must have got tired of making the climb and started home. +- Come on, boy! +- Just a minute. +There's a mining town near here. +It used to be called Pay Load. +It's still called Pay Load but nobody lives there. +- It's over beyond that far hill. +- Which hill? +- You see the first hill? +- Yes. +See the second one? +There's a third hill. +Pay Load's behind that. +- How much do you want for this mule? +- $50. +Flap Ears, when you unload this piker, you come on home to mother. +Get outta there! +Welshing on a bet! +Never could understand them rail road people. +Come on! +Come on! +- Mr Kimball. +- Come over to the telegraph shack. +Before you pass. +Did you bring the payroll? +Not now! +- Did you bring it? +- I didn't. +- Now what? +- The end of the rail road. +- Shut up, Feeney. +- Let go of me or I'll push this down your throat! +Who wants your man? +I don't want none of 'em! +They're all broke! +- See you in Denver. +- I'm off to Denver too. +- So am I! +- Nobody goes without orders from Kimball! +- I'm leaving. +- You are not. +You'll take no joyride in this town with them painted hussies. +We've waited this long. +Another night won't hurt us. +But if the money's not here in the morning, out we go! +Get back to work! +We're beat, Mr Kimball. +Without the pay, the gang will go to Junction City. +- I know. +- Any word from Jeff? +He's in Junction City. +Says the car held to the grade all the way. +He and his men will be after Whitey in... +They will not! +Tell him to stay right where he is until further orders. +Yes, sir. +Wonder if he thinks that's private property. +If he tries to divide that like he cuts up the loot, there's gonna be shooting. +- Your laundry? +- Sandwiches. +Do you want one? +No. +Where did you get them? +Junction City. +A girl in a restaurant gave them to me. +Was she pretty? +- Think you could get me a date? +- She's not that kind of a girl. +Any of you boys win enough to buy a drink? +- You ain't got a drink. +- I got a drink. +- I thought you was fresh out. +- I was till we made the hit. +While you looked for the payroll that wasn't there, I had important business. +Come on, fill her up. +Latigo ought to be running this bunch. +We might not eat, but we'd sure drink. +Ha ha! +You're a funny man. +Why don't you laugh? +- Am I supposed to? +- Not if you're smart +- I think you're smart +- And what else do you think? +That you made a mistake. +She'll only bring you trouble and guns. +Since when is $10,000 trouble? +That's exactly what you're worth. +You're very flattering. +But I'm inclined to agree with you. +Don't make a habit of it. +Latigo, I want a drink! +And you've got a few habits I don't like either. +Settle down. +Do you see what she's up to? +I can see you. +And what I see I don't like too good. +- I guess you could use one. +- Thank you, no. +- It's the best. +I got it off your own bar. +- You drink it. +Sorry, lady, I don't drink. +I'm studying to be a bartender. +- Don't you drink? +- Not alone. +Suppose I join you? +- Do you mind? +- And if I do? +Don't push it. +For a little while you're gonna need me and I'm gonna need you. +I watched you walk. +I could swear we've met before. +Could you? +Funny little things you do. +Like when you smile. +Strange. +I seem to recognise all your mannerisms, if you know what that means. +- I know what that means. +- Do you? +I'm supposed to fight Whitey over you. +With a little luck we'd kill each other. +- It's an interesting thought. +- What's interesting? +- She is. +- You're so right. +I may not send you back. +Not until you've helped me spend the ten thousand. +- You mind if we join the party? +- Yes! +You shouldn't, cos if you guess wrong you ain't gonna hang alone. +You like another drink? +- Thanks, I still have this one. +- Drink them both. +Anybody want to start the dance? +With only one girl? +Get back to the bar where you belong. +Let's all get back to the bar, where we belong. +- You almost got your wish. +- One of them. +- The other? +- To know your name. +His name? +He's the Utica Kid. +I don't like it either. +My family used to call me Lee. +Why don't you? +You're supposed to be outside. +Come out with your hands up. +- What are you doing here? +- I want to see the Utica Kid. +- Who are you? +- A friend of his. +Funny thing, he never told me about no girlfriend. +ls there any reason why he should? +- What's your name? +- Charlie Drew. +And you can put that gun away. +Or do I look dangerous? +Not exactly. +Give me that rope. +- When'd you get here? +- Just before they rode in. +Utica pulled the job off right on schedule. +I suppose you've known it was going to happen for quite some time. +No, I haven't. +Utica doesn't talk to me about jobs. +Not this kind. +- Did he ever have any other kind? +- He will have. +Soon. +Then why don't you hold out? +Why don't you keep away till he stops being a thief? +I told him that's what I'd do. +He just looked at me and smiled. +He said, "Hurry wonder if you can." +Tonight he has his answer. +You're here. +Yes, but only to tell him that you're... +Only to tell him I'm in town and might come looking for him. +I want to keep him alive. +I want to keep you alive. +- You know what he can do with a gun. +- I know. +Well, then, why? +Because of a little thing called self-respect. +Maybe you wouldn't understand anything about that. +For five years I've played that thing for nickels and dimes thrown into a hat. +For five years the Utica Kid has been laughing. +I may have been wrong, Charlie, but I'm not gonna make the same mistake twice. +Grant... +When you see him will you tell him that I'm here? +Leave it alone! +So all she'll bring is trouble and guns? +Did you bring the money with you? +No. +- How soon do we get it? +- I wouldn't know about that. +You should! +$10,000 is a lot of money. +And that's what he wants for me. +Well, I'd say he was selling out cheap. +Never mind what you'd say. +What did Kimball say? +If you don't know about the money, why did he send you? +He didn't send me. +I came on my own. +Why? +- Ask him. +- Well? +I wouldn't know. +Then again, maybe I would. +You were right the first time. +I can walk quiet at night and I'm a pretty good gun. +I'd like to join up with you. +You see, when a man gets fired off the rail road, he has a little trouble finding a job. +And when he can't find a job, he gets hungry. +I've been hungry for the last five years. +Haven't I? +- How would he know? +- I'm his brother. +- His brother? +- His younger brother. +Five years ago he was a troubleshooter for Kimball. +I lifted the feed herd and he came after me. +Then gave you a horse to get away. +But not until I'd heard all about good and evil. +I didn't buy what he had to sell then. +I'm not buying it now. +- So you don't want him in? +- No. +Funny thing. +I want him in. +- Any objections? +- It ain't that simple, Whitey. +There's a personal deal between me and him. +- About what? +- He got in my way. +That's right. +Oh, yeah, I remember you. +You're the man that fights kids. +Which way do you want it? +Get up, come on, get up! +Now one of you give him his gun. +All right, Harbin, you're the boss around here. +You call it. +I might just do that. +Well, I ain't gonna take him alone. +Then maybe you'd better move along. +Any further objections? +- Yeah. +- Now ain't that wonderful? +- I'd be happy to call it. +- You may get the chance. +You mind if the Utica Kid and me have a little talk? +Not at all. +Call me when you're ready. +I think you ought to know I'm working for the rail road again. +I figured as much. +- Troubleshooter? +- Tonight I was carrying the payroll. +- Where did you hide it? +- I gave it to the boy. +It's in that shoe box. +Now all you have to do is go in and tell Whitey. +You're gambling I won't? +- Same old story of good and evil. +- Same old story. +You lose, Grant. +Yeah, I kind of figured that when you laughed. +I'll give you the same break you gave me. +Ten-minute start, then I tell Whitey I sent you away. +I go, that money goes with me. +So does Kimball's wife. +- No. +- Wait a minute, Lee. +Hear me out on this. +If I leave here, that boy goes with me too. +Joey? +Why do you want him? +Maybe for the good of his soul. +It's been a long time since you heard that word, hasn't it? +Mother and Dad used to bring it up once in a while when we were kids. +You were just about Joey's age. +He thinks a lot of you, doesn't he? +- He wants to grow up to be just like you. +- He may make it, with practice. +Soon he'll be holding the horses while you and Whitey hit a bank. +There's another kid lying in the barn. +He got the start that way too? +- You didn't kill Howdy? +- I didn't hurt him. +- And you're not going to hurt Joey. +- How could I do that? +It's not hard. +It's not hard. +Not when he takes your road. +Or haven't you stopped to look at it? +Why bother? +I picked it, I'll ride it. +Lee, I'm asking you again. +Give Joey a chance. +No. +You've got ten minutes. +I won't need them. +Charlie's in there waiting for you. +Think about her. +She's been following you for five years too. +She's got a reason. +Or didn't I tell you I'm gonna marry her? +How much of that did you hear? +Just what I wanted to hear. +That you're gonna marry me. +When? +We're gonna have a lot of money, Charlie. +$10,000. +You can have pretty new dresses and pretty new shoes. +And a brand-new husband. +- Tomorrow. +- No. +Right now! +If you want me, take me away right now. +Please, please take me. +Why the sudden hurry? +Has my big brother been telling you the story of good and evil? +Don't laugh at him. +Why not? +Why mustn't I laugh at him? +Maybe it would be better if... if you tried to be a little more like him. +Now isn't that just great? +Now I get it from you! +Ever since I was a kid that's all I can remember. +"Why don't you be more like your brother? +Why can't you be more like Grant?" +I don't want to be like him. +I don't want any pan of him. +- That's not true. +- Yeah, it's true! +You don't know what it's like to be the kid brother. +Everything you do is wrong. +Everything you try. +Until one day I tried a gun. +Fit my hand real good. +And I wasn't the kid brother any more. +It's a good gun. +It's gonna get us everything we always wanted. +But I don't want it. +Not that way. +Why must you steal? +Because I like to steal. +I like to see what people will do when I take it away from them. +What happens when something is taken away from you? +Nobody's gonna take anything away from me. +Charlie, I'm asking you to marry me. +No. +Grant was right. +You'll never change. +And he calls me a thief? +Joey +Go on. +Play some more. +It's been a long time since I heard an accordion. +Any tune in particular? +Or would this do? +♪ Oh, you can't get far without a rail road ♪ +♪ You can't get far without a rail road ♪ +♪ You gotta have an engine ♪ +♪ and you gotta have a track ♪ +♪ Oh, you can't get far without a rail road ♪ +♪ There are tracks across the prairie ♪ +♪ Where the buzzard builds his nest ♪ +♪ There are tracks across the Rockies ♪ +♪ To the Golden West ♪ +How does it go from there? +How does it go from there, Lee? +Everybody will be neighbours +In this little dream of mine +Take you clear across the country +On the Bullfrog Line +♪ Oh, you can't get far without a rail road ♪ +- ♪ You can't get far without a rail road ♪ +Gentlemen! +- Renner! +- Didn't you know he was working for me? +- I've come for my thousand dollars. +- What thousand dollars? +Your memory is quite shod. +I supplied you with information about a certain boxcar. +I was prepared to supply you with information about the payroll. +- Concho did not keep the appointment. +- So? +So ten per cent of the payroll is mine. +Sorry to disappoint you but we missed the payroll. +Missed the payroll? +In that case I'm prepared to make a better deal. +For $2,000, I can tell you where the money is. +You made a deal. +Ben Kimball hired a man to carry it. +I might never have located this place if I hadn't heard that man's accordion. +He has the money. +Ask him! +Joey! +Come here, Joey! +Grant! +McLaine, there's a woman with you! +- That's right. +- Send her out before we come get you. +Here, hurry! +Come on, Charlie. +He's in the clear. +He's riding away. +Yeah, he's riding. +After me. +- What are we stopping for? +- We're going to the mill, the shod way. +Get down to the mill! +Come on! +Take cover! +Here. +There's a mine shaft at the end of these cables. +It runs clear through the mountains. +On the other side, about half a mile, is the rail road! +It's two hours to the end of track. +I have to send you out one at a time. +Come on, Verna. +- Tell Ben he'll get his payroll somehow. +- I'll tell him more than that. +You'll get that money even if you had to kill your own brother? +The next ore bucket that comes down, pull it around and jump in. +I'll cover for you. +It's clear, Charlie. +Get out! +See if you can reach him from over there. +He can't stand them off, not alone. +You figuring to help? +Grant! +Look out! +He's real good. +Only one better gun in Colorado. +Charlie! +Get over here! +- I thought I told you to get out. +- I'm staying right here. +All right. +Now you get back inside and I'll cover for you. +Thanks, Charlie. +Lee, not the kid! +You take care of the kid. +I'll see if I can keep them pinned down. +Would you mind if I play big brother just this one time? +- Shoots high. +- You or the gun? +- Joey all right? +- He's all right. +That makes you a winner. +Go ahead and make a sucker out of the kid. +Tell him all about good and evil. +Put him to work on the rail road. +Things get tough, he can always play the accordion for nickels and dimes. +Sounds like old times, Lee. +Welcome home. +Don't give me that big brother grin. +- Up there! +- Get him! +I count mine. +There's one left. +He hit you hard, Lee. +Not half as hard as you did with that Bullfrog Line. +That was Dad's favourite tune and you know it. +I know it. +You and your stinking accordion! +Charlie. +Charlie? +You and Joey get the horses. +What...? +I'll take care of my brother. +Here's your money. +Pay 'em off, Tim. +Thank you, Grant. +Looks like you won yourself a job. +Mine. +No, it won't fit. +Not nearly as well as your coat. +Want your old job back? +Thanks. +All right, Joey. +Get a bucket and start carrying water. +We're at end of track. +Now go on. +♪ Sometimes I feel like ♪ +♪ could jump over the moon ♪ +♪ And tell the sky above ♪ +♪ Does it matter how full the moon ♪ +♪ When you've an empty head ♪ +♪ Follow the river ♪ +♪ Wherever you may be ♪ +♪ Follow the river back to me ♪ +♪ Follow the river back to me ♪ +[SINGING] +ELIZABETH: +Darling. +- Papa, have I kept you waiting? +- No, that's all right. +Come on. +- Why isn't Peter here? +- He's playing with Kimani, Papa. +That brother of yours and that Kyuke are inseparable. +Can't he find a white playmate? +Why? +You can't treat an African like a brother and expect to have a good servant. +When Caroline died, Kimani's mother raised Peter. +In a way, they are brothers. +[WHISTLE BLOWS] +When do you leave for England? +Tomorrow, worst luck. +I'm homesick already. +A few years of school... +You won't let him marry anybody but me, Mr. McKenzie, will you? +Has he proposed? +No, but I have, quite often. +Which of you stole the rifle? +Step forward. +Your religion says it is evil to steal. +Your own medicine shall name the liar. +If you tell the truth, this will not burn your tongue. +He who lies burns. +Peter? +Kimani, my son, shall be the first. +Did you steal that gun? +Did you steal the gun? +Did you steal the gun? +Did you steal the gun? +[CHATTERING DOG BARKING] +I will find the weapon and bring it to you. +Punish him yourself. +The city teaches bad ways to young men. +How does it go with your wife? +The wife with child? +Tomorrow, the day after... +The time is near. +Papa. +- How does it work? +- Plain old witchcraft. +The Kikuyu is a very religious man. +He fears God, but he trusts him too. +- But hot steel is... +- Will not burn a wet tongue. +But the liar's spit dries up. +Him it will scorch. +Ha-ha-ha. +I think you know more about black witchcraft than you do about the Bible. +- Let me have my way with these devils... +- Poor old Jeff is the perfect colonizer. +What's his is his and what's theirs is his too. +Well, have a good shoot. +We're not raising cattle to feed a maverick lion. +PETER: +Kimani, Lathela. +Tell Kimani not to gut him. +We'll leave a smelly calling card for the lion. +Kimani, open the animal, but don't clean him. +Then you'd better service the guns. +When it comes time to kill the lion, I want to shoot the gun too. +It's Jeff's show. +And you know how he feels about Africans and guns. +KIMANl: +I want to shoot the gun too. +PETER: +I'm sorry. +Lathela. +KIMANl: +Always when we hunt it is the same. +You have all the fun, I do all the work. +When we were little and played together... +But we're big now. +And things are not the same. +Hit him. +Hit him. +Hit him hard. +Do what he says, now. +And in a hurry. +From now on, when he tells you to do something, do it. +Don't think about it, just obey. +Understand me? +Well? +Come on, Peter. +I really should've slapped you. +Might have been better all around if you had. +Heh-heh. +Forget it. +You had no right to hit Kimani. +JEFF: +Peter, how many times have I got to tell you? +Blacks are blacks and not playmates. +One thing you can never do is argue with them. +Never. +You tell them. +Oh, sometimes you can joke with them you can boot them in the tail sometimes look after them when they're sick. +But you never, never argue with them. +- The world's changing, Jeff. +- Not in Africa it isn't. +Kimani's mother raised both of us. +We grew up together. +You'll never live together on equal footing. +Not in our lifetime. +You can't spend the first 20 years of your life with someone sharing bread and secrets and dreams, and then one day say: +"Sorry, it's all over. +We live in different worlds." +I don't believe it and I don't like it. +Wait till you settle down and marry Holly and have to deal seriously with the wogs. +Have you heard from Holly? +A couple of letters from London. +She mentioned coming back? +Just stuff about school, things like that. +Hm... +Well, we'd better break camp and go after that lion. +Lathela. +Get Kimani to help you load. +Kimani not here. +PETER: +Where? +Forget that lion, Jeff. +We're gonna find Kimani, and right now. +All right, all right, all right. +[ENGINE STARTS] +You want Lathela with you? +No, you'll need him to track. +I'll meet you back here at sundown. +[HYENAS YIPPING] +[WHIMPERS] +[YELPS] +- Are you all right? +- Yes, bwana. +- Does it hurt much? +- No, bwana. +You're lying. +- And stop calling me bwana. +- What shall I call you? +"Boss"? "Master"? +Yes, it hurts. +Not where the trap cut me only where Jeff slapped me. +That is where it hurts. +Well, then stop thinking about it. +No one ever struck me in anger before. +Not even my own father. +It wasn't in anger. +He's already forgotten. +Can you forget it? +I cannot forget it either. +We are alike in many things. +You talk Kikuyu same as me. +I speak English same as you. +But you are white and I am black. +And you are the bwana and I am the servant. +And I carry the gun and you shoot. +- Why is shooting the gun so important? +- It's not the gun, it is... +What is it, then? +What? +We cannot talk as friends. +Why? +You said it yourself. +We are not children anymore so we are not friends anymore. +I saved your life as a friend. +I'll always be your friend. +Kimani... +Does it hurt much? +No. +[SPEAKING IN FOREIGN LANGUAGE] +[BIRD CROWS] +[SPEAKING INDISTINCTLY] +ELIZABETH: +The child doesn't come easily. +It is a curse. +This morning, I saw the dung of a hyena. +Just now a vulture passed over us. +Don't you talk like that. +Just don't you talk like that. +- Suppose the child is born feet first. +- Then it must be killed. +When that child comes, don't you touch it. +You understand? +It is you who do not understand. +I'm gonna fetch my father. +White magic will not remove the curse. +- Perhaps the curse is in your son? +- What evil did he do? +Suppose a snake came into his bed. +Suppose a man struck him and he did not strike back. +Suppose he broke a law. +[BABY CRYING] +The child enters life feet first. +Do what must be done. +[BABY STOPS CRYING] +[BELL RINGS] +[INAUDIBLE DIALOGUE] +Kimani. +Swear him in. +- Which god, please? +- The Christian God. +I worship Ngai, the god who lives on Mount Kenya. +I will swear by our sacred Githathi stone. +CROWN COUNSEL: +Your word will suffice. +KARANJA: +Oh, no, no. +If I lie before this symbol of God my children and their children and my home and my land will turn to dust. +[STICKS BANG] +And when I die I will have no life hereafter except to live forever in eternity by the cursed hyena, cowardly eater of the dead. +I speak the truth. +You're the father of the dead baby in question? +- Yes. +- Did you tell the midwife to kill the baby? +Yes. +It was born feet first, it was cursed. +Then what was done? +What is always done according to custom. +CROWN COUNSEL: +Tell His Honor what that is. +We smothered the child and buried it under a pot. +- You know that killing is against the law? +- God says to murder is wrong. +And when you had that newborn baby smothered, was that not murder? +No. +A child cannot join the tribe until he is 1 year old. +Therefore, he's not really born until his second year. +What was killed was a demon, not a child. +Yes, yes. +And then what did you do? +- What? +- Then what did you do? +We sacrificed a young ram. +Mm. +And that, I suppose, got rid of the curse. +KARANJA: +No. +No, sir. +Not yet. +I am still here, therefore the curse is still at work. +Would you do the same thing if another child were born to you feet first? +Yes, yes. +It would be my duty. +What in the name of Almighty God are we trying to do to these people? +CROWN COUNSEL: +Preserve the law, Henry, that's all. +Law? +Whose law? +Not theirs, surely. +All men are equal before the law. +Except some are more equal than others. +That man is an accomplice to murder. +He's admitted that. +But can we make him understand it? +We take away their customs, their habits, their religion. +We stop their tribal dances, we stop them circumcising their women. +Then we offer them our way of life, something they can't grasp. +We say, "Look how clean and rich and clever we are." +For the Africans different wages, different life. +We mock their wise men. +Take away the authority from their fathers. +What are the children going to do? +They'll lose respect for their elders and fathers and when they do, look out. +Maybe they'll lose respect for our white Jesus too. +Turn to something else for help. +It won't be to us. +Well, you understand, don't you, Peter? +If we don't make the African respect the law well, the next thing you know, he'll be wanting to rule this country. +Imagine that, now. +Whatever could give him that idea? +This is his son. +Can he come in while we're here? +[SPEAKS FOREIGN LANGUAGE] +[IN ENGLISH] The city frightens me. +- Let us go home quickly. +- Listen, old friend. +The law says you must stay here in jail for a while. +I'm sorry. +We'll do everything we can. +My daughter will visit you. +She'll bring you tobacco and food to comfort you. +Please keep this for me. +A jail is not the proper place to keep god's sacred symbol. +And when my son comes of age... +I understand. +I am happy it was not you who struck my son. +You are still his friend? +Yes. +And yours too, for as long as you both wish it. +MAN: +Boy, boy. +I told you. +He will not help you. +Our Mathanjuki will purify you. +He will drive the curse from your body and I will be free. +- No. +- You do not believe in god? +- Yes, yes. +But I do not believe in our witchcraft and black magic. +When Bwana Jeff struck you... +He struck a black man to prove that the white man is master, nothing else. +You are not in jail because of a curse but only because we are judged by their laws. +And that is the truth. +And I must follow where the truth leads me. +- Where does it lead you? +- To strike back. +We're men, not animals. +You have much to look forward to, my son. +You will become headman as I was. +Is that to be my life? +Headman for a white boss? +"Yes, bwana. +No, bwana. +Yes, bwana." +This land can serve me too. +I want my own land. +Then you must earn it. +I will, Father. +I will. +[DOG BARKING] +[GASPS] +Who are you? +Who sent you here? +Why you come here? +He told me to come here. +You told me the white man would put Father in jail. +- You said we had to fight the white man. +- Your father is in jail? +- Yes, and I'm ready to fight. +- You ran away from the McKenzie shamba? +- Yes. +- Why? +- You stole money? +- No. +- Guns? +No, why should I steal? +Then why should you run? +I don't know. +NJOGU: +This is my daughter, Wanjiru. +- He can be of no use to us. +He wants to fight the white man. +We can use him. +We will take him to the mountains. +We will train him. +Come, little boy. +First you will learn to steal guns. +Hm? +[ENGINE STARTS] +I have no parents and I am hungry. +I need work. +Not a sound. +Nothing. +Do not call. +Do not answer. +Do not cough or I kill you. +Understand? +You are not alone? +How many are there? +One other? +The houseboy? +You will call him by name. +Nothing else, just the name. +Call him. +COOK: +Migwe. +Migwe. +This boy is dead. +Nanyuki Police signing off, 1545. +- Hello, Peter. +- I need some help, Hillary. +If it's about the sentence of your headman... +His son, Kimani. +He's missing. +- When? +- Last night. +I want him found. +- What did he steal? +- Steal? +You want him found, what are the charges? +- He might be hurt. +- You check the infirmary? +And I've chased down his family within a hundred miles. +He'll show up. +He probably went to Nairobi on a toot and... +- Age? +- Twenty-one. +- Height? +- Six-two, weight a little under 13 stone. +Wait a minute. +There was a houseboy killed last night. +Buxton shamba, at the foot of the Aberdares. +A gang broke in, stole guns and whiskey. +- What's that got to do with Kimani? +- Maybe nothing. +Maybe everything. +- Not a chance. +- Why not? +I know Kimani. +I know how he thinks. +He's not a criminal. +You mean not yet. +You just find him. +At least send out a description. +Kimani's guilty of only one thing, captain. +Guilty of being born black. +[SINGING] +Take one. +Why that gun? +My friend Peter has a gun like this. +It is a fine gun. +I can kill a lion with this. +Or even a man, huh? +[SINGING STOPS] +There will be no drinking here again. +Never. +Adam is our leader. +Who are you to tell us what...? +NJOGU: +Daughter, ask the other women where to go and what to do. +Kimani. +I see you have earned a gun. +This gun. +To get some of these guns, one of our own people was killed. +When lightning strikes, a bystander may be hurt. +Lightning belongs to god. +This was murder by him. +It was the will of god. +No. +I do not like your ways. +Sit down. +I go to Nanyuki. +I work there to free my father in my own way. +Sit down. +Two reasons why you cannot leave us. +That houseboy. +That houseboy who was killed last night, Adam can hang for this. +So can you. +So can all of us. +- That is the law. +- Reason two. +You know our names and our faces. +You know where we live and how we live. +We would be safe only if you stay with us. +Or if you were dead. +We will not always live as hunted animals. +Great men make plans for us. +Plans to drive the white man from our country. +Plans to take back our land. +Plans to... +MAN [OVER PA]: +Flight 212, BO AC arriving from London, Rome, Athens, Cairo, Khartoum. +- Cigarette? +ELIZABETH: +No. +- Dad? +- No, thanks. +Flight 212 departing for Dar es Salaam, Johannesburg and Jamestown. +ELIZABETH: +There. +Two-one-two departing for Dar es Salaam, Johannesburg and Jamestown. +Each to their own. +Holly, I... +Six years is a long time. +Too long? +You'd better see to her luggage. +- Can't I watch too? +- It's indecent. +That's why I want to watch. +Oh, really. +PETER: +Kimani. +Hey. +[DOGS BARK] +Kimani. +Strange. +I thought I saw Kimani. +You remember Kimani? +Move. +Start moving. +[SPEAKS FOREIGN LANGUAGE] +[IN ENGLISH] Would you mind letting us by, please? +[SPEAKS FOREIGN LANGUAGE] +I've come to pray. +CLERK: +This is not a church. +My god does not live in a church. +How do you call yourself? +Kimani wa Karanja. +We are beggars and slaves in our own land. +The British allow us in their homes and hotels, yes. +But how? +As servants. +We are millions, they are a handful. +We are strong, they are weak. +How then are they the masters and we the slaves? +Is it white magic? +Is it god's will? +No. +They have the guns. +We too shall have guns. +Are we ready for this? +The whole colored world burns with the fever of revolt with the fire for freedom. +Do any of you have any questions? +Is there a doubt in your hearts? +What troubles you? +NJOGU: +Kimani. +His name is Kimani wa Karanja. +For five years, he has been in the mountains with us. +He is ready for leadership. +He is very strong and loyal. +Strong men have betrayed us before. +- You have a question, Kimani? +KIMANl: +Yes, sir. +- This talk of guns. +LEADER: +Yes? +Is this the only way we can get freedom? +Yes. +- By the spilling of blood? +- Yes. +We will never drive the British out with words. +And not with doubts and not with friendship. +It can only be done with guns. +The white man did not take this land with guns. +He bought this land. +- This is truth. +- Mm-hm. +And I must follow where the truth leads me. +You were educated in white missionary schools? +Yes, sir. +Long, long ago, to whom did the land belong? +- The people. +- Yes. +Not one person, but the entire clan. +And therefore only the clan can sell the land correct? +- Yes, sir. +No man of any other tribe can buy our land unless he becomes, in our religion, a Kikuyu. +Yes, sir. +And have the British ever become Kikuyus? +Or have you become one of the British? +Your father was a friend of the British. +But your father died in their prison. +There is only one way to drive out the British. +By terror and death. +Everyone must either be for us or against us. +Those who be with us, stand. +Good. +We will need a symbol, a sign, a name. +Here it is. +Mau Mau. +Mau Mau. +Use it, live by it, die for it. +Mau Mau is the machinery that will carry us to freedom and independence. +Mau Mau. +ALL: +Mau Mau. +I swear to kill an Englishman or may this oath kill me and my family. +I swear to kill an Englishman or may this oath kill me and my family. +- They make a nice couple, don't they? +- Mm. +She's got good lines for breeding too. +Look. +Mount Kenya. +Lathela, wait here. +No wonder the African believes that God lives on Mount Kenya. +If I were God, that's where I'd like to live. +I feel I'm really home now. +I love you, Peter. +I always have. +I suppose I always will. +I like the feel of you. +I wish... +Yes? +I wish it could always be like this moment. +Safe and warm and peaceful. +Always like this. +Home is always like this. +Why did your husband run away? +Did he steal? +Did he do something bad? +Where did he go? +Why didn't you go with him? +- I was afraid. +- Afraid? +Afraid of what? +WOMAN: +Hello, my darling. +MAN: +Hello, my darling. +LITTLE JEFF: +What did you bring? +PETER: +Hello. +LITTLE JEFF: +You didn't forget my rifle? +WOMAN: +Yes, it's right here. +MATSON: +Henry. +WOMAN: +Bring the children in. +Bring them in. +MATSON: +What do you think? +What's it mean? +I don't know. +Two Kyukes disappear from my place. +Jasper, his headman reports one gone from his farm, rifle missing too. +One gone from your place. +Why? +You saw his wife. +She's afraid. +Why? +What of? +[DOOR KNOCKS] +Come in. +According to Kikuyu custom we come to speak for Peter McKenzie, bachelor to Holly Keith, spinster. +- This shy Kikuyu maiden is grateful. +- She doesn't look very shy to me. +How many goats will be paid for me? +Three or four ought to be quite enough, don't you think? +Oh, I'd say 20 or 30 at least. +Why don't you throw yourself in and make it 31 goats? +And why has Peter wa Henry chosen me? +He needs someone to chop firewood and dig potatoes. +He needs someone to keep his bed warm. +- He promises not to beat you often. +- Unless it's absolutely necessary. +- He also expects a child every year. +- All of them his. +- A very narrow attitude. +- We shall also have to shave your head. +Do you accept my son? +If you do, we'll drink to the marriage bargain. +If you don't, I shall have to pour this on the ground. +HOLLY: +And waste all that precious gin? +Thank you for becoming one of our family. +You will swear a new blood oath. +When it is done, you will be part of the new army: +Mau Mau. +He who refuses to take the oath he dies. +He who breaks the oath he dies. +Cut off the sheep's head. +Fill this calabash with its blood. +Sugar cane. +Sugar cane and banana leaves the first source of food. +Mugere plant best and strongest magic. +The arch oldest Kikuyu symbol. +You will pass through the arch seven times and thereby enter a new life. +You will receive seven cuts on the arm to bind you together. +Seven. +All things in seven. +Seven, the unlucky number. +Break the oath and the evil seven will strike. +Sheep's blood symbol of sacrifice. +Millet seeds of nourishment. +Earth the earth we fight for. +The cause that brings us together. +You will eat this oath. +You will swallow it seven times so that it becomes part of you. +Bitter Sodom apples. +Take off everything that stinks of the European. +Watch, ring, money. +To give you an easy road. +The endless circles. +Earth. +Hold it to your belly. +That the land may feed us and not the foreigners. +Hold up your arm. +So that your blood will mix. +Now swallow the oath seven times. +Repeat after me as you pass through the arch. +If I sell land to any foreigners, may this oath kill me. +If I sell land to any foreigners, may this oath kill me. +- I will steal guns. +- I will steal guns. +I will never be a Christian. +I will never be a Christian. +I will drive out all Europeans or kill them. +I will drive out all Europeans or kill them. +NJOGU: +It is done. +They've all sworn. +I feel unclean. +I will not let Wanjiru take this oath. +It is not necessary. +She is loyal. +To swallow the oath was hard enough, but the rest of it... +The nameless filth, the shame. +And in front of the others. +Why was it necessary? +Why? +To bind us together forever. +Now they will do anything. +Killing of mother, father, son will be as nothing to them. +They will feel strong with power and purpose. +- Who gave you the oath? +- No one. +You never took it? +I am too old to change. +I am ready to give up my life, but I cannot give up my faith. +It is too deep, too strong. +In life and in death I will always believe in the god of my father the god who lives on Mount Kenya. +- So do I, in spite of the oath. +Your daughter carries my child. +Now, I wish to marry her before the child is born. +I consider you married. +I will gather cooking stones with my wife as my father before me gathered cooking stones with my mother. +Like you, I cannot tear out what is in my heart. +Do it quickly, then. +We need rest. +Tomorrow is the appointed day of the long knives. +Our first attack should be on the McKenzie shamba. +- Why there? +- Why not? +Look, that was my home, my friends. +A great leader has no friends, only a cause. +- You doubt my loyalty? +- I only ask you to prove it. +Let your panga come back as red as mine. +[CAMERA WINDING] +[BABOONS HOWLING GRUNTING] +[HOLLY CHUCKLES] +Thank you for a lovely day. +Lovely wedding day. +- No more anxiety? +- Mm-mm. +- You know why? +- Why? +Because everything's so full of life. +All the animals, the earth and even the air smells of life. +We've done nothing to spoil it. +Someday all this will be farm country. +What will happen to White Hunter McKenzie, then? +Four years ago, our crops were hit by locusts. +Wiped out. +Papa put all his savings into cattle. +The next year, rinderpest. +What cattle didn't die had to be killed. +Papa got a loan from the bank. +So part of the time, I take rich clients on safari. +For the money. +To pay back the loan. +So the land's good to us this year and the crops hold up, no locusts, no rinderpests I'll be back where I really belong. +On the farm. +You know, that's the most wonderful wedding present you could ever give me. +- Are you as happy as I am? +- I'm a very lucky man. +I have the two women I love most in the world. +- Who's the other one? +- Africa. +There are some things I can do for you that Africa can't. +What is it? +I don't know. +Something strange. +Well, I didn't hear anything. +I'm not certain. +It was something. +Just a feeling, I guess. +[HORN HONKS] +I wonder what's happened to the porch light. +Probably the fuse again. +I'll have a look at it. +JEFF: +Hey, what the...? +Ugh! +KIMANl: +Remember me? +Kimani. +- What do you want? +- I've come home. +[INAUDIBLE DIALOGUE] +[CRASHING WHISTLE BLOWING] +ELIZABETH: +Jeff! +KIMANl: +No. +[MOUTHS] Kimani. +MAN [OVER RADIO]: +Jeff Newton and two of his children dead. +His wife, Elizabeth, in critical condition. +On the open highway to Nanyuki in broad daylight Joe Matson and Mrs. Matson were ambushed while motoring. +Mrs. Matson was killed by machine-gun bullets. +Chief Waruhiu, leader of the anti-Mau Mau movement was murdered at Kiambu. +MEYLl: +Yes, bwana. +SUPERINTENDENT: +Were you in your hut last night? +MEYLl: +Yes. +SUPERINTENDENT: +It's lucky your father and the one boy were out visiting. +Where is Jeff and the kids? +SUPERINTENDENT: +What's your name? +MEYLl: +Meyli. +SUPERINTENDENT: +Who was with you? +MEYLl: +My husband and my children. +And the mother of my husband. +SUPERINTENDENT: +Did you ever attend any Mau Mau meetings? +MEYLl: +No, bwana. +SUPERINTENDENT: +Next, please. +[GASPS] +Mrs. McKenzie, what type blood are you? +- Type O. +- Come along, please. +Hurry. +Anybody else here with type O blood? +Peter? +Lathela is, I think. +DOCTOR: +Which one of you is known as Lathela? +Is that you? +Come with me. +We need blood to help Memsahib Elizabeth. +Papa. +Why Elizabeth? +Why the kids? +Why? +[WHISTLE BLOWING] +[GRUNTING YELLING IN FOREIGN LANGUAGE] +[CAR ENGINE STARTS] +[MUSIC PLAYING] +MAN [OVER PA]: +A state of emergency now exists in Kenya. +Kikuyus are being sworn into a terror organization called Mau Mau. +Small gangs are fighting guerrilla warfare. +There may be Mau Mau on your farms, in your cities, in your homes. +Any African found with a gun may be punished by death. +Peter, why do you have to go? +We've been over this a dozen times. +I have to go, that's all. +Yes, but there's the army... +The army is inexperienced in the mountain and the bush country. +- How long will you be away? +- I don't know. +What am I supposed to do while you're gone? +What the rest of the women are doing, help keep the place going. +Peter. +It wasn't very much of a honeymoon for you, was it? +Are you very afraid? +No, not of them. +Only for us. +It's us I'm afraid for, what will happen to us. +GAME WARDEN: +Mau Mau working underground everywhere. +Maybe right here in this room, for all we know. +Now, the government wants information. +Who's forging the ammunition permits? +Who's supplying the guns? +Who's giving the oaths? +So it's prisoners we're after. +It's your job to track them down. +I say kill them, make it open warfare, bomb them out. +Kill whom, all 6 million Africans in Kenya? +We're only 40,000. +That makes the odds about 150-to-1. +That's not the point. +We're not at war with the Kikuyu nation. +We're fighting Mau Mau. +For every one of us, they've killed a hundred Kikuyus. +- Loyal Kikuyus. +- They don't know what loyalty means. +Now, listen, man. +They're trying to drive us out. +What are we to do? +Pack up because their grandfathers were here first? +I was born here too. +This is my country. +Killing's no answer. +We gotta give the African a chance... +Black man's had Africa for years. +It'd be a jungle if we hadn't moved in. +It's not a question of black or white. +That's exactly what it is. +Black or white. +You'll follow orders or keep out of this. +Well? +All right. +I'll try it your way for a while. +No smoking. +And no fires for cooking. +Whiskey? +Jeff. +Talk to me, Papa. +I don't know what to say. +Anything, Papa. +Anything at all. +This off-season rain it should do a lot of good. +You're doing a big job, child. +Like my Caroline, a long time ago when the country was new. +She was delicate, but strong, like you. +She helped to make the land and hold it. +Like you. +No, Papa, not like me. +I'm weak. +I'm weak and I'm afraid and I'm lonely. +Papa. +Who said you could get out of bed? +I want to go to Nairobi to see the doctor. +Is it your arm again? +I know you'll think I'm mad but I'm going to have another baby. +You see, if there's any chance of it being born... +Well, I mean, after losing so much blood and... +And I want this baby, Papa. +More than I've ever wanted anything. +It'd be a little bit more of Jeff and... +Holly, will you take me in to the doctor in the morning? +[DOG BARKING] +[SINGING] +Hey, you, listen carefully. +[MATSON SPEAKS IN FOREIGN LANGUAGE] +You are surrounded by police. +[CHATTERING] +MATSON: [IN ENGLISH] Lay down your guns. +Listen carefully. +[GUNFIRE] +[MATSON SPEAKS IN FOREIGN LANGUAGE] +[IN ENGLISH] Lay down your guns. +You are surrounded by police. +[CHILD CRYING] +MATSON: +All right. +Waithaka, do you know any of these people? +[SPEAKS IN FOREIGN LANGUAGE] +- Next. +- A good farmer, no Mau Mau. +- No? +- No, bwana. +You see? +Njogu, soldier of god. +MATSON: +How long were you in the mountains? +One year. +Do not hurt me, bwana. +Who gave you the oath? +I do not know. +If you lie to me again, I'll kill you. +Now who was it? +Who made you swear to the oath? +[THUD] +Waithaka. +Help me. +Help me. +Waithaka. +- Help me. +- The woman lies. +I never saw her before, never. +I swear. +By my father, I swear. +Here's one of your loyal Kikuyus. +All right. +We'll start again. +- You gave the oath to the girl? +- No. +- She knew your name. +How? +- She's the wife of my brother. +- Who gave you the oath? +- It was dark and raining, I could not see. +How do you Mau Mau do it? +Since when do we use torture? +The Mau Mau do it. +They love it. +- You might even grow to love it yourself. +- I don't like it any more than you do. +But I don't like what happened to Matson's wife. +Or your family. +Or any families to come. +[WAITHAKA SCREAMS] +We're not such a big jump away from being savages ourselves, are we? +Please. +Please let me point him out from here. +Please let me. +This is the man. +- Your name. +- Njogu. +Is he the one? +Is he the oath-giver? +You said his name was Njogu. +You said he was here. +He spoke truly. +I gave the oath to him, to all of them. +They know nothing. +And from me, you will get nothing. +WAITHAKA: +Do not let me stay... +Do not let me stay here. +You promised, bwana. +You promised, you promised, you promised. +[CROWD SCREAMS] +[WAITHAKA SCREAMS] +[DOOR KNOCKS] +Who is it? +[DOOR KNOCKS VIOLENTLY] +LITTLE JEFF: +Uncle Peter. +Excuse my appearance. +I need a drink. +- I beg your pardon. +- Let me help you, son. +That's right. +Absolutely right. +You're gonna help us all. +I need your help. +Government needs help. +Everybody needs help. +It's a big secret job. +Very important. +Toast. +Toast. +I don't think he's taken off these clothes since he left home. +He probably never had a chance. +Thank God he's all right. +Holly strange things happen to people in war. +- Inside, I mean. +- Not between us. +- He'll be the same as always, you'll see. +- Nothing's ever the same. +That's one thing you can't do, stand still. +[GASPS] +Look, his sock has rotted away inside his boot. +[PANTING] +I'd forgotten how good our earth feels. +So rich and full of life. +Can you hear the soil through my fingers? +No. +What's it saying? +How much I love you and miss you and need you. +Last night, I thought... +Last night I had a nightmare and it was... +It was a nightmare. +Somebody will see us. +Does it matter? +It isn't the same, is it? +Yes, Holly. +You make me feel ashamed. +We waited lunch for you. +- Sorry. +- Finally gave up. +I didn't realize the time. +Daydreaming? +Yes. +You can pick your dreams in the daytime. +I'm sorry you've gotta go tonight. +So am I. +It's not fair to Holly. +She's carrying a pretty heavy burden. +No more than you or a dozen other women around here. +It's not easy for Holly looking after Papa and little Jeff and me. +It's not easy going to bed with a rifle by your side night after night instead of a husband never knowing if you're going to see daylight again. +Never laughing. +Never loving. +Never knowing if the next footstep on the porch is yours or... +You're her whole life, Peter. +Don't shut her out. +I feel empty. +Dead. +It's not so bad in the daytime, in the clean hot sun. +But when it grows dark I'm afraid, I guess. +And then when I think of Holly and how much I want her and when it's the moment to touch her and be with her, I can't. +I just feel dirty, I feel unclean. +Filthy business we're in. +Time will wash it clean. +Who knows how much time there is left? +- Ready? +- Yes, yes. +Where's Holly? +She's in the bedroom. +Well? +Don't go. +Please, don't go. +You expect me to run out? +Yes. +Yes, together. +Somewhere far away, where there's no war. +We belong here, Holly. +Here, this is our land. +It was worked for and paid for. +Nobody's driving me off this land. +They can bury me in it, but nobody is chasing me off it. +Peter, darling, what does a piece of land matter? +Look what it's doing to us, to everybody. +- Please, take me away from here. +- This is our home. +- They say not. +- They lie. +War is filled with lies. +What they say, what we say, lies. +Our place is here. +My place is with you. +And you have no place for me. +I'm selfish. +I don't want to lose you. +Please, let's go away from here before it's too late. +MATSON: +Do I get the names? +The oath-givers the man who killed my wife. +Joe. +Lathela. +You are not afraid of Mau Mau? +I'm like you. +I'm too old to be frightened by men. +The wrath of God frightens me, not the brutality of men. +What do you want of me? +How is it you gave the oath to others and never took it yourself? +I believe in the faith of my father. +Good. +Who are your leaders? +Your oath-givers? +[CHUCKLES] +By speaking out, you can end the war between us. +You leave Africa and the war will end. +Can't we live in peace, your people and mine? +Go away. +Your soft words are sharper than blows. +Would you prefer violence? +I'm no ordinary man. +Nothing can make me speak out. +They have tried. +They could not do it. +Not with torture, not with pain. +You will fail also. +[LIGHTNING CRASHES THUNDERRUMBLES] +Well, that's all we needed, a spell of weather. +Ngai is angry. +What's that? +Thunder and lightning. +When it storms, the Kikuyu believes he is face-to-face with god. +Thunder is the sound of god cracking his joints preparing for battle. +The lightning is god's sword of retribution. +You talk as if you believed that black hogwash yourself. +The important thing is whether our friend in there believes it. +If he does... +You'll never break him with mumbo jumbo. +His kind understands only one thing: +Force. +- Kill him, you make a martyr of him. +- He'll be dead. +Hold it, Joe. +Go ahead, Henry. +You gotta fight an idea with a better idea. +With the help of this weather, and if I know my man... +Well, give me one more go at him. +Tell me, Ngai, if I do right. +I only wish to do thy will. +Give me a sign that I may know. +[SPEAKS FOREIGN LANGUAGE] +[IN ENGLISH] Lathela, get some kerosene and dry wood. +- I am not afraid to face god. +- We will see. +I am the messenger of god. +Did god create Mau Mau? +Mau Mau is the will of god. +Did god tell you to mutilate innocent children? +Did Gikuyu and Mumbi ever violate animals? +Since the creation of Mount Kenya has god ever told you to steal and murder and burn and hate? +Is it the will of god that you eat human flesh and blood? +- I swear that... +- Wait. +Let your swearing have value in the eyes of god. +Swear by your sacred Githathi stone. +Hold this symbol of God in your hands and swear. +Then I'll believe you. +Now begin at the beginning. +Did you ever take the Mau Mau blood oath yourself? +- No. +- I believe you. +- Did you give the oath to others? +- Yes. +- By force? +- Yes. +You swore to drive the white men out of Africa, didn't you? +- Yes. +- Did God tell you to create Mau Mau? +Say yes before God and I'll believe you. +I've said enough. +You are afraid to face your god. +- If Mau Mau drives us out, then what? +- Then freedom. +- And faith in god too? +- Yes, yes. +How? +What faith? +Mau Mau, the promise to murder? +Will god take back the people who've eaten the blood oath? +That's why you didn't take the oath yourself, isn't it? +Because you wanted to be able to come back to god. +Yes, Ngai, I come to you faithful with no other gods before you. +HENRY: +But you've broken every law of your god. +Tell him that too. +Tell him you gave the blood oath to others by night, by force. +That you gave it before witnesses, gave it to women and children. +These are the worst violations. +How can you lead your people back to god? +Even tonight, more of your people are being oathed banished from the house of god cursed to live through eternity as a broken-spined hyena. +Is that the future for your people? +Is it? +Is that what you want? +No. +Who's the oath-giver in Nairobi? +Who is he? +If god cannot accept Mau Mau, Mau Mau cannot lead your people. +In Nairobi, his name is Timbu. +Who gives the oath in Thomson's Falls? +Lorry driver for Bwana Wilson. +Nyeri? +They are even in the home guard. +Are Mau Mau in our telephone service? +- Yes. +- Code words for guns? +- Mti, tree. +- Ammunition? +Makaa, charcoal. +The McKenzie shamba, who led the attack? +The... +The husband of my daughter. +His name? +Kimani wa Karanja. +MAN [OVER RADIO]: +The capture of a high-ranking oath administrator has led to the arrest of many Mau Mau in the Nyeri District. +Loyal Kikuyu witnesses are cooperating by pointing out those Africans who have taken the blood oath. +Witnesses wear white hoods to conceal their identities. +Shantytown in Nairobi, cesspool of intrigue and resistance is being flattened and razed. +Ready? +- Where do you think you're going? +- To find Kimani. +GAME WARDEN: +I can't spare the men for that chase. +- Just Lathela and I. +- And when you find him, then what? +- Ask him to surrender. +- Why should he? +Because I know Kimani. +Because he wants peace as much as we do. +Peace? +You said surrender. +Peace means terms. +What terms? +His precious life? +A seat in parliament? +You and your pet black boy. +You're just a black liberator, aren't you? +GAME WARDEN: +All right, all right. +What terms? +The lives of his people. +- What can we lose by trying? +- Did this Kimani take the oath? +The old man says yes. +You wouldn't have one chance in a thousand of coming out alive. +MAN [OVER RADIO]: +The emergency operations now cost the government more than a million pounds every month. +Several farmers in the Nyeri District have quit their farms and returned to England. +Mau Mau gangs are being forced deeper into the Aberdare Mountains. +[GUNSHOTS] +HOLLY: +The flare, Papa. +Send up the flare. +HENRY: +Elizabeth. +[WHISTLE BLOWING] +Jeff. +Where's Jeff? +Tomorrow, you can take Elizabeth into Nairobi. +To the hospital. +And leave here? +It's to help Elizabeth. +We'll get you a little flat in town and you can come and see me every day. +Yes. +Yes, I'd like that. +Are you all right? +No one came here. +Did you make contact? +Well? +Did you see Kimani? +Will he come? +He's a big general now. +I do not know if he will come. +And if he come, I do not know if it is to speak or to kill. +I do not know how a general thinks. +KIMANl: +Put down your gun. +Kimani? +KIMANl: +The guns. +And the pistol too. +The pistol. +Now, tell Lathela to build a fire. +Why? +I want my comrades to see you. +We're alone, you have nothing to fear. +I know this. +You have tobacco? +- Cigarettes. +- Pass them here. +Why did you come? +- Can we not talk face-to-face? +- No. +- Njogu is our prisoner. +- I know. +He confessed many things, told us many names. +- I know. +- He is not harmed. +Then why did he turn against us? +Njogu was braver than any of us. +He was not afraid to die. +He was afraid for his soul. +Can you understand that? +Yes. +The people he named have been arrested. +- I know. +- You know the war goes badly for you. +It is possible to lose a battle and still win a war. +Must Africa always stink of death? +Can we not live together as friends? +- Friends have equal rights. +- They will come. +Only when we take them. +- I think we're ready to give them. +- What do you want of me? +PETER: +Give up. +Surrender. +Bring in your people. +Surrender? +Peace. +On what terms? +Justice. +Understanding. +If you stop fighting, others will do likewise. +You must have faith. +You must try. +We have tried before. +Then try again. +And again and again and again. +Do you not love anyone? +Your wife? +Children who believe in you? +You know of my child? +No. +A man-child? +Yes. +He will find a better world than you and I. +I sometimes dream of when we were children, you and I. +- Peter? +- Yeah. +I've not said that name in many years. +How goes it with your father? +As well as age will allow. +He was a good man. +He's a friend of my father. +Yes. +And Memsahib Elizabeth? +She is with child. +- Peter? +- Yes. +I did not hurt her. +I did not hurt her or her children. +It was not my hands that struck them. +I believe you. +What's happened to us? +When did this hatred begin? +Before we were born, I think. +I will talk with my people. +I will tell them that I trust you. +But they must decide for themselves. +This will take time. +Four days hence, you will have your answer. +If they agree we will come to the meadow by the hidden spring. +- You know of it? +- Yes. +- You will be there? +- Yes. +Until then. +Kimani. +Grandpa. +HENRY: +Peter. +- So you pulled it off. +- Yes. +- I wanna hear about it. +You like a drink? +- No, thank you, later. +Holly? +Holly? +Holly is with Elizabeth in Nairobi. +Oh... +- You see, we had another raid here. +- I know. +I asked her to go. +- Don't blame her, son. +She was... +- Thanks, Papa. +What we do is stupid. +To surrender betrays everything we have done. +Our children need food, our sick need medicine. +All we need is courage. +Let me talk to them. +You cannot talk to a starving people. +Their belly have no ears. +And if they shoot us down? +No, I have the word of my friend. +Your friend is a white man. +He hates us. +It is your own hatred that you see in others. +PETER: +Holly. +Sister Williams. +I called at your flat. +You shouldn't go into Elizabeth's right now. +Anything wrong? +No, she's just a little overdue, that's all. +There's nothing to be alarmed about. +You're looking... +You're looking thinner. +You don't look so bad yourself. +Was it very bad? +Some days are good, some bad. +- No, they'll see us. +- Let them. +Do you have to go back? +Tonight. +Oh, I wish I could go with you. +We'll go away soon in that honeymoon we never had. +We don't have to go away to be on a honeymoon. +But I thought you wanted to... +To run away? +Yeah. +HOLLY: +Just when was that? +Let's see, about a month ago? +At least a hundred years. +I want to go home to our home. +With Mount Kenya and God in the garden. +The war may not be over for a long time. +I used to blame the war for everything, didn't I? +Somebody else's war is always to blame. +No, I was to blame. +When you grow up, you realize you can't run away from the world. +You just gotta live in it. +You're a big girl now. +I'm beginning to understand about that other woman too. +- What other woman? +- Africa. +Oh. +She's not the least bit jealous. +And neither am I. +Excuse me. +Your boy, Lathela, he says you have to start off for somewhere or other. +PETER: +Thank you. +See you soon. +Please, God, let it be soon. +Can't you make this thing go faster? +We've got to get there by daylight. +Why? +It's almost impossible. +- But if Kimani shows... +- He set no hour. +He'll wait for us. +Yes, but will Joe Matson wait? +- Matson? +- He got wind of it somehow. +You should have stopped him. +I only heard about him myself about an hour ago. +How do you keep a thing like this secret? +How do you keep Matson off the trigger? +This won't be any ceasefire, it'll be cold-blooded murder. +[PANTING] +[SLAP BABY CRYING] +Doctor? +Yes? +Is there any marks? +Just the mark of a man. +Look at this place. +It's a perfect trap. +What are we supposed to do? +Wait around till they show up? +MATSON: +We'd be caught in the open. +It's a perfect trap, I don't wanna get caught. +- If they show, it'll be to surrender. +- How do you know? +But they gave their word. +I'm taking cover. +You know how Joe is, always suspicious. +I know how Mau Mau is too. +Where is your friend? +You there, all of you, put down your guns. +[SCREAMING] +Wait. +Please. +[BABY CRYING] +[KIMANI SCREAMS] +[SPEAKS IN FOREIGN LANGUAGE] +Yeah, we lost him all right. +Come on. +[BABY MOANING CRYING] +- When we find Kimani, will you kill him? +- No. +Then why do we hunt him? +He must not think I betrayed him. +If he trusts us, others will do likewise. +If he escapes, if he does not believe Mau Mau will fight harder and longer. +Kimani will not surrender peacefully. +Not this time. +- He will try to kill you. +- Perhaps. +- Don't come along. +- I come with you. +- Why? +- This is my fight too. +Mau Mau has killed a hundred of my people for every one of yours. +I want the same thing for the African that Kimani wants. +Mau Mau is not the way to get them. +PETER: +Kimani? +Stay here and don't move. +And don't shoot. +- Let me talk to you. +- No! +You kill my wife and my people. +We were betrayed. +Both of us. +I'm here without a weapon. +Are you alone? +Lathela is here too. +I'm coming in. +Keep away. +Kimani. +[BABY CRYING] +[GRUNTING] +Don't make me do it. +Come back with me. +No. +We'll start over again. +- This time, it'll be different. +- No. +It is too late. +For you and me. +It is too late. +Must I kill you? +Yes. +[YELLS] +Give me the child and bury us both. +No. +Please. +He is dead. +- What will you do with the child? +- Take him home. +Elizabeth has a boy, raise them together. +Maybe for them, it'll be better. +It's not too late. +Subtitles by SDI Media Group +[ENGLISH SDH] +Darling. +- Papa, have I kept you waiting? +- No, that's all right. +Come on. +- Why isn't Peter here? +- He's playing with Kimani, Papa. +That brother of yours and that Kyuke are inseparable. +Can't he find a white playmate? +Why? +You can't treat an African like a brother and expect to have a good servant. +When Caroline died, Kimani's mother raised Peter. +In a way, they are brothers. +When do you leave for England? +Tomorrow, worst luck. +I'm homesick already. +A few years of school... +You won't let him marry anybody but me, Mr. McKenzie, will you? +Has he proposed? +No, but I have, quite often. +Which of you stole the rifle? +Step forward. +Your religion says it is evil to steal. +Your own medicine shall name the liar. +If you tell the truth, this will not burn your tongue. +He who lies burns. +Peter? +Kimani, my son, shall be the first. +Did you steal that gun? +Did you steal the gun? +Did you steal the gun? +Did you steal the gun? +I will find the weapon and bring it to you. +Punish him yourself. +The city teaches bad ways to young men. +How does it go with your wife? +The wife with child? +Tomorrow, the day after... +The time is near. +Papa. +- How does it work? +- Plain old witchcraft. +The Kikuyu is a very religious man. +He fears God, but he trusts him too. +- But hot steel is... +- Will not burn a wet tongue. +But the liar's spit dries up. +Him it will scorch. +Ha-ha-ha. +I think you know more about black witchcraft than you do about the Bible. +- Let me have my way with these devils... +- Poor old Jeff is the perfect colonizer. +What's his is his and what's theirs is his too. +Well, have a good shoot. +We're not raising cattle to feed a maverick lion. +Kimani, Lathela. +Tell Kimani not to gut him. +We'll leave a smelly calling card for the lion. +Kimani, open the animal, but don't clean him. +Then you'd better service the guns. +When it comes time to kill the lion, I want to shoot the gun too. +It's Jeff's show. +And you know how he feels about Africans and guns. +KIMANl: +I want to shoot the gun too. +I'm sorry. +Lathela. +KIMANl: +Always when we hunt it is the same. +You have all the fun, I do all the work. +When we were little and played together... +But we're big now. +And things are not the same. +Hit him. +Hit him. +Hit him hard. +Do what he says, now. +And in a hurry. +From now on, when he tells you to do something, do it. +Don't think about it, just obey. +Understand me? +Well? +Come on, Peter. +I really should've slapped you. +Might have been better all around if you had. +Heh-heh. +Forget it. +You had no right to hit Kimani. +Peter, how many times have I got to tell you? +Blacks are blacks and not playmates. +One thing you can never do is argue with them. +Never. +You tell them. +Oh, sometimes you can joke with them you can boot them in the tail sometimes look after them when they're sick. +But you never, never argue with them. +- The world's changing, Jeff. +- Not in Africa it isn't. +Kimani's mother raised both of us. +We grew up together. +You'll never live together on equal footing. +Not in our lifetime. +You can't spend the first 20 years of your life with someone sharing bread and secrets and dreams, and then one day say: +"Sorry, it's all over. +We live in different worlds." +I don't believe it and I don't like it. +Wait till you settle down and marry Holly and have to deal seriously with the wogs. +Have you heard from Holly? +A couple of letters from London. +She mentioned coming back? +Just stuff about school, things like that. +Hm... +Well, we'd better break camp and go after that lion. +Lathela. +Get Kimani to help you load. +Kimani not here. +Where? +Forget that lion, Jeff. +We're gonna find Kimani, and right now. +All right, all right, all right. +You want Lathela with you? +No, you'll need him to track. +I'll meet you back here at sundown. +- Are you all right? +- Yes, bwana. +- Does it hurt much? +- No, bwana. +You're lying. +- And stop calling me bwana. +- What shall I call you? +"Boss"? "Master"? +Yes, it hurts. +Not where the trap cut me only where Jeff slapped me. +That is where it hurts. +Well, then stop thinking about it. +No one ever struck me in anger before. +Not even my own father. +It wasn't in anger. +He's already forgotten. +Can you forget it? +I cannot forget it either. +We are alike in many things. +You talk Kikuyu same as me. +I speak English same as you. +But you are white and I am black. +And you are the bwana and I am the servant. +And I carry the gun and you shoot. +- Why is shooting the gun so important? +- It's not the gun, it is... +What is it, then? +What? +We cannot talk as friends. +Why? +You said it yourself. +We are not children anymore so we are not friends anymore. +I saved your life as a friend. +I'll always be your friend. +Kimani... +Does it hurt much? +No. +The child doesn't come easily. +It is a curse. +This morning, I saw the dung of a hyena. +Just now a vulture passed over us. +Don't you talk like that. +Just don't you talk like that. +- Suppose the child is born feet first. +- Then it must be killed. +When that child comes, don't you touch it. +You understand? +It is you who do not understand. +I'm gonna fetch my father. +White magic will not remove the curse. +- Perhaps the curse is in your son? +- What evil did he do? +Suppose a snake came into his bed. +Suppose a man struck him and he did not strike back. +Suppose he broke a law. +The child enters life feet first. +Do what must be done. +Kimani. +Swear him in. +- Which god, please? +- The Christian God. +I worship Ngai, the god who lives on Mount Kenya. +I will swear by our sacred Githathi stone. +Your word will suffice. +Oh, no, no. +If I lie before this symbol of God my children and their children and my home and my land will turn to dust. +And when I die I will have no life hereafter except to live forever in eternity by the cursed hyena, cowardly eater of the dead. +I speak the truth. +You're the father of the dead baby in question? +- Yes. +- Did you tell the midwife to kill the baby? +Yes. +It was born feet first, it was cursed. +Then what was done? +What is always done according to custom. +Tell His Honor what that is. +We smothered the child and buried it under a pot. +- You know that killing is against the law? +- God says to murder is wrong. +And when you had that newborn baby smothered, was that not murder? +No. +A child cannot join the tribe until he is 1 year old. +Therefore, he's not really born until his second year. +What was killed was a demon, not a child. +Yes, yes. +And then what did you do? +- What? +- Then what did you do? +We sacrificed a young ram. +Mm. +And that, I suppose, got rid of the curse. +No. +No, sir. +Not yet. +I am still here, therefore the curse is still at work. +Would you do the same thing if another child were born to you feet first? +Yes, yes. +It would be my duty. +What in the name of Almighty God are we trying to do to these people? +Preserve the law, Henry, that's all. +Law? +Whose law? +Not theirs, surely. +All men are equal before the law. +Except some are more equal than others. +That man is an accomplice to murder. +He's admitted that. +But can we make him understand it? +We take away their customs, their habits, their religion. +We stop their tribal dances, we stop them circumcising their women. +Then we offer them our way of life, something they can't grasp. +We say, "Look how clean and rich and clever we are." +For the Africans different wages, different life. +We mock their wise men. +Take away the authority from their fathers. +What are the children going to do? +They'll lose respect for their elders and fathers and when they do, look out. +Maybe they'll lose respect for our white Jesus too. +Turn to something else for help. +It won't be to us. +Well, you understand, don't you, Peter? +If we don't make the African respect the law well, the next thing you know, he'll be wanting to rule this country. +Imagine that, now. +Whatever could give him that idea? +This is his son. +Can he come in while we're here? +The city frightens me. +- Let us go home quickly. +- Listen, old friend. +The law says you must stay here in jail for a while. +I'm sorry. +We'll do everything we can. +My daughter will visit you. +She'll bring you tobacco and food to comfort you. +Please keep this for me. +A jail is not the proper place to keep god's sacred symbol. +And when my son comes of age... +I understand. +I am happy it was not you who struck my son. +You are still his friend? +Yes. +And yours too, for as long as you both wish it. +Boy, boy. +I told you. +He will not help you. +Our Mathanjuki will purify you. +He will drive the curse from your body and I will be free. +- No. +- You do not believe in god? +- Yes, yes. +But I do not believe in our witchcraft and black magic. +When Bwana Jeff struck you... +He struck a black man to prove that the white man is master, nothing else. +You are not in jail because of a curse but only because we are judged by their laws. +And that is the truth. +And I must follow where the truth leads me. +- Where does it lead you? +- To strike back. +We're men, not animals. +You have much to look forward to, my son. +You will become headman as I was. +Is that to be my life? +Headman for a white boss? +"Yes, bwana. +No, bwana. +Yes, bwana." +This land can serve me too. +I want my own land. +Then you must earn it. +I will, Father. +I will. +Who are you? +Who sent you here? +Why you come here? +He told me to come here. +You told me the white man would put Father in jail. +- You said we had to fight the white man. +- Your father is in jail? +- Yes, and I'm ready to fight. +- You ran away from the McKenzie shamba? +- Yes. +- Why? +- You stole money? +- No. +- Guns? +No, why should I steal? +Then why should you run? +I don't know. +This is my daughter, Wanjiru. +- He can be of no use to us. +He wants to fight the white man. +We can use him. +We will take him to the mountains. +We will train him. +Come, little boy. +First you will learn to steal guns. +Hm? +I have no parents and I am hungry. +I need work. +Not a sound. +Nothing. +Do not call. +Do not answer. +Do not cough or I kill you. +Understand? +You are not alone? +How many are there? +One other? +The houseboy? +You will call him by name. +Nothing else, just the name. +Call him. +Migwe. +Migwe. +This boy is dead. +Nanyuki Police signing off, 1545. +- Hello, Peter. +- I need some help, Hillary. +If it's about the sentence of your headman... +His son, Kimani. +He's missing. +- When? +- Last night. +I want him found. +- What did he steal? +- Steal? +You want him found, what are the charges? +- He might be hurt. +- You check the infirmary? +And I've chased down his family within a hundred miles. +He'll show up. +He probably went to Nairobi on a toot and... +- Age? +- Twenty-one. +- Height? +- Six-two, weight a little under 13 stone. +Wait a minute. +There was a houseboy killed last night. +Buxton shamba, at the foot of the Aberdares. +A gang broke in, stole guns and whiskey. +- What's that got to do with Kimani? +- Maybe nothing. +Maybe everything. +- Not a chance. +- Why not? +I know Kimani. +I know how he thinks. +He's not a criminal. +You mean not yet. +You just find him. +At least send out a description. +Kimani's guilty of only one thing, captain. +Guilty of being born black. +Take one. +Why that gun? +My friend Peter has a gun like this. +It is a fine gun. +I can kill a lion with this. +Or even a man, huh? +There will be no drinking here again. +Never. +Adam is our leader. +Who are you to tell us what...? +Daughter, ask the other women where to go and what to do. +Kimani. +I see you have earned a gun. +This gun. +To get some of these guns, one of our own people was killed. +When lightning strikes, a bystander may be hurt. +Lightning belongs to god. +This was murder by him. +It was the will of god. +No. +I do not like your ways. +Sit down. +I go to Nanyuki. +I work there to free my father in my own way. +Sit down. +Two reasons why you cannot leave us. +That houseboy. +That houseboy who was killed last night, Adam can hang for this. +So can you. +So can all of us. +- That is the law. +- Reason two. +You know our names and our faces. +You know where we live and how we live. +We would be safe only if you stay with us. +Or if you were dead. +We will not always live as hunted animals. +Great men make plans for us. +Plans to drive the white man from our country. +Plans to take back our land. +Plans to... +Flight 212, BO AC arriving from London, Rome, Athens, Cairo, Khartoum. +- Cigarette? +No. +- Dad? +- No, thanks. +Flight 212 departing for Dar es Salaam, Johannesburg and Jamestown. +There. +Two-one-two departing for Dar es Salaam, Johannesburg and Jamestown. +Each to their own. +Holly, I... +Six years is a long time. +Too long? +You'd better see to her luggage. +- Can't I watch too? +- It's indecent. +That's why I want to watch. +Oh, really. +Kimani. +Hey. +Kimani. +Strange. +I thought I saw Kimani. +You remember Kimani? +Move. +Start moving. +Would you mind letting us by, please? +I've come to pray. +This is not a church. +My god does not live in a church. +How do you call yourself? +Kimani wa Karanja. +We are beggars and slaves in our own land. +The British allow us in their homes and hotels, yes. +But how? +As servants. +We are millions, they are a handful. +We are strong, they are weak. +How then are they the masters and we the slaves? +Is it white magic? +Is it god's will? +No. +They have the guns. +We too shall have guns. +Are we ready for this? +The whole colored world burns with the fever of revolt with the fire for freedom. +Do any of you have any questions? +Is there a doubt in your hearts? +What troubles you? +Kimani. +His name is Kimani wa Karanja. +For five years, he has been in the mountains with us. +He is ready for leadership. +He is very strong and loyal. +Strong men have betrayed us before. +- You have a question, Kimani? +KIMANl: +Yes, sir. +- This talk of guns. +Yes? +Is this the only way we can get freedom? +Yes. +- By the spilling of blood? +- Yes. +We will never drive the British out with words. +And not with doubts and not with friendship. +It can only be done with guns. +The white man did not take this land with guns. +He bought this land. +- This is truth. +- Mm-hm. +And I must follow where the truth leads me. +You were educated in white missionary schools? +Yes, sir. +Long, long ago, to whom did the land belong? +- The people. +- Yes. +Not one person, but the entire clan. +And therefore only the clan can sell the land correct? +- Yes, sir. +No man of any other tribe can buy our land unless he becomes, in our religion, a Kikuyu. +Yes, sir. +And have the British ever become Kikuyus? +Or have you become one of the British? +Your father was a friend of the British. +But your father died in their prison. +There is only one way to drive out the British. +By terror and death. +Everyone must either be for us or against us. +Those who be with us, stand. +Good. +We will need a symbol, a sign, a name. +Here it is. +Mau Mau. +Mau Mau. +Use it, live by it, die for it. +Mau Mau is the machinery that will carry us to freedom and independence. +Mau Mau. +Mau Mau. +I swear to kill an Englishman or may this oath kill me and my family. +I swear to kill an Englishman or may this oath kill me and my family. +- They make a nice couple, don't they? +- Mm. +She's got good lines for breeding too. +Look. +Mount Kenya. +Lathela, wait here. +No wonder the African believes that God lives on Mount Kenya. +If I were God, that's where I'd like to live. +I feel I'm really home now. +I love you, Peter. +I always have. +I suppose I always will. +I like the feel of you. +I wish... +Yes? +I wish it could always be like this moment. +Safe and warm and peaceful. +Always like this. +Home is always like this. +Why did your husband run away? +Did he steal? +Did he do something bad? +Where did he go? +Why didn't you go with him? +- I was afraid. +- Afraid? +Afraid of what? +Hello, my darling. +Hello, my darling. +What did you bring? +Hello. +You didn't forget my rifle? +Yes, it's right here. +Henry. +Bring the children in. +Bring them in. +What do you think? +What's it mean? +I don't know. +Two Kyukes disappear from my place. +Jasper, his headman reports one gone from his farm, rifle missing too. +One gone from your place. +Why? +You saw his wife. +She's afraid. +Why? +What of? +Come in. +According to Kikuyu custom we come to speak for Peter McKenzie, bachelor to Holly Keith, spinster. +- This shy Kikuyu maiden is grateful. +- She doesn't look very shy to me. +How many goats will be paid for me? +Three or four ought to be quite enough, don't you think? +Oh, I'd say 20 or 30 at least. +Why don't you throw yourself in and make it 31 goats? +And why has Peter wa Henry chosen me? +He needs someone to chop firewood and dig potatoes. +He needs someone to keep his bed warm. +- He promises not to beat you often. +- Unless it's absolutely necessary. +- He also expects a child every year. +- All of them his. +- A very narrow attitude. +- We shall also have to shave your head. +Do you accept my son? +If you do, we'll drink to the marriage bargain. +If you don't, I shall have to pour this on the ground. +And waste all that precious gin? +Thank you for becoming one of our family. +You will swear a new blood oath. +When it is done, you will be part of the new army: +Mau Mau. +He who refuses to take the oath he dies. +He who breaks the oath he dies. +Cut off the sheep's head. +Fill this calabash with its blood. +Sugar cane. +Sugar cane and banana leaves the first source of food. +Mugere plant best and strongest magic. +The arch oldest Kikuyu symbol. +You will pass through the arch seven times and thereby enter a new life. +You will receive seven cuts on the arm to bind you together. +Seven. +All things in seven. +Seven, the unlucky number. +Break the oath and the evil seven will strike. +Sheep's blood symbol of sacrifice. +Millet seeds of nourishment. +Earth the earth we fight for. +The cause that brings us together. +You will eat this oath. +You will swallow it seven times so that it becomes part of you. +Bitter Sodom apples. +Take off everything that stinks of the European. +Watch, ring, money. +To give you an easy road. +The endless circles. +Earth. +Hold it to your belly. +That the land may feed us and not the foreigners. +Hold up your arm. +So that your blood will mix. +Now swallow the oath seven times. +Repeat after me as you pass through the arch. +If I sell land to any foreigners, may this oath kill me. +If I sell land to any foreigners, may this oath kill me. +- I will steal guns. +- I will steal guns. +I will never be a Christian. +I will never be a Christian. +I will drive out all Europeans or kill them. +I will drive out all Europeans or kill them. +It is done. +They've all sworn. +I feel unclean. +I will not let Wanjiru take this oath. +It is not necessary. +She is loyal. +To swallow the oath was hard enough, but the rest of it... +The nameless filth, the shame. +And in front of the others. +Why was it necessary? +Why? +To bind us together forever. +Now they will do anything. +Killing of mother, father, son will be as nothing to them. +They will feel strong with power and purpose. +- Who gave you the oath? +- No one. +You never took it? +I am too old to change. +I am ready to give up my life, but I cannot give up my faith. +It is too deep, too strong. +In life and in death I will always believe in the god of my father the god who lives on Mount Kenya. +- So do I, in spite of the oath. +Your daughter carries my child. +Now, I wish to marry her before the child is born. +I consider you married. +I will gather cooking stones with my wife as my father before me gathered cooking stones with my mother. +Like you, I cannot tear out what is in my heart. +Do it quickly, then. +We need rest. +Tomorrow is the appointed day of the long knives. +Our first attack should be on the McKenzie shamba. +- Why there? +- Why not? +Look, that was my home, my friends. +A great leader has no friends, only a cause. +- You doubt my loyalty? +- I only ask you to prove it. +Let your panga come back as red as mine. +Thank you for a lovely day. +Lovely wedding day. +- No more anxiety? +- Mm-mm. +- You know why? +- Why? +Because everything's so full of life. +All the animals, the earth and even the air smells of life. +We've done nothing to spoil it. +Someday all this will be farm country. +What will happen to White Hunter McKenzie, then? +Four years ago, our crops were hit by locusts. +Wiped out. +Papa put all his savings into cattle. +The next year, rinderpest. +What cattle didn't die had to be killed. +Papa got a loan from the bank. +So part of the time, I take rich clients on safari. +For the money. +To pay back the loan. +So the land's good to us this year and the crops hold up, no locusts, no rinderpests I'll be back where I really belong. +On the farm. +You know, that's the most wonderful wedding present you could ever give me. +- Are you as happy as I am? +- I'm a very lucky man. +I have the two women I love most in the world. +- Who's the other one? +- Africa. +There are some things I can do for you that Africa can't. +What is it? +I don't know. +Something strange. +Well, I didn't hear anything. +I'm not certain. +It was something. +Just a feeling, I guess. +I wonder what's happened to the porch light. +Probably the fuse again. +I'll have a look at it. +Hey, what the...? +Ugh! +KIMANl: +Remember me? +Kimani. +- What do you want? +- I've come home. +Jeff! +KIMANl: +No. +Kimani. +Jeff Newton and two of his children dead. +His wife, Elizabeth, in critical condition. +On the open highway to Nanyuki in broad daylight Joe Matson and Mrs. Matson were ambushed while motoring. +Mrs. Matson was killed by machine-gun bullets. +Chief Waruhiu, leader of the anti-Mau Mau movement was murdered at Kiambu. +MEYLl: +Yes, bwana. +Were you in your hut last night? +MEYLl: +Yes. +It's lucky your father and the one boy were out visiting. +Where is Jeff and the kids? +What's your name? +MEYLl: +Meyli. +Who was with you? +MEYLl: +My husband and my children. +And the mother of my husband. +Did you ever attend any Mau Mau meetings? +MEYLl: +No, bwana. +Next, please. +Mrs. McKenzie, what type blood are you? +- Type O. +- Come along, please. +Hurry. +Anybody else here with type O blood? +Peter? +Lathela is, I think. +Which one of you is known as Lathela? +Is that you? +Come with me. +We need blood to help Memsahib Elizabeth. +Papa. +Why Elizabeth? +Why the kids? +Why? +A state of emergency now exists in Kenya. +Kikuyus are being sworn into a terror organization called Mau Mau. +Small gangs are fighting guerrilla warfare. +There may be Mau Mau on your farms, in your cities, in your homes. +Any African found with a gun may be punished by death. +Peter, why do you have to go? +We've been over this a dozen times. +I have to go, that's all. +Yes, but there's the army... +The army is inexperienced in the mountain and the bush country. +- How long will you be away? +- I don't know. +What am I supposed to do while you're gone? +What the rest of the women are doing, help keep the place going. +Peter. +It wasn't very much of a honeymoon for you, was it? +Are you very afraid? +No, not of them. +Only for us. +It's us I'm afraid for, what will happen to us. +Mau Mau working underground everywhere. +Maybe right here in this room, for all we know. +Now, the government wants information. +Who's forging the ammunition permits? +Who's supplying the guns? +Who's giving the oaths? +So it's prisoners we're after. +It's your job to track them down. +I say kill them, make it open warfare, bomb them out. +Kill whom, all 6 million Africans in Kenya? +We're only 40,000. +That makes the odds about 150-to-1. +That's not the point. +We're not at war with the Kikuyu nation. +We're fighting Mau Mau. +For every one of us, they've killed a hundred Kikuyus. +- Loyal Kikuyus. +- They don't know what loyalty means. +Now, listen, man. +They're trying to drive us out. +What are we to do? +Pack up because their grandfathers were here first? +I was born here too. +This is my country. +Killing's no answer. +We gotta give the African a chance... +Black man's had Africa for years. +It'd be a jungle if we hadn't moved in. +It's not a question of black or white. +That's exactly what it is. +Black or white. +You'll follow orders or keep out of this. +Well? +All right. +I'll try it your way for a while. +No smoking. +And no fires for cooking. +Whiskey? +Jeff. +Talk to me, Papa. +I don't know what to say. +Anything, Papa. +Anything at all. +This off-season rain it should do a lot of good. +You're doing a big job, child. +Like my Caroline, a long time ago when the country was new. +She was delicate, but strong, like you. +She helped to make the land and hold it. +Like you. +No, Papa, not like me. +I'm weak. +I'm weak and I'm afraid and I'm lonely. +Papa. +Who said you could get out of bed? +I want to go to Nairobi to see the doctor. +Is it your arm again? +I know you'll think I'm mad but I'm going to have another baby. +You see, if there's any chance of it being born... +Well, I mean, after losing so much blood and... +And I want this baby, Papa. +More than I've ever wanted anything. +It'd be a little bit more of Jeff and... +Holly, will you take me in to the doctor in the morning? +Hey, you, listen carefully. +You are surrounded by police. +Lay down your guns. +Listen carefully. +Lay down your guns. +You are surrounded by police. +All right. +Waithaka, do you know any of these people? +- Next. +- A good farmer, no Mau Mau. +- No? +- No, bwana. +You see? +Njogu, soldier of god. +How long were you in the mountains? +One year. +Do not hurt me, bwana. +Who gave you the oath? +I do not know. +If you lie to me again, I'll kill you. +Now who was it? +Who made you swear to the oath? +Waithaka. +Help me. +Help me. +Waithaka. +- Help me. +- The woman lies. +I never saw her before, never. +I swear. +By my father, I swear. +Here's one of your loyal Kikuyus. +All right. +We'll start again. +- You gave the oath to the girl? +- No. +- She knew your name. +How? +- She's the wife of my brother. +- Who gave you the oath? +- It was dark and raining, I could not see. +How do you Mau Mau do it? +Since when do we use torture? +The Mau Mau do it. +They love it. +- You might even grow to love it yourself. +- I don't like it any more than you do. +But I don't like what happened to Matson's wife. +Or your family. +Or any families to come. +We're not such a big jump away from being savages ourselves, are we? +Please. +Please let me point him out from here. +Please let me. +This is the man. +- Your name. +- Njogu. +Is he the one? +Is he the oath-giver? +You said his name was Njogu. +You said he was here. +He spoke truly. +I gave the oath to him, to all of them. +They know nothing. +And from me, you will get nothing. +Do not let me stay... +Do not let me stay here. +You promised, bwana. +You promised, you promised, you promised. +Who is it? +Uncle Peter. +Excuse my appearance. +I need a drink. +- I beg your pardon. +- Let me help you, son. +That's right. +Absolutely right. +You're gonna help us all. +I need your help. +Government needs help. +Everybody needs help. +It's a big secret job. +Very important. +Toast. +Toast. +I don't think he's taken off these clothes since he left home. +He probably never had a chance. +Thank God he's all right. +Holly strange things happen to people in war. +- Inside, I mean. +- Not between us. +- He'll be the same as always, you'll see. +- Nothing's ever the same. +That's one thing you can't do, stand still. +Look, his sock has rotted away inside his boot. +I'd forgotten how good our earth feels. +So rich and full of life. +Can you hear the soil through my fingers? +No. +What's it saying? +How much I love you and miss you and need you. +Last night, I thought... +Last night I had a nightmare and it was... +It was a nightmare. +Somebody will see us. +Does it matter? +It isn't the same, is it? +Yes, Holly. +You make me feel ashamed. +We waited lunch for you. +- Sorry. +- Finally gave up. +I didn't realize the time. +Daydreaming? +Yes. +You can pick your dreams in the daytime. +I'm sorry you've gotta go tonight. +So am I. +It's not fair to Holly. +She's carrying a pretty heavy burden. +No more than you or a dozen other women around here. +It's not easy for Holly looking after Papa and little Jeff and me. +It's not easy going to bed with a rifle by your side night after night instead of a husband never knowing if you're going to see daylight again. +Never laughing. +Never loving. +Never knowing if the next footstep on the porch is yours or... +You're her whole life, Peter. +Don't shut her out. +I feel empty. +Dead. +It's not so bad in the daytime, in the clean hot sun. +But when it grows dark I'm afraid, I guess. +And then when I think of Holly and how much I want her and when it's the moment to touch her and be with her, I can't. +I just feel dirty, I feel unclean. +Filthy business we're in. +Time will wash it clean. +Who knows how much time there is left? +- Ready? +- Yes, yes. +Where's Holly? +She's in the bedroom. +Well? +Don't go. +Please, don't go. +You expect me to run out? +Yes. +Yes, together. +Somewhere far away, where there's no war. +We belong here, Holly. +Here, this is our land. +It was worked for and paid for. +Nobody's driving me off this land. +They can bury me in it, but nobody is chasing me off it. +Peter, darling, what does a piece of land matter? +Look what it's doing to us, to everybody. +- Please, take me away from here. +- This is our home. +- They say not. +- They lie. +War is filled with lies. +What they say, what we say, lies. +Our place is here. +My place is with you. +And you have no place for me. +I'm selfish. +I don't want to lose you. +Please, let's go away from here before it's too late. +Do I get the names? +The oath-givers the man who killed my wife. +Joe. +Lathela. +You are not afraid of Mau Mau? +I'm like you. +I'm too old to be frightened by men. +The wrath of God frightens me, not the brutality of men. +What do you want of me? +How is it you gave the oath to others and never took it yourself? +I believe in the faith of my father. +Good. +Who are your leaders? +Your oath-givers? +By speaking out, you can end the war between us. +You leave Africa and the war will end. +Can't we live in peace, your people and mine? +Go away. +Your soft words are sharper than blows. +Would you prefer violence? +I'm no ordinary man. +Nothing can make me speak out. +They have tried. +They could not do it. +Not with torture, not with pain. +You will fail also. +Well, that's all we needed, a spell of weather. +Ngai is angry. +What's that? +Thunder and lightning. +When it storms, the Kikuyu believes he is face-to-face with god. +Thunder is the sound of god cracking his joints preparing for battle. +The lightning is god's sword of retribution. +You talk as if you believed that black hogwash yourself. +The important thing is whether our friend in there believes it. +If he does... +You'll never break him with mumbo jumbo. +His kind understands only one thing: +Force. +- Kill him, you make a martyr of him. +- He'll be dead. +Hold it, Joe. +Go ahead, Henry. +You gotta fight an idea with a better idea. +With the help of this weather, and if I know my man... +Well, give me one more go at him. +Tell me, Ngai, if I do right. +I only wish to do thy will. +Give me a sign that I may know. +Lathela, get some kerosene and dry wood. +- I am not afraid to face god. +- We will see. +I am the messenger of god. +Did god create Mau Mau? +Mau Mau is the will of god. +Did god tell you to mutilate innocent children? +Did Gikuyu and Mumbi ever violate animals? +Since the creation of Mount Kenya has god ever told you to steal and murder and burn and hate? +Is it the will of god that you eat human flesh and blood? +- I swear that... +- Wait. +Let your swearing have value in the eyes of god. +Swear by your sacred Githathi stone. +Hold this symbol of God in your hands and swear. +Then I'll believe you. +Now begin at the beginning. +Did you ever take the Mau Mau blood oath yourself? +- No. +- I believe you. +- Did you give the oath to others? +- Yes. +- By force? +- Yes. +You swore to drive the white men out of Africa, didn't you? +- Yes. +- Did God tell you to create Mau Mau? +Say yes before God and I'll believe you. +I've said enough. +You are afraid to face your god. +- If Mau Mau drives us out, then what? +- Then freedom. +- And faith in god too? +- Yes, yes. +How? +What faith? +Mau Mau, the promise to murder? +Will god take back the people who've eaten the blood oath? +That's why you didn't take the oath yourself, isn't it? +Because you wanted to be able to come back to god. +Yes, Ngai, I come to you faithful with no other gods before you. +But you've broken every law of your god. +Tell him that too. +Tell him you gave the blood oath to others by night, by force. +That you gave it before witnesses, gave it to women and children. +These are the worst violations. +How can you lead your people back to god? +Even tonight, more of your people are being oathed banished from the house of god cursed to live through eternity as a broken-spined hyena. +Is that the future for your people? +Is it? +Is that what you want? +No. +Who's the oath-giver in Nairobi? +Who is he? +If god cannot accept Mau Mau, Mau Mau cannot lead your people. +In Nairobi, his name is Timbu. +Who gives the oath in Thomson's Falls? +Lorry driver for Bwana Wilson. +Nyeri? +They are even in the home guard. +Are Mau Mau in our telephone service? +- Yes. +- Code words for guns? +- Mti, tree. +- Ammunition? +Makaa, charcoal. +The McKenzie shamba, who led the attack? +The... +The husband of my daughter. +His name? +Kimani wa Karanja. +The capture of a high-ranking oath administrator has led to the arrest of many Mau Mau in the Nyeri District. +Loyal Kikuyu witnesses are cooperating by pointing out those Africans who have taken the blood oath. +Witnesses wear white hoods to conceal their identities. +Shantytown in Nairobi, cesspool of intrigue and resistance is being flattened and razed. +Ready? +- Where do you think you're going? +- To find Kimani. +I can't spare the men for that chase. +- Just Lathela and I. +- And when you find him, then what? +- Ask him to surrender. +- Why should he? +Because I know Kimani. +Because he wants peace as much as we do. +Peace? +You said surrender. +Peace means terms. +What terms? +His precious life? +A seat in parliament? +You and your pet black boy. +You're just a black liberator, aren't you? +All right, all right. +What terms? +The lives of his people. +- What can we lose by trying? +- Did this Kimani take the oath? +The old man says yes. +You wouldn't have one chance in a thousand of coming out alive. +The emergency operations now cost the government more than a million pounds every month. +Several farmers in the Nyeri District have quit their farms and returned to England. +Mau Mau gangs are being forced deeper into the Aberdare Mountains. +The flare, Papa. +Send up the flare. +Elizabeth. +Jeff. +Where's Jeff? +Tomorrow, you can take Elizabeth into Nairobi. +To the hospital. +And leave here? +It's to help Elizabeth. +We'll get you a little flat in town and you can come and see me every day. +Yes. +Yes, I'd like that. +Are you all right? +No one came here. +Did you make contact? +Well? +Did you see Kimani? +Will he come? +He's a big general now. +I do not know if he will come. +And if he come, I do not know if it is to speak or to kill. +I do not know how a general thinks. +KIMANl: +Put down your gun. +Kimani? +KIMANl: +The guns. +And the pistol too. +The pistol. +Now, tell Lathela to build a fire. +Why? +I want my comrades to see you. +We're alone, you have nothing to fear. +I know this. +You have tobacco? +- Cigarettes. +- Pass them here. +Why did you come? +- Can we not talk face-to-face? +- No. +- Njogu is our prisoner. +- I know. +He confessed many things, told us many names. +- I know. +- He is not harmed. +Then why did he turn against us? +Njogu was braver than any of us. +He was not afraid to die. +He was afraid for his soul. +Can you understand that? +Yes. +The people he named have been arrested. +- I know. +- You know the war goes badly for you. +It is possible to lose a battle and still win a war. +Must Africa always stink of death? +Can we not live together as friends? +- Friends have equal rights. +- They will come. +Only when we take them. +- I think we're ready to give them. +- What do you want of me? +Give up. +Surrender. +Bring in your people. +Surrender? +Peace. +On what terms? +Justice. +Understanding. +If you stop fighting, others will do likewise. +You must have faith. +You must try. +We have tried before. +Then try again. +And again and again and again. +Do you not love anyone? +Your wife? +Children who believe in you? +You know of my child? +No. +A man-child? +Yes. +He will find a better world than you and I. +I sometimes dream of when we were children, you and I. +- Peter? +- Yeah. +I've not said that name in many years. +How goes it with your father? +As well as age will allow. +He was a good man. +He's a friend of my father. +Yes. +And Memsahib Elizabeth? +She is with child. +- Peter? +- Yes. +I did not hurt her. +I did not hurt her or her children. +It was not my hands that struck them. +I believe you. +What's happened to us? +When did this hatred begin? +Before we were born, I think. +I will talk with my people. +I will tell them that I trust you. +But they must decide for themselves. +This will take time. +Four days hence, you will have your answer. +If they agree we will come to the meadow by the hidden spring. +- You know of it? +- Yes. +- You will be there? +- Yes. +Until then. +Kimani. +Grandpa. +Peter. +- So you pulled it off. +- Yes. +- I wanna hear about it. +You like a drink? +- No, thank you, later. +Holly? +Holly? +Holly is with Elizabeth in Nairobi. +Oh... +- You see, we had another raid here. +- I know. +I asked her to go. +- Don't blame her, son. +She was... +- Thanks, Papa. +What we do is stupid. +To surrender betrays everything we have done. +Our children need food, our sick need medicine. +All we need is courage. +Let me talk to them. +You cannot talk to a starving people. +Their belly have no ears. +And if they shoot us down? +No, I have the word of my friend. +Your friend is a white man. +He hates us. +It is your own hatred that you see in others. +Holly. +Sister Williams. +I called at your flat. +You shouldn't go into Elizabeth's right now. +Anything wrong? +No, she's just a little overdue, that's all. +There's nothing to be alarmed about. +You're looking... +You're looking thinner. +You don't look so bad yourself. +Was it very bad? +Some days are good, some bad. +- No, they'll see us. +- Let them. +Do you have to go back? +Tonight. +Oh, I wish I could go with you. +We'll go away soon in that honeymoon we never had. +We don't have to go away to be on a honeymoon. +But I thought you wanted to... +To run away? +Yeah. +Just when was that? +Let's see, about a month ago? +At least a hundred years. +I want to go home to our home. +With Mount Kenya and God in the garden. +The war may not be over for a long time. +I used to blame the war for everything, didn't I? +Somebody else's war is always to blame. +No, I was to blame. +When you grow up, you realize you can't run away from the world. +You just gotta live in it. +You're a big girl now. +I'm beginning to understand about that other woman too. +- What other woman? +- Africa. +Oh. +She's not the least bit jealous. +And neither am I. +Excuse me. +Your boy, Lathela, he says you have to start off for somewhere or other. +Thank you. +See you soon. +Please, God, let it be soon. +Can't you make this thing go faster? +We've got to get there by daylight. +Why? +It's almost impossible. +- But if Kimani shows... +- He set no hour. +He'll wait for us. +Yes, but will Joe Matson wait? +- Matson? +- He got wind of it somehow. +You should have stopped him. +I only heard about him myself about an hour ago. +How do you keep a thing like this secret? +How do you keep Matson off the trigger? +This won't be any ceasefire, it'll be cold-blooded murder. +Doctor? +Yes? +Is there any marks? +Just the mark of a man. +Look at this place. +It's a perfect trap. +What are we supposed to do? +Wait around till they show up? +We'd be caught in the open. +It's a perfect trap, I don't wanna get caught. +- If they show, it'll be to surrender. +- How do you know? +But they gave their word. +I'm taking cover. +You know how Joe is, always suspicious. +I know how Mau Mau is too. +Where is your friend? +You there, all of you, put down your guns. +Wait. +Please. +Yeah, we lost him all right. +Come on. +- When we find Kimani, will you kill him? +- No. +Then why do we hunt him? +He must not think I betrayed him. +If he trusts us, others will do likewise. +If he escapes, if he does not believe Mau Mau will fight harder and longer. +Kimani will not surrender peacefully. +Not this time. +- He will try to kill you. +- Perhaps. +- Don't come along. +- I come with you. +- Why? +- This is my fight too. +Mau Mau has killed a hundred of my people for every one of yours. +I want the same thing for the African that Kimani wants. +Mau Mau is not the way to get them. +Kimani? +Stay here and don't move. +And don't shoot. +- Let me talk to you. +- No! +You kill my wife and my people. +We were betrayed. +Both of us. +I'm here without a weapon. +Are you alone? +Lathela is here too. +I'm coming in. +Keep away. +Kimani. +Don't make me do it. +Come back with me. +No. +We'll start over again. +- This time, it'll be different. +- No. +It is too late. +For you and me. +It is too late. +Must I kill you? +Yes. +Give me the child and bury us both. +No. +Please. +He is dead. +- What will you do with the child? +- Take him home. +Elizabeth has a boy, raise them together. +Maybe for them, it'll be better. +It's not too late. +Subtitles by SDI Media Group +Darling. +- Papa, have I kept you waiting? +- No, that's all right. +Come on. +- Why isn't Peter here? +- He's playing with Kimani, Papa. +That brother of yours and that Kyuke are inseparable. +Can't he find a white playmate? +Why? +You can't treat an African like a brother and expect to have a good servant. +When Caroline died, Kimani's mother raised Peter. +In a way, they are brothers. +When do you leave for England? +Tomorrow, worst luck. +I'm homesick already. +A few years of school... +You won't let him marry anybody but me, Mr. McKenzie, will you? +Has he proposed? +No, but I have, quite often. +Which of you stole the rifle? +Step forward. +Your religion says it is evil to steal. +Your own medicine shall name the liar. +If you tell the truth, this will not burn your tongue. +He who lies burns. +Peter? +Kimani, my son, shall be the first. +Did you steal that gun? +Did you steal the gun? +Did you steal the gun? +Did you steal the gun? +I will find the weapon and bring it to you. +Punish him yourself. +The city teaches bad ways to young men. +How does it go with your wife? +The wife with child? +Tomorrow, the day after... +The time is near. +Papa. +- How does it work? +- Plain old witchcraft. +The Kikuyu is a very religious man. +He fears God, but he trusts him too. +- But hot steel is... +- Will not burn a wet tongue. +But the liar's spit dries up. +Him it will scorch. +Ha-ha-ha. +I think you know more about black witchcraft than you do about the Bible. +- Let me have my way with these devils... +- Poor old Jeff is the perfect colonizer. +What's his is his and what's theirs is his too. +Well, have a good shoot. +We're not raising cattle to feed a maverick lion. +Kimani, Lathela. +Tell Kimani not to gut him. +We'll leave a smelly calling card for the lion. +Kimani, open the animal, but don't clean him. +Then you'd better service the guns. +When it comes time to kill the lion, I want to shoot the gun too. +It's Jeff's show. +And you know how he feels about Africans and guns. +KIMANl: +I want to shoot the gun too. +I'm sorry. +Lathela. +KIMANl: +Always when we hunt it is the same. +You have all the fun, I do all the work. +When we were little and played together... +But we're big now. +And things are not the same. +Hit him. +Hit him. +Hit him hard. +Do what he says, now. +And in a hurry. +From now on, when he tells you to do something, do it. +Don't think about it, just obey. +Understand me? +Well? +Come on, Peter. +I really should've slapped you. +Might have been better all around if you had. +Heh-heh. +Forget it. +You had no right to hit Kimani. +Peter, how many times have I got to tell you? +Blacks are blacks and not playmates. +One thing you can never do is argue with them. +Never. +You tell them. +Oh, sometimes you can joke with them you can boot them in the tail sometimes look after them when they're sick. +But you never, never argue with them. +- The world's changing, Jeff. +- Not in Africa it isn't. +Kimani's mother raised both of us. +We grew up together. +You'll never live together on equal footing. +Not in our lifetime. +You can't spend the first 20 years of your life with someone sharing bread and secrets and dreams, and then one day say: +"Sorry, it's all over. +We live in different worlds". +I don't believe it and I don't like it. +Wait till you settle down and marry Holly and have to deal seriously with the wogs. +Have you heard from Holly? +A couple of letters from London. +She mentioned coming back? +Just stuff about school, things like that. +Hm... +Well, we'd better break camp and go after that lion. +Lathela. +Get Kimani to help you load. +Kimani not here. +Where? +Forget that lion, Jeff. +We're gonna find Kimani, and right now. +All right, all right, all right. +You want Lathela with you? +No, you'll need him to track. +I'll meet you back here at sundown. +- Are you all right? +- Yes, bwana. +- Does it hurt much? +- No, bwana. +You're lying. +- And stop calling me bwana. +- What shall I call you? +"Boss"? "Master"? +Yes, it hurts. +Not where the trap cut me only where Jeff slapped me. +That is where it hurts. +Well, then stop thinking about it. +No one ever struck me in anger before. +Not even my own father. +It wasn't in anger. +He's already forgotten. +Can you forget it? +I cannot forget it either. +We are alike in many things. +You talk Kikuyu same as me. +I speak English same as you. +But you are white and I am black. +And you are the bwana and I am the servant. +And I carry the gun and you shoot. +- Why is shooting the gun so important? +- It's not the gun, it is... +What is it, then? +What? +We cannot talk as friends. +Why? +You said it yourself. +We are not children anymore so we are not friends anymore. +I saved your life as a friend. +I'll always be your friend. +Kimani... +Does it hurt much? +No. +The child doesn't come easily. +It is a curse. +This morning, I saw the dung of a hyena. +Just now a vulture passed over us. +Don't you talk like that. +Just don't you talk like that. +- Suppose the child is born feet first. +- Then it must be killed. +When that child comes, don't you touch it. +You understand? +It is you who do not understand. +I'm gonna fetch my father. +White magic will not remove the curse. +- Perhaps the curse is in your son? +- What evil did he do? +Suppose a snake came into his bed. +Suppose a man struck him and he did not strike back. +Suppose he broke a law. +The child enters life feet first. +Do what must be done. +Kimani. +Swear him in. +- Which god, please? +- The Christian God. +I worship Ngai, the god who lives on Mount Kenya. +I will swear by our sacred Githathi stone. +Your word will suffice. +Oh, no, no. +If I lie before this symbol of God my children and their children and my home and my land will turn to dust. +And when I die I will have no life hereafter except to live forever in eternity by the cursed hyena, cowardly eater of the dead. +I speak the truth. +You're the father of the dead baby in question? +- Yes. +- Did you tell the midwife to kill the baby? +Yes. +It was born feet first, it was cursed. +Then what was done? +What is always done according to custom. +Tell His Honor what that is. +We smothered the child and buried it under a pot. +- You know that killing is against the law? +- God says to murder is wrong. +And when you had that newborn baby smothered, was that not murder? +No. +A child cannot join the tribe until he is 1 year old. +Therefore, he's not really born until his second year. +What was killed was a demon, not a child. +Yes, yes. +And then what did you do? +- What? +- Then what did you do? +We sacrificed a young ram. +Mm. +And that, I suppose, got rid of the curse. +No. +No, sir. +Not yet. +I am still here, therefore the curse is still at work. +Would you do the same thing if another child were born to you feet first? +Yes, yes. +It would be my duty. +What in the name of Almighty God are we trying to do to these people? +Preserve the law, Henry, that's all. +Law? +Whose law? +Not theirs, surely. +All men are equal before the law. +Except some are more equal than others. +That man is an accomplice to murder. +He's admitted that. +But can we make him understand it? +We take away their customs, their habits, their religion. +We stop their tribal dances, we stop them circumcising their women. +Then we offer them our way of life, something they can't grasp. +We say, "Look how clean and rich and clever we are". +For the Africans different wages, different life. +We mock their wise men. +Take away the authority from their fathers. +What are the children going to do? +They'll lose respect for their elders and fathers and when they do, look out. +Maybe they'll lose respect for our white Jesus too. +Turn to something else for help. +It won't be to us. +Well, you understand, don't you, Peter? +If we don't make the African respect the law well, the next thing you know, he'll be wanting to rule this country. +Imagine that, now. +Whatever could give him that idea? +This is his son. +Can he come in while we're here? +The city frightens me. +- Let us go home quickly. +- Listen, old friend. +The law says you must stay here in jail for a while. +I'm sorry. +We'll do everything we can. +My daughter will visit you. +She'll bring you tobacco and food to comfort you. +Please keep this for me. +A jail is not the proper place to keep god's sacred symbol. +And when my son comes of age... +I understand. +I am happy it was not you who struck my son. +You are still his friend? +Yes. +And yours too, for as long as you both wish it. +Boy, boy. +I told you. +He will not help you. +Our Mathanjuki will purify you. +He will drive the curse from your body and I will be free. +- No. +- You do not believe in god? +- Yes, yes. +But I do not believe in our witchcraft and black magic. +When Bwana Jeff struck you... +He struck a black man to prove that the white man is master, nothing else. +You are not in jail because of a curse but only because we are judged by their laws. +And that is the truth. +And I must follow where the truth leads me. +- Where does it lead you? +- To strike back. +We're men, not animals. +You have much to look forward to, my son. +You will become headman as I was. +Is that to be my life? +Headman for a white boss? +"Yes, bwana. +No, bwana. +Yes, bwana". +This land can serve me too. +I want my own land. +Then you must earn it. +I will, Father. +I will. +Who are you? +Who sent you here? +Why you come here? +He told me to come here. +You told me the white man would put Father in jail. +- You said we had to fight the white man. +- Your father is in jail? +- Yes, and I'm ready to fight. +- You ran away from the McKenzie shamba? +- Yes. +- Why? +- You stole money? +- No. +- Guns? +No, why should I steal? +Then why should you run? +I don't know. +This is my daughter, Wanjiru. +- He can be of no use to us. +He wants to fight the white man. +We can use him. +We will take him to the mountains. +We will train him. +Come, little boy. +First you will learn to steal guns. +Hm? +I have no parents and I am hungry. +I need work. +Not a sound. +Nothing. +Do not call. +Do not answer. +Do not cough or I kill you. +Understand? +You are not alone? +How many are there? +One other? +The houseboy? +You will call him by name. +Nothing else, just the name. +Call him. +Migwe. +Migwe. +This boy is dead. +Nanyuki Police signing off, 1545. +- Hello, Peter. +- I need some help, Hillary. +If it's about the sentence of your headman... +His son, Kimani. +He's missing. +- When? +- Last night. +I want him found. +- What did he steal? +- Steal? +You want him found, what are the charges? +- He might be hurt. +- You check the infirmary? +And I've chased down his family within a hundred miles. +He'll show up. +He probably went to Nairobi on a toot and... +- Age? +- Twenty-one. +- Height? +- Six-two, weight a little under 13 stone. +Wait a minute. +There was a houseboy killed last night. +Buxton shamba, at the foot of the Aberdares. +A gang broke in, stole guns and whiskey. +- What's that got to do with Kimani? +- Maybe nothing. +Maybe everything. +- Not a chance. +- Why not? +I know Kimani. +I know how he thinks. +He's not a criminal. +You mean not yet. +You just find him. +At least send out a description. +Kimani's guilty of only one thing, captain. +Guilty of being born black. +Take one. +Why that gun? +My friend Peter has a gun like this. +It is a fine gun. +I can kill a lion with this. +Or even a man, huh? +There will be no drinking here again. +Never. +Adam is our leader. +Who are you to tell us what...? +Daughter, ask the other women where to go and what to do. +Kimani. +I see you have earned a gun. +This gun. +To get some of these guns, one of our own people was killed. +When lightning strikes, a bystander may be hurt. +Lightning belongs to god. +This was murder by him. +It was the will of god. +No. +I do not like your ways. +Sit down. +I go to Nanyuki. +I work there to free my father in my own way. +Sit down. +Two reasons why you cannot leave us. +That houseboy. +That houseboy who was killed last night, Adam can hang for this. +So can you. +So can all of us. +- That is the law. +- Reason two. +You know our names and our faces. +You know where we live and how we live. +We would be safe only if you stay with us. +Or if you were dead. +We will not always live as hunted animals. +Great men make plans for us. +Plans to drive the white man from our country. +Plans to take back our land. +Plans to... +Flight 212, BO AC arriving from London, Rome, Athens, Cairo, Khartoum. +- Cigarette? +No. +- Dad? +- No, thanks. +Flight 212 departing for Dar es Salaam, Johannesburg and Jamestown. +There. +Two-one-two departing for Dar es Salaam, Johannesburg and Jamestown. +Each to their own. +Holly, I... +Six years is a long time. +Too long? +You'd better see to her luggage. +- Can't I watch too? +- It's indecent. +That's why I want to watch. +Oh, really. +Kimani. +Hey. +Kimani. +Strange. +I thought I saw Kimani. +You remember Kimani? +Move. +Start moving. +Would you mind letting us by, please? +I've come to pray. +This is not a church. +My god does not live in a church. +How do you call yourself? +Kimani wa Karanja. +We are beggars and slaves in our own land. +The British allow us in their homes and hotels, yes. +But how? +As servants. +We are millions, they are a handful. +We are strong, they are weak. +How then are they the masters and we the slaves? +Is it white magic? +Is it god's will? +No. +They have the guns. +We too shall have guns. +Are we ready for this? +The whole colored world burns with the fever of revolt with the fire for freedom. +Do any of you have any questions? +Is there a doubt in your hearts? +What troubles you? +Kimani. +His name is Kimani wa Karanja. +For five years, he has been in the mountains with us. +He is ready for leadership. +He is very strong and loyal. +Strong men have betrayed us before. +- You have a question, Kimani? +KIMANl: +Yes, sir. +- This talk of guns. +Yes? +Is this the only way we can get freedom? +Yes. +- By the spilling of blood? +- Yes. +We will never drive the British out with words. +And not with doubts and not with friendship. +It can only be done with guns. +The white man did not take this land with guns. +He bought this land. +- This is truth. +- Mm-hm. +And I must follow where the truth leads me. +You were educated in white missionary schools? +Yes, sir. +Long, long ago, to whom did the land belong? +- The people. +- Yes. +Not one person, but the entire clan. +And therefore only the clan can sell the land correct? +- Yes, sir. +No man of any other tribe can buy our land unless he becomes, in our religion, a Kikuyu. +Yes, sir. +And have the British ever become Kikuyus? +Or have you become one of the British? +Your father was a friend of the British. +But your father died in their prison. +There is only one way to drive out the British. +By terror and death. +Everyone must either be for us or against us. +Those who be with us, stand. +Good. +We will need a symbol, a sign, a name. +Here it is. +Mau Mau. +Mau Mau. +Use it, live by it, die for it. +Mau Mau is the machinery that will carry us to freedom and independence. +Mau Mau. +Mau Mau. +I swear to kill an Englishman or may this oath kill me and my family. +I swear to kill an Englishman or may this oath kill me and my family. +- They make a nice couple, don't they? +- Mm. +She's got good lines for breeding too. +Look. +Mount Kenya. +Lathela, wait here. +No wonder the African believes that God lives on Mount Kenya. +If I were God, that's where I'd like to live. +I feel I'm really home now. +I love you, Peter. +I always have. +I suppose I always will. +I like the feel of you. +I wish... +Yes? +I wish it could always be like this moment. +Safe and warm and peaceful. +Always like this. +Home is always like this. +Why did your husband run away? +Did he steal? +Did he do something bad? +Where did he go? +Why didn't you go with him? +- I was afraid. +- Afraid? +Afraid of what? +Hello, my darling. +Hello, my darling. +What did you bring? +Hello. +You didn't forget my rifle? +Yes, it's right here. +Henry. +Bring the children in. +Bring them in. +What do you think? +What's it mean? +I don't know. +Two Kyukes disappear from my place. +Jasper, his headman reports one gone from his farm, rifle missing too. +One gone from your place. +Why? +You saw his wife. +She's afraid. +Why? +What of? +Come in. +According to Kikuyu custom we come to speak for Peter McKenzie, bachelor to Holly Keith, spinster. +- This shy Kikuyu maiden is grateful. +- She doesn't look very shy to me. +How many goats will be paid for me? +Three or four ought to be quite enough, don't you think? +Oh, I'd say 20 or 30 at least. +Why don't you throw yourself in and make it 31 goats? +And why has Peter wa Henry chosen me? +He needs someone to chop firewood and dig potatoes. +He needs someone to keep his bed warm. +- He promises not to beat you often. +- Unless it's absolutely necessary. +- He also expects a child every year. +- All of them his. +- A very narrow attitude. +- We shall also have to shave your head. +Do you accept my son? +If you do, we'll drink to the marriage bargain. +If you don't, I shall have to pour this on the ground. +And waste all that precious gin? +Thank you for becoming one of our family. +You will swear a new blood oath. +When it is done, you will be part of the new army: +Mau Mau. +He who refuses to take the oath he dies. +He who breaks the oath he dies. +Cut off the sheep's head. +Fill this calabash with its blood. +Sugar cane. +Sugar cane and banana leaves the first source of food. +Mugere plant best and strongest magic. +The arch oldest Kikuyu symbol. +You will pass through the arch seven times and thereby enter a new life. +You will receive seven cuts on the arm to bind you together. +Seven. +All things in seven. +Seven, the unlucky number. +Break the oath and the evil seven will strike. +Sheep's blood symbol of sacrifice. +Millet seeds of nourishment. +Earth the earth we fight for. +The cause that brings us together. +You will eat this oath. +You will swallow it seven times so that it becomes part of you. +Bitter Sodom apples. +Take off everything that stinks of the European. +Watch, ring, money. +To give you an easy road. +The endless circles. +Earth. +Hold it to your belly. +That the land may feed us and not the foreigners. +Hold up your arm. +So that your blood will mix. +Now swallow the oath seven times. +Repeat after me as you pass through the arch. +If I sell land to any foreigners, may this oath kill me. +If I sell land to any foreigners, may this oath kill me. +- I will steal guns. +- I will steal guns. +I will never be a Christian. +I will never be a Christian. +I will drive out all Europeans or kill them. +I will drive out all Europeans or kill them. +It is done. +They've all sworn. +I feel unclean. +I will not let Wanjiru take this oath. +It is not necessary. +She is loyal. +To swallow the oath was hard enough, but the rest of it... +The nameless filth, the shame. +And in front of the others. +Why was it necessary? +Why? +To bind us together forever. +Now they will do anything. +Killing of mother, father, son will be as nothing to them. +They will feel strong with power and purpose. +- Who gave you the oath? +- No one. +You never took it? +I am too old to change. +I am ready to give up my life, but I cannot give up my faith. +It is too deep, too strong. +In life and in death I will always believe in the god of my father the god who lives on Mount Kenya. +- So do I, in spite of the oath. +Your daughter carries my child. +Now, I wish to marry her before the child is born. +I consider you married. +I will gather cooking stones with my wife as my father before me gathered cooking stones with my mother. +Like you, I cannot tear out what is in my heart. +Do it quickly, then. +We need rest. +Tomorrow is the appointed day of the long knives. +Our first attack should be on the McKenzie shamba. +- Why there? +- Why not? +Look, that was my home, my friends. +A great leader has no friends, only a cause. +- You doubt my loyalty? +- I only ask you to prove it. +Let your panga come back as red as mine. +Thank you for a lovely day. +Lovely wedding day. +- No more anxiety? +- Mm-mm. +- You know why? +- Why? +Because everything's so full of life. +All the animals, the earth and even the air smells of life. +We've done nothing to spoil it. +Someday all this will be farm country. +What will happen to White Hunter McKenzie, then? +Four years ago, our crops were hit by locusts. +Wiped out. +Papa put all his savings into cattle. +The next year, rinderpest. +What cattle didn't die had to be killed. +Papa got a loan from the bank. +So part of the time, I take rich clients on safari. +For the money. +To pay back the loan. +So the land's good to us this year and the crops hold up, no locusts, no rinderpests I'll be back where I really belong. +On the farm. +You know, that's the most wonderful wedding present you could ever give me. +- Are you as happy as I am? +- I'm a very lucky man. +I have the two women I love most in the world. +- Who's the other one? +- Africa. +There are some things I can do for you that Africa can't. +What is it? +I don't know. +Something strange. +Well, I didn't hear anything. +I'm not certain. +It was something. +Just a feeling, I guess. +I wonder what's happened to the porch light. +Probably the fuse again. +I'll have a look at it. +Hey, what the...? +Ugh! +KIMANl: +Remember me? +Kimani. +- What do you want? +- I've come home. +Jeff! +KIMANl: +No. +Kimani. +Jeff Newton and two of his children dead. +His wife, Elizabeth, in critical condition. +On the open highway to Nanyuki in broad daylight Joe Matson and Mrs. Matson were ambushed while motoring. +Mrs. Matson was killed by machine-gun bullets. +Chief Waruhiu, leader of the anti-Mau Mau movement was murdered at Kiambu. +MEYLl: +Yes, bwana. +Were you in your hut last night? +MEYLl: +Yes. +It's lucky your father and the one boy were out visiting. +Where is Jeff and the kids? +What's your name? +MEYLl: +Meyli. +Who was with you? +MEYLl: +My husband and my children. +And the mother of my husband. +Did you ever attend any Mau Mau meetings? +MEYLl: +No, bwana. +Next, please. +Mrs. McKenzie, what type blood are you? +- Type O. +- Come along, please. +Hurry. +Anybody else here with type O blood? +Peter? +Lathela is, I think. +Which one of you is known as Lathela? +Is that you? +Come with me. +We need blood to help Memsahib Elizabeth. +Papa. +Why Elizabeth? +Why the kids? +Why? +A state of emergency now exists in Kenya. +Kikuyus are being sworn into a terror organization called Mau Mau. +Small gangs are fighting guerrilla warfare. +There may be Mau Mau on your farms, in your cities, in your homes. +Any African found with a gun may be punished by death. +Peter, why do you have to go? +We've been over this a dozen times. +I have to go, that's all. +Yes, but there's the army... +The army is inexperienced in the mountain and the bush country. +- How long will you be away? +- I don't know. +What am I supposed to do while you're gone? +What the rest of the women are doing, help keep the place going. +Peter. +It wasn't very much of a honeymoon for you, was it? +Are you very afraid? +No, not of them. +Only for us. +It's us I'm afraid for, what will happen to us. +Mau Mau working underground everywhere. +Maybe right here in this room, for all we know. +Now, the government wants information. +Who's forging the ammunition permits? +Who's supplying the guns? +Who's giving the oaths? +So it's prisoners we're after. +It's your job to track them down. +I say kill them, make it open warfare, bomb them out. +Kill whom, all 6 million Africans in Kenya? +We're only 40,000. +That makes the odds about 150-to-1. +That's not the point. +We're not at war with the Kikuyu nation. +We're fighting Mau Mau. +For every one of us, they've killed a hundred Kikuyus. +- Loyal Kikuyus. +- They don't know what loyalty means. +Now, listen, man. +They're trying to drive us out. +What are we to do? +Pack up because their grandfathers were here first? +I was born here too. +This is my country. +Killing's no answer. +We gotta give the African a chance... +Black man's had Africa for years. +It'd be a jungle if we hadn't moved in. +It's not a question of black or white. +That's exactly what it is. +Black or white. +You'll follow orders or keep out of this. +Well? +All right. +I'll try it your way for a while. +No smoking. +And no fires for cooking. +Whiskey? +Jeff. +Talk to me, Papa. +I don't know what to say. +Anything, Papa. +Anything at all. +This off-season rain it should do a lot of good. +You're doing a big job, child. +Like my Caroline, a long time ago when the country was new. +She was delicate, but strong, like you. +She helped to make the land and hold it. +Like you. +No, Papa, not like me. +I'm weak. +I'm weak and I'm afraid and I'm lonely. +Papa. +Who said you could get out of bed? +I want to go to Nairobi to see the doctor. +Is it your arm again? +I know you'll think I'm mad but I'm going to have another baby. +You see, if there's any chance of it being born... +Well, I mean, after losing so much blood and... +And I want this baby, Papa. +More than I've ever wanted anything. +It'd be a little bit more of Jeff and... +Holly, will you take me in to the doctor in the morning? +Hey, you, listen carefully. +You are surrounded by police. +Lay down your guns. +Listen carefully. +Lay down your guns. +You are surrounded by police. +All right. +Waithaka, do you know any of these people? +- Next. +- A good farmer, no Mau Mau. +- No? +- No, bwana. +You see? +Njogu, soldier of god. +How long were you in the mountains? +One year. +Do not hurt me, bwana. +Who gave you the oath? +I do not know. +If you lie to me again, I'll kill you. +Now who was it? +Who made you swear to the oath? +Waithaka. +Help me. +Help me. +Waithaka. +- Help me. +- The woman lies. +I never saw her before, never. +I swear. +By my father, I swear. +Here's one of your loyal Kikuyus. +All right. +We'll start again. +- You gave the oath to the girl? +- No. +- She knew your name. +How? +- She's the wife of my brother. +- Who gave you the oath? +- It was dark and raining, I could not see. +How do you Mau Mau do it? +Since when do we use torture? +The Mau Mau do it. +They love it. +- You might even grow to love it yourself. +- I don't like it any more than you do. +But I don't like what happened to Matson's wife. +Or your family. +Or any families to come. +We're not such a big jump away from being savages ourselves, are we? +Please. +Please let me point him out from here. +Please let me. +This is the man. +- Your name. +- Njogu. +Is he the one? +Is he the oath-giver? +You said his name was Njogu. +You said he was here. +He spoke truly. +I gave the oath to him, to all of them. +They know nothing. +And from me, you will get nothing. +Do not let me stay... +Do not let me stay here. +You promised, bwana. +You promised, you promised, you promised. +Who is it? +Uncle Peter. +Excuse my appearance. +I need a drink. +- I beg your pardon. +- Let me help you, son. +That's right. +Absolutely right. +You're gonna help us all. +I need your help. +Government needs help. +Everybody needs help. +It's a big secret job. +Very important. +Toast. +Toast. +I don't think he's taken off these clothes since he left home. +He probably never had a chance. +Thank God he's all right. +Holly strange things happen to people in war. +- Inside, I mean. +- Not between us. +- He'll be the same as always, you'll see. +- Nothing's ever the same. +That's one thing you can't do, stand still. +Look, his sock has rotted away inside his boot. +I'd forgotten how good our earth feels. +So rich and full of life. +Can you hear the soil through my fingers? +No. +What's it saying? +How much I love you and miss you and need you. +Last night, I thought... +Last night I had a nightmare and it was... +It was a nightmare. +Somebody will see us. +Does it matter? +It isn't the same, is it? +Yes, Holly. +You make me feel ashamed. +We waited lunch for you. +- Sorry. +- Finally gave up. +I didn't realize the time. +Daydreaming? +Yes. +You can pick your dreams in the daytime. +I'm sorry you've gotta go tonight. +So am I. +It's not fair to Holly. +She's carrying a pretty heavy burden. +No more than you or a dozen other women around here. +It's not easy for Holly looking after Papa and little Jeff and me. +It's not easy going to bed with a rifle by your side night after night instead of a husband never knowing if you're going to see daylight again. +Never laughing. +Never loving. +Never knowing if the next footstep on the porch is yours or... +You're her whole life, Peter. +Don't shut her out. +I feel empty. +Dead. +It's not so bad in the daytime, in the clean hot sun. +But when it grows dark I'm afraid, I guess. +And then when I think of Holly and how much I want her and when it's the moment to touch her and be with her, I can't. +I just feel dirty, I feel unclean. +Filthy business we're in. +Time will wash it clean. +Who knows how much time there is left? +- Ready? +- Yes, yes. +Where's Holly? +She's in the bedroom. +Well? +Don't go. +Please, don't go. +You expect me to run out? +Yes. +Yes, together. +Somewhere far away, where there's no war. +We belong here, Holly. +Here, this is our land. +It was worked for and paid for. +Nobody's driving me off this land. +They can bury me in it, but nobody is chasing me off it. +Peter, darling, what does a piece of land matter? +Look what it's doing to us, to everybody. +- Please, take me away from here. +- This is our home. +- They say not. +- They lie. +War is filled with lies. +What they say, what we say, lies. +Our place is here. +My place is with you. +And you have no place for me. +I'm selfish. +I don't want to lose you. +Please, let's go away from here before it's too late. +Do I get the names? +The oath-givers the man who killed my wife. +Joe. +Lathela. +You are not afraid of Mau Mau? +I'm like you. +I'm too old to be frightened by men. +The wrath of God frightens me, not the brutality of men. +What do you want of me? +How is it you gave the oath to others and never took it yourself? +I believe in the faith of my father. +Good. +Who are your leaders? +Your oath-givers? +By speaking out, you can end the war between us. +You leave Africa and the war will end. +Can't we live in peace, your people and mine? +Go away. +Your soft words are sharper than blows. +Would you prefer violence? +I'm no ordinary man. +Nothing can make me speak out. +They have tried. +They could not do it. +Not with torture, not with pain. +You will fail also. +Well, that's all we needed, a spell of weather. +Ngai is angry. +What's that? +Thunder and lightning. +When it storms, the Kikuyu believes he is face-to-face with god. +Thunder is the sound of god cracking his joints preparing for battle. +The lightning is god's sword of retribution. +You talk as if you believed that black hogwash yourself. +The important thing is whether our friend in there believes it. +If he does... +You'll never break him with mumbo jumbo. +His kind understands only one thing: +Force. +- Kill him, you make a martyr of him. +- He'll be dead. +Hold it, Joe. +Go ahead, Henry. +You gotta fight an idea with a better idea. +With the help of this weather, and if I know my man... +Well, give me one more go at him. +Tell me, Ngai, if I do right. +I only wish to do thy will. +Give me a sign that I may know. +Lathela, get some kerosene and dry wood. +- I am not afraid to face god. +- We will see. +I am the messenger of god. +Did god create Mau Mau? +Mau Mau is the will of god. +Did god tell you to mutilate innocent children? +Did Gikuyu and Mumbi ever violate animals? +Since the creation of Mount Kenya has god ever told you to steal and murder and burn and hate? +Is it the will of god that you eat human flesh and blood? +- I swear that... +- Wait. +Let your swearing have value in the eyes of god. +Swear by your sacred Githathi stone. +Hold this symbol of God in your hands and swear. +Then I'll believe you. +Now begin at the beginning. +Did you ever take the Mau Mau blood oath yourself? +- No. +- I believe you. +- Did you give the oath to others? +- Yes. +- By force? +- Yes. +You swore to drive the white men out of Africa, didn't you? +- Yes. +- Did God tell you to create Mau Mau? +Say yes before God and I'll believe you. +I've said enough. +You are afraid to face your god. +- If Mau Mau drives us out, then what? +- Then freedom. +- And faith in god too? +- Yes, yes. +How? +What faith? +Mau Mau, the promise to murder? +Will god take back the people who've eaten the blood oath? +That's why you didn't take the oath yourself, isn't it? +Because you wanted to be able to come back to god. +Yes, Ngai, I come to you faithful with no other gods before you. +But you've broken every law of your god. +Tell him that too. +Tell him you gave the blood oath to others by night, by force. +That you gave it before witnesses, gave it to women and children. +These are the worst violations. +How can you lead your people back to god? +Even tonight, more of your people are being oathed banished from the house of god cursed to live through eternity as a broken-spined hyena. +Is that the future for your people? +Is it? +Is that what you want? +No. +Who's the oath-giver in Nairobi? +Who is he? +If god cannot accept Mau Mau, Mau Mau cannot lead your people. +In Nairobi, his name is Timbu. +Who gives the oath in Thomson's Falls? +Lorry driver for Bwana Wilson. +Nyeri? +They are even in the home guard. +Are Mau Mau in our telephone service? +- Yes. +- Code words for guns? +- Mti, tree. +- Ammunition? +Makaa, charcoal. +The McKenzie shamba, who led the attack? +The... +The husband of my daughter. +His name? +Kimani wa Karanja. +The capture of a high-ranking oath administrator has led to the arrest of many Mau Mau in the Nyeri District. +Loyal Kikuyu witnesses are cooperating by pointing out those Africans who have taken the blood oath. +Witnesses wear white hoods to conceal their identities. +Shantytown in Nairobi, cesspool of intrigue and resistance is being flattened and razed. +Ready? +- Where do you think you're going? +- To find Kimani. +I can't spare the men for that chase. +- Just Lathela and I. +- And when you find him, then what? +- Ask him to surrender. +- Why should he? +Because I know Kimani. +Because he wants peace as much as we do. +Peace? +You said surrender. +Peace means terms. +What terms? +His precious life? +A seat in parliament? +You and your pet black boy. +You're just a black liberator, aren't you? +All right, all right. +What terms? +The lives of his people. +- What can we lose by trying? +- Did this Kimani take the oath? +The old man says yes. +You wouldn't have one chance in a thousand of coming out alive. +The emergency operations now cost the government more than a million pounds every month. +Several farmers in the Nyeri District have quit their farms and returned to England. +Mau Mau gangs are being forced deeper into the Aberdare Mountains. +The flare, Papa. +Send up the flare. +Elizabeth. +Jeff. +Where's Jeff? +Tomorrow, you can take Elizabeth into Nairobi. +To the hospital. +And leave here? +It's to help Elizabeth. +We'll get you a little flat in town and you can come and see me every day. +Yes. +Yes, I'd like that. +Are you all right? +No one came here. +Did you make contact? +Well? +Did you see Kimani? +Will he come? +He's a big general now. +I do not know if he will come. +And if he come, I do not know if it is to speak or to kill. +I do not know how a general thinks. +KIMANl: +Put down your gun. +Kimani? +KIMANl: +The guns. +And the pistol too. +The pistol. +Now, tell Lathela to build a fire. +Why? +I want my comrades to see you. +We're alone, you have nothing to fear. +I know this. +You have tobacco? +- Cigarettes. +- Pass them here. +Why did you come? +- Can we not talk face-to-face? +- No. +- Njogu is our prisoner. +- I know. +He confessed many things, told us many names. +- I know. +- He is not harmed. +Then why did he turn against us? +Njogu was braver than any of us. +He was not afraid to die. +He was afraid for his soul. +Can you understand that? +Yes. +The people he named have been arrested. +- I know. +- You know the war goes badly for you. +It is possible to lose a battle and still win a war. +Must Africa always stink of death? +Can we not live together as friends? +- Friends have equal rights. +- They will come. +Only when we take them. +- I think we're ready to give them. +- What do you want of me? +Give up. +Surrender. +Bring in your people. +Surrender? +Peace. +On what terms? +Justice. +Understanding. +If you stop fighting, others will do likewise. +You must have faith. +You must try. +We have tried before. +Then try again. +And again and again and again. +Do you not love anyone? +Your wife? +Children who believe in you? +You know of my child? +No. +A man-child? +Yes. +He will find a better world than you and I. +I sometimes dream of when we were children, you and I. +- Peter? +- Yeah. +I've not said that name in many years. +How goes it with your father? +As well as age will allow. +He was a good man. +He's a friend of my father. +Yes. +And Memsahib Elizabeth? +She is with child. +- Peter? +- Yes. +I did not hurt her. +I did not hurt her or her children. +It was not my hands that struck them. +I believe you. +What's happened to us? +When did this hatred begin? +Before we were born, I think. +I will talk with my people. +I will tell them that I trust you. +But they must decide for themselves. +This will take time. +Four days hence, you will have your answer. +If they agree we will come to the meadow by the hidden spring. +- You know of it? +- Yes. +- You will be there? +- Yes. +Until then. +Kimani. +Grandpa. +Peter. +- So you pulled it off. +- Yes. +- I wanna hear about it. +You like a drink? +- No, thank you, later. +Holly? +Holly? +Holly is with Elizabeth in Nairobi. +Oh... +- You see, we had another raid here. +- I know. +I asked her to go. +- Don't blame her, son. +She was... +- Thanks, Papa. +What we do is stupid. +To surrender betrays everything we have done. +Our children need food, our sick need medicine. +All we need is courage. +Let me talk to them. +You cannot talk to a starving people. +Their belly have no ears. +And if they shoot us down? +No, I have the word of my friend. +Your friend is a white man. +He hates us. +It is your own hatred that you see in others. +Holly. +Sister Williams. +I called at your flat. +You shouldn't go into Elizabeth's right now. +Anything wrong? +No, she's just a little overdue, that's all. +There's nothing to be alarmed about. +You're looking... +You're looking thinner. +You don't look so bad yourself. +Was it very bad? +Some days are good, some bad. +- No, they'll see us. +- Let them. +Do you have to go back? +Tonight. +Oh, I wish I could go with you. +We'll go away soon in that honeymoon we never had. +We don't have to go away to be on a honeymoon. +But I thought you wanted to... +To run away? +Yeah. +Just when was that? +Let's see, about a month ago? +At least a hundred years. +I want to go home to our home. +With Mount Kenya and God in the garden. +The war may not be over for a long time. +I used to blame the war for everything, didn't I? +Somebody else's war is always to blame. +No, I was to blame. +When you grow up, you realize you can't run away from the world. +You just gotta live in it. +You're a big girl now. +I'm beginning to understand about that other woman too. +- What other woman? +- Africa. +Oh. +She's not the least bit jealous. +And neither am I. +Excuse me. +Your boy, Lathela, he says you have to start off for somewhere or other. +Thank you. +See you soon. +Please, God, let it be soon. +Can't you make this thing go faster? +We've got to get there by daylight. +Why? +It's almost impossible. +- But if Kimani shows... +- He set no hour. +He'll wait for us. +Yes, but will Joe Matson wait? +- Matson? +- He got wind of it somehow. +You should have stopped him. +I only heard about him myself about an hour ago. +How do you keep a thing like this secret? +How do you keep Matson off the trigger? +This won't be any ceasefire, it'll be cold-blooded murder. +Doctor? +Yes? +Is there any marks? +Just the mark of a man. +Look at this place. +It's a perfect trap. +What are we supposed to do? +Wait around till they show up? +We'd be caught in the open. +It's a perfect trap, I don't wanna get caught. +- If they show, it'll be to surrender. +- How do you know? +But they gave their word. +I'm taking cover. +You know how Joe is, always suspicious. +I know how Mau Mau is too. +Where is your friend? +You there, all of you, put down your guns. +Wait. +Please. +Yeah, we lost him all right. +Come on. +- When we find Kimani, will you kill him? +- No. +Then why do we hunt him? +He must not think I betrayed him. +If he trusts us, others will do likewise. +If he escapes, if he does not believe Mau Mau will fight harder and longer. +Kimani will not surrender peacefully. +Not this time. +- He will try to kill you. +- Perhaps. +- Don't come along. +- I come with you. +- Why? +- This is my fight too. +Mau Mau has killed a hundred of my people for every one of yours. +I want the same thing for the African that Kimani wants. +Mau Mau is not the way to get them. +Kimani? +Stay here and don't move. +And don't shoot. +- Let me talk to you. +- No! +You kill my wife and my people. +We were betrayed. +Both of us. +I'm here without a weapon. +Are you alone? +Lathela is here too. +I'm coming in. +Keep away. +Kimani. +Don't make me do it. +Come back with me. +No. +We'll start over again. +- This time, it'll be different. +- No. +It is too late. +For you and me. +It is too late. +Must I kill you? +Yes. +Give me the child and bury us both. +No. +Please. +He is dead. +- What will you do with the child? +- Take him home. +Elizabeth has a boy, raise them together. +Maybe for them, it'll be better. +It's not too late. +[SINGING] +ELIZABETH: +Darling. +- Papa, have I kept you waiting? +- No, that's all right. +Come on. +- Why isn't Peter here? +- He's playing with Kimani, Papa. +That brother of yours and that Kyuke are inseparable. +Can't he find a white playmate? +Why? +You can't treat an African like a brother and expect to have a good servant. +When Caroline died, Kimani's mother raised Peter. +In a way, they are brothers. +[WHISTLE BLOWS] +When do you leave for England? +Tomorrow, worst luck. +I'm homesick already. +A few years of school... +You won't let him marry anybody but me, Mr. McKenzie, will you? +Has he proposed? +No, but I have, quite often. +Which of you stole the rifle? +Step forward. +Your religion says it is evil to steal. +Your own medicine shall name the liar. +If you tell the truth, this will not burn your tongue. +He who lies burns. +Peter? +Kimani, my son, shall be the first. +Did you steal that gun? +Did you steal the gun? +Did you steal the gun? +Did you steal the gun? +[CHATTERING DOG BARKING] +I will find the weapon and bring it to you. +Punish him yourself. +The city teaches bad ways to young men. +How does it go with your wife? +The wife with child? +Tomorrow, the day after... +The time is near. +Papa. +- How does it work? +- Plain old witchcraft. +The Kikuyu is a very religious man. +He fears God, but he trusts him too. +- But hot steel is... +- Will not burn a wet tongue. +But the liar's spit dries up. +Him it will scorch. +Ha-ha-ha. +I think you know more about black witchcraft than you do about the Bible. +- Let me have my way with these devils... +- Poor old Jeff is the perfect colonizer. +What's his is his and what's theirs is his too. +Well, have a good shoot. +We're not raising cattle to feed a maverick lion. +PETER: +Kimani, Lathela. +Tell Kimani not to gut him. +We'll leave a smelly calling card for the lion. +Kimani, open the animal, but don't clean him. +Then you'd better service the guns. +When it comes time to kill the lion, I want to shoot the gun too. +It's Jeff's show. +And you know how he feels about Africans and guns. +KIMANl: +I want to shoot the gun too. +PETER: +I'm sorry. +Lathela. +KIMANl: +Always when we hunt it is the same. +You have all the fun, I do all the work. +When we were little and played together... +But we're big now. +And things are not the same. +Hit him. +Hit him. +Hit him hard. +Do what he says, now. +And in a hurry. +From now on, when he tells you to do something, do it. +Don't think about it, just obey. +Understand me? +Well? +Come on, Peter. +I really should've slapped you. +Might have been better all around if you had. +Heh-heh. +Forget it. +You had no right to hit Kimani. +JEFF: +Peter, how many times have I got to tell you? +Blacks are blacks and not playmates. +One thing you can never do is argue with them. +Never. +You tell them. +Oh, sometimes you can joke with them you can boot them in the tail sometimes look after them when they're sick. +But you never, never argue with them. +- The world's changing, Jeff. +- Not in Africa it isn't. +Kimani's mother raised both of us. +We grew up together. +You'll never live together on equal footing. +Not in our lifetime. +You can't spend the first 20 years of your life with someone sharing bread and secrets and dreams, and then one day say: +"Sorry, it's all over. +We live in different worlds". +I don't believe it and I don't like it. +Wait till you settle down and marry Holly and have to deal seriously with the wogs. +Have you heard from Holly? +A couple of letters from London. +She mentioned coming back? +Just stuff about school, things like that. +Hm... +Well, we'd better break camp and go after that lion. +Lathela. +Get Kimani to help you load. +Kimani not here. +PETER: +Where? +Forget that lion, Jeff. +We're gonna find Kimani, and right now. +All right, all right, all right. +[ENGINE STARTS] +You want Lathela with you? +No, you'll need him to track. +I'll meet you back here at sundown. +[HYENAS YIPPING] +[WHIMPERS] +[YELPS] +- Are you all right? +- Yes, bwana. +- Does it hurt much? +- No, bwana. +You're lying. +- And stop calling me bwana. +- What shall I call you? +"Boss"? "Master"? +Yes, it hurts. +Not where the trap cut me only where Jeff slapped me. +That is where it hurts. +Well, then stop thinking about it. +No one ever struck me in anger before. +Not even my own father. +It wasn't in anger. +He's already forgotten. +Can you forget it? +I cannot forget it either. +We are alike in many things. +You talk Kikuyu same as me. +I speak English same as you. +But you are white and I am black. +And you are the bwana and I am the servant. +And I carry the gun and you shoot. +- Why is shooting the gun so important? +- It's not the gun, it is... +What is it, then? +What? +We cannot talk as friends. +Why? +You said it yourself. +We are not children anymore so we are not friends anymore. +I saved your life as a friend. +I'll always be your friend. +Kimani... +Does it hurt much? +No. +[SPEAKING IN FOREIGN LANGUAGE] +[BIRD CROWS] +[SPEAKING INDISTINCTLY] +ELIZABETH: +The child doesn't come easily. +It is a curse. +This morning, I saw the dung of a hyena. +Just now a vulture passed over us. +Don't you talk like that. +Just don't you talk like that. +- Suppose the child is born feet first. +- Then it must be killed. +When that child comes, don't you touch it. +You understand? +It is you who do not understand. +I'm gonna fetch my father. +White magic will not remove the curse. +- Perhaps the curse is in your son? +- What evil did he do? +Suppose a snake came into his bed. +Suppose a man struck him and he did not strike back. +Suppose he broke a law. +[BABY CRYING] +The child enters life feet first. +Do what must be done. +[BABY STOPS CRYING] +[BELL RINGS] +[INAUDIBLE DIALOGUE] +Kimani. +Swear him in. +- Which god, please? +- The Christian God. +I worship Ngai, the god who lives on Mount Kenya. +I will swear by our sacred Githathi stone. +CROWN COUNSEL: +Your word will suffice. +KARANJA: +Oh, no, no. +If I lie before this symbol of God my children and their children and my home and my land will turn to dust. +[STICKS BANG] +And when I die I will have no life hereafter except to live forever in eternity by the cursed hyena, cowardly eater of the dead. +I speak the truth. +You're the father of the dead baby in question? +- Yes. +- Did you tell the midwife to kill the baby? +Yes. +It was born feet first, it was cursed. +Then what was done? +What is always done according to custom. +CROWN COUNSEL: +Tell His Honor what that is. +We smothered the child and buried it under a pot. +- You know that killing is against the law? +- God says to murder is wrong. +And when you had that newborn baby smothered, was that not murder? +No. +A child cannot join the tribe until he is 1 year old. +Therefore, he's not really born until his second year. +What was killed was a demon, not a child. +Yes, yes. +And then what did you do? +- What? +- Then what did you do? +We sacrificed a young ram. +Mm. +And that, I suppose, got rid of the curse. +KARANJA: +No. +No, sir. +Not yet. +I am still here, therefore the curse is still at work. +Would you do the same thing if another child were born to you feet first? +Yes, yes. +It would be my duty. +What in the name of Almighty God are we trying to do to these people? +CROWN COUNSEL: +Preserve the law, Henry, that's all. +Law? +Whose law? +Not theirs, surely. +All men are equal before the law. +Except some are more equal than others. +That man is an accomplice to murder. +He's admitted that. +But can we make him understand it? +We take away their customs, their habits, their religion. +We stop their tribal dances, we stop them circumcising their women. +Then we offer them our way of life, something they can't grasp. +We say, "Look how clean and rich and clever we are". +For the Africans different wages, different life. +We mock their wise men. +Take away the authority from their fathers. +What are the children going to do? +They'll lose respect for their elders and fathers and when they do, look out. +Maybe they'll lose respect for our white Jesus too. +Turn to something else for help. +It won't be to us. +Well, you understand, don't you, Peter? +If we don't make the African respect the law well, the next thing you know, he'll be wanting to rule this country. +Imagine that, now. +Whatever could give him that idea? +This is his son. +Can he come in while we're here? +[SPEAKS FOREIGN LANGUAGE] +[IN ENGLISH] The city frightens me. +- Let us go home quickly. +- Listen, old friend. +The law says you must stay here in jail for a while. +I'm sorry. +We'll do everything we can. +My daughter will visit you. +She'll bring you tobacco and food to comfort you. +Please keep this for me. +A jail is not the proper place to keep god's sacred symbol. +And when my son comes of age... +I understand. +I am happy it was not you who struck my son. +You are still his friend? +Yes. +And yours too, for as long as you both wish it. +MAN: +Boy, boy. +I told you. +He will not help you. +Our Mathanjuki will purify you. +He will drive the curse from your body and I will be free. +- No. +- You do not believe in god? +- Yes, yes. +But I do not believe in our witchcraft and black magic. +When Bwana Jeff struck you... +He struck a black man to prove that the white man is master, nothing else. +You are not in jail because of a curse but only because we are judged by their laws. +And that is the truth. +And I must follow where the truth leads me. +- Where does it lead you? +- To strike back. +We're men, not animals. +You have much to look forward to, my son. +You will become headman as I was. +Is that to be my life? +Headman for a white boss? +"Yes, bwana. +No, bwana. +Yes, bwana". +This land can serve me too. +I want my own land. +Then you must earn it. +I will, Father. +I will. +[DOG BARKING] +[GASPS] +Who are you? +Who sent you here? +Why you come here? +He told me to come here. +You told me the white man would put Father in jail. +- You said we had to fight the white man. +- Your father is in jail? +- Yes, and I'm ready to fight. +- You ran away from the McKenzie shamba? +- Yes. +- Why? +- You stole money? +- No. +- Guns? +No, why should I steal? +Then why should you run? +I don't know. +NJOGU: +This is my daughter, Wanjiru. +- He can be of no use to us. +He wants to fight the white man. +We can use him. +We will take him to the mountains. +We will train him. +Come, little boy. +First you will learn to steal guns. +Hm? +[ENGINE STARTS] +I have no parents and I am hungry. +I need work. +Not a sound. +Nothing. +Do not call. +Do not answer. +Do not cough or I kill you. +Understand? +You are not alone? +How many are there? +One other? +The houseboy? +You will call him by name. +Nothing else, just the name. +Call him. +COOK: +Migwe. +Migwe. +This boy is dead. +Nanyuki Police signing off, 1545. +- Hello, Peter. +- I need some help, Hillary. +If it's about the sentence of your headman... +His son, Kimani. +He's missing. +- When? +- Last night. +I want him found. +- What did he steal? +- Steal? +You want him found, what are the charges? +- He might be hurt. +- You check the infirmary? +And I've chased down his family within a hundred miles. +He'll show up. +He probably went to Nairobi on a toot and... +- Age? +- Twenty-one. +- Height? +- Six-two, weight a little under 13 stone. +Wait a minute. +There was a houseboy killed last night. +Buxton shamba, at the foot of the Aberdares. +A gang broke in, stole guns and whiskey. +- What's that got to do with Kimani? +- Maybe nothing. +Maybe everything. +- Not a chance. +- Why not? +I know Kimani. +I know how he thinks. +He's not a criminal. +You mean not yet. +You just find him. +At least send out a description. +Kimani's guilty of only one thing, captain. +Guilty of being born black. +[SINGING] +Take one. +Why that gun? +My friend Peter has a gun like this. +It is a fine gun. +I can kill a lion with this. +Or even a man, huh? +[SINGING STOPS] +There will be no drinking here again. +Never. +Adam is our leader. +Who are you to tell us what...? +NJOGU: +Daughter, ask the other women where to go and what to do. +Kimani. +I see you have earned a gun. +This gun. +To get some of these guns, one of our own people was killed. +When lightning strikes, a bystander may be hurt. +Lightning belongs to god. +This was murder by him. +It was the will of god. +No. +I do not like your ways. +Sit down. +I go to Nanyuki. +I work there to free my father in my own way. +Sit down. +Two reasons why you cannot leave us. +That houseboy. +That houseboy who was killed last night, Adam can hang for this. +So can you. +So can all of us. +- That is the law. +- Reason two. +You know our names and our faces. +You know where we live and how we live. +We would be safe only if you stay with us. +Or if you were dead. +We will not always live as hunted animals. +Great men make plans for us. +Plans to drive the white man from our country. +Plans to take back our land. +Plans to... +MAN [OVER PA]: +Flight 212, BO AC arriving from London, Rome, Athens, Cairo, Khartoum. +- Cigarette? +ELIZABETH: +No. +- Dad? +- No, thanks. +Flight 212 departing for Dar es Salaam, Johannesburg and Jamestown. +ELIZABETH: +There. +Two-one-two departing for Dar es Salaam, Johannesburg and Jamestown. +Each to their own. +Holly, I... +Six years is a long time. +Too long? +You'd better see to her luggage. +- Can't I watch too? +- It's indecent. +That's why I want to watch. +Oh, really. +PETER: +Kimani. +Hey. +[DOGS BARK] +Kimani. +Strange. +I thought I saw Kimani. +You remember Kimani? +Move. +Start moving. +[SPEAKS FOREIGN LANGUAGE] +[IN ENGLISH] Would you mind letting us by, please? +[SPEAKS FOREIGN LANGUAGE] +I've come to pray. +CLERK: +This is not a church. +My god does not live in a church. +How do you call yourself? +Kimani wa Karanja. +We are beggars and slaves in our own land. +The British allow us in their homes and hotels, yes. +But how? +As servants. +We are millions, they are a handful. +We are strong, they are weak. +How then are they the masters and we the slaves? +Is it white magic? +Is it god's will? +No. +They have the guns. +We too shall have guns. +Are we ready for this? +The whole colored world burns with the fever of revolt with the fire for freedom. +Do any of you have any questions? +Is there a doubt in your hearts? +What troubles you? +NJOGU: +Kimani. +His name is Kimani wa Karanja. +For five years, he has been in the mountains with us. +He is ready for leadership. +He is very strong and loyal. +Strong men have betrayed us before. +- You have a question, Kimani? +KIMANl: +Yes, sir. +- This talk of guns. +LEADER: +Yes? +Is this the only way we can get freedom? +Yes. +- By the spilling of blood? +- Yes. +We will never drive the British out with words. +And not with doubts and not with friendship. +It can only be done with guns. +The white man did not take this land with guns. +He bought this land. +- This is truth. +- Mm-hm. +And I must follow where the truth leads me. +You were educated in white missionary schools? +Yes, sir. +Long, long ago, to whom did the land belong? +- The people. +- Yes. +Not one person, but the entire clan. +And therefore only the clan can sell the land correct? +- Yes, sir. +No man of any other tribe can buy our land unless he becomes, in our religion, a Kikuyu. +Yes, sir. +And have the British ever become Kikuyus? +Or have you become one of the British? +Your father was a friend of the British. +But your father died in their prison. +There is only one way to drive out the British. +By terror and death. +Everyone must either be for us or against us. +Those who be with us, stand. +Good. +We will need a symbol, a sign, a name. +Here it is. +Mau Mau. +Mau Mau. +Use it, live by it, die for it. +Mau Mau is the machinery that will carry us to freedom and independence. +Mau Mau. +ALL: +Mau Mau. +I swear to kill an Englishman or may this oath kill me and my family. +I swear to kill an Englishman or may this oath kill me and my family. +- They make a nice couple, don't they? +- Mm. +She's got good lines for breeding too. +Look. +Mount Kenya. +Lathela, wait here. +No wonder the African believes that God lives on Mount Kenya. +If I were God, that's where I'd like to live. +I feel I'm really home now. +I love you, Peter. +I always have. +I suppose I always will. +I like the feel of you. +I wish... +Yes? +I wish it could always be like this moment. +Safe and warm and peaceful. +Always like this. +Home is always like this. +Why did your husband run away? +Did he steal? +Did he do something bad? +Where did he go? +Why didn't you go with him? +- I was afraid. +- Afraid? +Afraid of what? +WOMAN: +Hello, my darling. +MAN: +Hello, my darling. +LITTLE JEFF: +What did you bring? +PETER: +Hello. +LITTLE JEFF: +You didn't forget my rifle? +WOMAN: +Yes, it's right here. +MATSON: +Henry. +WOMAN: +Bring the children in. +Bring them in. +MATSON: +What do you think? +What's it mean? +I don't know. +Two Kyukes disappear from my place. +Jasper, his headman reports one gone from his farm, rifle missing too. +One gone from your place. +Why? +You saw his wife. +She's afraid. +Why? +What of? +[DOOR KNOCKS] +Come in. +According to Kikuyu custom we come to speak for Peter McKenzie, bachelor to Holly Keith, spinster. +- This shy Kikuyu maiden is grateful. +- She doesn't look very shy to me. +How many goats will be paid for me? +Three or four ought to be quite enough, don't you think? +Oh, I'd say 20 or 30 at least. +Why don't you throw yourself in and make it 31 goats? +And why has Peter wa Henry chosen me? +He needs someone to chop firewood and dig potatoes. +He needs someone to keep his bed warm. +- He promises not to beat you often. +- Unless it's absolutely necessary. +- He also expects a child every year. +- All of them his. +- A very narrow attitude. +- We shall also have to shave your head. +Do you accept my son? +If you do, we'll drink to the marriage bargain. +If you don't, I shall have to pour this on the ground. +HOLLY: +And waste all that precious gin? +Thank you for becoming one of our family. +You will swear a new blood oath. +When it is done, you will be part of the new army: +Mau Mau. +He who refuses to take the oath he dies. +He who breaks the oath he dies. +Cut off the sheep's head. +Fill this calabash with its blood. +Sugar cane. +Sugar cane and banana leaves the first source of food. +Mugere plant best and strongest magic. +The arch oldest Kikuyu symbol. +You will pass through the arch seven times and thereby enter a new life. +You will receive seven cuts on the arm to bind you together. +Seven. +All things in seven. +Seven, the unlucky number. +Break the oath and the evil seven will strike. +Sheep's blood symbol of sacrifice. +Millet seeds of nourishment. +Earth the earth we fight for. +The cause that brings us together. +You will eat this oath. +You will swallow it seven times so that it becomes part of you. +Bitter Sodom apples. +Take off everything that stinks of the European. +Watch, ring, money. +To give you an easy road. +The endless circles. +Earth. +Hold it to your belly. +That the land may feed us and not the foreigners. +Hold up your arm. +So that your blood will mix. +Now swallow the oath seven times. +Repeat after me as you pass through the arch. +If I sell land to any foreigners, may this oath kill me. +If I sell land to any foreigners, may this oath kill me. +- I will steal guns. +- I will steal guns. +I will never be a Christian. +I will never be a Christian. +I will drive out all Europeans or kill them. +I will drive out all Europeans or kill them. +NJOGU: +It is done. +They've all sworn. +I feel unclean. +I will not let Wanjiru take this oath. +It is not necessary. +She is loyal. +To swallow the oath was hard enough, but the rest of it... +The nameless filth, the shame. +And in front of the others. +Why was it necessary? +Why? +To bind us together forever. +Now they will do anything. +Killing of mother, father, son will be as nothing to them. +They will feel strong with power and purpose. +- Who gave you the oath? +- No one. +You never took it? +I am too old to change. +I am ready to give up my life, but I cannot give up my faith. +It is too deep, too strong. +In life and in death I will always believe in the god of my father the god who lives on Mount Kenya. +- So do I, in spite of the oath. +Your daughter carries my child. +Now, I wish to marry her before the child is born. +I consider you married. +I will gather cooking stones with my wife as my father before me gathered cooking stones with my mother. +Like you, I cannot tear out what is in my heart. +Do it quickly, then. +We need rest. +Tomorrow is the appointed day of the long knives. +Our first attack should be on the McKenzie shamba. +- Why there? +- Why not? +Look, that was my home, my friends. +A great leader has no friends, only a cause. +- You doubt my loyalty? +- I only ask you to prove it. +Let your panga come back as red as mine. +[CAMERA WINDING] +[BABOONS HOWLING GRUNTING] +[HOLLY CHUCKLES] +Thank you for a lovely day. +Lovely wedding day. +- No more anxiety? +- Mm-mm. +- You know why? +- Why? +Because everything's so full of life. +All the animals, the earth and even the air smells of life. +We've done nothing to spoil it. +Someday all this will be farm country. +What will happen to White Hunter McKenzie, then? +Four years ago, our crops were hit by locusts. +Wiped out. +Papa put all his savings into cattle. +The next year, rinderpest. +What cattle didn't die had to be killed. +Papa got a loan from the bank. +So part of the time, I take rich clients on safari. +For the money. +To pay back the loan. +So the land's good to us this year and the crops hold up, no locusts, no rinderpests I'll be back where I really belong. +On the farm. +You know, that's the most wonderful wedding present you could ever give me. +- Are you as happy as I am? +- I'm a very lucky man. +I have the two women I love most in the world. +- Who's the other one? +- Africa. +There are some things I can do for you that Africa can't. +What is it? +I don't know. +Something strange. +Well, I didn't hear anything. +I'm not certain. +It was something. +Just a feeling, I guess. +[HORN HONKS] +I wonder what's happened to the porch light. +Probably the fuse again. +I'll have a look at it. +JEFF: +Hey, what the...? +Ugh! +KIMANl: +Remember me? +Kimani. +- What do you want? +- I've come home. +[INAUDIBLE DIALOGUE] +[CRASHING WHISTLE BLOWING] +ELIZABETH: +Jeff! +KIMANl: +No. +[MOUTHS] Kimani. +MAN [OVER RADIO]: +Jeff Newton and two of his children dead. +His wife, Elizabeth, in critical condition. +On the open highway to Nanyuki in broad daylight Joe Matson and Mrs. Matson were ambushed while motoring. +Mrs. Matson was killed by machine-gun bullets. +Chief Waruhiu, leader of the anti-Mau Mau movement was murdered at Kiambu. +MEYLl: +Yes, bwana. +SUPERINTENDENT: +Were you in your hut last night? +MEYLl: +Yes. +SUPERINTENDENT: +It's lucky your father and the one boy were out visiting. +Where is Jeff and the kids? +SUPERINTENDENT: +What's your name? +MEYLl: +Meyli. +SUPERINTENDENT: +Who was with you? +MEYLl: +My husband and my children. +And the mother of my husband. +SUPERINTENDENT: +Did you ever attend any Mau Mau meetings? +MEYLl: +No, bwana. +SUPERINTENDENT: +Next, please. +[GASPS] +Mrs. McKenzie, what type blood are you? +- Type O. +- Come along, please. +Hurry. +Anybody else here with type O blood? +Peter? +Lathela is, I think. +DOCTOR: +Which one of you is known as Lathela? +Is that you? +Come with me. +We need blood to help Memsahib Elizabeth. +Papa. +Why Elizabeth? +Why the kids? +Why? +[WHISTLE BLOWING] +[GRUNTING YELLING IN FOREIGN LANGUAGE] +[CAR ENGINE STARTS] +[MUSIC PLAYING] +MAN [OVER PA]: +A state of emergency now exists in Kenya. +Kikuyus are being sworn into a terror organization called Mau Mau. +Small gangs are fighting guerrilla warfare. +There may be Mau Mau on your farms, in your cities, in your homes. +Any African found with a gun may be punished by death. +Peter, why do you have to go? +We've been over this a dozen times. +I have to go, that's all. +Yes, but there's the army... +The army is inexperienced in the mountain and the bush country. +- How long will you be away? +- I don't know. +What am I supposed to do while you're gone? +What the rest of the women are doing, help keep the place going. +Peter. +It wasn't very much of a honeymoon for you, was it? +Are you very afraid? +No, not of them. +Only for us. +It's us I'm afraid for, what will happen to us. +GAME WARDEN: +Mau Mau working underground everywhere. +Maybe right here in this room, for all we know. +Now, the government wants information. +Who's forging the ammunition permits? +Who's supplying the guns? +Who's giving the oaths? +So it's prisoners we're after. +It's your job to track them down. +I say kill them, make it open warfare, bomb them out. +Kill whom, all 6 million Africans in Kenya? +We're only 40,000. +That makes the odds about 150-to-1. +That's not the point. +We're not at war with the Kikuyu nation. +We're fighting Mau Mau. +For every one of us, they've killed a hundred Kikuyus. +- Loyal Kikuyus. +- They don't know what loyalty means. +Now, listen, man. +They're trying to drive us out. +What are we to do? +Pack up because their grandfathers were here first? +I was born here too. +This is my country. +Killing's no answer. +We gotta give the African a chance... +Black man's had Africa for years. +It'd be a jungle if we hadn't moved in. +It's not a question of black or white. +That's exactly what it is. +Black or white. +You'll follow orders or keep out of this. +Well? +All right. +I'll try it your way for a while. +No smoking. +And no fires for cooking. +Whiskey? +Jeff. +Talk to me, Papa. +I don't know what to say. +Anything, Papa. +Anything at all. +This off-season rain it should do a lot of good. +You're doing a big job, child. +Like my Caroline, a long time ago when the country was new. +She was delicate, but strong, like you. +She helped to make the land and hold it. +Like you. +No, Papa, not like me. +I'm weak. +I'm weak and I'm afraid and I'm lonely. +Papa. +Who said you could get out of bed? +I want to go to Nairobi to see the doctor. +Is it your arm again? +I know you'll think I'm mad but I'm going to have another baby. +You see, if there's any chance of it being born... +Well, I mean, after losing so much blood and... +And I want this baby, Papa. +More than I've ever wanted anything. +It'd be a little bit more of Jeff and... +Holly, will you take me in to the doctor in the morning? +[DOG BARKING] +[SINGING] +Hey, you, listen carefully. +[MATSON SPEAKS IN FOREIGN LANGUAGE] +You are surrounded by police. +[CHATTERING] +MATSON: [IN ENGLISH] Lay down your guns. +Listen carefully. +[GUNFIRE] +[MATSON SPEAKS IN FOREIGN LANGUAGE] +[IN ENGLISH] Lay down your guns. +You are surrounded by police. +[CHILD CRYING] +MATSON: +All right. +Waithaka, do you know any of these people? +[SPEAKS IN FOREIGN LANGUAGE] +- Next. +- A good farmer, no Mau Mau. +- No? +- No, bwana. +You see? +Njogu, soldier of god. +MATSON: +How long were you in the mountains? +One year. +Do not hurt me, bwana. +Who gave you the oath? +I do not know. +If you lie to me again, I'll kill you. +Now who was it? +Who made you swear to the oath? +[THUD] +Waithaka. +Help me. +Help me. +Waithaka. +- Help me. +- The woman lies. +I never saw her before, never. +I swear. +By my father, I swear. +Here's one of your loyal Kikuyus. +All right. +We'll start again. +- You gave the oath to the girl? +- No. +- She knew your name. +How? +- She's the wife of my brother. +- Who gave you the oath? +- It was dark and raining, I could not see. +How do you Mau Mau do it? +Since when do we use torture? +The Mau Mau do it. +They love it. +- You might even grow to love it yourself. +- I don't like it any more than you do. +But I don't like what happened to Matson's wife. +Or your family. +Or any families to come. +[WAITHAKA SCREAMS] +We're not such a big jump away from being savages ourselves, are we? +Please. +Please let me point him out from here. +Please let me. +This is the man. +- Your name. +- Njogu. +Is he the one? +Is he the oath-giver? +You said his name was Njogu. +You said he was here. +He spoke truly. +I gave the oath to him, to all of them. +They know nothing. +And from me, you will get nothing. +WAITHAKA: +Do not let me stay... +Do not let me stay here. +You promised, bwana. +You promised, you promised, you promised. +[CROWD SCREAMS] +[WAITHAKA SCREAMS] +[DOOR KNOCKS] +Who is it? +[DOOR KNOCKS VIOLENTLY] +LITTLE JEFF: +Uncle Peter. +Excuse my appearance. +I need a drink. +- I beg your pardon. +- Let me help you, son. +That's right. +Absolutely right. +You're gonna help us all. +I need your help. +Government needs help. +Everybody needs help. +It's a big secret job. +Very important. +Toast. +Toast. +I don't think he's taken off these clothes since he left home. +He probably never had a chance. +Thank God he's all right. +Holly strange things happen to people in war. +- Inside, I mean. +- Not between us. +- He'll be the same as always, you'll see. +- Nothing's ever the same. +That's one thing you can't do, stand still. +[GASPS] +Look, his sock has rotted away inside his boot. +[PANTING] +I'd forgotten how good our earth feels. +So rich and full of life. +Can you hear the soil through my fingers? +No. +What's it saying? +How much I love you and miss you and need you. +Last night, I thought... +Last night I had a nightmare and it was... +It was a nightmare. +Somebody will see us. +Does it matter? +It isn't the same, is it? +Yes, Holly. +You make me feel ashamed. +We waited lunch for you. +- Sorry. +- Finally gave up. +I didn't realize the time. +Daydreaming? +Yes. +You can pick your dreams in the daytime. +I'm sorry you've gotta go tonight. +So am I. +It's not fair to Holly. +She's carrying a pretty heavy burden. +No more than you or a dozen other women around here. +It's not easy for Holly looking after Papa and little Jeff and me. +It's not easy going to bed with a rifle by your side night after night instead of a husband never knowing if you're going to see daylight again. +Never laughing. +Never loving. +Never knowing if the next footstep on the porch is yours or... +You're her whole life, Peter. +Don't shut her out. +I feel empty. +Dead. +It's not so bad in the daytime, in the clean hot sun. +But when it grows dark I'm afraid, I guess. +And then when I think of Holly and how much I want her and when it's the moment to touch her and be with her, I can't. +I just feel dirty, I feel unclean. +Filthy business we're in. +Time will wash it clean. +Who knows how much time there is left? +- Ready? +- Yes, yes. +Where's Holly? +She's in the bedroom. +Well? +Don't go. +Please, don't go. +You expect me to run out? +Yes. +Yes, together. +Somewhere far away, where there's no war. +We belong here, Holly. +Here, this is our land. +It was worked for and paid for. +Nobody's driving me off this land. +They can bury me in it, but nobody is chasing me off it. +Peter, darling, what does a piece of land matter? +Look what it's doing to us, to everybody. +- Please, take me away from here. +- This is our home. +- They say not. +- They lie. +War is filled with lies. +What they say, what we say, lies. +Our place is here. +My place is with you. +And you have no place for me. +I'm selfish. +I don't want to lose you. +Please, let's go away from here before it's too late. +MATSON: +Do I get the names? +The oath-givers the man who killed my wife. +Joe. +Lathela. +You are not afraid of Mau Mau? +I'm like you. +I'm too old to be frightened by men. +The wrath of God frightens me, not the brutality of men. +What do you want of me? +How is it you gave the oath to others and never took it yourself? +I believe in the faith of my father. +Good. +Who are your leaders? +Your oath-givers? +[CHUCKLES] +By speaking out, you can end the war between us. +You leave Africa and the war will end. +Can't we live in peace, your people and mine? +Go away. +Your soft words are sharper than blows. +Would you prefer violence? +I'm no ordinary man. +Nothing can make me speak out. +They have tried. +They could not do it. +Not with torture, not with pain. +You will fail also. +[LIGHTNING CRASHES THUNDERRUMBLES] +Well, that's all we needed, a spell of weather. +Ngai is angry. +What's that? +Thunder and lightning. +When it storms, the Kikuyu believes he is face-to-face with god. +Thunder is the sound of god cracking his joints preparing for battle. +The lightning is god's sword of retribution. +You talk as if you believed that black hogwash yourself. +The important thing is whether our friend in there believes it. +If he does... +You'll never break him with mumbo jumbo. +His kind understands only one thing: +Force. +- Kill him, you make a martyr of him. +- He'll be dead. +Hold it, Joe. +Go ahead, Henry. +You gotta fight an idea with a better idea. +With the help of this weather, and if I know my man... +Well, give me one more go at him. +Tell me, Ngai, if I do right. +I only wish to do thy will. +Give me a sign that I may know. +[SPEAKS FOREIGN LANGUAGE] +[IN ENGLISH] Lathela, get some kerosene and dry wood. +- I am not afraid to face god. +- We will see. +I am the messenger of god. +Did god create Mau Mau? +Mau Mau is the will of god. +Did god tell you to mutilate innocent children? +Did Gikuyu and Mumbi ever violate animals? +Since the creation of Mount Kenya has god ever told you to steal and murder and burn and hate? +Is it the will of god that you eat human flesh and blood? +- I swear that... +- Wait. +Let your swearing have value in the eyes of god. +Swear by your sacred Githathi stone. +Hold this symbol of God in your hands and swear. +Then I'll believe you. +Now begin at the beginning. +Did you ever take the Mau Mau blood oath yourself? +- No. +- I believe you. +- Did you give the oath to others? +- Yes. +- By force? +- Yes. +You swore to drive the white men out of Africa, didn't you? +- Yes. +- Did God tell you to create Mau Mau? +Say yes before God and I'll believe you. +I've said enough. +You are afraid to face your god. +- If Mau Mau drives us out, then what? +- Then freedom. +- And faith in god too? +- Yes, yes. +How? +What faith? +Mau Mau, the promise to murder? +Will god take back the people who've eaten the blood oath? +That's why you didn't take the oath yourself, isn't it? +Because you wanted to be able to come back to god. +Yes, Ngai, I come to you faithful with no other gods before you. +HENRY: +But you've broken every law of your god. +Tell him that too. +Tell him you gave the blood oath to others by night, by force. +That you gave it before witnesses, gave it to women and children. +These are the worst violations. +How can you lead your people back to god? +Even tonight, more of your people are being oathed banished from the house of god cursed to live through eternity as a broken-spined hyena. +Is that the future for your people? +Is it? +Is that what you want? +No. +Who's the oath-giver in Nairobi? +Who is he? +If god cannot accept Mau Mau, Mau Mau cannot lead your people. +In Nairobi, his name is Timbu. +Who gives the oath in Thomson's Falls? +Lorry driver for Bwana Wilson. +Nyeri? +They are even in the home guard. +Are Mau Mau in our telephone service? +- Yes. +- Code words for guns? +- Mti, tree. +- Ammunition? +Makaa, charcoal. +The McKenzie shamba, who led the attack? +The... +The husband of my daughter. +His name? +Kimani wa Karanja. +MAN [OVER RADIO]: +The capture of a high-ranking oath administrator has led to the arrest of many Mau Mau in the Nyeri District. +Loyal Kikuyu witnesses are cooperating by pointing out those Africans who have taken the blood oath. +Witnesses wear white hoods to conceal their identities. +Shantytown in Nairobi, cesspool of intrigue and resistance is being flattened and razed. +Ready? +- Where do you think you're going? +- To find Kimani. +GAME WARDEN: +I can't spare the men for that chase. +- Just Lathela and I. +- And when you find him, then what? +- Ask him to surrender. +- Why should he? +Because I know Kimani. +Because he wants peace as much as we do. +Peace? +You said surrender. +Peace means terms. +What terms? +His precious life? +A seat in parliament? +You and your pet black boy. +You're just a black liberator, aren't you? +GAME WARDEN: +All right, all right. +What terms? +The lives of his people. +- What can we lose by trying? +- Did this Kimani take the oath? +The old man says yes. +You wouldn't have one chance in a thousand of coming out alive. +MAN [OVER RADIO]: +The emergency operations now cost the government more than a million pounds every month. +Several farmers in the Nyeri District have quit their farms and returned to England. +Mau Mau gangs are being forced deeper into the Aberdare Mountains. +[GUNSHOTS] +HOLLY: +The flare, Papa. +Send up the flare. +HENRY: +Elizabeth. +[WHISTLE BLOWING] +Jeff. +Where's Jeff? +Tomorrow, you can take Elizabeth into Nairobi. +To the hospital. +And leave here? +It's to help Elizabeth. +We'll get you a little flat in town and you can come and see me every day. +Yes. +Yes, I'd like that. +Are you all right? +No one came here. +Did you make contact? +Well? +Did you see Kimani? +Will he come? +He's a big general now. +I do not know if he will come. +And if he come, I do not know if it is to speak or to kill. +I do not know how a general thinks. +KIMANl: +Put down your gun. +Kimani? +KIMANl: +The guns. +And the pistol too. +The pistol. +Now, tell Lathela to build a fire. +Why? +I want my comrades to see you. +We're alone, you have nothing to fear. +I know this. +You have tobacco? +- Cigarettes. +- Pass them here. +Why did you come? +- Can we not talk face-to-face? +- No. +- Njogu is our prisoner. +- I know. +He confessed many things, told us many names. +- I know. +- He is not harmed. +Then why did he turn against us? +Njogu was braver than any of us. +He was not afraid to die. +He was afraid for his soul. +Can you understand that? +Yes. +The people he named have been arrested. +- I know. +- You know the war goes badly for you. +It is possible to lose a battle and still win a war. +Must Africa always stink of death? +Can we not live together as friends? +- Friends have equal rights. +- They will come. +Only when we take them. +- I think we're ready to give them. +- What do you want of me? +PETER: +Give up. +Surrender. +Bring in your people. +Surrender? +Peace. +On what terms? +Justice. +Understanding. +If you stop fighting, others will do likewise. +You must have faith. +You must try. +We have tried before. +Then try again. +And again and again and again. +Do you not love anyone? +Your wife? +Children who believe in you? +You know of my child? +No. +A man-child? +Yes. +He will find a better world than you and I. +I sometimes dream of when we were children, you and I. +- Peter? +- Yeah. +I've not said that name in many years. +How goes it with your father? +As well as age will allow. +He was a good man. +He's a friend of my father. +Yes. +And Memsahib Elizabeth? +She is with child. +- Peter? +- Yes. +I did not hurt her. +I did not hurt her or her children. +It was not my hands that struck them. +I believe you. +What's happened to us? +When did this hatred begin? +Before we were born, I think. +I will talk with my people. +I will tell them that I trust you. +But they must decide for themselves. +This will take time. +Four days hence, you will have your answer. +If they agree we will come to the meadow by the hidden spring. +- You know of it? +- Yes. +- You will be there? +- Yes. +Until then. +Kimani. +Grandpa. +HENRY: +Peter. +- So you pulled it off. +- Yes. +- I wanna hear about it. +You like a drink? +- No, thank you, later. +Holly? +Holly? +Holly is with Elizabeth in Nairobi. +Oh... +- You see, we had another raid here. +- I know. +I asked her to go. +- Don't blame her, son. +She was... +- Thanks, Papa. +What we do is stupid. +To surrender betrays everything we have done. +Our children need food, our sick need medicine. +All we need is courage. +Let me talk to them. +You cannot talk to a starving people. +Their belly have no ears. +And if they shoot us down? +No, I have the word of my friend. +Your friend is a white man. +He hates us. +It is your own hatred that you see in others. +PETER: +Holly. +Sister Williams. +I called at your flat. +You shouldn't go into Elizabeth's right now. +Anything wrong? +No, she's just a little overdue, that's all. +There's nothing to be alarmed about. +You're looking... +You're looking thinner. +You don't look so bad yourself. +Was it very bad? +Some days are good, some bad. +- No, they'll see us. +- Let them. +Do you have to go back? +Tonight. +Oh, I wish I could go with you. +We'll go away soon in that honeymoon we never had. +We don't have to go away to be on a honeymoon. +But I thought you wanted to... +To run away? +Yeah. +HOLLY: +Just when was that? +Let's see, about a month ago? +At least a hundred years. +I want to go home to our home. +With Mount Kenya and God in the garden. +The war may not be over for a long time. +I used to blame the war for everything, didn't I? +Somebody else's war is always to blame. +No, I was to blame. +When you grow up, you realize you can't run away from the world. +You just gotta live in it. +You're a big girl now. +I'm beginning to understand about that other woman too. +- What other woman? +- Africa. +Oh. +She's not the least bit jealous. +And neither am I. +Excuse me. +Your boy, Lathela, he says you have to start off for somewhere or other. +PETER: +Thank you. +See you soon. +Please, God, let it be soon. +Can't you make this thing go faster? +We've got to get there by daylight. +Why? +It's almost impossible. +- But if Kimani shows... +- He set no hour. +He'll wait for us. +Yes, but will Joe Matson wait? +- Matson? +- He got wind of it somehow. +You should have stopped him. +I only heard about him myself about an hour ago. +How do you keep a thing like this secret? +How do you keep Matson off the trigger? +This won't be any ceasefire, it'll be cold-blooded murder. +[PANTING] +[SLAP BABY CRYING] +Doctor? +Yes? +Is there any marks? +Just the mark of a man. +Look at this place. +It's a perfect trap. +What are we supposed to do? +Wait around till they show up? +MATSON: +We'd be caught in the open. +It's a perfect trap, I don't wanna get caught. +- If they show, it'll be to surrender. +- How do you know? +But they gave their word. +I'm taking cover. +You know how Joe is, always suspicious. +I know how Mau Mau is too. +Where is your friend? +You there, all of you, put down your guns. +[SCREAMING] +Wait. +Please. +[BABY CRYING] +[KIMANI SCREAMS] +[SPEAKS IN FOREIGN LANGUAGE] +Yeah, we lost him all right. +Come on. +[BABY MOANING CRYING] +- When we find Kimani, will you kill him? +- No. +Then why do we hunt him? +He must not think I betrayed him. +If he trusts us, others will do likewise. +If he escapes, if he does not believe Mau Mau will fight harder and longer. +Kimani will not surrender peacefully. +Not this time. +- He will try to kill you. +- Perhaps. +- Don't come along. +- I come with you. +- Why? +- This is my fight too. +Mau Mau has killed a hundred of my people for every one of yours. +I want the same thing for the African that Kimani wants. +Mau Mau is not the way to get them. +PETER: +Kimani? +Stay here and don't move. +And don't shoot. +- Let me talk to you. +- No! +You kill my wife and my people. +We were betrayed. +Both of us. +I'm here without a weapon. +Are you alone? +Lathela is here too. +I'm coming in. +Keep away. +Kimani. +[BABY CRYING] +[GRUNTING] +Don't make me do it. +Come back with me. +No. +We'll start over again. +- This time, it'll be different. +- No. +It is too late. +For you and me. +It is too late. +Must I kill you? +Yes. +[YELLS] +Give me the child and bury us both. +No. +Please. +He is dead. +- What will you do with the child? +- Take him home. +Elizabeth has a boy, raise them together. +Maybe for them, it'll be better. +It's not too late. +Studio "Les Films Marceau" is +Raymond Pellegrin +Jeanne Moreau +Paul Meurisse +The film "Until the last one" +Director: +Pierre Billon +By ANDRE Duquesne (novel) +Dialogues: +MICHEL ODIYAR +Cast: +MAX REVOL +JACQUELINE Noelle +JACQUES DYUFILHO and other +Composer: +GEORGE VAN PARIS +Operator: +PIERRE PETIT +Producer: +ANDRE REFFE +Warning! +Give out! +Let pass, madam! +Pass! +Let's hurry! +Come! +Where is the farce Marcella? +- Marcello fortuneteller? +- Yes. +- You her friend? +- No. +Her brother. +You also guessing on a glass bowl and tea leaves? +If only, I do not believe that any penny. +In any case, things you better than mine. +My name Kvedchi. +- Not all the same call Duran. +By Romani which means "a fig." +Here's how! +Once I was an acrobat - I jumped from 12 meters into the bath. +A one night missed. +Since then - not worth a fig. +Keep. +I mended your pad. +Can you portray Lovelace evening. +I do not work the shoulder muscles more. +But the language works. +Maybe I'm lucky, and you tell me where I can find Marcello? +There. +The second trailer for the circus. +Thank you. +- What is this rogue? +- Bro Marcella. +Go and prosperous branch of the family. +So smartly dressed! +- Too! +Or a policeman or a thug. +But it expressed pretty well. +So bandit. +- Oh, it's you! +- Your joy is encouraging me. +How do I see you has kept the family tradition. +How do you come from? +From prison. +A little rest in 6 months. +Clutter, shorter. +I wonder, when will you grow up and poumneesh? +Change the record, okay? +Give the best drink. +The buffet has a wine. +Wait a minute. +What's the matter? +Oh, nothing. +Fatigue. +Heart... +- No! +It is you not the weakest link. +You know, all of this - the word. +We fight, finding fault, but generally... +We love each other, no? +- Heck! +Here we are! +I need you, yes? +Yes. +I... +I would have to... +I have to hide for a few days. +But do not worry. +Do not the cops. +So much the better. +Because here strictly look after us. +Fair - is a disease of the gendarmes. +No one knows why. +How do you think you can get me a job? +You are not going to tell me that looking for a job? +Well, let's say, that was something to do. +It looks like you're in something cool vljapalsja! +I was in prison. +- Look, Bernard. +- Yes? +I do not play face-down. +I'm ready to be for you, but I need to know against whom? +I have already told you about my former friend - gang Richoni? +- Good buddy! +- I told you, the former! +They cranked a small business. +It is not weak. +We took a big jackpot - 14 million. +Wow! +Give me my pills. +There, in a box. +14 million - is hiding. +You - the shelter that I know. +You stole prey? +When you want to settle down, it takes money. +But do not worry, my friends about anything not guess. +Even the fact that I was known for their cache. +They are there, for sure, not see for several days, and during this time... +During this time? +I do not know, complications may occur, minor disassembly... +Accidents at work... +You sold them ? +! +I sell? +No. +Passed. +Do not you think the same, for the sake of the 14 million I will stand on ceremony? +14 million... +Can you imagine? +They will quickly realize which way the wind blows, if they have a head on their shoulders. +To get the moolah, they killed two agents and three passers-by. +So, believe me, my head on his shoulders at them - only temporarily. +The main thing that I could sit in the shelter, +Until they are caught. +- Money to you? +- Laugh or what? +- How much you give, if I help? +- What do you mean! +Will you take stolen money ? +! +You would divide wrongfully acquired? +Would deprive his brother ? +! +What about your sister? +You'll get as much as do. +Will not work, there is no fuel. +Okay. +Come descend to Cinco. +Let's go. +It is the owner of the circus. +And it is more than one, - he owes me money. +It's okay. +Just hoof ragged. +It is necessary to treat with ointment. +Or maybe to get started is to call the vet? +Vet? +And why not pedicurists? +Do you think I have little parasites on contentment? +Come on, shoo! +Take it from here. +But mother and Marcella. +Again, probably came to knock out money from the owner. +Who is she? +And it is quite personal. +This is your show? +Oh well! +Cinco! +A, Marcella, my beauty! +I'm always happy to see you. +Only you are not on time. +You just do not think I have my bad intentions. +Long for me - is sacred, but... +- I did not come here for this. +Do you still have no barkers? +- Yes. +And soon there will be nothing at all. +Things are deteriorating, people no longer go to the circus... +And you know why? +- Due to the television. +Exactly! +Circus offered to them right at home. +They baldeyut home with his family. +This is for him? +This is my brother, Fernand Bastia. +You do me a favor, if You take it. +It's hungry? +To work for me, you must be hungry. +Then consider that I'm hungry. +Well, if that's the manifestation of humanity - well. +And I know how to be grateful. +Just keep in mind - here you are not a farce. +It is necessary not only to be a greeter. +I must still be helpful. +And much work to do here. +And in response to the generosity of Cinco: +2000 francs per week, and grubs. +2000! +Are you kidding ? +! +You pay the guy the previous 5! +And nearly bankrupt, with such a breadth of US! +Do you want to take it or not. +- I take! +- Listen Cinco, can you... +- He has already agreed! +It you take a piece of bread! +You'll live with the acrobats. +Madeleine! +Take this guy for Dario. +Will live with him! +No, sit down, I'm going. +Well, we'll see you tonight? +Tell me, do you want? +Yes, after the closing. +But it's too late! +I can not walk after 10. +Okay, come when you want. +Something will think. +Oh, unwound, my mother is coming! +Lets go faster! +All the time an eyesore, and all the time with a servant! +All in father! +That did not stop my father to marry... +Society lady! +Gypsy acrobats - it's here. +This small palace! +You must have not often worked in the circus? +- Why? +- So, come to mind. +How long are you going to stay here? +Let's see. +What? +Nothing. +Just like that. +And why did you suddenly decide to come here? +I am looking for work. +So bad luck, you found it. +Way or not? +I am looking for work and found. +What is your name? +- Gina. +And this - my trailer. +Only with flowers. +Since then, as the Cinco cut staff, I live alone. +This has its cons and pros... +. +Dario? +Dario! +- What's the matter? +- Brought you a tenant. +Who else? +This brother Marcella. +Cinco hired him greeter. +Come here! +My name is Philip. +Philip Dario. +You surely have heard about me. +Of course! +Dario and Nellie - "The Ghost and Death"! +There is no more room. +- You did not tell Marcella? +- Yes, of course, I tell! +Okay, I'll leave you. +See you later. +Well, welcome... +Come! +Make yourself at home! +Your predecessor was sleeping on the right side, +If you have a preference or superstition... +No, no! +Take the couch, I will build on the cot. +I'm sorry, I have to go to work with Stella. +Stella - this is my daughter. +I'll explain it later. +Hey, Mom! +Mama! +What do you want? +Go keep an eye on the bench, I'll be right back. +The next... +Well, satisfied with their housing? +Oh, yes! +More than sugary hard to think! +Could get me anywhere else! +Where is it? +The trailer Marcella? +No... +I would have liked more than another. +Here is how? +What? +I do not know. +For example, the one with the flowers. +Beautiful colors, pleasant company and smells good... +For example, waking up in the morning, at breakfast... +- What do you eat breakfast? +- Coffee. +When I as a child - More and croissants. +What are you laughing at? +- You're just like a fair actor! +- Maybe belated vocation? +- Yeah, he can. +A can converge see your trailer? +No. +Not now. +- Gina... +- Gina, please! +- Yes! +- It's because I'm good, +I have to go. +Merchants closed at 7 o'clock. +There will be a bakery, there will be no croissants. +All this chatter! +He must be somewhere! +Good. +We here will not uyd置. +- So what? +- What? +A curtain! +It is nowhere seen. +- So he's hiding somewhere. +Thinly noticed! +I do not whether you think that it will be waiting for us on the terrace of a cafe? +Pour a mug. +- You've got the idea, Fredo? +They I have always, and it is ill-advised. +For ideas - as friends, they should not be too much. +Hello? +Yes, it's me. +Yes. +A? +What? +Yes. +Yes, I know! +Well, where is she? +Thank you. +You're a real friend! +What? +The name of his sister - Marcella fortune-telling. +Maybe he's hiding from her after the case in a villa in Neuilly? +Where she lives, this abnormal? +Powered by miserable fairs in provincial towns. +- These godforsaken full! +- Fredo! +You will not find a cigarette? +What if he did not go to his Sis? +Now, with attendants, that it may fall down abroad. +Well, call Jojo. +- All sorts of Jojo! +- Jojo, the little wagon! +- What's the matter? +- Police! +You bastard! +He passed us! +Open! +Police! +Yes, all right, go to sleep. +I have played so! +Brigade for the Protection of morality! +O, it happens with them. +Open. +They better not mess with. +- What is it? +- Open, gentlemen! +Ugolovka! +Hands up! +Hands up! +Well, Richoni? +What you say? +This time you got burned. +- Your informant still confused. +- Do not move! +- Oh, Fred! +Leave me alone! +Leave me alone! +No way! +Shoot, guys! +Shoot anything that moves! +Let's go through the yard! +What are you! +They have there just waiting for you! +Bastards! +In the hatch! +Faster! +Surrender! +I give you 2 minutes! +Now you can not rush. +To taste? +- Okay, a splinter of glass. +There is a way out? +- Yes. +What about the others? +As you said, friends should not be too much. +Exactly. +- You're not good? +- Do not worry, everything is fine. +It would be nice. +Let's go! +Here! +Come executed by my 2000 francs! +Ladies and gentlemen, the idea that you'll see, ... This idea. +Great idea! +With celebrities such as... +Madeleine, Gina, Stella and Dario ... and... +And also with the rest of the troupe! +If you think so you can get people to go to... +Just listen, as it should! +Come, ladies and gentlemen! +Come! +Cinco The circus - a circus, not like the others! +No billboards, no ads, no idle talk! +Just an idea! +We could show you 100 rooms! +These we have. +But we will show you only 10, but only with the stars! +Here Freni - Empress nudity! +Artistic art, in other words, educational, +Which you can watch the children. +Lovely Gina - goddess of dance! +You go? +Do not talk just started! +Lovely Gina - goddess of dance! +Dario and Stella - trapeze artists! +Calling gravity, puzzling scientists! +Mario - magnetic juggler! +Man flying pins! +Amedee and his dog, a tightrope walker! +Riri Fifi and clowns! +Finally, Mademoiselle Josiane - perfect woman! +And besides - daughter of yours truly! +Come, ladies and gentlemen! +Come! +This Circus Cinco - the only circus in the world, which they say friends! +Come in, come in, ladies and gentlemen! +The best places - 300 francs! +Military and children - 100 francs! +Come in, come in! +The show begins! +This, ladies and gentlemen! +- Hi, Am? +d? +e. +- Hi! +Do you want some coffee? +No. +No, thanks, I already drank. +Listen, you do not have a newspaper? +Bulk! +And you do not have one, but... +today? +No. +I, you know, they just build up the fire, so... +Good morning! +Well, Dad, we do not work this morning? +Works. +But I had to repair the suspension strap. +Hey, yesterday I had no time to introduce you to Stella, my daughter. +We are preparing with a single number. +Number stunning! +- Well, Dad, are we going? +- We are going. +Listen, I want to walk. +You do not have another key? +Why? +What is there to steal? +Yes, of course... +Well, Dario, your tenant already awake? +Half... +Such a strange type. +I do not know what time he arrived yesterday. +Sleeps dressed. +Maybe he a lunatic! +Oh yeah... +View Gina tired. +Perhaps she, too, a lunatic? +You could have knocked! +I'm sorry. +Still, good morning! +What you happy - it's your courtesy, tenderness. +Well, you can not be the same day and at night. +Have to evening dance with the long sleeves. +You guided me bruises. +Do you want to tell you one stupid? +Well, tell me. +I really like you. +You do not have to answer me, in turn, +Maybe it was just a nice night, just for you... +I wanted to tell you... +I mean, if you want... +You would not mind every night dance with long sleeves? +Here! +Go! +Buy a newspaper, and then I'll give you an aperitif. +Welcome! +No, well, you see? +Once he has a grandmother, it can no longer shake hands? +If he had a grandmother, he would not have worked for Cinco. +I know what I'm saying! +I'll be right back. +Teach by heart? +What? +Article about the fight at Pigalle. +3rd time already read. +Well, everything ? +! +Are you at home? +Check the pockets? +We follow the mail? +Would wait until I take a subscription before removing the meter reading! +These are your friends? +- Who? +- Men with Pigalle. +Why are you hiding? +Who are you afraid of? +I perfectly see that you're scared. +- Where are you going? +- Where do I want to. +Imagine, I do not like the slap. +- Liar! +Oh, forgive me! +When I'm on edge, slap yourself frustrated. +Let's forget, okay? +You read that five were killed. +If you do not know them, why do you have such a person? +Because the other two. +Are you saying that you would be staged 7 dead? +You are strongly capable in the long run. +You got me with that thing! +END OF THE GAME +Do not be angry! +Let's go sit down. +I'll treat you. +Waiter! +- Mademoiselle? +- The same. +- Now! +Stubborn around, huh? +Okay, come on. +I'm listening to you. +You got into something bad, Fernand. +That's why you're here. +I do not want to know, you're right or not. +And even if you're wrong, I'm ready to be with you. +Oh! +Love - it is so beautiful. +Why do you say that? +Because you know that those types, which finished off, participated in the robbery of Marseille. +What the police did not find 14 million francs. +So you talk. +And since you are able to run, you divide 14 2. +Yesterday you took me for a bandit, +And you liked it. +Today you take me for a sucker, and you like it even more. +I had a good night, Gina, but... +Than 14 million. +I simply offer you my assistance. +Help to spend it? +- Here, Mademoiselle Gina. +- Write down, I'll pay tomorrow. +See? +Do you believe that everything has already happened. +Wronged? +- Not at all. +You too cunning for me, Fernand. +Talking to himself, and makes me tired. +I was fascinated, but wrong. +It happens. +Goodbye and good luck! +A pack of cigarettes. +Thank you. +Time is right, kids! +Hurry! +- But where is Jean? +- From Bastia, where else? +I feel sorry for Gina, she sunk down on a guy. +What is she in it found in this clown? +I do not understand. +If I were in your place, I would know what to do. +You have returned the money that I have a year must be his sister? +All work! +And with a soul! +And with enthusiasm! +Revenue today should be good! +You know my number with Stella +Ready. +This could save you. +- I know, I know. +- It is necessary to order the posters! +Oh, wait a minute. +Posters fine, but it is not important... +- They can be made in two colors. +- Yes! +For instance, I just thought... +What are you doing here? +- I need to talk to you. +- No! +Every time you're talking about one and the same, and I already told you "no!". +Why? +Because you suggest it to all the girls. +But others - this is nonsense, does not mean anything. +You see, I'm honest! +Why would I be honest? +Because I love you. +Yes, you know it. +- When love girl, her respect. +Oh, you're reading too much! +And this is life. +You're the only one I love. +Do you want to be the only one with whom I do not want to sleep? +No, it is illogical to do everything! +Leave me alone! +What if I talk to your dad? +But for now, if he catches you in his trailer, he kicks your ass. +If he agrees, I'll marry you. +At once. +And in the church! +White dress, green plants, red carpet. +And the gatekeeper! +Well, I agree? +- No! +- This is the same train! +- Yes, that's it! +I am too poor, right? +But if that's the case, you will be mine! +Bastia? +Come help me prepare tickets. +You then asked. +- Who? +I do not know. +The man who got out of the black car. +- What did he want? +- To find out whether you're here. +- He did not say anything? +- No. +Only that will see you later. +And... he looked like? +In your style. +The style that we do not like, let it be known. +Thank you! +Thank you very much, that I was warned. +- Where's he gone? +- To hell, I hope! +- Then who will drum up? +- You're, like yesterday. +You're right. +At the same time I will spare 2000 francs. +Even 5000 - I add myself a salary. +All the places for the parade! +Are you going to go? +We do not prevent, I hope? +Pepe feared hurt. +However, Pepe? +Yeah. +Ogonyok not find? +Yes. +- Read newspapers? +- Yes. +You with Pepe lucky. +- So we said, going here: +We lucky! +In our country such a friend like you! +You've always been decent, Fernand. +We walked, and said, "Fernand decent." +We were wrong? +- No... +I was sure that we can count on you! +We Pepe plans to leave, but not enough money. +You know life - without the money does not go far. +But... +I have no money! +That's why we're here. +To tell where to find them. +Or rather, it is to remind you. +I'm sorry, Fred, but I gave up. +The last six months I was stunned. +I decided to change my life. +- Well done! +It is necessary to give up the old life to doing good, huh? +You will have a pleasant memory. +And it will be nice to Pepe. +The money is still in a place that you know. +- I? +- Yes. +Converge zaber群h and come back. +What if I caught? +On Piga, certainly, full of cops. +Do you know them! +I mean... +Do you know how to behave. +And then - you did not participate in Marseilles, so... 14 million for four - This is good, no? +A for the three do not want to? +Yes, it is tempting... +But very risky. +From my pedigree, I can get 10 years. +Understand me, Fredo... +- I understand you perfectly! +Only Pepe will not be happy. +He told me: "If you give up the slack Fernand, I'll kill him!" +Pepe - he was. +But calm down, I'm here! +I have to reason with him. +Well, I'll tell him you agree? +- Yes. +- Grandmas are tomorrow night? +- Yes. +- Good. +For example, at 7 pm. +I'll give you half an hour of reserve. +Then - descends Pepe. +- Everything went well? +- Delicious. +- Well, what did he say? +- And what could he say? +- And you left him? +Go away? +- Yes. +And you'll stay, +Keep an eye on him. +- Trust me. +- If you want to know my opinion... +- I know him. +You do not have to say. +But what did he want? +Money. +But I'd rather die! +Do you hear? +I'd rather die! +- Maybe this is not the way out? +I behaved with you is disgusting. +You could throw me. +You're a good girl, Gina. +I understand it now, because I start to see more clearly. +Because you are satisfied with it. +Imagine that also suits me. +- Yes! +- Do not start. +How was I to guess that you have money? +I loved you with them or not. +It's called loyalty. +- Listen to me, Gina... +Are you kidding over all? +The parade finished, the greeter was me. +Can I now draw a dancer ? +! +Come on, shoo! +This circus does not suit me! +Now +- Mademoiselle Josiane, perfect woman! +When they have to go back? +- Tomorrow at 7. +- There is a time to collect the suitcases. +- Are you ready to quit the circus? +- Anyway, he soon he would leave me. +Where is the money? +- In the suitcase. +- A suitcase? +The cell storage in the North railway station. +We'll leave tomorrow morning. +And if you will follow me? +Decide that you went for the money. +The funny thing is that it's true. +Yes... +Or maybe you prefer that I went for a suitcase? +Yes! +Yes, I prefer! +You see, I trust you. +In this and the good of the family are being built. +And now it's my turn. +This is a farewell waltz. +Lovely Gina, the goddess of dance! +Do babes such a success! +Local public immediately legible. +It is a pity that we have to leave tomorrow. +- Direction +- North Station. +Direction +- Arches. +What do I do in the North Station? +Pick up the suitcase on the receipt, which you stole from me. +Brock! +- What did you call me? +Thy name! +I pulled a receipt storage. +Receipt, which I hid here under the table! +And that you come back to me! +Look, Bastia, +Your pukalki can not force me to give what I did not take. +Do not give you in the face with it, too, will be able to make not. +A and so will happen, if you would not uber群h. +Then I'm glad. +Do not be offended, I was joking. +- Never mind. +But you're wrong, kidding... +Such things. +Yes. +It's like a cigarette butt can start a fire! +Perhaps it would suit the owner. +Yes, but only if he paid the premiums. +Gina! +Come here. +What's the matter? +- My receipt of storage! +- So what? +I pulled it! +- Richoni? +- No, definitely not. +Then who? +We've got no thieves. +What are you talking about ? +! +In addition to the receipt, I stole all the money out of a suitcase. +And so - no thieves! +What a fool! +This morning I took out a shirt out of the suitcase. +And the money was there still. +So it happened recently? +What does it change? +All! +If you hurry, you still catch my thief at Gare du Nord! +Do you have money? +I do not. +Maybe you have Marcella? +You carry nonsense. +Perhaps Cinco? +He told me to pay for a few weeks. +You should in any run. +I'll come to you first train. +Wait for me at the hotel "Piccardi," you know? +- Yes OK. +Fernand! +Yes? +If you return the money, we will go to Italy. +If you deceive me, I shall hand you to the police. +You clear favorite? +You are not as good as I thought, Gina. +Do not "is not so good." Not such a fool. +Okay, go. +If tonight everything goes well, +We will be able to pay taxes, for the light, and we can go tomorrow. +- To pay all the salary? +- If all pay, we will not go away. +I do not need anything Dario, fortunately. +He's an artist. +Madeleine - too. +Dame illusionist a little money, that's all. +And so well. +My poor Royal. +In such circumstances, we hold out long. +If Dario number will be successful, we will be able to get out. +This is our last chance. +- Phantom. +Cinco! +What do you want? +- Money! +- You're on time. +Cinco, I'm serious. +I have to leave. +- With the strikers? +- Yes. +Right now, Gina, I can not. +But in the evening, after the presentation, I will try. +But it's not great - throw us in a moment. +Sorry, Cinco. +I would have stayed, but I can not. +The rats are leaving the ship. +Hey, little girl, let's go have dinner. +Can not find your number 3968. +Perhaps it has already taken. +Yes, but... +You do not know who? +How should I know? +I atonement for service in 8 hours. +What's more, I could not give you your suitcase without a receipt! +And you tell me, as your colleague who works during the day, - where is he? +At home, I guess. +But if you think that he will be able to remember the customer...! +We then give out per day more than one thing, so... +- Hey, please! +- Yes, I'm coming! +Sorry, sir. +- Everything happened? +- Nothing like this. +Marcella must leave. +She needed all of her money. +What kind of selfish! +- But we still be able to leave? +Leave something we can always. +Depends only, under what conditions. +Any day fly off the vultures, hawks... +Hawks? +Bailiffs! +Do you think they will take my horse? +These people take everything. +Straw and logs, stairs and clocks, machinery and horses... +It Attila of our time! +Log in! +What do you want? +Nothing! +I was passing. +Well, Marcella sent you to hell? +- How do you know? +- To eavesdrop. +I'm always eavesdropping. +- Anyway, you're honest. +- I am glad that you found my dignity. +This will facilitate the work. +Cinco! +You are sitting on the rocks. +- Not at all! +Daughter you hard worker. +But you're still sitting on the rocks! +You already said that. +So what? +But if there was a guy, a good guy in all respects, +Which will accumulate? +What can you offer him? +- You know this guy? +- What can you offer him? +- Well... circus. +Number of Stella and Dario is almost ready. +International Class! +You can repeat it without laughing? +Horse Josiane. +Horse Mademoiselle Josiane! +With or without a rider? +- Nahal! +What do you mean? +I mean that is the only guarantee - if I become your kinsfolk. +I want to marry, and you need money. +I'm getting your son in law, and you save a circus. +For the salvation of the circus, my Kvedchi, you need a lot of money. +I have. +- And cash! +- Yes, I have. +And where? +You know, after my accident I embraced you. +I won. +Yes - compensation, disability benefits. +400 thousand! +What do you say to this, father? +Josiane, +You're already an adult girl, almost a woman. +A woman was not created to live alone. +I do not marry Kvedchi! +What you are discussing here is disgusting! +Is that you talking with her father so ? +! +Strange you raised it. +If I knew... +Sidi. +Why do you refuse Kvedchi? +As it has charm. +- Oh, yes! +And this charm he gives everything. +No one skirt missed! +Does it good! +Well, nothing can be done, Kvedchi. +I thought you were serious fellow. +Take your money. +Circus, certainly will not, +But my daughter will be happy. +I am happy with the ruined and robbed her father. +In the living corpse! +Television remove him hide, +Bailiffs will get seeds. +We beg, my girl. +But most importantly, I make you happy. +- Oh, come on, Dad, please! +I agree. +I agree, if Kvedchi promise me that... +Oh, yes! +I swear! +Hide grandmother! +- This is Gina. +- A, you can discover! +- Good evening! +- Good evening. +- Well, okay! +Till tomorrow. +- Till tomorrow. +- You asked to come in the evening. +- What is said is said. +How much do I owe you? +Today is... +34 thousand francs. +Wow! +- Hold. +With a small premium. +Yes, it's a fortune! +In life there are ups and downs. +At the moment - soon rise. +- Borrowed? +- Rodney. +In vain you are leaving us on the rise. +Can I still and will be back. +Thank Cinco. +Gina! +So, is it true? +Are you leaving us? +- Tomorrow I leave. +- With the strikers? +Yes. +Where are you going? +In another place. +It's because of those guys that came? +Cinco you paid? +It's wonderful, it has money - burn! +I know. +This is Marcella. +Once they slept together. +And she always had a weakness for him. +Marcella? +Can not be! +I'm telling you! +Goodnight Kvedchi. +Monsieur! +Monsieur! +- Who's there? +- You are asked to phone. +You call from Provence. +You can pick up the phone. +Hello? +Hello, yes? +Yes, yes, it's me. +Waiting. +Hello? +It is on the phone. +He got a call from Mersevalya, Marsevalya... +Stay here. +Yes, hello? +Is that you, Gina? +No, no, nothing happened. +I am late. +How is it not scary? +Yes. +And so, you are not thieves! +What? +How to... +Cinco ? +! +A lot of money? +Do you think you can still fix it? +Yes, it is. +Okay, I'm going. +Keep. +So will converge. +Wait, that's not all. +Thank you, mademoiselle. +Here. +Up to 9 hours, you call the number 7 in Marsevale. +And leave this message to Mr. Roland. +"Sending will Marsevale this morning." +"Suitcase was not present in the cold." +Rely on me. +- Well, call me a taxi. +Well, mademoiselle. +Now the flowers? +Yes, flowers. +For Josiane. +- So this is serious? +What? +I told you that it will be mine. +She is mine. +Well... almost. +I wonder what made her change her mind? +- My lovely manners. +- Your manners! +What are these two again come to do here? +Do you know them? +Then be engaged in their business! +What do I do! +It comes back, but no money. +- I am surprised that he returns. +- Maybe he likes trouble. +Go. +- I was in a hurry. +- I also. +Nice to hire? +We thought that you're tired, because the car drove. +Fernand! +What? +Send it. +Fernand, be kind. +- If you do not fall behind, I'll scream. +- I shoot. +- If you think I'm scared... +- As if I'm going to shoot you! +- Leave it, Gina, this is a misunderstanding. +- How cute! +Let's hope not the last. +Fredo, you must listen to me! +Of course, Fernand, we are here to do just that. +I do not dare to go for the money. +At the last moment I was afraid that the police monitors the cafe. +You is surely arranged. +As they watched the cafe, they have not followed the North Station. +Fredo, you're wrong! +- You think I'm guilty. +And I - a victim! +- Misunderstandings. +I know. +The only misunderstanding between us - I perceive you as a man. +I wanted to give you a chance. +You look like you could not use it. +- I was robbed of a receipt storage. +- It's impossible. +- I swear his eyes, Fredo! +- Look, Fernand, +You have passed the cops. +It is still possible to settle. +We all forget. +But the favor. +The money we need. +- But I'm telling you... +- And we'll get them. +Even if you have to pull out of the bills one by one. +But this - work for Pepe. +I'm telling you, I stole it! +I stuck it under the table. +We have a lot of time, Fernand. +Maybe you want to work Pepe? +I'm telling you I do not know anything! +- You're stubborn! +- Yes. +Everything is ready. +Are you comfortable? +Yes? +Good feeling? +Where is the money? +I would, perhaps, have learned if you trusted me. +Listen, give me time, I'll find a jug. +What are you risking? +It Again we throw! +I assure you, he can! +- Fuck you! +Pepe! +Calmly. +You should not tease him. +Where is the money? +Hell, Fred, if I knew, why would I come back? +In order for us to kill you! +I do it? +- While Turn to the machine. +Turn around. +We're going back to the circus. +It blockhead! +You can only help me! +I now know the circus. +Take me back, +And I swear I will settle everything quickly. +What do you think? +I think that you are too diligent. +Forget the circus, I will do everything for you. +Especially not flutter. +I just I will go and have a look and come back immediately. +Admit it, it would be a shame to die so young, with hoarded money? +- You leave Pepe? +Recklessly! +- Recklessly would leave him. +- I? +- Today you will work in a new way. +- You think so? +- Language, for a change. +- Do you have a candle? +- Yes. +How old are you? +Packaging. +And the matches. +No, the big boxes. +Please, sir. +With you 290 francs, monsieur. +Gina! +Gina! +So you did not go? +- As you see. +So you stay with us? +- Maybe... +- I am very happy. +Listen, +I go from Arsha. +Everything is settled, we're leaving tonight. +- Give me your jeep. +- You crazy? +- Give me your jeep! +- What does all this mean ? +! +Listen Cinco, all very serious! +A petrol - is also seriously? +I'll pay. +And be careful! +Strongly do not chase! +She left on your wheelbarrow! +Why did you give her? +Dahl gave! +I had time to give her? +Do not you see? +Log in! +- It is you - the owner's daughter? +- Yes. +Let me introduce myself - Angela Lombardi. +I said, your clicker left? +Maybe I could replace it? +- You ? +! +- Why not? +I started peddler under the counter on the boulevards. +And then, I have always loved the circus. +Monsieur. +Mademoiselle ready to replace the strikers. +I'll be glad if go up. +These pretty girls can not come. +But I can offer only 1000 per week. +More I did not ask. +I ran, Kvedchi waiting for me. +Goodbye, Mademoiselle. +- Goodbye. +- It's too good to be true. +Two days of work, and then... +- Let's see. +Agreed? +- Agreed. +Come later. +I will teach you the science barkers. +Intricacies of the profession. +It is an art! +Thank you! +You can sit down? +Do not worry. +- What You take? +- I do not know. +Coffee with cream. +Do you want to eat? +They then very tasty sandwiches. +No, thanks, I'm not hungry. +- Coffee with cream! +- Coffee with cream. +When we get married, we'll be there every day in the cafe. +How rich. +And yet, you know, I thought about our honeymoon. +We're going to Venice. +There's so wonderful in Venice! +How? +- I still have not been there... +- Does not matter, tell me! +Well, first, we make love in a gondola... +O Kvedchi! +- What? +- Well, let's say. +And then? +- And then... +- Expensive Cognac in the big glass. +- Okay, sir. +What's the matter? +Nothing. +- Want uyd置? +- No no. +- All right, I was hired. +- Well done! +You were fast. +Yes. +Now you have to find a guy who suspiciously quickly become rich. +Who is spending right and left. +You know what I mean? +I understand. +It's probably a whore, and I do not want her here. +I think her dad has already hired. +I tell you that he will dismiss it, and together with Gina! +But Gina had gone. +She left and came back. +And even stole your father's jeep. +Our jeep! +Do you like crabs in the pot? +A string beans... +love? +"Very fine"... +You are pampered! +Yes, but... +If you want to nibble on, will have to begin to sit at the table. +How funny! +When I want, I'm so merry! +Well, +Figured you about money? +I asked the question! +- Yes. +That's what I'll tell you: +If Fredo and his woman would find the money, +Them and they run away. +And some will remain with the nose - and it's you! +- You think? +- Yes. +How to drink to! +Fredo left you here to his hands were free. +But... the case is not yet completed. +You do untie we rush back, I'm taking the money, +And we divide them into two. +- You're going to work with me? +- Yes. +I had been thinking about it. +- ABOUT! +Well, Fernand, I here you simply hold oaf! +Cigarettes do not want? +I want. +- I do not have pockets, and I do not smoke. +- I have. +Here, in the pocket. +Tell me, +Who's there? +Do not be nervous, dear. +It's great, is not it? +You want to know who's here, right? +Now you know it. +- Gina! +- You start talking? +Gina! +Do Cinco never had any money. +And now - there. +According Kvedchi he gave Marcella. +Fortune Teller? +Sis Bastia? +Yes. +But it is certainly not true. +- Well, hang out. +Marcella had nothing to do with it! +You bastard! +So you gave the money to her Sis? +You're crazy! +Be polite! +Will be explained with his maid. +I believe her. +Fredo also believe! +You are one against. +And you're out of the game! +- Look, Pepe, I can help you! +You do not leave me here to die alone! +You're not alone here. +Madam - the neighborhood. +Lucky! +Hey! +Repeat. +- Okay, sir. +- How are you doing? +- At zero. +I put out the door. +It seems that fear of something. +Every fear, then there is a reason. +I'm sure that something was there. +- Could buy me a beer! +- Get fat from it. +- What's Your Number? +- 900 thousand! +I left 2 more ball. +I'll become a millionaire! +Yes. +Here the fair roaming gunmen. +You they probably know. +Who's on the phone? +Interrogate circus acrobat Dario, +More and Gina, a dancer. +But who are you? +Answer! +Hello? +Hello! +Hello... +You'll say, old owl ? +! +Will you speak ? +! +Will you say, vile creature ? +! +Hell! +- You know the kind of Dario? +- Of course, it is our acrobat. +- Where is he? +- Probably in his trailer. +The first right. +- Thank you. +- What do they want from Dario? +- This is probably due to Bastia. +From such people - always nothing but trouble! +Dad! +Where is Dad? +- What happened? +Marcella! +It's not moving! +I think she's dead! +Well, it just is not enough... +- This is certainly the heart deposited. +- It was in the evening departure! +- Your mother's looking for you, Kvedchi! +- You do not work, she is angry. +Okay, I go. +Here is a gift! +- She has always had a weak heart. +- I say that there is filthy! +It is, for sure, mutila with his brother. +- With a guy that was a greeter? +- Yes. +Doctor she is no longer needed. +So, parted, move! +You go out there! +Fast! +- What did I tell you! +- Maybe it's her brother? +This is murder! +She kept the house all your money! +I think it strangled. +She has marks on her neck. +Call to the site, let people send. +Yes, chef! +Expenses on a trailer! +All forbidden to leave the area of the holidays! +This is murder! +- I told you! +- I have long sought. +Yes. +Only you - not a policeman. +4 dead man in Marseilles, 5 - at Pigalle. +Who is next? +If the case begins with a fight, a fight over it. +- What do we do? +- I +- I do not know, and you - to collect the suitcase. +- You want me to leave? +- So you escaped. +We are going to fight, I feel. +A is not a ladies' game. +Rate - 14 million, and we have something to lose. +So I prefer you to leave the game. +We are all divided into two. +May, will continue? +Years in prison for two is not divided. +When the motley your age gets 10 years - this is the end. +Are you ready for 10 years wearing a gray robe and slippers tinkering? +I do not care. +Do not say that. +As long as you have the conscience of nothing. +Or almost nothing. +And tomorrow everything is going to be different. +Return to Paris and wait quietly. +Calmly wait what? +Exhaust itself? +Ask yourself, have arrested you or not? +Ask myself, what I bring, - oranges or flowers. +Shut up! +For fun you have to pay. +Life - is a journey. +I would like to go first class. +I have always loved silk shirts and shoes made to order. +And I have not traded in a row, it would be illogical. +- What's the matter? +- It's me! +Discover! +I thought I told you to go back and wait there? +Disaster struck, Fredo. +Chick Fernand came to explore, and I... +I caught it. +She uttered a few words about Marcello. +That she was involved. +More. +You went to Marcelle? +Yes. +To ask her any questions. +It is necessary to pass the buck, Fredo! +- Wait a minute! +Marcella? +Marcella! +I assure you, I have nothing to do with! +In her heart she refused. +Fredo, you're... +You do not leave me? +Where do I, in your opinion, go? +Where do you want. +To the Greeks. +Okay. +Then I will come back to the villa. +I left them there either. +Then finish them off for a full set. +Will you come, Fredo? +You do not leave me? +- No. +I will ask the President himself, so he put us together for the company. +Why did he kill her? +Misunderstanding, as it said Fernand. +Protracted misunderstanding. +Pepe was too stupid, Fernand - too cunning. +Police will be here soon. +It's time to disappear. +I? +You go back to Paris. +Come from time to time in the "In Field". +I'll leave it to you the news. +If all goes well. +Here's yet to wait. +No. +They you more useful. +This is unlikely. +The car, for sure, in the search. +What are you going to do? +- I'll go as soon as possible. +Either way, if I do not go down after 5 minutes they will rise. +Next! +Stop! +Stop or I'll shoot! +What? +Turns? +- Minute! +I sang this number 3 years ago Karpatto. +Pepe - a professional, and I have lost the knack. +My poor! +- Well, hurry up! +What are you naplela about my sister? +I'm not used to me about extinguished cigarettes. +In general, I would have passed anyone but you. +What's more, I just repeated what I was told. +- Who? +- Kvedchi. +Git! +- You think this is it? +- Definitely! +It's okay. +Stagnant blood. +It will pass. +How did you get here? +I follow you on a jeep owner. +Keep. +- With "Hold"? +Popey. +That's it. +Come on. +Bastia foul! +Bastia was blown away! +They still know enough! +Come on. +- Listen! +In minutes as the score goes! +No. +Do not for a minute. +It can wait. +Oh, you... you bastard! +Yes, it can wait! +He accused me of stealing receipts from storage. +He even guided me the gun. +Bring it in a report. +What's next? +Nothing. +He saw that I was not to blame, and calmed down. +Okay, good. +We have already moved. +The owner of the circus - are you? +Go. +You can be free. +But do not leave your trailer. +You must have a fortune of money? +- Yes. +So what? +If I had to kill all those who I have money, +You would have to double the staff. +- We can disagree? +- That's really not! +Well that ended this market? +I think they are looking for a suitcase. +Will conduct searches. +- By what authority? +- I do not know, but it's true. +Let there be sought! +The one who searches will find! +The search... +The search... +The search... +Stay here. +Hey, there! +Where are you? +Someone looking for? +Get down. +No, I... +I have come to my sister. +- Ah, the fortune-teller - your sister? +- Yes. +Well, okay, I go to next time. +Show me the documents! +The one who searches will find... +And find what? +Kvedchi! +Those guys! +Those guys will not find! +Those guys! +Hey, Kvedchi, open the door! +What are you doing, Kvedchi? +Tell me! +You open it or not ? +! +Are you crazy? +Why do you close? +- It is necessary. +Carriages will be searched. +What's burning? +Yes, it's money! +- This is mine, do not touch! +It is mine! +Money! +Do not touch the money! +They curse! +Yes, leave the money! +They curse! +Gimme! +Give it to me! +Thanks to you, give here! +I tell you, it will be searched! +If they find us... +Exploded gas cylinder? +- It's in Kvedchi! +- Faster! +Faster! +Do not approach! +Get away! +Here it is dangerous! +Save yourself! +Caution! +Caution, Fernand! +END +We proudly present: +One of greatest film of all time. +Brought to you by: +FNB.47 and others that I forgotten. +Have a nice time ;) --nttalex-- +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +Director of Photography S. URUSEVSKY +Associate Director +- B. FRIDMAN Production Designer +- Y. SVIDETELEV +Music by M. VAINBERG Sound by I. MAYOROV +English subtitles by T. KAMENEVA +Starring +T. SAMOILOVA as Veronica A. BATALOV as Boris +V. MERKURIEV as Feodor Ivanovich +A. SHVORIN as Mark S. KHARITONOVA as Irina +K. NIKITIN as Volodya V. ZUBKOV as Stepan +A. BOGDANOVA as Grandma B. KOKOVKIN as Chernov +Ye. +KUPRIANOVA as Anna Mikhailovna +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Your jacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools and the parents are no better. +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica! +In time of war, one should not get confused. +One should hold on to a normal life pace. +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I doubt it. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself! +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it. +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet, I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +There's so much excitement... +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders. +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry. +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma... +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee. +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee... +Comrade Boris, you must fight to the last drop of your blood. +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd better join us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don't just sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march! +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside. +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there. +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding. +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you. +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away! +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the devil I've got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes. +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +I'm doing all right as a girl. +Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +So, Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave ma alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse. +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +I've been saving this for you. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield. +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children, that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don't just stand there. +Give the flowers to whoever they're for. +Thank you very much, sister. +Oh, what a darling! +What a chubby little darling! +Look, the cranes are flying over Moscow! +The End +Subtitles ripped by: +--nttalex-- +MOSFILM +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +Director of Photography S. URUSEVSKY +Associate Director +- B. FRIDMAN Production Designer +- Y. SVIDETELEV +Music by M. VAINBERG Sound by I. MAYOROV +English subtitles by T. KAMENEVA +Starring +T. SAMOILOVA as Veronica A. BATALOV as Boris +V. MERKURIEV as Feodor Ivanovich +A. SHVORIN as Mark S. KHARITONOVA as Irina +K. NIKITIN as Volodya V. ZUBKOV as Stepan +A. BOGDANOVA as Grandma B. KOKOVKIN as Chernov +Ye. +KUPRIANOVA as Anna Mikhailovna +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Yourjacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools and the parents are no better. +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica! +In time of war, one should not get confused. +One should hold on to a normal life pace. +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I doubt it. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself! +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it. +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet, I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +There's so much excitement... +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders. +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry. +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma... +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee. +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee... +Comrade Boris, you must fight to the last drop of your blood. +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd betterjoin us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don'tjust sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march! +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside. +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there. +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding. +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you. +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away! +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the devil I'v got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes. +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +I'm doing all right as a girl. +Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +So, Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave ma alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse. +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +I've been saving this for you. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield. +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children, that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don'tjust stand there. +Give the flowers to whoever they're for. +Thank you very much, sister. +Oh, what a darling! +What a chubby little darling! +Look, the cranes are flying over Moscow! +The End +MOSFILM +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +Director of Photography S. URUSEVSKY +Associate Director +- B. FRIDMAN Production Designer +- Y. SVIDETELEV +Music by M. VAINBERG Sound by I. MAYOROV +English subtitles by T. KAMENEVA +Starring +T. SAMOILOVA as Veronica A. BATALOV as Boris +V. MERKURIEV as Feodor Ivanovich +A. SHVORIN as Mark S. KHARITONOVA as Irina +K. NIKITIN as Volodya V. ZUBKOV as Stepan +A. BOGDANOVA as Grandma B. KOKOVKIN as Chernov +Ye. +KUPRIANOVA as Anna Mikhailovna +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Your jacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools then the children are fools +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +Boris is working day and night. +I'm not waiting for anyone. +Verónica. +In time of war, one should not get confused. +One should hold on to +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I doubt it. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself! +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +there's so much excitement. +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders.. +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma.. +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down.. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee.. +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee.... +Comrade Boris, you must fight to the last drop of your blood +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd better join us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don't just sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside.. +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there.. +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding.. +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline.... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the devil I'v got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once.. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +I'm doing all right as a girl. +Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +So, Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave me alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse.? +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +I've been saving this for you. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well.... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don't just stand there. +Give the flowers to whoever they're for +Thank you very much, sister. +Oh, what a darling! +What a chubby little darling! +Look, the cranes are flying over Moscow! +The End +Uploaded by George M +MOSFILM +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +Director of Photography S. URUSEVSKY +Associate Director +- B. FRIDMAN Production Designer +- Y. SVIDETELEV +Music by M. VAINBERG Sound by I. MAYOROV +English subtitles by T. KAMENEVA +Starring +T. SAMOILOVA as Veronica A. BATALOV as Boris +V. MERKURIEV as Feodor Ivanovich +A. SHVORIN as Mark S. KHARITONOVA as Irina +K. NIKITIN as Volodya V. ZUBKOV as Stepan +A. BOGDANOVA as Grandma B. KOKOVKIN as Chernov +Ye. +KUPRIANOVA as Anna Mikhailovna +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Your jacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools and the parents are no better. +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica! +In time of war, one should not get confused. +One should hold on to a normal life pace. +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I doubt it. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself! +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it. +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet, I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +there's so much excitement... +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders. +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry. +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma... +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee. +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee... +Comrade Boris, you must fight to the last drop of your blood. +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd better join us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don't just sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march! +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside. +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there. +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding. +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you. +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away! +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the devil I'v got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes. +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +I'm doing all right as a girl. +Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +So, Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave ma alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse. +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +I've been saving this for you. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield. +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children, that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don't just stand there. +Give the flowers to whoever they're for. +Thank you very much, sister. +Oh, what a darling! +What a chubby little darling! +Look, the cranes are flying over Moscow! +The End +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships sailing up in the sky, +White ones and grey ones, with long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Your jacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools. +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +I'm not waiting for anyone. +Verónica. +In time of war, one should not get confused. +One should hold on to. +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I don't know. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself, you know? +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it. +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +there's so much excitement. +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders... +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry. +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma.. +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down.. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee... +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee... +Comrade Boris, you must fight to the last drop of your blood +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd better join us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don't just sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march. +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside... +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there... +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding... +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you. +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away. +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the hell I've got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes. +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +- I'm doing all right as a girl. +- Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave me alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse? +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +Here you are. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +Feodor? +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield. +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don't just stand there. +Give the flowers to whoever they're for. +Thank you very much, sister. +Oh, what a darling! +Look, the cranes are flying over Moscow! +The End +Stop, Squirrel. +Put them on. +Look! +"Cranes like ships, sailing in the sky +White ones, grey ones With long beaks they fly" +Look, look! +There you go. +You and your "cranes like ships." +THE CRANES ARE FLYI NG +Screenplay V. ROZOV +Director M. KALATOZOV +Cinematography S. URUSEVSKY +STARRI NG +Veronica T. SAMOI LOVA +Boris A. BATALOV +Fyodor Ivanovich V. MERKURYEV +Mark A. SHVORI N +A PRODUCTION OF MOSFI LM 1957 +Who's there? +Wait. +Well, okay. +When? +- Thursday, at the embankment. +- Come on, that's too long! +Squirrel! +We haven't finished. +Squirrel! +When? +What time on Thursday? +No, I can't. +I'll be at the factory. +Okay. +Don't be late! +Squirrel! +She's crazy about him. +And he about her. +That's what love is, my dear: +a harmless mental illness. +Why aren't you in bed yet, Grandma? +It's already time to get up, Boris! +Quit making noise! +Running around all night... +You're just jealous. +Did you tear it? +Your jacket's all in one piece. +Disgraceful! +Twelve o'clock, and he's still asleep. +He works a lot. +He's tired. +Let him at least get some sleep on Sunday. +This "work" of his will end in a wedding. +You're just afraid of losing him. +Irina's mind should be on her thesis, not on a wedding. +Watch out, Uncle Fedya. +She almost has her doctorate and you're still just a physician. +Well, if children don't surpass their parents, then the parents are bad and the children not much better. +Thanks, Mama. +Important announcement! +What's going on? +Boris! +War! +You hear me? +War! +Leave me alone. +Hello. +Boris is at the factory day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica. +In wartime, it's important not to lose your head. +Try to live a normal life. +Like me... +I dream of dedicating a piano concerto to you. +Will you come to hear it? +- Won't you be drafted? +Drafted? +I don't know. +I doubt it. +And why is that? +The most talented people will be exempt. +- And you suppose you're talented? +- Yes. +Why are you always following me around? +You ought to be ashamed. +I am. +I promised myself a thousand times I wouldn't. +I know Boris is my cousin, but I can't help myself! +You understand? +I can't. +Wait! +There's no need to escort me. +Watch out! +You'll hurt your leg. +It'll be harder at the front, my dear Boris. +They won't let you go to the front. +There will be only one exemption. +Either for you or for me. +That's right. +So you should stay. +You've got knowledge and experience. +And you've got something more important... talent. +Take care of your drawings. +You know, my wife's already got my bags packed. +Well, as they say, let's get our bayonets ready! +Stepan! +Excuse me, Sachkov. +Well? +Where's the notice? +Nothing yet. +I don't understand why they're so slow. +Are you going home? +- No, I'm... +- Oh, I see. +Well, say hello to her! +- I will. +What? +- Have you told her? +- No. +Why should I rush it? +- You're right. +See you tomorrow. +- Take care! +- Let go. +- I won't let go. +You're gonna fall! +Let go. +You'll tear the shade. +- It's a blanket. +- Let go. +I'll call the police. +- I'm tired of these blackouts! +Give it to me! +- You're gonna fall. +- I am not. +Squirrel, stop it. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- So? +- He's handsome. +So? +- Are you jealous? +- What? +- Are you jealous? +- I don't have the time. +Too bad. +I think I'll enroll at the Architectural Institute. +- They won't accept you. +- Yes, they will. +I doubt it. +Cranes like ships sailing in the sky +White ones, grey ones with long beaks they fly +Do you like my song? +Very profound. +Little croaking frogs Why didn't you look up? +You kept on hopping and jumping That's why you got eaten up +Eaten! +Well, hero, did you win? +I won, I won. +I won. +Do you think you'll be drafted? +- Of course. +- Would you volunteer? +- I might. +No, you won't! +You know very well you'll be exempt. +That's why you talk so big. +- What makes you so sure? +- I know. +All the smart ones will be exempt. +So only fools will fight? +I don't want to discuss it any further. +Veronica... +I want to talk to you about something. +Well, I don't. +And please don't call me Veronica. +Who am I? +- Squirrel. +- That's right. +Listen. +What will you give me tomorrow? +It's a secret. +If it's something good to eat, I'll eat it and forget about it. +Give me something I will always remember, for as long as I live. +Kiss me. +You know, when you're with me, +I'm not afraid of anything, not even the war. +I'm afraid of the police. +Veronica. +You know what? +Do you know? +For the wedding I'm going to make a white dress. +Like the one my grandma had. +And a long, long veil. +And you'll wear a black suit, and we'll go... +- To the registry office. +- Agreed then? +- Agreed. +You know, I like this blackout. +What's so good about it? +Hey! +Stepan! +I have a treat for you. +- What is it? +- It's a secret. +- Did it arrive? +- It did. +Why didn't you say so? +Tell me. +Things are crazy at the factory! +The guys ran to the barber's. +I went straight to your place. +- Make it short. +- Just wait. +So I was saying, the guys ran... +Listen, can't you make it shorter? +- Your family's worried. +- What time do we report? +Today at 5:00. +With your things. +Look at these cherries. +- What is it? +- Beautiful. +The notice came. +Really? +For you? +Yes, for me too. +We both volunteered. +What? +You volunteered? +But the notice came... +Wait. +What about me? +I'd better go home. +I've got a lot going on there too. +Squirrel. +I didn't want to tell you. +Tomorrow's your birthday. +I have to go. +Of course. +Squirrel. +What's the matter? +Cranes like ships +You like my poem? +Nothing will happen to me. +You hear? +And then you and I will live for a long, long time. +A hundred years. +Go. +We'll say good-bye later. +All right. +Don't be late. +Can't he stay home until tomorrow? +He's a swine if he's still at Veronica's. +Boris! +- Did Dad call? +- Yes. +He's furious. +Why didn't you tell us? +To avoid scenes like this. +Go to the factory tomorrow and turn these over to Kuzmin, the engineer. +I will, I will. +What are you stuffing in there? +I'm running out for a bottle of wine. +Grandma, do me a favor. +Just a minute. +Will they send you to the front right away? +Probably. +Here... wait a minute. +Early tomorrow morning take this to her. +What is it? +It's her birthday tomorrow. +And later, if things are hard for her... +After all, this is war... +Help her out. +And if I die? +You've got no business dying, especially now that you know so many secrets. +I just might up and die. +Quiet. +That's Veronica. +No, it's Irina. +Thank God, you're home. +Boris! +Come over here. +What is this about? +You're 25 years old and you... +forgive me... act like a fool! +What are we? +Children? +Is this a game? +Hide-and-seek? +He wants adventure! +There's character for you. +Where are Irina and Mark? +Irina's making coffee. +Mark went out to buy some wine. +Coffee, wine! +What's wrong with people these days? +Irina! +Bring me the bottle from the medicine cabinet. +Boris! +Come here. +Where's Veronica? +- She'll be here any minute. +- Where is she? +She's busy. +This isn't right. +She should be here. +Her fiancé is leaving. +I'm not her fiancé. +- What are you, then? +- We're just... +You're just what? +That sounds suspicious. +- I don't mean it that way, Dad. +- Then what do you mean? +- Stop picking on me. +- Wait! +- Why are you bothering him? +- Here. +From the medicine cabinet. +- Go ahead and mix it properly. +- Here's the port. +Drink it yourself. +We'll have a real drink. +So, is everybody here? +Sit down. +It's Veronica! +Go meet your bride, Mr. Bridegroom! +Finally! +- We came from the factory to see Boris. +- Please come in. +And I thought the bride had arrived. +- We're from the plant. +- They told us to bring you these gifts. +Sorry. +This one. +- On behalf of the Plant Committee... +- And the Communist Youth League... +What you want to say is: +"Comrade Boris, fight to the last drop of blood, and beat the fascists! +And we at the plant will meet and exceed our production quotas." +We've heard all that before. +Why don't you sit down with us, girls, and drink to my son Boris! +Things in this world aren't going as smoothly as we might like. +So now you're off to war, Boris... +- Let's have a drink! +- To you! +A glass for Grandma. +We sent our brother off yesterday. +Mother cried and cried. +What about you? +- I cried too. +- On behalf of the Plant Committee? +- No, on my own. +- Don't embarrass her. +We've got no one to send off. +There's just Mother and three girls. +We even felt a little ashamed, with all the others leaving... +When our men come back, you'll envy us. +The trouble is not all of them will come back. +For those who don't, we'll build a monument reaching to the sky with every one of their names in gold. +Irina, pour another round. +What are you waiting for? +I'll just put these away. +Well, you folks in the rear, meet and exceed your quotas! +Grandma, don't forget. +Mark, don't go. +Stay with Father. +- I'll walk you to the trolley. +About face! +Guards, forward march! +- Mother! +- The last time. +I'm sorry. +Not in the mood for a drink? +Where are you going? +- I'm going on duty. +You were on duty yesterday. +Varvara Kapitanova, may I see Boris for just a moment? +- He already left. +- He left? +Where did he go? +- To the assembly station. +- Oh, no. +- Come in. +- Where's the assembly station? +- I don't know. +- What's this? +- It's from Boris, for your birthday. +There's a note too. +- Where's the note? +- Isn't it there? +He must have forgotten in the rush. +Forgotten? +He'll write to you. +Where were you? +- Where's the assembly station? +- It's on Zvenigorodskaya. +Don't worry. +She'll come. +Even if she does, how will she find me in this crowd? +What are you doing? +Boris, where's Veronica? +Write to me every day. +Who has the invoices for the cauliflower? +Don't forget to send your field address. +Cheer up, pug-nose! +Take care! +Fall in! +She'll come. +Boris! +Fall in! +Forward march! +There's my kitten. +Grandma? +Nothing? +He hasn't written to me either. +- Anything? +- No. +Oh, this war. +Well, rain or shine, we must carry on. +Have you decided where you'll work? +I'll go to the war factory. +Citizens! +Air raid alert! +Hurry down to the subway. +I've got some urgent work to do. +Go get your things. +Where's the backpack? +- The backpack? +It's right there. +I won't go without you. +If it becomes dangerous, we'll go down to the shelter. +Go now. +Be careful in the subway. +She's so scared, poor girl! +- What about you? +When Veronica is safe and you're by my side, I'm not afraid. +They're still at it, the brutes. +Those parasites won't even let us talk! +For some reason he doesn't write to me. +It's the war. +The mail is so slow. +All clear. +The air raid is over. +Let's go. +Well, my place is right here. +If you decide to come join us, call me at the factory. +- Okay. +- Good-bye. +Where are you going? +Get back! +Where do you think you're going? +I'm sorry. +Veronica, you'll stay with us from now on. +Boris' room is free for now. +Mark will share a room with Fedya. +Mark, we must take good care of her. +Unfortunately, Irina and I are at the hospital day and night. +I'll try, Uncle Fedya. +Boris spoke to me about it. +Are you all right now? +Is this the factory? +May I speak to Kuzmin, please? +He's gone to the front too? +Excuse me. +Is there any news from Boris Borozdin? +If it weren't for the damned war, +I'd be playing this at Tchaikovsky Hall. +For you. +- Veronica, let's go to the subway. +- I'm not going. +- That's nonsense! +Let's go. +- Are you afraid? +Only for your sake. +Come on, let's go. +I'm not afraid of anything. +Veronica, let's go! +Don't be foolish. +You're acting crazy! +I won't go! +I won't, I won't, I won't! +I love you. +No. +I love you. +I love you. +I love you! +- Go away! +I love you. +What a stupid way to get surrounded. +- Stepan, stop whining. +- What do you mean, stop whining? +The captain said we might break through by tonight. +- At last! +Sachkov! +- Here! +Where's this rookie from? +Straight from an incubator. +A fresh reinforcement. +Now we'll break through for sure. +Is that any way to speak to a married man? +- Is that right? +- I got married in school. +See what education does to people. +You funny guys, always joking! +Laughed yourselves right into a trap. +Volodka, are you really married? +Are you kidding? +Sounds better, though, doesn't it? +Borozdin! +You'll go out on reconnaissance. +Your job is to find the best place to break through. +Turn over your papers. +- Yes, sir. +Hey, Sachkov! +Come on, help me here. +Let's take a break, guys, and have a smoke. +She's always laughing like that. +- They must think we're dead. +Let me see that beauty. +Yep, the life of a soldier. +You're over here, and she's... +And she's what? +Give me the harmonica. +Sachkov, hold it for a second! +Stop it! +Aren't you ashamed? +- No. +Five days' arrest. +You'll both go on reconnaissance. +Turn in your papers. +Boris, here. +Because of her? +She's worth fighting for. +- Exactly. +Stop that chatter! +Discipline! +Hear that? +Discipline. +Stepan, hold on to this. +Just don't lose it. +We're getting married, Uncle Fedya. +I forgot... +I still have some sausage. +- Keep your head down. +- Stop giving me orders. +- Let's get out of here or they'll get us. +- Run if you're scared. +You idiot! +Hey, you! +Musician! +You deaf? +How the hell did I get stuck with him? +What's wrong? +Hey, you! +Go on alone. +I want to rest for a bit. +- Are you wounded? +Hold on to me. +- Leave me alone. +Hold on to me, I said, and hold on tight! +Here, get on my back. +It'll be faster this way. +Leave me here. +- Idiot! +You're sore because I punched you. +- You were just lucky l... +Shut up. +We'll settle it later. +Hold on, hold on. +A little further to the woods, and then we're safe. +I'm tired. +Let's rest a bit. +It's quieter here. +So, are you alive? +- It's a little hard to breathe. +- To breathe? +We'll dance at your wedding yet. +Hey, buddy! +What's the matter? +Forgive me. +Forgive me. +Forgive me, friend! +Hey, somebody, help! +Help! +Help! +Boris! +What's wrong, Boris? +Are you wounded? +I'm not wounded. +I... +The Soviet Information Bureau reports no important changes on the fronts in the last 2 4 hours. +No important changes. +That's good. +Families evacuated with Moscow Plant 3 26 will be quartered on Vostaniya Street. +Comrades, report here. +Irina, help this wounded man. +- The paramedics will be here soon. +- Yes. +Unload! +Siberia. +We can't retreat much farther. +This is what's become of Mother Russia. +Attention, attention! +Chief of Hospital Number 4, Borozdin, report to the military commandant. +Perhaps we'll find some peace here. +Clear the way, folks. +The stove is smoking. +I'm sorry. +You can daydream when the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +She's always waiting for a letter. +From whom? +Her husband's right here. +Not like us, soldiers' wives. +She's not waiting for a letter from anyone. +- Are you on the second shift at school? +- Yes. +"Cranes like ships sailing in the sky." +Those silly lines are stuck in my head. +There it is. +- What? +The mail. +If I can count up to 50, there'll be a letter for me. +- Veronica, this is crazy. +...16, 17, 18, 19 20, 21... +- Stop! +...45, 46, 47... +- Hello. +- Hello. +There's nothing for you. +For you. +Lededeva? +- That's me. +- Palyukaitis? +- Nothing. +From my eldest son on the Ukrainian front. +I didn't know Boris, but everyone says he was a gifted young man. +Was? +Missing doesn't mean dead. +Of course not. +That didn't come out right. +What's the matter, Veronica? +I'm dying, Anna Mikhailovna. +My dear, what are you saying? +- I've lost everything. +- You have your life ahead of you. +I don't want to live! +What's the use? +- Forget the past. +It's human nature to forget. +I don't want to forget. +There's nothing I need to forget. +You mustn't punish yourself forever. +I must. +Till the end. +You teach history. +You're an intelligent woman. +Tell me: +What is the meaning of life? +The meaning of life? +Perhaps it's that... +Was Chernov here? +No. +Boy, am I hungry! +If Chernov comes, try to be polite. +He's revolting. +I may find him even more revolting than you do, but he's the boss. +Why do you always kiss up to him? +Dear Veronica, you're impossible. +You're always so irritable, and you keep picking on me. +Tell me what I can do for you. +I wish you had never been born. +Come in! +- I hope I'm not intruding. +- We're always happy to see you. +Make yourself comfortable. +Did you hear? +The Germans have advanced in the Caucasus. +It's awful. +But don't worry. +We'll show them yet. +Please, make yourself comfortable. +Your place is cozy. +My wife and children are in Tashkent, so I live like a homeless tramp. +Hello, Veronica. +- Where are you going, dearest? +- I'm on duty at the hospital. +- Bundle up. +It's very cold. +I admire your wife. +She's always so candid, so pure. +She must be very happy with you. +I looked for you today at the Philharmonic. +- Was there a concert? +- No. +Will you be at the birthday party tonight? +Probably. +- What will you take for a gift? +- What can I give? +Yes... the war. +It's nothing great, but attach a little something to it and I'm sure Antonina will be very happy. +It's wonderful. +How much do I owe you? +- It's nothing. +Don't mention it. +- Thanks very much. +Mark, I have a favor to ask. +Is there anyone upstairs? +No. +Do you think you could ask Fyodor Ivanovich for some medicine? +Good job, Irina. +He's going to live. +I hope so. +He'll be a real swine if he dies. +Irina, you should have been born a man! +I feel pretty good as a woman. +Veronica, why are you so early? +The clock was fast. +Poor girl. +I'll never forgive what she did to Boris. +Here comes another batch! +I've told you already, we're full! +This is a hospital, not a sardine can! +Where are they all from? +Kalach? +- Stalingrad. +Some from the front, some from the hospital. +There's no room. +Don't worry, they'll make room. +I'll take 80 men. +The rest will have to go to other hospitals. +Now, then... give my regards to Uncle Sergei, +Fyodor, Vassily, +Aunt Marya, Agrafena, +Katerina, Varvara, +Nikolai, +Katerina. +You already said Katerina. +This is a different Katerina. +- Then you should say so. +- It's okay. +They'll figure it out. +So... +Zinaida, +Antonina, Kuzma... +Nurse! +What's the matter, Vorobyev? +Nothing. +I want the nurse. +He needs the bedpan. +I'll get it for you. +Thank you. +That's lovely music. +Turn up the radio, please. +Turn off that music! +Turn that music off! +You hear me? +Who yelled? +I did! +What's it to you? +- Zakharov, what's wrong? +- Go away! +He's losing his mind. +He got word from home this morning. +His girlfriend didn't wait for him. +She married someone else, the bitch. +He hasn't eaten all day. +Try to comfort him. +Broads like that are worse than fascists. +They aim right at the heart. +You have to eat, Zakharov, or you won't get well. +I don't want to get well! +I want to die! +Call the doctor! +Calm down. +All because of some broad! +Call the doctor! +Quit yelling! +Shut up! +Where will they take us now? +There are plenty of hospitals in the world. +The head doctor's coming, boys! +Stop it this minute! +You're still a soldier in the Red Army! +Are you trying to get discharged? +Are you afraid we'll heal your hands and send you back to the front? +No, Doctor, he's not like that. +He got a letter. +- I know. +That's just an excuse. +Big deal! +So your bride ran off. +You should be glad! +She isn't worth a penny if she would trade a handsome guy like you, a real hero, for some rat sitting out the war at home! +It's she who's forfeited her happiness, not you! +And that's what she deserves. +That's right. +She's got a petty soul. +People like her can't understand how much suffering we've gone through. +Killing people like her would be too kind! +You stood up to Death itself. +You looked death in the face. +You approached it with your chest stuck out. +And she couldn't even pass the little test of time. +Women like her deserve only our contempt. +There can be no forgiveness for them! +Bandage him up. +Aunt Sima, bring him some tea and porridge. +Don't be a brat. +Veronica... +You idiot! +Keep an eye on your kid! +And it would have been my fault! +Just standing there with your mouth open like an idiot! +- Whose boy are you? +- Mama's. +- Where are you from? +- Voroshilovgrad. +- How old are you? +- Three months and three years. +What's your name? +Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert at the hospital. +- Can't you tell a better lie? +- All right, all right. +- Is Mark here? +- He is now. +- Here. +- Thank you, Anna. +A little boy is having a birthday and I wanted to give him a present. +You are a kind man after all, Mark Alexandrovich. +"The symptoms of such compound fractures depend on the degree of changes in the joints, as well as on the location." +Interesting, but unintelligible. +Why, I think it's quite clear. +What's this? +What kind of trick is this? +What trick? +He lost his parents at the station. +You should have taken him to the shelter for lost kids. +I don't want to go to the shelter! +Go there yourself! +- Rude child! +- You're rude. +Quiet, quiet. +We'll go find Mommy in Voroshilovgrad. +Stop that noise! +It's hurting my ears. +Here, play with this cap! +Here's a bagel for you. +- My eardrums will burst! +- We need to find a toy for him. +Irina, take him for a minute. +So now I have to hold him too? +Here, give him to me. +Come to me, little one. +I'll get you ready for bed. +Has anyone seen my squirrel? +Mark took it. +Mark? +Where'd he take it? +To give to some little boy as a present. +Some little boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +Where did he go? +You know, don't you? +Where? +Probably to see Antonina. +What Antonina? +Ask Mark. +- Tell me. +- Don't give me orders. +Mark... visits her occasionally. +You understand? +- You're saying this to hurt me. +- Why would I? +Just to spite me! +I'm loved. +I have a husband. +And you're still an old maid. +She lives in a small house near that large market. +You can check it out for yourself. +It's okay, it's okay. +I have to do something, I have to do something. +Talk to Mark when he comes back. +You should wait. +Wait? +Always waiting. +I'm always waiting. +I've had enough! +What use are words +Let lips fall silent +Sometimes +They tell lies +The eyes alone +Will never dare +To lie to other eyes +My eyes are now +Dark and sad +As though someone +Had blown out their flame +In Leningrad on my birthday, we'd take a car and go from one end of the city to the other. +Let's go for a ride! +In these times, Antonina, a car is worth its weight in gold, and gasoline is rationed. +Any kind of vehicle. +I beg you! +A fire engine, an ambulance, a truck. +Anything you like. +A ride against the forces of nature! +Just the two of us? +To forget everything else. +I'll try. +I love you. +Sorry. +I don't dance. +I thought I had tried everything, but I've never tried golden nuts. +Look, a message. +A birthday note for me? +So it's for your birthday? +Where's my squirrel? +Don't get the wrong idea. +There's a note from someone named Boris. +"My only love, happy birthday to you." +On this day you came into this world. +It's hard to leave you. +But what can we do? +This is war. +There's no way around it. +We can't continue living happily as we did before when death stalks our land. +But we'll be happy yet. +I love you. +I have faith in you. +Your Boris. +What are you so excited about? +Go home. +I'll be there soon. +What's that for? +Take your coat off. +Thank you. +You know, as usual all the Philharmonic's cars are taken, and I need one badly. +You're the head surgeon and all. +Surely you won't refuse... +We're very short on vehicles. +It was hard to do what I did for you, but I did it. +When you asked me to, I did my best. +What did I ask? +For an exemption. +It's about to expire, and this time, getting a new one will be practically impossible. +- What exemption? +- For Mark Alexandrovich. +Don't worry. +Not a soul will know about this. +Is it possible he lied to both of us? +He even offered me money in your name. +I'm sorry. +Very good. +Uncle Fyodor, +I turn to you for help. +Her behavior's impossible. +She stormed into a stranger's place, started a fight... +Shut the door. +Do you think anyone wants to send his son to war? +What are you talking about? +Or do you think others must pay for your welfare, for your life, with their hands, their legs, their eyes, their lives, +and you owe nothing to anyone? +I have an exemption, Uncle Fedya. +An exemption? +Tell me, how did you get it? +Why are you doing this? +It's okay. +I'll rent a room, I'll take Boris... +Perhaps someone else had better rent himself a room. +Gladly! +I've thought about doing that for a long time. +Why didn't you throw me out in the first place? +You've been through a terrible ordeal. +Only someone without a heart could reproach you. +Stay with us. +I can't. +I don't want to hide behind someone else's back. +I won't! +Think it over. +Could you tell me where the Borozdins live? +They live here. +Which of them do you want to see? +- Fyodor Ivanovich. +He's not home. +Did Boris send you? +What Boris? +No, I came on my own. +I must speak to Fyodor Ivanovich. +- Have a seat. +- Thank you. +He'll be home soon. +- May I go for a walk? +- You may. +Is he yours? +He looks like you. +Are you a relation of the Borozdins? +Not exactly. +You see, I'm out of the army. +Going home? +It's unlikely. +There's still a blockade around Leningrad. +I'm in a difficult situation. +- What is it? +- It's easy to tell you. +You're not part of the family. +Fyodor Ivanovich's son was killed. +Where? +West of Smolensk. +What shall I play for you? +Whatever you like. +Did you see him buried? +No. +I was injured and they carried me away on a stretcher, but a friend of his, Stepan, went up to him. +Now I have to find his girlfriend. +He loved her very much. +That's me. +Vladimir, come to see us if you're ever in Moscow. +Thank you. +I'll do that. +The war's over. +Strange, isn't it? +And you're still waiting? +Yes, I am. +One must always hope for the best. +Why do you delude yourself? +I saw it with my own eyes. +What did you see? +How he was wounded? +How he fell? +But you didn't see him die with your own eyes. +No... but why haven't you heard from him? +A lot of things could have happened. +There's no word from Stepan either. +At the factory they know he's in some special unit and will be back soon. +Dasha promised to tell me when he's back. +Boris is alive. +He's alive. +- Look, here they come! +- The victors are coming! +Boris! +- Veronica! +- Stepan! +Flowers for you. +Well? +What? +You see... +Here. +Dear mothers, fathers, sisters and brothers! +The happiness of our reunion is immeasurable. +The heart of every Soviet citizen is filled with joy. +Joy sings in our hearts. +It is victory that has brought us this joy. +We have all waited for this moment. +Everyone's dizzy with happiness. +But we shall not forget those left behind on the battlefield. +Time will pass. +Towns and villages will be rebuilt. +Our wounds will heal. +But our fierce hatred of war will never diminish! +We share the grief of those who cannot meet their loved ones today, and we will do everything to insure that sweethearts are never again parted by war, that mothers need never again fear for their children's lives, +that fathers need never again choke back hidden tears. +We have won, and we shall live not to destroy, but to build a new life! +Why are you just standing there? +Give your flowers to whomever they're for. +Thank you, sister. +My beautiful granddaughter! +Look, look! +Cranes are flying over Moscow! +THE END +Stop, Squirrel. +Put them on. +Look! +"Cranes like ships, sailing in the sky +White ones, grey ones With long beaks they fly" +Look, look! +There you go. +You and your "cranes like ships." +THE CRANES ARE FLYI NG +Screenplay V. ROZOV +Director M. KALATOZOV +Cinematography S. URUSEVSKY +STARRI NG +Veronica T. SAMOI LOVA +Boris A. BATALOV +Fyodor Ivanovich V. MERKURYEV +Mark A. SHVORI N +A PRODUCTION OF MOSFI LM 1957 +Who's there? +Wait. +Well, okay. +When? +- Thursday, at the embankment. +- Come on, that's too long! +Squirrel! +We haven't finished. +Squirrel! +When? +What time on Thursday? +No, I can't. +I'll be at the factory. +Okay. +Don't be late! +Squirrel! +She's crazy about him. +And he about her. +That's what love is, my dear: +a harmless mental illness. +Why aren't you in bed yet, Grandma? +It's already time to get up, Boris! +Quit making noise! +Running around all night... +You're just jealous. +Did you tear it? +Your jacket's all in one piece. +Disgraceful! +Twelve o'clock, and he's still asleep. +He works a lot. +He's tired. +Let him at least get some sleep on Sunday. +This "work" of his will end in a wedding. +You're just afraid of losing him. +Irina's mind should be on her thesis, not on a wedding. +Watch out, Uncle Fedya. +She almost has her doctorate and you're still just a physician. +Well, if children don't surpass their parents, then the parents are bad and the children not much better. +Thanks, Mama. +Important announcement! +What's going on? +Boris! +War! +You hear me? +War! +Leave me alone. +Hello. +Boris is at the factory day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica. +In wartime, it's important not to lose your head. +Try to live a normal life. +Like me... +I dream of dedicating a piano concerto to you. +Will you come to hear it? +- Won't you be drafted? +Drafted? +I don't know. +I doubt it. +And why is that? +The most talented people will be exempt. +- And you suppose you're talented? +- Yes. +Why are you always following me around? +You ought to be ashamed. +I am. +I promised myself a thousand times I wouldn't. +I know Boris is my cousin, but I can't help myself! +You understand? +I can't. +Wait! +There's no need to escort me. +Watch out! +You'll hurt your leg. +It'll be harder at the front, my dear Boris. +They won't let you go to the front. +There will be only one exemption. +Either for you or for me. +That's right. +So you should stay. +You've got knowledge and experience. +And you've got something more important... talent. +Take care of your drawings. +You know, my wife's already got my bags packed. +Well, as they say, let's get our bayonets ready! +Stepan! +Excuse me, Sachkov. +Well? +Where's the notice? +Nothing yet. +I don't understand why they're so slow. +Are you going home? +- No, I'm... +- Oh, I see. +Well, say hello to her! +- I will. +What? +- Have you told her? +- No. +Why should I rush it? +- You're right. +See you tomorrow. +- Take care! +- Let go. +- I won't let go. +You're gonna fall! +Let go. +You'll tear the shade. +- It's a blanket. +- Let go. +I'll call the police. +- I'm tired of these blackouts! +Give it to me! +- You're gonna fall. +- I am not. +Squirrel, stop it. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- So? +- He's handsome. +So? +- Are you jealous? +- What? +- Are you jealous? +- I don't have the time. +Too bad. +I think I'll enroll at the Architectural Institute. +- They won't accept you. +- Yes, they will. +I doubt it. +Cranes like ships sailing in the sky +White ones, grey ones with long beaks they fly +Do you like my song? +Very profound. +Little croaking frogs Why didn't you look up? +You kept on hopping and jumping That's why you got eaten up +Eaten! +Well, hero, did you win? +I won, I won. +I won. +Do you think you'll be drafted? +- Of course. +- Would you volunteer? +- I might. +No, you won't! +You know very well you'll be exempt. +That's why you talk so big. +- What makes you so sure? +- I know. +All the smart ones will be exempt. +So only fools will fight? +I don't want to discuss it any further. +Veronica... +I want to talk to you about something. +Well, I don't. +And please don't call me Veronica. +Who am I? +- Squirrel. +- That's right. +Listen. +What will you give me tomorrow? +It's a secret. +If it's something good to eat, I'll eat it and forget about it. +Give me something I will always remember, for as long as I live. +Kiss me. +You know, when you're with me, +I'm not afraid of anything, not even the war. +I'm afraid of the police. +Veronica. +You know what? +Do you know? +For the wedding I'm going to make a white dress. +Like the one my grandma had. +And a long, long veil. +And you'll wear a black suit, and we'll go... +- To the registry office. +- Agreed then? +- Agreed. +You know, I like this blackout. +What's so good about it? +Hey! +Stepan! +I have a treat for you. +- What is it? +- It's a secret. +- Did it arrive? +- It did. +Why didn't you say so? +Tell me. +Things are crazy at the factory! +The guys ran to the barber's. +I went straight to your place. +- Make it short. +- Just wait. +So I was saying, the guys ran... +Listen, can't you make it shorter? +- Your family's worried. +- What time do we report? +Today at 5:00. +With your things. +Look at these cherries. +- What is it? +- Beautiful. +The notice came. +Really? +For you? +Yes, for me too. +We both volunteered. +What? +You volunteered? +But the notice came... +Wait. +What about me? +I'd better go home. +I've got a lot going on there too. +Squirrel. +I didn't want to tell you. +Tomorrow's your birthday. +I have to go. +Of course. +Squirrel. +What's the matter? +Cranes like ships +You like my poem? +Nothing will happen to me. +You hear? +And then you and I will live for a long, long time. +A hundred years. +Go. +We'll say good-bye later. +All right. +Don't be late. +Can't he stay home until tomorrow? +He's a swine if he's still at Veronica's. +Boris! +- Did Dad call? +- Yes. +He's furious. +Why didn't you tell us? +To avoid scenes like this. +Go to the factory tomorrow and turn these over to Kuzmin, the engineer. +I will, I will. +What are you stuffing in there? +I'm running out for a bottle of wine. +Grandma, do me a favor. +Just a minute. +Will they send you to the front right away? +Probably. +Here... wait a minute. +Early tomorrow morning take this to her. +What is it? +It's her birthday tomorrow. +And later, if things are hard for her... +After all, this is war... +Help her out. +And if I die? +You've got no business dying, especially now that you know so many secrets. +I just might up and die. +Quiet. +That's Veronica. +No, it's Irina. +Thank God, you're home. +Boris! +Come over here. +What is this about? +You're 25 years old and you... +forgive me... act like a fool! +What are we? +Children? +Is this a game? +Hide-and-seek? +He wants adventure! +There's character for you. +Where are Irina and Mark? +Irina's making coffee. +Mark went out to buy some wine. +Coffee, wine! +What's wrong with people these days? +Irina! +Bring me the bottle from the medicine cabinet. +Boris! +Come here. +Where's Veronica? +- She'll be here any minute. +- Where is she? +She's busy. +This isn't right. +She should be here. +Her fiancé is leaving. +I'm not her fiancé. +- What are you, then? +- We're just... +You're just what? +That sounds suspicious. +- I don't mean it that way, Dad. +- Then what do you mean? +- Stop picking on me. +- Wait! +- Why are you bothering him? +- Here. +From the medicine cabinet. +- Go ahead and mix it properly. +- Here's the port. +Drink it yourself. +We'll have a real drink. +So, is everybody here? +Sit down. +It's Veronica! +Go meet your bride, Mr. Bridegroom! +Finally! +- We came from the factory to see Boris. +- Please come in. +And I thought the bride had arrived. +- We're from the plant. +- They told us to bring you these gifts. +Sorry. +This one. +- On behalf of the Plant Committee... +- And the Communist Youth League... +What you want to say is: +"Comrade Boris, fight to the last drop of blood, and beat the fascists! +And we at the plant will meet and exceed our production quotas." +We've heard all that before. +Why don't you sit down with us, girls, and drink to my son Boris! +Things in this world aren't going as smoothly as we might like. +So now you're off to war, Boris... +- Let's have a drink! +- To you! +A glass for Grandma. +We sent our brother off yesterday. +Mother cried and cried. +What about you? +- I cried too. +- On behalf of the Plant Committee? +- No, on my own. +- Don't embarrass her. +We've got no one to send off. +There's just Mother and three girls. +We even felt a little ashamed, with all the others leaving... +When our men come back, you'll envy us. +The trouble is not all of them will come back. +For those who don't, we'll build a monument reaching to the sky with every one of their names in gold. +Irina, pour another round. +What are you waiting for? +I'll just put these away. +Well, you folks in the rear, meet and exceed your quotas! +Grandma, don't forget. +Mark, don't go. +Stay with Father. +- I'll walk you to the trolley. +About face! +Guards, forward march! +- Mother! +- The last time. +I'm sorry. +Not in the mood for a drink? +Where are you going? +- I'm going on duty. +You were on duty yesterday. +Varvara Kapitanova, may I see Boris for just a moment? +- He already left. +- He left? +Where did he go? +- To the assembly station. +- Oh, no. +- Come in. +- Where's the assembly station? +- I don't know. +- What's this? +- It's from Boris, for your birthday. +There's a note too. +- Where's the note? +- Isn't it there? +He must have forgotten in the rush. +Forgotten? +He'll write to you. +Where were you? +- Where's the assembly station? +- It's on Zvenigorodskaya. +Don't worry. +She'll come. +Even if she does, how will she find me in this crowd? +What are you doing? +Boris, where's Veronica? +Write to me every day. +Who has the invoices for the cauliflower? +Don't forget to send your field address. +Cheer up, pug-nose! +Take care! +Fall in! +She'll come. +Boris! +Fall in! +Forward march! +There's my kitten. +Grandma? +Nothing? +He hasn't written to me either. +- Anything? +- No. +Oh, this war. +Well, rain or shine, we must carry on. +Have you decided where you'll work? +I'll go to the war factory. +Citizens! +Air raid alert! +Hurry down to the subway. +I've got some urgent work to do. +Go get your things. +Where's the backpack? +- The backpack? +It's right there. +I won't go without you. +If it becomes dangerous, we'll go down to the shelter. +Go now. +Be careful in the subway. +She's so scared, poor girl! +- What about you? +When Veronica is safe and you're by my side, I'm not afraid. +They're still at it, the brutes. +Those parasites won't even let us talk! +For some reason he doesn't write to me. +It's the war. +The mail is so slow. +All clear. +The air raid is over. +Let's go. +Well, my place is right here. +If you decide to come join us, call me at the factory. +- Okay. +- Good-bye. +Where are you going? +Get back! +Where do you think you're going? +I'm sorry. +Veronica, you'll stay with us from now on. +Boris' room is free for now. +Mark will share a room with Fedya. +Mark, we must take good care of her. +Unfortunately, Irina and I are at the hospital day and night. +I'll try, Uncle Fedya. +Boris spoke to me about it. +Are you all right now? +Is this the factory? +May I speak to Kuzmin, please? +He's gone to the front too? +Excuse me. +Is there any news from Boris Borozdin? +If it weren't for the damned war, +I'd be playing this at Tchaikovsky Hall. +For you. +- Veronica, let's go to the subway. +- I'm not going. +- That's nonsense! +Let's go. +- Are you afraid? +Only for your sake. +Come on, let's go. +I'm not afraid of anything. +Veronica, let's go! +Don't be foolish. +You're acting crazy! +I won't go! +I won't, I won't, I won't! +I love you. +No. +I love you. +I love you. +I love you! +- Go away! +I love you. +What a stupid way to get surrounded. +- Stepan, stop whining. +- What do you mean, stop whining? +The captain said we might break through by tonight. +- At last! +Sachkov! +- Here! +Where's this rookie from? +Straight from an incubator. +A fresh reinforcement. +Now we'll break through for sure. +Is that any way to speak to a married man? +- Is that right? +- I got married in school. +See what education does to people. +You funny guys, always joking! +Laughed yourselves right into a trap. +Volodka, are you really married? +Are you kidding? +Sounds better, though, doesn't it? +Borozdin! +You'll go out on reconnaissance. +Your job is to find the best place to break through. +Turn over your papers. +- Yes, sir. +Hey, Sachkov! +Come on, help me here. +Let's take a break, guys, and have a smoke. +She's always laughing like that. +- They must think we're dead. +Let me see that beauty. +Yep, the life of a soldier. +You're over here, and she's... +And she's what? +Give me the harmonica. +Sachkov, hold it for a second! +Stop it! +Aren't you ashamed? +- No. +Five days' arrest. +You'll both go on reconnaissance. +Turn in your papers. +Boris, here. +Because of her? +She's worth fighting for. +- Exactly. +Stop that chatter! +Discipline! +Hear that? +Discipline. +Stepan, hold on to this. +Just don't lose it. +We're getting married, Uncle Fedya. +I forgot... +I still have some sausage. +- Keep your head down. +- Stop giving me orders. +- Let's get out of here or they'll get us. +- Run if you're scared. +You idiot! +Hey, you! +Musician! +You deaf? +How the hell did I get stuck with him? +What's wrong? +Hey, you! +Go on alone. +I want to rest for a bit. +- Are you wounded? +Hold on to me. +- Leave me alone. +Hold on to me, I said, and hold on tight! +Here, get on my back. +It'll be faster this way. +Leave me here. +- Idiot! +You're sore because I punched you. +- You were just lucky l... +Shut up. +We'll settle it later. +Hold on, hold on. +A little further to the woods, and then we're safe. +I'm tired. +Let's rest a bit. +It's quieter here. +So, are you alive? +- It's a little hard to breathe. +- To breathe? +We'll dance at your wedding yet. +Hey, buddy! +What's the matter? +Forgive me. +Forgive me. +Forgive me, friend! +Hey, somebody, help! +Help! +Help! +Boris! +What's wrong, Boris? +Are you wounded? +I'm not wounded. +I... +The Soviet Information Bureau reports no important changes on the fronts in the last 2 4 hours. +No important changes. +That's good. +Families evacuated with Moscow Plant 3 26 will be quartered on Vostaniya Street. +Comrades, report here. +Irina, help this wounded man. +- The paramedics will be here soon. +- Yes. +Unload! +Siberia. +We can't retreat much farther. +This is what's become of Mother Russia. +Attention, attention! +Chief of Hospital Number 4, Borozdin, report to the military commandant. +Perhaps we'll find some peace here. +Clear the way, folks. +The stove is smoking. +I'm sorry. +You can daydream when the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +She's always waiting for a letter. +From whom? +Her husband's right here. +Not like us, soldiers' wives. +She's not waiting for a letter from anyone. +- Are you on the second shift at school? +- Yes. +"Cranes like ships sailing in the sky." +Those silly lines are stuck in my head. +There it is. +- What? +The mail. +If I can count up to 50, there'll be a letter for me. +- Veronica, this is crazy. +...16, 17, 18, 19 20, 21... +- Stop! +...45, 46, 47... +- Hello. +- Hello. +There's nothing for you. +For you. +Lededeva? +- That's me. +- Palyukaitis? +- Nothing. +From my eldest son on the Ukrainian front. +I didn't know Boris, but everyone says he was a gifted young man. +Was? +Missing doesn't mean dead. +Of course not. +That didn't come out right. +What's the matter, Veronica? +I'm dying, Anna Mikhailovna. +My dear, what are you saying? +- I've lost everything. +- You have your life ahead of you. +I don't want to live! +What's the use? +- Forget the past. +It's human nature to forget. +I don't want to forget. +There's nothing I need to forget. +You mustn't punish yourself forever. +I must. +Till the end. +You teach history. +You're an intelligent woman. +Tell me: +What is the meaning of life? +The meaning of life? +Perhaps it's that... +Was Chernov here? +No. +Boy, am I hungry! +If Chernov comes, try to be polite. +He's revolting. +I may find him even more revolting than you do, but he's the boss. +Why do you always kiss up to him? +Dear Veronica, you're impossible. +You're always so irritable, and you keep picking on me. +Tell me what I can do for you. +I wish you had never been born. +Come in! +- I hope I'm not intruding. +- We're always happy to see you. +Make yourself comfortable. +Did you hear? +The Germans have advanced in the Caucasus. +It's awful. +But don't worry. +We'll show them yet. +Please, make yourself comfortable. +Your place is cozy. +My wife and children are in Tashkent, so I live like a homeless tramp. +Hello, Veronica. +- Where are you going, dearest? +- I'm on duty at the hospital. +- Bundle up. +It's very cold. +I admire your wife. +She's always so candid, so pure. +She must be very happy with you. +I looked for you today at the Philharmonic. +- Was there a concert? +- No. +Will you be at the birthday party tonight? +Probably. +- What will you take for a gift? +- What can I give? +Yes... the war. +It's nothing great, but attach a little something to it and I'm sure Antonina will be very happy. +It's wonderful. +How much do I owe you? +- It's nothing. +Don't mention it. +- Thanks very much. +Mark, I have a favor to ask. +Is there anyone upstairs? +No. +Do you think you could ask Fyodor Ivanovich for some medicine? +Good job, Irina. +He's going to live. +I hope so. +He'll be a real swine if he dies. +Irina, you should have been born a man! +I feel pretty good as a woman. +Veronica, why are you so early? +The clock was fast. +Poor girl. +I'll never forgive what she did to Boris. +Here comes another batch! +I've told you already, we're full! +This is a hospital, not a sardine can! +Where are they all from? +Kalach? +- Stalingrad. +Some from the front, some from the hospital. +There's no room. +Don't worry, they'll make room. +I'll take 80 men. +The rest will have to go to other hospitals. +Now, then... give my regards to Uncle Sergei, +Fyodor, Vassily, +Aunt Marya, Agrafena, +Katerina, Varvara, +Nikolai, +Katerina. +You already said Katerina. +This is a different Katerina. +- Then you should say so. +- It's okay. +They'll figure it out. +So... +Zinaida, +Antonina, Kuzma... +Nurse! +What's the matter, Vorobyev? +Nothing. +I want the nurse. +He needs the bedpan. +I'll get it for you. +Thank you. +That's lovely music. +Turn up the radio, please. +Turn off that music! +Turn that music off! +You hear me? +Who yelled? +I did! +What's it to you? +- Zakharov, what's wrong? +- Go away! +He's losing his mind. +He got word from home this morning. +His girlfriend didn't wait for him. +She married someone else, the bitch. +He hasn't eaten all day. +Try to comfort him. +Broads like that are worse than fascists. +They aim right at the heart. +You have to eat, Zakharov, or you won't get well. +I don't want to get well! +I want to die! +Call the doctor! +Calm down. +All because of some broad! +Call the doctor! +Quit yelling! +Shut up! +Where will they take us now? +There are plenty of hospitals in the world. +The head doctor's coming, boys! +Stop it this minute! +You're still a soldier in the Red Army! +Are you trying to get discharged? +Are you afraid we'll heal your hands and send you back to the front? +No, Doctor, he's not like that. +He got a letter. +- I know. +That's just an excuse. +Big deal! +So your bride ran off. +You should be glad! +She isn't worth a penny if she would trade a handsome guy like you, a real hero, for some rat sitting out the war at home! +It's she who's forfeited her happiness, not you! +And that's what she deserves. +That's right. +She's got a petty soul. +People like her can't understand how much suffering we've gone through. +Killing people like her would be too kind! +You stood up to Death itself. +You looked death in the face. +You approached it with your chest stuck out. +And she couldn't even pass the little test of time. +Women like her deserve only our contempt. +There can be no forgiveness for them! +Bandage him up. +Aunt Sima, bring him some tea and porridge. +Don't be a brat. +Veronica... +You idiot! +Keep an eye on your kid! +And it would have been my fault! +Just standing there with your mouth open like an idiot! +- Whose boy are you? +- Mama's. +- Where are you from? +- Voroshilovgrad. +- How old are you? +- Three months and three years. +What's your name? +Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert at the hospital. +- Can't you tell a better lie? +- All right, all right. +- Is Mark here? +- He is now. +- Here. +- Thank you, Anna. +A little boy is having a birthday and I wanted to give him a present. +You are a kind man after all, Mark Alexandrovich. +"The symptoms of such compound fractures depend on the degree of changes in the joints, as well as on the location." +Interesting, but unintelligible. +Why, I think it's quite clear. +What's this? +What kind of trick is this? +What trick? +He lost his parents at the station. +You should have taken him to the shelter for lost kids. +I don't want to go to the shelter! +Go there yourself! +- Rude child! +- You're rude. +Quiet, quiet. +We'll go find Mommy in Voroshilovgrad. +Stop that noise! +It's hurting my ears. +Here, play with this cap! +Here's a bagel for you. +- My eardrums will burst! +- We need to find a toy for him. +Irina, take him for a minute. +So now I have to hold him too? +Here, give him to me. +Come to me, little one. +I'll get you ready for bed. +Has anyone seen my squirrel? +Mark took it. +Mark? +Where'd he take it? +To give to some little boy as a present. +Some little boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +Where did he go? +You know, don't you? +Where? +Probably to see Antonina. +What Antonina? +Ask Mark. +- Tell me. +- Don't give me orders. +Mark... visits her occasionally. +You understand? +- You're saying this to hurt me. +- Why would I? +Just to spite me! +I'm loved. +I have a husband. +And you're still an old maid. +She lives in a small house near that large market. +You can check it out for yourself. +It's okay, it's okay. +I have to do something, I have to do something. +Talk to Mark when he comes back. +You should wait. +Wait? +Always waiting. +I'm always waiting. +I've had enough! +What use are words +Let lips fall silent +Sometimes +They tell lies +The eyes alone +Will never dare +To lie to other eyes +My eyes are now +Dark and sad +As though someone +Had blown out their flame +In Leningrad on my birthday, we'd take a car and go from one end of the city to the other. +Let's go for a ride! +In these times, Antonina, a car is worth its weight in gold, and gasoline is rationed. +Any kind of vehicle. +I beg you! +A fire engine, an ambulance, a truck. +Anything you like. +A ride against the forces of nature! +Just the two of us? +To forget everything else. +I'll try. +I love you. +Sorry. +I don't dance. +I thought I had tried everything, but I've never tried golden nuts. +Look, a message. +A birthday note for me? +So it's for your birthday? +Where's my squirrel? +Don't get the wrong idea. +There's a note from someone named Boris. +"My only love, happy birthday to you." +On this day you came into this world. +It's hard to leave you. +But what can we do? +This is war. +There's no way around it. +We can't continue living happily as we did before when death stalks our land. +But we'll be happy yet. +I love you. +I have faith in you. +Your Boris. +What are you so excited about? +Go home. +I'll be there soon. +What's that for? +Take your coat off. +Thank you. +You know, as usual all the Philharmonic's cars are taken, and I need one badly. +You're the head surgeon and all. +Surely you won't refuse... +We're very short on vehicles. +It was hard to do what I did for you, but I did it. +When you asked me to, I did my best. +What did I ask? +For an exemption. +It's about to expire, and this time, getting a new one will be practically impossible. +- What exemption? +- For Mark Alexandrovich. +Don't worry. +Not a soul will know about this. +Is it possible he lied to both of us? +He even offered me money in your name. +I'm sorry. +Very good. +Uncle Fyodor, +I turn to you for help. +Her behavior's impossible. +She stormed into a stranger's place, started a fight... +Shut the door. +Do you think anyone wants to send his son to war? +What are you talking about? +Or do you think others must pay for your welfare, for your life, with their hands, their legs, their eyes, their lives, +and you owe nothing to anyone? +I have an exemption, Uncle Fedya. +An exemption? +Tell me, how did you get it? +Why are you doing this? +It's okay. +I'll rent a room, I'll take Boris... +Perhaps someone else had better rent himself a room. +Gladly! +I've thought about doing that for a long time. +Why didn't you throw me out in the first place? +You've been through a terrible ordeal. +Only someone without a heart could reproach you. +Stay with us. +I can't. +I don't want to hide behind someone else's back. +I won't! +Think it over. +Could you tell me where the Borozdins live? +They live here. +Which of them do you want to see? +- Fyodor Ivanovich. +He's not home. +Did Boris send you? +What Boris? +No, I came on my own. +I must speak to Fyodor Ivanovich. +- Have a seat. +- Thank you. +He'll be home soon. +- May I go for a walk? +- You may. +Is he yours? +He looks like you. +Are you a relation of the Borozdins? +Not exactly. +You see, I'm out of the army. +Going home? +It's unlikely. +There's still a blockade around Leningrad. +I'm in a difficult situation. +- What is it? +- It's easy to tell you. +You're not part of the family. +Fyodor Ivanovich's son was killed. +Where? +West of Smolensk. +What shall I play for you? +Whatever you like. +Did you see him buried? +No. +I was injured and they carried me away on a stretcher, but a friend of his, Stepan, went up to him. +Now I have to find his girlfriend. +He loved her very much. +That's me. +Vladimir, come to see us if you're ever in Moscow. +Thank you. +I'll do that. +The war's over. +Strange, isn't it? +And you're still waiting? +Yes, I am. +One must always hope for the best. +Why do you delude yourself? +I saw it with my own eyes. +What did you see? +How he was wounded? +How he fell? +But you didn't see him die with your own eyes. +No... but why haven't you heard from him? +A lot of things could have happened. +There's no word from Stepan either. +At the factory they know he's in some special unit and will be back soon. +Dasha promised to tell me when he's back. +Boris is alive. +He's alive. +- Look, here they come! +- The victors are coming! +Boris! +- Veronica! +- Stepan! +Flowers for you. +Well? +What? +You see... +Here. +Dear mothers, fathers, sisters and brothers! +The happiness of our reunion is immeasurable. +The heart of every Soviet citizen is filled with joy. +Joy sings in our hearts. +It is victory that has brought us this joy. +We have all waited for this moment. +Everyone's dizzy with happiness. +But we shall not forget those left behind on the battlefield. +Time will pass. +Towns and villages will be rebuilt. +Our wounds will heal. +But our fierce hatred of war will never diminish! +We share the grief of those who cannot meet their loved ones today, and we will do everything to insure that sweethearts are never again parted by war, that mothers need never again fear for their children's lives, +that fathers need never again choke back hidden tears. +We have won, and we shall live not to destroy, but to build a new life! +Why are you just standing there? +Give your flowers to whomever they're for. +Thank you, sister. +My beautiful granddaughter! +Look, look! +Cranes are flying over Moscow! +THE END +Stop, Squirrel. +Put them on. +Look! +"Cranes like ships, sailing in the sky +White ones, grey ones With long beaks they fly" +Look, look! +There you go. +You and your "cranes like ships." +THE CRANES ARE FLYI NG +Screenplay V. ROZOV +Director M. KALATOZOV +Cinematography S. URUSEVSKY +STARRI NG +Veronica T. SAMOI LOVA +Boris A. BATALOV +Fyodor Ivanovich V. MERKURYEV +Mark A. SHVORI N +A PRODUCTION OF MOSFI LM 1957 +Who's there? +Wait. +Well, okay. +When? +- Thursday, at the embankment. +- Come on, that's too long! +Squirrel! +We haven't finished. +Squirrel! +When? +What time on Thursday? +No, I can't. +I'll be at the factory. +Okay. +Don't be late! +Squirrel! +She's crazy about him. +And he about her. +That's what love is, my dear: +A harmless mental illness. +Why aren't you in bed yet, Grandma? +It's already time to get up, Boris! +Quit making noise! +Running around all night... +You're just jealous. +Did you tear it? +Your jacket's all in one piece. +Disgraceful! +Twelve o'clock, and he's still asleep. +He works a lot. +He's tired. +Let him at least get some sleep on Sunday. +This "work" of his will end in a wedding. +You're just afraid of losing him. +Irina's mind should be on her thesis, not on a wedding. +Watch out, Uncle Fedya. +She almost has her doctorate and you're still just a physician. +Well, if children don't surpass their parents, then the parents are bad and the children not much better. +Thanks, Mama. +Important announcement! +What's going on? +Boris! +War! +You hear me? +War! +Leave me alone. +Hello. +Boris is at the factory day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica. +In wartime, it's important not to lose your head. +Try to live a normal life. +Like me... +I dream of dedicating a piano concerto to you. +Will you come to hear it? +- Won't you be drafted? +Drafted? +I don't know. +I doubt it. +And why is that? +The most talented people will be exempt. +- And you suppose you're talented? +- Yes. +Why are you always following me around? +You ought to be ashamed. +I am. +I promised myself a thousand times I wouldn't. +I know Boris is my cousin, but I can't help myself! +You understand? +I can't. +Wait! +There's no need to escort me. +Watch out! +You'll hurt your leg. +It'll be harder at the front, my dear Boris. +They won't let you go to the front. +There will be only one exemption. +Either for you or for me. +That's right. +So you should stay. +You've got knowledge and experience. +And you've got something more important... talent. +Take care of your drawings. +You know, my wife's already got my bags packed. +Well, as they say, let's get our bayonets ready! +Stepan! +Excuse me, Sachkov. +Well? +Where's the notice? +Nothing yet. +I don't understand why they're so slow. +Are you going home? +- No, I'm... +- Oh, I see. +Well, say hello to her! +- I will. +What? +- Have you told her? +- No. +Why should I rush it? +- You're right. +See you tomorrow. +- Take care! +- Let go. +- I won't let go. +You're gonna fall! +Let go. +You'll tear the shade. +- It's a blanket. +- Let go. +I'll call the police. +- I'm tired of these blackouts! +Give it to me! +- You're gonna fall. +- I am not. +Squirrel, stop it. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- So? +- He's handsome. +So? +- Are you jealous? +- What? +- Are you jealous? +- I don't have the time. +Too bad. +I think I'll enroll at the Architectural Institute. +- They won't accept you. +- Yes, they will. +I doubt it. +Cranes like ships sailing in the sky +White ones, grey ones with long beaks they fly +Do you like my song? +Very profound. +Little croaking frogs Why didn't you look up? +You kept on hopping and jumping That's why you got eaten up +Eaten! +Well, hero, did you win? +I won, I won. +I won. +Do you think you'll be drafted? +- Of course. +- Would you volunteer? +- I might. +No, you won't! +You know very well you'll be exempt. +That's why you talk so big. +- What makes you so sure? +- I know. +All the smart ones will be exempt. +So only fools will fight? +I don't want to discuss it any further. +Veronica... +I want to talk to you about something. +Well, I don't. +And please don't call me Veronica. +Who am I? +- Squirrel. +- That's right. +Listen. +What will you give me tomorrow? +It's a secret. +If it's something good to eat, I'll eat it and forget about it. +Give me something I will always remember, for as long as I live. +Kiss me. +You know, when you're with me, +I'm not afraid of anything, not even the war. +I'm afraid of the police. +Veronica. +You know what? +Do you know? +For the wedding I'm going to make a white dress. +Like the one my grandma had. +And a long, long veil. +And you'll wear a black suit, and we'll go... +- To the registry office. +- Agreed then? +- Agreed. +You know, I like this blackout. +What's so good about it? +Hey! +Stepan! +I have a treat for you. +- What is it? +- It's a secret. +- Did it arrive? +- It did. +Why didn't you say so? +Tell me. +Things are crazy at the factory! +The guys ran to the barber's. +I went straight to your place. +- Make it short. +- Just wait. +So I was saying, the guys ran... +Listen, can't you make it shorter? +- Your family's worried. +- What time do we report? +Today at 5:00. +With your things. +Look at these cherries. +- What is it? +- Beautiful. +The notice came. +Really? +For you? +Yes, for me too. +We both volunteered. +What? +You volunteered? +But the notice came... +Wait. +What about me? +I'd better go home. +I've got a lot going on there too. +Squirrel. +I didn't want to tell you. +Tomorrow's your birthday. +I have to go. +Of course. +Squirrel. +What's the matter? +Cranes like ships +You like my poem? +Nothing will happen to me. +You hear? +And then you and I will live for a long, long time. +A hundred years. +Go. +We'll say good-bye later. +All right. +Don't be late. +Can't he stay home until tomorrow? +He's a swine if he's still at Veronica's. +Boris! +- Did Dad call? +- Yes. +He's furious. +Why didn't you tell us? +To avoid scenes like this. +Go to the factory tomorrow and turn these over to Kuzmin, the engineer. +I will, I will. +What are you stuffing in there? +I'm running out for a bottle of wine. +Grandma, do me a favor. +Just a minute. +Will they send you to the front right away? +Probably. +Here... wait a minute. +Early tomorrow morning take this to her. +What is it? +It's her birthday tomorrow. +And later, if things are hard for her... +After all, this is war... +Help her out. +And if I die? +You've got no business dying, especially now that you know so many secrets. +I just might up and die. +Quiet. +That's Veronica. +No, it's Irina. +Thank God, you're home. +Boris! +Come over here. +What is this about? +You're 25 years old and you... +forgive me... act like a fool! +What are we? +Children? +Is this a game? +Hide-and-seek? +He wants adventure! +There's character for you. +Where are Irina and Mark? +Irina's making coffee. +Mark went out to buy some wine. +Coffee, wine! +What's wrong with people these days? +Irina! +Bring me the bottle from the medicine cabinet. +Boris! +Come here. +Where's Veronica? +- She'll be here any minute. +- Where is she? +She's busy. +This isn't right. +She should be here. +Her fiancé is leaving. +I'm not her fiancé. +- What are you, then? +- We're just... +You're just what? +That sounds suspicious. +- I don't mean it that way, Dad. +- Then what do you mean? +- Stop picking on me. +- Wait! +- Why are you bothering him? +- Here. +From the medicine cabinet. +- Go ahead and mix it properly. +- Here's the port. +Drink it yourself. +We'll have a real drink. +So, is everybody here? +Sit down. +It's Veronica! +Go meet your bride, Mr. Bridegroom! +Finally! +- We came from the factory to see Boris. +- Please come in. +And I thought the bride had arrived. +- We're from the plant. +- They told us to bring you these gifts. +Sorry. +This one. +- On behalf of the Plant Committee... +- And the Communist Youth League... +What you want to say is: +"Comrade Boris, fight to the last drop of blood, and beat the fascists! +And we at the plant will meet and exceed our production quotas." +We've heard all that before. +Why don't you sit down with us, girls, and drink to my son Boris! +Things in this world aren't going as smoothly as we might like. +So now you're off to war, Boris... +- Let's have a drink! +- To you! +A glass for Grandma. +We sent our brother off yesterday. +Mother cried and cried. +What about you? +- I cried too. +- On behalf of the Plant Committee? +- No, on my own. +- Don't embarrass her. +We've got no one to send off. +There's just Mother and three girls. +We even felt a little ashamed, with all the others leaving... +When our men come back, you'll envy us. +The trouble is not all of them will come back. +For those who don't, we'll build a monument reaching to the sky with every one of their names in gold. +Irina, pour another round. +What are you waiting for? +I'll just put these away. +Well, you folks in the rear, meet and exceed your quotas! +Grandma, don't forget. +Mark, don't go. +Stay with Father. +- I'll walk you to the trolley. +About face! +Guards, forward march! +- Mother! +- The last time. +I'm sorry. +Not in the mood for a drink? +Where are you going? +- I'm going on duty. +You were on duty yesterday. +Varvara Kapitanova, may I see Boris for just a moment? +- He already left. +- He left? +Where did he go? +- To the assembly station. +- Oh, no. +- Come in. +- Where's the assembly station? +- I don't know. +- What's this? +- It's from Boris, for your birthday. +There's a note too. +- Where's the note? +- Isn't it there? +He must have forgotten in the rush. +Forgotten? +He'll write to you. +Where were you? +- Where's the assembly station? +- It's on Zvenigorodskaya. +Don't worry. +She'll come. +Even if she does, how will she find me in this crowd? +What are you doing? +Boris, where's Veronica? +Write to me every day. +Who has the invoices for the cauliflower? +Don't forget to send your field address. +Cheer up, pug-nose! +Take care! +Fall in! +She'll come. +Boris! +Fall in! +Forward march! +There's my kitten. +Grandma? +Nothing? +He hasn't written to me either. +- Anything? +- No. +Oh, this war. +Well, rain or shine, we must carry on. +Have you decided where you'll work? +I'll go to the war factory. +Citizens! +Air raid alert! +Hurry down to the subway. +I've got some urgent work to do. +Go get your things. +Where's the backpack? +- The backpack? +It's right there. +I won't go without you. +If it becomes dangerous, we'll go down to the shelter. +Go now. +Be careful in the subway. +She's so scared, poor girl! +- What about you? +When Veronica is safe and you're by my side, I'm not afraid. +They're still at it, the brutes. +Those parasites won't even let us talk! +For some reason he doesn't write to me. +It's the war. +The mail is so slow. +All clear. +The air raid is over. +Let's go. +Well, my place is right here. +If you decide to come join us, call me at the factory. +- Okay. +- Good-bye. +Where are you going? +Get back! +Where do you think you're going? +I'm sorry. +Veronica, you'll stay with us from now on. +Boris' room is free for now. +Mark will share a room with Fedya. +Mark, we must take good care of her. +Unfortunately, Irina and I are at the hospital day and night. +I'll try, Uncle Fedya. +Boris spoke to me about it. +Are you all right now? +Is this the factory? +May I speak to Kuzmin, please? +He's gone to the front too? +Excuse me. +Is there any news from Boris Borozdin? +If it weren't for the damned war, +I'd be playing this at Tchaikovsky Hall. +For you. +- Veronica, let's go to the subway. +- I'm not going. +- That's nonsense! +Let's go. +- Are you afraid? +Only for your sake. +Come on, let's go. +I'm not afraid of anything. +Veronica, let's go! +Don't be foolish. +You're acting crazy! +I won't go! +I won't, I won't, I won't! +I love you. +No. +I love you. +I love you. +I love you! +- Go away! +I love you. +What a stupid way to get surrounded. +- Stepan, stop whining. +- What do you mean, stop whining? +The captain said we might break through by tonight. +- At last! +Sachkov! +- Here! +Where's this rookie from? +Straight from an incubator. +A fresh reinforcement. +Now we'll break through for sure. +Is that any way to speak to a married man? +- Is that right? +- I got married in school. +See what education does to people. +You funny guys, always joking! +Laughed yourselves right into a trap. +Volodka, are you really married? +Are you kidding? +Sounds better, though, doesn't it? +Borozdin! +You'll go out on reconnaissance. +Your job is to find the best place to break through. +Turn over your papers. +- Yes, sir. +Hey, Sachkov! +Come on, help me here. +Let's take a break, guys, and have a smoke. +She's always laughing like that. +- They must think we're dead. +Let me see that beauty. +Yep, the life of a soldier. +You're over here, and she's... +And she's what? +Give me the harmonica. +Sachkov, hold it for a second! +Stop it! +Aren't you ashamed? +- No. +Five days' arrest. +You'll both go on reconnaissance. +Turn in your papers. +Boris, here. +Because of her? +She's worth fighting for. +- Exactly. +Stop that chatter! +Discipline! +Hear that? +Discipline. +Stepan, hold on to this. +Just don't lose it. +We're getting married, Uncle Fedya. +I forgot... +I still have some sausage. +- Keep your head down. +- Stop giving me orders. +- Let's get out of here or they'll get us. +- Run if you're scared. +You idiot! +Hey, you! +Musician! +You deaf? +How the hell did I get stuck with him? +What's wrong? +Hey, you! +Go on alone. +I want to rest for a bit. +- Are you wounded? +Hold on to me. +- Leave me alone. +Hold on to me, I said, and hold on tight! +Here, get on my back. +It'll be faster this way. +Leave me here. +- Idiot! +You're sore because I punched you. +- You were just lucky l... +Shut up. +We'll settle it later. +Hold on, hold on. +A little further to the woods, and then we're safe. +I'm tired. +Let's rest a bit. +It's quieter here. +So, are you alive? +- It's a little hard to breathe. +- To breathe? +We'll dance at your wedding yet. +Hey, buddy! +What's the matter? +Forgive me. +Forgive me. +Forgive me, friend! +Hey, somebody, help! +Help! +Help! +Boris! +What's wrong, Boris? +Are you wounded? +I'm not wounded. +I... +The Soviet Information Bureau reports no important changes on the fronts in the last 24 hours. +No important changes. +That's good. +Families evacuated with Moscow Plant 326 will be quartered on Vostaniya Street. +Comrades, report here. +Irina, help this wounded man. +- The paramedics will be here soon. +- Yes. +Unload! +Siberia. +We can't retreat much farther. +This is what's become of Mother Russia. +Attention, attention! +Chief of Hospital Number 4, Borozdin, report to the military commandant. +Perhaps we'll find some peace here. +Clear the way, folks. +The stove is smoking. +I'm sorry. +You can daydream when the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +She's always waiting for a letter. +From whom? +Her husband's right here. +Not like us, soldiers' wives. +She's not waiting for a letter from anyone. +- Are you on the second shift at school? +- Yes. +"Cranes like ships sailing in the sky." +Those silly lines are stuck in my head. +There it is. +- What? +The mail. +If I can count up to 50, there'll be a letter for me. +- Veronica, this is crazy. +...16, 17, 18, 19 20, 21... +- Stop! +...45, 46, 47... +- Hello. +- Hello. +There's nothing for you. +For you. +Lededeva? +- That's me. +- Palyukaitis? +- Nothing. +From my eldest son on the Ukrainian front. +I didn't know Boris, but everyone says he was a gifted young man. +Was? +Missing doesn't mean dead. +Of course not. +That didn't come out right. +What's the matter, Veronica? +I'm dying, Anna Mikhailovna. +My dear, what are you saying? +- I've lost everything. +- You have your life ahead of you. +I don't want to live! +What's the use? +- Forget the past. +It's human nature to forget. +I don't want to forget. +There's nothing I need to forget. +You mustn't punish yourself forever. +I must. +Till the end. +You teach history. +You're an intelligent woman. +Tell me: +What is the meaning of life? +The meaning of life? +Perhaps it's that... +Was Chernov here? +No. +Boy, am I hungry! +If Chernov comes, try to be polite. +He's revolting. +I may find him even more revolting than you do, but he's the boss. +Why do you always kiss up to him? +Dear Veronica, you're impossible. +You're always so irritable, and you keep picking on me. +Tell me what I can do for you. +I wish you had never been born. +Come in! +- I hope I'm not intruding. +- We're always happy to see you. +Make yourself comfortable. +Did you hear? +The Germans have advanced in the Caucasus. +It's awful. +But don't worry. +We'll show them yet. +Please, make yourself comfortable. +Your place is cozy. +My wife and children are in Tashkent, so I live like a homeless tramp. +Hello, Veronica. +- Where are you going, dearest? +- I'm on duty at the hospital. +- Bundle up. +It's very cold. +I admire your wife. +She's always so candid, so pure. +She must be very happy with you. +I looked for you today at the Philharmonic. +- Was there a concert? +- No. +Will you be at the birthday party tonight? +Probably. +- What will you take for a gift? +- What can I give? +Yes... the war. +It's nothing great, but attach a little something to it and I'm sure Antonina will be very happy. +It's wonderful. +How much do I owe you? +- It's nothing. +Don't mention it. +- Thanks very much. +Mark, I have a favor to ask. +Is there anyone upstairs? +No. +Do you think you could ask Fyodor Ivanovich for some medicine? +Good job, Irina. +He's going to live. +I hope so. +He'll be a real swine if he dies. +Irina, you should have been born a man! +I feel pretty good as a woman. +Veronica, why are you so early? +The clock was fast. +Poor girl. +I'll never forgive what she did to Boris. +Here comes another batch! +I've told you already, we're full! +This is a hospital, not a sardine can! +Where are they all from? +Kalach? +- Stalingrad. +Some from the front, some from the hospital. +There's no room. +Don't worry, they'll make room. +I'll take 80 men. +The rest will have to go to other hospitals. +Now, then... give my regards to Uncle Sergei, +Fyodor, Vassily, +Aunt Marya, Agrafena, +Katerina, Varvara, +Nikolai, +Katerina. +You already said Katerina. +This is a different Katerina. +- Then you should say so. +- It's okay. +They'll figure it out. +So... +Zinaida, +Antonina, Kuzma... +Nurse! +What's the matter, Vorobyev? +Nothing. +I want the nurse. +He needs the bedpan. +I'll get it for you. +Thank you. +That's lovely music. +Turn up the radio, please. +Turn off that music! +Turn that music off! +You hear me? +Who yelled? +I did! +What's it to you? +- Zakharov, what's wrong? +- Go away! +He's losing his mind. +He got word from home this morning. +His girlfriend didn't wait for him. +She married someone else, the bitch. +He hasn't eaten all day. +Try to comfort him. +Broads like that are worse than fascists. +They aim right at the heart. +You have to eat, Zakharov, or you won't get well. +I don't want to get well! +I want to die! +Call the doctor! +Calm down. +All because of some broad! +Call the doctor! +Quit yelling! +Shut up! +Where will they take us now? +There are plenty of hospitals in the world. +The head doctor's coming, boys! +Stop it this minute! +You're still a soldier in the Red Army! +Are you trying to get discharged? +Are you afraid we'll heal your hands and send you back to the front? +No, Doctor, he's not like that. +He got a letter. +- I know. +That's just an excuse. +Big deal! +So your bride ran off. +You should be glad! +She isn't worth a penny if she would trade a handsome guy like you, a real hero, for some rat sitting out the war at home! +It's she who's forfeited her happiness, not you! +And that's what she deserves. +That's right. +She's got a petty soul. +People like her can't understand how much suffering we've gone through. +Killing people like her would be too kind! +You stood up to Death itself. +You looked death in the face. +You approached it with your chest stuck out. +And she couldn't even pass the little test of time. +Women like her deserve only our contempt. +There can be no forgiveness for them! +Bandage him up. +Aunt Sima, bring him some tea and porridge. +Don't be a brat. +Veronica... +You idiot! +Keep an eye on your kid! +And it would have been my fault! +Just standing there with your mouth open like an idiot! +- Whose boy are you? +- Mama's. +- Where are you from? +- Voroshilovgrad. +- How old are you? +- Three months and three years. +What's your name? +Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert at the hospital. +- Can't you tell a better lie? +- All right, all right. +- Is Mark here? +- He is now. +- Here. +- Thank you, Anna. +A little boy is having a birthday and I wanted to give him a present. +You are a kind man after all, Mark Alexandrovich. +"The symptoms of such compound fractures depend on the degree of changes in the joints, as well as on the location." +Interesting, but unintelligible. +Why, I think it's quite clear. +What's this? +What kind of trick is this? +What trick? +He lost his parents at the station. +You should have taken him to the shelter for lost kids. +I don't want to go to the shelter! +Go there yourself! +- Rude child! +- You're rude. +Quiet, quiet. +We'll go find Mommy in Voroshilovgrad. +Stop that noise! +It's hurting my ears. +Here, play with this cap! +Here's a bagel for you. +- My eardrums will burst! +- We need to find a toy for him. +Irina, take him for a minute. +So now I have to hold him too? +Here, give him to me. +Come to me, little one. +I'll get you ready for bed. +Has anyone seen my squirrel? +Mark took it. +Mark? +Where'd he take it? +To give to some little boy as a present. +Some little boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +Where did he go? +You know, don't you? +Where? +Probably to see Antonina. +What Antonina? +Ask Mark. +- Tell me. +- Don't give me orders. +Mark... visits her occasionally. +You understand? +- You're saying this to hurt me. +- Why would I? +Just to spite me! +I'm loved. +I have a husband. +And you're still an old maid. +She lives in a small house near that large market. +You can check it out for yourself. +It's okay, it's okay. +I have to do something, I have to do something. +Talk to Mark when he comes back. +You should wait. +Wait? +Always waiting. +I'm always waiting. +I've had enough! +What use are words +Let lips fall silent +Sometimes +They tell lies +The eyes alone +Will never dare +To lie to other eyes +My eyes are now +Dark and sad +As though someone +Had blown out their flame +In Leningrad on my birthday, we'd take a car and go from one end of the city to the other. +Let's go for a ride! +In these times, Antonina, a car is worth its weight in gold, and gasoline is rationed. +Any kind of vehicle. +I beg you! +A fire engine, an ambulance, a truck. +Anything you like. +A ride against the forces of nature! +Just the two of us? +To forget everything else. +I'll try. +I love you. +Sorry. +I don't dance. +I thought I had tried everything, but I've never tried golden nuts. +Look, a message. +A birthday note for me? +So it's for your birthday? +Where's my squirrel? +Don't get the wrong idea. +There's a note from someone named Boris. +"My only love, happy birthday to you." +On this day you came into this world. +It's hard to leave you. +But what can we do? +This is war. +There's no way around it. +We can't continue living happily as we did before when death stalks our land. +But we'll be happy yet. +I love you. +I have faith in you. +Your Boris. +What are you so excited about? +Go home. +I'll be there soon. +What's that for? +Take your coat off. +Thank you. +You know, as usual all the Philharmonic's cars are taken, and I need one badly. +You're the head surgeon and all. +Surely you won't refuse... +We're very short on vehicles. +It was hard to do what I did for you, but I did it. +When you asked me to, I did my best. +What did I ask? +For an exemption. +It's about to expire, and this time, getting a new one will be practically impossible. +- What exemption? +- For Mark Alexandrovich. +Don't worry. +Not a soul will know about this. +Is it possible he lied to both of us? +He even offered me money in your name. +I'm sorry. +Very good. +Uncle Fyodor, +I turn to you for help. +Her behavior's impossible. +She stormed into a stranger's place, started a fight... +Shut the door. +Do you think anyone wants to send his son to war? +What are you talking about? +Or do you think others must pay for your welfare, for your life, with their hands, their legs, their eyes, their lives, +and you owe nothing to anyone? +I have an exemption, Uncle Fedya. +An exemption? +Tell me, how did you get it? +Why are you doing this? +It's okay. +I'll rent a room, I'll take Boris... +Perhaps someone else had better rent himself a room. +Gladly! +I've thought about doing that for a long time. +Why didn't you throw me out in the first place? +You've been through a terrible ordeal. +Only someone without a heart could reproach you. +Stay with us. +I can't. +I don't want to hide behind someone else's back. +I won't! +Think it over. +Could you tell me where the Borozdins live? +They live here. +Which of them do you want to see? +- Fyodor Ivanovich. +He's not home. +Did Boris send you? +What Boris? +No, I came on my own. +I must speak to Fyodor Ivanovich. +- Have a seat. +- Thank you. +He'll be home soon. +- May I go for a walk? +- You may. +Is he yours? +He looks like you. +Are you a relation of the Borozdins? +Not exactly. +You see, I'm out of the army. +Going home? +It's unlikely. +There's still a blockade around Leningrad. +I'm in a difficult situation. +- What is it? +- It's easy to tell you. +You're not part of the family. +Fyodor Ivanovich's son was killed. +Where? +West of Smolensk. +What shall I play for you? +Whatever you like. +Did you see him buried? +No. +I was injured and they carried me away on a stretcher, but a friend of his, Stepan, went up to him. +Now I have to find his girlfriend. +He loved her very much. +That's me. +Vladimir, come to see us if you're ever in Moscow. +Thank you. +I'll do that. +The war's over. +Strange, isn't it? +And you're still waiting? +Yes, I am. +One must always hope for the best. +Why do you delude yourself? +I saw it with my own eyes. +What did you see? +How he was wounded? +How he fell? +But you didn't see him die with your own eyes. +No... but why haven't you heard from him? +A lot of things could have happened. +There's no word from Stepan either. +At the factory they know he's in some special unit and will be back soon. +Dasha promised to tell me when he's back. +Boris is alive. +He's alive. +- Look, here they come! +- The victors are coming! +Boris! +- Veronica! +- Stepan! +Flowers for you. +Well? +What? +You see... +Here. +Dear mothers, fathers, sisters and brothers! +The happiness of our reunion is immeasurable. +The heart of every Soviet citizen is filled with joy. +Joy sings in our hearts. +It is victory that has brought us this joy. +We have all waited for this moment. +Everyone's dizzy with happiness. +But we shall not forget those left behind on the battlefield. +Time will pass. +Towns and villages will be rebuilt. +Our wounds will heal. +But our fierce hatred of war will never diminish! +We share the grief of those who cannot meet their loved ones today, and we will do everything to insure that sweethearts are never again parted by war, that mothers need never again fear for their children's lives, +that fathers need never again choke back hidden tears. +We have won, and we shall live not to destroy, but to build a new life! +Why are you just standing there? +Give your flowers to whomever they're for. +Thank you, sister. +My beautiful granddaughter! +Look, look! +Cranes are flying over Moscow! +THE END +MOSFILM +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +Director of Photography S. URUSEVSKY +Associate Director +- B. FRIDMAN Production Designer +- Y. SVIDETELEV +Music by M. VAINBERG Sound by I. MAYOROV +English subtitles by T. KAMENEVA +Starring +T. SAMOILOVA as Veronica A. BATALOV as Boris +V. MERKURIEV as Feodor Ivanovich +A. SHVORIN as Mark S. KHARITONOVA as Irina +K. NIKITIN as Volodya V. ZUBKOV as Stepan +A. BOGDANOVA as Grandma B. KOKOVKIN as Chernov +Ye. +KUPRIANOVA as Anna Mikhailovna +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Your jacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools and the parents are no better. +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica! +In time of war, one should not get confused. +One should hold on to a normal life pace. +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I doubt it. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself! +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it. +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet, I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +there's so much excitement... +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders. +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry. +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma... +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee. +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee... +Comrade Boris, you must fight to the last drop of your blood. +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd better join us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don't just sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march! +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside. +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there. +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding. +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you. +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away! +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the devil I'v got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes. +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +I'm doing all right as a girl. +Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +So, Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave ma alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse. +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +I've been saving this for you. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield. +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children, that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don't just stand there. +Give the flowers to whoever they're for. +Thank you very much, sister. +Oh, what a darling! +What a chubby little darling! +Look, the cranes are flying over Moscow! +The End +MOSFILM +Wait, Squirrel! +Here, put it on. +Look! +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly! +Look! +You see... +You with your "cranes like ships". +THE CRANES ARE FLYING +Written by V. ROZOV +Directed by M. KALATOZOV +Director of Photography S. URUSEVSKY +Associate Director +- B. FRIDMAN Production Designer +- Y. SVIDETELEV +Music by M. VAINBERG Sound by I. MAYOROV +English subtitles by T. KAMENEVA +Starring +T. SAMOILOVA as Veronica A. BATALOV as Boris +V. MERKURIEV as Feodor Ivanovich +A. SHVORIN as Mark S. KHARITONOVA as Irina +K. NIKITIN as Volodya V. ZUBKOV as Stepan +A. BOGDANOVA as Grandma B. KOKOVKIN as Chernov +Ye. +KUPRIANOVA as Anna Mikhailovna +An Order of Lenin Film Studio "Mosfilm" production, 1957 +Who is there? +Wait! +Well, all right. +Say when, then. +Thursday, on the embankment. +Come on, that's too long. +Squirrel! +You haven't told me when! +Squirrel, at what time? +What time on Thursday? +No, I can't make it. +I'll be working. +- All right. +- Don't be late. +Squirrel! +- She's gone crazy over him. +- And he's over her. +That's love, my dear. +A harmless mental disturbance. +Grandma, why aren't you asleep? +Because it's time to get up, Boris! +Stop chomping! +Running around all night... +Are you jealous? +You haven't torn it, have you? +Your jacket's all right. +Outrageous! +It's noon and he's still in bed. +The boy deserves a good rest on Sunday. +He works hard. +That work of his will result in a marriage. +That's when you'll be really jealous. +For Irina, her diploma comes first. +Look out, Uncle Fedya. +She'll be a full professor soon, while you're still only a MD. +If children don't surpass their parents, then the children are fools and the parents are no better. +Thanks, Mamma. +This is Radio Moscow broadcasting over all of the Soviet Union! +- What is it? +- What has happened? +Boris! +We're at war! +Do you hear? +We're at war! +Leave me alone! +Hi! +Boris is working day and night. +Are you waiting for him? +I'm not waiting for anyone. +Veronica! +In time of war, one should not get confused. +One should hold on to a normal life pace. +Take me. +I dream of dedicating to you my first symphony. +Will you come to the concert? +Suppose the Army calls you up? +The Army? +I doubt it. +Hardly. +Why "hardly"? +The most talented ones will be exempted. +- Are you the most talented one? +- Me? +Certainly. +Why are you following me around? +Aren't you ashamed? +I am. +I tried to keep away from you. +I know, Boris is my cousin. +But I can't help myself! +Wait! +- Wait! +- I'm going home alone. +Hey, slow down! +You just had an operation. +I'd better be in shape for that field-pack. +They're not wasting men like you in the Army. +There'll only be one exemption here, and one of us'll get it. +They'd better give it to you. +You've got knowledge, experience. +And you've got talent. +Save your sketches. +My wife's already got my bag packed. +Well, as they say, let's get our bayonets ready. +Hey, Stepan! +Guys, give me a hand... +Stepan! +Excuse me, Sachkov. +- Where's the summons? +- Not yet. +I can't wait. +- Are you off now? +- No, I've got those sketches... +- I see. +Take care. +- Okay. +- Hey! +- Yeah? +- Have you told her? +- No, it's too early... +- You're right. +See you tomorrow. +- Right. +- Let go. +- I won't. +- You're going to fall down. +- No, I won't. +- You'll rip up the blackout. +- It's a blanket. +I'm going to call the militia. +I'm sick of the blackout. +Give me the blanket. +- Let go. +You'll fall. +- No, I won't. +Come on, Squirrel, cut it out. +Let me hang this up. +You didn't come to the embankment today, but Mark did. +- He's very handsome. +- So what? +- Aren't you jealous? +- What? +- Aren't you jealous? +- I haven't got the time for it. +I won't have much time either when I go to the architecture college. +You'll never pass the entrance exams. +- I will! +- I doubt it. +Cranes like ships Sailing up in the sky, +White ones and grey ones, With long beaks, they fly. +- Do you like my song? +- Very profound. +Oh frogs, you keep on croaking, Why didn't you think of looking up? +You went on leaping, in mud soaking That's why you ended eaten up. +- All right, you won, hero. +- I won, I won! +I won. +All right. +- D'you think you'll be drafted? +- Sure. +- You won't volunteer? +- I might. +Why not? +No, you won't! +I won't let you. +You know you'll get an exemption. +That's why you talk so big. +- Why do you think so? +- Everyone smart will be exempted. +Then the only ones to do the fighting will be the fools. +I don't want to talk to you ever again. +Veronica, there's something I must tell you. +I don't want to hear it. +And, please, don't call me Veronica. +- Who am I? +- Squirrel. +Listen... +- What will you give me tomorrow? +- It's a secret. +If you give me something sweet, I'll eat it up and forget about it. +Give me something to remember you with. +Kiss me now. +When I'm with you, I'm not afraid of anything. +Not even the war. +Though, I'm afraid of the militia. +- Veronica... +- You know what? +- Do you know? +- No. +I'll have a beautiful white dress made for our wedding. +One like my grandmother had. +And a veil... +Very long and white. +And you should wear your dark suit. +- And you and I will go... +- To a registry office. +- Is it a deal? +- It's a deal. +- You know I like this blackout. +- What's so good about it? +Hi! +- Stepan! +- Veronica! +- I've got a treat for both of you. +- Fine. +- What is it? +- It's a secret. +- Has it arrived? +- Yes, this morning. +- Why didn't you say so? +Tell me. +- Well, go on. +You should've seen what's going on over at the factory. +Make it short, will you? +I'm telling you: +there's so much excitement... +- Never mind that. +- Your folks told me... +- When do we report? +- Today at 5:30. +Look at those cherries! +Is anything wrong? +- They're nice! +- Army orders. +- No! +For you? +- Me too. +We both volunteered... +When? +- You volunteered? +- It's army orders. +Wait! +What about us? +Stepan... +No, I've got to go. +My folks are going to... +So long. +Squirrel! +I didn't want to tell you before your birthday. +- And now I have to go. +- Of course. +Boris! +Squirrel, what is this? +White cranes flying... +I like that. +I'm going to be all right. +Do you hear? +And after that we'll live together... +a hundred years. +Go on now. +We'll say goodbye later. +Don't be late. +What difference would it make if he went a day later? +What a nerve if he's still with Veronica. +- Boris! +- Did Dad call? +He was furious. +Why didn't you tell anyone? +So that we didn't have any scenes like that. +Get these prints back to the factory tomorrow. +- Give them to Kuzmin, the engineer. +- I will, don't worry. +What are you putting in there? +I'm going out for a bottle of wine. +Grandma, do me a favor. +Just a minute... +- Will they send you to the front? +- Probably. +Here, Grandma... +Wait. +Tomorrow when you get up, take this to her... +- What is it? +- Her birthday present. +And help her. +After all, it's war... +Please, be kind to her. +And what if I die? +You don't have the right, especially now, with so many secrets to protect. +- Well, suppose I do... +- Come on... +Quiet now, Grandma. +That's Veronica! +No, it's just Irina. +Thank heaven, you've come. +- Boris! +- Yes? +Come over here. +You're 25 years old and you behave like a fool. +What are we, children? +What is it? +Are we playing hide and seek? +Are you starved for adventures? +What kind of a man are you? +Where's Irina, and Mark? +Irina is making coffee, Mark went out for wine. +Coffee, wine... +What kind of send-off is that? +Irina! +Bring that thing from the medicine chest. +Boris, come over here. +- Where is Veronica? +- She'll be here. +- But where's she? +- She's busy. +She's supposed to be here. +Her fiance is going away. +I'm not her fiance. +- What are you then? +- Just a friend... +- That sounds suspicious... +- I don't mean that way, Dad. +- Then what do you mean? +- Look, give me a break. +- Here's the alcohol. +- Have it diluted. +I got some port wine. +Drink it yourself. +We'll have a more robust drink. +Well, are we all here? +Let's sit down. +It's Veronica. +Aren't you going to welcome her, friend? +At last! +Is Boris home? +We're from the factory. +Please, come in. +I thought it was the fiancee. +- We've come from the factory. +- What about the presents? +- Sorry. +This one's yours. +- Yes... +Thank you. +On behalf of the Factory Committee... +Comrade Boris, you must fight to the last drop of your blood. +Smash the accursed fascists, and we, in the factory, will fulfil and overfulfil our quotas. +We've heard all that before. +You'd better join us and drink to my son, Boris. +Well, I suppose... life in this world of ours is not yet what we would like it to be. +Now you're going to war, Boris... +- Let's drink. +- To you. +Irina! +What about Grandma? +We saw my brother off last night. +My mother was crying... +- What about you? +- I was too. +- On whose behalf, the committee's? +- I wasn't thinking about that. +There's no one to see off in our family, we have 3 girls and Mom. +It's somewhat embarrassing... +I feel left out... +Yes, and when they come back, you'll really envy us. +The trouble is, not all of them will be coming back. +For those who don't, a magnificent monument, with their names inscribed in gold. +Irina, don't just sit there. +Fill the glasses. +And you folks in the rear, fulfil and overfulfil! +Now, Grandma, don't forget. +Mark, stay with Dad. +He'll be all right. +I'll see you off. +About face! +Platoon, forward march! +Take it, Grandma! +- Boris! +- Mamma! +- I won't see him again. +- I'm sorry, Mamma. +Drink it. +You'll feel better. +- Where are you going? +- To the hospital. +But you aren't on call now. +Varvara Kapitonovna, I've got to see Boris... +He's gone. +- Gone? +Where? +- To report for the Army. +- Oh, no! +- Come in. +- Where was he supposed to report? +- I don't know. +What is it? +It's from Boris. +For your birthday. +There's a note inside. +- Where's the note? +- Why? +Isn't it there? +Maybe it fell? +Maybe he forgot in a hurry. +- Forgot? +- He'll write to you. +Where were you? +- Where's Boris gone? +- It's the schoolyard near the park. +Calm down, she'll be here. +It would be quite a job finding someone in this crowd. +What are you doing? +Write to me. +Write every day. +Didn't I tell you to ship the cauliflower? +An airplane is high above, Over the roofs it's droning. +It's my sweetheart sends his love From his sky-high soaring. +It was used to be before That he saw me to my door. +Now it's been quite a turn-off: +I'm the one to see him off! +Don't forget to write your Army Post Office number. +- Cheer up, pug-nose! +- We'll wait till you come back. +Goodbye, Boris! +Take care! +Fall in! +She will come. +Boris! +Boris! +Dress! +Attention! +Forward march! +Boris! +That's my little chicken! +Boris! +Boris! +Grandma... +Nothing? +He hasn't written to me either. +- Any news? +- No. +Oh, this damn war! +We'll have to keep going somehow. +Have you decided about a job? +I'm starting at the war factory tomorrow. +Air-raid alert! +Hurry on to the subway. +I've got to finish this. +Get your things. +- Where's the knapsack? +- It's over there. +I won't go without you. +If it gets bad, we'll run down. +Go on, now. +Be careful in the subway! +She's so frightened, poor thing. +Aren't you? +When I know that Veronica's safe and you're with me, +I'm not such a coward. +The filthy murderers! +We'll get back at you, you wait! +He's not writing to me. +Oh, he must have written. +It's just the mail. +All clear! +The air raid has been terminated. +Let's go! +Here's where I live now. +If you decide to work with us, call me at the factory. +- I will. +- Goodbye. +Get down here! +Come back! +What's the matter? +Are you crazy? +I'm sorry. +Veronica, you can stay with us from now on. +You can have Boris' room. +Mark will move in with Fedya... +Mark, she'll need some attention to keep her from brooding. +Irina and I are so busy at the hospital. +I'll do what I can, Uncle Fedya. +I promised Boris. +- Is it agreed? +- Um-hmm. +Is this the factory? +May I speak to Kuzmin? +He was drafted, too? +Excuse me, has anyone heard from Boris Borozdin? +If it weren't for this damn war, +I'd be playing this in the Tchaikovsky Hall. +For you. +Veronica! +Let's go to the subway. +- I'm not going. +- Don't be silly. +Come on. +- Are you afraid? +- For you. +Come with me. +I'm not afraid of anything. +- Veronica, let's go to the subway! +- No, I'm not going. +- Stop it! +You've gone crazy! +- I'm not going! +I love you. +No. +- I love you! +- No! +No! +- I love you! +- Go away! +- I love you! +- No! +No! +No! +It's stupid to get surrounded like this. +- Stepan, quit whining. +- Who's whining? +I'm not. +The captain said we might be able to break out by tonight. +Yeah, that's what he says. +Sachkov! +Where'd you find that rookie? +In the incubator. +He's our reinforcements. +Now we'll break through for sure. +Is that a way to talk about a married soldier? +I got yoked in my last year of school. +The result of too much of education. +You're funny. +Laughed yourselves right into a trap, I guess. +- Volodya, you really married? +- I said it to sound important. +- Borozdin! +- Yes? +You'll go on a reconnaissance mission. +You got to find the best place for us to break through tonight. +- Turn in your documents. +- Yes, sir. +Hey, Sachkov! +Take this, will you? +Why don't we rest? +And have a smoke. +Is she always laughing like that? +She probably thinks we're all dead. +Let me see that beauty. +Hey, that's the soldier's life for you! +- You're here, and she... +- And she what? +Hey, let me try that thing. +- Hold it, will you, Sachkov? +- Certainly. +Not bad for a first try. +Stop that! +- Aren't you ashamed? +- No, sir. +- Five days under arrest! +- Yes, sir. +- You both go on a reconnaissance. +- Why? +Turn in your papers! +Boris, here. +On account of her? +- I'd say she was worth it. +- She sure is! +However, we must maintain discipline! +You hear that? +Discipline... +Stepan, keep this. +Be careful, don't lose it. +We... +We'll get married, Uncle Fedya. +Oh, I forgot. +There's some sausage left. +- Keep your head down! +- Stop ordering around! +Let's get out of here before they get wise. +- If you're scared, run. +- Come on, you idiot! +Hey! +Musician! +Are you deaf? +Why the devil I'v got tied up with him? +What's wrong with you? +Can you hear me? +- Go on. +I want to rest for a while. +- Are you wounded? +Hold on to me. +- Leave me alone. +- I tell you, get up! +Now hang on, hold tight. +This way's no good. +I'll have to carry you. +Come on, leave me here. +Are you still sore because I punched you? +- You were just lucky, otherwise... +- Shut up, we'll talk later. +Here we go... +Are you all right? +Hold on, friend. +It's only a little way to the woods. +We'll be safe there. +I'm winded. +Let's rest a bit. +It's a little quieter here. +How are you? +It's hard to breathe. +Hold on, we'll have to get you married yet... +Hey, buddy! +What's the matter with you? +What's wrong? +Forgive me, friend, forgive me... +It's my fault... +Forgive me... +friend... +Hey, somebody! +Help! +Help! +Help! +Can you hear me, Boris? +Are you hit? +It's nothing, I am just... +The Soviet Information Bureau reports that there were no important changes on the front in the past 24 hours. +No news is good news. +Families evacuated with Plant 326 will be quartered on Vosstaniya Street. +Comrades, report here, please. +- Irina, help me with the wounded. +- I'll get an orderly. +Everybody off! +Siberia! +We can't run much farther. +Poor Mother Russia! +Attention, please! +Chief of Army Hospital, Comrade Borozdin, please report to the military commandant at once. +Maybe we'll find peace here at last. +Out of the way, the evacuated. +Your stove is smoking. +Oh, I'm sorry. +Save your dreaming till the war is over. +Where are you going? +To the hospital. +I'm on duty. +She wanders around like a ghost, all nerves. +The poor thing is waiting for a letter. +From whom? +Her husband's not up at the front like ours. +She's not waiting for any letter. +- D'you have the 2nd shift at school? +- Yes. +Cranes like ships, Sailing up in the sky... +I can't get those silly verses out of my head. +There she is! +- Who? +- The mail carrier. +If I can count up to 50, there'll be a letter for me. +- One, two, three, four... +- Stop it, Veronica. +- Fifteen, sixteen... +- Veronica, this is madness. +- Nineteen, twenty... +- Stop it! +Forty-seven, forty-eight... +- Good morning! +- Good morning! +Sorry, nothing for you. +Here you are. +- Lebedeva? +- That's me. +- Paliukaitis? +- Nothing. +From my eldest. +From the Ukrainian Front. +I didn't know Boris. +But everyone says what a fine, talented boy he was. +Was? +Listed as missing in action doesn't mean he was killed. +Of course not. +I just didn't put it right. +- What's wrong, Veronica? +- I'm dying, Anna Mikhailovna. +Come on, Veronica. +You poor child. +I've lost everything. +You have your whole life before you. +I don't want it! +What's it good for? +You must forget the past. +It is human nature to forget. +I don't want to forget. +I don't need it. +But you can't go on tormenting yourself for your mistakes. +I should do it. +All my life. +You teach history. +You're a wise woman. +Tell me what's the meaning of life? +The meaning of life? +Maybe it's in... +- Did Chernov get here yet? +- Not yet. +Wow, I'm really famished! +Try to be nice to Chernov when he comes, please. +He makes me ill. +I feel exactly the same way, but after all he's my boss. +That gives you a reason to lick his boots? +Please, Veronica, this can't go on. +You're always so irritable, always criticizing. +Tell me, how can I make you happy? +Just disappear. +Come in, it's open. +Come in! +Mark, pardon my invasion. +Not at all. +It's a pleasure. +Here, let me take that. +Did you see the paper? +The Germans have advanced in the Caucasus. +Yes, it's awful. +But we'll show them what we're made of yet! +Please make yourself comfortable. +It's warm here. +Your place is nice and cozy. +My wife and children are in Tashkent, so I'm kind of homeless. +- Good day, Veronica. +- Good day. +- Where are you going, darling? +- To the hospital. +I'm on duty. +Bundle up. +It's very cold. +I admire your wife. +She's so honest... +She must be very happy with you. +- I was looking for you at the Philharmonic. +- Was there a concert? +No. +But are you going to the birthday party tonight? +I might. +- What are you giving her? +- What can I give her? +The war! +Yes, this war. +It's nothing gorgeous, of course, but tie a little trifle to it and Antonina will be pleased. +It's wonderful! +What do I owe you? +- It's really nothing, forget it. +- Thank you very much. +Mark, can you do me a favor? +- Is someone up there? +- No. +Could you get some drugs for me from Feodor Ivanovich? +Fine job, Irina. +He'll pull through. +I hope so. +It would be downright mean of him not to. +Irina, you should have been a man! +I'm doing all right as a girl. +Veronica! +What are you doing here so early? +The clock was fast. +Poor girl... +I can't forgive her for what she did to Boris. +New patients again! +I told them I have no more room. +I'm running a hospital, not a barrel of herrings! +- Are these from Kalach? +- From Stalingrad. +Some from the front line, others from the hospitals. +No place for us here, either. +Don't worry, they'll find room. +I'll take 80 men. +The rest will have to go to other hospitals. +Let's see now... +Please give my regards to Sergei, +Feodor, Vassily, Aunt Maria, +Agraphyona, Catherine, Barbara, +Nikolai, Catherine... +- You already said Catherine. +- That's another one. +- Don't you want to explain it? +- They'll figure it out. +So, Zinaida, Antonina, Kuzma... +Nurse! +- What do you want, Vorobyov? +- Never mind. +Nurse! +- He wants a potty. +- I'll give it to him. +Thanks. +That's beautiful music! +Turn it up a little louder, will you please? +Shut up your music! +Turn it down! +You hear me? +Who was that shouting? +I did, so what? +- Zakharov, what's wrong? +- Leave ma alone! +He's gone berserk. +He got bad news from home this morning. +His girl just got married to a friend of his, bitch. +He hasn't had a bite to eat. +Try to see what you can do, nurse. +Those broads are worse than fascists, aiming right in the heart. +You must try to eat. +It's the only way to get well. +I don't want to get well! +I just want to croak! +Get the doctor. +Calm down. +Please, calm down. +Because of a woman... +What a dumbbell! +Get the doctor! +Get the doctor now! +Quit that yelling! +Cackling like a bunch of hens! +Where will they take us now? +There're plenty of hospitals in this wide world. +Guys, the chief is coming! +Bastards! +Quiet down! +You're a soldier in the Red Army! +Want to desert it? +You afraid that if we cure you, you might go back in the army? +You're not being fair. +He got a bad letter from home. +I know. +That's just an excuse. +So what if his girl's left him? +Good riddance! +She's not worth a dime if she gave up a handsome soldier like this, a real hero, for a puny draft-dodger! +Right. +She's the one who's missed her happiness! +And whatever she's got, she deserves it! +What a petty soul! +Can a woman like that understand the suffering you've gone through? +Killing her would be too good for her kind. +You stood the most difficult trial. +You looked death in the face, went to meet it yourself. +And she couldn't stand the small test of time. +For women like that, no honorable man can have anything but contempt! +For such creatures there is no pardon! +Bandage him! +Aunt Sima, bring him fresh porridge and some hot tea. +Be good now. +Veronica... +What the hell kind of a mother are you? +Keep an eye on your kid! +And I'll be held responsible! +Daydreaming, you fool! +- Who are you? +- Mamma's boy. +- Where are you from? +- From Voroshilovgrad. +- How old are you? +- Three months and three years. +- What's your name? +- Boris. +- What? +- Boris. +- Why the fancy get-up? +- A concert in the hospital. +- A likely story! +- All right, all right. +- Is Mark here? +- So far yes. +I've been saving this for you. +Thank you very much, Anna Mikhailovna. +It's for a little boy we know. +It's his birthday. +I wish everyone were as kind- hearted as you are, Mark. +The symptomatology of this type of compound injury depends primarily on changes in the nodal structure... +- Interesting, but beyond me. +- Why, it's really quite simple. +They are not readily apparent to the clinical practitioner, but in most cases the etiology... +- What is this? +- What kind of a trick is that? +What do you mean, trick? +The poor child lost his parents. +I want my mommy! +You ought to have taken him to the Foundling Center. +You go yourself to the Center! +- Rude child! +- I'm not, you're rude! +Now, don't cry. +We'll go find your mommy in Voroshilovgrad. +Now, now, be quiet. +- Poor baby, he wants his mommy. +- Look, here comes a goat... +Stop rattling. +You're hurting my ears. +Here, play with the cover. +Don't you want it? +Oh, my God. +Here's a bagel roll for you. +Keep him quiet! +He's driving me crazy. +If we had some toys for him to play with... +Irina, take him for a minute. +Hah, what next? +Stop crying, will you? +Let me take him. +Come on, my little one, my little Boris... +I'll undress you and put you to bed... +Have anyone seen my squirrel? +Yes, Mark took it. +- Why? +- He's giving it to some boy. +My squirrel to a boy? +- Where's Mark? +- I don't know. +- Where's Mark? +- I don't know. +You're hiding something from me. +You know where he's, don't you? +Where's he? +He's probably gone to Antonina's party. +- What Antonina? +- Why don't you ask Mark? +- Who's she, tell me! +- Don't order me around. +Mark visits her occasionally. +Do you get it? +- You're saying this to spite me. +- Why would I want to? +Because I'm married, I'm loved, and you're still a spinster! +Stop it, Veronica! +Antonina lives near the food shop, in the little house next door. +Go over there and see for yourself. +Calm down. +I should do something. +When Mark comes home, you'll have a talk. +But now you must wait. +Sure, I must wait... +That's all I've been doing all the time. +That's enough! +May our lips benumb. +Words are futile. +They so often lie perchance. +And only our eyes Will never dare lie, +Forever true their parting glance. +My eyes are now sad and dark, +As though therein a candle was put out... +In Leningrad after my parties we'd go for a ride, from one part of the city to the other. +Arrange for a ride now. +There's a war on, Antonina. +Cars are worth its weight in gold, the gasoline is strictly rationed. +Get any kind of car! +I beg you! +A fire-engine, an ambulance, a truck... anything! +Let me hope where there's hope no longer! +Just the two of us? +To the point of full abandon? +I'll see what I can do. +I love you! +Sorry, I don't dance. +I thought I'd tried everything, but I've never tried golden chestnuts. +Look, a note! +- It's a birthday note for me. +- Congratulations! +Where's the squirrel? +Where's my squirrel? +Look, you mustn't think that... +There's a note here from somebody named Boris. +My only one, happy birthday... +On this day you were born. +It's hard leaving you. +But it can't be helped. +It's war! +I must go. +We can't go on living the way we did, enjoying ourselves while death stalks our land. +We will be happy some day. +I love you, I trust you. +Your Boris. +Why are you so alarmed? +Go home. +I'll be right back. +Why? +- Take your coat off. +- Thank you. +You know, all the Philharmonic cars are being used tonight, and I must have a car. +You're Chief Surgeon, you won't refuse me this little favor... +Transportation is our most critical problem. +It was difficult for me too, but I did my best. +I went out of my way, because you asked me... +- What I asked you? +- The exemption. +Now it's about to expire, and this time to get it will be almost impossible. +- What d'you mean, exemption? +- The exemption for Mark. +You can be sure I handled the whole thing discreetly. +Could Mark have done it without informing you? +He even offered me money in your name... +I'm sorry. +I'm glad you're here, Uncle Fedya. +I wish you'd talk to her. +She burst in without being invited, started a fight... +Shut the door. +Do you believe that anybody likes having his son marching off to war? +What do you mean? +Or do you believe that for your petty pleasures and well-being others must lose their arms, legs, eyes, jaws, even their lives? +And you owe nothing to no one? +You know I've got an exemption, Uncle Fedya. +Tell us how you got this exemption. +What are you doing, Veronica? +It's all right. +I'm going to rent a room. +And I'm taking the boy... +Perhaps someone else had better rent a room? +Gladly. +I've been wanting to for a long time. +I wish you'd driven me out in the first place. +You've been through a terrible ordeal. +Only one who had done something worse could have condemned you. +Stay with us. +I can't. +I cannot hide behind someone else's back. +I don't want to. +Think it over. +Listen, where can I find the Borozdin family? +- Which one are you looking for? +- Feodor Ivanovich. +He is not in at the moment. +Are you from Boris? +No, I'm by myself. +I have to see Feodor Ivanovich. +- Won't you sit down? +- Thanks. +Feodor Ivanovich should be here in a few minutes. +- May I go out? +- All right. +- Is he yours? +- Yes, he's mine. +He looks like you. +Are you a relative of the Borozdins? +Not really. +Well, I've done all the fighting I'll ever do. +Going home? +Not yet. +Leningrad's still blockaded. +- Yeah, I'm in a spot. +- Why? +I guess there's no harm in telling you because you're not the family. +But how do you tell a man his son was killed? +- Where did it happen? +- Near Smolensk. +What do you want me to play? +I don't care. +Tell me, did you see him buried? +No. +I was put on a stretcher and taken to a hospital, and he was with a friend of his, Stepan. +Stepan... +I've got to find his girl now. +He was really in love with her. +I'm the girl. +Come to see us when you're in Moscow, Volodya. +Thanks very much. +I will. +The war's over. +It's strange, isn't it? +And you're still waiting? +I am. +One must always keep on hoping. +What's the use of waiting? +I saw it with my own eyes. +What did you see? +You saw him wounded? +You saw him fall? +You didn't see him die. +But if he's alive, why hasn't he written to you? +Anything could happen. +Stepan hasn't written to anyone either. +They know at the factory that he was in some Special Operations. +Dasha promised to let me know when he's back. +Boris is alive. +He's alive. +Look! +The victors are coming! +Kolia, darling, you're back! +Boris! +Veronica! +Stepan! +The flowers... +For you. +Well? +What? +You see... +Well... +My darling! +Dear mothers, fathers, brothers and sisters! +The happiness of our reunion is boundless. +The heart of every Soviet citizen sings with joy, the joy of victory! +We have all waited for this happy moment. +We dreamed of it in the darkest hours of our struggle. +But we'll never forget those who lie silent on the battlefield. +Years will pass, our cities will rise again, and our wounds may one day be forgotten. +Let one thing remain in our hearts, a cold hatred of war! +We deeply feel the grief of those who cannot meet their loved ones today. +We must all take a vow to keep our promise that sweethearts will never again be parted by war, that mothers may never again fear for their children, that our brave fathers may not stealthily swallow their tears. +We have won and remained alive, not for destruction but to build a new life! +Don't just stand there. +Give the flowers to whoever they're for. +Thank you very much, sister. +Oh, what a darling! +What a chubby little darling! +Look, the cranes are flying over Moscow! +The End +Oh, mighty God +Please take my soul, to ask You why You torture me +Take my soul or alleviate the suffering +Oh, God, are You... +I ask Your forgiveness +I know You exist, my heart shivers hearing Your name +But I wonder, and You are the Most Merciful and Righteous +Why are we led to temptation? +Why does sin take over virtue? +Why does the evil in our souls overcome the goodness? +Why does one sin then remorse and ask for forgiveness? +I have committed many sins but I am confused; +was it my deprivation from my mother that pushed me towards evil? +My parents were divorced when I was two +And my father was responsible for bringing me up +He was my father, brother and mother as well +He granted me his youth, he lived only to please me +Nevertheless, nothing compensated for the loss of my mother +I envied any girl that had a mother +In a girl's life, there are things only a mother understands +These things were like a barrier between me and my dad when I started to turn into a young woman +It made me feel lonely and deprived +My father was the only thing I really possessed +I didn't demand for my rights as a daughter only, but more +I considered myself responsible for his happiness +We lived with my uncle who was only a few years older than I was +I was the lady of the house +My face had no sinister look to it +It is an innocent face, like that of a child who hadn't yet peen polluted by life's ugliness +I started my evil deeds by pulling small pranks that later developed into big disasters +Even my schoolmates were not exempted from them +Kawthar was in love with my cousin, Medhat +I convinced her falsely that Medhat loves me +I was able to part between them and ruin their lives just because I liked being evil but I would cry also +I cried for long nights, in regret for what I had done +And I was forever sleepless +SLEEPLESS +Based on a novel by: +Ehsan Apdel Koddous +Directed by: +Salah Apu Seif +Then came the day when I felt my life was really falling apart +I was sixteen, attending boarding school +My father came and took permission from the principal to take me home +You know something, Nadia +I don't like your staying in a boarding school +Why? +It's a great school +You know I sent you there because I had to +After you've grown like this, you couldn't stay home without a woman to look after you +Nanny Halima is like a mother to me +Well, at the end of the day, she's still a nanny +I have worried about you all my life +There were so many little issues in your life that I couldn't approach you with +Only a woman could talk to you about those issues +I never complained +Yes, but we have to live together forever +You know, when you get married, +I will make sure that your husband will take us both +We can never live together though unless I married +- Married? +- Yes, Nadia +I have lived without marriage for 14 years, for your sake +And now I married for your sake too +The only condition in the woman I was going to marry was that she would take care of you, and I found her +- I am sure you'll love her +- You should love her +If you love her, Nadia, I will love her +- Congratulations +- Just a plain congratulation? +I only want you to be happy, Daddy +Hello, Nadia +You're more beautiful than your picture +Aunt Safiya +Planning to get drunk, Aziz? +This is your third drink +What to do? +I'm starving +Looks like Nadia won't appear unless I go get her +How posh! +Bless your hands, Safy +See the difference a lady's presence makes in a house! +What have you done to yourself? +What is this hairstyle? +- Is it ugly? +- No, not at all +You look just like Aunt Safiya now +I am not as cute as Nadia +Nadia is beautiful, have a seat +Sit over there, Nadia, in the seat across me +Come on, darling +It's our fate to take the back seat +Well, get yourself a bride +- Here's my bride! +- I'd never give her to you! +You are always at night clubs! +When I was young, I wanted to marry Daddy +Well, he's taken now, I am the only one left +No man in this whole world is worthy of Nadia +Not even Daddy? +Your father is one of a kind +But I hope you find a man like him +- What's for vegetables? +- Messakaa +Oh, God! +It doesn't go well with whiskey +I have a long night yet, tonight is the big night +Do you hear that? +All his nights are like that +Actually, I asked the cook to make Messakaa because I learned that Nadia likes it +Tell me your favorite meals and I'll make them for you +- I like late nights +- And borrowing money +Oh, now you are reminding me of the 100 pounds I owe you! +- I'm not eating then! +- Why, Aziz? +Let him go, he probably has a date; +he's been looking at his watch +You are not a niece, you are a wicked mother-in-law! +- Good bye +- Good bye +Stop drinking, would you? +Good night +Will you sleep this early? +Yes, I'm a bit tired +Good night, darling +Don't forget to close the balcony door +- Good night, Auntie +- Good night, Nadia +- It's getting cold +- I don't think so +It's going to turn on fire +As long as you are by my side, I feel on fire +- What are you doing? +- Getting warm +This is not how to do it.. +Hasn't Nadia woken up yet? +Not yet, sir +Put this vase on the cupboard over there +Halima, wake Nadia up, it's ten o' clock +- Good morning, Nadia +- Good morning +I hope you get married soon +Your father, Lady Safiya and your uncle are waiting for you +- Uncle is awake? +- Yes +Everything has changed since Lady Safiya came +I feel that everything in the house is newer and prettier +The furniture is still the same, it was just too close together +I never thought I would ever wake up this early +Early? +It's 10:30! +Tomorrow, breakfast is at 8:00, we'll force you out of bed +Your father's marriage is trouble for me and you +- Good morning +- Good morning, dear +We should take Nadia to the doctor +I think she's a bit pale, she needs some vitamins +Vitamins? +No, all she needs is a husband +Husband? +Who could we fool into marrying her? +Remember when I asked you to make me scrambled eggs +You burned your hand, and nearly burned the house down! +We all did that as kids +I will teach her everything, she'll be just like me +I wish she'd be only half of you +Why do you want to marry me off? +Bored of me? +Safiya? +No one is answering +You answer it +Hello, how are you, Auntie? +Thursday? +What time? +Seven? +Definitely, yes, we'll be there +Bye-bye, Auntie +You know what, Daddy? +I'll never speak to my friend Aliya again +Why? +She's a nice, funny friend +I was once at her place, she left me alone and talked to her boyfriend on the phone +She was talking to him while her mother was sitting next to us +Be fair! +She was talking to him, pretending he was a girl +The strange thing is her tongue didn't slip once +- Live and let live +- Believe her, Ahmed, girls these days can do anything +Who wants to come to the club for some fun? +I'd love to but I have things to do +- Take Nadia with you +- I am tired +- We'll expect you for lunch +- I've forgotten what junk food is like! +Let's go +I am very sorry, miss +I apologies again, a hundred times +- Okay +- Okay what? +- Accept my apology +- What if I don't? +I won't eat or sleep +- It's over +- Thanks, see you around +- Anyone bugging you? +- Not at all +I know Mostafa, he thinks he's still a youngster +I don't like young men anyway +He's a playboy, everyday a new girlfriend +And you are straight? +Where were you just now? +Playing backgammon +So, was your opponent a brunette or a blonde? +Watch it, Ahmed +- Yes? +- Is this Mr. Mostafa? +Yes, who is this? +I am a girl, don't you like talking to women? +I am sure you would enjoy talking to me +No one prodded me to call you, no +I happen to like you +So you've seen me, you know me +It's not fair, you have the advantage! +This is selfishness! +You can imagine me as we speak +But I will always be asking myself: who is she? +Is she pretty or ugly? +Who told her to call me? +Be patient, you won't regret it +Later, when I feel comfortable about you +Who told you I needed more women? +Did I beg you to call me and test me - to see if I am worthy of you or not? +Wait a minute +- Wait a second +- I'll hang up +First you didn't want to talk, now you can't wait for a second? +This phone thing is old-fashioned +Times have changed +There are now clubs and social gatherings for people to meet and know each other +It's not logical for a girl to reveal half her body at the beach and then hide her identity on the phone +People have no time for such hypocrisy +Did you expect me to jump at you and say I loved you? +Since we've gone this far, please tell me your name +I will count till three +If you don't tell me I'll hang up 1, 2, 3 +- Wrong number +- My name is Nadia Lotfy +My father is Ahmed Lotfy, we live in Dokki +You saw me and you liked me +You even threw your ball at me this morning +Great! +When will we meet? +Please, Nadia +Since we will meet anyway, then the sooner, the better +Tomorrow at 4:30 in front of the Horse-Riding Club +No, 4:30 +I am confused, almost lost +As if an invisible hand pushed me towards an unknown fate +I needed someone by my side +I needed someone to guide me to the path of security +But I had no one +I couldn't ask my father's opinion, nor his wife's +I felt just as lonely as I had before +I feel afraid of Mostafa +He is stronger and older than I am, and more experienced +Should I turn back? +Doc you're beginning to sound like Sherlock Holmes. +homer, marge, bart, lisa, maggie diff --git a/bench/data/opensubtitles/en-medium.txt b/bench/data/opensubtitles/en-medium.txt new file mode 100644 index 0000000..4ae25a1 --- /dev/null +++ b/bench/data/opensubtitles/en-medium.txt @@ -0,0 +1,2170 @@ +Now you can tell 'em. +What for are you mixing in? +Maybe I don't like to see kids get hurt. +Break any bones, son? +He's got a knife behind his collar! +- There's a stirrup. +You want a lift? +- No. +- Why not? +- I'm beholden to you, mister. +Couldn't we just leave it that way? +- Morning. +- Morning. +- Put him up? +- For how long? +- I wouldn't know. +- It'll be two bits for oats. +- Ain't I seen you before? +- Depends on where you've been. +- I follow the railroad, mostly. +- Could be you've seen me. +- It'll be four bits if he stays the night. +- Fair enough. +Morning. +Did a man ride in today - tall, sort of heavyset? +- You mean him, Mr Renner? +- Not him. +This one had a scar. +Along his cheek? +No, sir. +I don't see no man with a scar. +I guess maybe I can have some apple pie and coffee. +I guess you could have eggs with bacon if you wanted eggs with bacon. +- Hello, Charlie. +- Hello, Grant. +It's good to see you, Charlie. +It's awful good to see you. +It's good to see you too. +- I'll get the eggs. +- No, get the pie. +I can pay for the pie. +You're a very stubborn man. +Apple pie is not for breakfast. +It is if you like apple pie. +Now I need a fork. +- Working here long? +- About three weeks. +How's the Utica Kid? +He was well... when I saw him last. +When was that? +- Good morning. +- Morning. +Well, business is early and Pete is late. +The lunches. +Are they fixed? +Why do I ask? +The lunches are always fixed. +Why? +Because you fix them. +Charlie, I'll make you an omelette like only Pete can make an omelette. +Very bad. +Come on around, sit down, have a cup of coffee. +Pete had that place in Santa Fe, remember? +Are you running a shoe store on the side? +Those are box lunches for the work train. +Money, money, money. +Pete knows how to make it. +He follows the railroad. +I guess a lot of people follow the railroad. +You and Pete. +The Utica Kid. +I asked when you saw him last. +They've lost three payrolls. +Now when did you see him last? +- Charlie, where did I put my apron? +- It's under here. +You must be nice fella. +If Charlie sits with you, you must be nice fella. +I make omelette for you too. +We were talking about the Utica Kid. +He can wait. +Ben Kimball's in town. +They put his car on the siding yesterday. +- I know. +- His wife is with him. +Is she? +I often wondered what Verna was like. +I saw her last night. +All fine silk and feathers. +She's soft and beautiful. +And I can understand now. +Can you? +How long are you gonna be in town? +- That depends on Ben Kimball. +- You working for the railroad again? +- If I am? +- That would be good. +Playing the accordion's not for you, not for a living. +You belong to the railroad and it belongs to you. +There were a lot of things that used to belong to me and somehow I lost them. +Two omelettes a-comin' up. +- Do you like eggs? +- No. +That's too bad. +You got an omelette coming up. +Well, somebody's gotta eat them. +Come on. +That means you. +- Could you put it in a box? +- An omelette? +I'll be hungrier when I get to end of track. +Maybe it will go down easy. +Easy or not, it goes down right now. +I can't pay for it. +Then you can help me sell lunches at the station. +Any more arguments? +Come in. +- You want to see me, Ben? +- I certainly do. +Hello, Grant. +Sit down. +All right, Jeff. +Renner, go to Pete's and get one breakfast and a jug of coffee. +- You haven't eaten yet? +- I've eaten. +Just get coffee. +Hot. +- How's everything been going? +- I make a living. +- Playing an accordion? +- That's right. +Want me to play a tune for you? +There's other jobs besides railroading. +Well, Colorado may be big in miles. +It's kinda short on people. +So when a man gets fired the way I was fired the story gets around. +Well, I'm... +I'm sorry. +- No, I like to make music. +- And it keeps you near the railroad. +If someone needs information about a payroll, you can sell it. +You know it's a funny thing. +I don't like you either. +- Is that why you sent for me? +- No. +And keep out of this. +Have it your way. +But I don't trust him now any more than I did when I sent him after the Utica Kid. +I sent you after a thief and you gave him a horse to get away on. +- I told you to keep shut. +- Let him talk. +I'm not wearing a gun. +I'll be honest with you. +He'd talk the same if I was. +- It's been nice seeing you. +- Grant. +I'm sure Jeff didn't mean to be rude. +Sometimes he has a blunt way of putting things. +Unfortunately, Ben isn't much better. +It's not unfortunate. +It just gets things said in a hurry. +Too much of a hurry. +They forgot to ask you if you'd work for the railroad again. +Would you? +Yes, I would. +Not to give you a short answer. +- It's the answer I wanted. +- Sit down, Grant. +Do you remember Whitey Harbin? +Used to work down in Arizona and New Mexico. +- Yeah. +- Well, he's moved into Colorado. +I thought he favoured stage lines and banks. +So did we. +But he's learned about railroad payrolls +- and he's grabbed three in a row. +- Where do I fit in? +They're making up a supply train in the yard. +I want you to ride it. +- With $10,000 in your pocket. +- Why me? +Quite frankly, because no one would suspect you of carrying a payroll. +I sure don't look like $10,000, do I? +Are you building a bridge you don't need? +The money's here. +Why not bring the men in on Saturday and pay them off in town? +And lose half the crew? +Turn them loose in a mining town, they'll go up the hills looking for gold. +It won't work. +And we have to finish this section before snow comes. +That's a pretty big gamble on a man who gave his horse to a thief! +Yes. +You might as well know the deck's stacked against you. +A boxcar will be hooked to the train. +I'll be one of the men in it. +- When did this happen? +- Last week. +- Renner, did you know? +- Yes. +- Why didn't you tell me? +- I told him not to. +- Why? +- Everything we plan gets back to Whitey. +- You think I'd tell him? +- You might trust the wrong people. +- If he takes the job, I'm sure of it. +- And if I don't take it? +Then Jeff will be sitting in Ben's chair. +Oh, I wouldn't like that. +Uh-uh. +So I'll take the job on one condition. +If I make the delivery I get his job. +You made a deal. +Thank you. +Wait a minute. +It's getting cold up in the hills. +This coat has always been too long for me. +Thanks. +Well. +I thought you didn't like him. +He said that. +I said I didn't trust him. +And I still don't. +Grant. +Are you surprised Ben sent for you? +I was until I talked to him. +He seems to have changed. +You're right. +He doesn't belong in a private car with clerks, figures and pressure from the office. +He belongs at the end of track, running a gang and building a railroad. +- He's a working stiff like you. +- Yes, but he can dream a little too. +Colorado wouldn't have a railroad if he hadn't sold them on the idea. +For his sake, I wish he hadn't. +He was happy at end of track but they kicked him upstairs and sent us to Chicago. +- And now he needs a little help. +- That's why he sent for you. +Oh, I may have had something to do with it. +Why? +There was a time when you were interested in me. +I was more than interested in you. +I wanted to marry you. +Times when I'm sorry you didn't. +Aren't you? +No. +A man likes to know his woman will back him when he's down and you didn't. +Ben called me a thief and you went right along with him. +It's as simple as that. +Grant. +For old times' sake. +For old times' sake? +Just that and nothing more? +Perhaps just a little more. +We want to be sure that payroll goes through, don't we? +I don't know. +Maybe Jeff is right. +His type seldom changes. +And if we've made a mistake, it's the finish of everything. +Then why not cut this car into the supply train? +If we're all playing showdown, I'd like to see the cards when they fall. +- Thank you. +I hope you have a nice trip. +- Thank you. +- Ma'am, is that all? +- Mm-hm. +- Here's your lunch. +You've earned it. +- Thanks. +- Mister, are you going to end of track? +- Yes. +Could you stake me to a ticket? +I can ride half fare if I'm with an adult. +- And you're an adult. +- Well, sometimes I wonder. +All right. +You can come along. +We'll ride with the other fellas with no money. +- On the flatcar? +- Go on. +Climb aboard. +Plenty of fresh air. +Do you good, make you grow. +Are you sure he didn't come while I was away? +Ain't nobody been here but the man riding the sorrel. +- What colour horse your man riding? +- How should I know? +It's extremely important that I see him. +They've cut in Mr Kimball's car. +Barley! +A man told you to put his horse up... +Don't start that too. +That there sorrel is the only horse what come in. +That there sorrel is the horse I want. +He belongs to my friend Grant McLaine. +McLaine? +That's who it is. +I knew him as a troubleshooter in Santa Fe before he went bad. +- He didn't go bad. +- What'll you do with his horse? +- Ride him! +I'll change, you saddle him. +- All right. +Hey, Pilgrim! +Come here! +Don't go getting your liver all upset. +- Once you miss 'em, they stay missed. +- It's none of your business. +- Could be. +You wanting to get on that car? +- If I am? +- I can take you to where it's going. +- On one of these? +They'll get you to end of track before the train does. +- That's ridiculous. +- $100 aging yours I'm right. +- You've got a bet. +- And you got stuck. +Here. +I'll let you ride Flap Ears. +- You can smoke inside, mister. +- I can smoke where I want. +You can burn too if it pleases you but it'll still cost you four bits. +- For what? +- Travelling first-class. +Otherwise ride the flats. +- You play that? +- Yeah, I play it. +- When? +- When? +Whenever somebody throws a dime in my hat. +- I ain't got a dime. +- This one's on me. +- Been up here before? +- Part way. +- What takes you to end of track? +- A job. +Figured I'd get one at Junction City. +They told me the foremen do the hiring. +You're a little small for swinging a sledge. +- I can carry water. +- Yeah, you can carry water. +- Very important job. +- Hey! +- What are you doing here? +- He's with me, Pick. +- Where did you get him? +- Somebody threw him away. +Don't you throw him away. +He'll get lost in the mountains. +Who tells the men who build railroads how to get through the mountains? +- The river. +- Huh? +They just follow the river. +- Who told you that? +- I guess my dad was the first. +He had a little song about it. +# Follow the river +# The river knows the way +# Hearts can go astray +# It happens every day +# Follow the river +# Wherever you may be +# Follow the river back to me # +Wouldn't you wanna be knowing about Concho? +- Who's Concho? +- The man you roped. +Do you wanna know? +Not unless you wanna tell me. +I ought to tell you. +He's fast with a gun. +Only know two men who are faster. +Which two men would they be? +Whitey Harbin for one. +I run away from Whitey. +That's why Concho was after me. +You're one of Whitey's men? +No. +I was in Montrose. +Whitey and his bunch were robbing a bank. +I was just in the road watching. +Whitey was all for killing me but the other fellow wouldn't let him. +He swung me up into the saddle and said, +"You ain't killing a kid. +Not while I ride with you." +- Whitey, he backed down. +- Cos the fella's faster with a gun? +Like lightning. +This other fella, does he have a name? +He's got a name. +The Utica Kid. +I'd have stayed with the bunch if he was boss. +- But he's not? +- Not yet. +Always he's shoving pins into Whitey, laughing at him, driving him crazy. +Even crazier than he is! +Someday Whitey will crack and he'll lose. +Is this the fresh air you were talking about? +How come them fellas can ride inside? +Well, it's the old story of good and evil. +If you spend all your money on whiskey, you have none left for a ticket. +Don't drink. +Then you'd have six bits when you need it. +That's very true. +Tell you what, maybe I have six bits. +Yeah. +What do you say we go in and spend it? +Come on. +Guess I wasn't tough enough to follow the river that way. +Sometimes it isn't easy travelling upstream. +- That will be a dollar. +- That'll be six bits. +I'm the adult. +Here. +Hold on to that. +- Don't worry about Concho. +- You would if... +Oh, no, come on. +Sit down. +We can both worry together if you want to tell me about it. +- It's nothing. +- And if it was, you'd rather not say. +All right. +I broke with Whitey. +Doesn't mean I have to talk. +No, you don't have to talk. +I even broke with the Utica Kid. +- Hi, Utica. +- Put him away, Howdy. +Sure. +Come on. +It's a pretty good rig. +Too good for the guy that owned it. +Remember that draw you taught me? +It worked. +He went down with his gun in the leather. +- And now you're an "in case" man. +- In case? +Yeah. +In case you miss six times with one, you draw the other. +- If you have time. +- I'll have time. +Call it. +Draw! +You better learn to draw that one before you fool around with the other. +About three inches high, Whitey. +You better take another look at that skull. +Next time it could be yours. +Don't soft-foot up behind me! +It makes me nervous! +So I notice. +What else did you notice? +Did you see Concho? +- Did you see him? +- He wasn't on the trail. +Did I ask you where he wasn't? +I asked you did you see him? +- I would've said so. +- Not straight out you wouldn't. +Because you're a funny man. +You've always gotta be laughing inside. +Well, go ahead, laugh. +But get this, Kid. +I'm a better gun than you. +Or would you like to try? +It's an interesting thought, but I'm afraid of you, Whitey. +You ain't afraid of me. +And in your feet, where your brains are, you think maybe you're just a bit faster. +And you know something? +It could be. +Before you break up completely, you mind putting a name on this? +It's just a little old wedge. +But when you put it through the latch of a boxcar, you can't open the door from the inside. +Now, you ask me, who would want to open the door of a boxcar from the inside? +- Jeff Kurth and a dozen gunmen. +- How would you know? +I was sleeping up there when Concho told you. +You better learn how to snore! +You wouldn't know how to shoot a man in the back. +I'll learn. +What'll it be, gents? +We got Old Grandpa, Old Grandma, Old Uncle Tom. +- And Old Empty. +- You ain't funny, Latigo. +Who could be funny, sweating it out in here? +Get away, boy. +You're too young for whiskey even if we had plenty. +Don't get fancy. +You ain't talking to Joey. +Speaking of Joey, you didn't happen to spot him along the trail, did you? +I'll take a shot of that Old Flannelmouth. +- Did you see him? +- No. +Did he leave any sign? +A little. +He was headed toward Junction City. +But you didn't follow him? +Joey always was a nuisance. +I was for dropping him in the river. +- Why didn't you? +- And get my brains shot out? +You've got to find a better reason to kill me. +Suppose Concho didn't catch up with Joey in town and suppose the kid talked? +- He won't talk. +- Maybe not, but Concho ain't back. +Unless he gets back, we won't know where they're carrying the money. +That's right. +Maybe it'd be smart to let this one go through. +Why? +We've grabbed three in a row. +Let's give them a breather. +That makes sense. +I go along with Utica. +You and me both. +We ought to let this one go through. +It ain't going through! +Why not? +You're the one who taught me about payrolls and now I like them. +- So do I. +- I'll buy that. +A man can get saddle-sore looking for a bank to take. +- I'm with Whitey. +- Me too. +What about you, Torgenson? +I got no complaints. +You call it, I'll play it. +Looks like you've been outvoted. +Or do you want a recount? +- Right now, I'd rather have a drink. +- Suit yourself. +If I can't buy a fight, I'll buy a drink. +Fill 'em up. +Sorry, the bar is closed. +On account of we're fresh out of whiskey. +Either get this floor fixed or get a new bartender. +When do we make the hit? +Any time you're ready. +She was halfway up the grade when I left. +Why didn't you tell me? +Why didn't you ask me? +Funny man! +Mount up! +Settle down. +It's only another job. +But if you was boss, we wouldn't do it. +If I was boss we wouldn't do it. +You ain't boss! +# So I bought myself a shovel and I bought myself a pick +# And I laid a little track along the bullfrog crick +# Then I built a locomotive out of 20 empty cans +# And I tooted on the whistle and the darned thing ran +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# Something's gotta take you there and gotta bring you back +# You can't go any distance in a buggy or a hack # +Throw some ropes around them timbers. +We'll pull it down. +Torgenson! +- OK, John. +- Hurry it up, Jubilee! +- Boy, they're pushing her fast today. +- Yeah! +Maybe they heard I needed a quick ten thousand. +- That water tower your idea? +- What's wrong with it? +Any self-respecting Injun could walk away with it. +Funny man! +He knows everything about everything. +Let's get down and lock the barn door. +We've stopped! +Whitey's making his hit! +- McLaine sold us out! +- No, Ben. +They didn't learn it from Grant. +Leary! +- A hold-up! +- They did it again! +Stop your moaning and hold on to your hat! +They won't stop old Tommy Shannon with a tank full of water. +That's no way to treat railroad property, Mr Shannon. +Take your hand off the throttle and reach for the brake! +All right. +Sit down and behave! +Come over here. +Open the safe! +- Ha! +- Move in! +Same as last time! +- We thought you were lost or drunk. +- There ain't nothing in there. +Jubilee! +How are you making out? +Try to talk your way out of this! +- I'm sorry I missed out with Renner. +- Never mind. +Where's the money? +- It's not in the safe. +- Then where is it? +It could be going to Junction City with Jeff's men. +That's not true. +Renner told us Jeff wouldn't carry the payroll! +That's a help. +Least we know who didn't carry it. +Funny man! +When you get through laughing, see what's in that red car. +Sure. +Glad to. +As soon as I pick up my horse. +He's worth more than anything I'm gonna find on this train. +Get those pilgrims out. +Maybe one of them is carrying it. +Hit the other cars! +See if you can find it. +Outside! +All of you! +Is this what you wanted to tell me? +Have a look inside, Latigo! +If that's McLaine... +No, Ben. +Put it away. +You may as well be comfortable. +- Be my guest. +- Gladly. +Do you mind if I ask the name of my host? +No, I don't mind. +Would the payroll be in there? +No. +Why not take a look, just to be sure? +Boy, is this stuff mellow. +Bottled in bond too. +- I forgot. +Ladies is always first. +- Thank you, no. +See for yourself. +Hello, Joey. +What are you doing here? +Getting robbed! +Don't bother. +None of them's got more than two dollars. +Whitey! +There ain't no payroll in there. +How come you missed out? +- I had a little trouble. +- Now, ain't that too bad? +- Maybe I ought to give you a little more. +- Whitey! +Kimball's back there with his wife. +You just got lucky! +Put them back in the car! +Get aboard! +Go on. +Good little boys don't run away. +This time you'll learn! +- Where's the payroll? +- The man says he doesn't know. +I can help him remember. +Take her outside. +Take her outside yourself. +I'm afraid of women. +They scream and scratch, and sometimes step on your toes. +Don't say no to me. +Not when I got a gun in my hand. +I won't. +Unless I'm holding one too. +- Outside. +- If you want the payroll... +You'll have to wait for the next work train. +We decided not to send it through on this one. +Oh? +I don't mind waiting. +I'll be at Pay Load. +You can bring it to me. +Then I'll take 12 hours' start, you get your wife back. +See what happens when you don't carry your brains in your feet? +I ought to make you walk. +Jubilee, lead them out. +Step up with Latigo. +What about Joey? +You gonna leave him here? +He'll ride with me. +Or would you like to? +Settle down. +We're getting $10,000 for the lady, remember? +Which one do I ride with? +Which one do you think? +Take her to the end of track, Mr Shannon! +Here's a stirrup. +Give you a lift? +I'll take that box. +Don't crowd the cantle. +You'll ride easier. +Whoa, mules! +Must have got tired of making the climb and started home. +- Come on, boy! +- Just a minute. +There's a mining town near here. +It used to be called Pay Load. +It's still called Pay Load but nobody lives there. +- It's over beyond that far hill. +- Which hill? +- You see the first hill? +- Yes. +See the second one? +There's a third hill. +Pay Load's behind that. +- How much do you want for this mule? +- $50. +Flap Ears, when you unload this piker, you come on home to mother. +- Get outta there! +- Gah! +Welshing on a bet! +Never could understand them railroad people. +Come on! +Come on! +- Mr Kimball. +- Come over to the telegraph shack. +- Before you pass. +Did you bring the payroll? +- Not now! +- Did you bring it? +- I didn't. +- Now what? +- The end of the railroad. +- Shut up, Feeney. +- Let go of me or I'll push this down your throat! +Who wants your man? +I don't want none of 'em! +They're all broke! +- See you in Denver. +- I'm off to Denver too. +- So am I! +- Nobody goes without orders from Kimball! +- I'm leaving. +- You are not. +You'll take no joyride in this town with them painted hussies. +We've waited this long. +Another night won't hurt us. +But if the money's not here in the morning, out we go! +Get back to work! +We're beat, Mr Kimball. +Without the pay, the gang will go to Junction City. +- I know. +- Any word from Jeff? +He's in Junction City. +Says the car held to the grade all the way. +He and his men will be after Whitey in... +They will not! +Tell him to stay right where he is until further orders. +Yes, sir. +Wonder if he thinks that's private property. +If he tries to divide that like he cuts up the loot, there's gonna be shooting. +- Your laundry? +- Sandwiches. +Do you want one? +No. +Where did you get them? +Junction City. +A girl in a restaurant gave them to me. +- Was she pretty? +- Mm-hm. +- Think you could get me a date? +- She's not that kind of a girl. +Any of you boys win enough to buy a drink? +- You ain't got a drink. +- I got a drink. +- I thought you was fresh out. +- I was till we made the hit. +While you looked for the payroll that wasn't there, I had important business. +Come on, fill her up. +Latigo ought to be running this bunch. +We might not eat, but we'd sure drink. +Ha ha! +You're a funny man. +Why don't you laugh? +- Am I supposed to? +- Not if you're smart. +- I think you're smart. +- And what else do you think? +That you made a mistake. +She'll only bring you trouble and guns. +Since when is $10,000 trouble? +That's exactly what you're worth. +You're very flattering. +But I'm inclined to agree with you. +Don't make a habit of it. +Latigo, I want a drink! +And you've got a few habits I don't like either. +Settle down. +Do you see what she's up to? +I can see you. +And what I see I don't like too good. +- I guess you could use one. +- Thank you, no. +- It's the best. +I got it off your own bar. +- You drink it. +Sorry, lady, I don't drink. +I'm studying to be a bartender. +- Don't you drink? +- Not alone. +Suppose I join you? +- Do you mind? +- And if I do? +Don't push it. +For a little while you're gonna need me and I'm gonna need you. +I watched you walk. +I could swear we've met before. +Could you? +Funny little things you do. +Like when you smile. +Strange. +I seem to recognise all your mannerisms, if you know what that means. +- I know what that means. +- Do you? +I'm supposed to fight Whitey over you. +With a little luck we'd kill each other. +- It's an interesting thought. +- What's interesting? +- She is. +- You're so right. +I may not send you back. +Not until you've helped me spend the ten thousand. +- You mind if we join the party? +- Yes! +You shouldn't, cos if you guess wrong you ain't gonna hang alone. +You like another drink? +- Thanks, I still have this one. +- Drink them both. +Anybody want to start the dance? +With only one girl? +Get back to the bar where you belong. +Let's all get back to the bar, where we belong. +- You almost got your wish. +- One of them. +- The other? +- To know your name. +His name? +He's the Utica Kid. +I don't like it either. +My family used to call me Lee. +Why don't you? +You're supposed to be outside. +Come out with your hands up. +- What are you doing here? +- I want to see the Utica Kid. +- Who are you? +- A friend of his. +Funny thing, he never told me about no girlfriend. +Is there any reason why he should? +- What's your name? +- Charlie Drew. +And you can put that gun away. +Or do I look dangerous? +Not exactly. +Give me that rope. +- When'd you get here? +- Just before they rode in. +Utica pulled the job off right on schedule. +I suppose you've known it was going to happen for quite some time. +No, I haven't. +Utica doesn't talk to me about jobs. +Not this kind. +- Did he ever have any other kind? +- He will have. +Soon. +Then why don't you hold out? +Why don't you keep away till he stops being a thief? +I told him that's what I'd do. +He just looked at me and smiled. +He said, "I wonder if you can." +Tonight he has his answer. +You're here. +Yes, but only to tell him that you're... +Only to tell him I'm in town and might come looking for him. +I want to keep him alive. +I want to keep you alive. +- You know what he can do with a gun. +- I know. +- Well, then, why? +- Because of a little thing called self-respect. +Maybe you wouldn't understand anything about that. +For five years I've played that thing for nickels and dimes thrown into a hat. +For five years the Utica Kid has been laughing. +I may have been wrong, Charlie, but I'm not gonna make the same mistake twice. +Grant... +When you see him will you tell him that I'm here? +Leave it alone! +So all she'll bring is trouble and guns, huh? +Did you bring the money with you? +No. +- How soon do we get it? +- I wouldn't know about that. +You should! +$10,000 is a lot of money. +And that's what he wants for me. +Well, I'd say he was selling out cheap. +Never mind what you'd say. +What did Kimball say? +If you don't know about the money, why did he send you? +He didn't send me. +I came on my own. +Why? +- Ask him. +- Well? +I wouldn't know. +Then again, maybe I would. +You were right the first time. +I can walk quiet at night and I'm a pretty good gun. +I'd like to join up with you. +You see, when a man gets fired off the railroad, he has a little trouble finding a job. +And when he can't find a job, he gets hungry. +I've been hungry for the last five years. +Haven't I? +- How would he know? +- I'm his brother. +- His brother? +- His younger brother. +Five years ago he was a troubleshooter for Kimball. +I lifted the feed herd and he came after me. +Then gave you a horse to get away. +But not until I'd heard all about good and evil. +I didn't buy what he had to sell then. +I'm not buying it now. +- So you don't want him in, huh? +- No. +Funny thing. +I want him in. +- Any objections? +- It ain't that simple, Whitey. +There's a personal deal between me and him. +- About what? +- He got in my way. +That's right. +Oh, yeah, I remember you. +You're the man that fights kids. +Which way do you want it? +Get up, come on, get up! +Now one of you give him his gun. +All right, Harbin, you're the boss around here. +You call it. +I might just do that. +Well, I ain't gonna take him alone. +Then maybe you'd better move along. +Any further objections? +- Yeah. +- Now ain't that wonderful? +- I'd be happy to call it. +- You may get the chance. +You mind if the Utica Kid and me have a little talk? +Not at all. +Call me when you're ready. +I think you ought to know I'm working for the railroad again. +I figured as much. +- Troubleshooter? +- Tonight I was carrying the payroll. +- Where did you hide it? +- I gave it to the boy. +It's in that shoe box. +Now all you have to do is go in and tell Whitey. +You're gambling I won't? +- Same old story of good and evil. +- Same old story. +You lose, Grant. +Yeah, I kind of figured that when you laughed. +I'll give you the same break you gave me. +Ten-minute start, then I tell Whitey I sent you away. +I go, that money goes with me. +So does Kimball's wife. +- No. +- Wait a minute, Lee. +Hear me out on this. +If I leave here, that boy goes with me too. +Joey? +Why do you want him? +Maybe for the good of his soul. +It's been a long time since you heard that word, hasn't it? +Mother and Dad used to bring it up once in a while when we were kids. +You were just about Joey's age. +He thinks a lot of you, doesn't he? +- He wants to grow up to be just like you. +- He may make it, with practice. +Soon he'll be holding the horses while you and Whitey hit a bank. +There's another kid lying in the barn. +He got the start that way too, huh? +- You didn't kill Howdy? +- I didn't hurt him. +- And you're not going to hurt Joey. +- How could I do that? +It's not hard. +It's not hard. +Not when he takes your road. +Or haven't you stopped to look at it? +Why bother? +I picked it, I'll ride it. +Lee, I'm asking you again. +Give Joey a chance. +No. +You've got ten minutes. +I won't need them. +Charlie's in there waiting for you. +Think about her. +She's been following you for five years too. +She's got a reason. +Or didn't I tell you I'm gonna marry her? +How much of that did you hear? +Just what I wanted to hear. +That you're gonna marry me. +When? +We're gonna have a lot of money, Charlie. +$10,000. +You can have pretty new dresses and pretty new shoes. +And a brand-new husband. +- Tomorrow. +- No. +Right now! +If you want me, take me away right now. +Please, please take me. +Why the sudden hurry? +Has my big brother been telling you the story of good and evil? +Don't laugh at him. +Why not? +Why mustn't I laugh at him? +Maybe it would be better if... if you tried to be a little more like him. +Now isn't that just great? +Now I get it from you! +Ever since I was a kid that's all I can remember. +"Why don't you be more like your brother? +Why can't you be more like Grant?" +I don't want to be like him. +I don't want any part of him. +- That's not true. +- Yeah, it's true! +You don't know what it's like to be the kid brother. +Everything you do is wrong. +Everything you try. +Until one day I tried a gun. +Fit my hand real good. +And I wasn't the kid brother any more. +It's a good gun. +It's gonna get us everything we always wanted. +But I don't want it. +Not that way. +Why must you steal? +Because I like to steal. +I like to see what people will do when I take it away from them. +What happens when something is taken away from you? +Nobody's gonna take anything away from me. +Charlie, I'm asking you to marry me. +No. +Grant was right. +You'll never change. +And he calls me a thief? +Joey. +Go on. +Play some more. +It's been a long time since I heard an accordion. +Any tune in particular? +Or would this do? +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# You gotta have an engine and you gotta have a track +# Oh, you can't get far without a railroad +# There are tracks across the prairie +# Where the buzzard builds his nest +# There are tracks across the Rockies +# To the Golden West # +How does it go from there? +How does it go from there, Lee? +Everybody will be neighbours +In this little dream of mine +Take you clear across the country +On the Bullfrog Line +# Oh, you can't get far without a railroad +- # You can't get far without a railroad # +- Gentlemen! +- Renner! +- Didn't you know he was working for me? +- I've come for my thousand dollars. +- What thousand dollars? +Your memory is quite short. +I supplied you with information about a certain boxcar. +I was prepared to supply you with information about the payroll. +- Concho did not keep the appointment. +- So? +So ten per cent of the payroll is mine. +Sorry to disappoint you but we missed the payroll. +Missed the payroll? +In that case I'm prepared to make a better deal. +For $2,000, I can tell you where the money is. +You made a deal. +Ben Kimball hired a man to carry it. +I might never have located this place if I hadn't heard that man's accordion. +He has the money. +Ask him! +Joey! +Come here, Joey! +Grant! +McLaine, there's a woman with you! +- That's right. +- Send her out before we come get you. +Here, hurry! +Come on, Charlie. +He's in the clear. +He's riding away. +Yeah, he's riding. +After me. +- What are we stopping for? +- We're going to the mill, the short way. +Get down to the mill! +Come on! +Take cover! +Here. +There's a mine shaft at the end of these cables. +It runs clear through the mountains. +On the other side, about half a mile, is the railroad! +It's two hours to the end of track. +I have to send you out one at a time. +Come on, Verna. +- Tell Ben he'll get his payroll somehow. +- I'll tell him more than that. +You'll get that money even if you had to kill your own brother? +The next ore bucket that comes down, pull it around and jump in. +I'll cover for you. +It's clear, Charlie. +Get out! +See if you can reach him from over there. +He can't stand them off, not alone. +You figuring to help? +Grant! +Look out! +He's real good. +Only one better gun in Colorado. +Charlie! +Get over here! +- I thought I told you to get out. +- I'm staying right here. +All right. +Now you get back inside and I'll cover for you. +Thanks, Charlie. +Lee, not the kid! +You take care of the kid. +I'll see if I can keep them pinned down. +Would you mind if I play big brother just this one time? +- Shoots high. +- You or the gun? +- Joey all right? +- He's all right. +That makes you a winner. +Go ahead and make a sucker out of the kid. +Tell him all about good and evil. +Put him to work on the railroad. +Things get tough, he can always play the accordion for nickels and dimes. +Sounds like old times, Lee. +Welcome home. +Don't give me that big brother grin. +- Up there! +- Get him! +I count mine. +There's one left. +He hit you hard, Lee. +Not half as hard as you did with that Bullfrog Line. +That was Dad's favourite tune and you know it. +I know it. +You and your stinking accordion! +Charlie. +Charlie? +You and Joey get the horses. +What...? +I'll take care of my brother. +Here's your money. +Pay 'em off, Tim. +Thank you, Grant. +Looks like you won yourself a job. +Mine. +No, it won't fit. +Not nearly as well as your coat. +Want your old job back? +Thanks. +All right, Joey. +Get a bucket and start carrying water. +We're at end of track. +Now go on. +# Sometimes I feel like I could jump over the moon +# And tell the sky above +# Does it matter how full the moon +# When you've an empty heart +# Follow the river +# Wherever you may be +# Follow the river back to me +# Follow the river +# The river knows the way +# Come to me, I pray +# I miss you more each day +# Follow the river +# Wherever you may be +# Follow the river back to me +# Sometimes I feel like I could jump over the moon +# And tell the sky above +# Does it matter how full the moon +# When you've an empty heart +# Bring back the great love +# The love that once we knew +# Make my dreams come true +# The dream I had with you +# Follow the river +# Wherever you may be +# Follow the river back to me +# Follow the river +# Wherever you may be +# Follow the river back to me # +(Man) I'd better get back to work. +Don't lose all your matches. +- Hello, Mac. +- Hi, Click. +Howdy, folks. +- Hi. +- Hello. +Welcome home, man. +Come sit down and give us a tune. +- We'll pay you with promises. +- A man can't eat promises. +He can't lose them at cards either. +McLaine! +- No, indeed he can't. +- Where have you been and why? +They were laying track in Wyoming. +Needed a troubleshooter. +- Didn't need me. +- That's too bad. +You can pick up a few nickels and dimes playing your accordion. +That's right, Tim. +What's this? +Playing cards with matches? +When's payday? +Tomorrow, if they get the money past Whitey Harbin. +Which they won't. +He's tapped that pay train three times up. +They'll get it past him or get no more steel before snow. +- O'Brien, shut your mouth! +- My sentiments exactly. +Day shift and night shift, night shift and day shift. +No money in a month. +My patience is ended. +So is their railroad. +Am I right? +- You are right! +- McLaine. +Please play me a peaceful tune or I'll have a revolution on my hands. +I see what you mean. +Are they giving you trouble? +Lucky you're not with the railroad. +Tis a weary man you'd be today if you were troubleshooting for us. +Could be you're right, Tim. +(# Folk tune) +Come on, pretty lady. +Give us a dance! +I dare you, Mr Feeney. +Where's the wife? +Come on! +Big Ed, are you through to Junction City? +This is for Kimball. +As per your instructions, this is to advise you that Grant McLaine is here at end of track. +You don't need that last. +Just say he's here. +Get away from him! +Get away from him! +Dancing, is it? +Let me... +Get back into your tent where you belong, you painted women. +You and your railroad. +Bringing the likes of this among decent folk. +For two cents I'd take me old man back to Junction City and be through with you. +If you had two cents! +They're at it again. +You can't mix wives and women, even to build a railroad. +Stop this shilly-shally music and give me a jig I can dance to. +Give us a jig, I said. +You watch your feet. +They're heavy. +And so is my fist. +Do I get a jig or do you lose your teeth? +Not now, Mac, not now. +He's not bad. +He's just a fool. +Consider yourself lucky. +Five years ago you'd have got a bullet between the eyes. +I've seen him kill men that could eat you without salt. +Play what you please. +(# Lively jig) +- You asked for a jig, now dance to it! +- Here I go, Feeney! +Hee-hee! +Up Garryowen! +# I was farming in Missouri I was getting tired of that +# So I bought myself a satchel and a stovepipe hat +# And I headed for the station gonna travel all about +# But there wasn't any station and I soon found out +# That you can't get far without a railroad +# You can't get far without a railroad +# Something's gotta take you there and gotta bring you back +# Oh, you can't go any distance in a buggy or a hack +# You can't get far without a railroad +# You can't get far without a railroad +# You gotta have an engine and you gotta have a track +# Oh, you can't get far without a railroad # +I haven't heard that one. +Where does it come from? +Dad used to play it when it got too rough around the house. +Pretty soon us kids would stop fighting and start dancing. +The man makes fine music. +Are we gonna let them use it all up? +Go on with you! +Clarence Feeney, stop looking at them painted hussies and give your wife a dance. +- Go away, woman, I'm tired. +- Tired, is it? +This is my day for dancing or fighting. +Which will you have? +Darling. +Nice work. +I'll give you five dollars tomorrow. +If Whitey lets the pay train through. +Three times is enough. +He won't hit it again. +Oh, don't bet on it. +He's a strange man, this Whitey Harbin. +He's got the big boss plenty worried. +Speaking of Kimball, he wants to see you. +- How would he know where I am? +- I told him. +Here. +You read it. +I'm afraid if I stop the music, Mrs Feeney'll hit me with something. +"Report to me at once in Junction City. +Urgent. +Ben Kimball." +- Maybe he'll give you... +- Another chance? +No. +That's not his way. +- But you will see him? +- Not till they've finished their dance. +- You old hag, I'll... +- Painted hussy! +(Groaning) +Let go of me! +Let go! +Let her go, I said! +(Woman screams) +(Groaning) +(Stops playing) +(Shouting) +(Screaming) +- Hold this. +- Right. +And this is the tune your father used to play to keep peace in the house? +I must have squeezed out a few wrong notes. +Yeah. +- Thanks, Tim. +- Goodbye, Mac. +(Woman screeches) +- Too late for coffee, mister? +- (Woman) Howdy. +I think there's a few warm dregs left. +- Oh. +Howdy, ma'am. +- Step down. +Much obliged. +- They keeping you busy? +- Yep. +Packing out the ore and packing in the vittles. +Them miners can eat more beans than they raise in all of Boston. +- Now they want me to bring in a mill. +- All at once? +No, just a few pieces at a time. +They got tired of waiting for the railroad to reach them. +Between you and me, I don't think it will before snow. +You're hoping it won't? +- First I was. +- Uh-huh. +Figured it'd put me out of business. +It won't. +- It won't? +- No. +It's a funny thing about gold. +There's always some jackass will find it where the railroad ain't. +Then he'll send for me and a few more jackasses to bring in his grub and pack out his ore! +Them crazy miners! +Look at the waste of that good machinery. +Two miles of cable and buckets to go with it. +Last week they up and left the whole thing! +Did the vein pinch out or did they hit low grade? +They didn't hit nothing but blue sky. +Uh-huh. +- This was mighty fine coffee, Mrs... +- Miss Vittles. +Miss Vittles. +I sure appreciate it. +- I got a long ride ahead of me. +- You heading for Junction City too? +Yes, ma'am. +But I'm kind of in a hurry. +I ain't looking for company. +Ten jackasses in a bunch is enough. +- I can save you a trip round the mountain. +- How's that? +Like I told you, the boys hit a good vein, followed it through the mountain. +Last week they busted out on the far side and there wasn't nothing there but blue sky. +Makes a mighty fine short cut into town. +- It sure does. +- Still think I'm crazy? +- I think you're real pretty. +- Ah! +- You going to spend time in these hills? +- Yes, ma'am. +When snow comes you're gonna need a woman. +Or a warm coat, else you'll freeze your knees. +Well, I can't rightly afford a warm coat. +So long, Miss Vittles. +People wonder what a calf feels when he gets roped. +Now you can tell 'em. +What for are you mixing in? +Maybe I don't like to see kids get hurt. +Break any bones, son? +He's got a knife behind his collar! +- There's a stirrup. +You want a lift? +- No. +- Why not? +- I'm beholden to you, mister. +Couldn't we just leave it that way? +- Morning. +- Morning. +- Put him up? +- For how long? +- I wouldn't know. +- It'll be two bits for oats. +- Ain't I seen you before? +- Depends on where you've been. +- I follow the railroad, mostly. +- Could be you've seen me. +- It'll be four bits if he stays the night. +- Fair enough. +Morning. +Did a man ride in today - tall, sort of heavyset? +- You mean him, Mr Renner? +- Not him. +This one had a scar. +Along his cheek? +No, sir. +I don't see no man with a scar. +I guess maybe I can have some apple pie and coffee. +I guess you could have eggs with bacon if you wanted eggs with bacon. +- Hello, Charlie. +- Hello, Grant. +It's good to see you, Charlie. +It's awful good to see you. +It's good to see you too. +- I'll get the eggs. +- No, get the pie. +I can pay for the pie. +You're a very stubborn man. +Apple pie is not for breakfast. +It is if you like apple pie. +Now I need a fork. +- Working here long? +- About three weeks. +How's the Utica Kid? +He was well... when I saw him last. +When was that? +- Good morning. +- Morning. +Well, business is early and Pete is late. +The lunches. +Are they fixed? +Why do I ask? +The lunches are always fixed. +Why? +Because you fix them. +Charlie, I'll make you an omelette like only Pete can make an omelette. +Very bad. +Come on around, sit down, have a cup of coffee. +Pete had that place in Santa Fe, remember? +Are you running a shoe store on the side? +Those are box lunches for the work train. +Money, money, money. +Pete knows how to make it. +He follows the railroad. +I guess a lot of people follow the railroad. +You and Pete. +The Utica Kid. +I asked when you saw him last. +They've lost three payrolls. +Now when did you see him last? +- Charlie, where did I put my apron? +- It's under here. +You must be nice fella. +If Charlie sits with you, you must be nice fella. +I make omelette for you too. +We were talking about the Utica Kid. +He can wait. +Ben Kimball's in town. +They put his car on the siding yesterday. +- I know. +- His wife is with him. +Is she? +I often wondered what Verna was like. +I saw her last night. +All fine silk and feathers. +She's soft and beautiful. +And I can understand now. +Can you? +How long are you gonna be in town? +- That depends on Ben Kimball. +- You working for the railroad again? +- If I am? +- That would be good. +Playing the accordion's not for you, not for a living. +You belong to the railroad and it belongs to you. +There were a lot of things that used to belong to me and somehow I lost them. +(Pete) Two omelettes a-comin' up. +- Do you like eggs? +- No. +That's too bad. +You got an omelette coming up. +Well, somebody's gotta eat them. +Come on. +That means you. +- Could you put it in a box? +- An omelette? +I'll be hungrier when I get to end of track. +Maybe it will go down easy. +Easy or not, it goes down right now. +I can't pay for it. +Then you can help me sell lunches at the station. +Any more arguments? +(Train rattling) +(Train whistle) +(Knocking) +Come in. +- You want to see me, Ben? +- I certainly do. +Hello, Grant. +Sit down. +All right, Jeff. +Renner, go to Pete's and get one breakfast and a jug of coffee. +- You haven't eaten yet? +- I've eaten. +Just get coffee. +Hot. +- How's everything been going? +- I make a living. +- Playing an accordion? +- That's right. +Want me to play a tune for you? +There's other jobs besides railroading. +Well, Colorado may be big in miles. +It's kinda short on people. +So when a man gets fired the way I was fired the story gets around. +Well, I'm... +I'm sorry. +- No, I like to make music. +- And it keeps you near the railroad. +If someone needs information about a payroll, you can sell it. +You know it's a funny thing. +I don't like you either. +- Is that why you sent for me? +- No. +And keep out of this. +Have it your way. +But I don't trust him now any more than I did when I sent him after the Utica Kid. +I sent you after a thief and you gave him a horse to get away on. +- I told you to keep shut. +- Let him talk. +I'm not wearing a gun. +I'll be honest with you. +He'd talk the same if I was. +- It's been nice seeing you. +- (Woman) Grant. +I'm sure Jeff didn't mean to be rude. +Sometimes he has a blunt way of putting things. +Unfortunately, Ben isn't much better. +It's not unfortunate. +It just gets things said in a hurry. +Too much of a hurry. +They forgot to ask you if you'd work for the railroad again. +Would you? +Yes, I would. +Not to give you a short answer. +- It's the answer I wanted. +- Sit down, Grant. +Do you remember Whitey Harbin? +Used to work down in Arizona and New Mexico. +- Yeah. +- Well, he's moved into Colorado. +I thought he favoured stage lines and banks. +So did we. +But he's learned about railroad payrolls +- and he's grabbed three in a row. +- Where do I fit in? +They're making up a supply train in the yard. +I want you to ride it. +- With $10,000 in your pocket. +- Why me? +Quite frankly, because no one would suspect you of carrying a payroll. +I sure don't look like $10,000, do I? +Are you building a bridge you don't need? +The money's here. +Why not bring the men in on Saturday and pay them off in town? +And lose half the crew? +Turn them loose in a mining town, they'll go up the hills looking for gold. +It won't work. +And we have to finish this section before snow comes. +That's a pretty big gamble on a man who gave his horse to a thief! +Yes. +You might as well know the deck's stacked against you. +A boxcar will be hooked to the train. +I'll be one of the men in it. +- When did this happen? +- Last week. +- Renner, did you know? +- Yes. +- Why didn't you tell me? +- I told him not to. +- Why? +- Everything we plan gets back to Whitey. +- You think I'd tell him? +- You might trust the wrong people. +- If he takes the job, I'm sure of it. +- And if I don't take it? +Then Jeff will be sitting in Ben's chair. +Oh, I wouldn't like that. +Uh-uh. +So I'll take the job on one condition. +If I make the delivery I get his job. +You made a deal. +Thank you. +Wait a minute. +It's getting cold up in the hills. +This coat has always been too long for me. +Thanks. +Well. +I thought you didn't like him. +He said that. +I said I didn't trust him. +And I still don't. +(Verna) Grant. +Are you surprised Ben sent for you? +I was until I talked to him. +He seems to have changed. +You're right. +He doesn't belong in a private car with clerks, figures and pressure from the office. +He belongs at the end of track, running a gang and building a railroad. +- He's a working stiff like you. +- Yes, but he can dream a little too. +Colorado wouldn't have a railroad if he hadn't sold them on the idea. +For his sake, I wish he hadn't. +He was happy at end of track but they kicked him upstairs and sent us to Chicago. +- And now he needs a little help. +- That's why he sent for you. +Oh, I may have had something to do with it. +Why? +There was a time when you were interested in me. +I was more than interested in you. +I wanted to marry you. +Times when I'm sorry you didn't. +Aren't you? +No. +A man likes to know his woman will back him when he's down and you didn't. +Ben called me a thief and you went right along with him. +It's as simple as that. +Grant. +For old times' sake. +For old times' sake? +Just that and nothing more? +Perhaps just a little more. +We want to be sure that payroll goes through, don't we? +I don't know. +Maybe Jeff is right. +His type seldom changes. +And if we've made a mistake, it's the finish of everything. +Then why not cut this car into the supply train? +If we're all playing showdown, I'd like to see the cards when they fall. +- Thank you. +I hope you have a nice trip. +- Thank you. +(Train whistle) +- Ma'am, is that all? +- Mm-hm. +- Here's your lunch. +You've earned it. +- Thanks. +- Mister, are you going to end of track? +- Yes. +Could you stake me to a ticket? +I can ride half fare if I'm with an adult. +- And you're an adult. +- Well, sometimes I wonder. +All right. +You can come along. +We'll ride with the other fellas with no money. +- On the flatcar? +- Go on. +Climb aboard. +Plenty of fresh air. +Do you good, make you grow. +(Clunking) +(Train whistle) +Are you sure he didn't come while I was away? +Ain't nobody been here but the man riding the sorrel. +- What colour horse your man riding? +- How should I know? +It's extremely important that I see him. +They've cut in Mr Kimball's car. +Barley! +A man told you to put his horse up... +Don't start that too. +That there sorrel is the only horse what come in. +That there sorrel is the horse I want. +He belongs to my friend Grant McLaine. +McLaine? +That's who it is. +I knew him as a troubleshooter in Santa Fe before he went bad. +- He didn't go bad. +- What'll you do with his horse? +- Ride him! +I'll change, you saddle him. +- All right. +(Train chugging) +(Train whistle) +Hey, Pilgrim! +Come here! +Don't go getting your liver all upset. +- Once you miss 'em, they stay missed. +- It's none of your business. +- Could be. +You wanting to get on that car? +- If I am? +- I can take you to where it's going. +- On one of these? +They'll get you to end of track before the train does. +- That's ridiculous. +- $100 aging yours I'm right. +- You've got a bet. +- And you got stuck. +Here. +I'll let you ride Flap Ears. +- You can smoke inside, mister. +- I can smoke where I want. +You can burn too if it pleases you but it'll still cost you four bits. +- For what? +- Travelling first-class. +Otherwise ride the flats. +(Discordant notes) +- You play that? +- Yeah, I play it. +- When? +- When? +Whenever somebody throws a dime in my hat. +- I ain't got a dime. +- This one's on me. +(# Folk tune) +- Been up here before? +- Part way. +- What takes you to end of track? +- A job. +Figured I'd get one at Junction City. +They told me the foremen do the hiring. +You're a little small for swinging a sledge. +- I can carry water. +- Yeah, you can carry water. +- Very important job. +- (Man) Hey! +- What are you doing here? +- He's with me, Pick. +- Where did you get him? +- Somebody threw him away. +Don't you throw him away. +He'll get lost in the mountains. +Who tells the men who build railroads how to get through the mountains? +- The river. +- Huh? +They just follow the river. +- Who told you that? +- I guess my dad was the first. +He had a little song about it. +# Follow the river +# The river knows the way +# Hearts can go astray +# It happens every day +# Follow the river +# Wherever you may be +# Follow the river back to me # +Wouldn't you wanna be knowing about Concho? +- Who's Concho? +- The man you roped. +Do you wanna know? +Not unless you wanna tell me. +I ought to tell you. +He's fast with a gun. +Only know two men who are faster. +Which two men would they be? +Whitey Harbin for one. +I run away from Whitey. +That's why Concho was after me. +You're one of Whitey's men? +No. +I was in Montrose. +Whitey and his bunch were robbing a bank. +I was just in the road watching. +Whitey was all for killing me but the other fellow wouldn't let him. +He swung me up into the saddle and said, +"You ain't killing a kid. +Not while I ride with you." +- Whitey, he backed down. +- Cos the fella's faster with a gun? +Like lightning. +This other fella, does he have a name? +He's got a name. +The Utica Kid. +I'd have stayed with the bunch if he was boss. +- But he's not? +- Not yet. +Always he's shoving pins into Whitey, laughing at him, driving him crazy. +Even crazier than he is! +Someday Whitey will crack and he'll lose. +(Train whistle) +Is this the fresh air you were talking about? +How come them fellas can ride inside? +Well, it's the old story of good and evil. +If you spend all your money on whiskey, you have none left for a ticket. +Don't drink. +Then you'd have six bits when you need it. +That's very true. +Tell you what, maybe I have six bits. +Yeah. +What do you say we go in and spend it? +Come on. +Guess I wasn't tough enough to follow the river that way. +Sometimes it isn't easy travelling upstream. +- That will be a dollar. +- That'll be six bits. +I'm the adult. +Here. +Hold on to that. +- Don't worry about Concho. +- You would if... +Oh, no, come on. +Sit down. +We can both worry together if you want to tell me about it. +- It's nothing. +- And if it was, you'd rather not say. +All right. +I broke with Whitey. +Doesn't mean I have to talk. +No, you don't have to talk. +I even broke with the Utica Kid. +- Hi, Utica. +- Put him away, Howdy. +Sure. +Come on. +It's a pretty good rig. +Too good for the guy that owned it. +Remember that draw you taught me? +It worked. +He went down with his gun in the leather. +- And now you're an "in case" man. +- In case? +Yeah. +In case you miss six times with one, you draw the other. +- If you have time. +- I'll have time. +Call it. +Draw! +You better learn to draw that one before you fool around with the other. +(Clanking) +(Horse whinnies) +About three inches high, Whitey. +You better take another look at that skull. +Next time it could be yours. +Don't soft-foot up behind me! +It makes me nervous! +So I notice. +What else did you notice? +Did you see Concho? +- Did you see him? +- He wasn't on the trail. +Did I ask you where he wasn't? +I asked you did you see him? +- I would've said so. +- Not straight out you wouldn't. +Because you're a funny man. +You've always gotta be laughing inside. +Well, go ahead, laugh. +But get this, Kid. +I'm a better gun than you. +Or would you like to try? +It's an interesting thought, but I'm afraid of you, Whitey. +(Laughs) You ain't afraid of me. +And in your feet, where your brains are, you think maybe you're just a bit faster. +And you know something? +(Laughs) It could be. +Before you break up completely, you mind putting a name on this? +It's just a little old wedge. +But when you put it through the latch of a boxcar, you can't open the door from the inside. +Now, you ask me, who would want to open the door of a boxcar from the inside? +- Jeff Kurth and a dozen gunmen. +- How would you know? +I was sleeping up there when Concho told you. +You better learn how to snore! +You wouldn't know how to shoot a man in the back. +I'll learn. +What'll it be, gents? +We got Old Grandpa, Old Grandma, Old Uncle Tom. +- And Old Empty. +- You ain't funny, Latigo. +Who could be funny, sweating it out in here? +Get away, boy. +You're too young for whiskey even if we had plenty. +Don't get fancy. +You ain't talking to Joey. +Speaking of Joey, you didn't happen to spot him along the trail, did you? +I'll take a shot of that Old Flannelmouth. +- Did you see him? +- No. +Did he leave any sign? +A little. +He was headed toward Junction City. +But you didn't follow him? +Joey always was a nuisance. +I was for dropping him in the river. +- Why didn't you? +- And get my brains shot out? +You've got to find a better reason to kill me. +Suppose Concho didn't catch up with Joey in town and suppose the kid talked? +- He won't talk. +- Maybe not, but Concho ain't back. +Unless he gets back, we won't know where they're carrying the money. +That's right. +Maybe it'd be smart to let this one go through. +Why? +We've grabbed three in a row. +Let's give them a breather. +That makes sense. +I go along with Utica. +You and me both. +We ought to let this one go through. +It ain't going through! +Why not? +You're the one who taught me about payrolls and now I like them. +- So do I. +- I'll buy that. +A man can get saddle-sore looking for a bank to take. +- I'm with Whitey. +- Me too. +What about you, Torgenson? +I got no complaints. +You call it, I'll play it. +Looks like you've been outvoted. +Or do you want a recount? +- Right now, I'd rather have a drink. +- Suit yourself. +If I can't buy a fight, I'll buy a drink. +Fill 'em up. +Sorry, the bar is closed. +On account of we're fresh out of whiskey. +Either get this floor fixed or get a new bartender. +When do we make the hit? +Any time you're ready. +She was halfway up the grade when I left. +Why didn't you tell me? +Why didn't you ask me? +Funny man! +Mount up! +Settle down. +It's only another job. +But if you was boss, we wouldn't do it. +If I was boss we wouldn't do it. +You ain't boss! +# So I bought myself a shovel and I bought myself a pick +# And I laid a little track along the bullfrog crick +# Then I built a locomotive out of 20 empty cans +# And I tooted on the whistle and the darned thing ran +# Oh, you can't get far without a railroad +# You can't get far without a railroad +# Something's gotta take you there and gotta bring you back +# You can't go any distance in a buggy or a hack # +(Train whistle) +Throw some ropes around them timbers. +We'll pull it down. +Torgenson! +- OK, John. +- Hurry it up, Jubilee! +- Boy, they're pushing her fast today. +- Yeah! +Maybe they heard I needed a quick ten thousand. +- That water tower your idea? +- What's wrong with it? +Any self-respecting Injun could walk away with it. +Funny man! +He knows everything about everything. +Let's get down and lock the barn door. +- (Neighing) +- We've stopped! +Whitey's making his hit! +- McLaine sold us out! +- No, Ben. +They didn't learn it from Grant. +Leary! +- A hold-up! +- They did it again! +Stop your moaning and hold on to your hat! +They won't stop old Tommy Shannon with a tank full of water. +That's no way to treat railroad property, Mr Shannon. +Take your hand off the throttle and reach for the brake! +All right. +Sit down and behave! +Come over here. +Open the safe! +- Ha! +- Move in! +Same as last time! +- We thought you were lost or drunk. +- There ain't nothing in there. +(Man) Jubilee! +How are you making out? +Try to talk your way out of this! +- I'm sorry I missed out with Renner. +- Never mind. +Where's the money? +- It's not in the safe. +- Then where is it? +It could be going to Junction City with Jeff's men. +That's not true. +Renner told us Jeff wouldn't carry the payroll! +That's a help. +Least we know who didn't carry it. +Funny man! +When you get through laughing, see what's in that red car. +Sure. +Glad to. +As soon as I pick up my horse. +He's worth more than anything I'm gonna find on this train. +Get those pilgrims out. +Maybe one of them is carrying it. +Hit the other cars! +See if you can find it. +Outside! +All of you! +Is this what you wanted to tell me? +Have a look inside, Latigo! +If that's McLaine... +No, Ben. +Put it away. +You may as well be comfortable. +- Be my guest. +- Gladly. +Do you mind if I ask the name of my host? +No, I don't mind. +Would the payroll be in there? +No. +Why not take a look, just to be sure? +Boy, is this stuff mellow. +Bottled in bond too. +- I forgot. +Ladies is always first. +- Thank you, no. +See for yourself. +Hello, Joey. +What are you doing here? +Getting robbed! +Don't bother. +None of them's got more than two dollars. +Whitey! +There ain't no payroll in there. +How come you missed out? +- I had a little trouble. +- Now, ain't that too bad? +- Maybe I ought to give you a little more. +- Whitey! +Kimball's back there with his wife. +(Laughs) +You just got lucky! +Put them back in the car! +(Concho) Get aboard! +Go on. +Good little boys don't run away. +This time you'll learn! +- Where's the payroll? +- The man says he doesn't know. +I can help him remember. +Take her outside. +Take her outside yourself. +I'm afraid of women. +They scream and scratch, and sometimes step on your toes. +Don't say no to me. +Not when I got a gun in my hand. +I won't. +Unless I'm holding one too. +- Outside. +- If you want the payroll... +You'll have to wait for the next work train. +We decided not to send it through on this one. +Oh? +I don't mind waiting. +I'll be at Pay Load. +You can bring it to me. +Then I'll take 12 hours' start, you get your wife back. +See what happens when you don't carry your brains in your feet? +I ought to make you walk. +Jubilee, lead them out. +Step up with Latigo. +(Concho) What about Joey? +You gonna leave him here? +He'll ride with me. +Or would you like to? +Settle down. +We're getting $10,000 for the lady, remember? +Which one do I ride with? +(Laughs) Which one do you think? +Take her to the end of track, Mr Shannon! +(Train whistle) +Here's a stirrup. +Give you a lift? +I'll take that box. +Don't crowd the cantle. +You'll ride easier. +Whoa, mules! +Must have got tired of making the climb and started home. +- Come on, boy! +- Just a minute. +There's a mining town near here. +It used to be called Pay Load. +It's still called Pay Load but nobody lives there. +- It's over beyond that far hill. +- Which hill? +- You see the first hill? +- Yes. +See the second one? +There's a third hill. +Pay Load's behind that. +- How much do you want for this mule? +- $50. +Flap Ears, when you unload this piker, you come on home to mother. +- Get outta there! +- Gah! +Welshing on a bet! +Never could understand them railroad people. +Come on! +Come on! +(Train whistle) +- Mr Kimball. +- Come over to the telegraph shack. +- Before you pass. +Did you bring the payroll? +- Not now! +- Did you bring it? +- I didn't. +- Now what? +- The end of the railroad. +- Shut up, Feeney. +- Let go of me or I'll push this down your throat! +Who wants your man? +I don't want none of 'em! +They're all broke! +- See you in Denver. +- I'm off to Denver too. +- So am I! +- Nobody goes without orders from Kimball! +- I'm leaving. +You'll take no joyride in this town with them painted hussies. +Doc you're beginning to sound like Sherlock Holmes. diff --git a/bench/data/opensubtitles/en-small.txt b/bench/data/opensubtitles/en-small.txt new file mode 100644 index 0000000..eecc4dd --- /dev/null +++ b/bench/data/opensubtitles/en-small.txt @@ -0,0 +1,39 @@ +Now you can tell 'em. +What for are you mixing in? +Maybe I don't like to see kids get hurt. +Break any bones, son? +He's got a knife behind his collar! +- There's a stirrup. +You want a lift? +- No. +- Why not? +- I'm beholden to you, mister. +Couldn't we just leave it that way? +- Morning. +- Morning. +- Put him up? +- For how long? +- I wouldn't know. +- It'll be two bits for oats. +- Ain't I seen you before? +- Depends on where you've been. +- I follow the railroad, mostly. +- Could be you've seen me. +- It'll be four bits if he stays the night. +- Fair enough. +Morning. +Did a man ride in today - tall, sort of heavyset? +- You mean him, Mr Renner? +- Not him. +This one had a scar. +Along his cheek? +No, sir. +I don't see no man with a scar. +I guess maybe I can have some apple pie and coffee. +I guess you could have eggs with bacon if you wanted eggs with bacon. +- Hello, Charlie. +- Hello, Grant. +It's good to see you, Charlie. +It's awful good to see you. +It's good to see you too. +Doc you're beginning to sound like Sherlock Holmes. diff --git a/bench/data/opensubtitles/en-teeny.txt b/bench/data/opensubtitles/en-teeny.txt new file mode 100644 index 0000000..89e83b4 --- /dev/null +++ b/bench/data/opensubtitles/en-teeny.txt @@ -0,0 +1 @@ +Sound like Sherlock Holmes. diff --git a/bench/data/opensubtitles/en-tiny.txt b/bench/data/opensubtitles/en-tiny.txt new file mode 100644 index 0000000..355cbc7 --- /dev/null +++ b/bench/data/opensubtitles/en-tiny.txt @@ -0,0 +1,2 @@ +I saw you before but I didn't think you were this young +Doc you're beginning to sound like Sherlock Holmes. diff --git a/bench/data/opensubtitles/ru-huge.txt b/bench/data/opensubtitles/ru-huge.txt new file mode 100644 index 0000000..e429753 --- /dev/null +++ b/bench/data/opensubtitles/ru-huge.txt @@ -0,0 +1,12685 @@ +-Две недели не даешь мне прохода. +Вот и действуй, чем ты рискуешь? +Я думал, что сделаю тебя счастливой. +Тоже мне счастье. +Муж не дает ни гроша, и у любовника ума не хватает подумать о деньгах. +- Хорошенькое счастье. +- Извини, я думал, ты любишь меня. +Ну люблю, люблю тебя, но и не хочу, чтобы все началось как в прошлый раз. +Ты не права. +У меня для тебя сюрприз. +Шлихтовальная машина, ты о ней давно мечтала. +-Для костей? +- Нет, настоящая. +Хочешь, приходи за ней вечером. +Я тебе не девочка. +Была бы ты девочкой, я бы тебе ее не купил. +Ты прекрасно знаешь, что я девочка. +Я люблю тебя, и вечером сделаю все, что пожелаешь, каналья. +Вам будет трудно. +Одинокой женщине руководить таким заведением... +Да нет, месье Эдуан уже давно почти забросил магазин. +А брать нового приказчика я не хочу. +Хватит и одного раза. +- Одного раза? +-Да. +Разве месье Мурэ вас не устраивал? +Да, он умный молодой человек, активный, смелый, но чересчур предприимчивый. +Его нельзя оставлять наедине с женщинами. +У него есть шарм. +Самой порядочной женщине трудно перед ним устоять. +- Хорошо, что предупредили. +- Что? +Нет-нет, я другое хотела сказать. +Я говорила о склонности месье Мурэ в общем. +Я уважаю вашу жену. +Сегодня вечером вы снова едете в Лион? +Ваш билет, месье? +- Какая ближайшая станция? +-Дижон. +А во сколько ближайший поезд до Парижа? +- Из Лиона? +- Нет, из Дижона. +В три десять, месье. +- Во сколько он прибывает? +- В семь часов. +Париж. +Просьба освободить вагоны. +-Улица Шезоль, дом двадцать четыре. +- Хорошо, месье. +- Что с тобой? +-Желудок болит. +Неудивительно, после обеда у Жосрана. +На лестничной клетке до сих пор запах. +Тебе нравится новая хозяйка? +Валери Вабр - настоящая дура. +Скорее, настоящая шлюха. +Ты шпионка. +Твоя хозяйка такая же стерва, как и ты. +Такая же уродина, как и ее мать. +И такая же шлюха. +Уверена, вы о Берте. +- Она тоже? +- Весь дом - сплошные свиньи. +Вот бы вернулся месье Август, а в его кровати красавчик Октав. +Бедняга Август, он целиком занят своей мигренью. +А ведь она правду говорит. +Везде деньги. +Подарок туда, подарок сюда. +Как в театре: за вход надо платить. +Ужасно. +Я отдаюсь за деньги? +Неужели ты веришь? +Скажи, ты в это веришь? +Нет, конечно. +На днях я застала ее на служебной лестнице. +А позавчера еще лучше - в новом платье. +Подарок Октава. +Тебе ночную сорочку, ей платье. +Цена растет. +Кстати, какой сегодня день? +Среда. +Значит, рогоносец в Лионе. +Ему давно пора раскрыть глаза. +Ничего не видит. +Ну, ничегошеньки. +Боже, боже. +Нам нельзя больше видеться. +- Возможно, ты права. +- Ты думаешь? +Ты сделал меня несчастной. +И расплатился с долгами. +- Я ничего такого не говорил. +-Да, но ты так думал. +Слушайте, красавчик Октав, наверное, кусает локти. +Зря он ушел от мадам Эдуан. +Теперь у него добыча помельче. +А ведь запросто мог иметь и ту и другую. +Ему не привыкать. +Да, но его больше всего прельщает касса. +Он спит не с Бертой, а с матрасом, набитым золотом. +Вот тебе и общественное мнение. +Грязные сплетни служанок на служебной лестнице. +И это все? +Думаешь, намеки на содержимое кассы мне приятны? +Ты мог бы протестовать. +Мог бы, если бы это было правдой. +Но кому, как не тебе знать, что касса тут ни при чем. +Ну да, ты спас меня от разорения, да еще и заработал. +Может, сменим тему? +- Тебе неприятен этот разговор? +- Разумеется, от него дурно пахнет. +Дурно пахнет? +Кто бы говорил. +Дорогая, если ты, правда, считаешь, что я люблю тебя из-за денег, то лучше сразу брось меня. +Ну, конечно. +А ты иди к мадам Эдуан. +Иди. +- Ну вот, приехали. +-Да, она вдова. +У нее все преимущества. +Бедная Берта, как ты похожа на мать. +Подумать только, я оплачиваю это ничтожество. +Заведи себе другого. +Откройте, откройте. +Я знаю, что вы оба там. +Откройте или я выбью дверь! +Не открывай, он вооружен. +Он убьет нас. +- Не бойся. +- Трус. +Трус. +Почему вы не отвечаете? +Мерзавец. +Негодяй. +Ну, зачем же применять силу? +Применять силу, применять силу... +Вор. +Мадам, мадам, входите, не стойте тут. +Считайте это пощечиной. +Жду ваших секундантов. +К вашим услугам. +- Что теперь со мной будет? +- Надо было им помешать. +Что теперь обо мне подумают люди? +Ваши родственники? +Разве они могут вас понять? +Они для вас чужие. +Если бы я знала. +Ни о чем не жалейте, не жалейте, раз вы его любили. +Берта, мы будем драться на дуэли. +Берта, малышка моя, мы не можем расстаться в ссоре. +Это было бы слишком глупо. +Мы оба ошибались. +Вот и все. +Это же не преступление. +Три месяца мы думали, что любим друг друга. +Это было чудесно. +Нет? +И потом, может быть это и есть любовь -думать, что любишь. +Если мы... не любили друг друга, то утешься. +Значит, любви не существует. +Нет-нет, мы не ошибались. +Как и все влюбленные, мы считали, что будем уникальной парой на свете. +А теперь, как и все влюбленные, станем такими же как остальные. +Займем свое место. +Берта, дай руку. +Я больше никогда не полюблю. +Никогда. +Ты почти излечилась. +Думаешь о будущем. +Так вы не будете драться? +Будут, будут. +Так нужно. +Но раз вы больше не любите друг друга. +Дуэли часто бывают и без причины. +Прошу прощения, но, кажется, я только что кое-что разрушил. +Не стоит извиняться. +Благодаря вам... я вам покажусь глупой, но чтобы не случилось, я больше не одна. +Вероятно, придется покинуть этот дом. +Ничего страшного. +Ничего страшного, месье Октав. +Это неважно. +Прощай, Берта. +-До свидания, Мари. +- Прощайте, месье Октав. +- Так ты будешь драться? +-До последнего. +Ты же не умеешь. +Я бы на твоем месте... +- Что с вами? +- Ничего. +Это нервное. +Не могу представить Августа на дуэли. +Ты и Дюверье будете моими секундантами. +Наверное, он у себя. +Его нет. +Вы не знаете, где его искать? +- Так вы в курсе? +- Как и все. +Какой же у меня насморк. +- Месье Башляра нет? +- В такой час его никогда не бывает. +Вы случайно не знаете адрес месье Трюбло? +Нет, но месье Башляр вам его даст. +- Во сколько он вернется? +- Наверное, он у племянницы. +Пассаж святого поля дом восемь? +Я знаю. +Спасибо. +На кого я теперь буду похожа? +Могла бы о матери подумать. +Я старалась пристроить тебя, чтобы в старости лет ты меня поддержала. +А ты связалась с этим продавцом. +И о чем ты думала? +- Я ненавидела Августа. +- Это не причина. +Разве я изменяла твоему отцу? +И тем не менее... +- Но она любила Октава. +- Твоя сестра никого не любит. +А если мне нравится никого не любить? +Думаешь достаточно требовать любить, любить, так нет, сердцу не прикажешь. +Она права. +Не выходят замуж только чтобы не подчиниться матери. +Я вышла замуж, чтобы покончить с этой жизнью, чтобы вдохнуть другой воздух, чтобы вырваться из этого дома. +Вышла замуж, чтобы изменять своему мужу. +Довольна? +Несложно было догадаться. +Я приняла меры предосторожности. +Предупреждаю - выхожу замуж через месяц. +Что? +За кого? +-За кого люблю, а он любит меня. +- Несчастная, я помешаю тебе. +- С этого момента... +- С этого момента хватит. +Мы больше не будем терпеть твою диктатуру и преследования. +Говоришь, что не изменяла. +Очень жаль. +Если бы изменяла, я был бы счастливее. +Посмотри на свою дочь. +Твое произведение. +Ни мужа, ни дома, больше ничего нет. +Не плачь, доченька. +Ты жертва моей слабости и ее тирании. +Это мы должны просить у тебя прощения, мы. +- Просить прощения? +Да я лучше умру. +- Это принесет нам только счастье. +Я этого не допущу. +Посмотрим, чья возьмет. +Вы как раз кстати, будете свидетелем. +Негодяй, вот негодяй! +- Свидетелем? +Понимаете, я... +- Свидетелем... +А зачем вы сюда пришли? +- Хотел спросить у вас адрес Трюбло. +- Вы издеваетесь? +Адрес Трюбло? +В кровати мадемуазели, вот где адрес Трюбло. +Прихожу я утром нагруженный подарками и что вижу? +Угадайте. +- Трюбло? +- Трюбло. +Этого мерзавца Трюбло. +А я так жаждал увидеть своего ангела. +- И тебе не стыдно, коварная? +- Я не знала. +- Что? +Не знала, что он тут? +- Не знала, что это вас так огорчит. +А я тебя предупреждала. +Если месье Нарцисс узнает, то будет не доволен. +Вот видишь, вместо того, чтобы меня послушать... +Вы оделись? +Выходите. +Выходите как есть. +Я же говорил -только служанки. +Я впервые нарушил правило. +Нарушил правило. +Иуда. +А как же дружба? +Вы изменили дружбе Башляра. +Я же хранил эту крошку для вас. +Ну да, говорил я себе: когда состарюсь, выдам ее замуж за Трюбло, отдам в надежные руки и спокойно умру. +Ведь у меня есть сердце. +Пятьдесят тысяч хотел дать этому мерзавцу. +Пятьдесят тысяч франков! +-Успокойтесь, Башляр. +- Послушайте месье Октава. +Как вы могли так поступить с другом? +Теперь будем драться на дуэли, на пистолетах с десяти шагов. +Не делайте этого. +Вам незачем драться на дуэли. +-А как же честь? +- Были бы вы ее мужем, тогда понятно. +Были бы вы ее мужем, мне было бы все равно. +Это еще как сказать. +Во-первых, мне нужен Трюбло. +-Зачем? +- Быть секундантом. +Я дерусь на дуэли. +- На дуэли? +-Да. +Но с женатым мужчиной. +С Августом Вабром. +Утром он застал меня с Бертой. +- С Бертой? +-Да. +В каком мире мы живем! +- Можешь мной располагать. +-А кто секунданты Августа? +- Теофиль и Дюверье. +-Дюверье? +Как мило. +У меня с ним встреча по поводу обеда у Клариссы. +Какая прекрасная возможность урегулировать дело чести. +Который час? +Малышка отбила весь аппетит. +Господи, я опаздываю. +А ты, никогда больше так не делай, иначе будешь иметь дело со мной. +Ну же скажи, что больше этого не повторится. +Этого больше не повторится. +Ну же, поцелуй ее, мерзавец. +В лобик. +Если я еще раз застукаю вас, лишу своего доверия. +-Дети мои, что происходит? +- Вы же видите. +- Я застукал их вместе. +- Я ничего не вижу. +Я собирался позавтракать у Клариссы. +Купил кое-что. +Прихожу, поднимаюсь: и никого, и ничего. +Она оставила мне мой портрет. +Все как у меня: купил драже, прихожу, поднимаюсь... +- Она не спала в своей кровати. +- Спала. +Она была с Трюбло. +Как омерзительно. +- Она была с Мурэ. +-Лежала в ночной рубашке. +- Стояла в ночной рубашке. +- Ничего - пустота, тишина, пустыня. +- Я вышиб дверь и набросился на него. +- Он вскочил с кровати. +- Я набросился на нее. +Она убежала. +- Ну вот. +- О ком вы говорите? +- О Берте и о Мурэ. +А я говорю вам о Клариссе. +Причем здесь Кларисса? +Я говорю о Фанни. +Фанни? +А причем тут Фанни? +Я говорю о Берте. +Я только что купил ей рояль. +А ведь ненавижу музыку. +Я никогда не приходил к ней с пустыми руками. +Всегда конфеты, деньги. +Хочешь свой портрет? +Вот тебе художник. +Точно как у моей жены. +Платье, драгоценности. +И это вытворяет двадцатилетняя девушка. +- Нет, простите, ей двадцать пять. +-Двадцать. +Может, вы лучше знаете? +Не сердитесь, но так говорить - дурной тон. +- Могу вам доказать. +- Кому, Клариссе? +Да причем тут Кларисса. +Фанни. +Я тоже говорил себе, что Валери уже не двадцать. +Вы закончили обсуждать свои дела? +А как я? +Я. +- Кто дерется на дуэли? +Вы или я? +- Ну да, он прав. +Август, друг мой, скажу вам одно - надо отомстить. +Слушай, я проголодался, пойдем, пообедаем? +И да здравствуют жены, господа. +Да здравствуют чужие жены и наши, которые, впрочем, чужие для других. +Мы не можем упрекнуть их в непостоянстве. +Ведь они становятся чьими-то любовницами. +И потом, верные жены -такое занудство. +Чтобы узнать это, надо быть женатым. +Разве нет? +Так о чем я говорил? +А ваша жена вам изменяла? +- Конечно. +- И что? +Отбил у нее всякую охоту. +Теперь десять раз подумает, прежде чем изменить. +Молодец, молодец. +За ваше здоровье, господа. +И за вашу смелость, Август. +Давайте поговорим о дуэли. +Завтра на рассвете? +- Если у меня не будет мигрени. +- Тогда перенесем на следующий день. +- Оскорбленный выбирает оружие. +- Но пощечину дали Октаву. +-Значит, оскорбленный он. +- Точно. +-А вы хотели дать ему пощечину. +- Во всяком случае, хотел. +Значит, оружие выбирает он. +Равенство - прежде всего. +Простите, но ведь я же... +- В общем... +- Рогоносец. +А это оскорбление. +Кто согласен со мной, господа, пусть поднимет руки. +Один, два, три. +Четыре. +Единогласно. +Итак. +Мечи, шпаги? +Минуточку, вы торопите события. +Вы послали секундантов к Трюбло? +Это другое дело. +Фанни еще ребенок, она не понимала, что делала. +-А вы разобрались с Клариссой? +- Но я не женат на Клариссе. +Если я убью Октава, то буду мучиться угрызениями совести. +Я католик. +Наполеон венчался в церкви, а потом всю жизнь воевал. +Но не за Жозефину. +Признаюсь, Октав не прав, но именно он спас меня от разорения. +Это логично. +А если я его не убью и не буду с ним драться, то мы останемся в ссоре. +- Не совсем. +-А магазин? +- Что магазин? +- Я не смогу оставить Октава. +Ему придется искать другое место. +Из-за недостойного поведения жены, я должен буду уступить натиску конкурентов. +- Это аргумент. +- Ну да, мы сразу разоримся, сразу. +Господа, это все меняет. +Дуэль будет безумием. +Более того, глупостью. +Я сам пойду к Октаву, я заставлю это животное извиниться. +Не будь я Башляр. +Уверяю, он извинится как миленький. +И так мы избежим скандала. +Но будет справедливо, что честь Августа не будет поругана. +А также и честь его супруги. +Славно мы придумали, господа. +Башляр угощает вас шампанским. +Сомелье. +Была бы здесь Фанни. +Нет, нет, я не буду секундантом у того, кто предал мое доверие. +Не будем преувеличивать. +Я архитектор этого дома и отвечаю не только за стены, но и за жильцов. +Отвечаю за ваше поведение. +Я художник, но тем не менее. +Когда я приютил вас здесь, разве не предостерегал вас, разве не просил, не приводить сюда женщин? +Я не приводил сюда женщин. +Здесь их много, и все красивые. +О, прошу вас. +- Я многое могу понять. +-Да, ведь вы художник. +Многое, кроме адюльтера. +-Адюльтера? +- Я его не одобряю. +- Он вне ваших принципов? +- Вне моей морали. +- И разума? +- Вполне возможно. +Вы шутите? +Нет, вы меня разыгрываете. +- Я вас не понимаю. +- Компардон, вы не изменяете жене? +Или малышка Гаспарина это нюанс. +Между нами говоря, Гаспарина... +Говорите тише, жена спит. +- Гаспарина не замужем. +-А вы? +Да будет вам. +Я не кручу роман с соседкой. +Нет, все в этом обвиняют жен. +- Месье Башляр спрашивает месье Мурэ. +- Пусть входит, пусть входит. +Входите, Башляр, входите. +Тихо, мадам Компардон спит. +Извините меня, хочу поговорить с месье Октавом Мурэ. +Вы тут не лишний, друг мой. +- Останьтесь, здесь вы у себя дома. +-Да будет так. +Дорогой мой, я все уладил. +Это было трудно, но мне удалось. +Ну так вот, дуэли не будет. +Вы довольны? +-Дуэли не будет? +- Нет. +Неужели хотите испортить карьеру этой скандальной дуэлью? +Давайте все забудем. +Вы просто извинитесь перед Августом, и все будет в порядке. +Все будет в порядке? +Где? +Здесь, повсюду, в другом месте, где пожелаете. +- И мое положение не изменится? +- Но мы же все забудем. +Забудем все и начнем все с начала. +Все, все, все, все. +Август хочет избежать пересудов. +Он выше сплетен, он ведь молодожен. +- И я извинюсь. +- Ну да. +- Перед кем? +- Перед Августом. +Выразите ему свое сожаление. +Вы знаете, как это делается. +Что? +Выражать сожаление, что сделал Берту счастливой? +Это же подлая трагедия. +Она такое очаровательное создание, она мне так нравится. +Нет, никаких сожалений. +А если Берта лично потребует от вас выразить сожаление? +Это будет принуждением. +Я этого не потерплю. +Хорошо. +А если вы и Август извинитесь друг перед другом? +Друг перед другом? +Вы за то, что соблазнили его жену. +А он за то, что дал вам пощечину. +- Но он не давал мне пощечину. +- Но намеревался - это одно и то же. +К несчастью, этого намерения у него не было. +- Тогда на что вы жалуетесь? +- Я? +Ни на что. +Я жду его секундантов. +А если он их не пришлет, вы станете посмешищем. +Я ему отомщу. +Между нами, откровенно, что вы намерены делать? +Раз Август даровал мне милость и решил со мной не драться, я решил покинуть этот дом и поселиться в другом месте. +А магазин? +Сердечные дела - одно, а коммерция - совсем другое. +Вы не можете уйти из магазина. +Неужели вы думаете, что я буду работать на Августа? +Нет, не хочу быть посмешищем. +-А Берта? +-Да. +Берта? +Что будет с Бертой, если она вас больше не увидит? +Хотите ее наказать? +Без ложной скромности скажу, что Берта решила обойтись без меня. +Неблагодарный. +Не настаивайте. +- Это ваше последнее слово? +- Самое последнее. +Я передам ваш ответ. +Какой ответ? +- Что вы отсюда съезжаете. +- Ну да. +Спасибо, что были свидетелем этого трудного разговора. +Большое спасибо, дорогой мой, за понимание. +Лиза. +Вы выпьете немного кокилы. +Принесите бутылку кокилы. +- Нет-нет. +-Да-да. +Я настаиваю. +-До свидания, мадам Эдуан. +-До свидания. +-До свидания. +-До свидания. +-До свидания, мадам Эдуан. +- Мадемуазель Гаспарина. +Раз вы увидите месье Мурэ, попросите его срочно зайти. +Я не уйду из магазина, пока он не придет. +Хорошо, мадам. +Передайте ему, передайте, что речь идет о важном, срочном деле. +Хорошо, мадам. +До свидания, мадам. +- Среди честных людей... +- Среди сердечных людей... +- Всегда найдешь родственную душу. +- И поле битвы. +Какой остроумный! +-Здравствуйте, господа. +-Здравствуйте, Гаспарина. +Месье Мурэ, мадам Эдуан хочет срочно поговорить с вами в магазине. +- Мадам Эдуан? +-Да. +Похоже, дело срочное. +Извините меня. +Мое почтение, мадам. +- Вы хотели со мной поговорить? +-Да. +Я... +Я в курсе вашей ссоры с месье Вабром. +Знаю, что он послал вам секундантов. +Вам нельзя драться. +- Но он же мой противник. +- Я не хочу, чтобы вы дрались. +А вам-то что? +А если он вас убьет? +Ведь он такой неловкий. +Дуэль предполагает риск. +Впрочем, рискуют оба. +Кто сказал, что месье Вабр будет победителем? +Увы, в этом я не сомневаюсь. +Однажды я от вас ушел, и вы смирились. +Три месяца назад я для вас умер. +Если я умру по-настоящему, какая разница. +Я без сожаления уйду из этого мира. +У меня нет угрызений совести. +Месье Октав, вы должны знать правду. +В этой истории виновата я. +Это я, да, я пробудила подозрение у месье Вабра. +Я ничего конкретного не сказала, просто повела себя не лучшим образом. +Не знаю, что на меня нашло, но ваше поведение разозлило меня. +- Мое поведение? +- Ну да. +То, что вы стали доверенным лицом господина Вабра. +Я вообразила, что все ваши усилия направлены против меня. +Ваш отказ вернуться поверг меня в отчаяние. +Так все дело в магазине. +Не знаю, все так запуталось. +И вы испугались угрызений совести, что я погибну из-за вас. +Успокойтесь, этого не будет. +У вас не будет угрызений совести. +Вы были правы, меня интересуют только деньги и ничего более. +Вы донесли на меня. +Отлично. +Я за это заплачу. +Вы легко перенесете мою смерть. +О, нет, лучше я брошусь в ноги месье Вабру. +Это будет забавно. +Прощайте, мадам. +Октав! +Нет. +Дело не в магазине. +Простите меня, Октав. +Хорошо, дуэль отменяется. +Но это последняя жертва, на которую я иду, мадам Мурэ. +- Ну что? +- Еще одна большая пушка. +- Избавьтесь от нее. +- Оставить французам? +- Я сказал: избавьтесь. +- Есть. +Месье? +Майор, вы сделали невозможное. +Каким образом семитонная пушка проскочила у вас между пальцев? +Они ее уничтожили. +По-моему, она слишком большая. +Ваше мнение меня не интересует. +Пушка нужна генералу Жувэ. +Выполняйте приказ, а не думайте. +- Есть. +- Видаль. +За пушкой охотятся англичане. +Они отправили в Испанию шпиона. +Не оплошайте. +Иначе генерал отправит нас обоих служить на конюшни. +Да, месье. +Выходите. +- Англичанин? +- Англичанин. +Проводите меня в штаб. +Англичанин. +Мне нужна ставка генерала Ларены. +- Они переехали? +- Отступили. +Куда? +- А вы кто? +- Испанцы, которые не отступили. +Герьерос. +Если у вас дело, говорите со мной. +У меня письмо генералу Ларене. +Простите. +Хуана. +Прочти это. +Это Энтони Трамбел, морской офицер. +Генерал Ларена должен передать ему большую пушку... и людей для того, чтобы доставить ее в Сантандер. +Зачем? +Чтобы она не досталась Наполеону. +- Англичане тоже с ним воюют. +- Зачем прислали моряка? +Я говорю по-испански и изучал артиллерию. +Пушки. +Хотите ее видеть? +Конечно, хочу. +Спасибо. +- У англичан такая есть? +- Такой нет ни у кого. +- Она сломана? +- Можно починить. +- Вы бы смогли? +- Если будут люди. +Они есть. +Кузнецы? +Плотники? +Гильермо. +Франсиско. +Пепе. +Слушайте капитана. +Нужны шесть толстых бревен. +И снимите с пушки колеса. +Карлос, займись. +Пусть все тянут канаты. +Канатов как можно больше. +- Что-нибудь еще? +- Пока всё. +Да, капитан. +Пошевеливайтесь. +Не тяните вниз. +Нет, нет, левее. +Мигель. +Мигель. +- Французская кавалерия. +- Далеко? +- На той стороне. +- Через час будут здесь. +Оставьте пушку. +Так ее проще будет спрятать. +Хосе, сюда. +Живей. +Рамон, собери людей, чтобы рубить деревья. +Помогите им. +Карлос, поднимайтесь. +Закрепите канаты. +Впрягите мулов. +Проверьте надежность узлов. +Я нашел лучший путь в Сантандер. +Да, капитан. +Но пушка поедет в Авилу. +- Прошу прощения? +- В Авилу. +- Но вы сказали... +- Что я сказал? +Вы видели приказ. +Генерал Ларена передаст пушку нам. +Генерала Ларены здесь нет. +Вам не пересечь Испанию, ведь вас всего двести. +- За пушкой пойдет подкрепление. +- У вас нет пороха. +- Я его достану. +- С Наполеоном сражается весь мир. +На этом фоне Авила - песчинка. +Весь мир меня не интересует. +Авила - штаб французов в Испании. +До нее тысяча километров. +Местность кишит французами. +- Вы не доберетесь. +- Доберемся. +В Авиле есть стена, которую пробьет эта пушка. +Мы войдем в город любой ценой. +Даже если мы погибнем, Авила будет взята, и французы поймут, что пора оставить Испанию. +Вы все безумцы. +Капитан, вам нужна пушка в Сантандере, а мне - в Авиле. +Поедем с нами. +Научите нас с нею управляться. +А потом мы переправим ее в Сантандер. +Где гарантия, что так и будет? +Ее нет. +- Коня капитану. +- Я пойду рядом с пушкой. +Вы устанете, капитан. +Коня. +Капитан, у вас лицо в грязи. +Хуанита. +Давай, Хуанита. +Уже поздно. +Что ты делаешь? +Отнесу англичанину еду. +Он не ел с остальными. +Значит, он не хочет. +Мы ели. +Он такой же, как мы. +- Он не такой. +- Почему? +Он разбирается в пушках. +И нужен тебе. +Ты сам так сказал. +Я так не говорил. +Он мне не нравится. +Мигель, ты ревнуешь. +- Не к нему. +- Ты ревнуешь ко всем, а к нему особенно, потому что он умеет стрелять. +- Может, я тоже умею. +- Не умеешь. +Не говори того, о чем будешь жалеть. +Он нам нужен. +Признай это. +Тогда пусть на тебя не смотрит. +Мигель. +И ты тоже на него не смотри. +Это мое право. +Вы хорошо знаете этого Мигеля. +Знаете, что у него пушка. +Скажите мне, где он. +Я говорю как противник, но могу стать вашим палачом. +Прекрасно. +Значит, нужен пример. +Я повешу десятерых из вас. +На следующий день будет еще десять, и еще. +До последней женщины и ребенка в Авиле, пока кто-нибудь не заговорит и не укажет, где эта пушка. +Увести. +Выполняйте приказ. +Я сомневаюсь, что все эти повешения... +Знаю, знаю. +Вы считаете, что они бесполезны. +Велика ли эта пушка? +В два раза больше, чем вы можете представить. +Оккупированный народ выглядит мучеником. +Но когда у него появляется цель, он превращается в новую армию. +Вот чем опасна пушка, генерал. +Я не глуп, Сэрмен. +И мы ее найдем. +Надо постараться построить плот за три дня. +Понадобится сотня бревен. +Пушку закрепим на этой платформе. +- Так пересечем реку. +- Пушка затонет. +Нет. +Да и другого выхода нет. +Только ждать, пока русло высохнет. +Я хочу доставить пушку в Авилу, а это риск. +Главное, чтобы работали все. +Нам нужна сотня бревен. +Ладно. +Собери людей, пусть рубят деревья. +Действуйте, капитан. +Но если пушка утонет... +- Мне надоели ваши угрозы. +- Мне это не нравится. +- В любом случае, риска нет. +- Вашего слова не достаточно. +- Тогда позовите людей назад. +- Ладно. +Подождите. +Я скажу. +Мы знаем причину этого глупого спора. +Если надо переправляться, не тратьте понапрасну время. +Отпускайте плавно. +Тяните, тяните. +Хватайте другой трос. +Ну вот. +Всё жерло в грязи. +Лучше бы я этого не видел. +- Ее можно вытащить? +- Как? +Чем? +- Есть люди, мулы. +- Им ее не сдвинуть. +- Сколько потребуется народу? +- Тысяча или две. +В Альгадо жителей больше, Мигель. +Жители Альгадо, я плюю вам в лицо. +Я, Мигель, иду с пушкой на Авилу. +В Авиле никто не сидит на трибунах с французами. +И не поднимает наш флаг рядом с флагом врага. +Нет. +Подождите. +Что вы за люди? +Сидите, радуетесь жизни. +В двухстах милях отсюда враг забавляется тем, что насаживает испанских детей на штыки. +Может, у вас нет сердца? +И нет стыда? +По ту сторону реки в грязи застряла пушка. +Нам нужна помощь. +Я не прошу вас умереть. +Или пролить кровь. +Лишь попотеть немного. +Скажете детям, что в потоке сопротивления есть и ваш пот. +Те из вас, кто остался испанцем, идите за мной. +У вас лицо в грязи. +Вам нельзя рисковать. +Придется. +Их больше, они хорошо вооружены. +- Обходить будем три недели. +- Пусть будет три. +Капитан, в Авиле - командующий наполеоновской армии. +Генерал Анри Жувэ. +У него красивая форма. +Вино ему доставляют из Франции, а женщин - из Марокко. +Каждое утро, чтобы сломить сопротивление, он вешает десять испанцев. +За три недели он повесит двести десять человек. +Вы рискнете ради них пушкой и успехом дела? +А сколько народу он повесит, если вы не доберетесь до Авилы? +Нас ждут тысячи людей. +Я не могу медлить. +Я вам не помощник. +Если нас разобьют, вы сами потащите пушку в Сантандер. +Герцог Веллингтон. +Капитан, есть люди, которых не изменить. +- Например, Мигель. +- В этом наша беда. +- Значит, вы нас бросаете? +- Я не хочу идти на самоубийство. +Послушайте. +Конечно, с Мигелем трудно. +Он упрям. +Упрям - это мягко сказано. +Но никто не знает Мигеля лучше меня. +Вы привыкли вести себя, как на своем корабле. +Мигель на кораблях не ходил. +И воевать умеет, как Герьерос. +- Вы его поддерживаете? +- Как и все. +Но если он ошибается, мы всё равно с ним. +Надеюсь, вы тоже. +Почему? +Капитан, думаю, вы считаете себя мужчиной, а не свиным окороком. +Так. +Мы готовы. +Ты останешься с Марией и с ним. +Мне нужно пять человек. +- Зачем? +- Чтобы украсть порох. +Дай ему людей. +Герьерос! +Герьерос. +Откатите бочки с порохом в сторону. +Живее. +Живее. +Вперед. +Сейчас взорвется, прыгайте. +Я не офицер штаба. +У меня нет информации. +Он полевой офицер, он не в курсе дел штаба. +Пусть попробует вспомнить. +Попробуйте вспомнить. +Мне нечего сказать. +Я готов. +Скажите им то, что они хотят знать. +И останетесь жить. +- Что вы сказали? +- Не хочу, чтобы его убили. +Убеждаю заговорить. +Говорите. +Клянусь, у нас нет сведений из Авилы. +У меня семья, я не хочу умирать. +Он клянется, что сведений об Авиле нет, и не хочет умирать. +Они лгали. +Не пытайтесь умыть руки. +Эта кровь не смывается. +- И что? +- Я не буду молча смотреть на это. +Можете не смотреть, капитан. +Вы много вмешиваетесь. +- Если бы не пушка... +- То что? +- Я бы с вами не связывался. +- Идите, вы нам не нужны. +- Я выполняю свой долг. +- У меня тоже долг. +Не вмешивайтесь, или следующим убьют вас. +Вы безумец. +В порту Лас Крусес стоит британский корабль. +Идите туда. +Хорошо. +Сегодня же. +Лучше прямо сейчас. +Вы довольны? +Англичане не получат пушку, он не умеет стрелять. +Авиле конец. +- Он стоит на своем. +- Безумец. +Я буду с ним. +Но вам меня не понять. +Это не мое дело. +Вам этого не понять. +Генерал Жувэ приговорил к повешению моих отца и брата. +Я ему понравилась. +Я пришла к нему. +Но он всё равно их повесил. +Я молилась со всеми, чтобы тоже умереть. +Мне незачем было жить дальше. +Пока не появился сын сапожника. +Он показал, для чего нам жить, бороться. +Это был Мигель. +Вы отблагодарили его сполна. +- Я остаюсь с ним. +- Вы с ним живете, но не любите. +Потому эта связь сомнительна. +Британский капитан и участница сопротивления... +- тоже не пара. +- Я готов рискнуть. +И подготовите пушку? +Он сказал, что сам справится. +Мигель не всегда говорит то, что думает. +Я не буду перед ним извиняться. +Этого не нужно. +Я сделала это за вас. +Сколько картона может съесть человек? +Три дня - вода и вот это. +Чтобы тянуть пушку, нам нужны силы. +Ты еще не мужчина. +Он тебе предан, а ты смеешься над ним. +Хосе, они просто шутят. +Я ничуть не хуже их. +И ты это знаешь. +Ты лучше. +Ты молод, смел, силен и красив. +Мечта любой женщины. +Ты также умен и... +Хватит, Хуана. +Довольно. +Я не сержусь. +Пожалуйста. +Умоляю вас. +Прошу. +Пожалуйста. +В деревне есть дети. +Отдайте еду. +Мы умрем. +Хотя бы хлеб. +Хоть что-нибудь. +Мигель, коньяк. +- Что такое? +- Вы сами слышали. +Ну и что? +- Нам ведь нужна еда. +- Поддержка крестьян важнее. +- Что вы знаете о крестьянах? +- Наверное, почти ничего. +Тысячи крестьян встретят вас в Авиле. +Что вы им скажете? +Я найду, что сказать. +Я устал от ваших советов. +Во всех деревнях будут прятать еду. +И никто больше не захочет нам помогать. +Уступаю вам право командовать. +Договоритесь с крестьянами. +Можете расплатиться с ними. +В фунтах стерлингов. +Объясните ему, что он не прав. +Я живу с крестьянами. +И меня не надо учить общаться с ними. +- Нет, конечно. +- По-твоему, он прав? +- Я думаю... +- Для женщины ты много думаешь. +По мне, так ты прав, Мигель. +Мигель, извинись перед ним за свои слова. +Хосе. +Нос утри. +Целый лагерь смели. +Хорошенькое дело. +Непобедимая французская армия бежит в горящих подштанниках. +А они скрылись. +Это их земля, генерал. +Они знают, когда нападать и где прятаться. +Они и сейчас прячутся. +Они снова выступят. +Я догадываюсь, где. +- Им помогают. +- Крестьяне. +Не только. +С ними британский морской офицер. +Военный корабль англичан стоит в Лас Крусесе. +Здесь. +Прекрасно. +Прекрасно. +Организовать на всех дорогах в Лас Крусес постоянный дозор. +Проверим вашу догадку. +Карлос. +Карлос. +Телеги. +Где телеги? +- Где телеги? +- Я не знаю. +Понятия не имею. +Я отправил их назад в деревню. +В деревню? +Мигель. +- Карлос его убьет. +- Он просто немного позабавится. +Карлос, хватит. +Рана не опасна. +Через несколько дней... +Я не перестану помнить, что убил этого человека. +Мигель не предполагал, что всё так выйдет. +Конечно. +Это была забава. +Мне жаль. +Правда. +Не надо. +Это вовсе не связано с телегами. +Он ревнует, и не напрасно. +Я сказал тебе, что доставлю пушку в Авилу. +И я это сделаю любой ценой. +Но не ради него и не ради долга. +Я знаю причину, ты тоже. +Мы видели пехоту. +На той стороне реки. +Нельзя, чтобы нас засекли на равнине. +Ничего. +Пересечь Кано трудно. +- Там есть мост. +- Моста нет. +Я же знаю. +Французы построили там мост. +На лодках. +- Сколько там лодок? +- Пятнадцать, шестнадцать... +Мне нужно больше пятисот фунтов пороха. +Вам нужно? +Ладно, давайте порох. +Энтони. +Возьми Хосе. +Он работал в шахте и применял порох. +Возьми. +Я скажу Мигелю. +Сколько тебе лет? +Все думают - двадцать. +Вообще-то, восемнадцать. +Боишься? +Нет. +Я - да. +Знаете, зачем Хуана меня отправила? +- Помогать. +- Да. +А еще вы ей нравитесь. +Я солгал. +Мне страшно. +Но ничего. +Я справлюсь. +Что ж, пора окунуться. +Стойте. +Я тебя искал. +Хотел сказать, что мне жаль Хосе. +Ты не виноват. +Хуана. +Всю жизнь я боялась, ведь ничто не вечно. +Сейчас тоже боюсь, что это всего лишь сон. +Нет. +Обещаю. +При других обстоятельствах ты бы на меня не взглянул. +Хочешь, чтобы я сказал? +Я... +Нет. +Просто всё было бы совсем иначе в Англии. +Я запер бы тебя в башне, поставив верных стражей, и хранил бы ключ. +Золотой. +Тебе не хватило бы жалования. +Когда я стану адмиралом, у нас будет карета. +И мы будем танцевать на королевских балах. +Мне понадобится новое платье. +Да. +И голубой шарф под цвет моей формы. +Кланяться я буду осторожно. +Штаны сидят слишком плотно - однажды порвались. +Энтони. +Да? +- С кем ты был? +- Когда? +Когда штаны порвались. +Король захочет с тобой познакомиться. +Расскажешь ему, как однажды в далекой Испании встретила английского капитана... и сделала его самым счастливым человеком. +Я люблю тебя, Энтони. +Хуана. +Да? +Мы все испанцы и знаем, чего хотим. +Нам известна цена похода на Авилу. +Я понимаю, Мигель. +Но ты хочешь знать, что будет после Авилы. +Да. +Этого я не скажу. +Но мы долго были вместе. +Ты жила со мной, хотя я не умею ни читать, ни писать. +Когда я не мог подобрать слова, ты делала это за меня, Хуана. +Я чувствовал себя настоящим мужчиной. +Но в глубине души я знал, что я никто. +Думаешь, я не способен чувствовать, чего хочет женщина? +Я могу отблагодарить тебя, только лишь вернув Авилу. +Если этого мало, скажи. +Попытка разыскать горстку повстанцев... останется в военной истории как пример беспомощности. +Ваша карьера поставлена под вопрос из-за этого марш-броска с пушкой. +Мы успели потерять мост и немало людей, прежде чем поняли, что пушка здесь. +Далеко от Лас Крусеса и от моря, полковник. +Да, месье. +В этих горах есть ущелье. +Вот оно. +Именно там я их встречу. +Не думаю, что им удастся уйти. +Ну? +Там французские пушки. +Это же все знают. +- Я тоже знаю. +- Как ты хочешь там пройти? +- Есть другой путь? +- Мы обещали помочь, но не ценой жизни. +Ты попадешь под перекрестный огонь. +Нас не услышат. +Постараемся, чтобы колеса не скрипели. +Думаете, французы глухие? +Если преодолеть незаметно хоть полпути, у нас есть шанс. +Так что не надо изображать упрямых ослов. +Мы оставили наши лавки и фермы. +Что течет в ваших жилах? +Что угодно, но не кровь. +Нам нужно на юг, чтобы попасть в Авилу. +А значит, нужно пройти здесь. +Это ясно? +Да, капитан. +Яснее некуда. +Нам немного стыдно, но у нас у всех жены и дети. +Мы не готовы умереть за эту пушку. +- Нам нужна помощь. +- Обойдемся без них. +Удивительное умение убеждать. +- Я должен встать на колени? +- Если это поможет - да. +- Они нам нужны. +- Обойдемся. +Полсотни греков защищали ущелье от тысячи солдат. +У нас всё наоборот. +Я не изучал историю, но знаю точно: +я буду стоять перед статуей Святой Терезы в Авиле. +Прекратить огонь. +Они вне зоны огня, но дороги перекрыты. +Смирно! +Их нет ни у входа, ни в самом ущелье. +Оставайтесь на позиции и ждите моего приказа. +Бревно сюда. +Тащите. +Хорошо вы знаете холмы. +Здесь не спуститься. +- Спустимся, как поднялись. +- Пушку потянет вниз. +Ускорение и масса взаимосвязаны. +При весе в пять тонн на спуске... ее масса достигнет десяти-пятнадцати тонн. +Ее будет не удержать. +Она всегда весит одинаково. +Поворачивай мулов. +Продолжайте. +Живее, живее. +Бревно сюда, бревно. +Капитан. +Бревно, скорей. +Отходите. +Освободите мулов. +Прыгай. +Крепление пушки сломано. +Вверх идти нельзя, надо спускаться. +Блестяще. +Спускаться было труднее. +Неподалеку есть городок Манесирас. +Манесирас. +Манесирас. +Предлагаю пойти туда и починить там пушку. +Нам нужны инструменты, кузница и укрытие от французов. +Мигель, вдруг там французы? +Он что, пойдет в форме? +Нет. +Что вы предлагаете? +Выбирайте. +Придется попросить вас. +Испанские блохи. +Они не кусают англичан. +- Это можно разрешить. +- Есть еще одно. +- Что? +- Пушка. +Сын мой, сила дома Господня велика. +Но пушка не читает молитвы. +Мы хотим спрятать ее внутри собора. +А завтра... +- Внутри собора? +- На одну ночь. +Идет страстная неделя. +Вы оскорбите святилище. +Солдатам и пушкам место за дверью. +Это дом Господа, но не арсенал. +Ты много просишь. +Ваше Преосвященство. +Вы не можете отказать. +Не могу? +Ни к чему прикрываться ответственностью и правилами. +Мало сказать, что пушке в соборе не место. +Это не просто пушка, а символ сопротивления Испании. +Знаете, сколько людей отдали свои жизни, чтобы она попала сюда? +Вы не видели горных троп, покрытых мертвыми телами. +Ради чего? +Вы можете не знать ответа, но вы испанец, священник, и должны это чувствовать. +Вы не можете отказать. +Хорошо. +Сегодня вечером будет служба. +Тогда и внесете пушку. +Святая Дева, ты услышала мои молитвы. +Он всё понял. +И я люблю его еще больше. +В твоих глазах я грешница. +Но я впервые с детства осмелилась мечтать. +Но есть еще Мигель. +И его мечта +- Авила - которую я навсегда разделяю. +Слишком дерзко просить, чтобы ты помогла обоим. +Но выслушай. +И пусть твое сердце простит мой выбор. +Это за Мигеля и Авилу. +А это за любовь, обретенную с другим. +Внутри собора? +Да. +Пушка там. +- Да ты пьян. +- Точно. +Я ее видел. +Ладно. +Проверим. +Итак, гости, наконец, прибыли. +Их больше, чем я думал. +В самом деле. +Они смогут пробить стены? +Да. +Если сами не взорвутся. +Сколько, по-вашему, там человек? +Около десяти тысяч. +И подходят еще. +Опасно для кавалерии. +Что-то тучи стали сгущаться. +Испанцы ждут момента истины. +Они готовы умереть и окропить землю своей кровью. +Зачем? +Потому что это их земля, генерал. +Итак, как вы себе это представляете? +Ждете чуда? +Чудес не бывает. +Есть только пушка. +Скажите им правду. +Утром мы выстрелим по стенам с расстояния в полтора километра. +Вес ядра - сорок четыре килограмма. +В момент удара его масса составит четыре тонны. +Этого хватит, чтобы пробить стену. +Как насчет французских пушек? +Они стреляют не дальше, чем на один километр. +Зато потом начнется. +Я насчитал восемьдесят пушек. +Как только вы подойдете, они начнут стрельбу. +Заряды будут взрываться, на вас посыплются ядра. +В полукилометре полетит картечь - металлический град. +Затем стрельбу откроет пехота. +На подходе к стенам вы потеряете половину бойцов. +Вы это понимаете? +Понимаем, Мигель. +Этим людям знакома смерть. +Спокойной ночи. +Спокойной ночи. +Это правда - то, что я им сказал. +Да. +Хуана, останься со мной возле пушки. +- Другие не смогут этого сделать. +- Я знаю. +Но если ты меня любишь, обещай. +Я люблю тебя, Энтони. +Обещай. +Обещаю. +Надо бы сказать Мигелю. +Нет надобности. +Он поймет. +Сейчас здесь так тихо. +Да. +Все люди собрались и ждут. +Спасибо, что ты им помог. +Поэтому ты пришла? +Мне страшно. +Я боюсь за них и за нас. +Стены так далеко. +Нам с тобой нечего бояться. +Это меня и мучает. +Они такие же, как и мы. +Они хотят жить, хотят любить, а завтра могут погибнуть. +Этого не изменишь. +Энтони, я не могу сдержать свое слово. +- Ты пойдешь с ними? +- Да. +- Нет, я тебе запрещаю. +- Энтони, я молилась, чтобы остаться с тобой. +Я хочу этого. +Останься. +Не ходи с ними. +Что может одна девушка среди десяти тысяч мужчин? +Ты сумел дать мне многое, но этого недостаточно. +Я испанка. +Авила в моем сердце. +Но ведь я тоже. +До конца жизни. +Но видит бог, любимый, я должна идти с Мигелем. +Хуана. +Обними меня. +Скажи, что ты меня понимаешь. +Что любишь. +Я не думал, что ты придешь. +Я пришла, Мигель. +Мне... мне жаль, что я не говорил, что ты для меня значишь. +Прости. +Артиллеристы медлят. +Поторопите их. +Отходим. +Выстроиться на площади. +Назад. +Генерал. +- Выстроиться на площади. +- Но, генерал... +Быстро. +Хуана. +Прости, Энтони. +Я просила слишком много. +Не надо... +Хотела, чтобы Мигель попал в Авилу. +И хотела любить тебя. +О чём я печалюсь, о чём я грущу, о том лишь гитаре открою. +Девчонку без адреса всюду ищу - и днём, и вечерней порою. +Быть может, она далеко-далеко, быть может, совсем она близко. +Найти человека в Москве нелегко, когда неизвестна прописка. +- Раз, два, три, четыре пять... +- Бабушка, что же ты меня считаешь, я же не чемодан! +Чистое наказание, Господи! +- Товарищ начальник, скажите пожалуйста, где останавливается десятый вагон? +- Десятый вагон, бабуся? +- Вот, конец платформы бачите? +- Вижу. +- Так це он там. +Будку бачите? +- Вижу. +- То тоже не там, вот дальше будки будет десятый вагон. +- Торопитесь, бабуся, поезд стоит одну минуту. +- Батюшки, дак как же я-то успею? +Ведь там так высоко, пока вскарабкаюсь, а у меня столько вещей! +- Бабушка, я вам помогу. +- Спасибо, милая! +- А вы-то чего стоите? +- Чистое наказание! +- Платформу построить не можете, так хоть помогите! +- Це не наши заботы. +- Как это не ваши заботы? +Берите-ка! +- Так что же это? +- Пошли! +- Почему это у вас такие платформы короткие? +Это неправильно +- Це не от нас зависит. +- А от кого же? +- От управления дороги. +- Мы цей вопрос уже не раз ставили. +- Бабушка, я хочу. +Ну вот, что ты ещё надумал? +Не вовремя! +Ох, чистое наказание! +Ну, садитесь, бабуся. +Так. +Поехали. +Большое вам спасибо, только нужно не вопросы ставить, а платформы! +- Значит так, 66 на 23 в вашу пользу. +- Бабушка, если нужно будет, я помогу вам. +- Здравствуйте. +- Здравствуйте. +- Где тут 14-е место? +- Здесь, здесь, пожалуйте. +- О, сейчас девушка с нами сыграет в подкидного! +- А я не играю. +- А на балалайке вы играете? +- Нет, не играю. +Напрасно. +Ну, тогда на гитаре сыграйте, для первого знакомства. +- А мы с вами не знакомы! +- Всё равно ж познакомимся. +- Вряд ли. +- Всё, кончилась наша тихая мужская жизнь. +Кончилась! +- Может, хватит? +- Согласен, перерыв. 66 раз проиграли. +- Но, говорят, кому в карты не везёт, тому в любви везёт. +- Не всегда. +- Поднимите-ка ноги. +- Вот это вы напрасно, придёт проводник и всё уберёт. +- А вам перед проводником не стыдно? +- Конечно, стыдно. +- Это вам нужно? +- Пустые нам не нужны. +- С перчиком девица! +- Язва! +- Молодой человек, это вагон для некурящих. +- Между прочим, это вагон для курящих. +Но если вам не нравится, мы можем выйти. +- Скажите пожалуйста, вы везде порядки наводите или только на транспорте? +- А вы только на транспорте... +- ...нарушаете или везде? +- Везде. +- Оно и видно! +Пойдём, покурим. +Какой-то документ. +Справка. +Дана Екатерине Ивановне Ивановой в том, что она работала в артеле "Восход" и уволена по собственному желанию в связи с неуживчивостью характера. +Пред. правления. +Клячкин. +Здесь билет, деньги. +- Так это нашей соседки. +- Ну, что вы! +- Точно! +Сразу видно, что неуживчивый характер. +- Позвольте. +Гражданочка, это вы сейчас сели? +Ваш билетик. +- Отдайте, отдайте! +- Тсс. +Я просто не знаю, куда он делся! +Мне что, штраф придётся платить, да? +Правило гласит - за потерю билета отвечает потерявший, тире потерявшая. +А, значит, вы тоже нарушаете порядки на транспорте! +Послушайте, оставьте меня, наконец, в покое! +А штраф большой? +- Не беспокойтесь, не придётся вам штраф платить, вот ваши документы. +- А зачем вы взяли чужой билет? +! +Не кричите на меня, я у вас его не брал! +А нашёл в коридоре на полу! +- Вместо того, чтоб спасибо сказать, кричат ещё! +- Большое спасибо! +- А сердце у вас, наверное, в пятки ушло? +- Ещё бы! +- А вы куда едете, в Москву? +- Угу, в Москву. +- Да, ладно уж, курите. +- Да ладно уж, не буду. +- А за что же вас всё-таки уволили? +- Да так, в связи с неуживчивостью характера. +- Это вот этот, Клячкин? +- Угу. +- А кто он такой? +- Жулик. +- Как жулик? +- Ну так, вообще-то, он председатель артели. +Я его критиковать стала, а он меня взял и уволил. +- Ну, а в Москву к кому, к отцу едете? +- Нет. +- К матери? +- Не-а. +- К мужу? +- Нет, к деду. +У меня никого нет, кроме него, а тут ещё и уволили! +- А дед-то у вас хоть работает? +- Угу, не хочет на пенсию уходить. +В райсовете работает. +- В райсовете, значит, начальство? +- Да. +- Чем же он у вас заведует? +- Дверями. +- Как дверями? +- А так, вахтёр он, сторож. +- А-а-а. +А в Москве что собираетесь делать, работать? +- Ага, и учиться. +- У меня на Москву большие надежды. +- Артисткой, поди, собираетесь стать, да? +Как это вы догадались? +- Да, все девушки мечтают стать актрисами. +- А... хорошо бы стать артисткой! +- Вот к нам оперетта приезжала, так я все постановки пересмотрела. +- А вы сами поёте? +- Немножечко. +- Спойте что-нибудь, а! +- Ну, что вы, уже все спят! +А вы тихо, сейчас. +- Да нет, нет. +- Тихонько. +- Ну, ладно. +- А про что вам спеть? +- Ну, про любовь. +Про любовь? +Я вот тут недавно песню слышала, она не совсем про любовь, но всё-таки. +С малых лет мы рядом жили, по одним дорожкам шли. +С малых лет мы с ним дружили, с малых лет мы с ним дружили и учились, и росли. +А теперь со мною встречи он боится, как огня, ходит мимо каждый вечер, еле смотрит на меня. +Объясните, если можно, почему он стал такой. +Мне и грустно, и тревожно, мне и грустно, и тревожно. +Потеряла я покой. +На меня он смотрит строго и никак я не пойму, чем же этот недотрога, чем же этот недотрога дорог сердцу моему. +А недавно долетело до меня на стороне, что он тоже то и дело речь заводит обо мне. +На душе моей тревожно, я не знаю, как мне быть. +Совершенно невозможно, совершенно невозможно без него на свете жить. +И всё. +- Хорошо! +- Правда, вам понравилась? +- Правда! +- А вы работаете или учитесь? +- Я дома строю. +- А... +- Давайте познакомимся по-настоящему. +Зовут меня Павел, а попросту, Паша. +- Катя. +- Катя Иванова с неуживчивым характером, всё знаю. +- Ну, спойте ещё что-нибудь. +- Ну что вы, уже пора спать. +Спокойной ночи, Паша. +Спокойной ночи, Катя! +К третьей платформе прибывает поезд номер 43-й Сочи +- Москва. +- Кать, а можно я вас провожу? +- Что вы, я сама дойду. +- Всего хорошего! +- Счастливо! +- До свидания! +- А вы можете заблудиться в Москве. +- А я не заблужусь. +- Но мне в ту же сторону. +- В какую? +- Ну, туда, куда и вам. +- В какую? +Вы же моего адреса не знаете! +- Так вот я его и узнаю. +- Катя, подождите меня! +- Я жду, жду. +Что вы наделали! +Всю мою диету рассыпали! +- Гражданка, разрешите пожалуйста пройти! +- Обождите, молодой человек. +Мы ещё не кончили сбор фруктов. +- Катя, обождите, сейчас я. +- Да вы что, с ума сошли? +Что Вы делаете? +Катя, вы идите, а я сейчас, с другой стороны. +- О, Катерина! +- Ой, дедушка! +- Выровнялась-то как! +Невеста! +Здравствуйте! +Второй день к этому поезду выхожу, как письмо получил! +- Это что же, всё твоё приданое? +- Всё. +- Ну, пошли. +- Подождите, дедушка, попозже пойдём, а то затолкают! +- Пошли, мы сами всех затолкаем! +- Дедушка, подожди, у меня туфель расстегнулся. +- Ну вот, нашла место! +- Всё? +На. +- У меня ещё правый. +- Уж не провожатого ли ты какого ждёшь? +- Что вы, дедушка! +- Пошли. +- Здорова, Павел, вылезай давай! +- Кошара, моя крошка! +- Давай чемодан. +- Спасибо, дорогой, спасибо! +Минуточку, здесь меня один товарищ ждёт. +- Какой товарищ? +Сейчас, обождите. +- Паш! +Паша! +- Да обожди, сейчас. +- Пашка, Паша! +- Ну, братцы! +- Кать! +- Паша! +- Катя, адрес, адрес скажи! +Никола... +- Паша, Паш! +- Уехал товарищ, до свидания. +- Хороший товарищ! +Слушай, какие улицы в Москве начинаются с Никола, а? +- Никола дураковский. +- Николозапьянцовский. +- Николачертовский. +Да я серьёзно спрашиваю! +Ну, вот и приехали. +Место моей работы. +Районной Советской власти. +А в этом доме я живу. +Пойдём! +Вон, в 41-ой квартире. +Дедушка, я же не виновата, я просто стерпеть не могла. +А вообще-то меня по собственному желанию уволили. +- Варенье бери. +- Угу. +- Должен тебе сказать, как человек с опытом, как выходец из прошлого века, что на людей бросаться зазря не нужно. +И иногда характер свой попридержать полезно. +Дедушка, а я зазря на людей никогда не бросаюсь, я просто не люблю, когда они не правильно поступают. +- Да когда ты знаешь, правильно или не правильно? +- Это же ясно, дедушка. +- Как ясно? +- Вот, правильно - это по-советски, а не правильно - это не по-советски. +В этом же каждый ребёнок разберётся! +А я уже семь классов кончила! +Да так-то оно так, Катерина, но ты всё-таки этого не очень чтоб.. +по молодости лет и ошибиться можешь. +Хорошо, что у тебя дед жив, человек с положением, а не будь меня, пропадёшь! +- Это вам, дедушка. +- Спасибо! +Что же касается твоего трудоустройства, то с Семён Петровичем поговорить надо. +Наш домоуправ. +Подумаем, куда шагнуть. +Это тоже... выбрать надо. +Если улицы Москвы вытянуть в одну, то по ней пройдёте вы через всю страну. +Если лестницы Москвы все сложить в одну, то по ней взберётесь вы прямо на луну. +Вот она какая, большая-пребольшая, приветлива со всеми, во всех сердцах жива. +Любимая, родная красавица-Москва! +Заблудиться можно в ней ровно в пять минут, но она полна друзей и тебя найдут, приласкают, ободрят, скажут."'Не робей"! +Звёзды красивые горят по ночам над ней. +Вот она какая, большая-пребольшая, приветлива со всеми, во всех сердцах жива. +Любимая, родная красавица-Москва! +Днём и ночью, как прибой, всё кипит вокруг, но когда-нибудь с тобой встречусь я, мой друг! +Я одна теперь пою, а тогда вдвоём эту песенку мою мы с тобой споём! +Вот она какая, большая-пребольшая, приветлива со всеми, во всех сердцах жива. +Любимая, родная красавица-Москва! +- Ничего, получается! +- Ой, дедушка, это вы? +- Ты что, в постановках играла? +- В самодеятельной художественности? +- Угу. +- Ну и что, как голос? +- Есть, нет, что говорят? +- Да я не знаю, мне почётную грамоту однажды присудили. +Так у меня знакомый есть по этой части, человек искусства, в театре работает, оперетты! +- Оперетты? +! +- Да. +Гардеробщиком. +Большой знаток, я его попрошу. +Пусть он проверит, что у тебя там, талант.. +или, может быть, просто так. +Почётная грамота. +- Ну, а в справочной что тебе сказали? +- Слушай, запутался я совсем. +- Чего? +Ты понимаешь, на одну Москву приходится две Никола улицы, десять Никол-переулков и два Никол-тупика. +Если только улицы не брать в расчёт, то получается 12-ть Никол-переулков. +В каждом переулке приблизительно по двадцать домов. +- Помножь двенадцать на двадцать, получается 240 домов. +- Это вот это, да? +А 4800, что это такое? +А это, в каждом доме приблизительно по 20 квартир. +- Ага. +- Значит, 20 помножить на 240, получается 4800 квартир, как одна копеечка. +- Это тебе все придётся обойти? +- Ну, а что делать? +- Сколько ж тебе время на это надо? +- Если я в день буду проходить по 30 квартир. +- Конечно, сто ему не обойти. +- Конечно. +Получается, 4800 делим на 30- 160 дней. +- Это полгода. +Это не считая улиц, а если с улицами, то вообще астрономия! +Знаешь, Паша, ты возьми отпуск на месяц. +А потом месяца два у тебя больничный будет. +- А зачем больничный? +- Ты же без выходных работать будешь, устанешь. +- Паш, а ты помнишь на каком автобусе она с вокзала уехала? +- Что ты, в этой суматохе я и не разобрал. +- Вот или четвёртый, или четырнадцатый. +- Слушай, Паш мы завтра узнаем, в районе каких Никол проходит 4-ый и 14-ый. +И для начала прочешем эти районы. +Клавочка, Клав! +Ну, ты что, заснула что ли? +Давай-ка панель сюда! +- Пашенька, я тебе сейчас стихотворенье Степана Щипачёва прочитаю. +- Чего-чего? +Любовь пронёс я через все разлуки И счастлив тем, что от тебя вдали... +Клава, мне панель нужна, а не Степан Щипачёв. +- Слышишь, ну, что с тобой? +- Павлушенька, это моё сердце бьётся! +- Слышишь? +- Не слышу, давай-ка панель, Клава. +Тимофей Тимофеевич, сейчас мы исполним арию графини из оперетты "Мальчик- гусар". +Катерина... +Я в жизни, Арно, повидала немало. +Я много любила, я много страдала. +Ты мальчик, Арнольд, и тебе не понять, что значит, что значит любить и страдать! +- Графиня! +- Дитя, позабудь об несчастиой графине, с тобой я встречаться не стану отныне! +Усталое сердце давно без огня, всё в прошлом, Арнольд, у меня! +- Молю, останься! +- Арнольд, моему ты последуй совету, вели запрягать поскорее карету. +Расстаться, Арнольд, наступила пора. +Любовь, любовь - роковая игра! +Выйди-ка. +- Что скажешь, Тимофей Тимофеевич? +- Что сказать, хороша! +- Но, не подойдёт. +- То есть, как не подойдёт? +- Каскаду у неё не хватает. +- То есть таланту? +- Нет, талант, это талантом,а каскад - это талант с каскадом. +- А без каскаду нельзя? +- Нет, можно, но только в МХАТ или в Малый, а у нас такие только для статистики. +- Не понял. +- Ну, статистами. +- То есть, в представлении не применяются? +Нет, они представляют, вот, шум за сценой или графиню какую-нибудь безмолвную. +Но, а вот ежели талант с каскадом, ну, это тогда совсем другое дело, тогда уж тут шик и блеск! +- А Катерина-то... +- Артистка должна быть фигуристой, должна в глаза бросаться всем... антуражем. +Может, её всё-таки попробовать сунуть во МХАТ, там у меня приятель из нашей артели. +Ведь у нас, понимаешь, и пой, и пляши, и публику весели. +Одним словом, оперетта. +Знаю я одно прелестное местечко. +Знаю я одно прелестное... +Катерина. +Не берёт он тебя в актрисы-то, Катерина. +Говорит, не подходишь ты ему. +Не дуй губы-то, актриса. +Ай, да не бойся ты! +Устрою не хуже, лифтёршей будешь. +- Там каскаду не нужно. +- Не буду я лифтёршей. +- Знал бы, не звал тебя, старая вешалка! +- Ну, уж это, знаете... после таких слов, прошу больше не рассчитывать на контрамарки. +- Тьфу! +- Тьфу! +О чём я печалюсь, о чём я грущу, одной лишь гитаре открою. +Девчонку без адреса всюду ищу - и днём, и вечернею порою. +Быть может, она далеко-далеко, быть может, совсем она близко. +Найти человека в Москве нелегко, когда неизвестна прописка. +Ах, адресный стол, вы учёный народ, найдите её по приметам. +Глаза-словно звёзды и брови в разлёт, и носик курносый при этом. +В Москве, отвечает учёный народ, бессмысленны ваши запросы. +Сто тысяч девчонок, чьи брови в разлёт и полмиллиона курносых. +Со смены отправлюсь на поиски вновь, лишь вечер над городом ляжет. +Надеюсь я только, друзья, на любовь, она мне дорогу подскажет. +Ну так, давай теперь подытожим. +Значит так, в 41-ой квартире никого не оказалось. +- В 42-ой вообще не стали разговаривать. +- По шее дали. +- В 43-ей... +- В 44-ой, в 45-ой, в 46-ой.. +Джульетты твоей не было. +- Нет, Паша, так будем искать - ножки протянем. +- Ну, я ж тебя не заставляю, можешь не ходить. +- Да ты не сердись, ты вспомни, что она ещё о себе говорила, чтобы один ориентир настоящий был, кроме этого Николы, пропади он пропадом! +- Ну, что она говорила? +.. +Вот, знаешь, про деда она говорила. +- Ну? +- Дед у неё есть. +- Ну, ты представляешь, сколько в Москве дедов? +! +Начнёшь московских дедов делить, умножать, такая арифметика получится! +- Потом ёщё... да, про оперетту говорила. +- Ну? +- Вот любит она очень оперетту. +- А ты любишь? +- Люблю. +- Простите пожалуйста, вы любите оперетту? +- Не знаю. +- Любите, спасибо, все любят оперетту, я тоже люблю оперетту. +Какой это ориентир? +- Знаешь что, дед у неё работает... +- Ну, что тебе дался дед, дед! +- Нет, он работает... +- Будьте добры, дайте за 40 копеек. +- Он работает в рай... +- Спокойно, Главспирт? +- Нет, в рай... +- Здравотдел? +- Нет, нет.. +- В райсобес? +В райсовете вахтёром. +- Что ж ты раньше молчал? +Это же самое главное! +Товарищ старшина, скажите пожалуйста, сколько в Москве районов? +- Двадцать пять. +- Двадцать пять районов. +- Двадцать пять. +- Двадцать пять райсоветов, двадцать пять вахтёров, считай, что мы её нашли! +Пойдём. +- Пошли. +- Паш! +- А? +- Ну, куда ты пошёл? +- Куда, в райсовет. +- Какой же райсовет, когда рабочее время кончилось? +Да? +Знаешь что, давай сейчас зайдём в 41-ую квартиру. +- Паша, видишь двор? +- Вижу и что? +- Смотрят, ходят два здоровых парня по квартирам, чёрт-те что подумают, ещё в какую-нибудь историю влипнем! +- Пойдём сейчас домой, а завтра с утра по райсоветам. +Пойдём. +- Пойдём. +- У него вся соль в кнопке. +Нажал - поехал. +Дело простое. +- Я понимаю, Семён Петрович. +Начальство не надо перебивать. +Не надо! +Заходи. +К примеру, мне надо на пятый этаж. +Что я делаю? +Нажимаю пятую кнопку и еду. +Заело... заело с пятой, действуй по утверждённой мной инструкции. +Вот, висит в рамочке. +Бери седьмой этаж, потом на эту - стоп, потом обратно пятый. +Стоим, так? +Не едем. +На этот случай у меня всё предусмотрено. +Жми аварийную. +Ах, замыкание. +И на этот случай всё предусмотрено. +- Слушай, надо бежать за монтёром. +- Ух, а нельзя его проклятого, насовсем починить? +Конечно можно, но руки до всего не доходят. +А у меня их только две. +Понятно? +Я теперь в сторону культработы рокировался. +Организовал уголок тихих игр. +Шахматы, шашки, а то от ребячьего футбола, должен вам сказать... +А, лифт работает! +- Всё в порядке, лифт работает. +- Угу, спасибо! +Куда, куда, куда вы удалились? +Весны моей... +Эй! +Безобразие! +Выньте меня отсюда! +Сейчас же! +Не волнуйтесь, пожалуйста, седьмую нажмите, вторую и пятую. +Ничего не получается, жму - не идёт! +Тогда так - первую, аварийную, потом пятую. +- Ага, звонок работает, а лифт нет. +- Почитайте, там свежие газеты лежат, а я за монтёром сбегаю. +- Да я же на концерт опаздываю! +- А вы артист? +! +- Ха, ну да. +Тогда я для вас всё сделаю! +- Семён Петрович, я так больше не могу! +- Что за крик? +Понимаешь, куда ты ворвалась? +! +- У нас там человек, артист! +- Что человек-артист? +Я вот комбинацию обдумываю. +Артист в клетке, а вы тут комбинируете! +Перед людьми же совестно! +- В самом деле, Семён Петрович, лифт у нас давно в цейтноте! +- Правильно, надоело! +Не надо перегибать, товарищи, не надо, лифт, конечно, застревает иногда... но только на рекордно короткие сроки. +Сколько сидит сегодняшний? +- Двадцать минут сидит. +Ну, вот видал, всего двадцать минут, норма. +Ты, товарищ Иванова, рассуждай в своём пешечном масштабе,... +-...не строй из себя ферзя. +- А это... +- Ферзя. +- Из себя не строю, я только за дело болею, вот что. +- Тихо, спокойно, у нас комната для тихих игр, а не дискуссий, понятно? +Всё! +- Делаю ход конём на С-6. +А? +- Ну, я тоже сделаю ход конём! +- Что? +- Ты зачем на него жаловаться ходила? +- Я сначала его по-хорошему просила, почините машину, чуть не плакала! +- А он... +- Чуть не плакала! +У человека по твоей милости неприятности... +-...и на мне это отзывается! +- А это вы не правильно, дедушка, говорите. +- Как ты можешь? +! +- На родного деда критику наводить! +- А если вы неправильно говорите? +У нас такой большой замечательный дом! +А из-за такого вот Ферзя люди и страдают! +Застревают между этажами! +И какие люди! +Ох, люди страдают, а что я, не люди? +Ходил, старый дурак, в ножки кланялся, просил, московскую прописку тебе отхлопотали, а ты... отблагодарила! +Где ты ещё такую работу найдёшь? +- На улице она не валяется. +- А вы мне работу не ищите, я сама найду. +Сама, где ты её найдёшь? +Артистки из тебя не получилось, лифтёршей не вышло, ах, Катерина, не будет из тебя толку! +Уж если ты на шее сидишь, так хоть помалкивай! +- Ну, последний райсовет, последний вахтёр. +- Если уж и здесь нет... +Дорогой дедушка. +Вам сердиться вредно. +Вернусь, когда из меня выйдет толк. +Большое спасибо за всё, ваша внучка Катя. +- Здрасьте. +- Здрасьте. +- Поздновато. +Вы по какому делу в райсовет, молодые люди? +- Вы Иванов? +- Вы Иванов. +- Ну, Иванов. +- А скажите пожалуйста, у вас внучка... +- У вас есть внучка, Катя Иванова. +- А вы кто такие будете? +- Что вы про неё знаете? +- А он вместе с ней в поезде в Москву ехал. +- Да мы в одном купе вместе. +Так это из-за тебя у ней на вокзале всё время обувь-то расстёгивалась? +- Нету внучки. +- Как нету? +- Ушла. +- Куда? +- В неизвестном направлении. +Семилетки кончаете, а родному деду подобные коммунике пишите! +Чему вас учат? +Ушла! +- Дедушка, вы её, наверное, обидели, да? +- А что такое я ей сказал? +Ничего такого особенного я ей не говорил. +- Нет, ну разве можно? +Вы ведь ей дед! +- Так я ей родной дед, а не попутчик какой-нибудь. +Я имею полное право и поучать, когда требуется. +А она ушла! +Пропадёт теперь! +Характер-то какой! +Да и попутчики-то разные бывают, обидеть могут. +Да и движение какое! +Москва! +Ой! +Господи! +Боже мой! +Ну, нельзя же так пугать людей, милочка! +- И зачем только таким права дают! +- А вы на неё подайте в суд! +- Да при чём здесь суд? +- Товарищ начальник! +- В чём дело? +- Это не несчастный случай, а счастливая встреча, я встретила подругу детства! +То есть, племянницу подруги детства. +- И слегка затормозила, только и всего. +- Верно, милочка? +- Верно? +- Да. +- Можно ехать, товарищ милиционер? +- Пожалуйста, пожалуйста. +Пойдём, милочка! +Спасибо. +Дорогу! +- Ну, как вы себя чувствуете, милочка? +- Ничего, только вот у меня локоть что-то разбит и потом я испугалась,... +-...когда вы на меня наехали. +- Куда вас отвезти? +- Я не знаю. +- Вы, наверное, недавно в Москве? +- Угу, недавно. +Ну, оно и видно, вы совершенно не умеете переходить улицу. +Вы работаете? +- Да, то есть нет, сейчас не работаю. +- Имеете жилплощадь? +- Нет. +То есть, да, но сейчас не имею. +- А у вас действительно всё цело, милочка? +- Вообще-то всё, а что? +- Я вам помогу. +Сама судьба бросила вас под мои колёса. +- Ну, а дед что сказал? +- Да он сам ничего не знает. +- Да, он получил от неё открытку. +- Ну и что? +- Ничего, жива-здорова,... +-...а обратного адреса нет. +- Ну, и бесполезно её искать. +- Между прочим, есть ещё один вариант. +- Какой? +- В справочной мне сказали, что в Москве проживает 2137 Екатерин Ивановых. +- Ну и что? +Надо узнать их адреса и обойти всех. +- Чего смеёшься-то? +- Так, ничего. +До самой старости будешь искать. +Борода во, в руках палка. :"Дедушка, вам кого"? +-"А мне Катю Иванову". +"Бабушка, вас какой-то дедушка спрашивает." +Тебе смешно, а мне кажется, что я её всё равно найду! +Душа ни по ком до сих пор не страдала, но ты повстречалася мне. +Куда же ты скрылась, куда ты пропала, неужто приснилась во сне? +Куда же ты скрылась, куда ты пропала, неужто приснилась во сне? +По мне это, может, совсем незаметно, но я уж такой человек, +Что если дружу, то дружу беззаветно, а если люблю, то- навек! +- Ты знаешь, мне кажется, что она на Таганке живёт. +- Почему? +На открытке стоит штамп таганского почтового отделения. +Она может жить в Малаховке, а открытку бросила на Таганке. +- Нормальные люди где живут там и бросают. +- Так то нормальные. +Пускай ненароком исчезла ты где-то, имей, дорогая, в виду, +Что я за тобою пойду на край света, а надо - и дальше пойду. +Что я за тобою пойду на край света, а надо - и дальше пойду. +Завтра на Таганку пойдём, да? +Пойдём. +Катя, со стола можно убрать. +Масик, ты будешь болеть или пойдёшь на работу? +- Я, Кошенька, поболею немножко. +- Правильно, поболей, Масик, поболей. +Всё равно не оценят. +- Кусенька, а ты разве уезжаешь? +- У меня в одиннадцать психическая гимнастика, а потом массаж нижних конечностей и гомеопат. +Ах, Катя! +Оставьте вазу! +Это Богемское стекло! +Его нельзя трогать, на него можно только молиться! +Она становится невыносимой! +- Масик. +- Кусик. +- Масенька! +- Кусик! +- Ну что хочет Масик, чтобы Кусенька ему привезла? +- Масик хочет водочки. +- Водочки? +Успокойся, Масик. +Привезу, мой красавчик. +Привезу, привезу, мой ангел! +- Оставьте книги! +- Пыль же, Раиса Павловна. +Это не та пыль, с которой надо бороться, она неподвижная. +Масик, у меня к тебе большая просьба, присмотри за этой. +А что? +Она ничего. +И вообще... старательная. +- Масик! +- Кусенька... +- Опять? +- Кусик, ну, что ты? +- Что Кусик? +- Кусик... +- Ну, что Кусик? +Что такое домработница? +Домработница - это своего рода внутренний враг. +Маська, ну, Маська! +Масенька! +Обожаю! +Ух! +- Не так, Катя, не так! +- А как же, Раиса Павловна? +Надо любить свой труд! +Труд облагораживает человека! +Что такое домработница? +Домработница - это своего рода директор домашнего хозяйства. +Вы занимаете ответственный пост, Катя! +В общем, вот так. +Плохо у вас получается, Катя, плохо, плохо! +Я скоро вернусь, без меня ничего не делайте. +Только сходите за папиросами для Василия Никодимыча, постирайте занавески, вымойте пол в кухне, купите всё на обед, перетрясите коврики, почистите ножи и вилки, а потом, когда я вернусь, будете готовить обед под моим руководством. +- Доброе утро! +- Доброе утро.. уже? +Возможно. +Что, брат, достаётся, а? +Птичка божия не знает ни заботы, ни труда... +В домработиицы попала.. дя-дя-дя ту... +- Отстаньте, Василий Никодимович! +- А что мне будет, если я отстану? +- Ну, пустите же! +- А что мне будет, если я пущу? +- Пустите! +Усю-сю, тю-тю... +Это тряпка. +Это же негигиенично! +Цель сего тра-ля-ля-ля-ла. +Тра-ра-ры ля-ля-лам. +Нам завидует каждый прохожий... +ЗВОНОК ТЕЛЕФОНА +Алло. +Да, Камаринский. +Что? +Из госконтроля? +Уже еду, еду. +Скажешь Раисе Павловне, что меня срочно вызвали в контору. +Вахтёр Иванов слушает. +Алле.. алле.. алле! +Алле! +Я девчоночка жила, забот не знала, словно ласточка, свободною была. +На беду свою тебя я повстречала, позабыть, как ни старалась, не смогла. +Позабыть, как ни старалась, не сумела, завладел моей ты девичьей судьбой. +Уж давно весёлых песен я не пела. +Неужели мы не свидимся с тобой? +Ты ушёл и не воротишься обратно, одинокой навсегда останусь я. +Годы лучшие проходят безвозвратно и проходит с ними молодость моя! +Я, девчёночка, жила, забот не знала, словно ласточка, свободною была. +Повстречала я тебя и потеряла, потеряла в тот же час, когда нашла. +Ой! +А-а! +Ой! +Боже мой! +СТУК В ДВЕРЬ +Откройте! +Что тут у вас? +Картина ясная. +Кран забыла закрыть? +- Ну и влетит теперь тебе! +- Безобразие! +- Пропустите меня! +Боже мой! +Боже мой! +Сплошной кошмар! +- Что тут случилось? +- Я убиралась. +- Маленькое наводненьице, на два этажа. +- За ваш счёт, Картина ясная. +- Вы понимаете, что вы наделали? +Зачем вы полезли в ванну? +- А-я-я-я-я-яй! +- Ничего я не наделала, я убиралась и вдруг вода... +Боже, ну кто же, по-вашему, открыл кран? +Наверное, Василь Никодимыч, перед тем, как на работу идти. +Да какое право вы имеете обвинять ответственного работника Бог знает в чём! +Вы лжёте! +- Ой, какая дорогая вещь, боже мой! +- Я не лгу! +- Боже мой! +Боже мой, мой Секинский ковёр! +Ах, мы разорены! +Вы лжёте, лжёте! +Вы мне за всё ответите, за всё! +- Боже, что же творится, боже! +- Раиса Павловна, я кран не открывала! +А я это проверю и горе вам, если вы солгали! +Проверьте! +Алло. +Алло, алло... +- Алло. +- Масик, ты болвасик! +Ты забыл закрыть кран в ванной! +- Ну, как я мог? +- У нас в квартире наводнение! +- Кусик! +- Такое наводнение, по колено вода! +- Кусик, Кусик... я.. +- Ты забыл закрыть кран в ванной! +Ты понимаешь, что ты наделал? +! +Мы совершенно разорены, мы погибли! +Кусенька, дай ей... по собственному желанию и пускай идёт на все четыре стороны! +- Лгунья! +- Нет, я не лгунья, я правду сказала! +Ну, что вы стоите? +Ковёр спасайте! +Вы должны в ногах у меня валяться! +Прощения просить, а не оправдываться! +Если бы я тогда на вас не наехала, вы бы давно погибли, как швец под Полтавой! +- У, дерзкая девчонка! +- Вы, пожалуйста, не кричите на меня. +Я вам благодарна за то, что вы на меня наехали, но этот наезд я вам с лихвой отработала, а теперь я ухожу от вас, вот что! +И пусть всё это ваше богемское стекло кто-нибудь другой обслуживает! +- А с меня хватит! +- Прекрасно! +Собирайте вещи и убирайтесь по обоюдоострому желанию! +- Куда сейчас-то поедем? +- В Новоспасский тупик. +- Снова так, Новоспасский, Николоспасский... +Так доездимся, что... +- Садитесь, пожалуйста. +- Спасибо! +Граждане, берите билеты. +- Будьте добры, один до конца. +- Возьмите. +- Извините, пожалуйста, я забыла деньги, я сейчас сойду. +- Пожалуйста, я уже взял. +- Что вы, зачем? +Не нужно, я всё равно сойду! +- Но ведь я же заплатил. +- Хорошо, дайте ваш адрес, я вам перешлю деньги. +- Зачем же? +Вот мы сейчас остановимся, мы сойдём с вами вместе и вы отдадите мне долг. +- Пожалуйста. +- Ты куда? +- Не могу же я такие деньги на ветер бросать! +Набережная, следующая Новоспасский. +- Серьёзно, надолго? +- Боюсь, навсегда. +- Ну, привет. +- Скажите пожалуйста, Екатерина Иванова в этой квартире живёт? +- В этой. +- А её можно будет видеть? +- А почему бы и нет? +Вы, пожалуйста, проходите, только она сейчас на кухне. +Вы вот слушайте меня, вы идите по коридору. +Правда там темно, у нас лампочка перегорела, я как раз сейчас иду покупать, но вы не смущайтесь, +Вы идите, идите и идите, и свернёте налево, потом пройдёте прямо, потом опять налево, потом увидите дверь. +- Ясно. +- Нет, вы туда не входите, вы идите дальше. +Справа будет ещё одна дверь, +- Вы тоже туда не ходите. +- Так... +- И идите дальше и попадёте в такой маленький узенький тёмный коридорчик, по нему пойдёте прямо и упрётесь в дверь кухни. +- Так. +- И перед вами она. +- Она? +- Да. +- Понятно? +- Ну, я так и сделаю, спасибо большое! +Можно? +Ой! +Чёрт-те, понаставили чего-то! +Тьфу, чёрт! +- Скажите пожалуйста... +- А-а-а-а! +А-а-а-аа! +- Да чего вы кричите? +- А-а-а-а! +- Катя, Катечка, Катюша! +- Что? +- Ну, что там? +- Бандиты! +- Да вы что, с ума что ли сошли? +- Где? +- Ванной! +- Спасите! +- Да не может быть этого! +- Подождите, не отворять! +- Откройте! +- Слушайте, я никакой ни бандит! +- Звоните скорее в милицию. +- А может откроем и сами разберёмся? +- Конечно, сами разберёмся. +- Сами разберёмся. +- Ни в коем случае! +- Только через мой труп! +Там же бандиты! +- Я не бандит, откройте мне, я вам сейчас всё объясню. +Ай! +... +- Феактист Феактистович. +- Я здесь. +- Скорее узнайте, сколько их там. +Ну, вы же смелый мужчина! +А-а-а-а! +- Постерегите здесь, а мы пойдём вооружаться. +- Откройте! +Если бандиты взломают дверь, бросайтесь на них и кричите:"А-а-а-а!" +- Но, если я кинусь, то я потом не поднимусь. +- И как вам не стыдно, вы же мужчина! +- Но ведь он тоже мужчина, пусть он и кидается. +- Я не мужчина, а ответственный съёмщик! +Оставайтесь. +Остальные, за мной! +Слушайте, товарищ Феоктистович, если вы мне сейчас не откроете, я взломаю дверь! +Это квартира умалишённых! +- Да-да-да-да. +- Молодые люди, имейте в виду, у меня в руках горячее оружие! +- Ну, что? +- Откройте! +ЗВОНОК В ДВЕРЬ +- Товарищ милиционер. +- Здравствуйте. +Где бандиты? +- Здесь. +В ванной комнате. +- Я их вооружил. +- Вот! +- Тихо, граждане, тихо! +Их там много! +- Выходите по одному! +Все выходите! +- Все - это я один. +- Какой молоденький! +- Как вы сюда попали, гражданин? +- Я пришёл к Ивановой Екатерине Ивановне. +- Ах, к вам? +- Я так и думала! +- Да я первый раз его вижу! +- Вы к ней пришли? +- Да не к ней я приходил. +- Пройдёмте, гражданин. +Попрошу со мной. +Вы что, с ума сошли? +Я должен переодеться! +- Руки, руки пусть поднимет вверх! +- Я не виноват совсем! +- Гражданин, попрошу в машину. +- В какую машину, зачем в машину-то? +- В машину попрошу. +- Товарищ начальник, я вам объясню. +- Спокойно, гражданин, спокойно. +- Не поеду я никуда! +- Руки вверх! +- Товарищ лейтенант, адреса. +- Ну и что? +- Так, всё ясно, пройдёмте, гражданин! +- Да куда вы меня везёте? +- Подождите! +Подождите! +- Товарищ начальник. +- В чём дело, гражданочка? +- Сейчас одного человека на машине увезли. +- Да. +- За что? +Ну, мало ли, гражданочка, за что угодить можно! +Может он в квартиру залез. +А может, ещё что-нибудь похуже. +Да.. +тогда крепко могут дать! +- А куда его повезли? +- Ну, поначалу, надо полагать, в отделение. +А вы что, что он вам знакомый? +- Или может родственные отношения? +- Знакомый. +Да нет, комсомольская характеристика не нужна, дело ясное. +Тут пришли ваши ребята. +- Савельев? +- Я Савельев.И Дубонос. +Он +- Дубонос. +- Савельев и Дубонос. +Ручаются. +- Ручаемся, конечно. +- Да я тоже думаю, поверить можно. +Всего хорошего! +- Так вот, граждане, ошибочка произошла. +вы уж его извините, пожалуйста. +- Простите пожалуйста. +- Извините, пожалуйста. +- Извините, пожалуйста. +- Пожалуйста, пожалуйста,... +-...это так романтично! +- Если нужно, заходите ещё. +Будем рады! +- Нет уж, спасибо! +Тем не менее, бдительность остаётся бдительностью. +Бдительность тут, пожалуй, ни при чём. +В следующий раз, Гусаров, влюбляйтесь в девушек с точным адресом и с менее распространённой фамилией. +Ясно? +Вот так. +- Девушка, дождь идёт! +- Ну и пусть идёт. +- Ну как же пусть, вы бы домой шли,... +-...что ж так мокнуть? +- У меня нет дома. +- Как нет дома? +- А вот так вот. +Нету. +- Знаете что, пошли ко мне, я живу недалеко, за углом. +- Не пойду я никуда. +Ну, вот что, вошли, нечего. +Так можно простудиться, берите чемодан. +Скорей, скорей! +- Пей чай, кушай как следует, не стесняйся. +- Спасибо, я и так вторую чашку уже! +- Согрелась? +- Угу. +- Бери сыр, колбасу, ешь. +Нет, я не хочу больше, я наелась, спасибо! +- Катя. +- А. +- Ты у меня пока останешься. +Сестра приедет не скоро, за это время ты успеешь устроиться на работу. +На. +Большое спасибо! +- А что же дедушка, так о тебе ничего и не знает? +- Нет. +Всё-таки дед... дедушка... я бы на твоём месте ему позвонила. +Я иногда ему звоню, только не отвечаю. +Если на работе, значит, здоров, а потом вешаю трубку. +Я сама такая, никогда не начну первая, если меня обидят. +Самое обидное, что он правду сказал, что я из себя представляю? +Ровным счётом ничего! +Чего я добилась? +Ну, ничего, утро вечера мудренее. +Самое главное - тебе надо устроиться на работу. +Значит, и я тоже виноват, раз ты могла такое подумать! +Спасибо. +- Но, о любви я никогда тебе ничего не говорил. +- О любви не говорят, о ней всё сказано. +- Это только в песне поётся. +- В кино ходили? +Два раза! +- Ну и что? +- На танцы приглашал. +- Ну, приглашал. +- И целовались! +- Когда? +- Как когда? +- Ну, один раз. +- Три! +- Да неужели это имеет какое-нибудь значение, Клавочка? +- Может все-таки любишь? +Неудобно, люди же ведь кругом смотрят, Клава! +Сердцу ведь не прикажешь. +Не плачь, Клавочка! +Девушка, посчитайте нам пожалуйста. +- А ту нашёл? +- Кого? +- Ту, с которой в поезде познакомились. +Нет. +Вахтёр Иванов слушает. +Алле, алле. +Катерина? +Это ты! +Брось баловаться, отвечай! +Молчишь, ну, молчи, молчи, а ко мне приходил попутчик твой. +- Видный такой парень, забыл, как его имя-то. +- А когда он приходил? +- Ой, дедушка, здравствуйте, тут что-то с трубкой было! +- Давно уж. +Сразу, как ты сбежала. +- Ты когда домой вернёшься, Катерина? +- Дедушка, из меня ещё толку не вышло, как выйдет, сразу приду. +А я живу хорошо, работаю, здорова, Вы за меня не беспокойтесь. +Сейчас же, сию минуту ступай домой! +Непутёвая! +Ух, какую моду взяла, от родного деда бегать! +Катерина, ты слышишь меня? +Алле, алле, алле! +Я, признаться, проявил глупость бесконечную. +Всей душою полюбил куклу бессердечную. +Для неё любовь - забава, для меня - мучение. +Придавать не стоит, право, этому значения! +Не со мной ли при луне пылко целовалася? +А теперь она во мне разочаровалася. +Для неё любовь - забава, всё ей шуткой кажется, кто ей дал такое право, надо мной куражиться? +Позабыть смогла она всё, что мне обещано. +Вам, наверно, всем видна в бедном сердце трещина. +Для неё любовь - забава, для меня - страдание. +Ей - налево, мне - направо, ну, и до свидания! +- Ну, вот мы и пришли. +- А завтра, Оленька, пойдём в кино. +- Вдвоём? +- Вдвоём, я билеты взял на последний сеанс. +- Ой, ещё и на последний! +- А что? +- Нет-нет, я возьму подругу. +А вы возьмите какого-нибудь приятеля. +- Ну, Оленька, кино-то вдвоём интересней смотреть! +- Почему интересней? +Ну, почему-почему? +- За что это, Оля? +- Мы только второй раз с вами встречаемся, а вы безобразничаете! +- Не второй, третий! +- Это всё равно. +Вот вы, значит, какой? +! +- Нате ваши цветы! +- Оля, Оля, я не хотел вас обидеть, я думал, что это... +- Что вы думали? +Разве вас девушки никогда не били за такое хулиганство? +- Никогда, даже наоборот. +- Вы с плохими девушками встречались, до свидания! +- Оля! +Я вам даю честное слово, что этого никогда больше не повторится без вашего на то разрешения! +Оля, можно я возьму билеты на завтра, на четверых, на последний сеанс? +Можно? +- Оля! +- Можно. +Встретимся возле кино. +- Хорошо, я вас провожу, а то там темно на лестнице! +- Нет уж не нужно, я сама. +До свидания! +- До свидания! +- Катя, пойдём завтра с нами в кино, а? +- Что ты, я вам мешать только буду. +- Ну, что ты, мешать? +- Он с товарищем придёт, познакомишься. +- Не нужно мне никакого товарища. +- Катенька, ну, я прошу тебя, ради меня, пойдём. +- Не нужно, Оль, не нужно. +Ой, всё-таки странная ты. +Это Москва, пойми, ну, как ты своего Пашу найдёшь? +Ты даже фамилии его не знаешь. +- Ну, где ты? +- Прости, ну, как? +- Красив, только смотри,... +-...как бы она от тебя тоже не убежала. +- Ничего, моя не бегает. +- У неё несколько другая привычка. +Будьте добры, зефира коробочку. +- Мить. +- А? +- А может быть, я не пойду с тобой в кино? +- Подругу приведёт. +- Ну и что, ты понимаешь, я ещё два адреса достал. +- Первый раз в жизни я тебя попросил и ты не можешь! +- Да я могу, но... в нашем распоряжении... +-...ещё пятьдесят минут! +Давай зайдём по одному адресочку, а? +- Быстро? +- Быстро. +- Пойдём. +- Гражданин. +- О, спасибо большое! +- Что, Алёнушка, тебе купить? +- Яблочко? +- Угу. +Так, 75-я. +- Слушай, здесь открыто. +Пойдём. +- Пашка... вспомни ванную. +Ну, я теперь учёный, ничего не будет, идём. +Можно? +Можно? +А кто-нибудь здесь есть? +Люди добрые, отзовитесь. +Ой! +Ну, вот так вот. +Примерно этого я и ожидал! +Это, между прочим, хуже чем ванная. +Хозяин, хозяин, есть тут кто-нибудь? +Как он смотрит, видишь? +Мы опоздаем из-за этой чертовки! +Слушай, тихо, она, наверное, не любит, когда с ней громко разговаривают. +- Ну, давай тогда по-хорошему, вежливо. +Она ж учёная. +- Давай. +- Шарик, хи-хи, позвольте выйти. +- Лобзик, Шурик, Шурик! +- Хорошая собачка! +- Лаечка! +- Лаенька! +- Почему они не идут? +- Уже скоро начало! +- Он, наверное, забыл. +- Что ты, как он может забыть? +- Что же мы теперь делать-то будем? +- А что, если её зефиром подкупить? +- Да что ты? +Собаки взяток не берут. +- А мы сейчас попробуем. +Лобзик, Лобзик, на. +Ну, скушай, Лобзик. +Вот так. +- Клюёт. +- Ну, теперь иди. +- Нет. +Ты иди. +- Ты кормил, ты и иди. +- Пойдём тогда вместе. +Спокойно, спокойно... раз, два.. +Хозяин! +- Оля, бесполезно ждать, пошли домой! +- Нет уж, я останусь и я ему всё скажу! +Ну, как хочешь, а я пойду. +- Аппетит-то какой-то нечеловеческий. +- Конечно, нечеловеческий, собачий. +Что я Оле скажу? +Ведь не поверит. +- Слушай, Мить, у меня есть план. +Кидай ей последнюю зефирину. +- Ну? +Пока она будет кушать, я потушу свет и в темноте пробьёмся. +- Ха, это идея! +- Давай. +- Только спокойно, Паша. +- Лаечка. +- Только осторожно! +- Лаечка, Лаечка... +Лаечка, на... +Раз.. +- Ай, ай, люди! +Хозяева! +- Караул! +Ай! +- Оленька, я сейчас вам всё объясню! +- Я ждала вас только для того, чтобы сказать вам, чтобы вы не смели, и запомните это, не приходить ко мне, не писать и не звонить! +Забудьте моё имя и тот день, когда вы заплатили за меня рубль в троллейбусе! +Да выслушайте ж вы меня, Оля! +- Нет, нам необходимы молодые кадры и они у нас должны быть! +- Юрий Александрович,... +-...вы неисправимый фантазёр! +- Елизавета Тимофеевна, для художника необходима фантазия. +- Я член художественного совета. +Мне, например, фантазия абсолютно не нужна. +- Да.. +И потом, мы внедрители, мы должны внедрять, а не фантазировать. +Елизавета Тимофеевна, вы посмотрите, какая очаровательная девушка! +Я лично ничего очаровательного не нахожу. +- Девушка, вы с вашей внешностью могли бы найти занятие поинтереснее. +- Вы куда-то шли, гражданин, ну, и идите. +Нет, Боже сохрани, вы меня не так поняли! +Я действительно, хочу вам предложить увлекательную, интересную, серьёзную работу. +Демонстрируются вечерние туалеты, созданные художниками-модельерами нашего экспериментального ателье. +Елизавета Тимофеевна, что делать? +Люся заболела и я не могу демонстрировать свою модель! +- Что вам сказала эта симулянтка? +- Она сказала, что у неё высокая температура, 39,2. +У неё температура, а у нас художественный совет. +Иванова, встаньте сюда. +- Размер её. +- Демонстрировать платье будете вы. +Что вы, Елизавета Тимофеевна, я даже не знаю, как в таком ходить! +Советская девушка должна смело ходить в том, что мы внедряем! +Но, Елизавета Тимофеевна, мне же говорили, что я только рабочую одежду буду показывать! +Вы знаете, у меня от неё каждые пять минут ра-разрыв сердца делается! +- Прежде всего, вы не должны затруднять работу, вы хотите стать асфальтщицей? +- Нет, я не хочу, но... +- Ведите её в кабину. +- Пойдёмте, Катя, пойдёмте. +- Идите сюда, идите. +Елизавета Тимофеевна, ну, как? +- Вполне на уровне! +- Даже лучше, чем я ожидала. +- Лизавета Тимофевна, здесь такой вырез большой! +- Мне как-то неловко. +- Почему вы вы-высказываетесь? +Вы-вы же не член худсовета! +Идите немедленно! +- Там никого больше нет.. +- Не ваше дело! +Идите немедленно! +Уберите все ваши руки и не падайте с лестницы. +- Неужели он тебя выгнал? +- Не, не выгнал, кричал только. +Нет у меня внучки, если вы ещё раз придёте от её попутчика, это он про тебя, вызову милицию. +Сумасшедший какой-то. +Ира, наверно, вся в него. +- Слушай, Мить, вот эта девушка так похожа на Катю! +- Какая? +Вот эта, в белом. +Ну, докатились, видения начинаются! +Она так похожа, только ростом чуть-чуть выше. +Слушай, Пашка, я тебе как другу говорю, брось ты эти поиски, не бросишь, плохо кончишь! +Что она тебе далась, ну, ты посмотри, сколько девчат кругом! +А? +- Платье держите скорее! +- Стой! +- Остановитесь! +Понимаешь, я его увидела и побежала! +Удержаться не могла! +- А потом по собственному желанию. +- Что, неужели выгнали? +- Ну, что ж ты теперь будешь делать? +- Не знаю. +Уехать что ли? +Вот, уехать, новость какая! +А ты знаешь что? +Мне кажется, что я могу тебя устроить. +- Я завтра поговорю. +- Оленька, спасибо! +Опять ты меня выручаешь! +- Ну, как настроение? +- Хорошее. +- Смотри, чтобы всё было аккуратно. +- И потом, чай наливай пожиже, потому что заварки не хватит. +- Ладно. +- Попьют сотрудники в перерыв чай и снова за работу. +- Оленька,... +-...а что это вы всё пишете, считаете? +- Пишем разные бумаги, а считаем разные цифры. +- А зачем все эти бумаги? +- Смешная ты. +Над нашей конторой есть ещё одна контора, которая главнее нашей. +Ну и вот, эта контора присылает нам свои бумаги, мы их переписываем и посылаем в ту контору, которая ниже нашей. +Понимаешь? +Не понимаю. +Почему же контора, которая ниже нашей, не может сразу послать бумаги в контору, которая ниже нашей? +Вот странная, эта контора, которая ниже... +перерыв, чай неси! +Семён Семёнович, возьмите на меня чай, пожалуйста, я сейчас! +Иванова, начальник очень занят. +Вы поставьте стакан на стол и сейчас же по - тихонечку уходите. +Понимаете? +Понимаю. +Таким образом, в целом, своевременность... +написали? +- Написала. +- Своевременность, оборачиваемость поступающих директив, своевременна..и.. происходит точно в своё время. +- Иванова, Иванова, что с вами? +- Ничего. +- Возьмите пакет и поезжайте на стройку. +- На стройку? +- Послушайте, девушка, вы тут всех знаете? +- Всех и всё, а что? +- У вас тут один товарищ работает. +- А у нас не один товарищ работает, девушка. +- У нас сотни, а зачем он тебе? +- Так, не важно. +- Ты учти, мы своих на сторону не отдаём! +- Ты что, пакеты разносишь? +- Пакеты! +- Ну и волоки свой бюрократизм! +- Не прохлаждайся! +Кому пакеты? +- Прорабу. +Где он? +- Вон туда иди. +- Ой, постой! +- А-а-а-а! +- Ушиблась, дочка? +- Нет, ничего. +- Да как же это тебя так угораздило? +- А мне прораба нужно! +- Я прораб. +- Ой, вот, наконец-то! +А у меня для вас пакет. +Лично, срочно. +Срочно? +О, да я эти новости неделю назад знал. +Сидите там, директивы переписываете, а с арматурой опять подвели? +Давай, сердешная, книжку-то твою. +Распишусь. +И кому нужна только эта ваша контора? +Наша контора - это необходимое связующее звено в сложной цепи взаимоотношений между главком и строительными площадками. +Я закругляюсь, товарищи. +В своё время мы своевременно сигнализировали и я считаю своевременным... поставить вопрос о несвоевременности сжатия нашего аппарата. +Нас надо не сжимать, нас надо расширять! +Значит, вы не согласны, товарищ Камаринский, что ваша контора превратилась в лишнюю инстанцию? +- Категорически! +Категорически не согласен! +- Это как же вы говорите, Василий Никодимыч, не лишняя? +Нас на стройке только лишними и ругают, лишняя инстанция, лишняя контора, со стыда можно сгореть! +А вы знаете, сколько эта лишняя инстанция казённого чаю выпивает? +Рублей на 500 в месяц! +Ха-ха-ха, демагогия! +Это безответственное выступление. +Да. +- Оля! +- Здравтсвуйте, Митя! +- Вы меня извините, я в таком виде! +Наше-то учреждение закрыли. +- Здравствуйте, Оля. +- Здрасьте. +- Значит, вы теперь тоже рабочий класс? +- А я нечаянно на вашу стройку попала. +- Это же великолепно, что вы именно на нашу стройку попали! +- Хотите к нам в бригаду, подсобницей? +Могу похлопотать. +- Куда? +Монтажником, наверх. +Работа не трудная, инструмент принести, то да сё. +А красотища! +Стрижи летают, ласточки. +Будете у нас королевой воздуха! +- Скажите, Митя, а вы королём там будете? +- Да нет, заместителем. +Подожди, сейчас. +- А я эти дни только о вас и думаю. +- Всё время? +- Всё время. +- Пять раз в день мимо вашего дома хожу. +- Почему же вы не зашли? +А как же я зайду, если вы мне запретили заходить к вам, звонить и даже писать. +Мало ли чего я там наговорила? +А я боялся. +Да подожди ты, одну минуту постой! +- Это ещё что такое? +- Иван Романович, это... +-...шефство над новенькими. +- Ну, так будем шефствовать над девицами, Савельев, десять лет дом не построим! +- Виноват, Иван Романович! +- Ну-ка марш на место! +- Больше не буду! +Через пять минут с третьей платформы отправляется поезд номер 72 Москва +- Иркутск. +Вот твой вагон! +Ты, Катерина, не забывай, что у тебя дед существует, пока что. +- Дедушка, не беспокойтесь, я вам писать буду. +- Как приедешь на место назначения, сразу телеграмму дай. +С точным адресом, а то ведь опять пропадёшь! +На вот тебе, письма от тебя всё равно не дождёшься, а открыточку нацарапай, жива мол, здорова, того и вам желаю. +- Тут 50 штук, про запас. +- Катенька, милая, может быть всё-таки останешься, будем опять с тобой вместе работать? +- Нет, решила, так уж решила. +- А ты знаешь, что мне Митя сказал? +Они меня в бригаду возьмут, подсобницей, будете у нас королевой воздуха! +Нет, королева - это не профессия, ты лучше в штукатуры иди, штукатуры - это дело! +- Что это ты оглядываешься? +- Я попросила Митю сюда придти, а его всё нет. +Будет ему сегодня от меня! +Опоздаешь! +Ты уж, Катерина, этого.. я ж.. не того.. +яж для тебя от всей души. +- Да что вы, дедушка! +- Ладно уж! +- Про адрес-то не забудь, непутёвая! +- Не забуду, дедушка, вы себя-то берегите! +- Оленька, спасибо тебе за всё, за всё! +- Катенька, не забывай меня, пиши! +Ну вот, опоздали, "ещё по одному адресочку зайдём", ищет прошлогодний снег! +- В последний раз! +- Да, в последний раз! +- Митя, она! +- Кто? +- Да, Катя! +Катя! +Катенька! +Катя! +- Катя! +- Паша! +- Катя, а я вас по всей Москве искал! +- А я думала, вы меня забыли. +- Да что вы, я всю Москву перевернул, а вас нет и нет! +- Гражданин, сойдите с вагона! +- Проводник, одну минуточку! +- Гражданин, кому говорят, сойдите! +- Я вас очень прошу! +- Гражданин, не нарушайте! +- Вы понимаете, что я эту девушку люблю! +- Любить можно, а нарушать нельзя! +- Можно или нельзя, это пожалуйста, ты куда, Катенька? +- На работу. +- А как же я, Катенька, оставайся. +- Мне же ехать надо! +- Зачем? +- Ну, что же мне делать? +- Ну, Катя, мы вместе поедем. +- Ну, решайтесь, решайтесь, девушка, поезд идёт! +- Поезд и правда идёт, Катя, а? +Где твои вещи пойдём, пойдём, прыгнем, а? +- Катя, прыгай! +- Ой, я боюсь, ой! +- Отдай чемодан! +- Отдай чемодан-то! +Ой, Пашенька, не правильно я сделала, мне же ехать надо! +- Что, опоздали, молодые люди? +- Нет, не опоздали, наоборот, успели! +- Пойдём? +- Пойдём! +"О чем я печалюсь, О чем я грущу, +Одной лишь гитаре открою. +Девчонку без адреса всюду ищу +И днем, и вечерней порою. +Быть может, она далеко-далеко. +Быть может, совсем она близко. +Найти человека в Москве нелегко, +Когда неизвестна прописка". +- Раз, два, три, четыре, пять. +- Бабушка, что же ты меня считаешь? +Я же не чемодан. +- Чистое наказание, господи! +Товарищ начальник, где останавливается 10-й вагон? +- Вон конец платформы, бачите? +- Вижу. +- Так це не там. +Будку бачите? +- Вижу. +- Це тоже не там. +Вот дальше будки будэ 10-й вагон. +Торопитесь, бабуся, бо поезд стоит 1 минуту. +- Батюшки, да как же я там успею? +! +Там так высоко. +Как я там вскарабкаюсь, когда у меня столько вещей? +! +- Бабушка, я вам помогу! +- Спасибо, милая. +- А вы-то чего стоите? +- Чистое наказание! +- Платформу построить не можете, так хоть помогите. +- Це не наша забота. +- Как это не ваша забота? +! +Берите-ка! +Так, пошли! +Почему это у вас такие платформы короткие? +Это неверно! +- Це не от нас зависит. +- А от кого? +- От управления дороги. +Мы сей вопрос уже не раз ставили. +- Бабушка, хочу! +- Ну вот что еще надумал. +Чистое наказание! +- Садитесь, бабуся! +Так, поихалы. +- Большое вам спасибо. +Только вы не вопросы ставьте, а платформы. +- Значит так, 66 на 23 в вашу пользу. +- Бабушка, если что нужно будет, я помогу вам. +Здравствуйте. +- Здравствуйте. +- Где тут 14 место? +- Здесь, пожалуйте. +- Сейчас девушка с нами сыграет в подкидного. +Да? +- Я не играю. +- А на балалайке вы играете? +- Нет, не играю. +- Тогда на гитаре, для первого знакомства. +- А мы с вами не знакомы. +- Все равно познакомимся. +- Вряд ли. +- Все! +Кончилась наша тихая мужская жизнь. +- Может, хватит? +- Согласен. +Перерыв. 66 раз проиграли. +- Говорят, кому в карты не везет, тому в любви везет. +- Не всегда. +- Поднимите-ка ноги. +- Напрасно вы. +Придет проводник и все уберет. +- Вам перед проводником не стыдно? +- Стыдно. +- Это вам нужно? +- Пустые не нужны. +- С перчиком девица-то. +- Язва. +- Молодой человек, это вагон для некурящих. +- Это вагон для курящих. +Но если вам не нравится, мы можем выйти. +Скажите, вы везде наводите порядки или только на транспорте? +- А вы их только на транспорте нарушаете или везде? +- Везде. +- Оно и видно! +- Пойдем покурим. +- Документ. +"Справка. +Дана Екатерине Ивановне Ивановой в том, что она работала в артели "Восход" и уволена по собственному желанию в связи с неуживчивостью характера. +Пред. правления Клячкин". +Здесь билет, деньги. +Так это нашей соседки. +- Ну что вы? +- Точно. +Сразу видно, что неуживчивый характер. +- Позвольте. +Гражданочка, это вы сейчас сели? +Ваш билетик. +- Отдайте. +- Я просто не знаю, куда он делся. +Мне штраф придется платить? +- Правило гласит: "За потерю билета отвечает потерявший ". +- Вы тоже нарушаете порядки. +- Послушайте, оставьте меня в покое! +А штраф большой? +- Не беспокойтесь, не придется вам штраф платить. +Вот ваши документы. +- А зачем вы взяли чужой билет? +! +- Не кричите! +Я у вас их не брал, а нашел в коридоре, на полу. +Вместо того чтобы "спасибо" сказать, кричат. +- Большое спасибо. +- А сердце-то у вас, наверное, в пятки ушло. +Да? +- Еще бы! +- А вы куда едете? +В Москву? +- В Москву. +Да ладно уж, курите! +- Да ладно уж, не буду. +А за что же вас уволили? +- Да так, в связи с неуживчивостью характера. +- Клячкин? +- Угу. +- А кто он такой? +- Жулик. +- Как жулик? +- Он председатель артели. +Я его критиковать стала, а он меня уволил. +- А в Москву к отцу едете? +- Нет. +- К матери? +- Нет. +- К мужу? +- Нет, к деду. +У меня никого нет, кроме него. +А тут еще и уволили. +- А дед-то у вас работает? +- Угу. +Не хочет на пенсию уходить. +В райсовете работает. +- Значит, начальство? +- Да. +- Чем же он у вас заведует? +- Дверями. +- Как дверями? +- А так. +Вахтер он. +- А в Москве что собираетесь делать? +Работать? +- Ага. +И учиться. +У меня на Москву большие надежды. +- Артисткой собираетесь стать. +- Как вы догадались? +- Сейчас все девушки мечтают быть артистками. +- Хорошо бы стать артисткой. +Вот к нам оперетта приезжала, так я все постановки пересмотрела. +- А вы сами поете? +- Немножко. +- Спойте что-нибудь. +- Ну что вы! +Уже все спят. +- А вы тихо. +Сейчас. +- Нет-нет. +- Тихонько. +- Ладно. +А про что вам спеть? +- Про любовь. +- Про любовь? +Я тут недавно песню слышала, она не совсем про любовь, но все-таки. +С малых лет мы рядом жили, По одним дорожкам шли. +С малых лет мы с ним дружили, С малых лет мы с ним дружили, +И учились, и росли. +А теперь со мною встречи Он боится как огня. +Ходит мимо каждый вечер, Еле смотрит на меня. +Объясните, если можно, Почему он стал такой? +Мне и грустно, и тревожно, Мне и грустно, и тревожно. +Потеряла я покой. +На меня он смотрит строго, И никак я не пойму, +Чем же этот недотрога, Чем же этот недотрога +Дорог сердцу моему? +А недавно долетело До меня на стороне, +Что он тоже то и дело Речь заводит обо мне. +На душе моей тревожно, Я не знаю, как мне быть. +Совершенно невозможно, Совершенно невозможно +Без него на свете жить. +И все. +- Вы поете хорошо. +- Правда? +Вам понравилось? +- Правда. +- А вы работаете или учитесь? +- Я дома строю. +Давайте познакомимся по-настоящему. +Зовут меня Павел. +Попросту +- Паша. +- Катя. +- Катя Иванова с неуживчивым характером, все знаю. +Спойте еще что-нибудь. +- Что вы, уже пора спать. +Спокойной ночи, Паша. +- Спокойной ночи, Катя. +К 3-й платформе прибывает поезд 43 "Сочи-Москва". +- Катя, а можно я вас провожу? +- Что вы, я сама дойду. +- Всего хорошего. +- Счастливо. +- До свидания. +- А вы можете заблудиться в Москве. +- А я не заблужусь. +- Но мне в ту же сторону. +- В какую? +- Туда, куда и вам. +- В какую? +Вы же моего адреса не знаете. +- Вот я его и узнаю. +Катя! +Подождите меня. +Хорошо? +- Я жду. +- Что вы наделали? +! +Всю мою диету рассыпали. +- Гражданка, разрешите пройти. +- Подождите, молодой человек, мы еще не кончили сбор фруктов. +- Катя, обождите, сейчас я. +- Да вы что, с ума сошли? +! +- Катя, вы идите, я выйду с другой стороны. +- О, Катерина! +- Ой, дедушка! +- Выровнялась-то как! +Невеста. +- Здравствуйте. +- Второй день к этому поезду выхожу, как письмо получил. +Это что же, все твое приданое? +- Все. +- Ну пошли. +- Подождите, дедушка! +Народ схлынет, и пойдем, а то затолкают. +- Пошли, мы сами всех затолкаем. +- Дедушка, подожди. +У меня туфель расстегнулся. +- Ну вот, нашла место. +Все? +На. +- У меня еще правый. +- Уж не провожатого ты какого ждешь? +- Что вы, дедушка. +- Пошли. +- Вон Павел! +- Здорово, Павел! +Вылезай! +- Минуточку, здесь меня один товарищ ждет. +- Какой товарищ? +- Обождите. +- Паша! +Паша! +- Обожди, сейчас. +- Паша! +Куда ты? +- Катя! +- Паша! +- Катя! +Адрес! +Адрес скажи! +- Николо... +- Паша! +Уехал товарищ? +До свидания, хороший товарищ. +- Слушайте, какие улицы в Москве начинаются с Николо? +.. +- Николо-Дураковкий. +- Николо-Запьянцовский. +- Николо-Святовский. +- Я серьезно спрашиваю! +ВЕСЕЛАЯ МУЗЫКА +- Ну вот и приехали. +Место моей работы - районная советская власть. +А в этом доме я живу. +Пойдем. +Вон. +В 41-й квартире. +- Дедушка, я не виновата. +Я просто стерпеть не могла. +А ведь меня по собственному желанию уволили. +- Варенье бери. +Должен тебе сказать как человек с опытом, как выходец из прошлого века, что на людей бросаться зря не нужно. +И иногда характер свой попридержать полезно. +- Дедушка, а я зря на людей никогда не бросаюсь. +Я просто не люблю, когда они неправильно поступают. +- Как ты узнаешь, правильно или нет? +- Это же ясно, дедушка! +- Как? +- Правильно - это по-советски, а неправильно - это не по-советски. +Это каждый ребенок разберет, а я уже 7 классов кончила! +- Это так. +Но ты, Катерина, по молодости лет и ошибиться можешь. +Хорошо, что у тебя дед жив, человек с положением. +А не будь меня - пропадешь. +- Это вам, дедушка. +- Спасибо. +Что же касается твоего трудоустройства - с Семен Петровичем поговорить надо. +Наш домоуправ. +Подумаем, куда шагнуть, это тоже выбрать надо. +Если улицы Москвы вытянуть в одну, +То по ней пройдете вы через всю страну. +Если лестницы Москвы все сложить в одну, +То по ней взберетесь вы прямо на Луну. +Вот она какая - Большая-пребольшая, +Приветлива со всеми, Во всех сердцах жива +Любимая родная Красавица-Москва. +Заблудиться можно в ней ровно в пять минут. +Но она полна друзей - И тебя найдут. +Приласкают, ободрят, скажут: "Не робей". +Звезды красные горят по ночам над ней. +Вот она какая - Большая-пребольшая, +Приветлива со всеми, Во всех сердцах жива +Любимая родная Красавица-Москва. +Днем и ночью, как прибой, все кипит вокруг. +Но когда-нибудь с тобой встречусь я, мой друг. +Я одна теперь пою, а тогда вдвоем +Эту песенку мою мы с тобой споем. +Вот она какая - Большая-пребольшая, +Приветлива со всеми, Во всех сердцах жива +Любимая родная Красавица-Москва. +- Ничего получается. +- Ой, дедушка. +- Ты что, в постановках играла? +В самодеятельной художественности? +- Угу. +- Ну и как? +Голос есть, нет? +- Я не знаю. +Мне однажды почетную грамоту присудили. +- У меня знакомый есть по этой части, человек искусства. +В Театре оперетты работает. +- Оперетты? +- Да. +Гардеробщиком. +Большой знаток. +Я его попрошу проверить, что у тебя - талант или просто так, почетная грамота. +- А в справочной что тебе сказали? +- Запутался я совсем. +- Чего? +- На одну Москву приходится 2 Николо-улицы, 10 Николо-переулков и 2 Николо-тупика. +- Так. +- Если улицы не брать в счет, получается 12 переулков. +В каждом переулке по 20 домов. +Я помножил 12 на 20 и получил 240 домов. +- Вот это. +А 4800- что такое? +- А это - в каждом доме по 20 квартир. 20 помножить на 240- получается 4800 квартир. +- Это тебе все придется обойти? +- А что делать? +- Сколько же времени на это надо? +- Если я в день буду проходить по 30 квартир... +- Конечно, 100 ему не обойти. +- То получается 160 дней. +- Это полгода. +- Не считая улиц. +А если с улицами, то вообще астрономия. +- Знаешь, Паша, возьми отпуск на месяц, а потом месяца 2 у тебя бюллетень будет. +- А зачем бюллетень? +- Наверное, без выходных работать будешь, устанешь. +- Паша, а ты помнишь, на каком автобусе она с вокзала уехала? +- Что ты! +В этой суматохе я не разобрал. +То ли 4, то ли 14. +- Слушай, Паш, завтра узнаем, в районе каких Никол проходят 4-й и 14-й. +И для начала прочешем эти районы. +- Правильно. +Клавочка! +Клав, ты что, заснула? +Давай-ка панель сюда. +- Паша, я тебе сейчас стихотворение Степана Щипачева прочитаю. +Чего-чего? +- "Любовь пронес я через все разлуки И счастлив тем, что от тебя вдали". +- Клава, мне панель нужна, а не Степан Щипачев. +Слышишь? +Ну что с тобой? +- Павлушенька, это мое сердце бьется. +Слышишь? +- Не слышу. +Давай панель, Клава. +- Тимофей Тимофеевич, сейчас мы исполним арию графини из оперетты "Мальчик-гусар". +Катерина. +Я в жизни, Арнольд, Повидала немало. +Я много любила, Я много страдала. +Ты мальчик, Арнольд, И тебе не понять, +Что значит, что значит Любить и страдать. +- Графиня. +- Дитя, позабудь о несчастной графине. +С тобой я встречаться не стану отныне. +Усталое сердце давно без огня. +Все в прошлом, Арнольд, у меня. +- Молю, останься. +- Арнольд, моему ты последуй совету: +Вели запрягать поскорее карету. +Расстаться, Арнольд, наступила пора. +Любовь. +Любо-овь - +Рокова-а-ая игра! +- Выйди-ка. +Что скажешь, Тимофей Тимофеевич? +- Хороша. +Но не подойдет. +- То есть? +- Каскаду у нее не хватает. +- То есть таланту? +- Нет, талант талантом. +А каскад - это талант с каскадом. +- А без каскаду нельзя? +- Можно, но только во МХАТ или в Малый. +А у нас такие артисты только для статистики. +- Не понял. +- Статистами. +- В представлении не применяются? +- Они представляют шум за сценой или графиню безмолвную. +Но ежели талант с каскадом, то это другое дело. +- А Катерина-то? +- Артистка должна быть фигуристой, в глаза бросаться всем антуражем. +Может, ее попробовать сунуть во МХАТ? +Там у меня приятель из нашей артели. +Ведь у нас пой, пляши и публику весели. +Одно слово - оперетта. +Знаю я одно прелестное местечко. +- Знаю я одно прелестное... +Катерина! +Не берет он тебя в актрисы. +Говорит, не подходишь ты ему. +Не дуй губы-то, актриса! +Не бойся, устрою не хуже. +Лифтершей будешь. +Там каскаду не нужно! +- Не буду я лифтершей. +- Знал бы, не звал бы тебя, старая вешалка. +- Ну, знаете! +После таких слов прошу больше не рассчитывать на контрамарки! +Тьфу! +- Тьфу! +"О чем я печалюсь, О чем я грущу, +Одной лишь гитаре открою. +Девчонку без адреса всюду ищу +И днем, и вечерней порою. +Быть может, она далеко-далеко. +Быть может, совсем она близко. +Найти человека в Москве нелегко, +Когда неизвестна прописка. +Ах, адресный стол, Вы ученый народ, +Найдите ее по приметам. +Глаза словно звезды, и брови вразлет, +И носик курносый при этом. +"В Москве, - отвечает ученый народ, - +Бессмысленны ваши запросы. +100 тысяч девчонок, Чьи брови вразлет, +И полмиллиона курносых". +Со смены отправлюсь на поиски вновь, +Лишь вечер над городом ляжет. +Надеюсь я только, друзья, на любовь, +Она мне дорогу подскажет". +- Давай подытожим. +В 41-й квартире никого не оказалось, в 42-й вообще не стали разговаривать. +- По шее дали. +- В 43-ей... +- В 43,44,45 Джульетты твоей не было. +Нет, Паша, так будем искать - ножки протянем. +- Я тебя не заставляю, можешь не ходить. +- Ты не сердись. +Вспомни, что она еще говорила. +Чтобы один ориентир настоящий был, кроме этого Николы. +- Про деда она говорила. +- Ну? +- Дед у нее есть. +- Ты представляешь, сколько в Москве дедов? +Начнешь дедов умножать-делить - такая арифметика получится. +- Да, про оперетту она говорила. +Любит она оперетту. +- А ты любишь оперетту? +- Люблю. +- Простите, вы любите оперетту? +- Не знаю. +- Любите, спасибо. +Все любят, я тоже. +- Знаешь, дед у нее работает... +- Что тебе дался дед? +- Он работает в рай... +- Спокойно. +Главспирт? +- Нет. +Рай... +- Здравотдел. +- Нет. +- Райсобес. +- В райсовете вахтером. +- Что ж ты раньше молчал? +Это самое главное. +Товарищ старшина, сколько в Москве районов? +-25. +-25 районов - 25 райсоветов - 25 вахтеров. +Считай, что мы ее нашли! +Пойдем. +- Пошли. +- Паша! +- А! +- Куда ты пошел? +- В райсовет. +- Рабочее время кончилось. +- Да? +Знаешь, давай зайдем в 41-ю квартиру... +- Паша, видишь дворника? +- Ну и что? +- Он смотрит, ходят два здоровых парня по квартирам, черт-те что подумает. +Пойдем сейчас домой, а завтра с утра по райсоветам. +- Ну пойдем. +- У него вся соль в кнопке. +Нажал и поехал. +Дело простое. +- Я понимаю, Семен Семеныч. +- Начальство не надо перебивать. +Заходи. +Гляди сюда. +Мне надо на 5-й этаж. +Что я делаю? +Нажимаю 5-ю кнопку и еду. +Заело. +Заело с 5-й? +Действуй по утвержденной мною инструкции. +Вот висит в рамочке. +Бери 7-й этаж, потом "стоп". +Потом обратно 5-й. +Стоим. +Так? +Не едем. +На этот случай все предусмотрено. +Жми аварийную! +ЗВОНОК +Замыкание. +И на этот случай все предусмотрено. +Слушай, надо бежать за монтером. +- А нельзя его насовсем починить? +- Можно. +Да руки до всего не доходят, а у меня их только две. +Понятно? +Я теперь в сторону культработы рокировался. +Организовал уголок тихих игр. +Шахматы, шашки. +А то от ребячьего футбола... +- Все в порядке. +Лифт работает. +- Спасибо. +Куда, куда вы удалились? +Весны моей... +Эй! +Безобразие! +Выньте меня отсюда! +Сейчас же! +- Не волнуйтесь, пожалуйста. +7- ю нажмите, 2-ю и 5-ю. +- Ничего не получается. +Жму, не идет. +- Тогда так: 1-ю, аварийную, потом 5-ю. +ЗВОНОК +- Звонок работает, а лифт - нет. +- Почитайте, там свежие газеты лежат, а я за монтером сбегаю. +- Я на концерт опаздываю! +- А вы артист? +- Ну да. +- Тогда я для вас все сделаю! +Семен Петрович, я так больше не могу! +- Что за крик? +! +Ты понимаешь, куда ворвалась? +- У нас там человек! +Артист! +- Я тут комбинацию обдумываю. +- Артист в клетке, а вы тут комбинируете! +Перед людьми совестно! +- В самом деле, Семен Петрович! +Лифт у нас давно в цейтноте! +- Не надо перегибать, товарищи жильцы. +Лифт застревает иногда, но на короткие сроки. +Сколько сидит сегодняшний? +-20 минут! +- Всего 20 минут. +Норма. +Ты, товарищ Иванова, рассуждай в своем пешечном масштабе, не строй из себя ферзя. +- А я этого... +- Ферзя. +- ... из себя не строю! +Я душой за дело болею! +- Тихо. +Это комната для тихих игр, а не дискуссий. +Понятно? +Делаю ход конем на С-6. +- Я тоже сделаю ход конем. +- Что? +- Ты зачем на него жаловаться ходила? +- Я сначала его по-хорошему просила починить машину, чуть не плакала. +- Чуть не плакала. +У человека по твоей милости неприятности. +И на мне это отзывается. +- А это вы неправильно, дедушка, говорите. +- Как ты можешь на родного деда критику наводить? +! +- А если вы неправильно говорите. +У нас большой и замечательный дом. +А из-за такого вот ферзя люди и страдают, застревают между этажами. +И какие люди! +- Люди страдают! +А я - не люди? +Ходил, старый дурак, в ножки кланялся! +Просил! +Московскую прописку тебе отхлопотали! +А ты? +Отблагодарила! +Где ты еще такую работу найдешь? +На улице она не валяется! +- А вы мне работу не ищите, я сама найду. +- Сама! +Где? +Артистки из тебя не получилось, лифтерши не вышло. +Не будет из тебя толку. +Если ты на шее сидишь, так хоть помалкивай. +- Последний райсовет, последний вахтер. +Если уж здесь нет! +.. +- "Дорогой дедушка, вам сердиться вредно. +Вернусь, когда из меня выйдет толк. +Большое спасибо за все. +Ваша внучка Катя". +- Здрасте. +- Здрасте. +- Поздновато. +Вы по какому делу в райсовет, молодые люди? +- Вы Иванов? +- Ну, Иванов. +- А у вас внучка... +- У вас есть внучка Катя Иванова. +- А вы кто такие будете? +Что вы про нее знаете? +- Он с ней в поезде в Москву ехал. +- В одном купе. +- Так это из-за тебя у ней на вокзале все время обувь расстегивалась? +! +Нету внучки. +- Как нету? +! +- Ушла. +- Куда? +- В неизвестном направлении. +Семилетки кончаете, а родному деду подобные коммюнике пишете. +Чему вас учат-то? +Ушла. +- Дедушка, вы ее, наверное, обидели? +- А что такое я ей сказал? +Ничего особенного я ей не говорил. +- Разве можно? +! +Вы ей дед! +- Так я ей родной дед, а не попутчик! +Я имею полное право и поучать. +А она ушла. +Пропадет теперь. +Характер-то какой! +Да и попутчики разные бывают. +Обидеть могут. +Да и движение какое! +Москва! +- Ой! +Нельзя же так пугать людей! +Чуть не умерла! +- И зачем только таким права дают! +- А вы в суд на нее подайте! +- При чем здесь суд? +Товарищ начальник, это не несчастный случай, а счастливая встреча. +Я встретила подругу. +То есть племянницу подруги. +И слегка затормозила. +Верно, милочка? +- Верно? +- Можно ехать, товарищ начальник? +- Пожалуйста. +- Пойдем, милочка. +Спасибо. +- Что за безобразие! +Так будут давить среди бела дня! +СВИСТИТ +- Дорогу! +- Как вы себя чувствуете, милочка? +- Ничего. +У меня локоть разбит, и я испугалась, когда вы на меня наехали. +- Куда вас отвезти? +- Я не знаю. +- Вы, наверное, недавно в Москве? +- Недавно. +- Оно и видно. +Вы совершенно не умеете переходить улицу. +Вы работаете? +- Да... +Нет, сейчас не работаю. +- Имеете жилплощадь? +- Нет. +Да, но сейчас не имею. +- У вас действительно все цело, милочка? +- Все. +А что? +- Я вам помогу. +Сама судьба бросила вас под мои колеса. +- А дед что сказал? +- Он сам ничего не знает. +Он получил от нее открытку. +- И что? +- Жива-здорова. +Обратного адреса нет. +- Бесполезно ее искать. +- Между прочим, есть еще один вариант. +- Какой? +- В справочной мне сказали, что в Москве проживает 2137 +Екатерин Ивановых. +- И что? +- Надо узнать адреса и обойти их всех. +Что смеешься? +- Так, ничего. +СМЕЕТСЯ +До самой старости будешь искать. +Борода во, в руках палка: +"Дедушка, вам кого?" - "Мне Катю Иванову". - +"Бабушка, вас дедушка спрашивает". +- Тебе смешно, а мне кажется, что я ее все равно найду. +Душа ни по ком до сих пор не страдала, +Но ты повстречалася мне. +Куда же ты скрылась? +Куда ж ты пропала? +Неужто приснилась во сне? +Куда же ты скрылась? +Куда ж ты пропала? +Неужто приснилась во сне? +По мне это, может, совсем не заметно, +Но я уж такой человек, +Что если дружу, то дружу беззаветно, +А если люблю, то навек. +Ты знаешь, мне кажется, что она на Таганке живет. +- Почему? +- На открытке стоит штемпель +Таганского почтового отделения. +- Она может жить в Малаховке, а открытку бросила на Таганке. +- Нормальные люди где живут, там и бросают. +- Так то нормальные. +Пускай ненароком исчезла ты где-то, +Имей, дорогая, в виду, +Что я за тобою пойду на край света. +А надо - и дальше пойду. +Что я за тобою пойду на край света, +А надо - и дальше пойду. +Завтра на Таганку пойдем, да? +- Пойдем. +- Катя, со стола можно убрать. +Масик! +Ты будешь болеть или пойдешь на работу? +- Я, Кусенька, поболею немножко. +- Правильно, поболей, Масик, все равно не оценят. +- Кусенька, а ты уезжаешь? +- Да. +У меня в 11 психическая гимнастика, а потом массаж нижних конечностей и гомеопат. +Катя! +Оставьте вазу. +Это богемское стекво! +Его нельзя трогать, на него можно только молиться. +Она становится невыносимой. +Масик. +- Кусик. +- Что хочет Масик, чтобы Кусенька ему привезла? +- Масик хочет водочки. +- Водочки? +Успокойся, Масик. +Привезу, мой красавчик. +Привезу, мой ангел. +Оставьте книги! +- Пыль же, Раиса Пална. +- Это не та пыль, с которой надо бороться, она неподвижная. +Масик, присмотри за этой. +- А что? +Она ничего. +Вообще... старательная. +- Масик! +Опять? +- Кусик. +- Что "Кусик"? +Ну что "Кусик"? +Что такое домработница? +Домработница - это внутренний враг. +- Я знаю. +- Хватит! +Обожаю. +Не так, Катя! +- А как, Раиса Пална? +- Надо любить свой труд. +Труд облагораживает человека. +Что такое домработница? +Домработница - это директор домашнего хозяйства. +Вы занимаете ответственный пост. +В общем, вот так. +Плохо у вас получается, Катя. +Я скоро вернусь. +Без меня ничего не делайте. +Только сходите за папиросами для Василь Никодимыча, постирайте занавески, вымойте пол в кухне, купите все на обед, перетрясите коврики, почистите ножи и вилки. +А когда я вернусь, будете готовить обед под моим руководством. +- Доброе утро. +- Доброе... утро? +Возможно. +Что, брат, достается? +Птичка Божия не знала Ни заботы, ни труда. +В домработницы попала. +Ла-ла-ла... +- Отстаньте, Василь Никодимыч! +- А что мне будет, если я отстану? +- Пустите же! +- А что мне будет, если я пущу? +- Пустите! +- Тряпка-то, негигиенично. +Алло. +Да, Комаринский. +В чем дело? +Что? +Из Госконтроля? +Я уже еду. +Скажешь Раисе Палне, что меня срочно вызвали в контору. +- Вахтер Иванов слушает. +Алло. +Я, девчоночка, жила, забот не знала, +Словно ласточка, свободною была. +На беду свою тебя я повстречала. +Позабыть, как ни старалась, Не смогла. +Позабыть, как ни старалась, Не сумела. +Завладел моей ты девичьей судьбой. +Уж давно веселых песен я не пела. +Неужели мы не свидимся с тобой? +Ты ушел и не воротишься обратно. +Одинокой навсегда останусь я. +Годы лучшие проходят безвозвратно, +И проходит с ними молодость моя. +Я, девчоночка, жила, забот не знала. +Словно ласточка, свободною была. +Повстречала я тебя и потеряла, +Потеряла в тот же час, когда нашла. +Ой! +А! +- Картина ясная! +Кран забыла закрыть! +Ох и влетит теперь тебе. +- Безобразие! +- Пустите меня! +Боже мой! +Сплошной кошмар! +Что тут случилось? +- Маленькое наводнение на два этажа! +За ваш счет! +- Вы понимаете, что вы наделали? +Зачем вы полезли в ванну? +- Я ничего не наделала. +Я убираюсь, и вдруг вода. +- Кто же, по-вашему, открыл кран? +- Это, наверное, Василь Никодимыч, перед тем как на работу уйти. +- Какое право вы имеете обвинять ответственного работника? +! +Вы лжете! +О! +Какая дорогая вещь! +- Я не лгу! +- Боже мой! +Мой персидский ковер! +Мы разорены! +Вы лжете! +Вы мне за все ответите! +- Раиса Пална, я кран не открывала! +- А я это проверю. +И горе вам, если вы солгали! +- Проверьте! +- Алло. +- Алло. +Алло. +Алло. +- Масик, ты болвасик! +Ты забыл закрыть кран в ванной! +- Как я мог? +! +- У нас теперь наводнение! +- Куся, я... +- По колено вода. +Ты забыл закрыть кран! +Ты понимаешь, что ты наделал? +! +Мы совершенно разорены. +- Дай ей по собственному желанию, и пусть идет на все четыре стороны. +- Лгунья! +- Я не лгунья. +Я правду сказала. +- Что вы стоите? +! +Ковер спасайте! +Вы должны в ногах у меня валяться, прощения просить. +Если бы я тогда на вас не наехала, вы бы давно погибли, как швец под Полтавой. +- Швед, а не швец. +- Как вы смеете меня поправлять? +! +- А если вы неправильно говорите. +- Дерзкая девчонка! +- Вы не кричите на меня! +Я вам благодарна за наезд на меня! +Но тот наезд я вам отработала. +А теперь я ухожу от вас! +И пусть все ваше богемское стекво кто-нибудь другой обслуживает! +А с меня хватит! +- Прекрасно! +Собирайте вещи и убирайтесь! +По обоюдоострому желанию! +- Куда сейчас поедем? +- Новоспасский тупик. +- Вот так. +Новоспасский, Николо-Спасский. +Так доездимся... +Садитесь, пожалуйста. +- Спасибо. +- Граждане, берите билеты. +- Будьте добры, один до конца. +- Извините, я забыла деньги. +Я сейчас сойду. +- Пожалуйста, я уже взял. +- Что вы, не нужно. +Я все равно сойду. +- Я уже заплатил. +- Хорошо. +Дайте ваш адрес, я перешлю вам деньги. +- Зачем? +Мы сойдем вместе, и вы отдадите мне долг. +- Пожалуйста. +- Ты куда? +- Не могу я такие деньги на ветер бросать. +"Набережная". +Следующая - "Новоспасский". +- Серьезно, надолго? +- Боюсь, навсегда. +- Ну, привет. +- Скажите, пожалуйста, Екатерина Иванова в этой квартире живет? +- В этой. +- А ее можно видеть? +- Почему бы нет. +Вы проходите. +Она на кухне сейчас. +Вы идите по коридору, но там темно, у нас лампочка перегорела. +Вы потом свернете налево. +Потом прямо, потом опять налево. +Увидите дверь. +- Ясно. +- Вы туда не входите, идите дальше, там будет еще одна дверь. +Вы тоже не входите, идите дальше. +Попадете в маленький узенький коридорчик, из него прямо и упретесь в кухню. +И перед вами она. +- Она? +- Да. +Понятно? +- Я разберусь. +Спасибо. +Можно? +Черт! +Понаставили чего-то. +Скажите, пожалу... +- А-а! +- Катя, Катечка. +- А-а-а! +- Да что вы кричите? +- Что? +- Что там? +- Бандит. +- Где? +- В ванной. +- Да не может быть. +- Не открывать! +- Откройте! +Слушайте, я не бандит. +- Идите скорей в милицию. +- Может, сами разберемся? +- Конечно сами! +- Ни в коем случае! +Только через мой труп! +- Я не бандит, откройте. +Я вам все объясню. +Ой! +- Феоктист Феоктистыч. +- Я здесь. +- Узнайте, сколько их там. +- Скорей! +- Вы здесь стерегите, а мы пойдем вооружаться. +Откройте! +- Если бандиты взломают дверь, бросайтесь на них и кричите. +- Если я кинусь, потом не поднимусь. +- Вы же мужчина. +- Но ведь он тоже мужчина, пусть он и кидается. +- Я не мужчина, а ответственный сьемщик! +Оставайтесь! +А остальные за мной. +- Слушайте, товарищ Феоктистыч, если вы мне не откроете, я взломаю дверь. +Квартира умалишенных! +- Молодые люди, имейте в виду, у меня в руках горячее оружие. +ГРОХОТ +- Ну что? +Откройте! +- Здрасте. +- Товарищ милиционер. +- Где бандиты? +- Вот здесь, в ванной. +- Я ответственный съемщик! +- Тихо, граждане. +- Их там много. +- Выходите по одному. +Все выходите! +- Все - это я один. +- Какой симпатичный! +- Как вы сюда попали, гражданин? +- Я пришел к Ивановой Екатерине Ивановне. +- Я так и думала! +- Я первый раз его вижу! +- Вы к ней пришли? +- Не к ней я приходил! +- Пройдемте. +- Правильно. +- Я должен переодеться! +- Руки пусть поднимет. +- Я не виноват совсем. +- Попрошу в машину. +- Зачем в машину? +Я вам все объясню. +- Спокойно. +- Да не поеду я никуда! +- Руки вверх! +- Товарищ лейтенант, адреса. +- Ну и что? +- Все ясно. +- Вы мне ответите. +- Подождите! +Товарищ начальник. +- В чем дело, гражданочка? +- Сейчас одного человека на машине увезли. +За что? +- Мало ли за что. +Может, он в квартиру залез. +А может, еще что-нибудь похуже. +Тогда крепко могут дать. +- А куда его повезли? +- В отделение. +А вы что? +Он вам знакомый? +Или, может, родственные отношения? +- Знакомый! +- Нет, комсомольская характеристика не нужна. +Дело ясное. +Тут пришли ваши ребята. +Савельев? +- Я Савельев. +- И Дубонос. +- Он Дубонос. +- Савельев и Дубонос. +Ручаются. +- Ручаемся, конечно. +- Я тоже думаю, верить можно. +Всего хорошего. +Так вот, граждане, ошибочка произошла. +Вы уж его извините, пожалуйста. +- Извините, пожалуйста. +- Пожалуйста, это так романтично. +- Если нужно, заходите еще. +Будем рады. +- Нет уж, спасибо. +- Тем не менее бдительность остается бдительностью. +- Бдительность тут ни при чем. +В следующий раз влюбляйтесь в девушек с точным адресом и с менее распространенной фамилией. +Ясно? +- Девушка, дождь идет. +- Ну и пусть идет. +- Вы бы домой шли. +- А у меня нет дома. +- Как нет дома? +- А вот так. +Нет. +- Знаете, пошли ко мне. +Я живу недалеко, за углом. +- Не пойду я никуда. +- Пошли. +Так можно и простудиться. +Берите чемодан. +Скорее! +Пей чай. +Кушай как следует, не стесняйся. +- Спасибо. +И так вторую чашку уже. +- Согрелась? +- Угу. +- Бери сыр, колбасу. +Ешь. +- Я не хочу больше, наелась. +Спасибо. +- Катя, ты у меня пока останешься. +Сестра приедет нескоро. +За это время ты успеешь устроиться на работу. +На. +- Большое спасибо. +- А что же дедушка, так о тебе ничего и не знает? +- Нет. +- Все-таки дед. +Я бы на твоем месте ему позвонила. +- Я иногда ему звоню, только не отвечаю: если на работе, значит здоров, - а потом вешаю трубку. +- Я сама такая, никогда не начну первая, если меня обидят. +- Самое обидное, что он правду сказал. +Что я из себя представляю? +Ничего. +Чего я добилась? +- Ничего, утро вечера мудренее. +Самое главное, тебе надо устроиться на работу. +ВЕСЕЛАЯ МУЗЫКА +- Значит, и я тоже виноват, раз ты могла такое подумать. +Спасибо. +Но о любви я тебе никогда не говорил. +- "О любви не говорят, О ней все сказано". +- Это только в песне поется. +- В кино ходили? +Два раза. +- Ну и что? +- На танцы приглашал? +- Приглашал. +- Целовались. +- Когда? +- Как когда? +- Один раз. +- Три! +- Какое это имеет значение, Клава? +- Может, любишь? +- Неудобно, люди же кругом смотрят. +Сердцу ведь не прикажешь. +Не плачь, Клавочка. +Девушка, посчитайте нам, пожалуйста. +- А ту нашел? +- Кого? +- Ну, с которой в поезде познакомились. +- Нет. +- Вахтер Иванов слушает. +Алло. +Катерин, это ты? +Брось баловаться! +Отвечай! +Молчишь? +Ну молчи. +А ко мне приходил попутчик твой. +Видный такой парень. +Забыл, как его имя-то. +- Когда он приходил? +Ой, дедушка, здравствуй. +Тут что-то с трубкой. +- Давно. +Сразу как ты сбежала. +Ты когда домой вернешься, Катерина? +- Дедушка, из меня еще толк не вышел, как выйдет - сразу приду. +Я живу хорошо. +Работаю. +Вы за меня не беспокойтесь. +- Сейчас же ступай домой! +Непутевая! +Какую моду взяла! +От родного деда бегать. +Катерина, ты слышишь меня? +Я, признаться, проявил Глупость бесконечную: +Всей душою полюбил Куклу бессердечную. +Для нее любовь - забава, +Для меня - мучение. +Придавать не стоит, право, +Этому значения. +Не со мной ли при луне Пылко целовалася? +А теперь она во мне Разочаровалася. +Для нее любовь - забава, Все ей шуткой кажется. +Кто ей дал такое право Надо мной куражиться? +Позабыть смогла она Все, что мне обещано. +Вам, наверно, всем видна В бедном сердце трещина. +Для нее любовь - забава, Для меня - страдание. +Ей - налево, мне - направо. +Ну и до свидания. +- Ну вот мы и пришли. +- А завтра, Оленька, пойдем в кино. +- Вдвоем? +- Вдвоем, я билеты взял на последний сеанс. +- Ой, еще и на последний. +- А что? +- Нет, я возьму подругу. +А вы возьмите приятеля. +- Ну, Оленька, кино-то вдвоем интереснее смотреть. +- Почему интереснее? +- Почему, почему... +За что это, Оля? +- Мы только второй раз с вами встречаемся, а вы безобразничаете. +- Не второй, а третий. +- Это все равно! +Вот вы какой. +Нате ваши цветы! +- Оля! +Я не хотел вас обидеть. +Я думал, что... +- Что думали? +Разве вас девушки никогда не били за такое хулиганство? +- Никогда. +Даже наоборот. +- Значит, вы с плохими девушками встречались. +До свидания. +- Оля! +Я даю вам честное слово, что этого никогда больше не повторится без вашего на то разрешения. +Оля, можно я возьму возьму билеты на завтра на четверых, на последний сеанс? +Можно, Оля? +- Можно. +Встретимся возле кино. +- Хорошо. +Я вас провожу, а то темно на лестнице. +- Не нужно, я сама. +До свидания. +- До свидания. +- Катя, пойдем завтра с нами в кино. +- Я вам мешать только буду. +- Что ты! +Он с товарищем придет. +Познакомишься. +- Не нужно мне никакого товарища! +- Катенька, я прошу. +Ради меня, пойдем. +- Не нужно. +- Странная ты. +Это же Москва! +Как ты своего Пашу найдешь? +Ты даже фамилии его не знаешь. +- Ну где ты? +- Прости. +Ну как? +- Красив. +Только смотри, как бы она от тебя тоже не убежала. +- Ничего. +Моя не бегает. +У нее несколько другая привычка. +Будьте добры, зефира коробочку. +- Митя, а может, я не пойду с тобой в кино? +- Она подругу приведет. +- Ну и что? +Я еще 2 адреса достал. +- Первый раз в жизни я тебя попросил, и ты не можешь. +- Я могу, но... +В нашем распоряжении еще 50 минут. +Давай зайдем по одному адресу. +- Быстро? +- Быстро. +- Пойдем. +- Гражданин! +- Спасибо большое. +- Слушай, здесь открыто. +Пойдем. +- Пашка, вспомни ванную. +- Я теперь ученый. +Ничего не будет, идем. +Можно? +- Можно? +- Кто-нибудь здесь есть? +- Люди добрые, отзовитесь! +Ну вот так. +Примерно этого я и ожидал. +- Это хуже, чем ванная. +- Хозяин! +Есть тут кто-нибудь? +Как он смотрит. +Видишь? +Опоздаем. +- Слушай, она, наверное, не любит, когда с ней громко разговаривают. +- Давай тогда по-хорошему. +Вежливо. +Она же ученая. +Шарик, позвольте выйти. +- Шурик. +- Хорошая собачка. +- Почему они не идут? +Уже скоро начало. +- Он, наверное, забыл. +- Что ты! +Как он может забыть? +- Что же мы теперь делать будем? +- А что, если ее зефиром подкупить? +- Ты что, собаки взяток не берут. +- А мы попробуем. +Лобзик, на! +Скушай. +Вот так. +- Ну, теперь иди. +- Нет, ты иди. +- Ты кормил, ты и иди. +- Пойдем вместе. +- Пойдем. +Шагаем. +- Оля, бесполезно ждать. +Пошли домой. +- Нет. +Я останусь и ему все скажу. +- Ну как хочешь. +Я пойду. +- Аппетит-то какой-то нечеловеческий! +- Собачий. +- Что я Оле скажу? +Ведь не поверит. +- Слушай, у меня есть план. +Кидай ей зефирину. +Пока она будет кушать, я потушу свет, и в темноте пробьемся. +- Это идея. +- Давай. +- Только спокойней, Паша. +- Лаечка. +Ай! +Люди! +Ай! +Держи! +- Оленька, я вам сейчас все объясню. +- Я ждала вас только для того, чтобы сказать, чтобы вы не смели ни приходить ко мне, ни писать, ни звонить! +Забудьте мое имя и тот день, когда вы заплатили за меня в троллейбусе! +- Да выслушайте меня, Оля! +- Нет, нам необходимы молодые кадры, и они у нас должны быть. +- Вы неисправимый фантазер. +- Елизавета Тимофеевна, для художника необходима фантазия. +- Я член худсовета. +Мне фантазия абсолютно не нужна. +Мы должны внедрять, а не фантазировать. +- Елизавета Тимофеевна, посмотрите, какая очаровательная девушка. +- Я ничего очаровательного не нахожу. +- Девушка, вы с вашей внешностью могли бы найти занятие поинтереснее. +- Вы куда-то шли, ну и идите! +- Нет, боже сохрани! +Вы меня не так поняли. +Я хочу вам предложить интересную серьезную работу. +- Демонстрируются вечерние туалеты, созданные художниками-модельерами нашего экспериментального ателье. +- Елизавета Тимофеевна! +Люся заболела, и я не могу демонстрировать свою модель. +- Что вам сказала эта симулянтка? +- Она сказала, что у нее температура 39,2. +- У нее температура, а у нас - художественный совет. +Иванова, станьте сюда. +Размер ее. +Демонстрировать будете вы. +- Что вы, я даже не знаю, как в таком ходить! +- Советская девушка должна смело ходить в том, что мы внедряем. +- Мне же говорили, что я только рабочую одежду буду показывать. +- У меня от нее каждые 5 минут разрыв сердца делается. +Прежде всего вы не должны срывать работу. +Вы хотите стать срывальщицей? +- Нет, но Елизавета... +- Ведите ее в кабину. +- Идемте, Катя, идемте. +Елизавета Тимофеевна, ну как? +- На уровне. +Даже лучше, чем я ожидала. +- Елизавета Тимофеевна, здесь такой вырез большой. +Мне неловко. +- Почему вы высказываетесь, вы же не член худсовета. +Идите немедленно. +- Там никого... +- Идите. +Уберите все ваши руки и не падайте с лестницы. +- Неужели он тебя выгнал? +- Нет. +Кричал только: "Нет у меня внучки! +Если вы еще раз придете, вызову милицию". +Сумасшедший какой-то. +И она, наверное, вся в него. +- Слушай, Митя! +- Что? +- Эта девушка так похожа на Катю. +- Какая? +- Эта в белом. +- Докатились. +Видения начинаются. +- Она так похожа, только ростом чуть выше. +- Слушай, Паша, брось ты эти поиски. +Не бросишь - плохо кончишь. +Что она тебе далась? +Ты посмотри, столько девчат ходит. +- Катя! +Это же моя модель! +- Иванова! +Вы взбесились? +- Куда она? +Почему сбежала? +- Окружайте! +Догоняйте! +КРИКИ ЛЮДЕЙ +- Катя, куда вы? +! +- Остановите ее! +- Платье держите! +- Это невозможно! +Я за молодыми кадрами должна гоняться по всем улицам! +- Понимаешь, я его увидела и побежала, удержаться не могла! +А потом по собственному желанию. +- Что, неужели выгнали? +- Что ты! +Я сама. +Они меня поругали немножко, но ничего такого. +Знаешь, Оля, не по душе мне там, не нравится. +- Что же ты теперь будешь делать? +- Не знаю. +Уехать, что ли... +- Ну вот, новость какая. +Ты знаешь, я могу тебя устроить. +У нас на работе нужна курьерша. +Я завтра поговорю. +- Оленька, спасибо. +Опять ты меня выручаешь. +- Ну, как настроение? +- Хорошее. +- Смотри, чтобы все было аккуратно. +Чай пожиже, заварки не хватит. +- Ладно. +- Попьют сотрудники в перерыв чай и снова за работу. +- Оленька, а что это вы все пишете? +- Пишем разные бумаги и считаем разные цифры. +- А зачем все эти бумаги? +- Смешная ты. +Над нашей конторой есть еще одна контора, которая главнее нашей. +Она присылает нам свои бумаги, мы их переписываем и посылаем в контору, которая ниже нашей. +- Не понимаю. +Почему контора, которая выше нашей, не может бумаги прямо послать в ту контору, которая ниже? +- Вот странная. +Чай неси. +- Семен Семенович, возьмите на меня чай, я сейчас. +- Спасибо. +- Иванова, начальник очень занят. +Поставьте стакан на стол и тихонечко уходите. +Понимаете? +- Понимаю. +- Таким образом, в целом... +Написали? +- Написала. +- ... своевременность оборачиваемости поступающих директив своевременна и происходит точно в свое время. +- Иванова. +Что с вами? +- Ничего. +- Возьмите пакет и поезжайте на стройку. +- На стройку? +- Послушайте, девушка, вы тут всех знаете? +- Всех и все, а что? +- У вас тут один товарищ работает. +- У нас не один товарищ работает, у нас их сотни! +А зачем он тебе? +- Неважно. +- Ты учти, мы своих на сторону не отдаем. +Ты пакеты разносишь? +- Пакеты! +- Ну и волоки свой бюрократизм! +Не прохлаждайся! +Кому пакет? +- Прорабу. +Где он? +- Вон туда иди! +Стой! +- Ушиблась, дочка? +- Нет, ничего. +- Как же тебя так угораздило? +- А мне прораба нужно. +- Я прораб. +- Ой, наконец-то! +У меня для вас пакет. +Лично. +Срочно. +- О! +Я эти новости неделю назад знал. +Сидите там, директивы переписываете. +А с арматурой опять подвели! +Давай, сердешная... +книжку твою, распишусь. +И кому нужна эта ваша контора? +- Наша контора - необходимое связующее звено в сложной цепи взаимоотношений между главком и стройплощадками. +В свое время мы своевременно сигнализировали. +И я считаю своевременным поставить вопрос о несвоевременности сжатия нашего аппарата. +Нас надо не сжимать, нас надо расширять. +- Вы не согласны, товарищ Комаринский, что ваша контора превратилась в лишнюю инстанцию? +- Категорически не согласен. +- Это как же вы говорите - не лишняя? +Нас на стройке только "лишними" +и ругают. "Лишняя инстанция", "лишняя контора". +Со стыда можно сгореть. +А вы знаете, сколько эта лишняя инстанция казенного чая выпивает? +Рублей на 500 в месяц. +- Демагогия. +Безответственное выступление. +- Оля! +- Здравствуйте, Митя. +Вы извините, я в таком виде. +Наше учреждение закрыли. +- Здравствуйте, Оля. +- Здравствуйте. +- Значит, вы теперь тоже рабочий класс. +- Я случайно на вашу стройку попала. +- Это же великолепно, что вы попали именно на нашу стройку! +Хотите к нам в бригаду подсобницей? +Могу похлопотать. +- Куда? +- К монтажникам. +Наверх. +Работа нетрудная. +Инструмент принести, то да се. +А красотища! +Стрижи летают. +Будете у нас королевой воздуха. +- Спасибо. +А вы королем там будете? +- Нет, заместителем. +Сейчас! +А я эти дни только о вас и думаю. +- Все время? +- Все время. +Пять раз в день мимо вашего дома хожу. +- Почему же не зашли? +- А как же я зайду, если вы мне запретили ходить к вам, звонить и даже писать? +- Мало ли чего я наговорила. +- А я боялся. +Подожди минутку! +- Это еще что такое? +- Иван Романович, это шефство над новенькими. +- Так будем шефствовать - за 10 лет дом не построим. +- Виноват. +- Ну, марш на место! +Через 5 минут отправляется поезд номер 72 +"Москва-Иркутск". +- Вот твой вагон! +Ты, Катерина, не забывай, что у тебя дед существует. +- Дед, не беспокойся, я писать буду. +- Как приедешь, сразу телеграмму дай. +С точным адресом, а то ведь пропадешь опять. +На вот тебе. +Письма от тебя не дождешься, а открыточку нацарапай: +жива, мол,здорова, чего и вам желаю. +Тут 50 штук, про запас. +- Катенька, может, останешься? +Будем опять с тобой вместе работать. +- Нет, решила так решила. +- А ты знаешь, что мне Митя сказал? +Они меня к себе в бригаду возьмут. +Буду у них королевой воздуха. +- Нет, королева - это не профессия. +Ты в штукатуры иди, это дело. +Что ты оглядываешься? +- Я попросила Митю сюда прийти, а его все нет. +Будет ему сегодня от меня. +- Опоздаешь! +Ты уж, Катерина... +Я для тебя от всей души. +- Что вы, дедушка! +- Ладно уж! +Про адрес не забудь, непутевая. +- Не забуду. +Вы себя берегите. +Оленька, спасибо тебе за все. +- Катенька, не забывай меня, пиши. +- Опоздали! +И все из-за тебя! +"Еще по одному адресочку зайдем!" +Ищешь прошлогодний снег! +- В последний раз. +Митя! +Она! +- Кто? +- Катя! +Катя! +Катя! +- Паша! +- Я вас по всей Москве искал. +- А я думала, вы меня забыли. +- Я всю Москву перевернул, а вас нет. +- Гражданин, сойдите с подножки. +- Одну минуточку... +- Гражданин, сойдите! +- Я вас очень прошу. +- Гражданин, не нарушайте. +- Я эту девушку люблю! +- Любить можно, нарушать нельзя! +- Ну и не мешайте! +- Да. +- Ты куда едешь, Катя? +- Далеко. +На работу. +- Как же я? +Оставайся! +- Мне же ехать надо! +- Зачем? +- Что же мне делать? +- Мы вместе поедем. +- Решайте, поезд идет. +- Поезд и правда идет. +Где твои вещи? +Пойдем, слышишь? +Катя, прыгай. +- Я боюсь. +А чемодан! +Ой, Пашенька, неправильно я сделала, мне же ехать надо. +- Что, опоздали, молодые люди? +- Нет, наоборот, успели. +- Пойдем? +- Пойдем. +Дуняшка! +Сухари зашила? +Сало солью пересыпала? +Вы , батя, свое дело управляйте, а я братушке так уложу, что до Черкасского не ворохнется. +— Что он, ест, что ли? +— Не, не ест. +Ну и не надо, а то он непоеный. +Петр, пробей. +Гришка его к Дону сводит. +Григорий, веди коня. +Чертяка бешеный! +Чудок конем не стоптал. +Степан твой собрался? +— А тебе чего? +— Спросить что ли, нельзя? +Собрался. +Ну? +Остаешься, стал быть жалмеркой? +Стал быть так. +Небось будешь скучать по мужу? +А то как же. +Ты вот женись опосля узнаешь скучают ай нет по дружечке. +А ить иные бабы ажник рады , как мужей проводют. +Наша Дарья без Петра толстеть зачинает. +Муж — он не уж, а тянет кровя. +Тебя-то скоро обженим? +Не знаю. +Как батя. +Должно, посля службы . +— Молодой ишо, не женись — А что? +Сухота одна. +Охоты нету жениться. +Какая-нибудь и так полюбит. +— Пусти, Гришка. +— Не пущу. +Не дури, мне мужа сбирать +Пусти, дьявол, вон люди. +Увидют, что подумают? +Ну, с Богом. +Час добрый. +Припозднились Мирон Григорьевич! +Что нашел, Гришуха? +Дай, закопаю. +— Ты чего? +— Да я напиться. +— Волосы у тебя... +— Чего? +Дурнопьяном пахнут. +Знаешь цветком зтаким. +— Пусти, Гришка. +— Помалкивай. +Пусти, а то зашумлю. +— Погоди, Ксюш. +— Дядя Пантелей! +Ты чего, Гришка, такой ненастный? +К дождю, видать поясницу ломит. +Он быков стеречь не хочет, ей-богу. +Гляди, траву чужую быками не потрави. +Гриша... +Гришенька... +Отец услышит. +Не услышит. +Пусти, чего уж теперь .. +Сама пойду. +Пантелей ПрокоФьевич, здорово ночевали. +— Доброго здоровья . +— Здрасьте. +Ты что ж зто, ПрокоФьич, примолчался-то? +Сына задумал женить а сам ни гу-гу. +— Какого сына? +— Григорий ведь не женатый. +Покеда ишо не собирался женить +А я слыхал, будто в снохи берешь Степана Астахова Аксинью . +От живого мужа... +Да ты что ж, Платоныч, навроде смеешься? +Да уж какой смех. +Наслышан от людей. +Зй, погоди-ка! +Чего еще? +Ты что ж зто, а? +Еще мужьин след не остыл, а ты уж хвост набок? +Ишь ты , курва, мало тебя били! +Чтоб ноги твоей с нонешнего дня на моем базу не ступало! +Я твоему Степану пропишу... +А ты что мне, свекор? +А? +Свекор? +Ты что меня учишь Иди свою толстозадую поучи. +Да я тебя, дьявола хромого, культяпого, в упор не вижу! +— Иди отсель не спужаешь — Погоди ты , дура! +— Нечего годить тебе не родить — Вот черт-баба! +Пиши хучь наказному атаману, а Гришка мой! +А захочу, с костями съем и ответ держать не буду! +Пиши! +За всю жизнь за горью отлюблю! +А там хучь убейте! +За что? +Не пакости соседу! +Не срами отца! +Не таскайся, кобелина! +Драться не дам! +На сходе запорю! +Ах ты , чертово семя! +На МарФутке-дурочке женю! +Я те выхолощу! +Женить сукиного сына! +Гриша, колосочек мой... +Осталось девять дён... +Ишо не скоро. +Степан придет, чего будем делать +Небось бросишь меня? +Побоишься? +Мне его что бояться, ты — жена, ты и боись +Степан придет — зто не штука. +Батя вот меня женить собирается. +Кого усватали? +Только собирается ехать +Маманя гутарила, кубыть к Коршуновым, за ихнюю Наталью . +Наталья ... +Наталья — девка красивая... +Дюже красивая. +Надысь видала ее в церкви. +Нарядная была. +Мне ее красоту за голенищу не класть +Я бы на тебе женился. +Гришка! +На что ты привязался ко мне, проклятый? +Гришка! +Душу ты мою вынаешь +— Гриша! +— Надумала что? +Дружечка моя... +родимый... давай уйдем. +Кинем все и уйдем. +И мужа, и все кину, лишь бы ты был. +На шахты уйдем, далеко. +На Парамоновских рудниках у меня дядя служит, он подсобит. +Гриша! +Хучь слово урони. +Дура ты , Аксинья , дура. +Ну куды я уйду от хозяйства? +Опять же мне и на службу на знтот год. +Нет, не годится дело. +Никуды я от земли не тронусь +Ну, ноне ей Степан даст! +— Гля, Степан-то притемнился. +— Да будет брехать-то! +Здоров, батя. +Ну, Аксинья ... +Не таюсь — грех на мне. +Бей, Степан! +Ишо не стряпалась +Нет ишо. +Собери-ка что-нибудь пожрать +Расскажи, милаха. +Расскажи, как мужа ждала, мужнину честь берегла? +А ну, разойдись Разойдись +А то зараз к атаману отправлю! +Вы что, черти? +Пойдем, Гришка. +Мы его в однорядь подсидим. +Нешто и ты не попадешься! +А ну, отвяжись Зараз к атаману отправлю! +Примай гостей, Мирон Григорич. +Гостям завсегда рады . +Марья , дай людям на что присесть +Дельце к вам имеем. +У вас — девка, невеста, у нас — жених. +Не снюхаемся ли? +Здорово ночевали. +Слава Богу. +Про то и речь что выдавать кубыть и рано. +Оно само собой — дело хозяйское. +Жених, он навроде старца, где хошь просит. +А уж раз вы , к примеру, ищете купецкого звания жениха, аль ишо что, зто совсем уж другое, звиняйте. +Что уж там, родимые мои! +Теперича самое светок лазоревый, что ж держать — аль мало перестарков в девках кулюкают? +Раз дело такое зашло, значится надо порешить его порядком и дитю своему на счастье , по доброму слову. +Аль мы детям своим супротивники и лиходеи? +Наша не засидится. +Да ведь придется, рано ль поздно ль расставаться. +Кличь дочерю, Мирон Григорьевич, поглядим. +Наталья . +Наталья ! +Натаха! +Пройди. +Ишь засовестилась +Ну, ступай. +Аксютка! +Сюда иди. +Пришла. +В чем зто у тебя щека? +— Должно, с подсолнуха. +— Ишо вот тут, возле глаза. +Мочи нету... +Пропала я, Гриша. +Чего ж он? +Не знаешь чего? +Вот. +Бьет каждый день Кровь высасывает. +И ты тоже хорош. +Напаскудил, как кобель и в сторону. +Все вы ... — Виноватого ищешь — Аль ты не виноват? +Ксюша, ну, погоди... +Ну, сбрехнул словцо, ну, не обижайся. +Чего кричишь +Я не навязываться пришла, не боись +Значится, кончилась наша любовь +Как зто кончилась +Как же зто? +Вот что, Аксинья ... +Я надумал... +Платок сними. +Как бы не увидали. +Надумал я... +Надо как-то дальше проживать +Надумал я, давай с тобой прикончим... +Чего? +Прикончим зту историю, а? +Аксинья ! +Сыр каравай принимайте, молодых одаряйте. +Дарим невесте шаль +Даруем бычка. +Горько! +Огонь по зебрам пошел! +А баранинки хочешь +Ты меня баранинкой не угощай. +Я, может, стерлядку ем. +Стерлядку? +Где она у нас? +Командует есаул Терсинцев... +Какого? +Взвод! +В атаку полным наметом! +Пики к бою, шашки вон! +Молодцы , баклановцы ! +.. +Здорово, Гришенька! +Здорово. +Как живешь-любишься с молодой женой? +Ничего, живем. +Слышь баба, Наташку не буди. +Она и так до свету встает. +Сбираются с Гришкой пахать +Дарью стегай. +С ленцой баба, спорченная. +Румянится да брови чернит, мать ее суку. +Нехай хучь первый годок покохается. +Гришка! +Григорий! +Гриша! +Батя кличет. +Дарья ! +Поди сюды ! +Знти два улеша вспаши, что за толокой у Красного лога. +— Петро не подсобит? +— Они с Дашкой на мельницу поедут. +Подсоби. +Проспал, а теперь лезешь Отойди, хохол, а то клюну! +Я тебе зоб вырву! +Стойте, братцы ! +Казаков бьют! +Стойте, братцы ! +Братцы , стойте! +Бабы , а вы что глядите? +Они же всех мужиков побьют! +Запалю! +Уходь со двора! +Запалю! +Уходь со двора! +На коней, казаки! +Догнать Дале гребня не ускачут! +Ты кто такой? +Откель сорвался? +Стойте, станичники! +Куцый кобель тебе станичник! +Мужик! +Лапоть дровяной! +Дай ему по гляделкам, Яша. +Погоди по гляделкам. +В чем дело? +— Хохлов били. +— За что? +За очередь Не залазь наперед. +Вложили им память +Хохлы , они огромадно сердитые. +— А ты кто? +— Я-то казак. +А ты не из цыганьев? +Нет, я не из цыганьев. +Мы с тобой, пожалуй, оба русские. +Брешешь +Казаки от русских произошли. +А я тебе говорю, казаки от казаков ведутся. +В старину от помещиков бежали крепостные и селились на Дону. +Их прозвали казаками. +Иди-ка ты , мил человек, своим путем. +Ишь поганка, в мужиков захотел переделать +Кто зто такой, АФанасий? +Приехал тут какой-то, просил довезть Кто его знает? +Моя Фамилия Штокман. +Сам я слесарь +Буду жить в хуторе Татарском. +Могу и по столярному делу. +Так что еще увидимся. +Поехали, хозяин, время-то идет. +Чужая ты какая-то. +Как знтот месяц. +Не холодишь не греешь +Не люблю я тебя, Наталья . +Ты уж на меня не гневайся. +Хоть и жалко тебя, а нету на сердце ничего. +Пусто. +Вот как зараз в степе. +Наталья , вот, сбирается уходить Зто через чего? +— Не знаю, через чего. +— А я знаю! +А я знаю через чего! +Я ее не сужу, хоть и страмно и перед Богом грех. +Не на ней вина, а вот на знтом сукином сыне. +— Кому я виноватый? +— А ты не знаешь чертяка? +Не знаю. +Я тебе вот что скажу: +не будешь с Наташкой жить — иди с базу куда глаза глядят. +Вот тебе мой сказ! +Иди куда глаза глядят! +Я вам, батя, не во гнев скажу. +Не я женился, а вы меня женили. +А за Натальей я не тянусь Хочет, нехай идет к отцу. +— Иди и ты отсель — И уйду! +И уходи к чертовой матери! +— Уйду! +— Куда ты пойдешь +Нехай идет, кобелина поблудный! +Нехай, будь он проклят! +Гриша! +Гриша, вернись +Пропади ты , разнелюбая! +Гришенька! +Да уж хорошо ли, плохо ли, да так сложилась история. +Да разве ж сами виноваты ? +До такой страмы довели казаков. +— Молчи уж, мужик. +— А мужики аль не люди? +Мужики-то? +Я как в Петербурге служил, так разных видал. +Вот был такой случай. +Перепало как-то верхи нести караул. +Едем, а с угла студенты вывернулись И видимо их невидимо. +Как увидели нас, да " Га-а-а! +Вы чего, казаки, разъезжаете?" +Я гутарю: " Караул несем, а ты поводья не хватай!" — и за шашку. +А тут один носатый вынает из портмоне десятку и гутарит: +"Выпейте, казаки, за здоровье моего покойного папаши" . +Дает нам десятку и вынает из сумки портрет. +"А зто, — говорит, — папашина личность возьмите на память" . +Ну, мы взяли. +А студенты отошли и опять " Га-а-а" . +С тем и отправились по Невскому прошпекту. +— Здравствуйте. +— Вот еще один казак явился. +Ты чего, Гришка? +— Ты отсюда скоро? +— Скоро. +— Я у тебя заночую. +— Со своими поругался? +Стало быть отправились по Невскому прошпекту. +Ну? +Ну, сменили нас. +Мы вахмистру гутарим: +"Заработали мы 1 0 целковых. +Должны пропить их за упокой души знтого деда" , — и показываем портрет. +Зтот портрет я взял на совесть для памяти над кроватью повесил. +Вижу, борода седая, собою подходимый человек, вроде из купцов. +А сотник доглядел и спрашивает: +"Откель взял зтот портрет, такой-сякой?" +"Так и так" , — гутарю. +А он и зачал меня костерить и по скуле, да ишо, стал быть раз. +"Да знаешь орет, что - зто атаман ихний Карла..." +— Запамятовал прозвище. +— Карл Маркс. +Во! +Он самый. +Подвел под монастырь мать его в пенек! +А ить к нам сам цесаревич Алексей с наставниками забегает. +А если бы доглядели? +Что б было? +А ты все мужиков хвалишь Видал, как его подковали-то? +Зато десятку пропили. +Хучь за Карлу бородатого, а пили. +Целых три дни пили! +Да, за него следует выпить +А чего ж он навершил такого доброго? +А зто я... обязательно... +Обязательно расскажу. +Только сейчас поздно уже. +До свидания, Осип Давыдович. +Я к тебе только на сутки, двое. +— А что, домой не вернешься? +— Нет. +А как же жить надумал? +Как жить А как люди живут. +Люди живут по-разному. +Заходи. +Садись вечерять будем. +Да, Гриша... +Люди по-разному живут. +Тяжело будет без привычки-то. +Ничего, привыкну. +Куда ж надумал? +Завтра к Сергею Платоновичу схожу. +А не то к генералу Листницкому в имение. +Зто что ж, батрачить будешь +Зх, Гриша... +Ну какой из тебя батрак? +На зтом деле шибко не разживешься. +Смотри, как бы гордость у тебя не взыграла. +— Ты чего? +— Гришка! +Сказал, чтобы как затемнеет, вышла к гамазину. +Тише, Машутка. +Может, ишо чего велел сказать +Ой, гутарил, чтобы все свое взяла, что можешь +Господи... +Да как же я? +И так-то скорочко... +Да что ж я? +Ну, я пойду. +Поди, скажи ему, что я скоро. +— Чего она приходила? +— Кто? +Машка Кошевых. +Зто она по своему делу. +Просила юбку ей скроить +А ты , никак, собираешься куда? +К Аникушке пойду, посижу трошки. +И когда ты находишься? +Что ни ночь то им игра. +Но, будя, слыхали. +Ты ложись не жди. +Ну-но. +Господи... +Ой, Гриша... +Погоди чуток. +Чего годить Надо поспешать +— Ой, погоди, Гриша... +— Ты чего? +Так, живот чтой-то. +Тяжелое нады подняла. +Ну, все, пойдем. +Ты и не спросишь куды веду. +Может, до первого яра, а там спихну? +Все одно уж мне. +Доигралась +Чего зто дверь-то настежь +Как живешь Аксиньюшка? +Благодарствую. +— Здорово. +— Здорово. +— Ты чего, Гетько? +— От Натальи . +Григорий Пантелеевич! +Пропиши мне, как мне жить и навовсе или нет потеряна моя жизня? +Ждала я, что ты возвернешься, но я разлучать вас не хочу. +Пожалей напоследок и пропиши. +Узнаю — буду одно думать а то я стою посередь дороги. +Ты , Гриша, не серчай на меня, ради Христа. +Наталья . +— Чего он сидел? +— А я почем знаю? +Пришел, сел вот так-то. +Глянь Гриша. +А коленка вострая-превострая. +— Примолвила, что ль его? +— Да нужен он мне, Господи! +То-то, гляди, а то я его в одноряд спихну с крыльца. +Я тебя оставлять дома боле не буду. +Со мной будешь ездить +Да Гриша... +Ты чего? +Что ж ты молчала раньше? +Да я робела, думала, бросишь +Скоро? +На Спасы , думается. +Степанов? +Твой. +Ну а где же? +.. +Григорий! +Наелся, пустяковая твоя душа? +Поди проспись +Обедня отошла. +Не давай баловать Не давай баловать +Прощай, генерал! +Смотри не зашибись +У Натахи-то Коршуновой, гутарют, кила. +Будет брехать-то. +— Через зто ее и муж бросил. +— Не, она со свекром спуталась +Стало быть через знто Гришка и убег с дому. +А то через чего ж? +— Чего? +— Чего... говори да откусывай. +Скучаешь по Гришке-то? +— А тебе что? +— Тоску твою разогнать хочу. +— Уйди, Митька. +— Не мордуйся, Наташка. +— Я батю зашумлю. +— Тю, сдурела! +Уйди, проклятый! +Как тебя земля только держит! +А вот так, держит, не гнется. +Ну что? +Дорога невозможная, моя донюшка. +Така тряска, что Гетько уси пзчонки поотбывав! +На, держи. +"Живи одна. +Мелехов Григорий" . +Здорово живете. +Здравствуй, батя. +Собираешься на службу? +А то как же? +— Раздевайся, батя, назяб небось — Ничего, терпится. +— Самовар поставим. +— Спасибочка. +Привез тебе справу: +два шинеля, седло, шаровары . +Возьми. +Всё там. +Выступать когда? +Другой день Рождества. +— Казак? +— Девка. +Уж такая писаная, вся в Гришу. +Наших кровей... +Ишь ты ! +Ты что ж, батя, едешь +Поспешаю пораньше возвернуться. +Значится, не думаешь с женой жить +Давнишний сказ. +Отгутарили. +— Не думаешь стал быть — Стал-быть так. +А Боr? +Ты гляди... +не чужого вскармливаешь +Чей бы ни был, а дите не брошу. +Наталья спортилась с того разу. +Как она? +Жилу нужную перерезала, шею кособочит. +Наталью мы возьмем. +Не хочет баба жить у своих. +Надысь видал ее, кликал, чтоб к нам шла. +На хуторе Ольшанском... +Гриша, стучат. +За жену не беспокойся. +Служи исправно. +Дед твой молодецкий был казак. +Чтоб и ты ... +Чтоб и ты держал себя достойно своего деда и отца. +Ведь зто отец на императорском смотру в 83-м году получил первый приз за джигитовку? +Так точно! +Ты , ПрокоФьич, у развилки шибко не гони, а то я вчера аккурат там перекинулся. +— Ну вот, успел уже... +— Долго ли ему. +— Садись в сани. +— Не, я верхом. +Трогай! +Погоди, Гриша! +Что-то хотела сказать .. +Ну, прощай. +Дите гляди. +Поеду, а то батя вон где уж. +Погоди, родимый... +— Счастливо, казак! +— Счастливо, дед. +— Дай чего подсоблю. +— Ничего, я сама. +Наташа, светочка, чего рассказать хочу... +Расскажи. +Мишка Кошевой вчера целый вечер простоял со мной возля гамазинов. +— Чего ж скраснелась — Ничуть +Глянь в зеркало — чисто полымя. +Ты ж пристыдила. +Рассказывай, я не буду. +"Ты , — гутарит, — как цветок лазоревый" . +А я: " Не бреши!" А он божится. +Зто кто ж такие? +— Кто их знает. +— К кому ж? +Прошу встать Вы арестованы . +В чем дело? +— Вы занимаете 2 комнаты ? +— Да. +Мы произведем у вас обыск. +Позвольте ключ от зтого сундука. +Чему я обязан, господин следователь +Об зтом мы еще успеем побеседовать +Пожалуйста. +Понятой, ну-ка! +— Прошу вас. +— Нет, зтот сорт я не курю. +Прошу вас начинать допрос. +Вы сюда прибыли по заданию своей организации? +О чем речь +С какого времени вы состоите членом РСДРП? +Вот справка из Ростова, подтверждающая вашу принадлежность к означенной партии +с 1 907 года. +Получали ли вы какие-либо директивы из Ростова? +Нет. +Читали рабочим, посещавшим вас, вот зту книжонку? +Мы читали стихи. +Стихи... +Вы читали запрещенные законом книги. +Ося! +Осип Давыдович! +Петро! +Перегодим жару. +Ой, Господи, искупаться бы . +Верхи какой-то бегет. +— Шибко. +— Ты гля, как пылит. +— Так и коня запалить можно. +— Наметом идет. +Сполох! +Сполох! +— Никак, война? +— Господи! +Цыть ты ! +Григория встретишь скажи, так мол, и так... +Война, значит... +По вагонам! +— Едете? +— Садись дед, с нами! +Милая ты моя говядинка! +— Братушки, вы куды ж зто? +— К куме на крестины . +Молчать +Мелехов, ты не робеешь а? +А чего робеть-то? +Как же, может, ныне в бой пойдем. +И пущай. +А я вот робею. +Всю ночь не спал. +Стреляют. +Как ребята палкой по частоколу. +Молчи ты , балабон. +Где зтот капитан? +Вам приказано было еще вчера закончить работу. +Молчать +О подвозе строительного материала надо было позаботиться раньше! +Молчать +Как я теперь проеду на ту сторону? +Я вас спрашиваю, как я проеду на ту сторону? +— Ну что вам? +— Какие будут приказания? +Да ступайте, ступайте. +Что зто? +Кто приказал? +Пики к бою, шашки вон! +В атаку рысью марш-марш! +Зй, ты , чего встал? +Я к тебе, Аксинья . +Ты зачем пришла? +Мне бы напиться... +Пей. +Ты отбила у меня мужа... +Отдай мне Григория. +Ты жизнь мою сломила. +Видишь я какая? +Мужа тебе? +Мужа тебе? +Ах, ты , гадюка подколодная! +Ты у кого просишь +Да ты первая отняла у меня Гришку! +Ты , а не я. +Ты знала, что он жил со мной, зачем замуж шла? +Я вернула свое, он мой. +У меня дите от него, а ты что? +Ты отца у дитя хочешь взять +Ты своего мужа бросила... +Не шуми так... +Кроме Гришки, нет у меня мужа. +Никого нету во всем свете! +Ты -то нужна ему? +Глянь шею-то у тебя покривило! +Ты , думаешь он здоровую бросил, а на калеку позавидует? +Не видать тебе Гришки! +Вот мой сказ! +Ступай! +Ты думаешь я надеялась что выпрошу? +— А зачем шла? +— Тоска меня пихнула. +Господи... прости... +Пожалей... +Не отнимай, Господи! +.. +Здравствуйте, барин. +Ой, слава Богу... +слава Богу. +Помянем. +Царство небесное дитю. +Душа ангельская преставилась +Ты бы , Ксюша, пошла, поглядела. +Может, чего снадобится. +Молодой барин приехал. +Алексеев? +Не может быть Не поверю. +И тем не менее. +Верховный в данном случае не прав. +Вот тебе аналогичный пример из русско-японской кампании... +Кушать подано. +— На днях ребенка похоронила. +— Да что ты ? +Так вот, я говорю аналогичный случай их русско-японской кампании. +Куропаткин как-то настаивал, требовал, а жизнь показала свое. +Здравствуй, Аксюша. +Здравствуйте. +— Ктой-то? +— Зто я. +Сейчас я оденусь +Ничего, я на минуту. +У тебя умерла дочушка... +Умерла. +Ты очень изменилась +Еще бы , я понимаю, что значит потерять ребенка. +Только ты напрасно изводишь себя. +К жизни ее не вернешь +А ты еще молода, ты еще будешь иметь детей. +Не надо так. +Возьми себя в руки, смирись +Смирись +В конце концов, не все потеряно со смертью ребенка. +Подумай, вся жизнь впереди! +Ты шо, Гриша, вертися? +Так ты говоришь что на потребу богатым нас гонят на смерть +А как же народ? +Аль он не понимает? +Неужели нет таких, который вышел бы и сказал: +"Братцы , так вот за что мы гибнем в кровях" . +Як це так, вышел? +Ты що, сказывся? +Вышел... +Побачив бы я, як ты вышел. +Мы ось с тобой шепчемся, а скажи ризко — и пид пулю. +Черная глухота у народа. +Война его разбудит. +Из хмары писля грому дощ буде... +Чего ж делать Говори, гад! +Ты мне сердце разворошил. +А що тоби сердце каже? +Не понимаю. +Хто мзнз с кручи пихае, того я пихну. +Трзба у того загнать пулю, кто посылае людей у пзкло. +И ты знай, Гриша, собирается взлика хмаря, вона усз снесз! +Что ж, все повернуть вверх ногами? +Власть трзба скынуть як грязные портки. +Трзба с панив овчину драть трзба им губы рвать бо гарно воны народ помордувалы . +В палату. +Быстро все проверьте. +На свое место. +Уложите, уложите. +Милости просим, ваше императорское высочество. +Пожалуйста, сюда, ваше императорское высочество. +Прошу вас. +Донской казак, георгиевский кавалер. +Какой станицы ? +Вёшенской, ваше императорское высочество. +За что имеешь крест? +Я бы ... мне бы по надобности сходить .. +По надобности, ваше императорское высочество. +По малой нужде. +Пожалуйста, в следующую палату, ваше императорское высочество. +— Ты , каналья ! +.. +— Я тебе не каналья , гад! +На Фронте вас нету! +Отправьте меня домой! +Отправим! +Убирайся к черту! +Стоять +Признал, признал... +Дед Сашка! +Спишь +Отцы -святители! +Гришка! +Откуда тебя холера взяла? +Вот так гость +Ну, садись покурим. +Ну, дидко, живешь Землю топчешь +Топчу помаленечку. +Я - как ружье кремневое, мне износу не будет. +Аксинья как? +Что ж Аксинья ... слава Богу. +— Танюшку где похоронили? +— В саду под тополем. +Так... — Ну, рассказывай. +— Кашель меня замучил... +Все живы -здоровы . +Пан вон попивает. +— Аксинья как? +— Она в горничных теперь +Знаю. +Ты бы покурить свернул. +У меня табачок первый сорт. +Ты говори, а то я уйду. +Я же чую, что ты слово какое-то, как камень за пазухой, держишь +— Бей, что ли. +— И вдарю! +— Бей! +— Вдарю. +Силов я не набрал молчать и мне, Гриша, молчать прискорбно. +Говори. +Змею ты грел! +Гадюку прикормил! +Она с Евгением свалялась Каков голос! +— Верно говоришь — Баба — кошка. +Кто погладил, к тому и ластится. +А ты не верь веры не давай! +Покури. +Стучал ты как, а я уснула... +Не ждала... +Любимый мой! +Ты чего дрожишь Пойдем скорей. +Озяб я. +— Гришенька... +— Ну, ладно, ладно. +Не ждала... +Давно не писал. +Думала, не придешь ты . +Хотела тебе гостинцев отправить а потом, думаю, погожу, может, письмо поучу. +А ты на горнишную не похожа. +На зкономку скорее. +Гриша... давай я тебя разую. +Ой, Гришенька... +Что ж ты кричишь +Аль не рада мне? +Вот он, георгиевский кавалер. +Однако ты возмужал, брат. +Надолго прибыл? +На две недели, ваше превосходительство. +Дочь-то похоронили. +Жаль жаль .. +Григорий? +Ты откуда? +Из Москвы , в отпуск. +Вот как. +Ранен был? +Так точно. +Я слышал... +Каким он молодцом стал, а, папа? +— Кавалер! +— Да... +Никитич, подавай! +Ваше благородие, дозвольте прокатить вас по старой памяти? +Что ж, сделай милость поедем. +Ну-ка, позволь +Зх, и прокачу ж я вас, Евгений Николаевич! +Прокати, на чай получишь +Премного вами довольны . +Спасибо, что Аксинью мою не забываете, кусок ей даете. +Возвращайтесь поскорей! +— Ты что? +— А вот что! +Скотина! +За меня! +За Аксинью ! +За меня! +За Аксинью ! +Ишо тебе за Аксинью ! +Черт, загнал коня! +Григорий! +Гадина! +Сука! +Гриша! +Гриша, прости! +Господи! +Маманя! +— Дождь — Идет. +Сотник прячет марьяж. +Сотник, вы разгаданы . +Никогда не ходите от третьей дамы . +Чего зто ты ноне? +Небось станицу во сне видал? +Угадал. +Степь приснилась +Так замутнело на душе... +Осточертела царева службица. +Чего уставился? +— Ну-ка, к свету. +— Погоди. +Враги ваши — австрийские и немецкие... — Чего? +— Вот. +"Враги ваши — не австрийские и немецкие солдаты , обманутые так же, как и мы , +а собственный царь" . +Крепко. +"Собственный промышленник и помещик" . +В бань бы неплохо. +В нашей землянке остается котел поставить воды хоть отбавляй. +Мокро, хозяева, мокро. +Благодарите Всевышнего, что сидим у болота, как у Христа за пазухой. +На чистом наступают, а мы едва по обойме за неделю расстреливаем. +Лучше наступать чем гнить заживо. +Мы рвемся в бой! +Сотник, вы как, рветесь в бой? +Я? +8 бубен. +В крести рвусь +Не для того держат казаков, чтобы уничтожать их в атаках. +Для чего же? +Для чего? +Когда на Фронте начнутся волнения, — а зто неизбежно: +война начинает солдатам надоедать — вот подавлять мятежников бросят казаков. +Ересь мелешь +А почему же ересь +Потому что ересь есть ересь +Увлекаешься, милейший. +Откуда ты знаешь о будущих волнениях? +А если предположить нечто обратное? +Союзники разбивают немцев, война завершается блистательным концом. +Тогда какую роль ты отводишь казачеству? +Что-то не похоже на конец, тем более блистательный. +Я ведь недавно из отпуска. +Ну и как там, в Петрограде? +Гремит столица? +Да, гремит. +Отрадного мало. +Не хватает хлеба. +В рабочих районах голод, недовольство, протест. +Благополучно мы не вылезем из зтой войны , как думаете, господа? +Как мы думаем? +Мы думаем, раз. +— Пас. +— Два. +Здесь Черт! +Русско-японская война породила революцию 1 905 года. +Зта война завершится новой революцией. +И гражданской войной. +Внимание, господа, хорунжий Бунчук начинает вещать по социал-демократическому соннику. +Петрушку валяешь Ну-ну, у каждого свое призвание. +Меня удивляет то обстоятельство, господа, что в среде нашего оФицерства есть такие вот субъекты . +Ты что же, стоишь за наше поражение в зтой войне? +Я? +Я за поражение. +Ну знаете ли! +Каких бы ты ни был политических убеждений, но желать поражения родине — зто национальная измена. +Минуту! +Зто бесчестье для каждого порядочного человека! +Подожди, Калмыков. +Хорошо, допустим, поражение. +Ну а дальше? +Царизм будет уничтожен, можете быть уверены . +— Что тебе? +— От полковника Ширяева пакет. +Давай. +Ступай. +Зкстренно приглашают к полковнику. +Сочувствуем. +— Всех? +— Всех. +Очередная диспозиция при возможной зкзекуции. +Имею основание думать зто приказ о наступлении. +С Богом, братцы ! +В добрый час! +Вперед! +Молчат. +Подпускают ближе. +А я боюсь ноне и не совестно мне. +А что если зараз повернуть и назад? +Тут как в картежной игре, не веришь себе - голову снимут. +Ты из лица пожелтел. +Либо ты хворый, либо кокнут тебя ноне. +Сотня, за мной! +Рысью марш! +Газы , братцы ! +Газы ! +Стой! +Стой! +Газы , братцы ! +Хватайся за стремя! +Сволочь Назад! +Назад, сволочь +Все, все, к чертовой матери. +Не скачи, не скачи шибко! +Задыхаюсь Не скачи, ради Иисуса Христа! +Садись +Полный сапог налило крови. +Гришка, нынче как шли в наступление... +Слышишь Григорий? +Нынче как шли, я в тебя сзади до трех раз стрелял. +Не привел Бог тебя убить +А ты меня от смерти отвел. +Спасибо. +А за Аксинью не могу простить Душа не дозволяет. +— Ты меня не неволь .. +— А я тебя не неволю. +Вот она. +Ты чего, Мелехов? +Григорий Пантелеевич! +Насыпали нам! +Дураков учить надо! +Учить +Сука народ! +Хуже! +Кровью изойдет, тогда поймет за что его по голове гвоздют. +Ты про что? +Умный сам поймет, а дураку силком не вобьешь +— Ты о присяге помнишь — Иди ты ... — Гришка... +— Живой ты ай нет? +— Да ты скажи что-нибудь — Живой... +Небось наш курень уж развалился? +Нет, зачем развалился — стоит. +Что ему сделается? +Соседи-то наши, Мелеховы , как живут? +Живут помалень . +Петро не приходил в отпуск? +Вроде не приходил. +А Григорий? +Гришка ихний? +Гришка приходил после Рождества. +Баба его двойню знтот год родила. +Григорий приходил по ранению. +Раненый был? +Раненый в плечо. +Его всего испятнили, как кобеля в драке: не поймешь то ли крестов на нем больше, то ли рубцов. +Какой же он, Гришка? +Такой же, горбоносый да черный. +Турка туркой, как и полагается. +Я не про то. +Постарел аль нет? +А чума его знает, может, и постарел трошки. +Баба двойню родила, значит, не дюже постарел. +Холодно здесь +Гнида гадкая, вонючая, какая ни на есть хуже. +Давно ли в чириках по хутору бегала, а теперь не скажет " тут" , а " здеся" . +Вредные мне зти бабы . +Я бы их, стервей... +Выползень змеиный! +Туда же... " холодно здеся" . +И пошла! +Возгря кобылья ! +Пра! +С какой роковой предопределенностью шло к зтому. +Я предвидел зто еще в начале войны . +Ну что ж... +Династия была обречена. +Ну неужели все же отрекся? +Разумеется. +Такими вещами не шутят. +Послушайте, что пишет Евгений. +Да, папа, грозные, грозные события. +Солдаты буквально все разложены ... +Ступай. +Воевать не желают — устали. +В зтом году не стало солдат в общепринятом смысле зтого слова. +Вы не можете представить до какой степени разложения дошла наша армия. +А впереди еще худшие испытания. +Станичники! +Волею народа, царствовавший доныне император Николай Второй низложен. +Туда ему и дорога! +Вся власть перешла к Временному комитету Государственной думы . +Армия, и вы в том числе должны спокойно перенести зто... +Прекратить +Прекратить ... известие. +Дело казаков защищать свою родину так же доблестно от посягательств как со стороны внешнего, так и... так и натиска внешнего врага. +Мы в дни таких великих потрясений должны быть тверды , как... — Как сталь — Как сталь +Мы будем биться так же доблестно, как и раньше, а там пусть Государственная дума... +Пусть Государственная дума решает судьбу страны . +В армии не должно быть политики. +— Не должно! +— Дай-ка я скажу. +Станичники! +Нельзя так-то! +Нас опять же под конФуз подвели. +Обман хочут сделать +Раз превзошла революция и всему народу дадена свобода — значится, войну должны прикончить +Аккуратно я гутарю? +По-правильному? +Да... +Во что же все зто выльется? +Как ты думаешь +Вот тебе раз! +Неужели, живя здесь вы не уяснили обстановку? +Несомненно, будет правительственный переворот. +У власти встанет Корнилов. +Армия ведь за него горой. +У нас говорят так. +Сейчас две равнозначных силы — зто Корнилов и большевики. +Керенский между двумя жерновами, — не тот, так другой его сотрет. +Пусть себе спит пока на постели царицы , благо она освободилась +Но армия... пойдет ли вся армия за Корниловым? +Сама солдатня, конечно, не пойдет. +Мы поведем ее. +Послезавтра Москва встречает Корнилова. +Дело чести каждого оФицера быть там. +Вечером я выезжаю. +— Я с тобой. +— Разумеется. +Молодец. +Не время, не время. +Господа оФицеры ! +Пока казаки поют, большой беды нет. +Теперь поют редко, все больше митингуют. +Надо учиться разговаривать с людьми. +Хорунжий Бунчук? +Ты на свободе? +Прости, но руки я тебе не подам. +Я не собирался протягивать тебе руку, ты поспешил. +Ты что же, спасаешь здесь свою шкуру? +Или прибыл из Петрограда? +Не от душки ли Керенского? +Зто что, допрос? +Законное любопытство о судьбе некогда дезертировавшего сослуживца. +Могу тебя успокоить я здесь не от Керенского. +Кто ж ты все-таки такой? +Погон нет, шинель солдатская. +Политический коммивояжер? +Товарищи казаки! +Наш зшелон дальше не пойдет. +Сгружаться тут зачнем. +— Правильно? +— Правильно! +Здравия желаю, станичники! +Агенты большевиков и Керенского препятствуют продвижению наших частей по железной дороге. +Получен приказ верховного главнокомандующего... +Верховного Корнилова! +В том случае, если не представится возможным продвигаться по железной дороге, то идти на Петроград походным порядком! +Сегодня же мы выступаем! +Приготовьтесь к выгрузке! +Товарищи казаки! +Я прислан к вам питерскими рабочими и солдатами. +Вас хотят вести на братоубийственную войну. +На разгром революции! +Если вы хотите идти против народа, если вы хотите восстановить монархию... — филосоФия! +— Провокатор! +Если вы хотите восстановить монархию, — идите! +Но питерские рабочие и солдаты надеются, что вы не будете каинами. +Они шлют вам пламенный братский привет! +Минуту! +Казаки, хорунжий Бунчук в прошлом году дезертировал с Фронта, вы все зто знаете! +Неужели мы будем слушать предателя и труса? +Арестовать его, подлеца! +Оружие прочь Пущай говорит, выясняет свою линию! +Говори, Бунчук! +Земно вам кланяемся и просим передать питерским... +Стой! +Гляди-ка на них. +А ну-ка, за мной. +Калмыков, ты арестован! +Руки! +Руки! +Разоружить +— К зтим приставить часовых. +— Слушаюсь +Калмыкова поведем в ревком гарнизона. +Ну, что же вы ? +! +Руки вверх. +Ловко. +Есаул Калмыков, извольте идти вперед. +За мной. +— Иди... +— Подлец! +Ты предатель изменник! +Ты еще поплатишься за зто! +Вы не партия, а банда гнусных подонков общества! +Кто вами руководит? +— немецкий главный штаб! +Большевики! +Хамы ! +Хамы продали родину! +Я бы вас всех на одной перекладине... +Время придет! +Ваш зтот Ленин не за 30 немецких марок продал Россию? +! +Хапнул миллиончик — и скрылся... каторжанин! +— Становись — Не смей бить +Убить хочешь +Стреляй! +Стреляй, сукин сын! +Смотри, как умеют умирать русские оФицеры ! +Я и перед смертью ... +Митрич... за что ты его? +Что же ты , Митрич? +А ты как думал? +Он бы в нас стрелял, не вынимая папироски изо рта. +Мы их или они нас! +Середки нету. +За мной! +Вперед! +Откуда, служивые? +Отвоевались что ли? +— Хватит, отцы , навоевались — А ты пойди, сам хвост потрепи. +Езжайте к бабам на печь +Миша! +Мы уж и не ждали! +А Мелехов Гришка где? +Гришка к большевикам подался, остался в Каменской. +К большевикам подался... +Мы подтягиваем братскую руку трудовому казачеству! +— Ты бы потише толкался! +— Пусти, комарь а то — к ногтю. +Рабочие и казаки вместе лили кровь +И в войне с Калединым мы должны быть вместе! +Рука с рукой мы пойдем в бой против тех, кто порабощал трудящихся в течение целых столетий! +Кто на Фронте ввел смертную казнь для солдата? +Корнилов! +Кто с Калединым душит нас? +Он! +Так к тому же вы пристанете, братцы казаки? +Задавим гидров зтих, в море спрудим! +Верно! +Дай им взвару! +Свою власть надо сделать +А добровольцы и разные партизаны пущай уходят с Дону! +И большевикам у нас делать нечего. +Мы с врагами рабочего народа сами сладим. +Чужой помощи нам не надо! +— А знто кто? +— Кривошлыков, с хутора Горбатова. +— А рядом? +— Зто сам Подтелков и есть +О, и Голубов тут. +Братья казаки! +Да замолчите вы ! +Не на базаре! +Дайте Подтелкову сказать +Братья казаки! +Покуда мы тут совещаемся, а враги трудового народа не дремлют. +Мы всё хотим, чтобы и волки были сытые, и овцы целые. +А Каледин — он так не думает. +Нами перехвачен его приказ об аресте всех участников нашего съезда. +Долой Каледина! +Предлагаю считать наш съезд властью на Дону! +Предлагаю... предлагаю из делегатов нашего съезда избрать казачий Военно-революционный комитет! +Ему поручить вести борьбу с Калединым и организацию... +Господа, господа! +Вот они, предатели! +Повесить их! +Господин хорунжий, я протестую. +Молчать Становись по три. +Шагом марш. +Всех повесить Всех! +Всех предателей! +Какое вы допускаете безобразие! +Благодари Бога, что живой останешься. +Я бы тебя, хамлюгу! +.. +Сидеть Вставать не будем. +Здравствуйте. +Здравствуйте. +Ну-с... какие же части вас уполномочили? +Так... ну и чего, собственно говоря, вы добиваетесь +Наше требование — передайте власть Военно-революционному комитету. +Как зто все просто. +Ультиматум. +Вам, вероятно, известно, что на 4 Февраля созывается Войсковой круг. +Члены правительства будут переизбраны . +Согласны ли вы на взаимный контроль +Нет! +Ежели вас будет меньшинство, мы вам диктуем свою волю. +Но ведь зто же насилие. +Да. +Ежели Войсковой круг нас не удовлетворит, мы его не признаем. +— Ну и кто же будет судьей? +— Народ! +Народ! +Чего нам слушать их? +Нам с большевиками не по пути. +Только изменники Дону и казачеству могут говорить о сдаче власти Советам и звать казаков идти за большевиками. +Неужели вы думаете, Подтелков, что за вами, за недоучкой и безграмотным казаком, пойдет Дон? +А ежели пойдут, то кучка оголтелых казаков, которые до дома отбились +Но они, брат, очнутся — и тебя же повесют! +Браво, Шеин! +Донское правительство рассмотрит предложение ревкома и даст ответ в письменной Форме к 1 0 часам утра назавтра. +На конь +Мальчики, красавчики, голубчики! +Ну-ка, птенчики! +Ну-ка, умницы , потревожим большевичков! +Мелехов, строй сотню и выводи в Ерохинскую балку! +Добро! +Живо! +Сотня! +Слушай мою команду! +Сотня! +За мной марш! +— Вы командир зтого отряда? +— Да. +Попробуйте по балочке в обход, а я буду их держать огнем на зтом участке. +Ну что ж, можно и по балочке. +Попробуем. +С такими навоюешь Детей бы ишо забрал с перинами. +Как я себя ругаю, что не оставил тебя в Ростове! +Бунчук, в вас заговорил собственник. +Сотня, за мной! +Ну как? +Что? +Ранило тебя? +А ну, давай. +Аня, где? +— Аккурат под сердце. +— Что под сердце? +Аня... +Аня... +Ты куда глядишь Аня? +Аня... +Вот он я... +Аня... +Вот... +Илья , милый... +Вот видишь как все просто... +Сперва удар... +Потом толчок... +А теперь печет, жжет. +На грудь воды лейте! +Воды ! +Дайте кто-нибудь воды ! +За веру! +За Русь За мной, соколики! +Сотня! +За мной в атаку! +Аня, не уходи! +Не уходи, Аня! +Не уходи, Аня! +Слушай сюда! +Слушай сюда! +Головной ко мне, остальные прямо! +За сохранность пленных отвечаете по всей строгости военно-революционного времени! +Чтоб доставить в штаб в целости! +Отдайте зто Подтелкову. +Мелехов! +Молодец! +— Да ты ранен, никак? +— В ногу. +— Кость цела? +— Вроде. +Наголову! +Наголову разнесли! +ОФицерский отряд так распушил, что и не собрать +Ты в штаб? +Передай Подтелкову, что Чернецова я беру на поруки. +Вот так и передай. +Езжай. +Подтелков, зараз гонят пленных. +Ты читал записку Голубова? +Плевать мне не Голубова! +Мало ли ему чего захочется! +На поруки ему Чернецова, зтого разбойника контрреволюционера? +Не дам! +Революционным судом судить и без промедления наказать +Голубов сказал, берет на поруки. +Ты чего вылез? +Лежал бы . +На поруки... +Ты знаешь сколько он крови на свет выпустил? +Море! +Сколько он шахтеров перевел? +Не дам! +Тут орать нечего! +Вас тут много судей! +Ты вот туда пойди! +А над пленными вас много распорядителей! +Я был там! +Не думай, что на тачанке спасался. +А ты , Мелехов, ты с кем гутаришь +ОФицерские замашки убирай! +Ревком судит, а не всякая там... +Уложите его. +Ну, орелик... +Попался, гад! +Изменник казачества! +Предатель Подлец! +Разбегайтесь господа! +Господи, прости меня, грешного. +Зто что ж такое делается? +А ты думал - как? +Али лоб контре под пулю подставим? +Маманя, едут. +Едут, маманя! +Здорово! +— Здоровый? +— Рану получил, под Глубокой. +Нужда заставила там огинаться! +Шел бы домой. +Да ты , Дуняха, черт тебя знает, какая девка-то вышла! +А я думал, дурненькая будет. +Ну уж ты , братушка! +Сын-то какой, погляди! +Дай мне моего сына поглядеть +А дочь-то, Гриша! +Ну, возьми же! +Ну что, не узнаете папань -то, орехи лесные? +Наташа, возьми их, а то я на порожки не влезу. +Табачищем-то прет! +— Дарья , на стол собирай. +— У него своя жена есть +К масленой блины с каймаком будем исть +— Ну, признал папаньку? +— Признал. +— Зто тебе, маманя. +— Милые мои... +— Ба, он на полу валяется. +— Ничего. +Карга старая, а туда же — перед заркалой. +Батя, тебе. +Ну, спаси Христос. +А я Фуражку присматривал. +В лавке нонешний год их не было, а старую в пору на чучело надевать +Ты чего ж, дрючок старый? +Господи, ну и глупа ты ! +Ить самовар — не зеркало. +Вот он, казачок лейб-гвардии казачьего полка! +На императорском смотру первый приз захватил. +Седло и всю амуницию! +Вот он я! +Наташа. +Дуняшка. +Петро. +Дарья . +— Ну, а знто кому? +— Мне. +— Да ты как полковник. +— Крестов-то! +Прикинь Гриша. +Прикинь батяня будет довольный. +Чего ж ты , задаром заслуживал, что ли? +фу, какой ты пышный! +Народи ты себе таких, чекатуха. +По крайней мере два сыночка — и обое в люди вышли. +Ну, будя. +Арбузы соленые есть +Ну как же! +Наташа. +Пока народ не подошел, расскажи Петру, что там делается. +Папа, а чего вы водичку из рюмочки пьете? +Дерутся. +Большевики где зараз? +С трех сторон: с Таганрога, с Тихорецкой, с Воронежа. +Ну а... ты какой же стороны держишься? +Я-то? +За Советскую власть +Дурак! +Петро, хучь ты втолкуй ему. +Горячий он у нас, как необъезженный конь +Разим ж ему втолкуешь +А мне нечего втолковывать я и сам не слепой. +фронтовики что у вас гутарют? +Да что нам зти Фронтовики? +Поиграли мы в большевиков на Фронте, пора и за ум браться. +Мы ничего чужого не хочем, ну и нашего не берите. +Ты , Гришка, подумай. +Парень ты не глупый. +Казак — как он был казак, так казаком и останется. +Вонючая Русь у нас не должна править +А то знаешь что иногородние зараз гутарют? +Всю землю разделить на души. +Зто как? +Иногородним коренным, какие в Донской области живут издавна, дадим землю. +А шиша им! +Вот им выкусить +— Здорово, служивый! +— Здорово. +Телка испужал, горластый. +Ишо не хватало... +Ну, Пантелей ПрокоФьевич, магарыч станови. +— Хлеб-соль — Седайте с нами. +Чего ж Михайло Кошевого не видать +Да тут он, на хуторе. +Ты чего, Валет, здесь За рыбой, что ли? +На кой она мне. +Худые дела, худые. +Кончай рыбку удить А то удим, удим, да про все забудем. +Ну, какие новости? +Выкладывай. +Под Мигулинской красную гвардию разбили. +Началась клочка... +Шерсть летит. +Откуда под Мигулинской? +Шли через станицу, казаки дали им чистоты . +Пленных кучу в Каргин пригнали. +Там военно-полевой суд уже наворачивает. +Нонче у нас мобилизация. +Вот-вот в колокол ахнут. +— Как же теперь — Надо подаваться из хутора. +— Куды ? +— Куды ! +А я почем знаю? +Прикрутит — сам найдешь лазейку. +Беги к Ивану Алексееву, а я вентери отнесу и зараз приду. +Уходить сейчас же! +Нонче же сматывать удочки! +Ты резон дай — чего мы пойдем? +Начнется мобилизация, думаешь зацепишься? +— Не пойду. +— Поведут. +Я не бычок на оборочке. +Возьмут, Валет правильно гутарит. +Куда идти — вот загвоздка. +Опять Как да куды . +Шутки шутите? +Время, вишь какое... +Тут все к черту пойдет. +Не сепети, твое дело другое. +Ни спереду, ни сзаду — снялся да пошел. +А у меня баба да двое детишков. +Тебе только языком трепать У тебя, кроме пинжака, ничего нету. +Ты чего рот раззявил? +ОФицерство свое кажешь +Не ори! +Плевать мне на тебя! +Замолчи, гаденыш! +Сопля паршивая! +Валяй, чтоб тобой не воняло тут! +Брось Григорий! +Казацкие замашки бросать надо. +И не совестно? +Совестно, Мелехов. +Стыдно. +Еще в Красной гвардии был... +Таких мы на распыл пущали! +Ступай! +Ноги повыдергаю! +С ума сошел? +А чего он не свое на себя берет? +Дождались +Вон-на, кличут! +З, нет. +Я зараз на баркас. +На знтот берег. +Потель меня и видали. +Ну так как же? +Зараз никуды не пойдем. +Бывайте. +Расходятся, видать наши тропки. +Зх, Мишка, Мишка... +Молодой ты , горячий. +Ты думаешь не сойдутся? +Сойдутся еще, будь в надежде. +Бывайте. +Слезай! +— Откель станичники? +— С хутора Татарского. +Припоздали вы трошки. +Поймали без вас Подтелкова. +— А где ж они? +— Вон ведут. +— И куды ж их? +— К покойникам. +Что ты брешешь +Сбреши лучше, ваше благородие. +Глянь им уже рели поставили. +Да, ежели бы вышли с Ростова на трое суток раньше, не пришлось бы тут смерть принимать +Кверху ногами поставили бы всю контру. +Черт с ними, пускай убивают. +И смерть пока не страшна. +Боюсь одного я, что в мире ином — друг друга уж мы не узнаем... +Как не узнаем? +Что ты ? +Ну, погутарили, хватит. +Старики! +Позвольте нам с Кривошлыковым поглядеть как наши товарищи будут смерть принимать +Нас повесите опосля. +А зараз хотелось бы поглядеть нам на своих друзьев-товарищей, поддержать которые духом слабы . +— Ну как? +— Нехай. +Дозволяем. +Нехай побудут. +Отведите их от ямы . +Выводи. +От вашего хутора есть охотники? +— Какие охотники? +— Приговор приводить в исполнение. +— Нету и не будет. +— Я стрельну. +Я согласный. +Только дай патронов. +Пойдем. +Держись +9, 1 0, 1 1 , 1 2, 1 3, 1 4, 1 5. +Так и не вспомнил, как звать +Так и умрешь без имени? +Имя есть +Член Российской коммунистической партии большевиков, питерский рабочий, сам из казаков. +Хватит. +По изменникам казачеству пли! +И ты тут, Мелехов? +— Тут, как видишь — Вижу. +Расстреливаешь братов? +Оборотился? +Вон ты какой... +Пли! +Под Глубокой бой помнишь Помнишь как оФицеров стрелял? +Теперича отрыгивается! +Не одному тебе казацкие шкуры дубить +Ты , поганка, казаков продал! +Ишо сказать +Что? +Стой! +Что я? +! +Что я? +Стой! +Отуманенные вы ! +Слепые! +Слепцы ! +Пусть погутарит напоследок. +Заманули вас, заставляют кровных братов убивать +Думаете, ежели нас побьете, зтим кончится? +Нет! +Советская власть установится по всей России! +Вот попомните мои слова. +Зря кровь вы чужую льете! +Глупые вы люди! +Мы и с знтими зтак управимся. +Всех, дед, не перестреляете. +Всю Россию на виселицу не вздернешь +Своя голова ближе! +Всхомянетесь вы опосля, да поздно будет! +Погутарил, хватит. +Лучших сынов Тихого Дона поклали вы в зту яму. +Вешать-то ишо не научились +Садись +Иди-ка сюда. +Обозники приехали. +С ними папаша ваш. +Ну? +! +Будет брехать +Право слово. +Иди встревай. +Зачем вас принесло, земляки? +А мы в обувательских, снаряды вам привезли, только воюйте. +Зто от матери тебе. +— А ты чего приехала? +— Да с батей. +Маманя забоялась случись чего, он один на чужой стороне. +— Здорово, соседка. +— Здорово, сосед. +Господи, и поглядеться-то некуда. +Заправду говорят, мыслишку держите дальше границ не ходить +А зачем дальше идтить +Выбьем мужиков с казачьей земли — и по домам. +По домам... +Вот придавят чеха, а потом как жмякнут всю красную армию, которая по ним была, и потекет из нас мокрая жижа. +Одно слово — Россия! +Шутишь что ль +Не пужай! +Аж возле пупка заноило от дурацкого разговора. +А по мне хоть всю жизнь воевать Люблю знто дело. +Выходи! +Не успели войтить уже выходи. +Опять значит, на позиции. +А вы гутарите: границы . +Какие могут быть границы ? +По домам надо! +Ну, пошли. +Ну-ка, Проша. +Поди погляди, чего там. +Хочу погутарить с тобой. +На той неделе я ездил к Петру. +Ихний полк за Калачом зараз. +Они, сынок, там неплохо поджились +Петро, он дюже гожий к хозяйству. +Дал мне чувал одежи, коня, сахару. +Конь справный. +Погоди. +Ты сюда не за зтим заявился? +— А что? +— Как что? +Люди ить Гриша, берут. +Люди! +Берут! +Своего мало? +Хамы вы ! +За такие штуки на германском Фронте людей расстреливали! +Не сепети, я у тебя не прошу. +Мне ничего не надо. +Ты об себе подумай. +Скажи, богатей какой нашелся. +Да и что ж не взять с знтих, какие к красным подались +Грех с них не брать +Ты мне оставь зто! +А не то живо провожу отсель +Давай коня. +Степан Астахов явился. +Слыхал? +Как зто? +Аксинья к нему вернулась +Ты бы внукам гостинцы послал. +Какие с Фронта гостинцы ? +Я на заставу. +Дарья ! +— Чего ишо? +— Подсоби. +Ой, Господи... +Вы , батя, и со своим дерьмом не расстанетесь +Молчи, шалава. +Буду я им ишо котел оставлять +Из тебя хозяйка, как из Гришки-поганца. +Батюшки! +Родимый! +Греха не боишься! +За что сирот обижаешь +Станичники, ну-ка, подсобите. +За что сирот обижаешь +Отдай хомут. +Отдай ради Господа Бога. +Ты Бога оставь +Твой-то комиссар, никак? +Раз " твое-мое-Богово" , значит, — молчок, не жалься. +Прощай, бабочка, не гневайся. +Вы себе ишо наживете. +Тебе вспомянется! +Ишо отольются вам наши слезы ! +Нет, правда за нами и сила за нами. +Вы находитесь господа, в историческом зале со стен которого на нас смотрят герои другой народной войны , войны 1 81 2 года. +Было время, когда Париж приветствовал своих освободителей — донских казаков. +1 04 года назад наш атаман граФ Платов гостил в Лондоне. +Теперь мы ожидаем союзные войска в Москве! +Мы ожидаем вас, чтобы под звуки торжественных маршей и нашего гимна вместе войти в Кремль вместе испытать всю радость мира и свободы ! +За великую, единую и неделимую Россию! +Ура! +Господа! +Господа, гимн! +По врагам революции огонь +Станичники, что же вы ? +! +Братцы , куда же вы ? +Стой! +За власть Советов вперед! +Вставай, проклятьем заклейменный, +Весь мир голодных и рабов! +Кипит наш разум возмущенный... +Ну что? +Без погон приехал? +Иди, поручкайся с братом. +Тоже вчера прибег. +Матерю порадуйте. +Жена вон, ребятишки истосковались +Да, вот какое дело... +Григорий! +Григорий Пантелеевич, что ж ты , как сурок, на пече лежишь +Слазь +Пропали мы , батя! +Чадушка моя. +Жалкий ты мой... +Молочка кислого положить +Как же ты думаешь +Отступать значит? +А то как же? +ОФицеров-то они не милуют. +Может, вы думаете оставаться, а я уж... +Не уж, я поеду. +А дом как же? +Зто что ж, знатца, вы уедете, а мы должны оставаться? +Добро будем оберегать +Через него, может, жизни лишишься! +Да сгори оно ясным огнем! +Не останусь я. +Ежели хутор миром тронется, и мы не останемся. +Пеши уйдем. +Дуры ! +Сучки! +Цытьте, окаянные! +Мущинское дело, а они равняются. +Ну давайте все бросим и пойдем куда глаза глядят. +А скотину куда денем? +За пазуху покладем? +А курень +Скотину можно с собой угнать +Угоним! +Старая корова починает. +Докель ты ее угонишь +Бездомовщина! +Ух, ты , поганка! +А овец? +Ягнят куды денешь +Наживал им, наживал, и вот что припало услыхать +Ну вот, слава Богу. +Погутарили. +Нашли время скалиться. +А человек с Большого Громка сказывал, что красные к Вёшкам подходят. +Зто что ж зто? +А вот! +Совсем никуды не пойдем. +Ехать — так всем, а не ехать — так никому. +Ну, коли так — остаемся. +Укрой и оборони нас, Царица Небесная. +Да надел я. +Сипилин Иван Авдеевич. +Пущал пропаганды против советской власти. +Правильно. +Здорово живешь +Проходи. +Жалься. +А я не жалиться. +Побрехать зашел да кстати сказать чтобы в обывательские не назначали. +Кони у нас в ножной. +А быки? +На быках какая ж езда? +Сколизь +Замерз, замерз, ребятки. +Григорий, здравствуй. +Здорово. +Ну, повидал я председателя. +Вхожу в кабинет, а он за руку со мной: " Садитесь товарищ" . +Зто окружной. +А раньше как было? +Генерал-майор! +Как перед ним стоять надо было? +Вот она, власть наша, любушка. +Все ровные. +Чему ж ты возрадовался? +Как чему? +Человека во мне увидали, как же мне не радоваться? +За что ж тогда воевали? +За генералов? +— Ты за что воевал? +— Я за себя воевал. +Мне ни те, ни знти не по совести. +Чем ты зту власть корить будешь +А чего ты за нее распинаешься? +Ну ты ... зтой власти дюже не касайся. +Потому — я председатель и мне тут с тобой негоже спорить +А власть твоя, — уж ты как хочешь — а поганая власть +Чего она дает казакам? +Каким казакам? +Казаки тоже разные. +Всем. +Земли дает? +Волю? +Равняет? +Земли у нас — хоть заглонись ею. +Воли боле не надо, а то зачнут на улице друг дружку резать +Атаманов сами выбирали, а теперь сажаете. +Твои слова — контра! +И ты меня на свою борозду не своротишь +Ты Советской власти враг! +Бывайте. +Коршунов. +Кашулин. +Синилин пущал... +Чего пущал? +Пропаганды против советской власти. +— Председателя мне нужно. +— Я председатель +Осип Давыдович! +Вдарь меня, сукиного сына. +Не верю я своим глазам! +Знал, что ежели жив остался, он будет в Татарском председателем. +Миша. +Здравствуйте. +— У вас и сесть не на чем? +— Садись в креслу. +— Моховское? +— Да. +Откель же ты взялся? +Откель я взялся? +С политотделом армии. +Вместе с революцией к вам пришел. +Очень братки, все просто. +Да... все очень просто... +Все очень просто... +Что ж, в общем, все правильно. +Только не все тут у вас. +Вот, скажем, Мелеховы где? +Мелеховы ? +Да, Мелеховы . +Зто я не с Григорием сейчас в дверях столкнулся? +Да был он тут. +Пожалели? +Пожалели. +А он, думаете, вас пожалеет? +Ты о Подтелкове помнишь +Обстановку знаешь фронт в полутораста верстах. +Если сейчас не взять наиболее активных врагов, снова вспыхнет восстание. +Казакам 300 лет дурманили голову. +Основная масса казачества настроена против нас враждебно. +Вот какова обстановка. +"Революцию в перчатках не делают" , — говорил Ленин. +К ночи можно будет взять Мелехова. +— Почему к ночи? +— Меньше разговоров. +Ну знаешь ли, зто... +Ерунда зто. +Зтих отправь +Зараз Мелехова доставлю. +Доставишь +Нет, брат, ищи теперь ветра в поле. +Здорово живете. +Успели. +Ну ладно. +Ничего, давайте разберемся. +Можно я скажу? +Бузуй! +Только товарищ Штокман, скажите, могу я гутарить так, как хочу? +— Говори. +— А вы меня не заарестуете? +Говори. +Мы так промеж себя судим: +что хотят коммунисты нас изничтожить +Смотри, не попадись на книжку. +А я как пьяный: у меня что на уме, то и на языке. +Хотят изничтожить чтобы на Дону казачьего духу не было. +Теперь не скажешь что расстрелов больше не будет! +— Коммунисты ... +— Чего опять коммунисты ? +Коммунисты хотят одного. +Чтобы перестала литься кровь и казачья , и не казачья . +Но пока лютуют наши враги, мы не говорим, что расстрелов, дескать не будет. +Теперь посмотрим, за что же были расстреляны наши хуторные враги Советской власти. +Коршунов... +Ну, его вы все знаете. +Атаманил, на чужом горбу катался. +Вот-вот. +Кашулин Андрей Матвеевич участвовал в расстреле красных казаков Подтелкова. +Бодовсков федот НикиФорович, то же самое. +Мелехов Григорий Пантелеевич, подъесаул, настроенный враждебно против советской власти. +Правда, Мелехова нам взять не удалось +Богатырев. +Ну, ему вы все цену знаете. +Кошевой, вы тут митингуете, а по хуторам томаха идет. +То ли белые, то ли еще кто. +Со станицей связь прервана. +Так в чем же дело, товарищи? +Осип Давыдович, со станицей связь прервана. +Не то белые, не то ишо что. +Со станицей связь прервана. +Скачи в Кашинскую. +Ступай, живо! +Бей его, ребята! +Бей гадину! +Ты что? +Стойте! +Пустите, люди добрые! +Дайте я над ним сердце отведу! +Антип, в отца жизню не вдуешь а человека загубишь +Братцы , на складе сахар делют, туды и ступайте. +Кто там? +— Кто? +— Откройте, мама. +Господи... +Уходи! +Ради Христа уходи, Мишенька. +Вечор казаки весь баз перерыли, тебя искали. +Антипка Брех плетью меня секнул. +"Скрываешь — говорит, — жалко, что его, заразу, не убили" . +Уходи! +Найдут тебя тут... +Господи, спаси и помилуй... +Здорово, сосед. +Ты что ж дома сидишь +Аль навоевался? +Воевать не пойду. +Берите коня, что хотите со мной делайте, а я винтовку брать не хочу. +— Как зто не хочешь — А так, не хочу — и все. +А ежели красные заберут хутор, с нами пойдешь или останешься? +Там видно будет. +А коли так, бери его, Христан. +Мы тебя зараз к стенке прислоним. +А ну пошли! +— Братцы ! +— Мы тебе не братцы ! +Пустите, я запишусь в сотню. +Слабый я от тиФу. +Давно бы так. +Иди бери винтовку. +Сотня! +Слезай! +Коней в укрытие. +Братуха! +Патроны приберегайте. +Бить когда дам команду. +Вот что, отведи свою сотню влево. +Никак батарею устанавливают на Матвеевом кургане. +Да. +Позиция мне не по душе. +Надо бы минуть зти яры . +А то обойдут с Фланга, беды не оберешься. +Чего ты , как зто нас обойдут? +Не, яры - не помеха. +— Гляди, парень — Ну, с Богом. +Сотня, за мной! +Зй ты , генерал Платов, прикажи донцам по чарке водки. +Молчи, водошник. +Отсекут тебе красные другую руку, чем до рта донесешь +Из корыта придется хлебать +А и выпил бы , недорого отдал. +Ушли. +По коням! +Через яр! +Братцы , в яр! +Степка Астахов за хвост своего коня поймал, ускакал. +А мне вот не пришлось Видит Бог, пропали, братцы . +Вот они. +Зй, вы ! +Вылазьте! +Все равно перебьем. +Петро Мелехов! +Вылазь +Говорит Михаил Кошевой. +Предлагаем сдаться добром. +Все равно не уйдете. +Вправо! +Прямо! +Орудие вперед! +Пулемет на тачанку! +Навоевался? +Ты командовал ими? +Раздевайся. +Живее ты ! +Ладно, хватит. +Кум... кум Иван, ты ж мое дите крестил. +Кум, не казните меня. +Гляди! +Гляди! +Гляди, что твой наделал! +Изничтожить бы семя ваше! +Ой, Петюшка... +Ой, Петюшка... +Ой, родимый! +Встань .. +Отойди. +Сынок... чадунюшка... +Да за что же они меня? +За что? +Что я им сделала? +А вы чего выпятились Али вам тут место? +Всех! +Всех на Фронт! +Там вас нету! +На конь +Лети, пташка канарейка, +Лети в горы высоко, +Пропой песню про войну, +Про несчастье про мое... +Григорий Пантелеевич, ты — гордость наша, не дай нас в страту. +Опять нами генералы владеют, всю власть к рукам забрали. +Какую ишо власть +На-ка, пей лучше. +Давайте Советской власти поклонимся: виноваты , мол. +Я шучу. +Пей, Христан. +Чего шутить Тут дело сурьезное. +Хучь Кудинова, хучь генералов, всех сместим, а тебя поставим. +Я говорю, всех сместим, а его посадим. +Верно? +Уйдут — хорошо, а нет, так двинем полки на Вёшки. +Да нету боле об зтом разговору. +Самогонка есть +— А поздороваться не надо? +— Здорово, хозяюшка! +— И сколько ж вас еще? +— А вся дивизия! +Григорий Пантелеевич, сокол ты наш, выпьем... +Будя вам его поить Не видишь он негожий никуды . +Ты зараз с ним не ходи, толку не будет. +Черт бессовестный, залил зенки и несешь неподобное. +— Может, взвару налить — Зачерпни. +Григорий Пантелеевич! +Слушай сюда! +Первую сотню поведу сам! +Шашки вон! +В атаку, братцы , за мной! +Мало тебе? +Мало? +Убью ! +Григорий Пантелеевич, опомнитесь +Уйди! +Уйди! +Успокойся. +Опомнись Григорий Пантелеевич! +Кого же рубил! +Братцы ! +Нету мне прощения! +Зарубите меня! +Смерти предайте! +Видать навоевался досыта. +Как очумеется, сажай на коня и вези до дома. +— Молочка налить — Ты лучше раненым оставь +— Здешняя? +— Здешняя. +Осип Давыдович. +Ничего, ничего. +Зто мы ишо поглядим, чья переважит. +— Чего же ты молчишь — А об чем гутарить с тобой? +Рассказал бы , как пьянствовал, как с жалмерками вязался. +А ты уж знаешь +Весь хутор знает. +Есть от кого услыхать +А коли знаешь чего расспрашиваешь +— Опять за старое берешься? +— Оставь Наталья . +Кобелина проклятый, ненаедный! +За что ж ты меня опять мучаешь +Дети вон уж у тебя какие! +Как гляделками не совестно моргать +Ты бы поменее брехни слухала. +Ну, трошки виноват перед тобой. +Она, жизнь Наташка, виноватит. +Все время на краю смерти ходишь ну и перелезешь иной раз через борозду. +Я вот и к водке потянулся. +Надысь припадком меня вдарило. +Неправильный у жизни ход, и, может, и я в зтом виноватый. +Зараз бы надо с красными замириться и на кадетов. +А как? +Кто нас теперь сведет с Советской властью ? +Все у меня, Наташка, перемутилося в голове. +Уж ты бы мне зубы не заговаривал. +Напаскудил, теперь на войну сворачиваешь +Мало через тебя, черта, я лиха приняла? +Жалко что тогда не до смерти зарезалась +Может, подсобить в чем, Гришенька? +Да нечего подсоблять +Ах, Григорий Пантелеевич, до чего вы со мной, вдовой, строгие. +Не улыбнетесь и даже плечиком не ворохнете. +— Шла бы стряпаться, зубоскалая. +— Ах, какая надобность +Наталье подсоби. +Мишатка бегает грязней грязи. +Ишо чего недоставало! +Вы их будете родить а мне замывать +Наталья как трусиха плодющая. +Она их тебе нашибает еще штук 1 0. +Зтак я от рук отстану, обмываючи всех их. +Ступай. +Григорий Пантелеевич! +Вы зараз в хуторе один казак на всех. +Не прогоните, дайте хучь издаля поглядеть на ваши черные завлекательные усы . +Ну и ухо ты ! +Как с тобой Петро жил? +У тебя не сорвется. +Зто уж будьте покойны . +Слышь Гришка, а мне бабы молодые гутарют: +"Что зто за права? +Казаков нету, а Гришка приехал и от жены не отходит. +Хучь от него и половинка супротив прежнего осталась а мы за зту половинку подержались бы с нашим удовольствием" . +Я им говорю: " Нет, бабочки. +Гриша наш только на чужих хуторах на короткую ножку прихрамывает. +А дома он за Натальин подол держится без отступу. +Он у нас с недавней поры святой стал" . +Ну и сука ты ! +Язык у тебя — чистое помело. +Уж какая есть +А попадись мне, я бы такого храброго, как ты , в страх привела. +Здравствуй, Аксинья дорогая. +Здравствуй. +Давно мы с тобой не видались +Давно. +Я уж и голос твой позабыл. +— Скоро. +— Скоро ли? +Неужели нам с тобой и погутарить не об чем? +Чего ж ты молчишь +Видно, мы свое отгутарили. +Ой ли? +Да так уж, должно быть Деревце один раз в году цветет. +Думаешь и наше отцвело? +А то нет? +Чудно все как-то. +А я, Ксюша, все тебя от сердца оторвать не могу. +И дети у меня большие, и сам наполовину седой, +а все думается о тебе. +Во сне тебя вижу и люблю доныне. +— А начну вспоминать .. +— Я тоже... +Мне тоже надо идтить Загутарились мы . +А ить наша любовь у зтих мостков и зачиналась +— Помнишь — Все помню! +— Даша. +— Кто зто? +Зто я, Аксинья . +Подойди на-час. +— Чего зто я тебе понадобилась — Дюже нужна. +Чего зто? +Никак, кольцо? +— Мне, что ли? +— Тебе. +От меня в память +Золотое. +Носи. +Ну, спаси Христос. +Чего нужно, за что даришь +Вызови мне... +вызови Григория вашего. +Опять что ли? +Мне с ним погутарить надо, может он Степану бы отпуск исхлопотал. +— А чего ж к нам не зашла? +— Наталья могет подумать .. +Ну ладно, вызову. +Мне его не жалко. +Кто? +— Здорово. +Кошевой дома? +— В чем дело? +Беда. +Сердобский полк восстал. +Пехота разоружила батарею. +А зараз возле церкви митинг. +— А Кошевой где? +— Уехал в Усть-Медведицкую. +Я еще вчера по разговорам понял, куда клонят. +Собирайся. +— А где остальные коммунисты ? +— Кто их знает. +— Коммунисты , на митинг. +— Идем. +Оружие можно оставить Не в бой идете. +Слава рядовому бойцу! +Молчать +Молчать +Молчать +Красноармейцы ! +Позор вам! +Вы предаете власть народа! +В самый тяжелый момент! +Вас продали казачьим генералам! +Ваши командиры — изменники! +Брехня! +Опомнитесь +Вашей рукой хотят задушить рабоче-крестьянскую власть +Не смей! +Не смей. +Убить всегда успеешь +Слава бойцу-коммунисту! +Вы можете меня убить .. +Дайте сказать +Дайте сказать +Вы можете меня убить но я повторяю вам - опомнитесь +Ваш командир полка... +Осип Давыдович! +Вас... ввели... в заблуждение. +Но коммунизм... все равно... +Смерть Смерть коммунистам! +Врагам трудового крестьянства! +Бей их! +Гонят! +Ведут! +Ведут пленных! +Врагов гонят. +Иван Алексеевич гляди-ка какой... +Гляди, Котлярова гонят. +Вижу. +Бессовестными глазами глядит. +Довольно, хватит им. +Нагулялись +Земельки захотели, а? +Вашего хуторца пригнали. +Покрасуйтесь на него, на сукиного сына. +А другой-то, Кошевой Мишка, где? +Один ваш хуторец. +Да по куску на человека и знтого хватит растянуть +Ну-ка, сосед. +— Здорово, кум. +— Здорово, кума Дарья . +А расскажи-ка, родненький куманек, как ты кума своего, моего мужа Петра Пантелеевича убивал-казнил. +Нет, кума Дарья . +Не казнил я его. +Как зто не казнил? +Ить зто же вы с Мишкой Кошевым казаков убивали. +Был я в том бою. +Был! +Дашка, что ты ? +! +Своих побьешь +Ах ты , сука. +На какую-то веревку заперлись +Дома-то есть кто? +Чего зто ты ? +Мать Наталья где? +Да чего у вас тут? +Пленных давно прогнали? +Побили их. +Ой, Гриша! +Дашка наша, стерва проклятая, сама Ивана Алексеевича стрельнула! +Чего ты брешешь А Штокман? +Кошевой? +Не было их с пленными. +А маманя забоялась с Наташкой в хате спать к соседям ушла. +А Дашка откель-то пьяная пришла, пьянее грязи. +Зараз около амбара спит. +Гадюка! +Здравствуйте, господа старики! +Здравия желаем, ваше превосходительство! +Милости просим принять хлеб-соль от казачества. +Благодарю вас. +Прошу. +Вы видите, на хуторе остались только старики, бабы и мальчишки, которые не могут носить оружия. +Начинайте. +Все казаки сражаются на разных Фронтах за наше общее дело. +Мелехова Дарья ТимоФеевна! +— Мелехова! +— Тута я! +Что? +А, да... +Вы - вдова убитого хорунжего Мелехова? +Да. +Сейчас вы получите деньги, 500 рублей. +Правительство Дона благодарит вас за выказанное вами высокое мужество и просит принять сочувствие. +Мне можно идти? +Да-да, разумеется. +Мы награждаем женщин, проявивших в боях с большевиками большое мужество. +Первая из награжденных мною — жена оФицера — сама убила прославившегося жестокостью комиссара. +Господи! +За что зто тебе? +За кума Ивана Алексеевича, Царство небесное сукину сыну. +А знто... за Петю. +— Куды тебе их? +— Чего куды ? +— Деньги куды денешь — Куды хочу, туды и дену. +Зто, маманя, Петю поминать +Вселенскую панихиду закажите, кутьи наварите. +А мне бы теперича ишо крестов нахватать и сейчас в генералы ! +ОФицеры -то все на Фронте, а кто будет стариков обучать маршировке? +Вот их и предоставят под мою команду, а я уж с ними, со старыми чертями, управлюсь +Вот как я буду ими командовать +Старики, смирно! +Бороды поднять выше! +Кругом, налево шагай! +И пошли мои старички. +Ать-два, ать-два. +Не балуйся. +Подуй. +Ой, Господи... +Чего зто ты ? +Ну, будя, будя... +Скоро помру я, Натаха. +Да полно тебе, чего мелешь +Ты меня шибко не целуй. +Почему? +Заразная я. +Доигралась .. +Да ты не боись так-то уж не пристанет. +Вот что, Натаха, хочу повиниться перед тобой. +Мне ить так и так не жить +Чье колечко? +Да ты погоди обмирать-то. +Кольцо-то знаешь чье ? +Да, соседки Аксиньи . +А за что она мне его подарила, ну-ка, прикинь +За то, что Гришу к ней вызывала. +— А ты и не догадывалась — Догадывалась +А догадывалась чего ж ты у него не допыталась +Хочешь я у Аксиньи все допытаю? +Она мне все дочиста расскажет. +Не хочу я твоей услуги. +Ить не из жалости ты призналась что сводничала, а чтобы мне тяжельше было. +Верно. +Рассуди сама, не мне ж одной страдать +А ты своего дюже любишь +Как умею. +Значит, дюже. +А мне вот не приходилось +Мне бы теперича сызнова жизню начать .. +Могеть и я бы другой была? +Примечаю я за тобой, опять ты не такая стала. +Аль с Гришкой у вас что получилось +Он, маманя, опять с Аксиньей живет. +Зто... зто откуда ж известно? +Верно, маманя, чего уж там... +Не доглядела ты за ним. +С такого муженька глаз не надо сводить +Чего ж его, к юбке привязывать +Наполовину седой стал, а старое не забывает. +Зто и вся беда? +Какая вы , маманя... +И чего ж ты надумала? +А чего ж окромя надумаешь +Заберу детей и уйду к своим. +Больше жить с ним не буду. +Смолоду и я так думала. +Мой-то тоже был кобель не из последних. +Куды прийдешь Кому ты нужна? +Да ишо детишек от отца забирать Как зто? +Ишо сама тяжелая, третьего ждешь +Нет, не велю и слухать не буду. +Нет, маманя, жить я с ним боле не буду. +И родить от него боле не буду. +И поворачивается у тебя язык, у бессовестной? +Ну хватит. +Всех слез не вычерпаешь оставь и для другого раза. +Господи! +Всю душень он мою вымотал! +Нету боле мочи так жить Господи, покарай его! +Срази его там насмерть чтобы боле не жил он, не мучил меня! +— Опамятуйся! +— Господи, покарай, накажи! +Становись на колени. +Слышишь Наташка? +! +Проси у Бога прощения. +Проси, чтобы не принял Он молитву. +Кому ты смерти просишь Родному отцу своих детей. +Ох, великий грех... +Крестись Кланяйся в землю. +Говори: " Господи, прости мне, окаянной, мои прегрешения" . +Зн-ци-кло-пе-ди... +Знциклопедия. +Стой. +А вот тута? +Поваренная книга. +Где Наталья ? +— Что? +— Наталья где? +Собрала узелок и ушла. +— Когда? +— Утром. +А чего она гутарила? +Какой узелок? +Да почем я знаю? +Взяла чистую юбку, еще что-то и ушла, ничего не сказала. +Головушка горькая... +Беда-то какая... +Беда-то какая! +Бати нету? +Что же ты с собою сделала? +! +Не шумите, маманя. +Мне бы лечь +Ничего, ничего... +Горе ты мое... +Чего стоишь Постель готовь +Сымите чистую одежу, постелите чего похуже. +Молчи, молчи. +Уйди и не показывайся сюда! +Не дело тебе тут отираться. +Зараз запрягай, езжай в станицу за Фершалом. +Выдумаешь чертовщину. +Чего еще поделалось +Наталья ... +Ах, паскудница! +Чего надумала, а? +! +Батя, не входи ради Христа. +Наработала, чертова дочь +Одурел, проклятый? +! +Куды ты лезешь +Чего возишься, как жук в навозе? +Наташка помирает, а он возится. +Запрягай, а то сама поеду! +Тю, сдурела! +Тебя еще не слыхали, короста липучая. +Тоже еще, на отца шумит, пакость +Укройте мне ноги шубой. +Как помру я, маманя, наденьте на меня юбку зеленую, знту, какая с прошивкой на оборке. +Гриша любил, как я ее надевала. +Не плачьте, маманя... +Ничего... +Вот ты гутарила, Дашка, что тебе помирать скоро. +Тебе ишо жить да жить +А мой час пришел. +Маманька, ты чего? +Захворала твоя маманька. +Подойди ко мне, жаль моя. +— Мамань ужинать будешь — Не знаю. +Должно быть нет. +Ну тогда я тебе сюда принесу, ладно? +Нагнись Мишенька. +Истый батя... +Только сердцем не в него... помягче... +Ну-ка, дай. +Григорий Пантелеевич, шибко не гони, не убей коня. +Григорий Пантелеевич! +Пропал конь +Не уберегли... +"Правь Британия, морями!" . +За вашу родину, мистер Кзмпбелл. +Ах, какая зто страна, подъесаул. +Вот вы представить себе не можете, а я жил там. +Выпьем. +Вот мистер Кзмпбелл не верит, что мы справимся с красными. +— Не верит? +— Не верит. +Он плохо отзывается о нашей армии и похваливает красных. +Проклятый коньяк. +Крепок, как спирт. +Немногим слабее. +А вы мне нравитесь подъесаул. +Ну что вы такой грустный? +Что случилось подъесаул? +У меня недавно жена померла. +Да, зто ужасно. +А почему он красных уважает? +Уважает? +А кто сказал " уважает" ? +Вы сказали. +Не может быть +Он не может их уважать Я сейчас спрошу у него. +— Чего он болтает? +— Сейчас. +Он видел, как они в пешем строю, обутые в лапти, шли в атаку на танки. +И зтого довольно. +Он говорит, что народ нельзя победить +Дурак. +Вы ему не верьте. +— Как не верить — Вообще не верьте. +— Зто как? +— Надрался и болтает ерунду. +Почему зто народ нельзя победить +Часть его можно... уничтожить +А остальных привести в исполнение. +Как я сказал? +Исполнение? +Нет, в повиновение. +Знаешь что я тебе скажу? +Езжай-ка ты поскорее домой. +Пока тебе здесь голову не свернули. +В наши дела вам незачем мешаться. +Езжай, пожалуйста, а то тебе здесь накостыляют. +— Слышишь бабка, музыку-то? +— Какую музыку-то? +А вот что на одних басах играет. +Слыхать слышу, да не пойму, что зто такое. +Скоро поймешь Зто из орудиев бьют. +У наших стариков потроха вынают. +Как встанет Дон, погонят нас красные до самого моря. +— Зто куды ж? +— На Дон, искупаться. +Какое ишо нынче купание? +Ничего, маманя. +О, Господи... +Поди погуляй на баз. +На улицу не ходи, а то стопчут. +Мишатка, поди сюды . +Родный мой! +Ой, Григорьевич! +Хороший мой! +Как же я по тебе соскучилась .. +Дура твоя тетка Аксинья . +Ой, какая дура! +— Не гляди на меня. +— Чего зто? +Не гляди, не люблю. +Зто с каких пор? +С таких. +Ладно, пойду так. +— Здорово, Машутка. +— Здорово. +Прощай, Дуняха! +Ты чего, Дашка? +Вылазь +Дарья ! +Дашка утопла! +Дашка утопла! +Дашка утопла! +Батю давно на Фронт забрали? +Недавно. +Он было упрятался, да Митька Коршунов доказал. +Вот какие ноне свояки пошли. +— Какой он нам свояк? +— Зверь чистый зверь +Старуху Кошевую зарубил вместе с ребятами. +Зто Мишке отомстил? +И никто не вступился? +Кто ж заступится-то? +У каждого свое. +Меня не было. +Ох и постарел ты , братуха. +Серый какой-то стал, как бирюк. +Мне так и полагается. +Мне — стареть тебе — в пору входить жениха искать +Только вот чего я тебе скажу. +О Мишке Кошевом и думать позабудь +Ты не гляди, что я его старуху пожалел. +Зто одно к одному не касается. +Услышу, что ты об нем сохнуть будешь на одну ногу наступлю, за другую возьмусь и раздеру. +— Ехать когда думаешь — Завтра. +Я вот что... +Я думаю Аксинью Астахову взять с собой. +Супротив ничего не имеешь +А мне-то что? +Бери хучь двух Аксиньев. +Коням будет тяжеловато. +На холеру она тебе сдалась +Зто тебя не касается. +Ну, война кончилась +Пихнули нас красные так, что до самого моря будем пятиться покуда не упремся задницей в соленую воду. +Чего оскаляешься-то? +Невеста, да и только. +Рада, что с хутора вырвалась +А то, думаешь не рада? +Нашла радость Глупая ты баба. +Ишо не видно, чем зта прогулка кончится. +Мне хуже не будет. +Молчала бы . +Муж-то где? +Схватилась с чужим дядей и едешь черт-те куда. +А ежели зараз Степан на хутор заявится, тогда как? +Знаешь чего, Проша, ты бы в наши дела не путался, а то и тебе счастья не будет. +Да не ругайтесь вы по-первам. +Дорога дальняя, ишо успеете. +— Гриша! +— Тут я, тут. +Ну, тут я, Ксюша. +Гриша... +Беда, Гриша. +Гриша... +Тут я. +Тут я, Ксюша. +Закрывайте дверь плотнее. +— Зто жена ихняя будет? +— Жена. +И дети есть +И дети есть все есть одной удачи нам нету. +Слухай, друг, пособи моей беде ради Христа. +Везти дале ее нельзя, помрет. +Дозволь оставить ее у вас. +За догляд заплачу сколько положите. +Само собой. +Даром кто будет за ней уход несть +Тут такое дело, сам не знаешь как управиться. +Не откажи, сделай милость Век буду помнить ваши заботы . +Ну а сколько бы вы положили за уход? +Сколько вам будет не жалко? +Все, какие есть +И что зто за деньги? +Николаевских у вас нету? +Нету. +Может, керенки есть +— Зти уж больно ненадежные. +— Керенок нету. +Хошь коня своего оставлю? +— Бери. +— Бери... +Не белые, так красные все одно заберут, пользы никакой. +Чего? +Чего? +На. +Задавись +Ладно, сделаем уважение. +Когда воевали — нужны были, а зараз мы им ни к чему. +Ну их к черту, пойдем отсюда. +Давай подадимся до ТиФлиса, а оттуда к туркам. +Надо ж как-то спасаться. +Чего ты , как рыба, снулый? +Нет, не поеду. +Не к чему. +Да и поздновато трошки. +Гляди. +Красные. +Здравствуй, соседушка. +Долго ж ты пропадала в чужих краях. +Ты чего воззрилась на меня и молчишь +Аль плохие вести принесла? +Григорий-то... +Он когда оставил тебя, не хворый поехал? +Нет, он не хворал. +И на том спасибо. +Не может быть чтобы лишилась я последнего сына. +Не за что Богу меня наказывать +Вы не печалуйтесь об нем, бабушка. +Разве такого хворость одолеет? +Да он крепкий, прямо как железный. +Такие не помирают. +О детишках не вспоминал? +И о вас и о детишках вспоминал. +Здоровые они? +Чего им подеется. +А Пантелей ПрокоФьевич помер в отступе. +Остались мы одни. +Ну, прощай. +Обживешься — зайди к нам, проведай. +Может, узнаешь что про Григория — скажи. +Хорошо, бабушка. +Здорово, тетка Ильинична. +Не ждала? +Здорово. +А ты кто такой мне, чтобы я тебя ждала? +Нашему забору двоюродный плетень +— Как-никак, знакомы были. +— Только и всего. +— Я ить не жить к вам пришел. +— Зтого ишо недоставало. +А Евдокия Пантелеевна где ж? +Прибирается. +Больно ранний ты гость добрые люди спозаранок не ходят. +Соскучился, вот и пришел. +Чего уж тут время выбирать +Ох, Михаил, не гневил бы ты меня. +Чем же я вас, тетенька, гневлю? +Как у тебя совести хватает приходить к нам, бесстыжий? +И ты ишо спрашиваешь ! +Кто Петра убил? +Не ты ? +Ну, я. +Опосля зтого кто ж ты есть +И ты идешь к нам, садишься, будто... +— Ну, здравствуй. +— Здравствуй. +Ступай воды принеси. +Как только твои глаза на меня глядят? +Не с чего моим глазам зажмуряться. +А ежели б Петро меня поймал, чего бы он сделал? +Он ведь тоже меня убил бы . +Не для того мы на знтих буграх сходились чтобы нянькаться один с другим. +На то она есть война. +Враг он есть враг, а на врага у меня рука твердая. +Через зту твердость ты и прожелтел весь +Совесть небось точит. +Какая совесть Лихоманка меня замучила. +— А то бы я их, мамаша... +— Какая я тебе мамаша? +Душегуб! +Уходи отсель +Уходи! +Зрить я тебя не могу. +А Митька Коршунов, свояк ваш, не душегуб? +А Григорий кто ж? +Про сынка-то вы молчите. +А уж он-то душегуб настоящий, без подмесу. +Траву в лугу косить думаете? +Люди уж поехали за Дон. +Нам и переехать не на чем. +Баркас с осени стоит, рассохся. +Надо бы спустить его на воду. +А кто ж его спустит? +А конопи-то есть у вас? +Должно, остались ишо. +Пойду погляжу. +— А, тезка, здорово. +— Здорово. +Чего ты будешь делать +Чего я буду делать Баркас вам наладить надо. +А грабельки маленькие сделаешь +Сделаю. +Ты чего? +Михайло Григорьевич, тезка, принеси дерюжку, я ляжу. +Бабаня! +Бабаня! +Дядя Михаил лег под сараем и так дрожит, ажник подсигивает. +Ты чего молчишь бабаня? +Снеси ему, антихристу, одеяло, нехай накроется. +Лихоманка его бьет. +— Донесешь — Донесу. +Постой! +Не неси. +Дуня! +— Прохор Зыков вернулся. +— Да что ты ? +! +Раненый. +Я побегу, может, чего скажет про Григория. +Здорово, односумка! +Не чаял живой тебя увидать +Здравствуй, Проша. +Ну как он, тиФок, прихорашивает вашего брата? +Ну проходи, садись Гостем будешь +Погутарим, покуда моей бабы нету. +Я ее за самогонкой снарядил. +А меня видишь как шляхи обработали, в рот им дышло! +Ты бы сказал... +Знаю, скажу. +Вот так велел кланяться. +Чего ж ты кричишь глупая? +Вот бабы ! +Убьют — кричат, живой остался — опять кричат. +Да утрись Говорю тебе, живой, здоровый, морду во какую наел. +Мы с ним в Новороссийске поступили в Конную армию товарища Буденного. +Ладно. +Принял Григорий Пантелеевич сотню. +Зскадрон. +Я при нем состою. +И прямиком на Киев. +Что ж он, может, в отпуск... +И думать не моги. +Говорит, буду служить до тех пор, пока прошлые грехи замолю. +Из боя не выходит. +Благодарность ему была. +Вот он какие котелки выкидывает, твой Пантелеевич. +Садись чай пить будем. +Да нет, я... +Ну беги, звони по хутору. +Чегой-то вы , маманя? +А зто я, Дуняшка... +Зто... войдешь с база, глянешь легче делается. +Как будто он уже с нами. +Маманя, благословите меня за Михаила. +Опять ты ! +Нету тебе моего благословения. +Не отдам тебя за него. +Тогда я уйду. +Опамятуйся ты ! +Что ж я одна с детишками буду делать +Пропадать нам? +Как знаете, маманя, а я все одно уйду. +На хуторе гутарят: +"Аль наняли Михаила в работники?" +Зтой иконой меня покойница мать благословила. +Ну, свое все вынула? +То-то... +Мое не захвати. +Чего зто вы смертное приготовили? +Рано вам ишо о смерти думать Господь с вами. +Нет... пора мне. +Детишек береги, соблюдай, пока Гриша возвернется. +А я уж, видно, не дождусь +Ну а к чему идтить в церковь +— Аль нельзя так? +— Нет, Миша, не проси. +Маманя и так благословила со слезьми. +Нельзя так. +Ох, девка... +И чего мне с тобой делать +Гришенька! +Родненький мой! +Кровинушка моя! +Помирать собралась маманя. +Чего тебе? +Ну, старик, получай вольную. +Переизбрали тебя. +Меня назначили. +— Слава тебе, Господи. +— Сдавай дела. +Вот тебе, соколик ты мой, бумажки. +Вот тебе ишо бумажки. +Во! +Бумажки. +А вот тебе... +Во! +Хуторская печать +Забери ради Христа все зто. +А мне куды уж? +Восьмой десяток живу, мне с Богом пора беседовать а меня председателем назначили. +— Секретарь где? +— Ась +— Секретарь говорю, где? +— В поле жито сеет. +С Егорьего дня глаз не кажет. +Придет бумага какая важная, а его с собаками не сыщешь +Я-то с трудом расписываюсь а читать и вовсе не могу. +Печать становить могу. +Вот и все хуторское хозяйство. +Денежных суммов нету. +А атаманской насеки при Советской власти не полагается. +Вот коли хочешь могу тебе свой костыль отдать +Ну, дед, будем считать что дела от тебя я принял. +Теперь катись отседова к едреной бабушке. +— Куды ? +— Домой иди! +А, ну ладно. +Я тебя сразу признал. +Кошевого, покойника, сын? +— Он самый. +— Ну, будь здоров. +Ступай, ступай. +— Чего зто ты ? +— Гриша приехал. +С радостью тебя. +— Ну, здравствуй, Миша. +— Здравствуй, здравствуй. +Давно мы с тобой не видались Будто сто лет прошло. +Да, давненько. +С прибытием тебя. +Спасибо. +Породнились значит? +Пришлось Чего зто у тебя кровь на щеке? +Бритвой порезался, спешил. +Ты чего? +Хочу позвать кого-нибудь валушка зарезать +Надо хозяина встретить как полагается. +Скажи Прохору Зыкову, чтобы в землю зарылся, а достал самогонки. +Он в знтом деле лучше тебя разберется. +Покличь его вечерять +Ну... хозяйка? +Григорий Пантелеевич! +Григорий Пантелеевич! +Милушка ты мой! +Вот и не чаял, и не думал дождаться. +— Совсем пришел? +— Совсем, вчистую. +До какого ж чина дослужился? +Был помощником командира полка. +Чего ж так скоро тебя отпустили? +Не нужен стал. +Через чего ж зто? +Не знаю, должно, за прошлое. +А Михаил где? +На базу. +Платона Рябчикова с месяц назад расстреляли. +— Что ты говоришь — Истинный Бог. +Потом погутарим. +Что ж, товарищ командир, выпьем! +Заходи, Ксюша. +Садись гостем будешь +Здравствуйте. +Здравствуй, Ксюша. +Садись +Односумка! +Ксюша! +Вместе отступали, вместе вшей кормили. +Выпей за здоровье Григория Пантелеевича. +Ты его не слухай, он уж набрался. +С приездом вас, Григорий Пантелеевич. +А тебя, Дуняшка, с радостью . +А тебя с чем? +С горем? +И меня с радостью . +С великой! +Тяни ее всю до капельки, ради Христа. +Умеешь сказать прямо, умей и пить прямо. +Мне нож вострый в сердце, когда остается. +Ты , Михаил, в зтом деле хуже, чем телок. +А я в напитках толк знаю. +Вот есть такое вино — не успеешь пробку вынуть а оттуда пена идет, как из бешеной собаки. +Я в ту ночь до трех раз с коня падал, как ветром сдувало. +Такое вино бы натощак по стакану. +Ну, как ты ? +Ох, всего не перескажешь +— Придешь — Приду. +Кувшин с собой не возьму. +Душа не дозволяет ходить с порожней посудой. +Зараз приду, жена зачнет меня казнить +Ты до дому-то дойдешь +Раком, а доползу. +Али я не казак, Пантелеевич? +Даже очень обидно слухать +Стой. +Что ж, потолкуем, Михаил? +Давай. +Что-то у нас не так. +Не по душе тебе мой приезд, так, что ли? +Так. +Не по душе. +— Почему? +— Лишняя забота. +Я думаю сам прокормиться. +Я не об зтом. +Тогда о чем же? +Враги мы с тобой. +— Были. +— Да, видно, и будем. +Почему? +Много ты наших бойцов загубил. +Через зто не могу так легко на тебя глядеть +Зтого из памяти не выкинешь +Крепкая у тебя память +Ты брата Петра убил, а я тебе что-то об зтом не напоминаю. +Ежели все помнить — волками жить +Поглядел бы я на тебя, как бы ты со мной разговаривал, ежели б зараз кадетская власть была, ежели б вы одолели. +Ремни, небось со спины вырезывал бы . +Зто ты зараз такой добрый. +Может, кто и резал бы ремни, а я поганить руки об тебя не стал бы . +Выходит, разные мы с тобой люди. +Сроду я не стеснялся об врагов руки поганить и зараз не сморгнул бы при нужде. +Пить будешь +Давай, а то дюже трезвые мы стали для такого разговору. +Так чего ж ты , Михаил, боишься, что я буду против Советской власти бунтовать +Ничего я не боюсь а между прочим думаю: +случись какая заварушка, и ты переметнешься на другую сторону. +Никуды я не переметнусь +Я свое отслужил. +Никому боле не хочу служить +Навоевался я за свой век предостаточно. +И уморился душой страшно. +Все мне надоело, и революция, и контрреволюция. +Пропади оно все пропадом. +Хочу пожить возле своих детишек, заняться хозяйством. +Вот и все. +Ну, зто, брат, ишо не все. +Ревтрибунал не будет спрашивать чего ты хочешь +В Вёшенскую когда поедешь на учет? +— Как-нибудь днями. +— Надо ехать завтра. +Денек отдохну. +Не убегу же я. +Черт тебя знает. +Я за тебя отвечать не хочу. +До чего ж ты сволочной стал. +Ты меня не сволочи. +Я к зтому не привык. +Зти, знаешь оФицерские повадки бросать надо. +Отправляйся завтра же, а ежели добром не пойдешь — погоню под конвоем, понятно? +Теперь мне все понятно. +Милый ты мой Гришенька... +Сколько у тебя волос-то седых в голове... +Стареешь стал быть +Каким же ты парнем был! +Дуняшка. +Братушка! +Уходи зараз! +К нам из станицы четверо приехали, говорят, будто тебя арестовать надо. +Спасибо, сестра. +Хлеба скорей! +Да не целый, краюху! +Ступай, а то заметят, что ушла. +Прощай. +Прощай. +Скоро подам вестку, Прохор скажет. +Дверь запри. +Ежели спросят, скажи, ушел в Вёшки. +Ну, прощай. +Гриша... +Стой! +Стой, сукин сын! +Ты кто такой? +Коммунист? +Руки из карманов вынай, а то голову срублю! +— Иди вперед! +— Куда? +Вперед! +Руки за спину заложи! +— А вы кто такие? +— Православные. +Шагай. +Мелехов! +Здравствуйте. +Вот уж воистину степь широкая, а дорога узкая! +Откедова ты взялся-то? +— Здорово. +— Здорово. +Раздевайся, садись +Где же мои ребята тебя сцапали? +Возле хутора. +Куда шел? +А куда глаза глядят. +Думаешь мы тебя словим и в Вёшки повезем? +Нет, брат, нам туда дорога заказаная. +Не робей. +Мы перестали Советской власти служить +Развод взяли. +Думаю все-таки поднять казаков. +Прекрати мотаться. +Я кому сказал? +Слухом пользуемся, кругом война идет, всюду восстания. +И в Сибири, и на Украине, и даже в самом Петрограде. +Весь Флот восстал в крепости... ну, как ее... +В Кронштадте. +Идиот. +Ну, что же надумал? +Говори, да давай ложиться спать +В чего говорить +С нами идешь или как? +Всю жизнь по чужим катухам не прохоронишься. +Вот зто ты верно сказал. +Деваться некуда. +Вступаю в твою банду. +Зто мы банда? +! +Ты зто название брось Почему зто — банда? +Зто название нам коммунисты дали, а тебе его говорить негоже. +Просто восставшие люди. +Коротко и ясно. +Ладно, будя. +Коня тебе своего отдаю. +У меня есть запасной. +Тот, рыжий. +Казаки, на собственной шее вы почувствовали, какие тяготы возложила на хлеборобов советская власть +Вы дойдете до окончательной разрухи, если советскую власть не свергнуть +Здорово! +Вот оно, мое войско! +Черту рога можно сломать с такими ребятами. +Советской власти не жить +А тебе? +Кончай. +Плетешь невесть что. +Станичники! +Учись как надо. +Станичники! +Мы с нынешнего дня освобождаем вас от продразверстки. +Хлеб больше не возите на приемные пункты ! +Пора перестать кормить коммунистов-дармоедов! +Они жир нагуливали на вашем хлебе! +Но зта чужбинка кончилась +Вы — свободные люди! +Вооружайтесь и поддерживайте нашу власть +Казаки, ура! +Твоя власть хорошая, а мыла ты нам привез? +А сами чьим хлебом кормитесь +Небось побегут по дворам побираться. +У них шашки, они курам головы порубят. +Как зто — хлеб не возить +Нынче вы тут, завтра вас не сыщешь а нам отвечать +Не дадим вам наших мужьев! +Воюйте сами. +А кто с ними пойдет? +Не к чему бунтовать +Нужды нет. +Пора подходит убирать а не воевать +Да, а знтот усы распушил, разъезжает на конике, народ мутит. +Учитель нашелся! +Чего молчишь рыжее мурло, аль неправду я гутарю? +Цыц, рябая стерва! +Ты еще тут агитацию разводишь ! +У, зараза большевистская! +Я из тебя дурь выбью ! +Прикажу задрать тебе подол да всыпать шомполов, тогда доразу поумнеешь +А зтого ты не видал, Аника-воин? +Меня? +! +Пороть ! +А в носе у тебя не кругло! +Ишь ты , царь-освободитель +На конь Красные! +Зто ишо мы поглядим! +Я оружие не сложу. +Садитесь вечерять разбойнички. +Я идейный борец против советской власти. +А ты меня обзываешь чер-те по-каковски. +— Правильно обзывает. +— Правильно? +Да ты понимаешь дурак, что я сражаюсь за идею? +Ты мне голову не морочь Тоже нашелся идейный. +Разбойники, и боле ничего. +Какая бы Советская власть ни была, а с 1 91 7 года держится. +И кто супротив нее выступает, тот и есть разбойный человек. +Прекрати жрать +Ты не один пока. +Ишо нас четверо. +А один уйдет, троим боле достанется. +Что? +Ты что? +Бежать +Бежать мне некуда да и не от кого. +А уйтить — все одно уйду и не удержишь +Мелехов, брось +Стрелять буду! +Не будешь побоишься. +Вам тут тихо жить надо. +Здравствуй, Ксюша! +Погоди. +Тихо. +Не отпирай дверь я через окно. +Как же ты ? +.. +Как пришел, где пропадал? +А ежели поймают тебя, Гришенька? +Не бойся, не поймают. +Поедешь со мной? +Куда? +На юг, на Кубань али дальше. +Проживем, прокормимся как-нибудь Никакой работы не погнушаюсь +Моим рукам работать надо, а не воевать Едешь +А как бы ты думал? +Как бы ты думал? +Пеши пойду, поползу следом за тобой. +Нет мне жизни без тебя, Гришенька! +А дети? +На Дуняшку оставим. +Опосля заберем и их. +Едешь +Гриша! +Когда-то мы с тобой в Ягодное вот так же шли. +Только тогда узелок был поболее, да и сами мы были помоложе. +К чему ты при оружии едешь На что оно тебе сдалось +Вот отъедем, тогда брошу. +Все брошу, Ксюша. +Верхом-то удержишься? +Господи, тут хучь как-нибудь +Выберемся из яра — пойдем наметом. +Не будет так тряско. +Стой! +Кто едет? +Скачи, Ксюша! +Пригинайся ниже! +Стой! +Кажись попал. +Ради Господа Бога! +Хоть слово! +Да что же зто ты ? +! +Ты чего здесь делаешь +Кто ж там? +Жена. +— Куды ж идешь — Легкую жизнь шукать +Может, и ты со мной? +Легкую? +Нет. +Ступай один. +А ты куды ж теперича? +Домой, что ль +Домой. +Хочешь бери коня. +Спаси Христос. +Счастливо. +Мишатка! +Сынок! +Сынок... +Сынок! +Во мраке древнего мира, на берегу забытом самим временем, - есть сумеречная зона между жизнью и смертью. +Там пребывают те, кто обречён скитаться по земле вечно - ходячие мертвецы. +Извините, мисс Джен. +Сэм, я думала ты уже знаешь каждую кочку на этой дороге +Я то знаю, мисс Джен, но здесь кроме как по кочкам ездить и нельзя. +Что ж, я рада, что Африка совсем не изменилась. +Я боялась, что спустя 10 лет я бы ехала по первоклассному шоссе с драйв-инами по обеим бокам. +В этой части Африки немного изменилось, мисс Джен, - ни за 10 лет, ни за 50. +Сэм! +Сэм. +Остановись, ты сбил человека! +Это был не человек. +Это был один из этих. +Я очень сожалею, мисс Джен, но я не мог затормозить. +Вот стоит ваша бабушка. +Она скажет вам, что я был прав. +Она ждёт вас. +Ты дрожишь. +Мы сбили человека. +Проехали по нему на дороге меньше, чем в миле отсюда +Сэм даже не остановился. +Я видел его, мэм. +На нём были водоросли. +Он стоял прямо посередине дороги и пытался остановить машину. +Отнеси вещи мисс Джен в её комнату. +А как же этот человек? +Он, вероятно, сильно ранен, или мёртв. +На дороге никого нет. +Запомни это! +Я видела его! +Сэм видел его! +Он подтвердит. +Заходи внутрь, Джен, и освежись. +Так вы всё так же верите в это вуду? +Я думала, что это кошмар из моего детства. +Я думала, что теперь будет всё иначе. +Позже, ты решишь всё для себя сама, Джен. +Мне жаль, что твоя первая ночь после твоего приезда сюда, так началась. +За спокойное плавание, впрочем, мы уже приплыли. +Якорь стал на глубине 18 фатомов. +Хорошо, хорошо. +Спускайте лодку. +Да, сэр. +Нет, я больше не хочу, спасибо. +А теперь - за миллион баксов в бриллиантах, который скоро у нас будет. +Ты напиваешься. +Почему бы и нет? +Через несколько дней, я наряжу твоё прекрасное тело в бриллианты с ног до головы. +И что я буду делать с бриллиантами на ногах? +Не обращай внимания. +Это было мило. +А ты что будешь делать со своими бриллиантами, а Джеф? +Я? +Я набью ими миленький маленький ящичек, арендованный у Первого Национального банка Нью-Йорка. +Вот это романтично. +Ты перепила портвейна, Мона. +Твой муж позади тебя. +Что, уже не можешь по-дружески поцеловать её без мыслей о том, что из этого может получиться? +А как насчёт меня, Мона? +Меня тоже поцелуешь? +Ты не в доле, доктор, и бриллиантов не получишь. +Ну, если бы я знал, что к ним прилагается, то настоял бы на своей доле. +Ну ты послушай его! +Просто Ромео какой-то. +Лодка готова, сэр. +Кто здесь? +На помощь! +- Я попал. +Оба раза. +- Идиот! +Я ж говорю тебе, я попал в него, кто бы это ни был. +- Оба раза. +- Скорее всего, ты попал в Джонсона. +Что? +Он мёртв. +Я не мог в него попасть. +Я не настолько пьян. +Я не думаю, что ты в него попал. +У него шея сломана. +Кто это сделал? +Кто это был? +Зови сюда остальных. +Доставим его на берег. +Кто это был? +Ты мне всё равно не поверишь, Джен. +Такому в школе не учат. +Мне показалось, что это был мужчина. +Я видела, как он зашёл прямо в воду. +Я пришла посмотреть на прибытие корабля. +Я не ожидала их так скоро. +Но после того, что произошло с вами на дороге, я знала, что они будут сегодня. +Миссис Питерс? +Я доктор Эггерт. +Я ждала вас. +Это моя правнучка, Джен Питерс. +Как поживаете, мисс Питерс? +Это Джордж Харрисон. +Миссис Харрисон. +А это наш ныряльщик, Джеф Кларк. +- Одного из наших людей только что убили. +- Я знаю. +Я слышала выстрелы и крики. +Что здесь происходит? +Я писала. +Я предупреждала вас об опасности. +Вы имеете в виду эту чепуху про вуду? +Это был человек. +Я стрелял в него. +И вы в него попали. +И никакого эффекта, да? +Я хочу пойти в полицию. +От полиции тут проку не будет, мистер Харрисон. +Она отсюда далеко. +Нам нужно похоронить беднягу. +- Сегодня? +- Ну он же мёртв. +Так что мы можем его похоронить. +Если полиция захочет потом его выкопать, то это их проблемы. +У меня нет гроба, но я найду кого-нибудь, чтобы зашить его в парусину. +Это могилы тех, кто первыми пришёл за бриллиантами. +Это было в 1906 году. +Они были британцами. +Прямо перед тем, как началась война, в 1914 году была немецкая экспедиция. +Хотел бы я знать как они все погибли, миссис Питерс? +Ещё одна британская группа попытала свою удачу в 1923-м. +Португальцы в 1928-м. +Первые американцы объявились здесь 10 лет спустя, в 1938 году. +Ваша попытка добыть бриллианты - шестая. +А это чьи могилы? +Первая - для погибшего моряка. +А другие для остальных. +Она пытается нас запугать. +Она хочет сама заполучить сокровища. +Я уже знаю, что тех, кто приходят за бриллиантами нельзя запугать. +Помогите мне. +Эта могила, она для меня, я знаю! +Уведите меня! +Пожалуйста. +- Я положу её в постель. +- Пускай занимают большую комнату для гостей. +Согласно расчётам Эггертра, "Сьюзан Б" лежит на отмели, на глубине примерно 100 футов. +- Кстати, а где Эггерт? +- Он совещается пожилой леди. +Может, ему удастся выяснить, зачем старушка побеспокоилась о том, чтобы выкопать могилы заранее. +Значит, если отмель не переместилась, то корабль должен находится примерно тут. +Эта вещь сбивает меня с толку. +Конечно, она дохристианская, но она не похожа на вещь африканского происхождения. +Вы знаете, ближе из всего, что я видел, она находится к тем фигурам на острове Пасхи. +Вы быстро выбрали жемчужину этой коллекции. +Я полагаю, что вы кое-что смыслите в Африке. +Но только что это за люди с которыми вы прибыли? +Как я и писал вам, уже 20 лет я изучаю легенду о "Сьюзан Б". +У мистера Харрисона корабль для водолазно-спасательных работ. +Он прибыл за бриллиантами. +Я прибыл за историей. +Я думаю, что умер бы счастливым, если бы мне удалось закончить своё исследование. +Не то, чтобы я горю желанием занять какую-то из тех могил... +Только глупцы боятся могил. +Есть вещи и похуже. +Тела здесь нужно хоронить быстро, доктор Эггерт. +- Вы имеете в виду, из-за климата? +- Нет! +Мне не нравится объяснять всё дуракам, которые считают, что у меня старческое слабоумие, но вы должны понять. +Ходячие мертвецы? +Вы верите в них? +И вы поверите, не пройдёт и недели. +Мой муж, капитан "Сюзан Б" Джереми Питерс +- один из них. +Это фото было сделано больше 60 лет назад. +Сейчас он выглядит точно так же, кроме глаз. +Я видела его. +Вы знаете историю. +"Сьюзан Б" прибыла сюда для торговли в 1894 году. +Моряки нашли золотой шлем наполненный необработанными бриллиантами. +Они украли шлем. +Затем была битва. +Десятеро из них считались погибшими, среди них и капитан. +Остальные вернулись на корабль со шлемом. +Вскоре десятеро пропавших неожиданно появились. +Что-то произошло. +Остальная часть команды была жестоко убита, а судно потоплено в заливе. +Вы думаете, что десятеро убитых членов экипажа вернулись на свой корабль? +Они были мертвы, как и мертвы они сейчас. +Но они до сих пор охраняют эти проклятые бриллианты. +Один из них убил сегодня вашего моряка. +Они убили всех, кто приходил за бриллиантами. +Так они убийцы! +Ваш муж... +Я же говорю - они мертвецы! +У них нет понятий о морали, нет свободы воли. +Он убьют каждого, кто попытается украсть бриллианты. +А как же вы? +Меня они не беспокоят. +Они откуда-то знают, что мне не нужны их драгоценные сокровища. +Уже прошло больше, чем 50 лет как я услышала о том, что моего мужа видели здесь. +И я приехала, чтобы это выяснить. +Постепенно, я собрала воедино всю историю. +Я построила этот дом. +Вы хотите быть со своим мужем, этим ходячим мертвецом? +Я пришла, чтобы помочь ему обратится в прах и найти вечный покой. +Но как? +Как это можно сделать? +Ох, опять эта глупая женщина! +Джен! +Огонь! +Это единственный способ с ними совладать. +Если вы меня послушаете, я помогу вам добыть бриллианты. +Куда он ушёл? +Вы его не найдёте. +Я убираюсь отсюда. +Бриллианты, или нет, но с меня хватит. +- Ты останешься. +- Джордж, ты же видел это! +Я пришёл сюда за бриллиантами. +И я остаюсь, как и вы все. +Но если ты знала, что будут такие трудности, убийства, то зачем ты дала им сюда приплыть? +Я ничего им не позволяла. +Эггерт просто написал мне и сообщил, что они прибывают. +- Ни залив, ни бриллианты мне не принадлежат. +- Но ты хотела, чтобы они прибыли. +Да! +Я хочу, чтобы они нашли бриллианты, а затем уничтожили их. +Только когда они будут уничтожены, твой дедушка обретёт покой. +Уничтожить их? +Неужели ты думаешь, что Харрисон из тех людей, которые уничтожат бриллианты после того, как добыл их с такими трудностями? +Выбросит их из-за сказок какой-то старухи про то, как люди умерли 60 лет назад, но ещё не мертвых? +Если они когда-нибудь найдут бриллианты, то они будут рады уничтожить их. +Я знаю, что делать. +И в этот раз с бриллиантами и ходячими мертвецами будет покончено навсегда. +Привет. +Разве вы не испугались, что это мог быть зомби? +Зомби не курят. +Они боятся огня. +- Так вы всё о них знаете? +- Только то, что мне сказала бабушка. +- И вы ей верите? +- Нет. +Тогда кто же ворвался вечером в дом? +И кто убил Джонсона? +Если бы я знала. +Я хотела попросить вас и остальных уплыть. +Бросьте эту затею пока не убили кого-нибудь ещё. +- Разве я похож на того, кто испугается зомби? +- Но Джонсон погиб, погибли и другие, похороненные возле дома. +Оно не стоит того. +О да, стоит. +Если тех бриллиантов даже вдвое меньше, чем то количество, о котором говорят, то моя доля может быть около миллиона долларов. +- Это куча денег. +- Чего они стоят, когда ты мёртв? +Послушайте, мисс Питерс. +Я, может, и паршивый ныряльщик, но зато арифметику я знал на "отлично", когда учился в 81-й начальной школе. +Это в Нью-Йорке. +И вот как это теперь сказывается. +Работая ныряльщиком, я обычно зарабатываю 100 долларов в день. +Если повезёт, я работаю 3 дня в неделю. +Это 15 тысяч в год. +Представляете, сколько лет мне понадобится, чтобы сделать миллион? +67 лет. +Вам бы лучше возвратиться в школу и узнать сколько стоит 60 лет человеческой жизни. +Или 50, или 20, или хотя бы 10. +Ну ладно, я вам пообещаю, что если я заработаю этот миллион, или хотя бы половину, то я оставлю свою опасную профессию и никогда больше не нырну ни во что глубже бассейна. +Или, если и это будет заставлять вас нервничать, мне придётся пристраститься к очень сухому мартини. +Не смешно? +Вы, кажется, даже не слушали. +Есть ещё кое-что. +Сегодня, когда Сэм вёз меня домой, мы сбили на дороге одного из этих людей меньше чем в миле отсюда. +Мы его сильно ударили и проехали по нему. +Должно быть мы убили его. +Я бы хотела выяснить это. +Я тоже. +Мы можем взять машину? +Они должны боятся света. +Если бы даже я согласился и захотел выйти из игры, то не смог бы. +Это не моя затея. +Всё это оборудование и вложенные деньги +- Харрисона +Вот почему он забирает три четверти всего, что мы найдём. +Здесь, прямо перед нами. +Я, кажется, вижу что-то. +- Это случилось прямо тут. +- Осторожнее. +Похоже на воду. +Точно не кровь. +- Это произошло здесь? +- Где-то тут. +- Может, немного дальше. +- Давай посмотрим. +Осколки вашей фары. +Здесь вы должно быть с чем-то столкнулись. +- Что это? +- Водоросли. +Вода и водоросли? +Думаете, он пришёл со стороны залива? +Он внезапно появился на дороге. +Следы. +Ведут туда. +Значит он действительно пришёл со стороны залива +Ударило его, вероятно, там, где мы нашли стекло и пуговицу. +Его отбросило на пару ярдов и он побежал вон туда. +Давай вернёмся и посмотрим, что ещё мы сможем там найти. +Джен, ты иди по этой стороне дороги, а я пойду по другой. +Смотри, может, тебе попадутся ещё следы. +Джеф! +Он просто поднялся и ушёл. +Я бы хотел пойти по этим следам. +- Сегодня? +- Нет. +Надо чем-то пометить место. +Мы вернёмся утром, с остальными. +Джен, ты слышишь меня? +Постарайся убежать пока я удерживаю их ракетами. +Джен, пошли, надо идти. +Это должно их задержать. +Повезло, что ты взял с собой ракетницу. +Почему ты подумал именно о ней? +Я вспомнил, как старушка зашла вчера с козыря со своим факелом. +Я не знал, куда меня собирается отвезти девушка, +Я подумал, что это может быть ловушка. +Поэтому схватил ракетницу из ящика. +Ты говорил, что мавзолей, находящийся посреди джунглей, примерно 40 на 20 футов. +Без водопровода и центрального отопления. +Если хотите, мы соберём вещи для пикника и мы сходим туда. +Думаешь, ты сможешь найти это место опять? +Ну, я должен. +Ты же не отпускал меня всю ночь и всё записывал. +Знаете, док, я думаю, вы должны поделиться со мной частью своего гонорара за книгу. +Мне кажется, ты был прав. +Ставлю на что угодно, что Маленькая мисс "Милашка и Солнышко" пыталась завлечь тебя в ловушку. +Можно не сомневаться, что она и эта старая ведьма за всем этим стоят. +- Доброе утро. +- Доброе утро. +Тёплое молоко, Маргарет. +Я хочу поблагодарить вас, мистер Кларк, за спасение жизни Джен. +Она очень дорога мне и я буду вечно вам за это признательна. +Ну, теперь у тебя есть друг до самой смерти, Джеф. +Мы все умрём в надлежащее время, миссис Харрисон. +Могила ждёт всех нас. +Ты старая карга! +Ты уже мертва. +Тебе просто не хватает ума угомониться. +- Заткнись! +- Ну это же правда. +Она стоит за всем, что здесь происходит и вы все это знаете. +Я прошу прощения, миссис Питерс. +Понимаете ли, она обучалась манерам в баре Эдди на Фронт Стрит +- Она... +- Как я уже сказала, я признательна и я сделаю всё от меня возможное, чтобы вы получили эти бриллианты. +Спасибо, но сейчас это уже неважно. +- Видите ли, я решил выйти из игры. +- Что? +Ты не можешь так просто взять, и всё бросить. +Я фактически научил тебя вести бизнес. +Надо было тогда и научить меня как вести бизнес выхода из бизнеса. +И тогда бы я валялся на палубе, загорал и имел бы 75 процентов, пока ты под водой заигрывал бы с рыбами. +У нас есть договор. +Я вложил в это дело 30 тысяч, практически всё, что у меня есть. +Ищи себе другого дурачка. +Ныряй сам. +Мне никто не говорил, что здесь будут толпится оравы головорезов, и мне всё равно кто за этим стоит. +Хорошо. +Я дам тебе ещё пять процентов. +Возможно он прав, Джордж +Нам нужно уехать. +Меня в дрожь бросает от этого места. +- Ещё одно слово от тебя и я... +- Что ты сделаешь? +Закуёшь в кандалы? +Чего ты хочешь? +Я прошлой ночью вспоминал арифметику, Харрисон. +Знаешь, 50 процентов - не та сумма после которой я стану сопротивляться. +- Надеюсь, что ты доживёшь до её получения. +- О, я на это рассчитываю. +Видишь ли, я надеюсь, что ты будешь беречь мою жизнь, по крайней мере, пока мы не добудем бриллианты. +Мы теряем целое утро. +- Доброе утро. +- Доброе утро. +Доброе утро, мисс Питерс. +- С тобой всё в порядке? +- Так ты всё-таки участвуешь? +Да. +Харрисон меня уговорил. +Спроси у миссис Питерс. +Я ж говорю, я засунул ему нож в горло по самую рукоять. +- Значит не задел жизненно важных органов. +- Хорошо. +Но я хотел бы увидеть хоть бы немного крови из восьмидюймовой раны. +Вы верите в ходячих мертвецов, доктор Эггерт? +Я знаю всё только по книгам. +И что говорят книги, док? +Мертвецы хорошие пловцы? +Ну, дышать им под водой не нужно. +Что ж, в этом моя слабость. +Мне дышать необходимо. +Постарайся это запомнить, Харрисон. +- Последнее напутствие? +- Просто найди эти бриллианты. +- Я пока попытаюсь просто найти каюту. +Пятнадцать минут. +Не дай себя убить, Джеф. +Это будет такая потеря. +Ты слышишь меня? +Связь в порядке? +Давление воздуха в порядке? +Хорошо, поехали. +...двадцать четыре, двадцать пять. +25 футов. +Как оно? +Вода чистая. +Но я пока ничего не вижу. +Этот ваш первосортный шлем протекает, прокладка спереди. +Где ты его взял? +В магазине подержанных товаров? +Что, так плохо? +Пока нет. +Продолжаем. +50 футов. +Подготовьте другой костюм. +75 футов. +Как течь? +Хуже не становится. +- Хочешь подняться? +- Нет. +Пока нет. +Опускайте дальше. +Я что-то вижу! +Прямо подо мной. +Осторожнее. +Я гляжу прямо на трюм. +Нам повезло. +Я думаю, что смогу зайти в трюм. +Может, смогу прямо сейчас. +Хочешь попробовать? +Да. +Это даже не погружение. там даже нету 100 футов. +Но зачем тебе спускаться? +Ты не в том состоянии. +Я не могу позволить ему наложить свои лапы на бриллианты без моего присутствия. +Я вижу его! +Я вижу сейф! +Поднимайте. +Джеф, ты слышишь меня? +Ты внутри корабля? +- Джеф! +- Что случилось? +Давление воздуха на нуле. +Он ни за что не зацепился? +Ты можешь его втащить? +- Он вроде поднимается, если только... +- Если только что? +Если только трос не порвался. +Так может ты спустишься и посмотришь? +Так будет быстрее всего. +Продолжайте крутить. +Он жив. +Нам лучше доставить его к доктору. +Ближайший доктор находится в миссии Энджел. +Это пять часов езды отсюда. +Я здесь вместо доктора. +Через мой труп. +Он еле дышит. +Если мы быстро не сделаем что-то по этому поводу, он может и не выкарабкаться. +Я приготовлю для него кое-что. +Ты же не дашь ей давать ему что-то, правда? +А ты что думаешь? +- Ну, я не думаю, что она убийца, но... +- Да у неё с головой не всё в порядке. +Я не уверена, дышит ли он вообще. +Это поможет ему дышать. +Давайте ему одну унцию каждый час. +Миссис Питерс, не то, чтобы мы вам не доверяли... +Поставь. +Сами решите, давать ему это или нет. +Подождите! +Оно крепкое лекарство, +но безвредное. +Я дам вам знать, если будут изменения. +Хорошо, Флоренс Найтингейл. +Когда будешь заканчивать свою смену - позовёшь. +Ещё карту. +Я просто вне себя от восхищения. +Экзотическая Африка. +Дикие животные, тропические ночи. +И вот я тут - учу профессора играть в очко. +У меня 21. +Прекрасно. +Значит он должен тебе ещё одну тысячу спичек. +Не нервничай. +Почему она не скажет нам что там происходит? +Она только полчаса назад сказала тебе. +Он мирно спит и нормально дышит. +Чего тебе нужно? +Информационное сводку каждые 10 минут? +- Я пойду и посмотрю сама. +- Только не скандаль там. +- Как ты себя чувствуешь? +- Нет, не останавливайся. +Кажется, у меня наконец получилось: +Мягкие облака, золотые лестницы, глас трубы и ангелы. +Даже не думай, Джеф. +Ты в Африке. +И с моей колокольни, оно выглядит точно так же как и всякое другое место. +Почему ты не позвала нас, когда он проснулся? +- Он только что проснулся. +- Ага, конечно +Что здесь происходит? +Тебе на этой работе за сверхурочные платят или что? +Почему ты нас не позвала? +Я предупреждал тебя, чтобы ты не скандалила! +Какого обращения ещё ждать от такого пещерного человека как ты. +Я говорил тебе держаться от него подальше? +Придётся преподать тебе урок, который ты точно поймёшь! +Всё равно вернёшься. +- Как Джеф? +- С ним всё в порядке. +По поводу того, что случилось у затонувшего корабля, мы поговорим с ним позже. +О ходячих мертвецах говорят, что их души не могут найти покоя и они существуют в мучениях. +Как будто люди могут найти покой для души и разума во время жизни. +Огонь горит уже два часа. +Если бы Мона увидела огонь, она бы нашла путь назад. +Как только входишь в эти заросли, то далеко уже не видно. +Ей не следовало бы бродить по джунглям самой. +Она у них. +Я уверена. +Тогда мы должны пойти за ней. +- На кладбище? +- Я тоже пойду. +- Уверен, что хочешь пойти с нами? +- Ну, я хотел бы помочь. +Мы идём не пейзажами наслаждаться. +Если она у них уже так долго, ничего хорошего из этого не выйдет. +Вы все погибнете там. +Это должно быть где-то здесь. +Я засекал время вчера ночью когда мы ехали назад. +Хочешь опять использовать ракетницу? +Хочешь оружие, док? +Нет, спасибо. +Я лучше возьму ещё один фонарик. +Хорошо. +Пошли. +Вот и тропинка. +Арт и Джонни, вы замыкаете сзади. +Внимательно следите по обеим сторонам. +Док - вы в середине. +А ты оставайся сразу за мной. +И не стреляйте пока не будет другого выхода. +Ладно, пошли. +Подожди. +Это браслет Моны. +Это с другой стороны валуна. +Пожилая леди сказала, что это было кладбище европейцев, которые добывали здесь бриллианты 100 лет назад. +Арт, Джонни, оставайтесь здесь. +Если кто-то из этих покажется, стреляйте из ракетницы. +- Пойдёшь с нами? +- Да. +Хорошо. +Тогда понесёшь бензин. +- Она мертва. +- Может и нет. +Мы заберём ей. +Но давай придумаем как и самим выбраться отсюда. +Док, вылей бензин с обеих сторон двери. +Хорошо. +Давай. +Только не спускай с них глаз. +Я буду сразу за тобой и попытаюсь удерживать их при помощи ракет. +Она точно мертва. +Убираемся отсюда! +Смотри! +Мона! +Мона! +С тобой всё в порядке? +Забирай её. +Я прикрою! +Ок. +Пошли. +Они нашли тебя! +Ты в порядке. +Я так рада... +Она холодная, как... +С ней точно всё хорошо? +Она не сказала ни слова. +Может, она под воздействием наркотика, или в шоке. +Я думаю, что вам лучше положить её в постель. +Она мертва. +Ваша жена мертва, мистер Харрисон. +Вы же видите - она ходит. +Вы же все видите... +Посмотрите на её глаза. +Она не дышит. +Холодна как смерть. +Я больше не хочу слушать этот бред. +Вы слышите? +Чтобы его больше не было. +- Я положу её в постель. +- Только не в этом доме. +- Пожалуйста, бабушка. +- Мы можем положить её на корабле. +Нет. +Я знаю, что это ваш дом, но я не хочу больше, её куда-то везти сегодня. +Так что если вы боитесь - сами убирайтесь. +Я боюсь не за себя, я боюсь за вас. +За всех вас. +Мисс Питерс, не поможете положить её в постель? +Конечно. +А как же мы? +Пускай остаются. +В первой спальне. +Они нам могут понадобиться. +Мона, почему бы тебе не закрыть глаза и не попытаться поспать? +Джеф, ты не спишь? +- Как Мона? +- Без изменений. +- Ты хочешь завтра спускаться под воду? +- Ну, сейф находится пока ещё там. +Я думаю, что ещё одно погружение и мы сможем его поднять. +А что? +Ты хочешь от всего отказаться? +Я должен позаботиться о Моне. +Мне нужно найти ей доктора. +На помощь! +На помощь! +Джеф! +Харрисон! +Она сошла с ума! +- На помощь! +На помощь! +- Мона! +Джеф, помоги. +Я не могу её остановить! +Зажгите свечи. +Как можно больше. +Он мёртв. +Она зарезала его. +А потом пошла за мной. +Скажи Сэму пусть принесёт столько больших свечей, сколько сможет найти. +А теперь заставьте её идти к себе в комнату. +Они боятся огня. +Мне кажется, что это единственное, что может их уничтожить. +Она больна, миссис Питерс. +Она не в себе, правда? +Я очень сожалею, мистер Харрисон. +Я знаю по себе, что вы чувствуете. +Поставьте ещё парочку возле двери. +Если огонь действует здесь, то и под водой должен подействовать. +Поддерживайте огонь на том же уровне и они вас не побеспокоят. +- Они останутся внутри. +- Я понял. +- Если только не найдут другой путь. +- В любом случае, стоит попробовать. +Может и получится их закупорить. +В любом случае, вы и ваши люди будут в безопасности, если будут оставаться у огня. +Мы будем тут. +Пошли. +Я думаю, что сейф там не очень надёжный. +Так что я его открою за пять-десять минут. +и пока я буду горелкой срезать петли, ты стой с другой горелкой наготове. +Если они появятся, отгоняй их своей горелкой. +Но я надеюсь, что из-за огня они не будут бродить туда-сюда. +Будет уже темно когда мы закончим. +По поводу того поломанного компрессора... +Хорошо, что мы это выяснили перед погружением. +Могли бы подождать и до завтра +Я думал, что завтра ты хочешь отвезти Мону в Дакар. +- Один день ничего не значит. +- Послушай, ночь, день - неважно. +Под водой темно в любое время суток. +К тому же, завтра у меня могут труситься поджилки, как вот у тебя сейчас. +Ладно! +Док, вы следите за интеркомом, чтобы мы могли говорить дурр с другом. +Само собой, Джеф. +- Харрисон, слышишь меня? +- Слышу. +- Давление воздухе в порядке? +- Давление в норме. +Хорошо. +Я пойду первым. +Следуй на расстоянии 10 футов. +И следи за моим курсом. +Вали уже. +Удачи, Джеф. +И тебе, Джордж. +Я на дне. +Джордж, ты меня слышишь? +Слышу. +И вижу тоже. +Стравите ещё трос. +Да, Джеф. +Травите. +Настоящая развалюха. +Ещё и со внешними петлями. +Знаешь, я думаю, что смогу вскрыть его даже скаутским ножом. +Горит как дрова. +Первая петля с минуты на минуту должна отвалится. +- Джеф, они вокруг меня. +- Ты можешь удержать их? +Не знаю. +Я уже над второй работаю. +- Сколько ещё? +- Ещё минута. +С петлями покончено. +Есть. +Через 10 секунд можно убираться отсюда. +Я не могу удержать их. +Я поднимаюсь. +Поднимайте меня! +Поднимайте меня! +Опускайте платформу для погружения. +Здесь двое - ждут, чтобы на меня наброситься. +Я хочу удостовериться, что мой трос свободен и когда дам команду, тащите меня как безумные. +Мы поняли, Джеф. +Ждём команду. +Сработало! +Где Харрисон? +Только показался на поверхности. +Их целая куча вокруг него. +Четверо, или пятеро. +Стреляйте из ракетницы. +Опускайте платформу для погружения. +Подтяните меня на палубу. +Что с Харрисоном? +Он потерял много крови. +Он в своей каюте. +- У нас заканчиваются ракеты. +- Экономьте. +- Смотрите! +Они поднимаются на борт. +- Возьмите факелы и керосин. +Есть, сэр. +Посмотрим, сумеем ли оставить их себе. +Возьмите бриллианты в каюту и запритесь. +Рассредоточьтесь по палубе. +Из-за этого факела может начаться пожар. +- Сколько у нас ракет? +- Две, сэр. +Держи их на прицеле. +Пошли. +Выстрели им в ноги. +Я пойду и заберу этот факел. +Джонни! +Сзади! +Док, открой! +Пусти! +Есть что-нибудь горючее? +Чистящая жидкость? +Что-нибудь, что горит? +Да, в ящике стола. +- Да отдайте им эти вшивые бриллианты! +- Пускай кто-нибудь попробует. +- Есть идеи получше? +- Да. +Пройдём через них с боем. +А кто понесёт тебя, пока я буду драться? +Я справлюсь сам. +- Ты в прекрасной форме для бега. +- Через минуту буду в порядке. +Я возьму это и попытаюсь прорваться. +Если получится, то направлюсь к берегу на лодке. +Они последуют за мной и у вас будет шанс уйти. +И не думай, Джеф. +Тебе это так нужно? +Так получай! +- Он не уйдёт далеко с этими бриллиантами. +- Ты идиот, Харрисон. +- Он не пытается их украсть. +- Заткнись. +Он спас твою и мою жизнь. +И сделал больше, чем мог бы сделать ты со своей раненой ногой. +Я знаю его лучше, чем ты. +Расчехляй спасательную шлюпку. +- Ты в безопасности! +Я так волновалась. +Я увидела... +- Потом. +Нам надо кое-что сделать. +Пошли. +Похоже, она приходит в себя. +Мона! +Они явно загипнотизировали её. +Пошли. +Итак, значит ты преуспел, там где другие потерпели неудачу. +Я верила в тебя. +Послушайте, за этим гонится целое стадо их. +Они будут здесь через пару минут и церемониться не будут. +И я не хочу быть здесь, когда они появятся. +И я не хочу, что бы здесь в это время была Джен, и вы, - миссис Питерс. +Я думаю, нам нужно сесть в машину, взять Мону и убираться. +С Харрисоном встретимся в Дакаре. +Я бы поделился своей долей с вами. +Я подумал, что за все эти годы вы это заслужили. +Если, конечно, эта доля будет. +Я всё ещё не уверен, что бриллианты у нас. +- Как это открыть? +- Этот ларец древнее, чем пирамиды. +У них конечно не было ни замков, ни пружин, но они кое-что знали о рычагах. +Обычно... +Дай мне свой платок. +Быстро. +Садитесь с лодку и заводи её. +Мы вернёмся через пару минут. +Если они появятся, отпугивайте их факелами. +Если они подойдут близко, я отплываю. +Скажи девушке отдать мне ларец. +И скажи ей, если она попытается что-нибудь учудить, я застрелю тебя за то, что ты украл бриллианты и сбежал пока на нас нападали. +Это не правда! +Он принял всю опасность на себя. +- Послушай, Харрисон... +- У меня нету времени. +Пиви и Джонни разогревают двигатель. +Майк и Тони ждут в лодке. +Я забираю бриллианты и Мону. +Я переписал наш договор. +Отдай ему ларец. +Может, ты его уже открыл. +И как ты это собираешься узнать? +- Не надо, пожалуйста, ты испортишь его. +- Я найду способ. +Если пойдёшь за мной, я убью тебя. +Но бриллианты должны быть твоими. +Ты их нашёл, ты сберёг их +Спасибо, док. +Смотри. +Мы должны быстро пройти к лодке, понятно? +Пошли. +Давай. +Залазь! +Он мёртв. +Это она его убила. +- Всё произошло так быстро. +- Давайте занесём его в дом. +Но вы даже не знаете точно, бриллианты ли они хотят. +Может, они хотели ларец. +Тогда мы их больше не увидим. +Им нужны именно бриллианты. +Они вернутся, когда выяснят, что ларец пуст. +Но как я могу их уничтожить, даже если я этого захочу? +Развей их по ветру. +Разбросай по морю, чтобы никто и никогда их не нашёл. +Пошли со мной, Джен. +Через несколько минут мы будем на корабле, а ещё через 10 выплывем из залива. +Где они нас будут ловить? +В Нью-Йорке? +Куда бы ты не пошёл, они отправятся за тобой. +Ну ладно, я быстро избавлюсь от бриллиантов и обращу их в деньги. +Они будут продаваться во всех столицах мира. +Что они сделают тогда? +Будут штурмовать все ювелирные лавки на 5-й авеню? +Джен, я хочу, чтобы ты была со мной. +Я хочу, чтобы ты тоже наслаждалась богатством. +Я хочу, чтобы ты вышла за меня замуж, +Я бы с удовольствием, Джеф. +Но я не могу. +Я не могу её так оставить. +Неужели ты тоже во всё это веришь? +В то, что если выброшу бриллианты, то все они исчезнут? +Да, это правда. +Они прекратят ходить по земле. +Они найдут вечный покой. +Бриллианты должны быть уничтожены. +У них невозможно украсть бриллианты. +Джен! +Она верит. +Всю свою жизнь она верила. +Ты не можешь обмануть её ожидания. +Я не могу их выбросить. +Я бы хотел. +Но я собираюсь взять их с собой. +И вы тоже идёте со мной. +Обе. +Я не могу оставить вас тут пока они тут бродят. +- Я остаюсь здесь. +- Но вы не можете тут оставаться. +Это слишком опасно. +- Извините, но если придётся - я вас понесу. +- Я не сомневаюсь, что вы сможете. +У нас нет времени, миссис Питерс. +Я высажу вас где пожелаете. +Если вы хотите, я устрою, чтобы вы вернулись сюда позже. +Помоги ей залезть. +Стойте! +Они вернулись за бриллиантами. +- Чего мы ждём? +- Подождите, пожалуйста. +Мы уже в безопасности. +Капитан Питерс. +Неужели ты так и не обретёшь покой? +Ну ладно. +Хорошо, берите. +Вот бриллианты, миссис Питерс. +Они ваши. +Делайте с ними всё, что хотите. +Спасибо. +Спасибо. +Наконец-то, Джереми Питерс. +Свершилось. +Наверно я уже никогда не стану богатым. +Subs by linyok +Джультта Мазина +Приз Каннского фестиваля 1957 года за лучшую женскую роль +НОЧИ КАБИРИИ +Фильм Федерико Феллини +Авторы сценария Федерико Феллини, Эннио Флайянно, Тулио Пинелли +В ролях: +Франсуа Перь +Франка Марци, +Дориан Грей +Альдо Сильвани, Марио Пассанте Эннио Джиролами, Кристиан Тассу +А также Амедео Надзари +Оператор +-Альдо Тонти +Композитор +- Нино Рота +Дирижёр +- Франко Феррара +В создании сценария принимал участие Пьр Паоло Пазолини +Беги к реке. +Чего ты ждёшь +Как здесь спокойно. +Джорджио! +Помогите! +Помогите! +Спасите! +Помогите! +Помогите, кто-то тонет! +Кто-то тонет! +Скорее! +Кто-то тонет! +Скорее! +Помогите! +Эй, где Ромуаль +Ушёл в мэрию. +В мэрию? +Зачем его туда понесло? +Это женщина! +Вон она! +А Пиладо, его тоже нет? +Что она делает? +Вон она, за ней! +Прыгаем! +Если она попадёт в сточную трубу, ей не выбраться. +Женщина тонет! +Скорее за ней, надо помочь +Паджелло, сюда! +Запрокинь ей голову и смотри не тряси. +Стефано, поторапливайся! +Откуда ты её вытащил? +Осторожнее, держите под живот. +Она тонула. +Должно быть, она заснула и свалилась в воду. +Как только мы её увидели, сразу бросились на помощь +- Вы видели, как она упала? +- Нет. +Сколько раз она уходила под воду? +3. +Больше, 7 раз. +10! +Значит, она наглоталась воды . +Нам нужна помощь +Стефано! +- Что случилось +- Эта женщина тонула. +- Паджелло, быстрее. +- Она потеряла туфлю. +По-моему, она умерла. +Паджелло, нужно откачать её. +Смотри, делаем так. +Ребята, отойдите. +Это мы её спасли. +Отойдёте вы или нет? +Давай позовём Пампео, он никогда не видел утопленников. +- Мы только посмотрим. +- Я не хочу, боюсь +Идём же. +Мне кажется, она мёртвая. +Она бы не всплыла, если бы была мёртвая. +Она открыла глаза. +Стефано, она открыла глаза. +Хватит, положи её. +Надо снова сделать ей искусственное дыхание. +Ей бы сейчас бренди. +Бренди. +Ей нужно молока. +Тихо, она приходит в себя. +Ты , кажется, на мотоцикле? +Сгоняй, привези молочка. +У меня нет горючего. +Спокойно, синьорина, всё хорошо. +Вы счастливая, правда, счастливая. +-А где Джорджио? +- Какой Джорджио? +- Не волнуйтесь +-Джорджио! +Успокойтесь Успокойтесь +Джорджио! +Кто это Джорджио? +- Разве с ней был кто-то? +- Не знаю. +Джорджио, что же ты сделал? +Эй, успокойся. +Я иду домой! +Где мои туфли? +Вот один. +Где другой, я не знаю. +У неё, как у кошки, 9 жизней. +Идти-то нормально не может. +Нет, вы только посмотрите! +Минуту назад ты чуть не умерла, куда ты собралась +Отстаньте, отвяжитесь +Пустите меня, пустите! +Это мы тебя спасли! +Хорошо, отлично! +Вы меня спасли? +А теперь я хочу домой! +Мне это нравится. +Иди куда хочешь +Привет, Кабирия! +-Джина, ты её знаешь +- Конечно, это Кабирия. +Где она живёт? +В Оцилии. +Она гулящая, её там все знают. +Джорджио, открывай! +Это я, это я, Кабирия! +Джорджио! +Ванда! +Ванда, ты видела Джорджио? +Что с тобой? +Отвечай на вопрос. +Где Джорджио? +- Какой Джорджио? +- Мой Джорджио. +Что ты придумала? +Что тебе надо? +Что тебе надо? +Мне ничего не надо. +И вообще, не лезь ко мне! +Зайди в дом и умойся. +У меня нет ключа. +А куда же ты его дела? +Он лежал в сумочке. +А сумочка где? +Была у Джорджио. +Мы гуляли у реки. +Не знаю, как случилось, но я упала в воду. +Наверное, он испугался и убежал. +Кабирия, открой! +Открой, Кабирия! +Я хочу спать +Сколько там было денег? +Кабирия, отзовись, ответь мне! +Увидишь Джорджио, я здесь +Ну что ты делаешь +Вообще-то ты права, что остаёшься дома. +Полежи, выспись хорошенько. +Позже я к тебе зайду. +Выпей аспирин, станет лучше. +Ты всё ещё здесь, не устала болтаться? +Видишь, ты надоела мне! +И вообще, с каких это пор ты стала моей подругой? +Проваливай, сделай одолжение. +Проваливай отсюда! +И не смей больше брать мой термометр! +А когда это я брала твой термометр? +Вот зануда, брюзга. +Хочешь сказать, что он столкнул меня в воду из-за сорока тысяч лир? +Значит, он утопил бы меня за 40 тысяч лир? +Да любой из них утопиттебя за жратву. +Даже тот, кто любит? +Вы встретились месяц назад, как же он мог полюбить тебя? +Ты даже не знаешь, где он живёт и как его фамилия. +Согласись, Кабирия, он столкнул тебя в воду. +Поверь, дорогая. +Если б на его месте была я, то для верности подержала бы тебя за башку под водой. +- Иди в полицию. +-Думаешь, я доносчица? +Послушай меня, заяви в полицию. +Зачем, зачем он это сделал? +У него же было всё, всё, о чём он просил. +Зачем же воровать +Что же я была за дура? +Я же могла утонуть +Хватит, всё, пора с этим кончать +Довольно, ищи себе другую дуру, которая будет покупать тебе шёлковые рубашки. +Рубашки! +Какая же я дура! +Проваливай, ищи себе другую дуру. +Это же я купила тебе все эти шмотки: костюм, пиджак. +Такого больше не повторится. +Никогда, никогда! +Желаю счастья ! +Интересно, где же это ты собираешься теперь жрать +На площади Святого Петра? +Грязная крыса! +Ты ни на что не годен, обманщик. +Торгуй и дальше собой. +Воттак! +Гори, пока не сдохнешь +Это было в прошлый раз. +Говорю тебе, ты меня здесь больше не увидишь +Стоять рядом с тобой для моей репутации – просто погибель +С вами я не останусь +Как я хороша! +Красавица, настоящая королева! +Да, ты похожа на Моби Дика, королева. +Это ты мне? +Да как ты смеешь +Знаешь, где тебя ждут? +В цирке. +Быстро ты хвост прижала. +Да кто ты такая? +Где у тебя глаза? +Я же красавица, одно удовольствие посмотреть +- Королева! +- Нашла королеву! +Тебе становится всё хуже. +Когда тебя закроют в психушке? +А когда ты там окажешься? +Это печка, а тут вода для стекла. +-Здесь всё есть +-Даже кока-кола. +- Поехали покатаемся? +- Нет, я не такси. +- Выходи! +- Я не уйду. +Давай выходи! +Что ты будешь делать +Выходи, я хочу покатать Ванду. +Но ведь ты не умеешь водить +Не волнуйся, это моя машина, и я делаю, что хочу. +Выходи! +Я посмотрю, что будет. +Тоже мне, водитель +Почему ты не купила модель покруче? +Не слушай её. +Что ты понимаешь в машинах? +Что смеёшься? +Думаешь, раз ты на колёсах, значит, крутой? +Осторожно, сюда идёт лунатик. +- Привет, милашка. +-До встречи, Кабирия. +-Зайди ко мне, ладно? +-Ладно. +- Привет, Мориса. +- Привет, Кабирия. +- Привет, Ванда. +- Привет. +Красавица, просто красавица! +Но на твоём месте я купила бы серую, цвет красивее. +А впрочем, прекрасная машина. +Давай, давай, вот посадишь аккумулятор. +Вылезай, не хочу ругаться с тобой сегодня. +Да на кой чёрт она мне? +Цвет, конечно, неважный. +У машин всё проще. +Садишься сюда и сигналишь +Хочешь повернуть, делаешь левый поворот или правый. +Все мужчины будут твои. +Подумают, что твой папочка – богач. +Будут обхаживать тебя как принцессу. +Мне бы понравилось +Эта всё никак не заткнётся. +Я знаю, как ты получила эту машину! +Толкаешь наркотики! +Наркоманка! +Сиди! +Пусти! +Сиди! +А теперь музыка. +Мамба! +Потанцуем, Кабирия? +Лучшего танцора тебе не найти. +Давай же! +Давай! +Нет, вы посмотрите, что происходит! +Теперь она нашла другого воздыхателя, чтобы говорил: " Я люблю тебя" . +А потом она переспит с монахом. +Какое странное лицо. +Я должна её остановить +Синьоры , синьоры , смотрите, я намного лучше! +Чтоб вам пусто было! +Уроды ! +Куда ты хотела поехать на этой машине? +На кладбище? +До чего же хорошо! +Уродка, идиотка! +Шла бы ты домой! +Кабирия, ты разрешаешь ей оскорблять тебя? +Проучи её! +Посмотрим, где ты закончишь свои дни! +Шлюха дешёвая! +Будешь стоять на паперти, даже на кофе не хватит. +А всё из-за милого Джорджио! +Дай ей, Кабирия, врежь ей! +Кабирия! +Кабирия, покажи ей! +Она тебе ничего не сделает, бей в живот! +Остановитесь, плохо будет, если нас заметят. +Отпусти руку! +Разнимите их! +Что вы смотрите? +Держи её! +Держи! +Пустите меня, пустите! +Я ей сейчас покажу! +Руки прочь +Успокойся ты , садись в машину. +Пусти меня, пусти! +Кабирия, может, хватит? +Кого ты назвала наркоманкой? +Это кто наркоманка? +А, ты меня боишься? +Иди к чёрту! +Боишься, боишься! +Скорей, поехали. +Садись, садись, Кабирия. +Ты меня боишься, боишься, неудачница! +Хочешь сигарету? +Куда собираешься? +Давай мы тебя подбросим. +На Виавенето. +Что с тобой? +Знаешь, Кабирия, нам с тобой нужно очень серьёзно поговорить +Ты живёшь неправильно, за тобой некому присматривать +Видишь, как живём мы с Морисой? +У Морисы нет проблем. +В Риме нам не делают ничего плохого. +А всё почему? +Скажи мне, почему? +Давай сменим тему. +Скажи мне, что ты будешь делать на Виавенето? +Ты знаешь, что на Виавенето и Вилабадхези приходится бороться за место? +Давай лучше подыщем тебе серьёзного парня, такого, как я. +- Мне никто не нужен. +- Ну да, конечно. +Никто, понятно? +Зачем мне вкалывать на такого как ты , покупать еду, выпивку? +Скажи, зачем? +Смени пластинку, я счастлива. +-Дай мне выйти. +-Да с удовольствием. +До скорого! +Урод безмозглый! +Машина со свалки! +Что? +Я просто стою тут. +Какой ты красавец! +Проходи. +Что? +Я останусь здесь, я тут стою. +Добрый вечер. +Извините. +Смотреть надо! +Джесси. +Джесси, ты не можешь так уйти. +Альберто Родзари! +Джесси! +Джесси, не будем ссориться, ну хватит. +-Джесси, хватит. +-Дай пройти! +Не доводи меня, осторожно. +Мои ключи! +Пойдём, не дури. +Не смей меня трогать, убери руки! +Подвинься, дай я сяду. +Куда мы едем? +Куда, я спрашиваю? +Ты дашь ключи или нет? +Нет. +Сиди. +Пусти, мне больно! +Оставь меня! +Джесси! +Послушай, я последний раз говорю. +Хватит, уже всё сказано. +Меня тошнит от этих глупостей. +Пусти, ты порвёшь мне шубу! +- Я её покупал. +- Негодяй! +Секундочку. +Что тебе нужно? +Убирайся. +Дешёвый актёришко! +Предупреждаю тебя, если ты уйдёшь, между нами всё кончено. +Всё кончено! +Ну и ладно, пусть +Делай как хочешь +Спасибо тебе, Джесси! +Что тебе? +Свободен. +Эй, ты . +Иди сюда. +Иди. +Кто, я? +Да, ты , иди сюда. +Прокатимся немного. +Садись +И дверь закрой. +Ночной клуб +Давай. +Что это значит? +Давай выметайся. +Что ты раскомандовался? +"Выходи, заходи! +Садись, пошла вон!" +Кто ты такой вообще? +Идём, повеселимся чуть-чуть +Добрый вечер, синьор. +- Он велел мне идти с ним. +-Заходите. +Добрый вечер. +Как поживаете? +Не хотите присесть за столик? +У нас замечательное представление сегодня. +Ваш зонтик, синьора. +Прошу сюда, синьора. +Что такое? +Вам помочь +Проходи, садись туда. +Прошу вас. +Сядь +Альберто! +Коника! +Что ты здесь делаешь +Смотришь представление? +Тебе, наверно, не стоит говорить, кто это? +Рада познакомиться. +Представляешь, американская компания предложила мне написать сценарий. +И, кажется, всё получилось +Да, получилось прекрасно. +У меня дома есть копия фильма. +Синьоры , первая часть нашей программы подошла к концу. +Но перед тем как начнутся танцы , хотелось бы поприветствовать нашего почётного гостя Альберто Родзари. +Альберто, мне тоже надо тебя приветствовать +Итак, мамба №28! +Доставьте мне удовольствие, присядьте к нам. +Мои друзья были бы рады с вами познакомиться. +Пожалуйста, пожалуйста. +В самом деле, Альберто, идём. +Невозможно, я с дамой. +Идём потанцуем. +Воттак, мамба! +Воттак, все танцуют мамбу! +Мамба! +Мамба, воттак! +Если хочешь, иди к друзьям, не обращай на меня внимания. +Что ты сказала? +Если хочешь, к друзьям иди. +Ладно, хватит, идём. +Быстрее, садись +Ты ужинала? +Нет, хотя привыкла есть в 10. +- Поехали поужинаем. +- Что? +Поедем ужинать +- Прекрасно. +А куда? +- Ко мне домой. +Эй, минутку, ладно? +Эй, вы , лярвы , посмотрите, посмотрите, с кем я! +Кого я отхватила! +Знаете, кто это? +- Кто-нибудь звонил? +- Никто, синьор. +Откуда ты знаешь, что никто? +Вечером никто не звонил. +Может, ты спал. +Нет-нет, я был рядом с телефоном. +Хорошо. +Принесёшь нам ужин в спальню. +Если кто-нибудь позвонит, особенно синьорина Джесси, я сплю. +Будет настаивать я сплю. +Ты должен сказать ей только два слова: " Он спит" . +Да, синьор. +Идём, ужинать будем наверху. +- Как тебя зовут? +- Кабирия. +- Как? +- Кабирия. +Кабирия. +Ну идём. +И ещё собака. +Что это, зоосад? +И аквариум тоже есть +Куда бы я его поставил? +Оставь, прислуга уберёт. +Но ведь он помнётся. +Какой же я идиот. +Скажи, ты когда-нибудь видела идиота? +Он перед тобой. +Оставь же! +Иди сюда. +Как, говоришь, тебя зовут? +Кабирия. +Кабирия. +- Откуда ты ? +- Что? +Откуда ты ? +Из Рима, пьяццо Ридежемьнто. +Сядь, ты действуешь мне на нервы . +Нравится? +Не знаю. +Не в моём вкусе. +Не в моём вкусе. +А что это? +Бетховен, пятая симфония. +Моя любимая. +Войдите. +Вот и хорошо. +Давид, закрой за собой дверь +Посмотрим, что он принёс. +Икра, омары . +Обслуживай себя сама. +Я не в настроении. +Давай, давай, это всё для тебя. +1957 год. +Почему ты не снимешь кофту? +Здесь тепло. +Кажется, я порвала блузку. +Значит, где ты живёшь +На окраине Рима, недалеко. +Где это? +В Остии, в 10 милях от неё. +А работаешь на Виавенето? +- Я на Виавенето? +- Почему нет? +Я работаю на альпийских дорогах, это намного удобнее. +Почему? +Садишься на автобус из Оцилии и по прямой. +У меня есть подружка, её зовут Ванда. +Мы соседи и поэтому ездим вместе. +Мы никого не беспокоим, не спим на улицах, как другие. +Воттак. +У меня есть собственный дом со светом, водой, газом. +У меня есть всё необходимое. +И даже термометр. +Эта кофточка никогда не ночует на улице. +И под мостом она тоже не спит. +Ну разве лишь однажды . +Или дважды . +Но, конечно, мой дом – ничто по сравнению с этим дворцом. +Но я счастлива, мне достаточно. +Что же ты ? +Ешь +Что случилось +Я знаю, кто ты . +-Знаю! +Можно сказать +- Можно. +- Правда, можно? +-Да, да. +Альберто Родзари. +Я тебя сразу узнала. +Я смотрела все твои фильмы . +Ты потрясающий актёр. +Какой же фильм тебе больше всего понравился? +Дай подумать Последний. +У тебя был такой костюм с массой разных штучек. +Там ещё играл Витторио Гассман. +Ты распахиваешь дверь и... " Руки вверх!" +Что смешного? +Я не снимался в этом фильме. +Как это? +Ты красивый, как и твой дом. +- Принеси фужеры . +- Несу. +Шампанское. +Садись +За тебя! +Нет, нет. +Почему ты плачешь +Они скажут, что я вру, если я скажу, что знакома с тобой. +Никогда не поверят. +Эти дуры никогда не поверят. +Я и сама не верю. +Можно попросить тебя об одолжении? +Дай мне свою фотографию и напиши на ней: +"Кабирия была здесь, со мной. +Альберто Родзари" . +Нет: " Кабирия Чиакарелли была здесь, со мной. +Альберто Родзари" . +Я им её покажу. +Ладно, Кабирия Чиакарелли. +А теперь можно и поесть Здесь что? +Как вкусно! +Цыплёнок. +Цыплёнок, сейчас ты избавишься от всех проблем. +Ну вот. +Если хочешь послушать музыку, пока я ем, пожалуйста, я не возражаю. +А это что за зверь +Кажется, я видела такого в кино. +- Синьор. +-Давид, что случилось +Синьорина Джесси. +Я же велел сказать, что я сплю. +Она внизу. +- Что? +- Внизу. +Нет-нет, нельзя, чтобы она сюда вошла. +Она уже вошла и поднимается. +Идиот! +Альберто, открой. +- Кто там? +- Не будь дураком. +Открывай, слышишь Открывай. +Я хочу сказать тебе кое-что важное. +Минутку. +- Фотографию. +-Ах да. +Ты собираешься открывать +Иди в ванную, мы недолго. +Через минуту я от неё отделаюсь +Если ты не откроешь, я буду здесь стоять всю ночь +Не шевелись, тихо. +Альберто. +Пожалуйста, пожалуйста, открой. +Открой же! +Что тебе надо? +Что ты опять придумала? +Почему ты не идёшь спать +Завтра мне вставать в 6 утра. +Мне нужно выпить Дай мне выпить +- Что? +- Я хочу выпить +В чём дело? +Я так больше не могу. +Я так больше не могу! +Я тоже. +Ты невыносима и к тому же патологически ревнива. +Я сделал всё, что мог. +Ну остановимся и расстанемся друзьями. +Это самый лучший выход, останемся друзьями. +Нет! +Ни за что! +Нет! +Джесси. +Перестань, пожалуйста. +Иди домой. +Джесси, пожалуйста. +Тебе нужно лечь в постель, ты устала. +Альберто! +Джесси. +Ты меня больше не любишь, не любишь +- Я этого не говорил. +- Нет, не любишь +Нет, пожалуйста, не надо. +Согласись, это так. +Я никогда этого не говорил. +Скажи мне, что не любишь, и я оставлю тебя в покое, клянусь +Джесси, я бы солгал. +Я была бы рада, если бы мы могли иногда встречаться. +Раз в 2-3 дня, и я буду довольна. +Почему так редко? +Если хочешь, мы могли бы встречаться чаще. +Каждый день +Да, каждый день Если хочешь, каждую ночь +Но я не могу сделать так, чтобы женщины на меня не смотрели. +Это невозможно. +- Ты такой гадкий. +-Да. +Кабирия. +Кабирия. +Кабирия. +Пока, пока. +До свидания. +И где тут выход? +Эй, Кабирия, Альберто Родзари тебя обыскался! +Проваливай, я не желаю с тобой разговаривать +- Не обращай внимания. +-А кто обращает? +Кабирия, смотри, надо же, Димпи. +Вот плут несчастный! +Должно быть, не терпится за решётку. +Идём, Кабирия, здесь должно быть интересно. +Привет, Ванда. +Что ты к нему пристаёшь +Дай спокойно откинуть ноги. +Мадонна поможет дяде снова начать ходить +О чём ты говоришь +О чём? +Разве ты не слышала? +В центре города состоится молебен. +Ты правда в это веришь +А ты в чудеса не веришь +Нет. +Уверена, каждому есть, что попросить у Мадонны . +В следующее воскресень хорошо бы попасть туда. +Кабирия, а ты пойдёшь +Не знаю. +Подумаю. +Очень может быть, что пойду, только чем Мадонна может мне помочь +Скоро я закончу платить за дом. +У меня всё есть +Впрочем, я пойду, наверное. +Да, пожалуй. +Ты думаешь, Мадонна поможеттвоему дяде? +Смеёшься? +Будто Мадонна не знает, как он зарабатывает деньпи - торгует кокаином и заставляет женщин работать +Мадонна всё знает. +Если даже я знаю. +Над такими вещами нельзя смеяться. +Да ну тебя! +Зачем тебе туда ходить +О чём ты попросишь +Я спрашиваю, о чём ты попросишь +Эй, красотка! +Может, прокатимся? +- Пока, Ванда! +- Пока, Кабирия! +"Кратчайшим путём" . +И это короткий путь +Я иду уже час. +Где я? +Ты живёшь в пещере? +Я тебя никогда не видел. +У меня есть свой дом. +Горджано. +Горджано, это я. +Как дела? +Неплохо, спасибо, синьор, спасибо. +А где Пьтро? +Спит? +Два дня назад его положили в больницу. +Мне сказали, что ему очень плохо. +Что тебе нужно? +Всё, что дадите. +Спасибо, синьор. +Вот одеяло. +Подойдёт? +В какой госпиталь отвезли Пьтро? +В госпиталь Святых братьв. +Хорошо. +Если у меня будет время, я его навещу. +Пока. +Туйнок? +А это кто? +Что это за благотворительность +Я тебя спрашиваю. +- Можно вам помочь +- Нет, спасибо. +А вы куда? +Возвращаетесь в Рим? +Не подвезёте меня на своей машине? +Подвезу. +Хильда! +Хильда! +Твидиш, кто это? +Пришёл только сегодня, я тебя ждала в субботу. +Дорогой, дорогой! +Я только вчера думала, он придёт в среду. +Так прошло уже 9, 10 дней. +Я думала, мы увидимся в субботу. +Бомба? +Я её знаю. +Бомба, как ты ? +Хочешь знать, что у меня было? +Квартира в Риме, квартира в Остии. +Было полно подарков: деньпи в банке, украшения, золото. +У меня было 5 килограммов золота. +Не ври. +Кто тебе поверит? +В твои-то годы . +Меня заставляют причёсываться. +Я надеваю кофточку с вырезом, белые серьпи. +Воттак. +Иди, иди. +Поторопись +Ты мне принёс сладкое? +Это только мне, а не другим. +Дай мне, дай я спрячу. +А это с шоколадом. +Чёрт побери! +Эх, зануда! +Наверное, пойдёт дождь +Дорогой, спасибо, спасибо. +Ну всё, хватит. +Пока. +А когда ты вернёшься? +Когда ты вернёшься? +В понедельник или субботу. +Пусть Мадонна хранит тебя от всякого зла. +Хорошо, что они не умерли от голода в Риме. +Они работают по ночам? +Нет, они прекратили, хватит. +День на день не приходится, всяко бывает. +Да, это верно. +Как ты нашла этих людей? +Так получилось +Я осталась ночью на улице и встретила вас. +А вот как вам пришло в голову заниматься этим делом? +Я и сам не знаю. +Правда, не знаю. +Вот, мы приехали. +Твой трамвай. +Ты далеко живёшь 19-й километр по дороге в Остию. +Как тебя зовут? +Мария Чиакарелли. +Живёшь одна? +Мои родители умерли, когда я была маленькой. +Я из Рима. +Ну хорошо, иди спать, бедняжка. +Я только... +Пока. +Что такое? +Спасибо, спасибо за всё. +Дон Минченцо, прибыла группа из Венеции! +Вата, сладкая вата! +Шарики из спелой вишни! +Добро пожаловать на молебен! +Мадонна творит чудеса. +Вата, сладкая вата! +Шарики! +Давай руку. +Осторожно, он инвалид. +Спасибо. +Ванда, посмотри, сколько народу! +Давай, дядя, пойдём поставим свечи. +Скажите, сколько стоят свечи? +Смотря какие. +Эти - по 50, эти – по 100, эти - по 200 лир. +Я куплю самую большую. +Даже две, тебе и себе. +Ванда, давай купим свечи. +- Эти подойдут? +-Да. +Мне одну, но я сама за неё заплачу, сама. +Нет, я плачу за всех. +А что теперь с ней делать +Какая тупица! +Сколько за все? +Две четыреста. +Дорогу! +Пропустите больного человека. +Разрешите пройти! +С дороги, пропустите нас! +Такой молодой. +Мы здесь, подождите! +Пойдёмте фотографироваться! +Пойдёмте фотографироваться! +Уже иду! +Пошли, Кабирия, нас ждут. +Иду! +- Где Ванда? +- Я здесь +- Ванда, пошли. +- Иду. +Я хочу сфотографироваться. +Сфотографируйте меня, пожалуйста. +Что теперь надо делать +Во-первых, пойдём на исповедь +Туда, вниз, к исповеднику. +Но я вчера исповедовался. +Осторожней, он же калека. +Ванда,.. +я попрошу Святую Мадонну о том же, о чём ты . +А разве я тебе сказала? +Только ты не говори, что забыла. +Я хочу попросить большую квартиру рядом с парком. +Ванда, это же совсем не то. +Ты что? +Ты что, забыла? +Прекрати. +Разве нельзя просить, о чём хочется? +Но ты говорила, что попросишь .. +Я передумала. +Ванда. +Не надо так. +Что с тобой? +Ты задула мою свечу, будь осторожней. +30 мест по тысяче лир за каждое. +- Итого 30 тысяч. +- Ты шутишь +- Я дал 35 тысяч за все. +- Правильно сделал. +На исповедь сюда. +А что нужно говорить на исповеди? +Господи, я всем сердцем раскаиваюсь во всех содеянных грехах, и я... +Да вот, написано же. +Подожди. +Что ты ? +Нельзя идти вдвоём. +Нет, я войду. +Всё, пока всё. +В другой вход. +Потише, не толкайтесь, не толкайтесь +Мне плохо. +Так лучше? +Ты что, не видишь Осторожно. +Осторожно. +- Вот алтарь, дядя. +- Я больше не могу. +-А в чём дело? +- Я не могу. +Хватит, я не могу. +Я помогу, мы уже подходим к алтарю. +Мне нужно немного отдохнуть +Рози, подойди на минутку, он ослаб. +Мы почти это сделали, пойдём. +Все ваши желания будут исполнены Божьй милостью , если вы подойдёте к Нему с чистым сердцем и душой, очищенной от грехов. +Услышь меня, Мадонна! +Мадонна, услышь меня! +Молитесь Деве Марии, матери Божьй! +Спасибо, Мадонна! +Спасибо, Мадонна! +Славься, Мадонна! +Спасибо, Мадонна, благосклонная Мадонна! +Пресвятая Мадонна! +Милостивая Мадонна! +Спасибо тебе! +Спасибо, Мадонна! +Мадонна, спасибо тебе! +Молю тебя, будь благосклонна! +Мадонна, спасибо тебе! +Молю тебя, будь благосклонна! +Ванда, иди сюда! +Не уходи, хорошо? +- Что дальше? +- Откуда я знаю. +Ванда, у меня сердце колотится, я боюсь, я боюсь её. +Так странно, Ванда. +Славься, Мадонна! +Спасибо, Мадонна! +Спасибо, Мадонна! +Мадонна, услышь наши молитвы ! +А теперь преклоните колени и молитесь, молитесь, дети мои. +Эннио, скажи, Мадонна сделает так, что я снова буду ходить +Я думаю, да. +Встаньте, дети мои, поднимитесь +Если вы очистили свои души, милость Всевышнего отныне распространится и на вас. +Мадонна, помоги мне! +Пусть моя жизнь изменится! +Пожалуйста, помоги мне найти лучшую долю в жизни. +Пожалуйста, помоги! +-Дядя, пора. +- Нет. +Попробуй ходить Уверен, всё получится. +- Нет, я боюсь +- Я просто уверен. +Ну давай же! +Пожалуйста, я не могу, не могу. +Боже, какой же я грешник! +Мадонна, спасибо! +Спасибо, Мадонна! +Кабирия. +Кабирия, ты что, язык проглотила? +На, выпей. +Осторожно. +Ей бы не мешало хорошенько поесть +Она так напилась, что и дорогу домой не найдёт. +- Кабирия, что ты делаешь +-Думаю. +Брось, выпей. +- Что она сказала? +- Сказала, что думает. +Не напрягай голову, а то она лопнет. +Посмотрите на этих кретинов! +Надоели со своим дурацким мячом! +Он нарочно это сделал. +Я ему покажу нарочно! +Красавица, подкинь мячик! +Подай мяч, красавица! +Хорошо, но в следующий раз я брошу его в другую сторону! +Ванда, может, она хочет остаться одна? +Пусть скажет, мы уйдём. +Откуда ты взял, что я хочу остаться одна? +Что с тобой? +Откуда ты взял, что я хочу остаться одна? +Эй, если вам нужен мяч, идите берите сами! +Забирайте, если он вам нужен! +Кабирия! +Останови её, она даже идти не может. +Я не хочу с ней разговаривать, она мне надоела. +Кабирия, ты правда думала, что что-то изменится? +Вот дура-то! +Увидите, это ещё не конец. +Знаете, что я сделаю? +Вы даже себе представить не можете. +Я продам дом! +Я всё продам и всё брошу к чертям! +Я уеду! +И куда же ты уедешь Куда? +Какая разница? +Я же, я же не такая, как ты . +Я другая. +На земле полно мест, куда можно поехать и изменить свою жизнь +А куда, по-вашему, они идут? +Куда, скажи мне? +Эй, куда вы собрались с флагами? +Что вы делаете? +Собираетесь поддержать президента на выборах? +-Зачем ты дала ей вино? +-Да всего один стакан. +Кабирия! +Разве Мадонна дала вам богатство? +Разве она послушала вас, ответьте? +Ты хочешь, чтобы нас всех забрали? +Кабирия, вернись Пожалуйста, вернись +- Сделайте что-нибудь +-Да что я могу сделать +Да вы только посмотрите на неё! +- Ну и что? +- Верни её, верни! +Отстань, я хочу послушать +Кабирия! +Кабирия! +Услышала Мадонна ваши молитвы , ну скажите? +Вы дураки! +Давайте, давайте. +"Мадонна нас услышит!" Как же, как же! +Идите и не забудьте свои флаги! +Кабирия, хватит, хватит. +Убирайтесь, проваливайте! +Кабирия! +Кабирия, ты совершенно пьяная. +Кто пьяная, я? +Это кто пьяная? +Какой спектакль +Я тебя спрашиваю. +Хороший. +Что ещё? +Синьоры , вы изволите видеть, голова моего помощника была проколота насквозь +Кинжалы прошли через коробку. +Из ужасных ран должна была хлестать кровь +Но уважаемые, вы в недоумении, потому что головы просто нет. +Что вы на это скажете? +Теперь перейдём ко второй части нашего представления. +Эксперимент с магнетизмом, гипнозом и другими видами внушения. +Если есть добровольцы , прошу на сцену. +- Может, вы ? +- Я? +Давай, разве ты не мужчина? +Давай, давай! +Идите, не бойтесь Обещаю, я не причиню вам вреда. +Это научный эксперимент. +А мне за это заплатят? +Вы можете поучаствовать в удивительном эксперименте. +Теперь нам нужна представительница прекрасного пола. +- Синьорина, может, вы ? +- Я? +Да, поднимайтесь +Все увидят, какая вы храбрая. +- Я не хочу. +-Давай же! +Синьорина, мы не можем бросить этих юношей в одиночестве. +А может лучше вы ? +Иди, все хотят посмеяться. +Посмотри на себя в зеркало и обхохочешься. +Не надо на меня давить, не надо! +Пожалуйста, не заставляйте себя упрашивать +Вам понравится. +Может, вы хотите, чтобы я сам за вами спустился? +Идите, не бойтесь, все вас просят. +Вы же ведь среди друзей. +Всё это жульничество. +- Идите, синьорина. +- Хорошо, иду! +Настоящий доброволец! +Я ведь могу и не ходить +Прекрасно. +Друзья мои, не бойтесь +Прекрасно. +Вы храбрая девушка, это делает вам честь +Идите сюда. +Всё будет хорошо. +А теперь, друзья , давайте развлекаться. +Ах, дырявая голова, это непростительно! +Я забыл, что синьорина Вера всё ещё здесь +Как же я могзабыть, подумать только! +Мне кажется, здесь тепло. +Как вы думаете? +Может, прогуляемся на лодке? +Кто-нибудь страдает морской болезнью ? +Нет, когда я был маленьким, то плавал по реке. +Хвастун, ты же боишься воды . +Значит, всё в порядке. +Хорошо, мы прекрасно прогуляемся. +А вот и лодка. +Мы назовём её " Отважная" . +При плохой погоде лучшей лодки нам не найти. +Все на борт! +Не заставляйте меня упрашивать вас. +Вы постойте здесь Идите за мной. +Погода прекрасная, море спокойное. +Куда вы ? +Смотрите сюда! +Смотрите на меня! +Воттак. +Невольники, возьмите вёсла. +Смотрите мне в глаза! +Начали грести. +Раз, два, три. +Море синее спокойное, тихое и прозрачное. +Вы чувствуете морской ветерок и запах морской соли и йода. +Какое удовольствие. +Смотрите, дельфины ! +Ребята, смотрите, дельфины ! +Здесь глубоко, погода начинает портиться. +Мы в открытом море. +Волны большие, начинается шторм! +Упритесь ногами. +Верьте, мы доберёмся до суши. +Следите за кормой! +Мама, нам никогда не выбраться! +Пресвятая Дева Мария, услышь меня! +Господи, помоги нам! +Помолитесь за наши души! +Успокоились Спасибо, синьоры , спасибо. +Всё-всё, вы свободны , свободны . +Ну ребята, вы так перепугались +Струхнули? +Не уходите. +- Вы мне? +- Вам. +- Разве ещё не всё? +- Нет, не всё. +Оставляете меня в одиночестве? +Но ведь уже всё. +Вы замужем или нет? +Нет. +Вам понравилось представление? +Нет, не очень +Я бы хотел поговорить с вами. +Подойдите, пожалуйста. +- Вы из Рима? +-Да, из Рима. +А в каком районе вы живёте? +Колонна, Приоли, Прати? +В Прати. +Не пытайтесь обмануть меня. +Сейчас вы расскажете, где живёте. +В Сан-Франческо. +Почему вы смеётесь +Не обращайте внимания, они шутят. +Вы сказали, что не замужем. +А вам хотелось бы замуж? +Откуда вы это взяли? +Кому она нужна? +Вы , конечно, хотели бы выйти замуж. +Этого хочет каждая девушка. +Я знаю одного очаровательного юношу, который ищет спутницу жизни. +Он бы с радостью женился на вас. +На мне? +Он красив и здоров. +У него собственный Феррари. +А чем вы занимаетесь +Она графиня. +Послушайте, я довольна жизнью . +У меня всё есть, всё. +А теперь до свидания. +Слышали? +У меня всё есть Всё есть +Что с вами? +Я очень рад за вас. +Значит, у вас есть деньпи в банке, собственность и всё остальное? +У меня свой дом. +И такое бывает. +А сейчас, если вы не против, я уйду. +Секундочку. +Вы ставите меня в дурацкое положение. +Позвольте, по крайней мере, представить вам этого юношу. +- Его зовут Оскар. +- Какой Оскар? +Оскар! +Иди к нам. +Как же хорошо ты одет. +Подойди ближе. +Я хочу представить тебя этой молодой особе. +Думаю, она будет рада. +Как поживаешь +Я счастлив, что познакомил вас. +Теперь вы встретились, и я оставляю вас наедине. +Вы в чудесном саду, повсюду растут цветы . +Тишина. +И вы слышите только шелест листвы . +Вы можете разговаривать друг с другом, секретничать, и никто вас не слышит. +Синьорина, смотрите, Оскар предлагает вам руку, в этом нет ничего плохого. +Но мы же только встретились +Вы идёте по поляне, поросшей цветами. +Сладко поют птицы , и Оскар не смеет заговорить с вами. +Он слегка оробел. +Вы вынуждены умолять его. +Но вот он решился и говорит: +"Синьорина, я так долго ждал нашей встречи. +Можно задать вам вопрос?" +Да. +У вас есть жених? +Был ли в вашей жизни мужчина? +Я так и подумал. +Я часто смотрел, как вы стоите у окна. +Видел вас по воскресеньям в церкви. +Ваши глаза всегда опущены . +А ещё я видел, как вы собираете цветы . +Кто любит цветы , у того доброе сердце. +Могу ли я надеяться вас снова увидеть +Спасибо. +Как вы сказали ваше имя? +Мария. +Мария, какое чудесное имя. +Спасибо, синьорина Мария. +Я сохраню эти цветы как драгоценные сокровища. +Вы подарите мне танец? +Пожалуйста, маэстро. +Оскар, Мария любиттанцевать +Оркестр начинает играть чудесный вальс . +Я богат, но печален и одинок. +Что проку иметь машину, останавливаться в роскошных отелях, скитаясь по свету в одиночестве? +На самом деле мне нужен дом, полный детишек, и жена, как вы . +Мы должны были встретиться, когда мне было 18. +У меня были прекрасные чёрные волосы , которые спадали мне на плечи. +Для меня вы на всю жизнь останетесь юной. +Значит, вы действительно любите меня? +Это замечательно. +Вы не разыгрываете меня, правда? +Поклянитесь +Синьорина? +Синьорина? +Ну всё, всё. +Всё. +Что вы заставили меня делать +Что вы заставили меня делать +Спасибо, спасибо. +Занавес! +Вы что, никогда не уйдёте отсюда? +Пора закрывать +Ухожу, ухожу. +Скажи, все эти полоумные уже ушли? +Все ушли, только вы остались +Почему бы вам не уйти? +Пора закрывать +Уходите. +Хорошо. +Я ещё покажу им! +Извините, синьорина. +Меня зовут Донофрио. +Извините за беспокойство. +Обычно я не знакомлюсь с дамами на улице. +Я сидел на балконе. +Значит, вы видели? +Прекрасный спектакль, классная штука! +Меня выставили на посмешище! +Синьорина, простите. +Позвольте сказать, я с вами абсолютно согласен. +Представляю, что вы чувствуете. +Я хотел сказать, вы мне понравились +Я искренне восхищён. +Знаете ли, мы все такие притворщики и ужасные типы . +Но когда вдруг встречается такой человек, как вы , чистосердечный, по-детски доверчивый, +то мы понимаем, что есть ещё люди чистые и открытые. +Вы пробуждаете в людях самое лучшее. +Я очень признателен вам. +Становится прохладно. +Подержите, пожалуйста. +Я только надену свой плащ. +Могу я предложить вам выпить +Не знаю. +Возьмите, пожалуйста. +Дураки проклятые, всё шляются, шляются! +Простите, пожалуйста, мою настойчивость, но эти эксперименты с гипнозом могут пагубно отразиться на здоровь и спровоцировать серьёзные болезни. +Наверное! +Поэтому я так странно себя чувствовала. +Меня бросало то в жар, то в холод, я потела, как при температуре. +Посмотрите на меня. +Могу предложить бренди. +Это поможет. +Давайте зайдём. +Мы ненадолго. +Пожалуйста, садитесь +Два бренди, пожалуйста. +Клянусь, я никогда не страдал так, как сегодня вечером. +Этот шарлатан так разговаривал с вами. +Такая неслыханная дерзость +А вы отвечали энергично, но скромно. +Я очень страдал. +Всё горело внутри. +Мне больно об этом говорить, я просто заболел. +Поторапливайтесь, мы уже закрыли. +Не беспокойтесь +Существуют вещи, которые не трогает вульпарность +Это не могло слишком повлиять на вас, я уверен. +Всегда, даже в самой дикой толпе, найдётся человек, который поймёттакую, как вы , и оценит. +Ваше здоровь ! +А что было на сцене? +Он заставил вас участвовать в деликатной и трогательной сцене. +Сцене любви. +На меня это так подействовало, не знаю даже, как описать +А больше всего то, что вы были как 18-летняя девушка, привыкшая ходить на мессу с матерью , и у которой были чудесные чёрные волосы , +чёрные волосы до плеч. +Он заставил меня это сказать +Не пора ли расходиться? +Сколько я вам должен? +150 лир. +Спасибо. +Спасибо. +Пора по домам. +Я хотел сказать +То, что случилось сегодня вечером, очень важно для меня. +Совпадение. +А вдруг? +Я живу не здесь +Просто шёл без дела и всё, бродил по городу. +Знаете, я сюда не заглядывал никогда. +И вдруг решил пойти в театр. +Впрочем, я не знаю, зачем. +Наверное, это судьба. +Да-да, судьба. +Да, именно судьба. +Но кто вы ? +По вашей манере говорить, можно подумать, что вы из Приоли. +Простите, не понял? +Вы разговариваете как синьор из самой богатой части города – Приоли. +Меня зовут Донофрио, я уже говорил. +Я бухгалтер. +Чего вы хотите от меня? +Поймите, ведь то же имя. +Оскар. +И меня зовут Оскар. +Подумаешь, Оскар. +Ну и что? +Ну что из этого? +Оскар. +Согласен. +Но вдруг это ещё одно совпадение. +Ведь гипнотизёр выбрал имя Оскар. +Я должен вас увидеть ещё раз. +Вы ждёте автобус? +Да, я езжу на автобусе. +Пора домой, я смертельно устала. +Мы прощаемся так, как будто больше никогда не встретимся. +Нет, мы должны увидеться снова. +Нельзя воттак расстаться. +Мне ещё много нужно вам сказать +Когда же я увижу вас снова? +Не знаю. +Я же работаю, торгую на улице. +Что мы можем ещё друг другу сказать Что? +Вы о чём? +Что мы можем друг другу сказать +Автобус. +Увидимся, до свидания. +До свидания. +Не говорите " нет" , пожалуйста. +Я тоже работаю. +Но после работы , завтра вечером, например? +Завтра вечером, хорошо? +Я не могу вечером. +И даже в воскресень ? +В воскресень ? +Да, в воскресень в 7, на вокзале. +Не знаю. +Но мне так хорошо сегодня. +Значит, договорились +Что вы делаете? +Ладно, поехали. +Синьорина! +Синьорина, я здесь +Я был внизу. +Простите, что заставил вас ждать, засмотрелся. +Я рад, что вы пришли. +Честно говоря, я побаивался, что вы приняли меня за ловеласа или даже за маньяка. +Всё так необычно, странно. +Как сон, правда? +Я позволил себе купить вам цветы . +Спасибо, но не стоило беспокоиться. +Зачем вы это сделали, зачем? +Прошу вас. +Идёмте. +Позвольте. +Он говорит, что ему нравится беседовать со мной. +Он всё время говорит, ну просто замечательный рассказчик. +Он из тех, кто много читает и образован. +А ещё он назначил мне свидание, и мы ходили на премьру в" Метрополитен" . +Это уже треть . +Они такие вкусные! +Это самые лучшие. +Так о чём я говорила? +Мы смотрели прекрасный фильм -премьру, называется " Гладиаторы " , о мучениках-христианах. +Правда, в фильме всё изменили, но он объяснил, что это нужно для сценария. +А ещё он говорил, как ему нравится со мной разговаривать и гулять +Всё потому, что я его понимаю. +Можете не верить, но он красив, молод. +У него каштановые волосы . +Он похож, он похож на северянина. +А потом мы ходили в ресторан, ели пиццу, и он купил мне цветы . +Ну что скажете? +И ты считаешь, что это бескорыстно? +Бескорыстно. +Хватит разыгрывать нас, Кабирия. +Завтра мы с ним снова увидимся. +Кабирия, скажи мне, что ему надо? +Откуда я знаю? +Какая разница? +Кому какое дело? +Думаешь, опять деньпи? +Ты угадала. +Полиция! +Полиция! +Сейчас тебя упекут. +Сейчас тебя упекут, ты этого заслуживаешь +Стервы , вы все туда отправитесь +Здравствуйте, синьорина. +Здравствуйте. +Как поживаете? +Прекрасно выглядите. +Как дела? +Хорошо. +А у вас? +Тоже. +Спасибо. +Это вам. +Спасибо. +Не стоило беспокоиться. +- Пожалуйста. +- Это уж слишком. +- Возьмите. +- Спасибо. +Куда бы вы хотели пойти? +- Куда хотите. +- Спасибо. +Тогда идём в парк. +Да, пойдёмте в парк. +Ваша семья живёт в Риме? +У меня нет семьи . +Мои отец и мать умерли, когда я был ребёнком. +Я совсем один. +Но лучше одиночество, чем водить дружбу с кем попало. +Да-да. +Мы жили в Поднополии, в маленькой деревушке. +Её название не имеет значения, вы всё равно его не знаете. +Я вырос в большом доме с керосиновыми лампами. +У отца был небольшой надел земли. +Отца звали Джованни,.. +а маму +- Эльза. +Мне нравится имя Эльза, чудесное имя. +Братьв и сестёр у меня не было. +И когда отец умер, родственники наложили руку на этот несчастный кусок земли, который достался моей матери. +Мы узнали, что такое нищета. +Привет, Кабирия! +Что ты делаешь, дитя моё? +Добрый день, отец. +Пожертвуй для Святого Антония. +Извините, у меня нет с собой денег. +Это неважно, можно и потом. +Самое главное – вера в Господа. +А ты веришь в Бога, дитя моё? +Нет. +- Не веришь в Бога? +- Нет. +Почему? +Каждый должен верить +Кто находится в милости Божьй, тот испытывает удовлетворение. +Возьми меня, я верю в Бога и удовлетворён. +Я ходила к Мадонне, просила её о благосклонности, но бесполезно. +Всё дело в том, как просить +Может, ты просто перестала надеяться. +- Ты замужем? +- Нет. +Все девушки должны выходить замуж и иметь много детей. +Супружество – священный долг. +Это тоже путь к Божьму благословению. +Помолись Святому Антонию. +А если захочешь у меня что-нибудь спросить, приходи во францисканский монастырь к брату Джованни. +Не знаю, правда, сможешь ли ты меня найти, я всегда так занят. +Эй, блондиночка! +Пока! +-Завтра? +-Завтра я работаю. +Тогда послезавтра, в то же время. +Я и послезавтра работаю. +Как же так? +Воттак. +По правде говоря, я хотела сказать, что мы больше не увидимся. +- Никогда? +- Никогда. +Это не значит, что ты мне не нравишься. +Но что проку в наших встречах? +Зачем всё это? +Мы просто теряем время. +Зачем? +Зачем, ответь +Зачем? +Ну ответь мне. +Хорошо. +Я хочу жениться на тебе. +Мне хотелось заговорить об этом раньше,.. +но у меня не хватало мужества. +Я хочу этого с первой нашей встречи. +Что ты говоришь +Ты бы женился на мне? +Ты что? +Женился бы на девушке, которую знаешь всего две недели? +Нет, это не разговор. +Благодари свою счастливую звезду, что я не такая, как другие. +Мы только познакомились, всего две недели назад. +Ты понимаешь, что ты говоришь +Соображаешь, что делаешь +Так нельзя! +Такими вещами не шутят. +Это нечестно! +Зачем ты так говоришь +Я ни о чём не спрашиваю. +И ничего не хочу знать +Всё неважно. +К чёрту предубеждения. +Потому что самое главное, что я понимаю тебя и хорошо знаю. +Ты и я – мы созданы друг для друга. +Ну уж. +Я хочу жениться на тебе, потому что ты нужна мне. +Не говори так. +- Ведь это несерьёзно. +- Серьёзно. +Ванда! +Ванда! +Ванда! +Что случилось, Кабирия, что? +Что? +Я выхожу замуж, вот что! +Я выхожу замуж, он просил моей руки! +Мы покупаем в Пирати магазинчик. +Он уже подписал контракт. +Я ничего не знала. +Он всё устроил. +Дом, магазинчик... +Я продаю дом, продаю всё! +День свадьбы мы назначили через две недели. +Ванда, я уезжаю! +А он знает, что ты ... +Да. +Я ему всё рассказала, ничего не скрыла. +Он ангел! +Он сказал, что это его не волнует. +Он меня любит. +Ванда, любит! +Ванда, кто-то на земле меня любит! +Кто там? +Здравствуйте, падре. +-Здравствуйте. +-Здравствуйте. +Можно увидеть брата Джованни? +Его нет. +А зачем вам брат Джованни? +Я бы хотела исповедаться. +Почему бы вам не пойти в церковь +Да, но я хочу исповедаться именно ему. +Исповедь действительна вне зависимости оттого, кому исповедоваться. +- Вы это знаете? +-Да, знаю, падре. +Но я хочу именно к брату Джованни. +- Хорошо, подождите. +- Спасибо. +Это тоже в чемодан. +А это я не возьму. +Сову брать +Нет, это приносит несчасть . +А раковину? +Думаю, да. +Воттак, возьму. +Ну-ка, посмотрим. +Отлично. +А это на продажу. +Кабирия, что за разорение? +Не надо всё бросать, тебе это понадобится. +А это? +Нет, всё на продажу. +Оставишь здесь, хорошо? +Это? +Но я же не дарю, я это всё продала, понятно? +Тащить с собой дороже. +И потом, он ведь тоже всё продал, и я должна. +Мы всё начнём сначала. +Всё начнём сначала, новую жизнь +На твоём месте я бы взяла вещи. +Ничего не забыла? +А что мне забывать +Деньпи взяла? +Как же я могла забыть о деньпах? +Ты оставила пуховую кофту. +Это старьё , выброси. +Выброси! +Можно взять для тёти? +Бери, если хочешь Они уже хотят внести вещи. +Да, им и вправду не терпится. +Закроешь мой чемодан? +Подожди, ещё мамино фото. +Мама. +Забавный этот мир. +Надо же, я выхожу замуж. +Что ты сказала? +Я выхожу замуж. +Что я сказала? +Ничего. +Как я выгляжу? +Как я выгляжу? +Потрясающе. +Она обошлась мне в две тысячи лир. +Очень мило. +Но ты слишком переплатила. +Ну где чемодан? +До свидания, Гарибальди! +В путь +Ванда, идём, идём. +Идём. +Посмотри на этих несчастных. +Когда я такое вижу, просто с ума схожу. +Ванда, пошли. +Вот ключи от дома, я ухожу. +До свидания. +До свидания. +До свидания. +Если вам что-нибудь понадобится, это моя подруга Ванда, она напишет мне. +- Пока. +- Приятного путешествия. +- Приятного путешествия! +- Спасибо, вам того же. +До свидания, дедушка! +Дедушка! +Я бы хотела попрощаться со всеми, это замечательно. +Я так счастлива, что вот упаду и расплачусь +Понятное дело, после стольких лет. +Привет, Чана! +Я уезжаю. +До свидания, Кабирия, до свидания! +Весёлой свадьбы ! +Попрощайся за меня со всеми. +Надо же, сегодня никого нет. +Кабирия, дай 10 лир! +- Милые, правда? +-Замечательные. +Скоро ты выйдешь замуж, а я даже не видела твоего жениха. +Ведь я твоя подруга. +Не могу же я привезти его сюда, где меня все знают. +Идёт. +Автобус. +Пока, Ванда! +Ну не надо, не плачь +-А кто плачет? +- Вот и хорошо. +Не волнуйся, я тебе напишу. +Как только приеду, сразу пришлю адрес. +Увидишь, ты тоже скоро выйдешь замуж. +Надо торопиться, давай чемодан. +Я пришлю тебе адрес. +Я пришлю тебе адрес. +Не забудь +Ванда, не беспокойся. +Жди. +Ты тоже выйдешь замуж, так же неожиданно, как я. +- Я надеюсь +- Всё сбудется. +Пока, Ванда! +Пока, Кабирия! +Пока! +Кабирия! +- Пожалуйста, я заплачу. +- Ну что ты , не стоит. +Но я была бы счастлива потратить свои деньпи. +За всё всегда ты платил, а ведь всё, что моё – это твоё, разве нет? +Да, конечно. +Официант! +Солнце садится. +Ты увидишь, как чудесны здешние закаты . +Ты хочешь, чтобы я напилась +Это ведь лёгкое вино. +Приданое. +Спрячь +Приданое. +350 тысяч - это всё, что они дали мне за дом. +Они знали, что я тороплюсь продать, и воспользовались этим. +Я забрала все деньпи из банка. +400, всего 750 тысяч. +Ты никогда не спрашивал, есть ли у меня деньпи. +Ты никогда не спрашивал, есть ли у меня деньпи. +Ангел святой, ты и предположить не мог, что у меня такая куча денег. +Я говорил, что не хочу об этом ничего знать +Пойдём отсюда. +Есть мужчины , которым нравится мучить женщин. +Их интересуеттолько одно: деньпи. +Ты не поверишь, но за любовь .. +за любовь я отдала бы все свои деньпи. +А они крадут деньпи. +Подумать только, в мои годы я кому-то нужна! +Прости. +Прости. +Официант, получите. +Идём. +Одно я знаю точно: рано или поздно но я бы изменилась, изменилась обязательно. +Я бросила бы всё. +Представляешь свою жизнь, похожую на мою? +Представляешь +Знаешь, что мы с Вандой хотели сделать +Мы хотели купить наркотик и забыться, забыться навсегда. +А куда мы пойдём? +Как здесь хорошо! +- Погуляем? +-Давай. +Не помню даже, с чего я начала. +Кажется, была ещё не очень старая. +Годы , годы . +А чемодан мой возьмём? +Нет, заберём потом. +Видел бы ты меня в 15 лет. +Какие у меня были волосы ! +Я была ужасно наивна. +Моя мать хотела только одного, чтобы я зарабатывала деньпи. +- Куда мы идём? +- Просто гуляем. +Пошли вниз. +Поцелуй меня, Оскар. +Спасибо, любимый. +Идём. +Я знаю короткую дорогу. +Оскар! +Оскар, куда ты пропал? +Плохой мальчик. +Я нарвала для тебя цветов. +Как замечательно они пахнут! +А пойдём ещё куда-нибудь Пойдём? +Хорошо. +Понюхай. +Какие это цветы ? +Какие? +Что с тобой? +Ты загрустил? +Я? +Нет. +Это потому, что я перестала петь +Давай вырежем наши инициалы на дереве. +Пойдём на озеро, посмотрим закат, там очень красиво. +Закат? +Я знаю, что у тебя на уме. +Ты и в самом деле хочешь смотреть закат? +Ты был прав. +Чудесно! +В мире всё-таки есть справедливость +Ты страдаешь, идёшь напролом через невзгоды , но, в конце концов, к каждому приходит его звёздный час. +Ты мой ангел. +У тебя руки холодные, ты замёрз? +Нет-нет. +О чём ты думаешь +Красиво, да? +Как там глубоко? +Хорошо бы взять лодку и доплыть до середины . +Интересно, там внизу есть лодки? +Ты умеешь плавать +Нет, нет, не умею. +Однажды меня столкнули в воду. +Я стала тонуть, но меня спасли. +Что такое? +В чём дело? +Что такое? +Ты ведь не убьёшь меня? +Не убьёшь +Ответь +Ты не убьёшь меня? +Отвечай! +Говори же. +Скажи. +Скажи! +Из-за денег? +Из-за денег, да? +Убей, убей меня! +Ну что же ты ? +Убей! +Я хочу умереть Я не хочу жить +Мне осточертела такая жизнь +Убей! +Убей меня! +Столкни меня в озеро! +Я не хочу жить Я хочу умереть +Я не собираюсь тебя убивать +Я только... +Тихо! +Ну давай, убей меня! +Ну давай! +Я не хочу жить, с меня довольно! +Убей меня, пожалуйста! +Я не хочу жить Только умереть +Дай мне умереть, убей меня! +Убей! +Маурицио, поторопись +Мы уже идём! +Мы идём домой, правда, я не знаю, как мы туда попадём! +Добрый вечер. +Берт Ланкастер +Кирк Дуглас +В фильме ПЕРЕСТРЕЛКА В О.К. КОРРАЛ. +В фильме также снимались: +Ронда Флеминг +Джо Ван Флит +Джон Айлэнд и другие. +Автор сценария: +Леон Урис. +Оператор: +Чарльз Ланг. +Композитор: +Дмитрий Темкин. +Продюсер: +Холл Би Уолис. +Режиссер: +Джон Старджес. +-Привет, Эд. +-Где Док Холидэй? +-Наверное в отеле. +Он ждал тебя уже... +-Скажи ему, что я жду его. +В этом нет нужды. +Весь город знает, что ты его ждешь. +Прежде чем... +Займись своим делом. +И не лезь в мои дела. +Твой брат пришел сюда пьяный и просил чтобы... +Виски! +-Он хотел убить его. +-Быстро! +Будь по-твоему, Эд. +Сдай оружие, если хочешь остаться. +Оставь бутылку. +У тебя нет шанса. +С Бэйли еще двое. +Дорогой, пора убираться отсюда пока не поздно. +Весь город, включая шерифа, точит на тебя зуб... +Они собираются повесить тебя за очередное убийство. +Ты это знаешь, Док. +Ты меня даже не слушаешь. +Кейт, мистер Бэйли приехал из форта, +-чтобы поговорить по-джентльменски. +-По-джентльменски. +Будет некрасиво, если я уеду из города. +Хватить болтать про джентльменские дела. +Дело в том, что ты... это то, что ты не совсем понимаешь. +Почему ты всегда обращаешься со мной, как будто я дерьмо? +Ты не лучше, чем я. +-С этим можно поспорить. +-Правда? +Что ты говоришь? +Вот что я тебе скажу, Док. +Твое пижонство и умная болтовня не делают тебя джентльменом. +Ты такое же дерьмо как и я. +И я устала это слышать. +Плантация в Джорджии и все твои друзья. +Их давно уже нет, давно! +Давно! +Их уже нет, но я с тобой. +Твоя семья не пошевелила даже пальцем, чтобы позаботится о тебе после войны. +Ты действительно хорош. +Они тобой так гордятся. +Не смей говорить о моей семье в таком тоне. +Док, пожалуйста... +Док, пожалуйста... забудь о Бэйли. +Давай уедем отсюда. +Может быть... может поедем в Лоредо. +Ты же сам говорил, ты же хотел поехать туда. +У нас еще есть время. +Твое беспокойство меня очень трогает. +Ты знаешь, что я чувствую к тебе. +Я знаю, что ты чувствуешь. +Я не знаю, не знаю, что буду делать, если с тобой что-нибудь случится. +Тебе не на что будет жить. +Не говори так, Док... +Я хорошо относилась к тебе. +Почему ты обо мне никогда не думаешь? +Иди к Шэнси. +Скажи, что я сейчас буду. +-Не ходи туда. +-Делай, что говорят. +Мне нужны деньги. +Уайт Эрп. +Котон Уилсон... +Давно не виделись. +Я планирую уйти со службы. +Для меня новости есть? +Клэнтон проезжал мимо, три дня назад и отправился на восток. +Джонни Ринго был с ним. +На восток? +Ты не получил телеграмму? +Получил. +Почему ты его не задержал? +У меня на него ничего нет. +Его не за что задерживать. +Не за что? +На нем висит куча преступлений. +Я все спланировал, чтобы он попался тебе в руки. +Один человек в Техасе смог бы его задержать. +-И это ты. +-Хватит молоть чушь, Эрп. +Котон, ты меня знаешь. +10 лет назад я покровительствовал тебе в Оклахома Сити. +Помнишь, как ты подстрелил самых кровожадных стрелков? +10 лет это очень много. +Я становлюсь старым. +Никто не говорил мне, что Котон Уилсон стал трусом. +Ты не имеешь права так говорить со мной, Эрп. +Я был один на один с самой кровожадной бандой. +Почему ты не задержал Клэнтона? +Не справляешься, тогда верни значок. +Я верну значок... +Я защищал закон 25 лет. +Мною затыкали все дыры. +И знаешь, что у меня есть? +Комната за 12 баксов в месяц и старенький домик. +Думаешь, мне нравится так жить? +Это тупик, Эрп. +Когда-нибудь ты это поймешь. +Это происходит со всеми нами. +Где этот ублюдочный трус? +Не торопись, Эд. +Он заставляет тебя нервничать. +Почему Холидэй задерживается? +Хочет, чтобы они понервничали... +Уайт Эрп. +Как давно тебя не видел. +Почему не сказал, что едешь? +-Рад тебя видеть. +-Привет, Шериф. +Сигару? +Будь я проклят. +Наверное, издалека приехал. +Сначала Элсворт, Уичита, а теперь Додж Сити. +Никогда не думал, что станешь шерифом. +Ты всегда был дикарем. +Я и сам не думал. +Стэйк из моего запаса. +Как братья? +-Они женятся. +-Женятся? +Ничего себе. +-Мне нужна помощь. +-Все, что угодно. +Клэнтон и Джонни Ринго. +Три дня назад. +Против них много обвинений. +Я просил Котона их задержать, но он облажался. +-Котон струсил. +-Ты что-нибудь знаешь? +Вряд ли, хотя, минутку. +Док Холидэй играл с ними в покер. +Может он знает. +Бармен! +Бармен! +Подай еще виски! +Эд Бэйли, Док убил его брата. +Сам напросился. +Пришел пьяный, жульничал в карты. +Наставил на Дока пистолет. +Ты знаешь его? +Да, мы встречались, он был дантистом. +Он отлично дерется. +Проблемы всегда его находят. +По-моему, он даже участвовал в битве при Бут Хил. +Представляешь, он заработал себе там репутацию. +Это точно. +Где он? +Нужно найти его пока не поздно. +В отеле. +-Стэйк подождет, я скоро вернусь. +-Никуда он не денется. +Холидэй. +Садитесь, будьте как дома. +Не стесняйтесь. +Не знаю, помните ли... +Помню, конечно, Уайт Эрп. +10 лет назад лечил вам зубы. +Если бы я знал, что встречу вас через 10 лет, то просто... +Я слышал, вы занялись другим делом. +Плохо, вы были хорошим дантистом. +Пациентов раздражал мой кашель. +Мне нужна информация. +Эта игра называется пасьянс. +Давайте поторгуемся. +-Добрый вечер, мистер Эрп. +-Вас могло бы это заинтересовать. +Вы не знаете ничего, что могло бы меня заинтересовать. +У мистера Бэйли есть маленький пистолет, который он прячет в ботинке. +-В левом или правом? +-В левом. +Отлично, Бэйли левша. +Как Клэнтон и Ринго, которые были здесь 3 дня назад. +Вы играли с ними в карты. +Куда они поехали? +Не знаю. +-Мы же заключили сделку. +-Вы так сказали, а я не заключал сделок. +-Вы знаете, куда они поехали? +-Послушайте, вы мешаете мне играть. +Вы ненавидите закон, да? +Есть причина, по которой я не должен? +Ваш брат, Морган, обманул меня и забрал 10000 долларов. +И кстати, ваши братья позволяют себе все, что угодно. +Увидимся, Холидэй. +Если будете поблизости. +-Узнал что-нибудь? +-Ничего. +Мне кажется, они поехали в Тумбстоун. +Там у него ранчо. +Но я не уверен. +-Твой брат шериф Тумбстоуна? +-Именно. +Я послал ему телеграмму, чтобы он был настороже. +Что будешь делать? +А что я могу поделать? +Я не знаю, где они. +Утром поеду в Додж Сити. +-Мистер Холидэй. +-Да. +Оплатите ваш счет за проживание... я хочу сказать, что мы не знаем, съезжаете вы или нет. +Узнаешь через 15 минут. +Ты заходишь в опасное место, Док. +Если Бэйли не убьет тебя, то шериф всегда начеку. +Будь умнее, лучше уезжай... +Такое впечатление, что ты хочешь, чтоб тебя убили. +Может быть. +Добрый вечер, Холидэй, сдай свой пистолет. +Добрый вечер, Гарри. +Как обычно. +Да, сэр. +Я слышал, что приехал господин, который хочет поговорить со мной. +Он лучше бы научил своего брата играть правильно в карты. +Если ты увидишь этого господина, то скажи, что я буду ждать его в Бут Хилл. +Оттуда он сможет отправиться только в одно место... в могилу. +Я тут подумал, оказывается, он и не джентльмен вовсе. +Настоящий трусливый сукин сын. +Ну что, Док, пошли. +Конечно... +В чем меня обвиняют? +-Что-нибудь придумаем. +-Не сомневаюсь. +Спасибо, Гарри. +Уберите его отсюда. +Все кончено. +Хватит. +Все к барной стойке. +Бесплатная выпивка за счет заведения. +Дай-ка мне пивка. +После убийства такой беспорядок. +Док испортил всем настроение. +Он безумец, но очень смелый. +Что будешь делать, Эрп? +Ты же сам видел, они не имели право его забирать. +Они не имели права это делать. +-Кейт, его подруга. +-Его подставили. +Бэйли хотел убить его. +Мисс Фишер, расслабьтесь и успокойтесь. +Закон разберется. +В этом городе нет закона. +Не видел человека, который хотел бы, чтобы его убили. +-Вы должны ему помочь. +-Он меня не касается. +-Пожалуйста. +-Это не мое дело. +Он мне даже не нравится. +Извините, спокойной ночи. +У меня есть лошади, мы могли бы отдать их за проживание в отеле. +Это все, чем я могу помочь. +Мне очень нравится Док, но к сожалению, я ничем не смогу ему помочь. +10-ый номер... +-Здесь живет Уилсон? +-Нет, сэр. +Здесь только Док Холидэй. +Он в своей комнате. +-Мистер Эрп. +-Я уже сказал, это не мое дело. +Мне плевать, что вы о нем думаете. +На улице происходит нечто ужасное. +Это уже вас касается. +И не важно, прав ли Док или нет. +Он не заслуживает, чтобы его подвесили как животное. +Нужно уходить. +С каких пор вы спасаете ублюдков от виселицы? +Ничего личного, не люблю линчевания. +-Чего мы ждем? +-Рано. +Сейчас самое время. +Горит сарай Страджеса! +Пора. +Выходи через черный ход. +Спасибо, шериф. +Увидимся в Додж Сити. +-Еще раз спасибо. +-Держись подальше от Додж Сити. +Давайте воду! +Быстрее! +Граница. +Ничего себе. +-Таким не место в Додж Сити. +-Она наверняка из большого города. +Похоже, она хочет остаться. +Здорово. +Кое-что нужно обсудить. +На самом деле, я приехал по делу. +Шеф Далкниф в ярости. +Мне нужны твои представители. +Тебе всегда не хватает людей. +-Кто эта девушка? +-Да, кто? +Какая девушка? +Я узнал, что Док Холидэй и его девушка только что приехали в отель. +Док Холидэй? +Я же сказал ему не приближаться к Додж Сити. +Пойду навещу его. +-Дашь мне своих представителей? +-Хорошо, но Чарли останется со мной. +Возьмешь остальных. +Не забудь вернуть их до приезда фермеров, ты же знаешь, как нам будет трудно без них. +Марио, иди прогуляйся. +Пришел поприветствовать меня? +Я говорил тебе, чтобы ноги твоей здесь не было. +Люблю острые лезвия, а ты? +Хочешь побриться? +У нас сегодня собрание. +Я хочу, чтобы ты пришел. +Не могу. +Шериф Абелины послал меня сюда. +Кстати, пусть вам кто-нибудь напишет новую речь. +Слышу одну и ту же в каждом городе. +Тогда останешься в отеле до послезавтра. +Потом я посажу тебя на поезд и ты уедешь. +Уайт, какой ты жесткий. +Я в состоянии полного банкротства. +Мне не на что даже купить билет. +Шэнси сказал, что у тебя было целое состояние в Гриффине. +А он не сказал, что 10000 долларов лежат в его сейфе? +Знаешь, что он сделал? +Ты сказал, что я должен покинуть город, а те две лошади возле отеля обошлись мне в 5000 долларов каждая. +Как тебе это? +Полотенце, пожалуйста. +Спасибо. +Всех так и тянет покуситься на мою жизнь. +Уайт... сколько тебе платят? +100 долларов в месяц и 2 доллара за арест? +-Хочешь подкупить меня? +-Нет, не тебя. +Хочу предложить тебе сделку. +Неплохо. +-Сбережения есть? +-Немного. +Хочешь купить ранчо или магазинчик? +Давай все упростим. +Забираешь мои 10000, и я иду на все четыре стороны. +Деньги имеют свойство накапливаться. +50 на 50, да? +Любому другому я бы отдал 10 процентов, но ты мне нравишься. +Мне нравится твоя стрижка. +Мне нравятся такие прически. +А почему так щедро? +Парикмахеру нужно это, шерифу нужен пистолет. +А я картежник. +Деньги это всего лишь инструмент в моих руках. +И ты гарантируешь, что ты исчезнешь? +Я никогда не исчезаю. +Игроки в покер любят деньги. +Я никогда не проигрываю, потому что мне нечего проигрывать, даже свою жизнь. +Договорились? +Ну ты даешь. +Ну что ж, тогда тебе придется купить мне билет на поезд. +Холидэй, я совершил много ошибок. +И совершу еще одну. +Я позволю остаться тебе в городе. +-Это почему же? +-Мне нравится твоя прическа. +Останешься здесь и будешь играть при одном условии. +Никаких ножей, пистолетов и убийств. +Никаких ножей, пистолетов и убийств. +Именно. +Даю слово джентльмена. +И еще кое-что... +Или ухаживай за той девушкой, +-или брось ее. +-Кейт? +Бедняжка Кейт. +Она любит то, что я ненавижу в себе. +Заплати парикмахеру, хорошо? +Я кое-что узнал об этой девушке. +Где ты взял это? +Сделали для меня. +Что на счет леди? +-Очень длинный ствол. +-В самый раз. +-И приклад какой-то... +-Что ты несешь? +Девушка, которая приехала позавчера. +-И что? +-Она сейчас в баре. +Говорят, что у нее целые чемоданы прекрасной одежды. +Некоторые из Франции. +Она высокая, весит 120 фунтов, светлые волосы, +-зеленые глаза... +-Что она здесь делает? +-Играет. +Очень смешно. +Если думаешь, что это смешно, тогда возьми и сам посмотри. +Ты умрешь от смеха. +Привет, Уайт. +В чем дело? +Придется прервать вашу игру. +Не могу, Уайт. +Женщины имеют право играть. +Знаю, но каждый раз, когда женщина за столом, всегда возникают проблемы. +Игра закончена. +-Уайт, это Лора Дэнбо. +-Ты мэр этого города. +Мы договорились с тобой об этом. +У мисс Дэнбо много своих магазинов +-и она исключение. +-Только не в Додж Сити. +Значит, это вы Уайт Эрп? +-Шериф, судья и присяжный. +-Да, мэм. +Начиная с вас и заканчивая Южной стороной. +Кто этот ублюдок? +-Заткнись и не лезь не в свои дела. +-Ты разговариваешь с леди. +-Похоже, шериф раньше не встречался с леди. +-Вы играете в мужскую игру. +Поэтому я и обращаюсь с вами, как с мужчиной. +Ты не джентльмен. +-На этом и остановимся, мисс Дэнбо. +-Не трогай ее. +Стой Чарли. +Я устал от твоих нравоучений. +Доставай пистолет, я убью тебя. +У меня нет пистолета, ковбой. +Я безоружен. +Не подходи! +Ты пьян и не ведаешь, что творишь. +Отдай пистолет, пока не начались серьезные проблемы. +Я не потерплю, чтобы так разговаривали с леди. +Стой спокойно... и отдай мне пистолет. +Я не стрелок... +Я все равно бы никого не убил. +Я знаю, ковбой. +Ты просто хотел поразить леди. +Чарли, отведи его, пусть умоется, и выведи его из салуна. +Вы арестованы. +-За что, мистер Эрп? +-За нарушение порядка. +Минутку, Уайт. +Все нормально, шериф пытается спасти репутацию Додж Сити. +Кроме того, я люблю проводить время в тюрьме. +Может, позовете своих помощников? +Я очень отчаянная. +Я вас отпущу, если пообещаете, что не будете играть в этом районе. +В этом районе? +Нет, я уж останусь. +Возможно, судья не такой правильный, как шериф. +Вы не откроете дверь? +Знаете, мне это пока не понадобится. +Купите себе новую шляпу. +А то эта маловата. +Закройте дверь, шериф. +-Посадил ее? +-За нарушение порядка. +-Я вытащу ее. +-500 на то, что не сможешь. +Давай 1000, и я ее вытащу. +Удваиваешь или нет? +Договорились. +Вернусь через 30 минут. +-Добрый вечер, Чарли. +-Привет, Док. +Господи, как же я устал за сегодняшний день. +Я провел полжизни за бумажной работой. +Выпить хочешь? +Док, ты же знаешь, что я не пью на дежурстве. +Что за праздник? +Хочу вытащить мисс Дэнбо. +Давай. +19. +20. +Не могу, Док. +У нее завтра суд. +Под залог нельзя. +Хватит. +21. +Тогда подожду Уайта. +Не думаю, что он скоро вернется, Док. +-Блэкджэк. +-И у меня. +Если бы мы играли по настоящему, то я бы захотел взглянуть на колоду карт. +Тогда попробуй. +Держи мой. +Хорошо, что Эрп не разрешает носить такие штуки, кто-то может пострадать. +Пойду посмотрю как там заключенные и лошади. +-Присмотри за офисом, Док. +-Конечно, Чарли. +-Никогда у меня не было столько ружей. +-Что ты здесь делаешь? +Пришел выкупить мисс Дэнбо. +Она же все-таки леди. +Ни каких поблажек. +Тогда освободи ее в обмен на информацию. +Ты не знаешь ничего, что меня может заинтересовать. +А если я тебе скажу, Шингхай Пирс едет сюда с головорезами? +Шингхай Пирс? +Похоже, ты не ладишь с ним. +Я хорошенько ему врезал, когда он напился и решил меня подстрелить. +Он не плохой парень, просто заносчивый. +Он собирается перестрелять весь Додж Сити. +И он нанял Ринго, чтобы ты не испортил веселье. +И самое главное... +Он назначил цену за твою голову в 1000 баксов. +А что еще? +Я думал, ты удивишься таким новостям. +Холидэй, пока я здесь шериф, никто из них не посмеет приехать сюда с оружием. +И мне плевать, что его зовут Шингхай Пирс. +Отлично сказано. +Повторю эти слова на твоих похоронах. +-Так как на счет мисс Дэнбо? +-Забудь об этом. +Мы же договорились. +Ты договорился. +А я не соглашался, ты помнишь? +Чарли, ты работаешь на мошенника. +-Правда? +-Иди домой, я еще посижу. +-Спасибо. +Спокойной ночи. +-Спокойной ночи. +Уайт, отпусти ее. +Она ничего такого не сделала. +Думаю, Чарли прав. +Выпусти ее. +Совесть? +Может, она мне нравится. +Скажи ей, чтобы играла в другой комнате. +Не хочу, чтобы она светилась на первом этаже. +-Добрый вечер, мисс Дэнбо. +-Добрый вечер. +-Выходи, у нас еще куча дел. +-Спасибо. +Шериф? +-Приятного вечера, мистер Эрп. +-Вам тоже, мисс Дэнбо. +Приятного вечера, мистер Эрп. +Пара тузов. +Посмотрим, что у леди. +-50. +-Мне еще. +-50, мне еще. +-Договорились. +Еще 50. +Док, нам пора. +Уже почти утро. +Ты слышишь? +Почему ты молчишь? +-Еще 100. +-Док. +Купи себе выпить. +-Поднимаю ставку. +-Для меня многовато. +Еще 200. +Поддерживаю леди. +4 туза. +-Господа, мы облажались. +-Спасибо, господа, мне пора. +Выдай мне деньги. +Спокойной ночи. +-Можно вас проводить? +-Спасибо, Док. +-Спокойной ночи. +-Спокойной ночи. +-Еще разок сыграем? +-Давай. +-Тетушка бы моя не помешала. +-Спокойной ночи. +Где Люк Шорт? +Ричи Бэл и его ребята грабанули банк в Салине. +Убили кассира, едут сюда. +Я послал его в Абилин. +Когда ты собираешься ехать? +Немедленно. +Нужно только напасть на след. +Люк - единственный, кто умеет стрелять. +А как же Чарли? +Кто-то должен присматривать за городом. +Нужен стрелок? +Ты? +Нет, спасибо. +Я неплохой стрелок. +Проблема в том, что все мои враги не могут этого подтвердить. +-Сам справлюсь. +-Как хочешь. +Подними правую руку. +Клянешься ли ты... +Это смешно. +Я беру тебя. +Собирайся, я приготовлю лошадей. +-А мне не полагается звезда шерифа? +-Только не при жизни. +Лекарство? +Для умного игрока, у тебя куча пристрастий. +Ты не протянешь и года. +А что ты знаешь о пристрастиях? +Этот кашель не излечим. +Тогда забудь про эти вонючие салуны. +Поезжай в горы и живи там. +Только не я. +Да, ты привык жить рискуя. +Нет, пусть кашель высушит мое тело медленно. +Точно. +Жить быстро, умереть молодым. +Уайт, меня беспокоит лишь смерть в постели. +Не хочу, чтобы это тянулось долго. +Когда-нибудь меня все равно убьют. +И это будет очень быстро. +Эрп, я приехал сюда не для того, чтобы выслушивать твои речи. +Меня всегда это интересовало. +Зачем ты приехал? +Если я буду заниматься одним и тем же делом, рано или поздно ты сунешь нос в мое дело. +Вот так-то. +-Я не хочу остаться твоим должником. +-Ты ничего мне не должен. +Мне никто ничего не должен. +И уж точно, не Док Холидэй. +Смотрю, тебе это нравится. +Насколько я знаю, ты можешь сесть на лошадь и ускакать. +Нет, спасибо, я пожалуй, останусь. +Знаешь, мы с тобой очень похожи. +У нас есть пушки. +Только у меня значка нет. +В чем дело, священник? +Не нравится, когда тебе причитают? +Заткнись и ложись спать. +Ричи Бэл больше не будет грабить банки. +Я думал, ты спал. +Нет, я думал. +Возвращаемся в Додж. +Хочу лечь в постель. +Зачем? +Она не убежит. +Я уж точно, спать не хочу. +Не ходи в эти грязные салуны. +Поезжай жить в горы. +Чарли. +Привет. +Пойду составлю рапорт. +Спасибо, Док, теперь мы в расчете. +Пока нет. +Пока долги не выплачены сполна. +Слышал, ты хорошо стреляешь. +Ну, я готов поработать помощником. +Все нормально? +Найди Кейт и скажи, чтобы пришла немедленно в отель. +Я уже давно не видел Кейт, Док. +В смысле? +Никто не видел ее с тех пор, как ты уехал. +Позвать врача? +Доброе утро, Лора. +Не думала, что буду рада вас видеть. +-Что случилось? +-Лошадь хромает на правую ногу. +Подкова треснула. +Лучше пока не ездить на ней. +Оставьте ее здесь. +Я пришлю кузнеца. +Хорошо, что вы едете один. +Это не случайно. +Я знаю, что каждый день вы проезжаете здесь. +Я подвезу вас до города. +Или вы хотите пойти пешком? +Держитесь крепче. +Еще крепче. +Что вы здесь делаете, Док? +Сейчас только 3 часа. +Оздоровительная прогулка. +Нужно пройти 20 ярдов. +Что тут происходит? +Приводим в порядок стадо к приезду ковбоев. +Не хотите, чтобы Бэт возвращался? +Хотя, наши помощники шерифа... +А где Кейт? +Где она, Чарли? +Очень тяжело объяснить, Док. +Я... +Слушаю... +Вы обещали Уайту, что не будет никакой перестрелки. +-Вы не... +-Где она, Чарли? +В отеле Уолли. +Ринго приехал в город и забрал с собой Кейт на 3 дня. +Похоже, намечается небольшая резня. +Это только начало, подождите. +Уайту сейчас перестрелка ни к чему. +Это лишние проблемы. +Скот перемешался в стаде. +Проваливай отсюда, ублюдок! +И больше не возвращайся! +Унеси меня. +Я готова полюбить тебя, а его оставить. +Значит, ты заболела. +-Так, так. +Пришел закон. +-Тебя не было 3 дня. +А я думала, ты не заметишь. +А ты ищешь меня по всей стране. +Я болел, Кейт. +Ты нужна была мне. +Тогда накинь-ка веревку на мою шею и води за собой, если я тебе нужна. +-Как всегда. +Опять все сначала. +-Оставь меня в покое, Док. +Всегда поворачиваешься спиной. +Если бы ты замечал меня, то я бы не делала этого. +Какая тебе разница, куда и с кем я хожу? +Заткнись! +Собирай вещи, ты уезжаешь. +Она остается. +-Это не твое дело, Ринго. +-Ты не имеешь право сюда входить. +Я разговариваю с Кейт, а ты гуляй. +Говори в его присутствии. +-Шлюха. +-Минутку. +Не смей разговаривать так с моей женщиной. +-Твоей женщиной? +Это женщина каждого. +-Я разорву тебя на части. +Я безоружен, Ринго. +Теперь нет. +Бери. +-Я не буду стрелять. +-Не будет. +Он обещал Эрпу, что будет послушным. +Я слышал, что хорошо умеешь расправляться с алкашами. +Так давай, бери. +Не буду. +Тогда выпей. +Док. +Мне понравилось танцевать. +Жаль, но мне нужно идти. +Вы разбили многим сердце. +-Спокойной ночи. +-Спокойной ночи. +Могу я вас проводить? +-Спасибо, мне не далеко. +-Мы могли бы прогуляться. +Здесь так прекрасно. +Я рада, что приехала сюда. +У вас поменялось выражение лица. +Вы выглядите как маленькая напуганная девочка. +Я не напугана и уж точно, не маленькая девочка. +Почему вы поехали со мной? +Хотела бы ответить на ваш вопрос. +Но я не знаю. +Тогда я отвечу. +-Отличная стрельба, да Ринго? +-Да. +Это им урок на всю жизнь. +-Мы - хозяева таких городов. +-Точно. +Шингхай Пирс в городе. +Его люди громят улицу. +Найдите Уайта и приведите помощь. +Я постараюсь их задержать. +Никто не должен выходить на улицу. +Пирс, угомони своих людей, пока никто не пострадал. +Передай своему Боссу, что я жду личного приглашения. +-Ты арестован, Пирс. +-Ты слышал? +Я арестован. +Я слышал. +Очень шумно. +Очень. +Хватит играть. +Пора уходить. +Хватит болтать, я еще не доиграл. +Еще. +Пожалуйста, Док. +Договорились. +Что тут у нас? +Танцы. +Разве это не прекрасно? +Приглашаете нас на танец? +Не очень гостеприимно. +Забирай своих выродков и проваливай отсюда. +Слышали? +Это уважаемые люди. +Деньги они всегда готовы забрать. +А мои люди готовы потанцевать с вашими женщинами. +Мои ребята хотят танцевать! +Пианист, музыку! +Живее! +Привет, Шингхай. +Ну что ж, мои дни сочтены. +Ты ответишь за этот шрам, который ты нанес мне в Вичите. +Сдайте оружие и пройдемте со мной. +Лучше молись, Эрп. +-Твой блеф не сработает. +-Подумай, прежде чем навлечь на себя беду. +Убирайся отсюда. +-Давай надерем ему зад, босс. +-Отличная идея. +Пусть твои друзья посмотрят, на сколько ты крут. +Хочу посмотреть как ты танцуешь, шериф. +Храбрые изречения, когда за тобой 20 человек. +Давай выйдем и сразимся один на один. +Нет, даже и не пытайся. +Все время блефуешь, да? +Ну что ж, ребята, взять этого ублюдка. +Господа, вы так много шумите, что я было уже испугался. +Вы испортили мне игру. +Веселье закончено. +Сдайте оружие. +Перестреляем их. +-Ну что, Шингхай? +-Давайте, попробуйте. +Ты первым получишь пулю. +-А ты вторым, Ринго. +-Начнем, босс. +Даю вам 5 секунд, чтобы сдать оружие. +1... 2... 3... 4... +-Хватит, ребята. +Сдайте оружие. +-Гэрри, Джэк, заберите оружие. +Быстрее. +Док! +Кто еще хочет испытать удачу? +Пошел, давай, шевелись. +Док, это еще не конец. +Могли бы закончить, но я сегодня добрый. +Быстрее! +Шевелитесь. +-Келли, отведи их и запри на всю ночь. +-Вы слышали шерифа? +Шевелитесь. +Думаю, ты не ждешь благодарности. +Теперь мой долг отдан сполна. +Ничего личного, шериф. +Доброе утро, Док. +Доброе утро. +Подумал, что тебе будет полезно узнать, что одним шерифом станет меньше. +Для меня это хорошая новость. +Я еду в Калифорнию. +Куплю ранчо и уеду, пока не поздно. +Умно. +Лора едет со мной. +Мы поженимся через несколько дней. +Я приглашаю тебя на свадьбу, если это не мешает твоей игре. +С меня нет толку на свадьбах, только на похоронах. +Уайт, я не поеду. +Она хорошая женщина. +Желаю вам счастья. +Тебе повезло, уезжаешь из этих мест. +Может, и ты попытаешься? +Увидимся, Док. +Я хочу вернуться, Док. +Пожалуйста. +Дай мне шанс. +Позволь мне вернуться. +Я сделаю все, что захочешь. +Мне плевать на то, как ты со мной обращаешься. +Прости за мои выходки. +Ты не виновата, я не виноват, никто не виноват. +Просто, так легла карта. +Я никогда не давал тебе шанса. +Может быть, все было бы по-другому. +Еще не поздно, Док. +Обещаю, что стану хорошей женой. +Слишком поздно для нас обоих. +Пока есть шанс, найди себе получше мужчину. +Не отпускай меня, Док. +Не отпускай меня. +Оставь меня в покое. +Оставь меня в покое. +Надеюсь увидеть тебя мертвым. +-Привет, Уайт. +-Привет. +Письмо от генерала. +И что там? +Пишет, что готов сделать тебя шерифом США, когда захочешь. +Уайт Эрп, шериф США, все что нужно. +Они все мертвы, Чарли. +Да, чуть не забыл... +Он твой. +Я покончил с законом. +-Пришла телеграмма. +-Читай. +Вирджил мой брат. +У него проблемы, я нужен ему. +Пойми, Лора. +Какая же я дура, что влюбилась в тебя. +-Если бы я мог... +-Уайт, когда я тебя встретила, я подумала, что не смогу следовать за тобой из города в город и ждать новостей о твоей смерти. +Я так не могу. +Мы не можем начать совместную жизнь, когда на тебя наставлен пистолет. +-Клянусь, Лора. +Тумбстоун и все. +-Это не кончится. +Твоя репутация всегда будет следовать за тобой. +-Он мой брат. +-А я будущая жена. +-Я не могу его бросить. +-Не бросай меня. +Я брошу все, поеду за тобой. +Буду работать с тобой в поле, но ты должен обещать мне. +Я должен ехать в Тумбстоун. +Давай, зачисти весь Тумбстоун. +Таких городов множество и все они ждут великого Эрпа. +Давай, перестреляй всех бандитов. +Поезжай! +Я люблю тебя, Лора. +Я люблю тебя, Уайт. +Добрый день, шериф. +Решил прокатиться? +Да, 700 миль. +В Тумбстоун? +Я и сам туда еду, может, кашель пройдет. +С каких пор ты заботишься о здоровье? +Немало важен и финансовый вопрос. +Никто уже не хочет со мной играть. +-Не против, если я поеду с тобой? +-Это свободная страна. +Где твое снаряжение? +Кладбище Бут Хил. +Тумбстоун. +Спасибо что подбросил. +Если хочешь, продай мою лошадь. +Док. +Знаю, никаких ножей, пистолетов и убийств. +Как здорово. +Я уже забыл, что такое домашняя еда. +Бэтти, я украду тебя у Вирджила. +Ты единственный, кто не женат. +У меня семья в Дэдвуде, даже маленький Джимми пытается жениться. +Что значит маленький? +Мне скоро 19. +19? +Когда ты женишься, Уайт? +Сигару? +Это сигнал для женщин и детей покинуть комнату. +Идем, Томи, пора спать. +Обязательно? +Да, обязательно. +Увидишь дядю завтра. +-Спокойной ночи, дядя Уайт. +-Спокойной ночи. +-Спокойной ночи, дядя Морган. +-Спокойной ночи. +-Спокойной ночи, дядя Джим. +-Спокойной ночи. +-Спокойной ночи, папа. +-Спокойной ночи. +Мы рады, что вы приехали. +Надеюсь, вы приехали не по работе. +Она чем-то расстроена. +Она просит меня уйти с работы. +Ты же знаешь женщин. +Перейдем к делу. +Морган и Джимми уже в курсе. +Ты знаешь Клэнтона. +У него есть ранчо за пределами города. +Да, я знаю. +Он организовал банду головорезов и держит шерифа округа под контролем. +-Кто он? +-Котон Уилсон. +Котон Уилсон. +Он работает на него. +Клэнтон забирает у мексиканцев скот. +Он должен перегонять его, но единственный путь через Тумбстоун. +Но он не сделает этого, пока мы контролируем город. +Вот так. +У него много людей и все они отличные стрелки. +-Мы не можем отбивать его атаки вечно. +-А что на счет жителей Тумбстоуна? +Джон Клам, издатель газеты, и некоторые люди, готовы помочь нам, если нужно. +Мы думаем, что нужно покончить с этим. +Меня беспокоит одно, и я скажу об этом. +Будет много разговоров о том, что ты приехал с Холидэем. +А что не так? +Он самый отчаянный убийца, вот что. +Плохо, что ты приехал с ним. +Холидэй спас мне жизнь в Додж Сити. +Я этого не забуду и он человек слова. +Пока он играет в карты и не убивает, мы не имеем право выгнать его. +-Не знал, что вы команда. +-Мы не команда. +Это наше с ним дело. +Он останется. +-Только под твою ответственность. +-Отлично. +Есть карта округа? +Мы должны сказать Клэнтону, что для него город закрыт. +Тогда мы сможем контролировать округ. +Я передам письмо, которое отвезет один человек. +Где находится ранчо Клэнтона? +Вот здесь. +Привет, я ждал тебя. +Отлично выглядишь. +Здорово. +-Не жалуюсь. +-В чем дело? +Клэнтон хочет заключить сделку. +Обещает тебя не беспокоить, если позволишь забрать весь скот из Тумбстоуна. +-Это здорово. +-Он отличный парень. +У него полно скотины и он собирается перегнать ее в другое место. +Правда? +20000 наличными. +20000 долларов? +Плата за грехи растет. +20000 против могилы в Бут Хиле. +Или 20 долларов в месяц, если выживешь. +Я уже думал об этом. +Знаешь, Котон, это хороший маленький городок. +Отличное место. +Возможно, я скоро стану шерифом округа. +Я этого не боюсь. +У меня есть все. +25000 на счету и ранчо. +Знаешь что? +-Сплю я очень крепко. +-А я нет. +Хватит упрямиться. +Элсвот, Вичита, Джодж Сити. +Может, сжалишься хотя бы над своей женщиной. +Хватит уже смертей. +Передай это своему боссу. +В пределах города Тумбстоун ношение оружия запрещено. +Значит, этого он хочет? +Он не хочет, чтобы ты контролировал город. +Давно не видались. +-Слишком давно. +-Привет, Ринго. +-Все еще носишь свой пистолет? +-Да, шериф. +А ты не слишком молод, чтобы носить пистолет? +Может, проверишь? +Куда-то собрался? +-На шоу, шериф. +Есть возражения? +-Нет, если вы сдадите оружие. +А ты сдай свое. +Стой! +Моих братьев вы знаете. +Джон Клам из общества горожан. +Ты мертвец, Уайт. +В этом городе для тебя нет места. +Приедешь с оружием, уедешь в гробу. +Проваливай. +-А вот и проблемы. +-Кто это? +Кейт Фишер. +Не сидится ей дома. +4. +Мне не нужно. +Бармен, принеси виски. +Оставь бутылку. +Две пары. +Туз. +Док, что у тебя? +Три. +Отличный городок, Кейт. +Так, так, так. +Помощник шерифа. +Док, раздавай. +Не поздороваешься со старым другом? +Ровно. +Дай мне Крим Дэ Мэнтре. +Помощник шерифа. +Не хочешь со мной выпить? +Ты пьян, Ринго. +Ты свою репутацию заработал на алкашах. +Доставай пистолет. +Встретимся на улице через 5 минут. +Я приду. +Надеюсь увидеть тебя мертвым. +Что ты себе позволяешь? +Клэнтону только и нужна война. +С меня хватит. +Хочешь с ним сопли разводить, пожалуйста. +Давай пистолет, Док. +Ты не имеешь права носить его. +Ты... благодари бога, брат Уайта Эрпа. +Холидэй, если тебе не нравится Уайт, то проваливай. +Ему не хватало такого убийцы, как ты. +-Слышал, ты уезжаешь. +-Именно. +Уезжаю завтра. +Я думал, что здешний климат поможет тебе. +Священник, мое пребывание здесь очень проблематично. +Некоторые думают, что я шериф. +Ты уезжаешь не из-за меня? +Из-за тебя? +Ты тут не причем. +Удачи, Док. +Жаль, что к финишу мы придем не вместе. +Привет, Уайт. +Тут пришло письмо. +В чем дело? +Младший Клэнтон напился в салуне. +Положите его на скамейку, пусть проспится. +Минутку. +Сколько потребуется времени, чтобы собрать людей? +Недолго. +Мне придется съездить на ранчо Клэнтона. +-Ты спятил? +-Я не думаю. +-Возьми пистолет. +-Только это мне и нужно. +Если не вернусь через пару часов, пусть граждане города будут готовы похоронить меня. +Ранчо Клэнтона. +Билли! +С ним все нормально. +Перебрал немного. +Вставай. +Иди домой, Билли. +Не знаю, что делать с этим парнем. +Он закончит как и его отец. +Его пристрелят за воровство скота. +Думаешь ты крут, сынок? +Не видел стрелка, который бы дожил до 35 лет. +Я знаю одно на счет стрелков. +Всегда найдется человек, который быстрее чем ты, сынок. +И он убьет тебя. +Думаешь, я не знаю, что творится у тебя внутри? +У меня были старшие братья, которые воевали на войне. +Но я был слишком молод. +Я хотел жить так же как и ты. +Пытался подражать им во всем. +-Вы знакомы с этим? +-Конечно, знаком. +Я не совсем хочу быть стрелком. +Просто, иногда мне кажется, что я одинок. +Все стрелки одиноки. +Они живут в страхе. +Они умирают и на их могилу не приходит ни друг, ни женщина. +-Я об этом не думал. +-Тогда подумай, подумай об этом. +Билли, послушай шерифа. +Больше этого не повторится, мама. +Билли. +Что ты здесь делаешь? +Привез твоего пьяного сына. +Ты должен гордиться, гордиться им. +Проваливай. +Не стоит этого делать. +Мои друзья начнут волноваться, если я вскоре не вернусь. +Не плевать, Уайт. +Ты не на своей территории. +Правда? +Назначение на должность шерифа США... +Мне жаль разочаровывать тебя. +Подожди. +Я не ищу с тобой ссоры. +Хватит на меня давить. +Давай все обговорим, я согласен на все. +Я хочу лишь, чтобы ты вернул весь скот в Мексику. +-Был у судьи? +-Был. +Ну и? +Легальным путем ты не сможешь запретить шерифу приближаться к тебе. +Судья как раз уехал, когда я приехал. +-И нам пора сваливать, Айк. +-Заткнись, Фрэнк. +Нам остается одно. +У нас не было проблем, пока не приехал Уайт. +Это точно, Айк. +У нас нет выбора. +Мы устроим ему засаду. +Ты не забыл о братьях? +С ними мы справимся. +Это наша проблема. +-А что, если придет Клам? +-Не посмеют, слишком гордые. +Они сделают так, как мы этого хотим. +Закон, намного важнее, чем любой другой, семейная гордость. +Поймаем его, когда он будет делать обход. +Мне все равно. +-Устал? +-Да, что-то меня сморило. +Выпей кофе. +Надеюсь, это поможет. +Ужасная тишина. +Слишком тихо. +Ты подумал, что нам делать с этими ублюдками? +Хотел бы я знать, Джимми. +Может быть, он поймет, что это безнадежно. +Хочешь вернуться в Калифорнию? +Все время об этом думаю. +-Наверное, она отличная девушка. +-Да уж. +Ну что ж, пойду поработаю. +Может, я сегодня сделаю обход? +Все равно делать нечего. +Хорошо, я пока посплю. +Когда я делаю обход, есть о чем подумать. +Айк сам напросился. +Пусть будет так. +Они этого только и хотят. +Не позволяй им манипулировать тобой. +Это ты мне говоришь? +Ты шериф, не выкидывай свою жизнь на помойку. +-Подумай. +-Не буду. +Мой брат мертв. +-Кто там? +-Открой дверь! +-Говори, Кейт. +-Док, +-я ничего не знаю. +-Говори. +Зачем? +Какое это имеет значение? +Я опять все испортила, да Док? +Я хотела, чтоб ты вернулся. +Я люблю тебя, и поэтому я +думала, что если Уайта не будет, то ты вернешься ко мне. +И поэтому, я молчала, когда услышала об этом. +Я просто сошла с ума. +Я сошла с ума, Док. +Где? +На ранчо Клэнтона. +Кто там был? +Я не хотела, чтобы убили его брата. +Кто еще там был? +Айк, этот парень, Котон Уилсон, и братья Маклоэры. +И Ринго? +Там был Ринго? +Да, он был там. +Нет, Док, пожалуйста, Док. +Не надо. +Док! +Док! +Пожалуйста, Док. +Не убивай меня, пожалуйста. +Пожалуйста! +Не убивай меня! +Не убивай меня! +Док? +Док! +Док! +Док... +Все нормально, дорогой. +Все нормально. +Уайт. +Айк послал меня. +Я здесь не причем. +Поверь мне, я не причем. +Благодари бога, что тебя зовут Клэнтон. +Айк послал меня. +Он хочет встретиться с тобой и с твоими братьями. +-Я жду не дождусь. +-Но без Клама. +Даю слово. +Сколько он приведет с собой? +6. +Там будут, Айк, Фин, Ринго +-и братья Маклоэры. +-Где и когда? +-На рассвете в О.К. Коррал. +-Передай, что я приду. +Ты сказал 6. +Я пойду с ними. +Не надо, Билли. +Поживи подольше. +Я думал об этом. +Я очень долго думал. +Нет, я не могу просто сбежать. +Айк и Фин мои братья... +Вы же понимаете? +Да, я понимаю. +Почему вы сидите, сложа руки? +Как вы можете сидеть в такой момент? +Что с вами? +Идите к Джону Кламу и попросите помощи. +Это не его дело. +Это личное, между нами и Айком Клэнтоном. +Но вы же представители закона. +Вы шерифы. +Вы не должны ставить себя выше безопасности города. +Вы должны служить народу, а не собственной гордости. +Какие гордые. +Посмотрите на себя. +Да вы только посмотрите на себя. +Морган, твоя жена знает, что завтра окажется вдовой? +Выйди из комнаты. +Вирджил, твой сын хочет поцеловать тебя перед сном. +Увидимся утром. +Док, проснись. +Док, это я, Уайт. +Вставай, ты меня слышишь? +Просыпайся, алкаш. +Ты мне нужен, не подведи меня. +-Проснись, ты слышишь меня? +-Оставь его. +Не видишь, он умирает? +Не трогай. +Док. +Как ты себя чувствуешь? +Перестрелка сегодня? +Ну... я не знаю... +Тебе нельзя. +Нельзя! +Тебе нельзя, Док. +Ты даже не можешь стоять! +Тебя убьют, если ты пойдешь. +Дай мне умереть с единственным другом, Кейт. +На нас тебе плевать? +Мы с тобой... все в прошлом, Кейт. +Нам было плевать друг на друга с рождения. +Лошадей на задний двор. +Хорошо. +Пойдем, Котон. +Фрэнк. +Полезай в повозку. +Вперед. +Морган и Вирджил уже ждут. +Айк хочет с тобой поговорить. +-Он не вооружен. +-Минутку, Уайт. +Кейт рассказала мне об убийстве твоего брата. +Они были у Клэнтона, и ты тоже был там. +-Я не причем. +-Пошел отсюда. +-Поверь мне, я... +-Возвращайся к своим друзьям. +Они идут. +С ними Док Холидэй. +Холидэй? +Котон, останься с лошадями. +Айк, мне надоели эти игры. +Отпусти меня. +Иди к лошадям. +Семь с Котонном. +Я вижу только шестерых. +Разделимся. +Фрэнк... +На землю! +Прикройте меня. +Ружье! +-Все нормально? +-Да. +Все нормально. +Котон, трусливый сукин сын! +Они убили моего брата! +Давай, Эрп! +Я убью тебя! +Выходи, Эрп! +Выходи, сволочь! +-Вирдж. +Больно? +-Нога, нога. +Док. +Я позабочусь о Ринго. +Билли... +Бросай оружие и выходи. +Выходи, у тебя нет шанса. +Иди и убей меня! +Иди сюда! +Не заставляй меня это делать. +Не заставляй. +Я уезжаю, Док. +Как братья? +Все будет хорошо. +С ними все будет нормально. +Принеси стаканчик, Джо. +Хочу чтобы ты знал. +Без тебя бы ничего не вышло. +-Куда едешь? +-В Калифорнию. +-Лора? +-Надеюсь. +Она ждет. +Послушай меня. +Тебе нужно в госпиталь в Денвере. +Так ты не протянешь и пару месяцев. +Спятил? +Чтобы пропустить игру в карты? +Увидимся. +Увидимся, священник. +-Добрый день господа. +-Привет, Док. +-Привет. +-Во что играем? +КОНЕЦ ФИЛЬМА. +Когда-то мир был большим, и ни один человек за всю жизнь не мог обойти его. +На протяжении столетий, наука сделала жизнь длиннее, а мир - меньше. +И самых далёких уголков Земли теперь можно достичь всего лишь нажав кнопку. +Время потеряло всякое значение когда человечество изобрело аппараты движущиеся во много раз быстрее чем скорость звука +Здесь, возле самой верхушки мира, люди борются со стихиями чтобы как-то защитить свою свободу. +Радары раннего оповещения, чувствительные электронные приборы обнаружения присутствия объектов в небе таких как бомбардировщики, или управляемые ракеты, а также грозовые тучи и почтовые голуби. +Новые радары должны быть откалиброваны при помощи тестовых полётов, чтобы определить точность оборудования и нанести на карту контуры области обнаружения для того, чтобы выяснить мёртвые зоны, куда радар не может проникнуть +Б-8035. +Высота 9. +Б-7540. +Высота 9. +Б-7045. +Высота 9. +Тестовый полёт. +Тестовый полёт. +Это Снеговик-3. +Дайте показания приборов. +Приём. +Снеговик-3, это Тестовый полёт. +Направление полёта 340 градусов от ориентира, высота 10, скорость 400. +Как слышно? +Приём. +Всё сходится кроме высоты, Митч. +Твоя высота по нашим показаниям - 9. +Альтиметр показывает 10 тысяч на носу. +Лучше проверьте уровень крепления антенны. +Принято. +Как там мадемуазель Математик? +Ей уже достаточно цифр, чтобы засунуть в свою машину? +Вы получили всю информацию, которую хотели, миссис Колдуэлл? +Ещё один пролёт, пожалуйста. +На низкой высоте. +Ещё раз, Митч. +Вектор - 105 градусов, низко. +Понял. +Разворот на 180 градусов. +Снижение. +Тестовый Полёт, приём и отбой. +Я не знала, что пилотам разрешают так делать. +Пилотам Воздушных сил - нет, вы правы. +Но Митч инженер-электроник. +Он хоть и работает на правительство, мэм но руководствуется своими правилами. +Как и трёхлетний ребёнок, пока мама не отшлёпает. +- Мамочка, дорогая, я жду, если ты готова. +- Забыл выключить. +инженер-электроник. +Офицер-радиолокационщик. +Математик и специалист по системному анализу. +Оператор радара. +Пара картографов. +Люди выполняют свою работу. +Хорошо. +Эффективно. +Когда серьёзные, когда шутят. +Делают свою работу. +Ситуация нормальная...на данный момент. +Семнадцатый день месяца. +Небо затянуто облаками, облачность сплошная. +Видимость ограничена +Время, 13:32 Знаменательная минута в истории. +Минута, когда инженер-электроник по имени Митч МакКафи увидел что-то в небе. +Нечто, что чуть не стало началом конца жизни на планете Земля. +МакКафи немедленно сообщил по радио о наблюдении НЛО, неопознанном летающем объекте. +Офицер-радиолокационщик ответил, что этого не может быть. +Кроме самолёта Митча, на радаре не было ни единого объекта поблизости. +В радиусе ста миль в небе не было ничего. +МакКафи не волновало, что показывал радар. +Он верил тому, что видел собственными глазами. +И он решил разглядеть объект получше. +МакКафи развернулся, чтобы неопознанный летающий объект полетел прямо на него. +В голосе МакКафи не было неуверенности или поспешности. +Что-то, он ещё не знал что, но нечто размером с эсминец только что пронеслось мимо него на такой скорости, что он даже не успел попытаться её измерить. +Когда речь идёт о национальной обороне, лучше перестраховаться, чем потом жалеть об этом. +По тревоге были подняты в воздух истребители. +- Ну что? +- Что, ну что? +Давайте не будем валять дурака, майор. +Ваши люди нашли это? +Мистер МакКафи, если бы вы были военным, то я бы уже отдал вас под арест и вам уже бы предъявляли обвинение в военном суде. +К сожалению, вы гражданский +- и я не имею над вами власти. +- О чём ты говоришь? +Но я могу послать донесение на вас, и я так и сделаю. +И к тому времени как я с вами закончу, мистер Инженер-электроник, вы будете считать, что вам повезло если вам поручать тестировать батарейки для фонариков. +Послушайте, майор Берген, я участвовал в последнем проверочном полёте, заметил НЛО и доложил об этом. +Это что, делает меня преступником, предателем моей страны, или каким-то психопатом? +МакКафи, вы электроник, специалист по радарам. +- Ну да, за это мне и платят. +- Если бы в воздухе было что-нибудь, если бы что-нибудь летело, это было бы видно на радаре? +- Ну..да, но... +- Радар бы засёк это? +Да или нет? +- Да. +- За вами следило три радара каждую минуту пока вы были в воздухе, каждую, и ни один не видел ничего кроме вас. +- Послушайте, майор. +- Вам об этом сказали. +Вы это знали. +И, тем не менее, настояли на своей глупой шутке. +- Полегче, Берген. +- Вы продолжали бить тревогу пока кто-то не нажал кнопку сигнала тревоги и не поднял в воздух истребители. +Отлично. +Значит ваши штурмовики обшарили всё вокруг и ничего не нашли, и теперь вы злой и хотите, чтобы я заплатил за горючее, которое они спалили, или потерянное время, или вы придумали что-то ещё более остроумное. +Звено было поднято в воздух и было рассредоточено, чтобы покрыть наибольшую возможную площадь +И благодаря вашей совсем не смешной ложной тревоге, мистер МакКафи, один из самолётов не вернулся. +Пропали и самолёт и пилот. +Майор Берген. +Что? +Да. +Да. +Да. +Вызывайте резервные бригады. +И измените расписания дежурств. +Придётся попотеть. +Послушайте, майор, я сожалею по поводу пилота, но никакой ложной тревоги не было. +Ох, да перестань же, Митч. +Ты и так Уже принёс немало вреда со своим "летающим эсминцем". +- Просто пере... +- Минутку, мисс Колдуэлл. +Звонили с "Заполярных авиалиний". +Сообщили, об опоздании и пропаже самолёта. +- О, нет! +- 60 пассажиров и экипаж. +Был отчаянный крик пилота, а затем ничего. +Пропала связь. +- Проблема с двигателем? +- Нет. +Пилот прокричал что-то по поводу НЛО. +А потом радио перестало работать. +- А на радарах? +- Ничего. +Никого, кроме их самолёта. +Больше никого. +Ну что ж, майор, мы закончили работу здесь. +- Наш транспорт уже готов? +- Самолёт с пилотом уже на лётном поле. +- Долетите прямо до Нью-Йорка. +- Спасибо. +Пошли, Салли. +Держись. +Я сейчас. +Привет, Пит. +Мы там работать не можем. +Я думал, по прогнозу погоды мы долетим до Нью-Йорка без тряски. +- Похоже, на небольшой метеофронт, Митч. +- Может сверху перелетим? +Можно. +Подожди, я отправлю запрос. +Военно-воздушные Силы, ЗЛ-7979, вызываю Международный аэропорт Нью-Йорка. +Приём. +ЗЛ-7979. +Международный аэропорт Нью-Йорка. +Приём. +Высота 8 тысяч, скорость 250. +Впереди непредвиденная грозовая активность в районе гор Адирондак. +Запрашиваю разрешение сменить высоту на 12 тысяч. +Приём. +ЗЛ-7979. +Даю разрешение. +Приём. +ЗЛ-7979. +Понял. +Отбой. +- Как я и сказал, нет проблем. +- Спасибо, Пит. +Я замолвлю за тебя словечко перед майором. +Спасибо. +Пока я не прогоню данные через компьютер, я сказать точно не могу, но похоже, что профайлер в этой точке ныряет вот так и у нас получается мёртвая зона. +Ага. +Так что, или у нас криво стоит антена, или там местность поднимается и закрывает весь снимок, а мы не приняли это во внимание +- Можешь дать мне топографическую карту? +- Да. +Держи. +Митч. +Митч. +Иди сюда. +- Что такое? +- Садись, Митч. +- Ну. +- Сейчас, может, покажется. +- Что, например? +- Неопознанный летающий объект. +- Пролетел прямо над нами. +- И ты туда же. +Ой, оставь шутки. +Я уже известил аэропорт. +Митч, я уверен, что видел что-то похожее на облако, только оно двигалось гораздо быстрее любого облака. +Прямо по нашему курсу с северо-востока. +Ставлю четвертак, что его не засёк ни один радар. +- Что? +- Не обращай внимания. +Я, кроме неба, ничего не вижу. +Я тоже, сейчас. +Я потерял его из виду, когда оно залетело за нас сверху. +А это что было? +Приборы не показывают такого сильного ветра. +Дружище, это было сильнее, чем просто ветер. +- Ты в порядке? +- Вроде да. +А ты? +Я в норме. +А вот Пит в плохой форме. +Пошли. +На землю. +Сейчас рванёт. +Что это было? +Такое впечатление, что с нами там что-то столкнулось. +Ага. +Летающий эсминец, которого не было в небе. +- Эй! +Эй! +- Здесь. +Сюда.! +Хорошая яблочная водка. +Я её сам делаю. +От змеиных укусов хорошо помогает. +Привет, Пьер. +Мистер МакКафи? +Верно. +Это пилот? +Да. +Давайте, парни. +Они зарезервировали для вас место на коммерческий рейс до Нью-Йорка и прислали машину, чтобы отвезти вас и юную леди в аэропорт. +А что с разбившимся самолётом? +У нас приказ оцепить местность. +Всё засекретили. +Что случилось? +Столкнулись с летающей тарелкой, или что? +О, ничего банального вроде летающей тарелки, офицер. +Просто летающий эсминец. +Что ж, удачи вам с вашим летающим эсминцем. +Ваша машина скоро будет. +- Где самолёт, Пьер? +-14-я дорога, за дорогой. +Пошли, ребята. +Алло? +Да, это ферма Пьера Бруссара. +Кого? +Минутку. +Какой-то генерал Ван Баскирк - вас мистер МакКафи. +Сейчас, чувствую, будет ещё один змеиный укус. +Надо срочно принять лекарство. +Летающий эсминец, розовый слон - никакой разницы. +Попробуй вместо них пахту. +Я сказал, что оно выглядело как эсминец, а не было эсминцем. +Надо было назвать это счётной машиной-переростком, тогда по крайней мере ты бы мне точно поверила. +Генерал Баскирк.Это МакКафи. +Да, сэр. +Я знаю, что пилот сообщал об НЛО. +Нет, на этот раз я сам ничего не видел. +Мисс Колдуэлл тоже не видела. +Ага, радар не увидел ничего, кроме нашего самолёта. +Ну что ж, я этого ожидал. +Шутка? +Ложная тревога? +Послушайте, генерал, за какого инфантильного идиота вы меня принимаете? +Я же говорю... +Спасибо. +Да, сэр. +Да, сэр. +Да, сэр. +Понятно, сэр. +Когда пастух кричал "волк", они поверили ему. +По крайней мере, первый раз. +Командование Гражданской Авиации высылает первым делом с утра исследовательскую бригаду. +А после этого и Воздушные Силы, как только КГА закончит. +Когда мы доберёмся, то должны явиться для допроса. +По-моему в этом стакане дырка. +Куда оно всё девается? +- Как там поживает кувшин, Пьер? +- Тебе нравится бормотуха Пьера, да? +О, идеальное лекарство от змеиных укусов, грома, молнии и неверящих генералов. +Наполняй, Пьер. +- Что это? +- Что-то испугало животных! +Это Пьер! +Сюда. +Спокойнее, Пьер, спокойнее. +Ты в безопасности. +Ты в доме. +- Карканья. +Это была карканья. +Я видел её! +- Что такое карканья, Пьер? +- Давай, расскажи нам. +- Это дьявол бури с лицом волка и телом женщины и с крыльями. +- больше, чем можно себе представить. +- Ты наверно увидел орла, Пьер. +- О, нет! +Это была карканья! +Карканья! +- А, я помню. +Я такое где-то читала. +Это суеверие, легенда зародившаяся среди французских канадцев и которая потом вместе с ними пришла потом и сюда +Ага. +Я тоже что-то такое смутно припоминаю. +Пьер, это вероятно были лишь гром и молния. +- Ты всё выдумал. +- Нет! +Нет! +Я видел карканью! +На. +Глотни-ка вот этого. +Войдите. +Что с Пьером? +Он полагает, что увидел что-то странное в небе. +Я видел её. +Я видел карканью! +- Он никак не может выбросить это из головы. +- Да, я понимаю. +Я и сам в это верил. +Тут много старожилов верят в эту байку но я в первый раз вижу, чтобы кто-то утверждал, что сам видел старую ведьму. +- Вы приехали, чтобы отвезти нас в аэропорт? +- Да. +Машина снаружи. +- Я не хотела бы оставлять его в таком состоянии. +- О, Не беспокойтесь мэм. +Джо побудет с ним. +А нам лучше поспешить. +- Самолёт ждёт. +- Пошли, Салли. +Из-за нас задержали вылет, так что нам лучше поспешить. +Мы даже не поблагодарили его. +Я боюсь, что дружеская любезность не будет много значить для человека в состоянии в котором находится Пьер. +Он прав, мэм. +У вас ничего не получится, он же онемел от ужаса. +От ужаса? +Ну, увидел большую птицу. +И поэтому его должно парализовать от страха? +- А он вам не сказал? +- Что не сказал? +- О легенде. +Согласно ней, если увидишь эту птицу, то это знак, что ты очень скоро умрёшь. +- Самолёт ждёт. +Пойдёмте. +- Ок, сержант. +"Неравноценны наши поцелуи" +Разносторонний человек, этот мистер МакКафи +Сначала инженер и пилот, затем - любовник и поэт. +О, поэзия была шекспировская. +Я знаю, но откуда это желание? +- С левой стороны поля, наверно. +- Бейсбол мне нравится. +А может, просто потому что я сидел рядом с симпатичной девушкой. +Иногда этого достаточно. +Даже сидя рядом с Мадемуазель Математиком? +Или лучше вернёмся бейсбольным аналогиям? +Что там цифры, что там цифры... +Непобедимая логика. +Банально, но правда. +Ты почти поразил меня. +Почти? +Что ж, давай завершим то, что начали. +Смотри, какая луна. +Если снова повернуть к бейсболу и левой стороне поля... +Меня кое-кто предупредил, что ты играешь по своим правилам. +- Кто бы это ни сказал - он мне не друг. +- Но он друг мне. +Это диверсия! +О, это слишком мелодраматично. +Давай вернёмся к бейсболу и скажем вместо этого +- пытается украсть вторую базу. +- В дворовые команды, тут же.. +Трусишка. +Я так и знала. +Ни борьбы, ни спортивного духа. +Конечно, рефери всегда может изменить своё решение. +Нет, мы лёгких путей не ищем. +Надо следовать системе. +Сначала низшие лиги, потом - высшие. +- Я привыкла к правилам, Митч. +Извини. +- Зачем извиняться? +Ты можешь всегда... +Система. +- Система. +- В чём дело? +Система. +Мне нужна одна из твоих карт +Ортогональная проекция, от полюса до экватора. +- Дай скорее, у тебя есть? +- Ну да, конечно. +Кажется, она была где-то здесь. +Ага. +Вот. +Что? +Патруль военно-воздушных сил пропал в море. +Раскрой карту. +Вот здесь я заметил НЛО. +Здесь исчез поисковый самолёт. +Тут - пассажирский, наш самолёт у Пьера, и, наконец, патрульный самолёт ВВС. +- Ты что-то бормотал насчёт системы. +- Ну да. +Не видишь? +Вообще-то нет. +Не прямая линия, не дуга, ничего. +Смотри. +Система. +Идеальная система во времени и пространстве. +Каждый случай, каждое пересечение позже чем предыдущее. +И каждое новое дальше по спирали от центра. +Ты имеешь в виду, что нечто летело по такой схеме? +Да. +Что-то, что я видел. +Что-то, что пролетело надо мной в воздухе. +Хм, тогда оно должно было лететь с огромной скоростью, чтобы покрыть такое расстояние +- за такое время. +- Да, должно быть. +Что-то, что и уничтожило четыре самолёта и чудом не заметило тебя в первый раз. +Да. +Что-то вроде твоего летающего эсминца? +- Ладно, забудем. +- Ну хорошо, Митч. +Давай будем благоразумными. +Почему по такой системе, чтобы сбить несколько разбросанных на большом расстоянии самолётов? +И что это? +Метеорит? +Не может быть! +Управляемая ракета? +Её бы остановил первый же самолёт. +Да и кто его запустил? +И зачем? +Нет, Митч, совпадение. +Но система - нет. +Держи свою карту. +Ну ты как ребёнок, Митч, подумай! +Если бы что-то летало по такой траектории, его бы засекли десятки радаров. +И ни один из них не засёк ничего. +И что? +Это, наверно, была Пьерова карканья. +"с головой волка и телом женщины и с крыльями больше, чем можно себе представить!" +- Только не нужно сарказма. +- Послушайте, не будете ли вы любезны утихомириться, чтобы все мы могли поспать? +Спасибо. +Извини. +Наверно, я вёл себя по-ребячески. +Мне кажется, у тебя выходило лучше с поэзией, чем с дедуктивным методом. +- Я знаю ещё один стих. +- Да ну? +Умеренной в еде ты будь, в одежде - скромной. +Короче, милая, меня ты поцелуй и, будь добра, умолкни. +Дата, 18 число месяца. +Небо чистое, лёгкая облачность. +Видимость абсолютная. +Время - 18:15 утра. +Самолёт КГА летит к месту крушения, случившегося днём раньше с Митчем МакКафи. +На борту четыре следователя Командования Гражданской авиации и пилот. +Время, 08:16 утра. +Ещё один знаменательный момент в истории. +Ещё раз поражённый пилот передаёт по радио о наблюдении НЛО. +Это птица. +Огромная как эсминец птица кружит и готовится напасть на самолёт КГА. +Хватит облокачиваться на звонок. +Иду, иду. +Мистер МакКафи? +- Или его сносная копия. +- Мы от генерала Баскирка, сэр. +- Он бы хотел увидеться с вами прямо сейчас. +- Ох, имейте совесть, капитан. +Я приехал поздно ночью. +Я только успел заснуть, когда вы меня разбудили. +- Простите, сэр. +Генерал говорит, что это неотложно. +- Мой сон тоже неотложный! +У меня есть приказ доставить вас к генералу немедленно. +Даже если я вынужден буду взять вас под предупредительный арест. +Хорошо, капитан. +Вы не нервничайте, а я пойду натяну штаны. +Моё наблюдение. +Поисковый самолёт. +Пассажирский самолёт, наш самолёт у Пьера и патруль ВВС. +Случаев слишком много и подходят они друг к другу слишком хорошо, чтобы быть просто совпадением. +Было ещё два случая после самолёта ВВС. +Частный самолёт прошлой ночью здесь и самолёт КГА с четырьмя пассажирами и пилотом - здесь. +Оба подходят для вашей схемы тютелька в тютельку. +Радары ничего не зафиксировали, я так понимаю? +Как обычно, ничего, с тех пор как начался этот кошмар. +Кроме пропажи самих самолётов. +Пилоты что-нибудь докладывали? +С частного самолёта - ничего. +А вот пилот самолёта КГА сообщил об НЛО. +- Он сказал, что это было? +- Да. +Птица. +Птица, огромная как эсминец кружила, а потом и атаковала самолёт. +- Поверьте, мистер МакКафи, это не шутка. +- О, нет. +Самолёт был полностью разрушен и все пятеро человек на борту пропали с лица Земли. +Вы эксперт по электронике. +Могут ли радары не заметить какой-нибудь достаточной крупный объект в небе? +Это невозможно! +Но я видел это сам. +Да. +Трое сообщили о наблюдении чего-то и двое из них мертвы. +Ну значит теперь я стал вроде как и жнец, и швец и в дуду игрец. +Мистер МакКафи, это чрезвычайно важно. +Вы хорошо разглядели то, что увидели? +Нет, я увидел всего лишь размытое пятно. +Хотел бы я иметь с собой фотоаппарат. +Фотокамера! +Генерал Баскирк, перед тем, как я выехала на тестирование радаров с Митчем, я работала над калибровкой искривления земной поверхности +И как нам это поможет сейчас? +Дело в том, что мы снимали изнутри тестовых ракет, а также со стационарных камер и с аэростатов наблюдения. +- Салли, может быть у тебя получилось заснять это! +- Если аэростаты ещё в воздухе, то есть небольшая возможность, что они засняли это, чем бы оно ни было. +Генерала Эдварда Консидайна, Пентагон. +Неотложно. +Быстрее! +Что-то показалось. +Вырубай. +Этот диафильм и вся информация касающаяся птицы относятся к разряду совершенно секретных. +Известите все органы и персонал, которого это касается и который контролирует этот проект, или будет контролировать. +Да, сэр. +- Джонсон! +- Да, сэр? +Сейчас же передайте директиву о полной боевой готовности. +Известите Пентагон и пускай передадут генералу Консидайну, что я уже еду. +Да, сэр. +Полковник Тайлер на взлётной полосе? +Первую линию, пожалуйста. +Нейт. +Нейт. +Это Баскирк. +Заводи мой самолёт и и зарегистрируй полётный лист. +Национальный аэропорт, Вашингтон. +Правильно. +Мы уже выходим. +Я и ещё два пассажира. +Ок. +Вы летите со мной в Вашингтон. +Мисс Колдуэлл. +Мистер МакКафи. +Да, это какая-то птица. +Нет сомнений. +Мисс Колдуэлл, возможно ли, чтобы эта птица летала в мёртвых зонах, +- которые не видят наши радары? +- Нет, сэр. +Я всё тщательно проверила. +По меньшей мере десять радаров должны были засечь её. +Мистер МакКафи, может ли скорость или высота объекта повлиять на возможность быть увиденным радаром? +Нет. +Такой причины нет, - ни научной, ни любой другой, почему наши радары не могут её засечь Они просто не могут. +Точка. +Тогда, если вкратце, то вы говорите, что белое - это чёрное, а дважды два - шесть. +Послушайте, генерал. +Я не придумывал этот летающий кошмар. +Я всего лишь его увидел и доложил. +Генерал всё понимает, мистер МакКафи. +Он ни в чём вас не обвиняет. +Расслабься. +Расслабиться? +Когда мы закончим расслабляться и начнём хоть что-то делать? +Ясным умом наделены не только гражданские, мистер МакКафи. +Мы знаем как позаботиться и о себе, и о стране. +Спокойнее, Вэн, полегче. +Сейчас, сынок, поднята общая воздушная тревога. +Сотни самолётов со всех подразделений сейчас прочёсывают небо в поисках этого стервятника-переростка. +- И мы его найдём, будьте уверены. +- Ну, допустим, нашли. +И что дальше? +Да? +Отлично. +Где? +Так, теперь уже всё официально. +Передайте приказ стрелять. +Без вопросов, без игр и пижонства. +Просто сбить. +Да. +Дайте мне запись всех переговоров земля-воздух и воздух-воздух, и по "горячей линии" передавайте сюда. +Одна из наших эскадрилей только что обнаружила её. +Я приказал им немедленно атаковать и сбить птицу. +Наши самолёты оснащены пушками, пулемётами и ракетами. +Это будет концом гигантской птицы, которая была, а потом её не стало. +Вы услышите как всё будет происходить. +Это командир эскадрильи Ловкий пекарь. +- Цель внизу и сбоку. +Видите? +- Ого! +Матерь Божья! +Видал я на ферме отъевшихся бройлеров но эта крошка, чувак, берёт первый приз. +Клянусь, никогда больше не назову свою тёщу стервятником. +Это командир эскадрильи Ловкий пекарь. +Выходите из строя по сигналу. +Один заход и потом уже каждый сам по себе. +Это командир эскадрильи Ловкий пекарь. +Птица жрёт один из самолётов. +У меня наверно крыша едет. +Так не бывает. +Пули, ракеты, её ничего не берёт. +Это командир эскадрильи Ловкий пекарь. +Чарли выпрыгнул с парашютом, когда птица схватила его самолёт, и теперь он... +Нету Чарли. +Ни его, ни парашюта. +Бессмыслица какая-то. +Как будто мы стреляем по эсминцу из рогатки. +Оно летит за другим самолётом. +Осторожнее! +Это командир эскадрильи Ловкий пекарь. +Миссия провалена. +Мы собираемся направляться.... +Нет! +Она летит за мной! +Нет! +Нет! +Пулемёты, пушки, ракеты, - ничто её не задело. +- Пилоты... +- И мы её найдём, будьте уверены. +Конец гигантской птицы. +Вы были правы, мисс Колдуэлл. +Мы нашли её, что дальше? +Вторая фаза, привести в состояние боевой готовности. +- Известите начальников штабов. +- Есть, сэр. +Бред какой-то. +Это же просто птица, большая птица. +- Пули, ракеты, пушки. +Просто птица. +- Ага, всего лишь птица. +Радары стоимостью десять миллионов долларов не видят её. +Огневая мощь способная смести с лица земли армию даже не задевает её. +Всего лишь птица, ага. +Так что же мы будем делать, сидеть тут и плакаться? +- Ох, отстаньте же, МакКафи. +- Мы не плачемся, МакКафи, и не бежим в панике. +Но сложно ответить на вопрос даже не зная, в чём он заключается. +А просто грубить ещё никому не помогало. +Я не критикую ни вас, ни ВВС, ни тех парней, которые только что погибли, пытаясь уничтожить этого монстра. +Я не пытаюсь острить, или грубить. +Я просто испуган. +Как и мы всё, думаю. +Давайте в этом признаемся и попытаемся что-нибудь сделать по этому поводу. +- Есть предложения, МакКафи? +- Конечно, из электронная рогатки собьём. +- Вэн. +- Близко, генерал, близко. +Только не из электронной. +Из атомной. +- Да? +- Фаза вторая в состоянии полной готовности. +- Все соединения в состоянии боевой готовности. +- Хорошо. +Вас вызывает доктор Кэрол Нойман из исследовательской лаборатории. +Возьму на другом телефоне. +Доктор Нойман, это генерал Консидай. +Повторите ещё раз. +Прекрасно, прекрасно. +Оставайтесь там, я сейчас буду. +Мы держали в курсе последних событий исследовательскую лабораторию. +Они работали на месте крушения самолёта КГА +- и там где упали вы. +- Что-то нашли, Эд? +Они думают, что выяснили, что это за птица и откуда она взялась. +И об атомной рогатке. +За час до того, как ваш самолёт приземлился в Вашингтоне, я приказал привести в состояние боевой готовности все пусковые площадки в стране имеющие управляемые ракеты с атомными боеголовками там где схема зоны выпадения радиоактивных осадков позволяет их взрывать. +Приказ привести вторую фазу в состоянии боевой готовности, который вы слышали, был приказом выпускать ракеты в тот же момент, когда птицу засекут, где бы это ни было! +- Генерал, я прошу прощения. +Мне кажется, что.... +- Не извиняйся, сынок. +Я восхищён твоим мужеством. +И продолжай доставать нас всякий раз как мы что-нибудь упустим. +- Вэн? +- Извини, Мак. +- Мы просто все хотим как лучше. +- Вам тоже лучше пойти с нами. +Всё равно вы в этом деле по уши. +Пошли. +Атом - основной строительный элемент любой материи. +Перед нами модель обычного атома, как мы его знаем. +Ядро с положительным зарядом, электроны - с отрицательным. +В этом отношении, как мы считали, все атомы одинаковы. +Но это не так, совсем не так. +В соответствии с законами электродинамики, всё в природе симметрично. +Всё находится в состоянии баланса. +И если есть материя, то должна быть и антиматерия, зеркальное отражение симметричное материи. +Здесь у нас ядро с положительным зарядом, и электроны с отрицательным. +В его антиподе, ядро должно быть с негативным, а электроны - с положительным зарядом. +Наукой доказано, что это так. +Не на нашей планете и не в Солнечной системе, но где-то во вселенной есть звёзды, планеты, даже целые галактики целиком состоящие из антиматерии. +Доктор, вы хотите сказать, что эта птица из антиматерии? +Что это вывернутый наизнанку образ, зеркальное отражение, как вы его называете? +Минуточку, генерал. +Доктор, существование антиматерии доказано. +Но также было доказано, что если антиматерия вступит в контакт с обычной материей, они уничтожат друг друга, взорвутся. +Почему же тогда птица не взорвалась когда в неё стреляли, или когда она касалась чего-нибудь? +Что ж, вы оба и правы и неправы одновременно. +Сама птица не из антиматерии. +Но она без сомнения испускает какое-то излучение, энергетический экран, невидимое препятствие. +И вот оно-то и состоит из антиматерии. +Пушки, пулемёты, ракеты - неудивительно, что её ничего не смогло задеть +При ударе об щит из антиматерии, предмет взрывался и не мог навредить птице. +- Митч, это объясняет отказ радаров. +- Ага. +Нет отражающей поверхности. +Волны радаров не наталкиваются на неё, а просто огибают. +Нет отражённого сигнала, нет и следов. +Доктор Нойман, несколько вопросов. +Это не просто лишь ваша догадка? +Нет, генерал, это не догадка. +Очевидно, что птица способна убирать этот щит из антиматерии, чтобы воспользоваться своим клювом, когтями и крыльями, чтобы сеять разрушения. +Вот часть упавшего самолёта. +Изучая его, наши учёные узнали всю эту невероятную историю +Всё было проверено и перепроверено. +- Что-нибудь ещё, генерал? +- Да, доктор. +Откуда эта птица взялась? +Вот фрагмент пера птицы с места катастрофы по крайней мере, мы называем это пером, хотя точно не знаем что это, только на что похоже. +Мы подвергли его химическому анализу, электроскопии, всем мыслимым тестам. +Оно состоит из вещества неизвестного на Земле, ни одного известного нам элемента. +- Выяснение всего этого нам дорого обошлось. +- Это как? +У нас было несколько таких перьев. +Осталось только это. +В качестве последнего средства мы попробовали электронный анализатор. +Взгляните. +Эта птица не с нашей планеты. +Она прилетела из космоса, из какой-то богом забытой галактики из антиматерии в миллионах световых лет от Земли. +Другого объяснения нет. +Вэн отвезёт вас обратно в Нью-Йорк. +Было бы замечательно, если бы вы оставались в состоянии готовности. +И, конечно, вы понимаете, что всё услышанное и увиденное вами секретно. +Моя команда готова и ждёт звонка, Эд. +Просто позвони. +Просто позвонить, Вэн? +Мне понадобится вся помощь, которую я смогу раздобыть. +Всем нам понадобится. +Единственная проблема в том, что когда я в последний раз говорил со священником, в единственное место где мы можем получить нужную нам помощь была не проведена телефонная линия. +Генерал Консидайн. +Это срочно. +Дайте мне министра обороны. +До сих пор, всего один человек видел птицу и остался жив. +Среди тех, кто знал об этом, существование птицы было строгим секретом. +Но когда были сделаны все приготовления для срочной встречи Президента, Кабинета министров, +Национального комитета безопасности и Объединённого комитета начальников штабов птица показалась всему миру и спокойствие сменилось паникой. +Паникой, ужасом и кошмаром. +Ни одни клочок Земли не был избавлен от того ужаса, когда глядишь в небеса и чувствуешь... +не безопасность и спокойствие, а видишь крылатый ужас в перьях +А, заходи. +Я полночи провела, прогоняя через вычислительную машину твои данные. +- Надеюсь, это то, что тебе надо. +- Хорошо! +Спасибо. +Митч? +О. Спасибо. +Нет, ну что это такое. +С тех пор как мы вернулись из Вашингтона уже как два дня и две ночи ты зарылся с головой во все эти бумаги, данные, расчёты. +- Митч, отдохни, поешь, поспи. +- Я был занят. +То, над чем ты работаешь, имеет какое-то отношение к птице? +Над тем, как уничтожить птицу? +Сработает, Митч? +Не знаю. +Честное слово, не имею малейшего представления. +Это одна из сумасбродных идей, в полном отчаянии взятых с потолка. +Ты говорил об этом с генералом Баскирком или генералом Консидайном? +Чтобы они посоветовали мне не совать нос в чужое дело? +Нет, спасибо. +Да и какой смысл? +Всё равно шанс, что это сработает - один из миллиона. +Это просто занятие, чтобы не сидеть сложа руки и ждать. +Митч, я тоже думала о птице. +Ага, как и все в мире. +Ты когда-нибудь задумывался о том, зачем она сюда прилетела? +Ради пищи? +Я имею в виду, эта птица есть в том смысле как едим мы? +Ну, доктор Нойман говорит, что она поглощает энергию из того, что уничтожает, включая людей. +Своего рода молекулярный осмос. +А может она прилетела сюда отдохнуть? +- Может и прилетела, но сейчас она точно не отдыхает. +- Именно. +Насколько мы знаем, она продолжает безостановочно облетать Землю. +Летает без передышки. +Это беспокоило меня, и я позвонила генералу Баскирку. +Митч, помнишь Пьера Бруссара с фермы? +Конечно, его карканью, или что он там видел. +Это всего лишь доказывает поговорку о том, что правда ещё страннее, чем вымысел. +Это был не вымысел. +Пьер видел что-то, он видел птицу. +В небе на высоте 12 тысяч футов, ночью, в бурю? +- Нет. +Птица спустилась на землю. +- Но ты только что говорила... +Генерал Баскирк сказал мне, что они нашли следы гигантской лапы на поле возле фермы Пьера Бруссара, и я знаю почему. +Птица прилетела сюда, чтобы построить гнездо. +Гнездо. +Яйца. +Ещё птицы. +Это должно быть причиной. +Других просто нет. +Генерал Баскирк. +Это МакКафи. +Срочно. +Крошка, собери мне, пожалуйста, вот те бумаги. +И эти тоже. +Генерал Баскирк? +МакКафи. +Прошу вас, не спорьте и не спрашивайте что и зачем. +Я объясню позже. +Это ужасно важно. +Мне нужен быстрый самолёт и вертолёт. +Очень прошу, пожалуйста, поверьте мне. +Я знаю, что делаю. +Да, на ферме Бруссара. +Хорошо. +Мы выезжаем прямо сейчас. +Салли со мной. +Да. +Едем прямо в аэропорт. +Мы прерываем нашу передачу для важного объявления. +Леди и джентльмены, говорит Вашингтон. +Генерал-лейтенант Консидайн, Военно-воздушные Силы Соединённых Штатов Америки. +Мы столкнулись с кризисом, кризисом, выход из которого все страны мира, несмотря не беспрецедентное сотрудничество, не могут найти. +Но мы не успокоимся, пока его не найдём. +Мы испробовали самое совершенное оружие из арсеналов самых мощных армий на Земле и оно оказалось совершенно бесполезным. +атомные, водородные бомбы, способные смести с лица земли города и страны оказались абсолютно бесполезными против этого небесного чудовища. +Два дня назад все полёты были отменены. +Лишённая источников пищи и энергии птица всё же выжила и начала серию наземных атак устраивая невиданные доселе фантастические вакханалии разрушения. +Ничто не устояло перед нападением птицы: +домашний скот, посевы, дома, поезда, все виды средств передвижения. +Очевидно, что птицу привлекает движение. +Таким образом, наше правительство, как и все правительства мира, объявили чрезвычайную ситуацию и ввели военное положение. +Кроме запрета на полёты, движение всего наземного транспорта, включая автомобили, грузовики, автобусы, поезда, корабли и прочего, должно быть немедленно прекращено. +Доставка еды и предметов первой необходимости будет производится вооружёнными силами. +Каждую ночь с заката до рассвета, до специального уведомления, будет соблюдаться режим обесточивания. +Любое движение по улицам или дорогам в светлое время суток должно быть сведено к минимуму и может осуществляться только там, где оно разрешено как необходимое +Вы слышали генерала Консидайна из Вашингтона. +Оставайтесь с нами. +Митч! +Что ж, самолёт ждёт нас. +Нам нужно лететь на ферму Пьера. +Вот она! +нам лучше приземлиться перед тем, как она вздумает сделать так ещё раз. +Ружья. +Патроны Везерби 378 Магнум. +Остановят всё, что хочешь. +Всё, что хочу, Митч? +Ну, всё, кроме птицы, но нам нужны яйца. +Без щита из антиматерии, будем надеятся. +- Карканья? +- Нет, Пеп, не карканья, а в сто раз хуже. +Выходим. +Похоже на гнездо. +Но нет и следов яиц. +Оно должно быть где-то там внутри. +Единственный путь это выяснить - это пойти и взглянуть. +Карканья! +Яйцо! +Ты стрелять ружьё, делать большой шум, приходить карканья и мы все умирать. +Пьер, мы должны разбить яйцо, это наш единственный шанс. +Пьер тут не оставаться. +Пьер! +Вернись! +Я из Монтаны. +Пьер и его карканья. +- Он был прав. +Увидев её, он действительно вскоре погиб. +- Да. +Я предупрежу Вашингтон. +Пускай направляют поисковые группы. +Есть шанс, что могут быть ещё яйца в тех местах мира где видели птицу. +Поэтому их надо найти и уничтожить. +Хоть это мы можем сделать. +Что ж, поехали в город. +С птицей поблизости летать слишком опасно. +Так что вертолёт мы бросим и возьмём машину Пьера. +Она ему всё равно уже не понадобится. +- Давай Брэд, жми на газ. +- Давай. +Прибавь газку. +Чувак, она у тебя еле ползёт. +Давай! +Газку! +- Какой-то псих едет с включёнными фарами, и быстро едет. +- Наверно он не слышал объявления. +Я ему посигналю, чтобы он остановился, когда будет проезжать мимо. +- Эй, папаша. +Убирай свою консервную банку с дороги. +- Давай, дядя. +- Эй, дядя, испугался большой злой птицы? +- Погасите фары! +Съезжайте с дороги! +Ты о нас не беспокойся. +У нас с собой есть соль, чтобы насыпать ей на хвост. +Осторожней там с солью, смотри, чтобы не просыпалась в карбюратор. +Поехали. +Сумасшедшие дети! +Они не понимают, что творят! +- Счастливо оставаться.. +- Эй папаша. +Ты нам не сигналь, это мы тебе посигналим. +- Парень сильно ранен, но жив. +- Девушка без сознания. +По дороге город, там есть больница. +Отвезём их туда. +А мы с тобой едем сегодня в Вашингтон. +Я подгоню машину для ребят. +Мисс Колдуэл, МакКафи, я занятой человек. +Поэтому я надеюсь, что это не какая-нибудь очередная чокнутая затея. +Ещё какая чокнутая. +Ну, мальчик, вставляй свои пять копеек. +Что ты мне хотел показать? +- Как сбить птицу в небе? +- Какое-то новое оружие? +Нет, обычным оружием, пулями, бомбами. +МакКафи, я говорил вам, что у меня нет времени... +Постойте, генерал. +Моя идея может оказаться такой же глупостью как и трёхдолларовая банкнота, +- но мне кажется, что её стоит выслушать. +- Ну что ж, валяй. +Сейчас неважно, прилетела птица из космоса, или с Аппер Сэдл-ривер, штат Нью-Джерси, она всё равно из плоти и крови в некотором роде и значит уязвима для пуль и бомб. +Если бы только можно было забраться за экран из антиматерии. +Именно. +Это именно то, что, как я думаю,... +надеюсь, я и придумал как сделать +Я только что поставил на тебя эти пять копеек, парень. +Продолжай. +Вот это увеличение фотографии из пузырьковой камеры. +Я бомбардировал камеру быстрыми частицами. +В результате мы имеем след сделанный частицей известной как мю-мезон. +Но обратите внимание на вот этот промежуток. +Это - одно из самых поразительных недавних открытий науки. +Митч МакКафи, летающий Шерлок Холмс. diff --git a/bench/data/opensubtitles/ru-medium.txt b/bench/data/opensubtitles/ru-medium.txt new file mode 100644 index 0000000..58a510f --- /dev/null +++ b/bench/data/opensubtitles/ru-medium.txt @@ -0,0 +1,1323 @@ +-Две недели не даешь мне прохода. +Вот и действуй, чем ты рискуешь? +Я думал, что сделаю тебя счастливой. +Тоже мне счастье. +Муж не дает ни гроша, и у любовника ума не хватает подумать о деньгах. +- Хорошенькое счастье. +- Извини, я думал, ты любишь меня. +Ну люблю, люблю тебя, но и не хочу, чтобы все началось как в прошлый раз. +Ты не права. +У меня для тебя сюрприз. +Шлихтовальная машина, ты о ней давно мечтала. +-Для костей? +- Нет, настоящая. +Хочешь, приходи за ней вечером. +Я тебе не девочка. +Была бы ты девочкой, я бы тебе ее не купил. +Ты прекрасно знаешь, что я девочка. +Я люблю тебя, и вечером сделаю все, что пожелаешь, каналья. +Вам будет трудно. +Одинокой женщине руководить таким заведением... +Да нет, месье Эдуан уже давно почти забросил магазин. +А брать нового приказчика я не хочу. +Хватит и одного раза. +- Одного раза? +-Да. +Разве месье Мурэ вас не устраивал? +Да, он умный молодой человек, активный, смелый, но чересчур предприимчивый. +Его нельзя оставлять наедине с женщинами. +У него есть шарм. +Самой порядочной женщине трудно перед ним устоять. +- Хорошо, что предупредили. +- Что? +Нет-нет, я другое хотела сказать. +Я говорила о склонности месье Мурэ в общем. +Я уважаю вашу жену. +Сегодня вечером вы снова едете в Лион? +Ваш билет, месье? +- Какая ближайшая станция? +-Дижон. +А во сколько ближайший поезд до Парижа? +- Из Лиона? +- Нет, из Дижона. +В три десять, месье. +- Во сколько он прибывает? +- В семь часов. +Париж. +Просьба освободить вагоны. +-Улица Шезоль, дом двадцать четыре. +- Хорошо, месье. +- Что с тобой? +-Желудок болит. +Неудивительно, после обеда у Жосрана. +На лестничной клетке до сих пор запах. +Тебе нравится новая хозяйка? +Валери Вабр - настоящая дура. +Скорее, настоящая шлюха. +Ты шпионка. +Твоя хозяйка такая же стерва, как и ты. +Такая же уродина, как и ее мать. +И такая же шлюха. +Уверена, вы о Берте. +- Она тоже? +- Весь дом - сплошные свиньи. +Вот бы вернулся месье Август, а в его кровати красавчик Октав. +Бедняга Август, он целиком занят своей мигренью. +А ведь она правду говорит. +Везде деньги. +Подарок туда, подарок сюда. +Как в театре: за вход надо платить. +Ужасно. +Я отдаюсь за деньги? +Неужели ты веришь? +Скажи, ты в это веришь? +Нет, конечно. +На днях я застала ее на служебной лестнице. +А позавчера еще лучше - в новом платье. +Подарок Октава. +Тебе ночную сорочку, ей платье. +Цена растет. +Кстати, какой сегодня день? +Среда. +Значит, рогоносец в Лионе. +Ему давно пора раскрыть глаза. +Ничего не видит. +Ну, ничегошеньки. +Боже, боже. +Нам нельзя больше видеться. +- Возможно, ты права. +- Ты думаешь? +Ты сделал меня несчастной. +И расплатился с долгами. +- Я ничего такого не говорил. +-Да, но ты так думал. +Слушайте, красавчик Октав, наверное, кусает локти. +Зря он ушел от мадам Эдуан. +Теперь у него добыча помельче. +А ведь запросто мог иметь и ту и другую. +Ему не привыкать. +Да, но его больше всего прельщает касса. +Он спит не с Бертой, а с матрасом, набитым золотом. +Вот тебе и общественное мнение. +Грязные сплетни служанок на служебной лестнице. +И это все? +Думаешь, намеки на содержимое кассы мне приятны? +Ты мог бы протестовать. +Мог бы, если бы это было правдой. +Но кому, как не тебе знать, что касса тут ни при чем. +Ну да, ты спас меня от разорения, да еще и заработал. +Может, сменим тему? +- Тебе неприятен этот разговор? +- Разумеется, от него дурно пахнет. +Дурно пахнет? +Кто бы говорил. +Дорогая, если ты, правда, считаешь, что я люблю тебя из-за денег, то лучше сразу брось меня. +Ну, конечно. +А ты иди к мадам Эдуан. +Иди. +- Ну вот, приехали. +-Да, она вдова. +У нее все преимущества. +Бедная Берта, как ты похожа на мать. +Подумать только, я оплачиваю это ничтожество. +Заведи себе другого. +Откройте, откройте. +Я знаю, что вы оба там. +Откройте или я выбью дверь! +Не открывай, он вооружен. +Он убьет нас. +- Не бойся. +- Трус. +Трус. +Почему вы не отвечаете? +Мерзавец. +Негодяй. +Ну, зачем же применять силу? +Применять силу, применять силу... +Вор. +Мадам, мадам, входите, не стойте тут. +Считайте это пощечиной. +Жду ваших секундантов. +К вашим услугам. +- Что теперь со мной будет? +- Надо было им помешать. +Что теперь обо мне подумают люди? +Ваши родственники? +Разве они могут вас понять? +Они для вас чужие. +Если бы я знала. +Ни о чем не жалейте, не жалейте, раз вы его любили. +Берта, мы будем драться на дуэли. +Берта, малышка моя, мы не можем расстаться в ссоре. +Это было бы слишком глупо. +Мы оба ошибались. +Вот и все. +Это же не преступление. +Три месяца мы думали, что любим друг друга. +Это было чудесно. +Нет? +И потом, может быть это и есть любовь -думать, что любишь. +Если мы... не любили друг друга, то утешься. +Значит, любви не существует. +Нет-нет, мы не ошибались. +Как и все влюбленные, мы считали, что будем уникальной парой на свете. +А теперь, как и все влюбленные, станем такими же как остальные. +Займем свое место. +Берта, дай руку. +Я больше никогда не полюблю. +Никогда. +Ты почти излечилась. +Думаешь о будущем. +Так вы не будете драться? +Будут, будут. +Так нужно. +Но раз вы больше не любите друг друга. +Дуэли часто бывают и без причины. +Прошу прощения, но, кажется, я только что кое-что разрушил. +Не стоит извиняться. +Благодаря вам... я вам покажусь глупой, но чтобы не случилось, я больше не одна. +Вероятно, придется покинуть этот дом. +Ничего страшного. +Ничего страшного, месье Октав. +Это неважно. +Прощай, Берта. +-До свидания, Мари. +- Прощайте, месье Октав. +- Так ты будешь драться? +-До последнего. +Ты же не умеешь. +Я бы на твоем месте... +- Что с вами? +- Ничего. +Это нервное. +Не могу представить Августа на дуэли. +Ты и Дюверье будете моими секундантами. +Наверное, он у себя. +Его нет. +Вы не знаете, где его искать? +- Так вы в курсе? +- Как и все. +Какой же у меня насморк. +- Месье Башляра нет? +- В такой час его никогда не бывает. +Вы случайно не знаете адрес месье Трюбло? +Нет, но месье Башляр вам его даст. +- Во сколько он вернется? +- Наверное, он у племянницы. +Пассаж святого поля дом восемь? +Я знаю. +Спасибо. +На кого я теперь буду похожа? +Могла бы о матери подумать. +Я старалась пристроить тебя, чтобы в старости лет ты меня поддержала. +А ты связалась с этим продавцом. +И о чем ты думала? +- Я ненавидела Августа. +- Это не причина. +Разве я изменяла твоему отцу? +И тем не менее... +- Но она любила Октава. +- Твоя сестра никого не любит. +А если мне нравится никого не любить? +Думаешь достаточно требовать любить, любить, так нет, сердцу не прикажешь. +Она права. +Не выходят замуж только чтобы не подчиниться матери. +Я вышла замуж, чтобы покончить с этой жизнью, чтобы вдохнуть другой воздух, чтобы вырваться из этого дома. +Вышла замуж, чтобы изменять своему мужу. +Довольна? +Несложно было догадаться. +Я приняла меры предосторожности. +Предупреждаю - выхожу замуж через месяц. +Что? +За кого? +-За кого люблю, а он любит меня. +- Несчастная, я помешаю тебе. +- С этого момента... +- С этого момента хватит. +Мы больше не будем терпеть твою диктатуру и преследования. +Говоришь, что не изменяла. +Очень жаль. +Если бы изменяла, я был бы счастливее. +Посмотри на свою дочь. +Твое произведение. +Ни мужа, ни дома, больше ничего нет. +Не плачь, доченька. +Ты жертва моей слабости и ее тирании. +Это мы должны просить у тебя прощения, мы. +- Просить прощения? +Да я лучше умру. +- Это принесет нам только счастье. +Я этого не допущу. +Посмотрим, чья возьмет. +Вы как раз кстати, будете свидетелем. +Негодяй, вот негодяй! +- Свидетелем? +Понимаете, я... +- Свидетелем... +А зачем вы сюда пришли? +- Хотел спросить у вас адрес Трюбло. +- Вы издеваетесь? +Адрес Трюбло? +В кровати мадемуазели, вот где адрес Трюбло. +Прихожу я утром нагруженный подарками и что вижу? +Угадайте. +- Трюбло? +- Трюбло. +Этого мерзавца Трюбло. +А я так жаждал увидеть своего ангела. +- И тебе не стыдно, коварная? +- Я не знала. +- Что? +Не знала, что он тут? +- Не знала, что это вас так огорчит. +А я тебя предупреждала. +Если месье Нарцисс узнает, то будет не доволен. +Вот видишь, вместо того, чтобы меня послушать... +Вы оделись? +Выходите. +Выходите как есть. +Я же говорил -только служанки. +Я впервые нарушил правило. +Нарушил правило. +Иуда. +А как же дружба? +Вы изменили дружбе Башляра. +Я же хранил эту крошку для вас. +Ну да, говорил я себе: когда состарюсь, выдам ее замуж за Трюбло, отдам в надежные руки и спокойно умру. +Ведь у меня есть сердце. +Пятьдесят тысяч хотел дать этому мерзавцу. +Пятьдесят тысяч франков! +-Успокойтесь, Башляр. +- Послушайте месье Октава. +Как вы могли так поступить с другом? +Теперь будем драться на дуэли, на пистолетах с десяти шагов. +Не делайте этого. +Вам незачем драться на дуэли. +-А как же честь? +- Были бы вы ее мужем, тогда понятно. +Были бы вы ее мужем, мне было бы все равно. +Это еще как сказать. +Во-первых, мне нужен Трюбло. +-Зачем? +- Быть секундантом. +Я дерусь на дуэли. +- На дуэли? +-Да. +Но с женатым мужчиной. +С Августом Вабром. +Утром он застал меня с Бертой. +- С Бертой? +-Да. +В каком мире мы живем! +- Можешь мной располагать. +-А кто секунданты Августа? +- Теофиль и Дюверье. +-Дюверье? +Как мило. +У меня с ним встреча по поводу обеда у Клариссы. +Какая прекрасная возможность урегулировать дело чести. +Который час? +Малышка отбила весь аппетит. +Господи, я опаздываю. +А ты, никогда больше так не делай, иначе будешь иметь дело со мной. +Ну же скажи, что больше этого не повторится. +Этого больше не повторится. +Ну же, поцелуй ее, мерзавец. +В лобик. +Если я еще раз застукаю вас, лишу своего доверия. +-Дети мои, что происходит? +- Вы же видите. +- Я застукал их вместе. +- Я ничего не вижу. +Я собирался позавтракать у Клариссы. +Купил кое-что. +Прихожу, поднимаюсь: и никого, и ничего. +Она оставила мне мой портрет. +Все как у меня: купил драже, прихожу, поднимаюсь... +- Она не спала в своей кровати. +- Спала. +Она была с Трюбло. +Как омерзительно. +- Она была с Мурэ. +-Лежала в ночной рубашке. +- Стояла в ночной рубашке. +- Ничего - пустота, тишина, пустыня. +- Я вышиб дверь и набросился на него. +- Он вскочил с кровати. +- Я набросился на нее. +Она убежала. +- Ну вот. +- О ком вы говорите? +- О Берте и о Мурэ. +А я говорю вам о Клариссе. +Причем здесь Кларисса? +Я говорю о Фанни. +Фанни? +А причем тут Фанни? +Я говорю о Берте. +Я только что купил ей рояль. +А ведь ненавижу музыку. +Я никогда не приходил к ней с пустыми руками. +Всегда конфеты, деньги. +Хочешь свой портрет? +Вот тебе художник. +Точно как у моей жены. +Платье, драгоценности. +И это вытворяет двадцатилетняя девушка. +- Нет, простите, ей двадцать пять. +-Двадцать. +Может, вы лучше знаете? +Не сердитесь, но так говорить - дурной тон. +- Могу вам доказать. +- Кому, Клариссе? +Да причем тут Кларисса. +Фанни. +Я тоже говорил себе, что Валери уже не двадцать. +Вы закончили обсуждать свои дела? +А как я? +Я. +- Кто дерется на дуэли? +Вы или я? +- Ну да, он прав. +Август, друг мой, скажу вам одно - надо отомстить. +Слушай, я проголодался, пойдем, пообедаем? +И да здравствуют жены, господа. +Да здравствуют чужие жены и наши, которые, впрочем, чужие для других. +Мы не можем упрекнуть их в непостоянстве. +Ведь они становятся чьими-то любовницами. +И потом, верные жены -такое занудство. +Чтобы узнать это, надо быть женатым. +Разве нет? +Так о чем я говорил? +А ваша жена вам изменяла? +- Конечно. +- И что? +Отбил у нее всякую охоту. +Теперь десять раз подумает, прежде чем изменить. +Молодец, молодец. +За ваше здоровье, господа. +И за вашу смелость, Август. +Давайте поговорим о дуэли. +Завтра на рассвете? +- Если у меня не будет мигрени. +- Тогда перенесем на следующий день. +- Оскорбленный выбирает оружие. +- Но пощечину дали Октаву. +-Значит, оскорбленный он. +- Точно. +-А вы хотели дать ему пощечину. +- Во всяком случае, хотел. +Значит, оружие выбирает он. +Равенство - прежде всего. +Простите, но ведь я же... +- В общем... +- Рогоносец. +А это оскорбление. +Кто согласен со мной, господа, пусть поднимет руки. +Один, два, три. +Четыре. +Единогласно. +Итак. +Мечи, шпаги? +Минуточку, вы торопите события. +Вы послали секундантов к Трюбло? +Это другое дело. +Фанни еще ребенок, она не понимала, что делала. +-А вы разобрались с Клариссой? +- Но я не женат на Клариссе. +Если я убью Октава, то буду мучиться угрызениями совести. +Я католик. +Наполеон венчался в церкви, а потом всю жизнь воевал. +Но не за Жозефину. +Признаюсь, Октав не прав, но именно он спас меня от разорения. +Это логично. +А если я его не убью и не буду с ним драться, то мы останемся в ссоре. +- Не совсем. +-А магазин? +- Что магазин? +- Я не смогу оставить Октава. +Ему придется искать другое место. +Из-за недостойного поведения жены, я должен буду уступить натиску конкурентов. +- Это аргумент. +- Ну да, мы сразу разоримся, сразу. +Господа, это все меняет. +Дуэль будет безумием. +Более того, глупостью. +Я сам пойду к Октаву, я заставлю это животное извиниться. +Не будь я Башляр. +Уверяю, он извинится как миленький. +И так мы избежим скандала. +Но будет справедливо, что честь Августа не будет поругана. +А также и честь его супруги. +Славно мы придумали, господа. +Башляр угощает вас шампанским. +Сомелье. +Была бы здесь Фанни. +Нет, нет, я не буду секундантом у того, кто предал мое доверие. +Не будем преувеличивать. +Я архитектор этого дома и отвечаю не только за стены, но и за жильцов. +Отвечаю за ваше поведение. +Я художник, но тем не менее. +Когда я приютил вас здесь, разве не предостерегал вас, разве не просил, не приводить сюда женщин? +Я не приводил сюда женщин. +Здесь их много, и все красивые. +О, прошу вас. +- Я многое могу понять. +-Да, ведь вы художник. +Многое, кроме адюльтера. +-Адюльтера? +- Я его не одобряю. +- Он вне ваших принципов? +- Вне моей морали. +- И разума? +- Вполне возможно. +Вы шутите? +Нет, вы меня разыгрываете. +- Я вас не понимаю. +- Компардон, вы не изменяете жене? +Или малышка Гаспарина это нюанс. +Между нами говоря, Гаспарина... +Говорите тише, жена спит. +- Гаспарина не замужем. +-А вы? +Да будет вам. +Я не кручу роман с соседкой. +Нет, все в этом обвиняют жен. +- Месье Башляр спрашивает месье Мурэ. +- Пусть входит, пусть входит. +Входите, Башляр, входите. +Тихо, мадам Компардон спит. +Извините меня, хочу поговорить с месье Октавом Мурэ. +Вы тут не лишний, друг мой. +- Останьтесь, здесь вы у себя дома. +-Да будет так. +Дорогой мой, я все уладил. +Это было трудно, но мне удалось. +Ну так вот, дуэли не будет. +Вы довольны? +-Дуэли не будет? +- Нет. +Неужели хотите испортить карьеру этой скандальной дуэлью? +Давайте все забудем. +Вы просто извинитесь перед Августом, и все будет в порядке. +Все будет в порядке? +Где? +Здесь, повсюду, в другом месте, где пожелаете. +- И мое положение не изменится? +- Но мы же все забудем. +Забудем все и начнем все с начала. +Все, все, все, все. +Август хочет избежать пересудов. +Он выше сплетен, он ведь молодожен. +- И я извинюсь. +- Ну да. +- Перед кем? +- Перед Августом. +Выразите ему свое сожаление. +Вы знаете, как это делается. +Что? +Выражать сожаление, что сделал Берту счастливой? +Это же подлая трагедия. +Она такое очаровательное создание, она мне так нравится. +Нет, никаких сожалений. +А если Берта лично потребует от вас выразить сожаление? +Это будет принуждением. +Я этого не потерплю. +Хорошо. +А если вы и Август извинитесь друг перед другом? +Друг перед другом? +Вы за то, что соблазнили его жену. +А он за то, что дал вам пощечину. +- Но он не давал мне пощечину. +- Но намеревался - это одно и то же. +К несчастью, этого намерения у него не было. +- Тогда на что вы жалуетесь? +- Я? +Ни на что. +Я жду его секундантов. +А если он их не пришлет, вы станете посмешищем. +Я ему отомщу. +Между нами, откровенно, что вы намерены делать? +Раз Август даровал мне милость и решил со мной не драться, я решил покинуть этот дом и поселиться в другом месте. +А магазин? +Сердечные дела - одно, а коммерция - совсем другое. +Вы не можете уйти из магазина. +Неужели вы думаете, что я буду работать на Августа? +Нет, не хочу быть посмешищем. +-А Берта? +-Да. +Берта? +Что будет с Бертой, если она вас больше не увидит? +Хотите ее наказать? +Без ложной скромности скажу, что Берта решила обойтись без меня. +Неблагодарный. +Не настаивайте. +- Это ваше последнее слово? +- Самое последнее. +Я передам ваш ответ. +Какой ответ? +- Что вы отсюда съезжаете. +- Ну да. +Спасибо, что были свидетелем этого трудного разговора. +Большое спасибо, дорогой мой, за понимание. +Лиза. +Вы выпьете немного кокилы. +Принесите бутылку кокилы. +- Нет-нет. +-Да-да. +Я настаиваю. +-До свидания, мадам Эдуан. +-До свидания. +-До свидания. +-До свидания. +-До свидания, мадам Эдуан. +- Мадемуазель Гаспарина. +Раз вы увидите месье Мурэ, попросите его срочно зайти. +Я не уйду из магазина, пока он не придет. +Хорошо, мадам. +Передайте ему, передайте, что речь идет о важном, срочном деле. +Хорошо, мадам. +До свидания, мадам. +- Среди честных людей... +- Среди сердечных людей... +- Всегда найдешь родственную душу. +- И поле битвы. +Какой остроумный! +-Здравствуйте, господа. +-Здравствуйте, Гаспарина. +Месье Мурэ, мадам Эдуан хочет срочно поговорить с вами в магазине. +- Мадам Эдуан? +-Да. +Похоже, дело срочное. +Извините меня. +Мое почтение, мадам. +- Вы хотели со мной поговорить? +-Да. +Я... +Я в курсе вашей ссоры с месье Вабром. +Знаю, что он послал вам секундантов. +Вам нельзя драться. +- Но он же мой противник. +- Я не хочу, чтобы вы дрались. +А вам-то что? +А если он вас убьет? +Ведь он такой неловкий. +Дуэль предполагает риск. +Впрочем, рискуют оба. +Кто сказал, что месье Вабр будет победителем? +Увы, в этом я не сомневаюсь. +Однажды я от вас ушел, и вы смирились. +Три месяца назад я для вас умер. +Если я умру по-настоящему, какая разница. +Я без сожаления уйду из этого мира. +У меня нет угрызений совести. +Месье Октав, вы должны знать правду. +В этой истории виновата я. +Это я, да, я пробудила подозрение у месье Вабра. +Я ничего конкретного не сказала, просто повела себя не лучшим образом. +Не знаю, что на меня нашло, но ваше поведение разозлило меня. +- Мое поведение? +- Ну да. +То, что вы стали доверенным лицом господина Вабра. +Я вообразила, что все ваши усилия направлены против меня. +Ваш отказ вернуться поверг меня в отчаяние. +Так все дело в магазине. +Не знаю, все так запуталось. +И вы испугались угрызений совести, что я погибну из-за вас. +Успокойтесь, этого не будет. +У вас не будет угрызений совести. +Вы были правы, меня интересуют только деньги и ничего более. +Вы донесли на меня. +Отлично. +Я за это заплачу. +Вы легко перенесете мою смерть. +О, нет, лучше я брошусь в ноги месье Вабру. +Это будет забавно. +Прощайте, мадам. +Октав! +Нет. +Дело не в магазине. +Простите меня, Октав. +Хорошо, дуэль отменяется. +Но это последняя жертва, на которую я иду, мадам Мурэ. +- Ну что? +- Еще одна большая пушка. +- Избавьтесь от нее. +- Оставить французам? +- Я сказал: избавьтесь. +- Есть. +Месье? +Майор, вы сделали невозможное. +Каким образом семитонная пушка проскочила у вас между пальцев? +Они ее уничтожили. +По-моему, она слишком большая. +Ваше мнение меня не интересует. +Пушка нужна генералу Жувэ. +Выполняйте приказ, а не думайте. +- Есть. +- Видаль. +За пушкой охотятся англичане. +Они отправили в Испанию шпиона. +Не оплошайте. +Иначе генерал отправит нас обоих служить на конюшни. +Да, месье. +Выходите. +- Англичанин? +- Англичанин. +Проводите меня в штаб. +Англичанин. +Мне нужна ставка генерала Ларены. +- Они переехали? +- Отступили. +Куда? +- А вы кто? +- Испанцы, которые не отступили. +Герьерос. +Если у вас дело, говорите со мной. +У меня письмо генералу Ларене. +Простите. +Хуана. +Прочти это. +Это Энтони Трамбел, морской офицер. +Генерал Ларена должен передать ему большую пушку... и людей для того, чтобы доставить ее в Сантандер. +Зачем? +Чтобы она не досталась Наполеону. +- Англичане тоже с ним воюют. +- Зачем прислали моряка? +Я говорю по-испански и изучал артиллерию. +Пушки. +Хотите ее видеть? +Конечно, хочу. +Спасибо. +- У англичан такая есть? +- Такой нет ни у кого. +- Она сломана? +- Можно починить. +- Вы бы смогли? +- Если будут люди. +Они есть. +Кузнецы? +Плотники? +Гильермо. +Франсиско. +Пепе. +Слушайте капитана. +Нужны шесть толстых бревен. +И снимите с пушки колеса. +Карлос, займись. +Пусть все тянут канаты. +Канатов как можно больше. +- Что-нибудь еще? +- Пока всё. +Да, капитан. +Пошевеливайтесь. +Не тяните вниз. +Нет, нет, левее. +Мигель. +Мигель. +- Французская кавалерия. +- Далеко? +- На той стороне. +- Через час будут здесь. +Оставьте пушку. +Так ее проще будет спрятать. +Хосе, сюда. +Живей. +Рамон, собери людей, чтобы рубить деревья. +Помогите им. +Карлос, поднимайтесь. +Закрепите канаты. +Впрягите мулов. +Проверьте надежность узлов. +Я нашел лучший путь в Сантандер. +Да, капитан. +Но пушка поедет в Авилу. +- Прошу прощения? +- В Авилу. +- Но вы сказали... +- Что я сказал? +Вы видели приказ. +Генерал Ларена передаст пушку нам. +Генерала Ларены здесь нет. +Вам не пересечь Испанию, ведь вас всего двести. +- За пушкой пойдет подкрепление. +- У вас нет пороха. +- Я его достану. +- С Наполеоном сражается весь мир. +На этом фоне Авила - песчинка. +Весь мир меня не интересует. +Авила - штаб французов в Испании. +До нее тысяча километров. +Местность кишит французами. +- Вы не доберетесь. +- Доберемся. +В Авиле есть стена, которую пробьет эта пушка. +Мы войдем в город любой ценой. +Даже если мы погибнем, Авила будет взята, и французы поймут, что пора оставить Испанию. +Вы все безумцы. +Капитан, вам нужна пушка в Сантандере, а мне - в Авиле. +Поедем с нами. +Научите нас с нею управляться. +А потом мы переправим ее в Сантандер. +Где гарантия, что так и будет? +Ее нет. +- Коня капитану. +- Я пойду рядом с пушкой. +Вы устанете, капитан. +Коня. +Капитан, у вас лицо в грязи. +Хуанита. +Давай, Хуанита. +Уже поздно. +Что ты делаешь? +Отнесу англичанину еду. +Он не ел с остальными. +Значит, он не хочет. +Мы ели. +Он такой же, как мы. +- Он не такой. +- Почему? +Он разбирается в пушках. +И нужен тебе. +Ты сам так сказал. +Я так не говорил. +Он мне не нравится. +Мигель, ты ревнуешь. +- Не к нему. +- Ты ревнуешь ко всем, а к нему особенно, потому что он умеет стрелять. +- Может, я тоже умею. +- Не умеешь. +Не говори того, о чем будешь жалеть. +Он нам нужен. +Признай это. +Тогда пусть на тебя не смотрит. +Мигель. +И ты тоже на него не смотри. +Это мое право. +Вы хорошо знаете этого Мигеля. +Знаете, что у него пушка. +Скажите мне, где он. +Я говорю как противник, но могу стать вашим палачом. +Прекрасно. +Значит, нужен пример. +Я повешу десятерых из вас. +На следующий день будет еще десять, и еще. +До последней женщины и ребенка в Авиле, пока кто-нибудь не заговорит и не укажет, где эта пушка. +Увести. +Выполняйте приказ. +Я сомневаюсь, что все эти повешения... +Знаю, знаю. +Вы считаете, что они бесполезны. +Велика ли эта пушка? +В два раза больше, чем вы можете представить. +Оккупированный народ выглядит мучеником. +Но когда у него появляется цель, он превращается в новую армию. +Вот чем опасна пушка, генерал. +Я не глуп, Сэрмен. +И мы ее найдем. +Надо постараться построить плот за три дня. +Понадобится сотня бревен. +Пушку закрепим на этой платформе. +- Так пересечем реку. +- Пушка затонет. +Нет. +Да и другого выхода нет. +Только ждать, пока русло высохнет. +Я хочу доставить пушку в Авилу, а это риск. +Главное, чтобы работали все. +Нам нужна сотня бревен. +Ладно. +Собери людей, пусть рубят деревья. +Действуйте, капитан. +Но если пушка утонет... +- Мне надоели ваши угрозы. +- Мне это не нравится. +- В любом случае, риска нет. +- Вашего слова не достаточно. +- Тогда позовите людей назад. +- Ладно. +Подождите. +Я скажу. +Мы знаем причину этого глупого спора. +Если надо переправляться, не тратьте понапрасну время. +Отпускайте плавно. +Тяните, тяните. +Хватайте другой трос. +Ну вот. +Всё жерло в грязи. +Лучше бы я этого не видел. +- Ее можно вытащить? +- Как? +Чем? +- Есть люди, мулы. +- Им ее не сдвинуть. +- Сколько потребуется народу? +- Тысяча или две. +В Альгадо жителей больше, Мигель. +Жители Альгадо, я плюю вам в лицо. +Я, Мигель, иду с пушкой на Авилу. +В Авиле никто не сидит на трибунах с французами. +И не поднимает наш флаг рядом с флагом врага. +Нет. +Подождите. +Что вы за люди? +Сидите, радуетесь жизни. +В двухстах милях отсюда враг забавляется тем, что насаживает испанских детей на штыки. +Может, у вас нет сердца? +И нет стыда? +По ту сторону реки в грязи застряла пушка. +Нам нужна помощь. +Я не прошу вас умереть. +Или пролить кровь. +Лишь попотеть немного. +Скажете детям, что в потоке сопротивления есть и ваш пот. +Те из вас, кто остался испанцем, идите за мной. +У вас лицо в грязи. +Вам нельзя рисковать. +Придется. +Их больше, они хорошо вооружены. +- Обходить будем три недели. +- Пусть будет три. +Капитан, в Авиле - командующий наполеоновской армии. +Генерал Анри Жувэ. +У него красивая форма. +Вино ему доставляют из Франции, а женщин - из Марокко. +Каждое утро, чтобы сломить сопротивление, он вешает десять испанцев. +За три недели он повесит двести десять человек. +Вы рискнете ради них пушкой и успехом дела? +А сколько народу он повесит, если вы не доберетесь до Авилы? +Нас ждут тысячи людей. +Я не могу медлить. +Я вам не помощник. +Если нас разобьют, вы сами потащите пушку в Сантандер. +Герцог Веллингтон. +Капитан, есть люди, которых не изменить. +- Например, Мигель. +- В этом наша беда. +- Значит, вы нас бросаете? +- Я не хочу идти на самоубийство. +Послушайте. +Конечно, с Мигелем трудно. +Он упрям. +Упрям - это мягко сказано. +Но никто не знает Мигеля лучше меня. +Вы привыкли вести себя, как на своем корабле. +Мигель на кораблях не ходил. +И воевать умеет, как Герьерос. +- Вы его поддерживаете? +- Как и все. +Но если он ошибается, мы всё равно с ним. +Надеюсь, вы тоже. +Почему? +Капитан, думаю, вы считаете себя мужчиной, а не свиным окороком. +Так. +Мы готовы. +Ты останешься с Марией и с ним. +Мне нужно пять человек. +- Зачем? +- Чтобы украсть порох. +Дай ему людей. +Герьерос! +Герьерос. +Откатите бочки с порохом в сторону. +Живее. +Живее. +Вперед. +Сейчас взорвется, прыгайте. +Я не офицер штаба. +У меня нет информации. +Он полевой офицер, он не в курсе дел штаба. +Пусть попробует вспомнить. +Попробуйте вспомнить. +Мне нечего сказать. +Я готов. +Скажите им то, что они хотят знать. +И останетесь жить. +- Что вы сказали? +- Не хочу, чтобы его убили. +Убеждаю заговорить. +Говорите. +Клянусь, у нас нет сведений из Авилы. +У меня семья, я не хочу умирать. +Он клянется, что сведений об Авиле нет, и не хочет умирать. +Они лгали. +Не пытайтесь умыть руки. +Эта кровь не смывается. +- И что? +- Я не буду молча смотреть на это. +Можете не смотреть, капитан. +Вы много вмешиваетесь. +- Если бы не пушка... +- То что? +- Я бы с вами не связывался. +- Идите, вы нам не нужны. +- Я выполняю свой долг. +- У меня тоже долг. +Не вмешивайтесь, или следующим убьют вас. +Вы безумец. +В порту Лас Крусес стоит британский корабль. +Идите туда. +Хорошо. +Сегодня же. +Лучше прямо сейчас. +Вы довольны? +Англичане не получат пушку, он не умеет стрелять. +Авиле конец. +- Он стоит на своем. +- Безумец. +Я буду с ним. +Но вам меня не понять. +Это не мое дело. +Вам этого не понять. +Генерал Жувэ приговорил к повешению моих отца и брата. +Я ему понравилась. +Я пришла к нему. +Но он всё равно их повесил. +Я молилась со всеми, чтобы тоже умереть. +Мне незачем было жить дальше. +Пока не появился сын сапожника. +Он показал, для чего нам жить, бороться. +Это был Мигель. +Вы отблагодарили его сполна. +- Я остаюсь с ним. +- Вы с ним живете, но не любите. +Потому эта связь сомнительна. +Британский капитан и участница сопротивления... +- тоже не пара. +- Я готов рискнуть. +И подготовите пушку? +Он сказал, что сам справится. +Мигель не всегда говорит то, что думает. +Я не буду перед ним извиняться. +Этого не нужно. +Я сделала это за вас. +Сколько картона может съесть человек? +Три дня - вода и вот это. +Чтобы тянуть пушку, нам нужны силы. +Ты еще не мужчина. +Он тебе предан, а ты смеешься над ним. +Хосе, они просто шутят. +Я ничуть не хуже их. +И ты это знаешь. +Ты лучше. +Ты молод, смел, силен и красив. +Мечта любой женщины. +Ты также умен и... +Хватит, Хуана. +Довольно. +Я не сержусь. +Пожалуйста. +Умоляю вас. +Прошу. +Пожалуйста. +В деревне есть дети. +Отдайте еду. +Мы умрем. +Хотя бы хлеб. +Хоть что-нибудь. +Мигель, коньяк. +- Что такое? +- Вы сами слышали. +Ну и что? +- Нам ведь нужна еда. +- Поддержка крестьян важнее. +- Что вы знаете о крестьянах? +- Наверное, почти ничего. +Тысячи крестьян встретят вас в Авиле. +Что вы им скажете? +Я найду, что сказать. +Я устал от ваших советов. +Во всех деревнях будут прятать еду. +И никто больше не захочет нам помогать. +Уступаю вам право командовать. +Договоритесь с крестьянами. +Можете расплатиться с ними. +В фунтах стерлингов. +Объясните ему, что он не прав. +Я живу с крестьянами. +И меня не надо учить общаться с ними. +- Нет, конечно. +- По-твоему, он прав? +- Я думаю... +- Для женщины ты много думаешь. +По мне, так ты прав, Мигель. +Мигель, извинись перед ним за свои слова. +Хосе. +Нос утри. +Целый лагерь смели. +Хорошенькое дело. +Непобедимая французская армия бежит в горящих подштанниках. +А они скрылись. +Это их земля, генерал. +Они знают, когда нападать и где прятаться. +Они и сейчас прячутся. +Они снова выступят. +Я догадываюсь, где. +- Им помогают. +- Крестьяне. +Не только. +С ними британский морской офицер. +Военный корабль англичан стоит в Лас Крусесе. +Здесь. +Прекрасно. +Прекрасно. +Организовать на всех дорогах в Лас Крусес постоянный дозор. +Проверим вашу догадку. +Карлос. +Карлос. +Телеги. +Где телеги? +- Где телеги? +- Я не знаю. +Понятия не имею. +Я отправил их назад в деревню. +В деревню? +Мигель. +- Карлос его убьет. +- Он просто немного позабавится. +Карлос, хватит. +Рана не опасна. +Через несколько дней... +Я не перестану помнить, что убил этого человека. +Мигель не предполагал, что всё так выйдет. +Конечно. +Это была забава. +Мне жаль. +Правда. +Не надо. +Это вовсе не связано с телегами. +Он ревнует, и не напрасно. +Я сказал тебе, что доставлю пушку в Авилу. +И я это сделаю любой ценой. +Но не ради него и не ради долга. +Я знаю причину, ты тоже. +Мы видели пехоту. +На той стороне реки. +Нельзя, чтобы нас засекли на равнине. +Ничего. +Пересечь Кано трудно. +- Там есть мост. +- Моста нет. +Я же знаю. +Французы построили там мост. +На лодках. +- Сколько там лодок? +- Пятнадцать, шестнадцать... +Мне нужно больше пятисот фунтов пороха. +Вам нужно? +Ладно, давайте порох. +Энтони. +Возьми Хосе. +Он работал в шахте и применял порох. +Возьми. +Я скажу Мигелю. +Сколько тебе лет? +Все думают - двадцать. +Вообще-то, восемнадцать. +Боишься? +Нет. +Я - да. +Знаете, зачем Хуана меня отправила? +- Помогать. +- Да. +А еще вы ей нравитесь. +Я солгал. +Мне страшно. +Но ничего. +Я справлюсь. +Что ж, пора окунуться. +Стойте. +Я тебя искал. +Хотел сказать, что мне жаль Хосе. +Ты не виноват. +Хуана. +Всю жизнь я боялась, ведь ничто не вечно. +Сейчас тоже боюсь, что это всего лишь сон. +Нет. +Обещаю. +При других обстоятельствах ты бы на меня не взглянул. +Хочешь, чтобы я сказал? +Я... +Нет. +Просто всё было бы совсем иначе в Англии. +Я запер бы тебя в башне, поставив верных стражей, и хранил бы ключ. +Золотой. +Тебе не хватило бы жалования. +Когда я стану адмиралом, у нас будет карета. +И мы будем танцевать на королевских балах. +Мне понадобится новое платье. +Да. +И голубой шарф под цвет моей формы. +Кланяться я буду осторожно. +Штаны сидят слишком плотно - однажды порвались. +Энтони. +Да? +- С кем ты был? +- Когда? +Когда штаны порвались. +Король захочет с тобой познакомиться. +Расскажешь ему, как однажды в далекой Испании встретила английского капитана... и сделала его самым счастливым человеком. +Я люблю тебя, Энтони. +Хуана. +Да? +Мы все испанцы и знаем, чего хотим. +Нам известна цена похода на Авилу. +Я понимаю, Мигель. +Но ты хочешь знать, что будет после Авилы. +Да. +Этого я не скажу. +Но мы долго были вместе. +Ты жила со мной, хотя я не умею ни читать, ни писать. +Когда я не мог подобрать слова, ты делала это за меня, Хуана. +Я чувствовал себя настоящим мужчиной. +Но в глубине души я знал, что я никто. +Думаешь, я не способен чувствовать, чего хочет женщина? +Я могу отблагодарить тебя, только лишь вернув Авилу. +Если этого мало, скажи. +Попытка разыскать горстку повстанцев... останется в военной истории как пример беспомощности. +Ваша карьера поставлена под вопрос из-за этого марш-броска с пушкой. +Мы успели потерять мост и немало людей, прежде чем поняли, что пушка здесь. +Далеко от Лас Крусеса и от моря, полковник. +Да, месье. +В этих горах есть ущелье. +Вот оно. +Именно там я их встречу. +Не думаю, что им удастся уйти. +Ну? +Там французские пушки. +Это же все знают. +- Я тоже знаю. +- Как ты хочешь там пройти? +- Есть другой путь? +- Мы обещали помочь, но не ценой жизни. +Ты попадешь под перекрестный огонь. +Нас не услышат. +Постараемся, чтобы колеса не скрипели. +Думаете, французы глухие? +Если преодолеть незаметно хоть полпути, у нас есть шанс. +Так что не надо изображать упрямых ослов. +Мы оставили наши лавки и фермы. +Что течет в ваших жилах? +Что угодно, но не кровь. +Нам нужно на юг, чтобы попасть в Авилу. +А значит, нужно пройти здесь. +Это ясно? +Да, капитан. +Яснее некуда. +Нам немного стыдно, но у нас у всех жены и дети. +Мы не готовы умереть за эту пушку. +- Нам нужна помощь. +- Обойдемся без них. +Удивительное умение убеждать. +- Я должен встать на колени? +- Если это поможет - да. +- Они нам нужны. +- Обойдемся. +Полсотни греков защищали ущелье от тысячи солдат. +У нас всё наоборот. +Я не изучал историю, но знаю точно: +я буду стоять перед статуей Святой Терезы в Авиле. +Прекратить огонь. +Они вне зоны огня, но дороги перекрыты. +Смирно! +Их нет ни у входа, ни в самом ущелье. +Оставайтесь на позиции и ждите моего приказа. +Бревно сюда. +Тащите. +Хорошо вы знаете холмы. +Здесь не спуститься. +- Спустимся, как поднялись. +- Пушку потянет вниз. +Ускорение и масса взаимосвязаны. +При весе в пять тонн на спуске... ее масса достигнет десяти-пятнадцати тонн. +Ее будет не удержать. +Она всегда весит одинаково. +Поворачивай мулов. +Продолжайте. +Живее, живее. +Бревно сюда, бревно. +Капитан. +Бревно, скорей. +Отходите. +Освободите мулов. +Прыгай. +Крепление пушки сломано. +Вверх идти нельзя, надо спускаться. +Блестяще. +Спускаться было труднее. +Неподалеку есть городок Манесирас. +Манесирас. +Манесирас. +Предлагаю пойти туда и починить там пушку. +Нам нужны инструменты, кузница и укрытие от французов. +Мигель, вдруг там французы? +Он что, пойдет в форме? +Нет. +Что вы предлагаете? +Выбирайте. +Придется попросить вас. +Испанские блохи. +Они не кусают англичан. +- Это можно разрешить. +- Есть еще одно. +- Что? +- Пушка. +Сын мой, сила дома Господня велика. +Но пушка не читает молитвы. +Мы хотим спрятать ее внутри собора. +А завтра... +- Внутри собора? +- На одну ночь. +Идет страстная неделя. +Вы оскорбите святилище. +Солдатам и пушкам место за дверью. +Это дом Господа, но не арсенал. +Ты много просишь. +Ваше Преосвященство. +Вы не можете отказать. +Не могу? +Ни к чему прикрываться ответственностью и правилами. +Мало сказать, что пушке в соборе не место. +Это не просто пушка, а символ сопротивления Испании. +Знаете, сколько людей отдали свои жизни, чтобы она попала сюда? +Вы не видели горных троп, покрытых мертвыми телами. +Ради чего? +Вы можете не знать ответа, но вы испанец, священник, и должны это чувствовать. +Вы не можете отказать. +Хорошо. +Сегодня вечером будет служба. +Тогда и внесете пушку. +Святая Дева, ты услышала мои молитвы. +Он всё понял. +И я люблю его еще больше. +В твоих глазах я грешница. +Но я впервые с детства осмелилась мечтать. +Но есть еще Мигель. +И его мечта +- Авила - которую я навсегда разделяю. +Слишком дерзко просить, чтобы ты помогла обоим. +Но выслушай. +И пусть твое сердце простит мой выбор. +Это за Мигеля и Авилу. +А это за любовь, обретенную с другим. +Внутри собора? +Да. +Пушка там. +- Да ты пьян. +- Точно. +Я ее видел. +Ладно. +Проверим. +Итак, гости, наконец, прибыли. +Их больше, чем я думал. +В самом деле. +Они смогут пробить стены? +Да. +Если сами не взорвутся. +Сколько, по-вашему, там человек? +Около десяти тысяч. +И подходят еще. +Опасно для кавалерии. +Что-то тучи стали сгущаться. +Испанцы ждут момента истины. +Митч МакКафи, летающий Шерлок Холмс. diff --git a/bench/data/opensubtitles/ru-small.txt b/bench/data/opensubtitles/ru-small.txt new file mode 100644 index 0000000..896f930 --- /dev/null +++ b/bench/data/opensubtitles/ru-small.txt @@ -0,0 +1,18 @@ +-Две недели не даешь мне прохода. +Вот и действуй, чем ты рискуешь? +Я думал, что сделаю тебя счастливой. +Тоже мне счастье. +Муж не дает ни гроша, и у любовника ума не хватает подумать о деньгах. +- Хорошенькое счастье. +- Извини, я думал, ты любишь меня. +Ну люблю, люблю тебя, но и не хочу, чтобы все началось как в прошлый раз. +Ты не права. +У меня для тебя сюрприз. +Шлихтовальная машина, ты о ней давно мечтала. +-Для костей? +- Нет, настоящая. +Хочешь, приходи за ней вечером. +Я тебе не девочка. +Была бы ты девочкой, я бы тебе ее не купил. +Я люблю тебя +Митч МакКафи, летающий Шерлок Холмс. diff --git a/bench/data/opensubtitles/ru-teeny.txt b/bench/data/opensubtitles/ru-teeny.txt new file mode 100644 index 0000000..6dccb35 --- /dev/null +++ b/bench/data/opensubtitles/ru-teeny.txt @@ -0,0 +1 @@ +летающий Шерлок Холмс. diff --git a/bench/data/opensubtitles/ru-tiny.txt b/bench/data/opensubtitles/ru-tiny.txt new file mode 100644 index 0000000..bafd891 --- /dev/null +++ b/bench/data/opensubtitles/ru-tiny.txt @@ -0,0 +1,2 @@ +Это - одно из самых поразительных недавних открытий науки. +Митч МакКафи, летающий Шерлок Холмс. diff --git a/bench/data/opensubtitles/zh-huge.txt b/bench/data/opensubtitles/zh-huge.txt new file mode 100644 index 0000000..62804bd --- /dev/null +++ b/bench/data/opensubtitles/zh-huge.txt @@ -0,0 +1,22000 @@ +魯哇克香貓咖啡 世界上最稀有的飲品 Kopi luwak. +the rarest beverage in the world. +嘗一小口 Take a whiff. +來 Go ahead. +寇爾先生 董事會已準備好聽你的提案 Uh, mr. +cole, the board is ready to hear your proposal. +等一下下 Hold on just a second. +來 繼續 Go ahead. +go on. +怎樣 Well? +真不錯 Really good. +真不錯 Really good. +寇爾先生? +Mr. +cole. +sir? +吉姆 你知道庸俗是什麼嗎 Do you know what a philistine is, jim? +先生 我叫理查德 Sir, it's richard. +沒錯 費爾 出動你的如簧巧舌吧 That's right, phil. +give them the spiel. +謝謝 主席先生 主管們 Thank you, mr. +chairman, fellow supervisors. +我們寇爾集團財務的管理不善 We at the cole group feel the decline of the winwood hospital... +直接造成了溫伍德醫院的衰敗 ...is a direct result of significant fiscal mismanagement. +請原諒 我們醫院... +I beg your pardon, this hospital... +日常開支近2倍 overhead costs are nearly double. +你們的租金和置業費用高得不可置信 Your lease and land costs were similarly overbid. +在科研分析 兒科 腫瘤學和核磁共振等領域的貢獻 Donations have atrophied to the point you've fallen far behind +萎縮到了有史以來曲線的最低點 the curve in research, pediatrics, oncology and mri. +7年來 寇爾集團私有化了15家公立醫院 The cole group has privatized 15 public hospitals in seven years... +每一家目前都為社區提供 或即將提供 ...each of which now provides, or will soon provide... +最高標準的醫療服務 ...the highest standard of medical care to their communities. +人手問題就不管了嗎 despite being grossly understaffed? +越好的醫生 越需要... +the better the doctor, the need... +床位怎麼辦 外面在傳你們收太多病人 What about beds? +there are rumors you increased the number +擠都擠不下了 of patients to the point of overpopulation. +病人的密度一直是... +Patient density has always been... +還有急診室 這可是眾所周知的... +And your emergency rooms, I mean, they are known... +我開的是醫院 不是健康療養所 I run hospitals, not health spas. +一個房間兩張床 無一例外 Two beds to a room, no exceptions. +聽著 我和米雪爾. +費弗約好了來這兒吃午飯 Look, I passed up a lunch with michelle pfeiffer to be here... +我們能否盡早停止惺惺作態 ...so can we desist from all of this inane posturing? +男孩女孩們 你們需要我 Boys and girls, you need me. +而我卻不需要你們 I do not need you. +這信封裡有一張大額支票 Now, there's a sizeable check in this envelope... +如果決定了就請隨便使用吧 ...let me know if you decide to cash it. +寇爾先生 你沒事吧 Mr. +cole, are you all right? +你在這兒幹嘛 What are you doing here? +為生命而戰鬥啊 你呢 Oh, you know, fighting for my life. +you? +我只是有點驚奇... +Uh, no, I was just surprised... +我並不在乎保險 and I don't care about the insurance! +去告訴那個腦子糊了屎的醫生 必須告訴我 And tell dr. +shit +-for +-brains i wanna know everything +為什麼一定要我打這一針光黴素 about this bleomycin drip he wants to get me on. +我聽說它會吞噬你的肺 I hear it eats your lungs. +等我下個月去國會座談時 When I address congress next month... +我不想通過喉嚨裡的洞來呼吸 ...i don't want to do it breathing through a hole in my throat. +-其實並不完全是這樣 +-這傢伙是誰 +- that's not exactly what happens. +- who the hell is this guy? +-湯馬斯在哪兒 湯姆 +-我在這兒呢 先生 +- where's thomas? +tom! +- in plain view, sir. +-你好 湯姆 +-我們要把你挪上床 +- hi, tom. +- we're gonna move you into the bed. +我能自己來 我還沒死呢 I can do it myself. +I ain't dead yet. +現在怎樣 How about now? +我最近炒你魷魚了嗎 Have I fired you lately? +自從奧普拉事件以來還沒有 Not since the oprah incident. +-他是個好人 +-對 好員工 +- that was a good one. +ha +-ha +-ha. +- yeah, it's good stuff. +那他媽是誰 Who the hell is that? +你他媽又是誰 Who the hell are you? +他說 "你他媽... +?" He said, "who the hell... +?" +天哪 我在哪兒 這是停屍房嗎 Oh, god. +what am i, in the morgue? +那是我第一次將目光停留在愛德華. +寇爾身上 That was the first time I laid eyes on edward cole. +一個不祥的開始 一定是這樣 An inauspicious beginning, to be sure. +放過我吧 親愛的上帝 Oh, spare me. +sweet jesus. +我討厭這些... +我討厭針管 I hate these... +I hate tubes! +要是接下來3個星期裡 I'll be damned if I'm gonna spend the next three weeks +我都挨著這個傢伙一起睡的話 我一定會死的 laying next to this guy. +怪人一個 像個半死人 Zombie boy. +looks half +-dead already. +你不能住單間 You can't have your own room. +不然會造成巨大的公關問題 It would create an enormous pr problem. +我沒有定過這樣的鬼規矩 I don't give a shit about pr. +我要住單間 這是我的醫院 沒天理啊 I want my own room. +it's my hospital, for chrissake. +別告訴我不能住單間 Don't tell me I can't have my own room. +無意冒犯 保爾 No offense, pal. +這政策你已公開辯護過無數次 You have publicly defended this policy countless times. +你開的是醫院 不是健康療養所 You run hospitals, not health spas. +一個房間兩張床 無一例外 two beds to a room, no exceptions. +我從前沒有生過病 I've never been sick before. +好吧 艾爾德瑞吉醫生馬上就要來給您打麻醉 Okay, dr. +eldridge will be in in a minute to dot you up, okay? +打麻醉 Dot me up. +上帝 Jesus. +湯馬斯 Thomas +麻醉時別讓我清醒著 don't let me wake up paralyzed. +我會竭我所能 I'll do what I can. +這真的是你的醫院嗎 This really your hospital? +是的 沒錯 Yeah, pretty much. +難喝的豌豆湯需要改進一下 Might wanna do something about the pea soup. +在早上的手術時發現 By the morning of the surgery, +癌癥已經擴散到愛德華的全身 the cancer had spread so far throughout edward's body +醫生們估計他只有5%的希望能活下來 that the doctors gave him only a 5 percent chance to survive +但他們卻未曾估計到他對他們有多生氣 But then, they didn't account for how pissed off they'd made him. +沒有人來看他嗎 No visitors come in to see him? +手術結束後他就一直睡著 He's been sleeping a lot since they brought him back. +哦 Mm. +我親自來護理你 還有一個原因 That's another reason I don't miss nursing. +你看病人要是那樣 是多麼可憐啊 It's always so sad seeing a patient like that, +還獨自一人 挺過手術 all alone after that kind of surgery. +至少他不嘮叨 At least he's quiet. +瑞秋今早來過電話 Rachel called this morning. +真的? +她怎麼樣 Really? +how's she doing? +她在為下學期在交響樂團當首席小提琴手做準備 She's auditioning for first violin in next semester's symphony. +那真是太好了 That's wonderful. +還要書嗎 Need any more books? +不用了 我很好 No, I'm... +I'm fine. +今晚的藥拿到了嗎 Got your meds for the night? +嗯 我已經吃過了 Mm +-hm. +I already took them. +枕頭怎麼樣 How about pillows? +我很好 弗吉尼亞 真的 謝謝你 I'm fine, virginia, really. +thank you. +如果你願意的話 我可以陪你待一會兒 You know, I could stay a while if you want me to. +沒必要把你也給拖累了 對嗎 No use both of us being useless in the morning, right? +好吧 Okay. +她走了? +She gone? +什麼 What? +作為公共健康專家之流 As something of a public health expert, +我相信更多的人死於探望者 而勝過死於疾病 I believe more people die from visitors than diseases +這種草莓 600塊 "it's the berries," for 600. +這種瑞典草莓和越橘一樣享有盛名 This swedish berry is also known as the cowberry. +-越桔又是什麼 +-越桔又是什麼 +- what is a lingonberry? +uh, what is a lingonberry? +正確 這種草莓 800塊 Correct! "it's the berries," for 800. +1956年熱賣前40名中 這草莓告訴貝多芬轉存 In a top 40 hit of 1956, this "berry" told beethoven to roll over. +誰是查克. +貝瑞 Who is chuck berry? +誰是查克. +貝瑞 對 Who is chuck berry? +yes. +嘿 Hey. +杜克 Duke? +你介意嗎 You mind? +哦 對不起 Oh. +sorry. +no. +-什麼是馬裡亞那海溝 +-什麼是馬裡亞那海溝 +- what is the mariana trench? +- what is the mariana trench? +早上好 愛德華 Good morning, edward. +-早 +-感覺怎麼樣 +- morning. +- how you feeling? +明擺著呢 Dumb question. +導管怎麼樣 How's that catheter? +真不知道沒有它的時候我是怎麼過來的 Don't know how I ever did without it. +幽默是個好兆頭 Ah, humor is a good sign. +你去死吧 Kiss my ass. +太粗魯了 這是你最大的愛好了 對吧 As is surliness. +it's one of your favorite flavors, right? +-對 +-看看這裡怎麼樣 +- yeah. +- let's see what we got here. +看起來不錯 It looks good. +手術很順利 好嗎 All right, so the operation went well, okay? +所有的術後腦掃瞄都很乾淨 All the post +-op brain scans are clean. +現在我們要乘勝追擊你體內剩餘的腫瘤 Now we go after the sarcoma in the rest of your body. +不幸的是 你的血壓很高 Now, unfortunately, your blood markers are extremely high, +我希望今早我們就開始化療 so I would like to begin chemo this morning. +喜歡早上化療的味道 Love the smell of chemo in the morning. +現代啟示錄 對嗎 Apocalypse now, right? +讓我感覺像個勝利者 Makes me feel like victory! +-我等會兒和你去辦手續 +-好的 +- I'll check in with you later. +- all right. +喂 大夫? +大夫? +Say, doc? +doc? +你可以來看一下... +You think you could just take a look at... +? +-對不起 我遲到了 你的醫生是誰 +-蓋比安醫生 +- sorry, I'm late. +who's your doctor? +- he's dr. +gibian. +我告訴護士 I'll let the nurse know. +謝謝 Appreciate it. +婊子 不是嗎 Bitch, ain't it? +-夸克是什麼 +-夸克是什麼 +- what are quarks? +- what are quarks? +你在這兒多久了 how long you been here? +進進出出幾個月了 In and out over the past few months. +把我當成試驗品 got me on an experimental treatment. +-二元方程式是什麼 +-二元方程式是什麼 +- what is the quadratic equation? +what is the quadratic equation? +有多痛苦 How rough is it? +化療? +Chemo? +不是很糟 Not too bad. +只要你不介意晝夜不停的嘔吐 If you don't mind around +-the +-clock vomiting... +看著你的血管變黑 ...watching your veins turn black... +感覺骨頭像是汽油膠化劑做的一樣 ...and feeling like your bones are made of napalm... +與在海灘上度假一日無異 ...it's a day at the beach. +那真是種欣慰 That's a relief. +當然 我聽說每個人的反應都不一樣 Of course, I hear people react to it differently. +今晚你自己就知道了 You'll know by tonight. +今晚? +Tonight? +聽著 Listen, um... +是否介意我八卦一下 ...you don't mind my asking... +那邊那個奇妙的裝置是什麼 ...what is that contraption you got over there? +是虹吸壺 煮咖啡用的 It's a siphon. +makes coffee. +它還能幹些什麼 What else does it do? +它還能幹些什麼呢 What else does it have to do? +你是否知道咖啡最初是由埃塞俄比亞的 Did you know that coffee was originally discovered +一個牧羊人所發現的 by a shepherd in ethiopia? +-不必說了 +-是真的 +- you don't say. +- it's true. +好像是他的山羊在一個陌生的灌木叢中吃漿果 Seems his goats were eating berries from an unfamiliar bush. +沒過多久 羊就到處跑跑跳跳 Before long, they were running and jumping all over... +度過了一段歡欣雀躍的時光 ...having a gay old time. +於是牧羊人帶了一些樹枝回到當地的修道院 So the shepherd took some of the branches to the local monastery +修道院長決定把樹枝烤熟 where the abbots decided to roast them. +烤著烤著 When the berries burned +裡面的豆子散發出了濃郁的香氣 the beans inside gave off such a pleasant aroma +他們把豆子放入燉鍋中釀造 they brewed them into a stew. +燉鍋 Stew, huh? +隨後的幾百年裡 咖啡流傳到了阿拉伯 歐洲... +And over the next few hundred years, it spread to arabia, europe... +甚至蘇門答臘島 正如你從那兒買的烈酒一樣 ...even sumatra, like that hooch you got over there. +它叫做魯哇克香貓咖啡 It's called kopi luwak. +我知道它的名字 I know what it's called. +是嗎 You do? +從來沒人逮住過我喝那玩意兒 Never catch me drinking that shit. +你喝過嗎 Have you ever tried it? +沒有 我更鍾情於速溶咖啡 No. +I'm more of a instant +-coffee man. +來 我來幫你 Here, here we are. +-謝謝 +-不客氣 +- thanks. +- no problem. +好了 給 There you are. +你一直有雀斑嗎 You always had those freckles? +是的 Far as I know. +挺好看的雀斑 Nice freckles +嗯 Hmm. +好了 我們有培根火腿和甜瓜 還有些意大利布拉塔乾酪 Okay, we got prosciutto and melons, some burrata mozzarella... +和一塊小牛排 ...and a veal paillard. +都是上好的意大利傳統膳食 The folks at toscana send their best. +你要全部吃完嗎 You sure you wanna eat all that? +是這麼打算的 That's the plan. +什麼 What? +哦... +Oh, uh... +要湯馬斯給你也來一盤嘛 You want thomas to make you a plate? +湯米 弄一盤給... +Tommy, uh, fix a plate for, uh... +卡特 Carter. +是姓還是名? +First name or last? +名字 First. +真的? +很有意思 Really? +interesting. +要來一盤嗎... +? +說不定能讓你振奮 So you want, uh... +? +might cheer you up. +不需要了 謝謝 No, thanks, I'll pass. +確定? +You sure? +好吃 好吃 Mm, yum, yum. +全洛杉磯最好吃的 Best in l. +a. +再也不是洛杉磯最好的了 It ain't the best in l. +a. +no more. +我的天啊 Oh, man. +瑪亞又是三好學生 Maya made the honor roll again. +我肯定她行的 Bet your ass she did. +我的天啊 My god. +還不如得個心臟病什麼的 Somewhere, some lucky guy's having a heart attack. +同志們 Fellows. +寇爾先生 Mr. +cole. +別管我 我只是在自言自語而已 Don't pay any attention to me. +I'm just, uh, talking to myself. +這是凱爾給你的 It's from kai. +他說長大後想成為像他爺爺一樣的機械師 Says he wants to be a mechanic like his granddad when he grows up. +希望你讓他打消這個念頭 I hope you talked him out of that. +我試過了 Well, I tried. +看看是什麼東西 What do we got here? +一部福特野馬350 It's a shelby 350. +-我一直想要一部 +-是啊 +- I always wanted one of those. +- yeah. +凱爾記著 kai remembered. +媽媽覺得你好像休息得不夠 Mom seems to think you're not getting enough rest. +恩 Mm +-hm. +她愛你 爸爸 She loves you, pop. +恩 Mm +-hm. +好 Okay. +檢查報告出來後 給我們打電話 好嗎 You'll, uh, call us when you get your test results, huh? +恩 Mm +-hm. +如果有結果的話 If that day ever comes. +好 Okay. +-保重 +-好 +- take care. +- okay. +你的長子? +He your oldest? +是 Yeah. +他做什麼的 What's he do? +-羅傑是稅務律師 +-哦 +- roger's a tax attorney. +- oh. +你看 Here. +他弟弟李 是個工程師 His brother, lee, is an engineer. +這個漂亮的小女孩是誰 Who's the pretty little lady? +那是瑞秋 三個中最小的 That's rachel. +youngest of the three. +年紀差得好大 Big age difference. +是啊 她是個驚喜 Yeah, well, she was a surprise. +她出生後 我兒子們都寧願呆在家裡照顧她 We'd hardly gotten the boys out of the house when she came along. +她小提琴拉得很棒 She's an outstanding violinist. +你有小孩嗎 You got kids? +這要看了 Depends. +-我的婚姻關係都不長 +-恩... +- never stayed married long enough. +- oh, well... +別擔心 對於我們兩個來說我結婚夠久了 ...don't worry, I've been married long enough for the both of us. +覺得怎麼樣 How's that going? +就這樣 It's going. +感覺不錯吧? +That good, huh? +這就是為什麼要發明電燈開關的原因了 Well, that's why they invented light switches. +別誤會 我愛婚姻生活 結過四次婚 Don't get me wrong, I loved being married, been there four times. +問題在於我鍾情於獨身 Problem is I love being single too. +魚和熊掌不可兼得 Hard to do them both at the same time. +人無完人嘛 Well, nobody's perfect. +我唯一成功的就是我的事業 Only successful marriage I had was me and my work. +我16歲時就開始賺錢... +I started making money when I was 16... +...之後就 ...and that was that. +沒有停過 Never stopped. +我比較倒霉 I'll be damned. +我原來想當歷史教授 I wanted to be a history professor. +人無完人啊 Nobody's perfect. +弗吉尼亞告訴我懷孕前 I made it through two months of city college... +我在城市學院做過兩個月 ...before virginia gave me the news. +然後... +And then, you know... +年紀小 黑人還窮 孩子又要生了 ...young, black, broke, baby on the way... +就接了第一份待遇還不錯的工作 Take the first decent job that comes along. +我一直想回去 I always meant to go back +但45年一晃就過去了 but 45 years goes by pretty fast. +時光飛逝 Like smoke through a keyhole. +該死 Shit! +不要睡著的時候給我打嗎啡 真是浪費 Don't give me the morphine while I'm sleeping. +it's a waste. +她可能是想把我們倆都殺了 你說呢 Maybe she's trying to kill us both. +you ever think of that? +贏了 Gin. +你是什麼 魔鬼嗎 What are you, the devil? +如果我已經失去理智了怎麼辦 What if I lost my mind already? +老天啊 不會吧 Jesus, no. +不 不 不 這不是祈禱 No. +no, no jesus, this is not praying. +我只是在自言自語 這是 I'm talking to myself out loud, that's... +你想過自殺嗎 You ever think about suicide? +自殺? +我? +Suicide? +me? +yeah. +沒有 no. +知道了 你是第一階段 Thought so. +stage one. +什麼 What? +有五個階段 但是... +The five stages, but... +否認 Denial. +然後是憤怒 抵抗 沮喪 接受 Then anger, bargaining, depression, acceptance. +所以你現在當然不會想到自殺 So of course you're not thinking of suicide. +你處於第一階段 否認 You're in stage one. +denial. +那你在哪個階段 What stage are you in? +否認 Denial. +想過自殺嗎 And thinking about suicide. +好吧 這只是一個... +Yeah, okay. +it's just a frame of... +看上去你好像不再需要這個了 Well, it looks like you won't be needing this anymore. +-結束了? +-第4個療程 也是最後一個 +- that's it? +- yep, fourth and final. +接下來做什麼呢 What's next? +醫生要先看看所有的檢查結果再決定 They have to run all the tests first, see where we stand. +-要多久 +-需要點時間 +- well, how long? +- takes a while. +我會讓蓋比安醫生安排檢查的 I'll get dr. +gibian to schedule them when I see him. +謝謝 Thanks. +我離下班還有一個小時 還有什麼需要嗎 I'm on for another hour, anything you need? +如果可以的話 我想要健康證明書 Clean bill of health if you got one. +堅持一下 卡特 Hang in there, carter. +我就是這麼做的 That's what I do. +到中心線 上壘... +And line to center, base hit... +將要打三個反彈球 ...kent will have to play it on three bounces... +得分 投球手向後... +...and alou will score. +the throw goes to the back... +啊呀抄近路 天啊 Hit the cutoff man, for crying out loud. +你看 這就是比賽癥結所在 You see that's the problem +沒有基本原則 No fundamentals. +有讀過這本書嗎 Did you ever read the time of your life? +-威廉. +薩洛揚寫的 +-是的 +- william saroyan. +- yeah. +"沒有基礎 完全沒有" "no foundation. +all the way down the line." +當我們長大後... +你在做什麼 When we were growing up... +what are you doing? +沒有 隨便寫寫 Nothing, scribbling. +寫點什麼 Scribbling? +what? +沒什麼 亂寫而已 Nothing. +just scribbling. +當然 這是你想做的 Oh, sure, that's what you wanna do +三壘的人 球偏了點 bounce a slider with a man on third. +現在的這些孩子... +These kids today, they... +戴耳機了 我原來在自言自語 Earphones. +I'm talking to myself, again. +-愛德華? +-醫生 +- edward? +- doc. +感覺如何 How's it going there? +愚蠢的問題 Dumb question. +檢驗報告出來了 I got the test back. +現在就說嗎 I'll just lay it out, huh? +只剩六個月 Six months. +幸運的話一年 A year if we're lucky. +我們有一個實驗性的療程 There is an experimental program that we've been conducting +但不要抱太大希望 and I don't wanna get your hopes up +只是覺得你比較適合來試試看 but I think you would be an excellent candidate +醫生 Hey, doc. +怎麼了 Yes? +你擋住我視線了 You're blocking my view. +哦 Oh. +對不起 Sorry. +如果你有什麼想問的 Anyway, if there's any questions +不管什麼時候 都可以來找我 day or night, you know where to find me. +有一個問題 One question. +當然 問吧 Sure, of course. +卡特 你有什麼要問霍林斯醫生的嗎 Carter, you wanna ask dr. +hollins something? +我其實對錢柏先生的病情不太瞭解 I mean, I'm not familiar with mr. +chambers'... +那就去瞭解一下 Well, get familiar. +我只是想知道我還能活多久 就這個 I just wanted to know how I stand, that's all. +好的 那我先去看看你的病情報告 Sure. +how about I'll go take a look at your chart, okay? +謝謝 Thank you. +愛德華? +Edward? +愛德華? +Edward? +曾經有一項調查 There was a survey once. +一千名被調查者被問到否願意 A thousand people were asked, if they could know in advance... +事先知道他們的死期 ...would they want to know the exact day of their death. +96%的人不想 Ninety +-six percent of them said no. +我我以為我就是那剩下的4% I always kind of leaned toward the other 4 percent. +因為如果能知道自己的生命還剩多少 I thought it would be liberating... +將會是一種解脫 ...knowing how much time you had left to work with. +最好的情況是1年 A year at best. +但其實... +我不是 It turns out, it's not. +想玩牌嗎 You want to play cards? +以為你再也不會問了 Thought you'd never ask. +太陽高高昇起 Rise and shine. +或者這樣 Or that. +讓我看看 Let me see that. +還有 湯馬斯 And, uh, thomas... +打電話給克裡斯蒂拍賣行的瑪麗 call marie at christie's and tell her +這個季度我不去競拍了 I won't be bidding this season. +知道了 I understand. +我不想冒犯你 Uh, sir, I don't mean to sound indelicate +但你要我怎麼處理你的... +but how do you want me to handle your? +遺產? +Death? +就當作你的遺產一樣處理 Treat it as if it were your own. +把所有的錢都留給我的助理? +So leave all the money to my assistant? +去給我買塊杏仁牛角麵包 Go get me one of those almond croissants that I like. +給我挑好的 And don't buy any green bananas. +-你在看什麼 +-這是什麼 +- what are you doing? +- what is this? +-快還給我 +-是什麼 +- come on, give it back. +- what is it? +還給我 Give it back. +地上撿的 我又不知道這是國家機密 It was on the floor. +I didn't know it was a state secret. +我大一時 有個哲學教授 Well, my freshman philosophy professor +給我們佈置過一份作業 關於人生規劃 assigned this exercise in forward thinking. +叫做"遺願清單" He called it a "bucket list." +我們要把一生中想做的事情列出一個清單 We were supposed to make a list of things we wanted to do +-在我們... +-翹辮子之前 in our lives before we... +- kicked the bucket. +真做作 Cutesy. +我列出來的是"成為百萬富翁" Anyway, I wrote things like "make a million dollars" +"當第一位黑人總統" 都是些年少輕狂的想法 "first black president," you know, young man's wishes. +我想重新列一張 但是... +I was gonna redo the list, but then... +"善意地幫助一位陌生人" "help a complete stranger for the good." +"大笑到流淚" "laugh until I cry." +不是要評論 但這也太弱了點 Not to be judgmental, but this is extremely weak. +現在也沒什麼用了 Well, it's pointless now. +我要從反面跟你理論一下 I would argue the exact opposite. +好吧 就這樣 All right. +that's it. +你在幹嘛 What are you doing? +只是稍微改一下 A little rewrite, that's all. +難道你不想去參加舞會 玩玩槍 I mean, don't you want to go out with some balls? +guns blazing? +找點樂子? +Have a little fun? +這可不是關於什麼槍什麼的 It was not supposed to be about guns blazing or anything like that. +你還沒弄明白 You're missing the point. +"欣賞宏偉的景色"這是什麼鬼東西 What the hell is "witness something majestic"? +你有去過喜馬拉雅山嗎 Have you ever been to the himalayas? +"駕駛福特野馬跑車" 這還不錯 "drive a mustang shelby." not bad. +想到一個 去跳傘怎麼樣 I got one. +all right. +how about skydiving? +現在我們有事做了 Now we're onto something. +我們有事請做了? +We're onto something? +-對啊 +-讓我看看 快點 +- uh +-huh. +- let me see that. +come on. +好 Fine. +"親吻世界上最美的女孩" "kiss the most beautiful girl in the world"? +你打算怎麼做到 How do you propose doing that? +大親特親 Volume. +"刺一個紋身" 這就是你的勇氣? +"get a tattoo." is that the sum of your ambition? +愛德華 我寫的可比你深刻 Edward, I've taken baths deeper than you. +比大一學生深刻是容易的 It's easy to be deep in freshman philosophy. +霍林斯醫生怎麼說的 What's dr. +hollins say? +我們只有幾個月了 對嗎 We got months, right? +也許一年 A year, maybe. +你覺得45年過得很快嗎 You think 45 years went by fast? +我們能去做這些事的 We could do this. +我們應該去完成這些願望 We should do this. +不行 我不能 No, I couldn't. +不要擔心錢 我有的就是錢 Don't think about money. +that's all I got is money. +但我不知道... +But I don't know. +I... +你不知道什麼 What don't you know? +我只是打比方而已 It was meant to be metaphorical. +-我只是想試著去處理... +-全是廢話 +- I'm just trying to get a handle on... +- blah, blah, blah. +打比方 Metaphors. +你光說不做 所以才會遺憾 現在機會來了 You're the one crying you never took a shot. +here's your chance. +什麼機會 把自己變成傻瓜 My chance to what? +make a fool of myself? +永遠不遲 Never too late. +你覺得接下來會怎麼樣 What do you think happens now? +我回去 然後聽別人說一大堆 I go back and sit around listening to people +關於融資理財和次級貸款 talking about mezzanine financing and subordinated debt +假裝關心很關心我那些該死的錢 pretending that I care about dead money. +你回到家去為你的死亡準備一個儀式 You go home to some ceremonial procession into death... +在你想安慰大家的時候 ...with everyone standing around watching you die... +他們卻都圍著看你離去 ...while you try to comfort them. +那就是你想要的嗎 被憐憫和憂傷所充斥著 Is that what you want, to be smothered by pity and grief? +我可不想 Well, not me. +卡特 我相信在你的內心深處你也不想這樣 And in your heart, carter, I believe not you either. +我們現在是同舟共濟 這個比喻怎麼樣 We're both in the same boat. +how's that for a metaphor? +我們現在有個很好的機會 We got a real opportunity here. +機會 Opportunity? +即使是對你來說 這麼講也太離譜 That is real twisted, even by your standards. +我們依然感覺不錯 對嗎 精力又回來了一點 We still feel good, right? +energy's coming back a little bit. +醫生說沒事了 Asymptomatic, the doc says. +照我的看法 我們可以躺在這兒 The way I see it, we can lay around here... +期待在某個爛科學實驗中發生奇跡 ...hoping for a miracle in some bullshit science experiment... +或者我們能更進一步 ...or we can put some moves on. +跳傘 對嗎 Skydiving, huh? +太好了 All right. +這是什麼醫院 居然連個醫學博士都沒有 What kind of hospital is this? +there isn't an m. +d. +within a mile. +弗吉尼亞 我們得談一下 Virginia, we have to talk. +醫院怎麼說的 What did they say? +錢柏太太 你們談 我出去一下 Uh, mrs. +chambers, I'm gonna give you two a little quiet time. +請原諒 Excuse me. +情況不太好 It's not good. +我就知道我們應該去加州大學附屬醫院 I knew we should have gone to ucla. +那兒的外科醫生和手術水平都更好 The surgeons are better. +post +-op is better. +-這沒什麼關係 +-你根本不懂 +- wouldn't have mattered. +- you don't know that. +我們絕不放棄 我有其他辦法 We're not giving up. +I want another opinion. +弗吉尼亞 virginia. +請接腫瘤科的維特裡醫生辦公室 Yes, oncology, please. +dr. +veteri's office. +弗吉尼亞 別打了 Virginia, no. +讓我來處理 Let me handle this. +維特裡醫生嗎 我是弗吉尼亞. +錢柏 Dr. +veteri? +virginia chambers. +是的 沒錯... +Yes, that's right... +我要離開一段時間 I'm going away for a while. +你在說什麼 What are you talking about? +我在說愛德華和我要出發了 I'm talking about edward and I are going away. +愛德華和你 Edward and you? +出發去哪裡 Going away where? +我不期望你能理解 I don't expect you to understand. +你說對了 我不理解 You're damn right I don't understand. +我不理解你怎麼能就這樣放棄 I don't understand how you can just give up like this. +你怎麼能就這樣... +放棄鬥爭 How you can just quit... +quit fighting. +-弗吉尼亞 +-為什麼你不和孩子們那樣去說 +- virginia. +- why don't you tell our children that? +當他們發現是你放棄了他們時 看他們怎麼說 See what they say when they find out you've given up on them. +放棄他們 Given up on them? +放棄他們 Given up on them? +我在引擎蓋下面修了45年的車 I've got 45 years greased up under the hood of a car... +那樣他們就不會來要求什麼了 他們確實沒有 ...so that they didn't want for anything, and they didn't. +我想我該給自己一點時間了 I think I've earned some time for myself. +去做什麼 和一個完全陌生的人離開 To do what? +run off with a total stranger? +他不是一個陌生人 He's not a stranger. +我是你的妻子 I'm your wife. +我是你的丈夫 他們的父親 And I'm your husband. +and I'm their father. +他們的祖父 還是一個該死的修車師 And I'm a grandfather. +and I'm a damn mechanic! +你是個傻子 And you're a fool. +你是個認為他會給你指一條 You're a fool who thinks he's figured out +不會得癌癥的路的傻子 a way how not to have cancer. +對不起 I'm sorry. +我丈夫不是用錢可以換走的 My husband is not for sale. +她恨我 She hates me. +你恨我嗎 Do you hate me? +目前還沒有 Not yet. +因此計劃就開始了 And so it began. +我常常害怕坐飛機 I've always been afraid to go up in an airplane +現在我就要在一個瘋子的幻想中跳下去 now I'm gonna jump out of one at the whim of a maniac! +想撿回來嗎 Wanna get it? +你怎麼能建議我們這樣做 How do you suggest we do that? +等等 Wait. +噢 Ow! +見鬼 Damn it. +閉嘴 Not a word. +回到座位上去吧 凱爾 Back to the seat, kyle. +你要原諒我 凱爾 You'll have to forgive him, kyle. +他在擔心家裡的那個女人 he's worried about the little woman. +這和我妻子沒有關係 This has nothing to do with my wife. +30秒後起跳 Thirty seconds to drop. +結局是這樣的 The sequel was like that. +她從未支持過我做任何事 She never backed me up on anything. +結局 The sequel? +我的第二任妻子 The second mrs. +edward cole. +天啊 那個女人恨死我了 God, that woman hated me. +可能是因為你叫她"結局" Maybe because you called her the sequel. +凱爾 我從來沒那樣想過 kyle, I never looked at it that way. +-15秒 +-不 不 +- fifteen seconds. +no, no. +-等一下 我不能這樣做 +-當然可以 +- wait! +wait, I can't do this. +- sure you can. +不 我真的不能 No. +I can't. +really. +你害怕的不是跳下去 It's not the jump you're afraid of. +當然不是 The hell it's not! +你只是在擔心你的降落傘不能打開 You're just afraid your chute won't open +然後你會像個煎蛋卷一樣 出現你自己的葬禮上 and you'll show up at your own funeral as a denver omelet. +不 我真的非常擔心降落傘不能打開 No, I'm pretty much just worried the chute won't open. +不 不 No, no! +他的嗓子不錯 對嗎 Man's got some lungs, huh? +讓我們用降落傘降落吧 Let's hit the silk! +我們是勇士 Geronimo! +哇塞 太漂亮了 Oh, yeah, beautiful! +啊 啊 Aah! +aah! +快拉 快拉繩索 Pull the thing! +pull the cord! +感覺怎麼樣 這才是生活 How about this, huh? +this is living. +我恨死你了 I hate your rotten guts. +向天空說投降吧 Surrender to the void! +這麼多繩索 哪條是用來拉的 Which one of these damn cords do you pull? +別碰他 我們還沒到降落地點 Don't touch it. +we're not in the drop zone yet. +我們可以借助風勢... +we could wind up in the... +好吧 打開降落傘吧 Okay. +let's deploy. +我有種感覺 我在降落 I got a feeling I'm falling +我們到了紅色區域了 拉繩索 We're in the red zone. +pull the cord. +我有種感覺 我在墜入愛河 I got a feeling I'm falling in love +快拉繩索 Pull the damn cord! +我曾擁有愛 I was in love once. +湯米 我們活著就為了某天死去 Tommy, we live to die another day. +我很走運 How lucky for me. +說真的 湯馬斯 記住那遺囑 它離你很近了 No jokes, thomas, remember the will. +you're so close. +我想問你點事情 Let me ask you something. +你是叫湯米還是湯馬斯 Uh, is it tommy or thomas? +實際上我叫馬修 但他覺得那名字太宗教化了 Um, it's actually matthew, but he finds that too biblical. +我們吃點東西吧 快來 Let's eat something. +come on! +他瘋了嗎 Is he insane? +時不時地 Depends. +你決定了嗎 So you decided? +不 我不想要任何 No, I couldn't think of anything +會困擾我永世的東西 I wanted to be stuck with permanently. +還永世呢 我們就要在五分鐘內死去了 What's permanently? +we're gonna be dead in five minutes. +-什麼 +-比喻說法 +- what? +- figure of speech. +不舉同盟旗 不信黑色耶穌 So no confederate flag, no black jesus. +不 我將要... +No, I'm gonna... +去世 當然會 Pass. +yeah, sure. +我向來不主張褻瀆自己的身體 Well, I never agreed to desecrate my body. +你在擔心他們不會把你葬在猶太人的公墓 You worried they won't bury you in a jewish cemetery? +擔心你妻子嗎 What, the wife? +這只是個紋身 It's a tattoo. +這與你在外搞婚外情是不同的 It's not like you're dumping her for another woman. +我從來沒和其他女人在一起過 I never been with another woman. +哇 Whoa. +那個必須要寫在清單上面 That's gotta be on the list. +不 我不這麼認為 No, no. +I don't think so. +66年 Sixty +-six years? +夥計 我們應該來次放縱 Man, oh, man. +we ought to have a big orgy. +不 No. +放縱並不等於是不忠 Orgy's not even being unfaithful. +不 No. +這只不過看上去更專業 It's just, like, professional. +不 No! +我從來沒去過那種地方 I don't even have to be there. +你好 親愛的 Hello, darling. +你要駕駛她還是給她買身漂亮衣服 you gonna drive it or buy it a dress? +只是讓我們彼此熟悉一下 Just getting to know each other. +你確信我們準備好了嗎 You sure we're cleared for this? +當然已經準備好了 要不然怎麼樣 Of course we're cleared for it. +what if we weren't? +只是檢查一下 Just checking. +快 加油寶貝 看看她到底如何 Come on! +tap it, baby! +let's see what she's got. +我們很棒啊 Ah, we're doing just fine. +你聽上去好像小孩要去參加大三的舞會 You sound like some kid going to the junior prom. +你聽上去好像誰正在等待扭屁股的勝利 You sound like someone looking for an ass +-whupping. +扭屁股勝利 哈 哈 Ass +-whupping? +ho +-ho +-ho +-ho. +-你一無所有 +-哈 哈 +- you got nothing! +- ha, ha. +有你就足夠了 快樂的吉姆 加速 Got enough for you, sunny jim, dangling. +開這麼快想證明你雞雞有多能幹嗎 Did you just make a penis reference? +如果我有呢 What if I did? +上帝 你要讓我們兩個送命嗎 Jesus! +you're gonna kill us both! +如果我要呢 What if I do? +見鬼 Goddamn it! +你給我帶來了麻煩 You're breaking evil on me. +麻煩 我給你表演一下麻煩 Evil? +I'll show you evil. +我來給你表演一下真正的飛車麻煩製造者 I'll show you evel goddamn knievel. +嘗嘗這個 膽小鬼 Pick up on this, chicken man! +耶 哈 Yee +-ha! +膽小鬼 哼 Chicken man, huh? +你能跑 但你不能躲起來 You can run, but you cannot hide! +接下去你想做什麼 What do you wanna do next? +你到底有多少錢 How much money do you have anyway? +沒人告訴過你 Didn't anyone ever tell you +議論別人的財產 是件很不禮貌的事情嗎 that it's rude to talk about someone else's money? +這麼有錢的人 我還是第一次認識 I never knew anyone with enough to ask. +很像病房啊 Medicinal. +這是難以形容的美麗 It's indescribably beautiful. +我喜歡在地球兩極上空飛行 I love flying over the polar cap. +在荒涼的上空 Above the desolation. +星星 The stars +是上帝所創造的美好事物之一 it's really one of god's good ones. +你認為是某種生命體創造了這些 So you think a being of some sort did all this? +你不這麼認為嗎 You don't? +你的意思是我是否相信當我仰望天空 You mean, do I believe if I look up in the sky +允諾這個或那個的時候 and promise this or that +上帝就會讓我們挽回生命嗎 the biggie will make all this go away? +不會 No. +那你的意思地球上95%的人都錯了 Then 95 percent of the people on earth are wrong? +生活告訴我 If life has taught me anything +這95%的人總是犯錯 it's that 95 percent of the people are always wrong. +這就叫信仰 It's called faith. +事實上我羨慕那些有信仰的人 I honestly envy people who have faith. +但我自己卻做不到 I just can't get my head around it. +也許你正在努力 Maybe your head's in the way. +卡特 我們聽夠了無數次類似的討論 Carter, we've all had hundreds of these discussions... +但每個人最終都遇到了同樣的問題 ...and every one of them always hits the same wall. +就是到底有沒有神靈的存在 Is there a sugarplum fairy or not? +沒人能夠回答這個問題 And nobody has ever gotten over that wall. +那你信仰什麼呢 So, what do you believe? +我拒絕所有的信仰 I resist all beliefs. +沒有大爆炸之後宇宙的存在 No big bang? +random universe? +我們活著 We live. +我們死去 We die. +生命的車輪在不停的前進 And the wheels on the bus go round and round. +如果你錯了呢 What if you're wrong? +我很高興自己是錯的 I'd love to be wrong. +如果我錯了 那我就贏了 If I'm wrong, I win. +我不確定這樣有沒有用 I'm not sure it works that way. +你不認為你知道一些我不知道的事 Well, you're not claiming you know something I don't. +恩 Mm +-mm. +我有信仰的 I just have faith. +哈雷路亞 夥計 Hallelujah, brother... +不談這個了 ...and pass the mustard. +-你知道他們是怎麼收穫魚子醬的嗎 +-不知道 +-Know how they harvest caviar? +-hit me. +當雌鱘魚被抓住的時候 When a female sturgeon is caught... +漁夫必須注意觀察 她死得是否很安詳 ...the fisherman has to take great care to see she dies peacefully. +-恩 +-只要她感覺到一點點的恐懼 +- mm +-hm. +- lf she feels the least bit threatened... +...她就會分泌一些酸液來破壞魚卵 ...she secretes a sour chemical that ruins the eggs. +聽上去像我第三任妻子 Sounds like my third wife. +她認為蛋黃醬是種出來的 Woman thought mayonnaise came from a plant. +我對此已經習以為常了 I could get used to this. +聽上去也像我的第三任妻子 Also sounds like my third wife. +這30年裡 我常來這裡 Thirty years I've been coming here. +和一個男人來這裡是第一次 First time with a guy. +我很榮幸 Well, I'm flattered. +艾米莉的十歲生日是最美好的 雖然... +Emily's 10th birthday was the best, though. +誰是艾米莉 Who's emily? +我的小... +My little, uh... +她已經不再是小姑娘了 Well, she's not so little anymore. +你有個女兒 You have a daughter? +-但是你說... +-是的 +- but I thought you said... +- yeah, well... +那時我還不認識你呢 i didn't know you then. +長話短說 Make a long story short, +我們不見面的 i don't see her. +你在幹什麼 What are you doing? +現在是時候了 It's time. +-不 不 把它劃掉吧 +-為什麼不去 +- no, no, no. +cross that off. +- why not? +-劃掉它 +-為什麼 +- cross it off. +- why? +為什麼 Why? +沒有什麼為什麼 There is no why. +-你怎麼了 +-請原諒 +- what's the matter? +- excuse me. +你去哪裡 Where you going? +真像個女人 Just like a broad. +喂 卡特 Look, uh, carter... +對不起 我知道 I'm sorry. +I know +有時我有一點傲慢和... +sometimes I get a little overbearing and l... +上帝啊 Jesus christ. +-沒事的 沒關繫了 +-什麼 什麼 +- it's all right. +it's okay. +- what? +what? +上面的導管流出來的 沒什麼 The top on the catheter came loose, that's all. +也許該送你去醫院 卡特 Well, maybe we should get you to a hospital, carter... +-我剛從醫院裡出來 +-嗯? +- I just busted out of the hospital. +- huh? +沒事了 看 已經不流了 我們出去吧 It's all right. +look, it's already stopped, see? +let's get out of here. +看上去很好 嗯... +It looks wonderful. +uh... +uh... +-也許我要去拿... +-我們直接走吧 +- maybe I'll get the... +- let's just go. +-你直接上車去 +-走吧 走吧 +- you go straight to the car. +- come on. +come on. +好吧 Okay, all right. +-湯米在哪? +在哪? +-在客廳 先生 +- where's... +? +where's tommy? +in the salon, monsieur. +噢 天哪 Oh, my. +你到底有多少錢呢 How much money do you have? +我可不會流血到地毯上 Well, I wouldn't bleed on the rugs. +我要找個地方好好洗個熱水澡 I'm gonna find someplace where I can take a nice hot bath. +洗得乾乾淨淨的 Be as good as new afterwards. +是的... +你... +好吧 Yeah... +you... +okay. +好吧 我們都準備好了 好的 okay, we're all set, okay +好了 雖然花了點功夫 但是我都重新安排好了 All right, it took some doing, but, uh, I rearranged everything. +明天去開羅 在坦桑尼亞呆兩天 Cairo tomorrow, tanzania for two days, +然後週六去約翰內斯堡 then johannesburg on saturday. +而且事先聲明 不准鬥牛 不准獵虎 And, as previously directed, no bullfight, no tiger hunt. +湯馬斯 我真的很想說你是不可替代的 Thomas, I'd really like to say you're irreplaceable +但是那是在說謊 but I'd be lying. +我也很想說你真的是個不錯的人 我熱愛我的工作 And I'd really like to say you're a gracious man, and I love my job +但是我 也是在說謊 but i, too, would be lying. +反擊得很合理 Turnabout is fair play. +肯定是跟我學的吧 I believe you learned that from the master. +嘿 過來看 他們遇到危險了 在浴室 Hey, look! +they got jeopardy! +in the bathroom! +電視上的 冒險者 On the tv. +jeopardy! +冒險者 在法國 Jeopardy! +? +in french? +喂 Hello? +是寇爾先生嗎? +我是弗吉尼亞. +錢柏 Mr. +cole? +virginia chambers. +噢 我知道了 嗯 你好 Oh. +yeah. +um, hi. +我幫你叫卡特接電話 Let me get carter for you. +實際上 我是打給你的 Well, actually, I called to speak to you. +噢 Oh. +他還好嗎 Is he all right? +噢 是的 他... +他很好 Oh, yeah. +he's... +he's fine. +我能問下你們在哪嗎 May I ask where you are? +法國 實際上 嗯 明天... +France, actually. +uh, tomorrow... +把他還給我 Give him back to me. +弗吉尼亞 我可以叫你弗吉尼亞嗎? +Virginia. +may I call you virginia? +我不確定我是否可以讓他 I'm not sure that I can make... +別拿他當借口 I'm not asking for his sake. +寇爾先生 Mr. +cole +我這一生的職業就是護士 I've been a nurse my entire adult life. +我親眼目睹了很多人的悲劇 Had a ringside seat to more human tragedy... +我比任何女人承受過的都要多 ...than any woman should ever have to bear. +現在 我早有了丈夫將亡的心理準備 Now, I'm prepared for my husband to die. +我只是沒準備 在他還活著的時候就失去他 I'm just not prepared to lose him while he's still alive. +-霍迪. +杜迪是誰? +-答對了 +- who is howdy doody? +-you got it. +-你來選 +-電視木偶類 400元 +- you pick. +- "tv puppets," for 400. +這兩個提線木偶 These two muppets... +是室友 他們長期在芝麻街節目中表演 ...are roommates on the long +-running show sesame street. +伯特和爾尼是誰 who are bert and ernie? +斯必羅. +阿格紐是誰 Who is spiro agnew? +斯必羅. +阿格紐是誰 Who is spiro agnew? +看來 Well... +你看起來 嗯 ...you're looking, uh... +很愉快 ...buoyant. +這是我第一次躺在一個沒有角的浴缸裡 This is the first time I was ever in a tub with no corners. +是嗎 Really? +嗯 卡特 其實我一直在想 You know, ahem, carter, uh, I've been thinking +剛才導管的事 還有其他的事 what with the catheter and everything +也許我們應該把旅行暫停一陣子 maybe we should put this on hold for a while. +拜託 我不是跟你說了嗎 別擔心 我現在很好 Come on, now, I told you, stop worrying. +I'm fine. +不 不 不是指那個 不是指那個 No, no, it's not that. +it's not that. +只是 我的意思是 或許我會讓你失望 It's just, I mean, if you're worried about letting me down +你知道 畢竟我更可能會死 you know, it's a lot easier for me. +你和弗吉尼亞談過了 是嗎 You talked to virginia, didn't you? +你認為我這麼做是為什麼 Why do you think I'm doing this? +因為我讓你這麼做的 Because I talked you into it. +愛德華 你是很厲害 但是沒有那麼厲害 Edward, you're strong, but you're not that strong. +知道嗎 Know. +自從瑞秋上大學後 我的生活就出現了個缺口 After rachel left for college, there was a hole. +我的意思是 你知道 不再有家庭作業 不再有社團 I mean, you know, no more homework, no more little league... +背誦 學校比賽 ...recitals, school plays... +孩子的哭聲 打鬧 摔傷膝蓋 ...kids crying, fights, skinned knees. +40年來我第一次看著弗吉尼亞 And for the first time in 40 years, I looked at virginia +周圍沒有絲毫吵鬧聲 沒有任何干擾 without all of the noise, without all of the distractions +我甚至記不起來那種感覺 and I couldn't remember what it felt like +那種不牽著她的手逛街的感覺 when I could not walk down the street without holding her hand. +我的意思是 她還是那個我深愛的女人 I mean, she was the same woman I fell in love with, +她沒有變 she hadn't changed. +但是不知怎麼了 一切都變了 But somehow everything was different. +一路走來 我們似乎失去了什麼 We'd lost something along the way. +你明白嗎 You know? +查理. +麥卡錫是誰 Who is charlie mccarthy? +獅子在今夜沉睡 "the lion sleeps tonight" +看 看 看 Look, look, look! +啊哈 Aah! +我很高興當愛德華決定 I was very pleased when edward decided +把單子上的第9條劃去 to eliminate item number nine +"獵虎" "hunt the big cat." +當然 他依然堅持要放幾槍 Of course,he insisted on discharging rounds from the big gun +其實一槍就夠了 One proved to be enough. +你知道嗎 Do you know +唯一一條被閃電擊中的狗 that the only dog ever struck by lightning +就是在這 在埃及 was right here, in egypt? +我真希望我能在被叛死刑前認識你 I wish I'd met you before we were dead. +這樣看來 You know, technically +我們可以劃去兩條了 we could cross off two items: +親眼目睹金字塔 "see the pyramids" +還有欣賞宏偉的景象 and "witness something majestic." +這裡已經很宏偉了 This is about as majestic as it gets. +還是等看到我的山再下結論吧 Wait till you see my mountain. +噢 好吧 Oh, yeah. +你的山 Your mountain. +不過 這裡確實不錯 Still, this ain't half bad. +古埃及人對於死亡有個美好的信仰 the ancient egyptians had a beautiful belief about death. +當他們的靈魂到達天堂的入口時 When their souls got to the entrance to heaven +上帝會問他們兩個問題 the gods asked them two questions. +他們的回答將決定他們能否進入天堂 Their answers determined whether they were admitted or not. +好吧 我想知道 Okay, I'll bite. +問了什麼問題 What were they? +你找到生命中的快樂了麼 Have you found joy in your life? +這個 Uh +-huh. +回答問題 Answer the question. +-我? +-是的 你 +- me? +- yeah, you. +回答問題 你找到生命中的快樂了麼 Answer the question, "have I found joy in my life?" +找到了 Yes. +你的生活給別人帶去快樂了麼 Has your life brought joy to others? +恩 這種問題 我 Ah, this type of question, l... +我不知道 嗯 I don't know, uh... +我不知道別人是怎麼想的 嗯 I don't think about how other people gauge, uh... +你問他們吧 Ask them. +我在問你 I'm asking you. +好吧 Fine. +好吧 Fine. +這麼跟你說吧 Let me put it to you this way. +離婚後 接著我就不再是爸爸了 After the breakup, and the ensuing fleecing of the dad +艾米麗和她母親一起生活 emily went to live with her mother. +你知道 雖想保持親近 但只能假期聚聚 You know, you try to stay close, but it gets down to holidays +偶爾打個電話 寄張生日卡什麼的 phone calls, birthday cards, you know. +總之... +Anyway... +艾米麗上大學了 加入了個拯救窮人 emily goes to college, joins one of her "save the poor people" +動物之類的 the animals, whatnot +遇見了個男人 而且愛上了他 meets a guy, decides she loves him. +那小子長得不錯 有野心 聰明 Good +-looking kid, driven, smart. +但是他有些問題 But there was something about him +所以她告訴我 他們要訂婚的時 我反對了 so when she said they were engaged I told her I was against it +但是不愧是我的女兒 於是 but being my daughter, naturally +她還是和他結婚了 she went ahead and married him anyway. +不用說 她沒有邀請我參加他們的婚禮 Needless to say, I wasn't invited to the wedding. +你肯定很傷心 That must have hurt. +你這麼認為 You think? +他第一次打她 她來找我 First time he hit her, she came to me. +我想打爆他的頭 I wanted to bash his brains in. +她阻止了我 She wouldn't let me. +說她愛他 這不是他的錯 他只是喝了點酒 Said she loved him, said it wasn't his fault, he'd had a few drinks +是她先惹他的 she was the one picked the fight. +他第二次打她時 她沒有來找我 Next time it happened, she didn't come to me. +前妻告訴我的 很高興又聽到她的消息 The ex told me. +nice to hear her voice again. +你做了什麼 What did you do? +盡為父所能 What any father would do. +我把他擺平了 I took care of it. +我找了個傢伙 他找了個專門處理這類事的人 I called a guy who called a guy who handles these kinds of things. +我不知道他說了什麼 做了什麼 I don't know what he said, don't know what he did +我只知道他沒有殺他 all I know is he didn't kill him +我女兒從此再沒有他的消息了 and my daughter never heard from him again. +她怎麼反應的 How did she react? +你無法相信他直呼我的名字 更糟的是 Called me names you wouldn't believe, and worse +她說對她而言我已經死了 Said I was dead to her. +我不為我所做的事情感到驕傲 I'm not proud of everything I did +但是我很肯定 要是能重來 我仍會那麼做 but I'm pretty sure I'd do it all again +如果他們因為我女兒恨我 so if they don't let me into egyptian heaven +而不讓我進入埃及的天堂 because my daughter hates me +我猜他們確實會這麼做 well, then I guess that's just the way it goes. +不管怎麼說 算是回答了你的兩個問題 However you answer your two questions. +我們怎麼從墳墓下去呢 How do we get down from this tomb? +皇后是莫臥兒帝國第5位國王 沙. +賈漢的妻子 The empress was the wife of shah jahan, the fifth mogul emperor. +雖然是包辦婚姻 但是他們深深愛著對方 Although it was an arranged marriage, they were deeply in love +在他們第14個孩子出生時她死了 and remained inseparable until she died +而他們的感情至死不渝 giving birth to their 14th child. +介意我叫你雷嗎 Do you mind if I call you ray? +大多數人叫雷 Main man ray. +你有在聽我講話嗎 Are you listening to anything I'm saying? +當然 Absolutely. +14個孩子 我聽著呢 Fourteen kids. +I'm with you. +這個建築耗費了20,000個工人22年的時間來建造 It took 20,000 volunteers 22 years to complete this structure. +這裡的一切都是賈漢親自設計的 Every square foot designed by the shah himself. +所以那是真愛 So that's true love. +那是真愛 That's true love. +肯定很幸福 Must be nice. +也許我會把這整個買下來 Don't know if I buy the whole "20,000 volunteers" business. +安排葬禮讓我很苦惱 Funeral plans tend to confuse me. +確切的說 是土葬好還是火葬好 Specifically, buried or cremated. +土葬吧 Take buried. +雖然我知道這無關緊要 但是我有幽閉恐懼癥 Now, I know it shouldn't matter, but I'm claustrophobic. +如果哪天我在地下突然醒了 沒有人聽到怎麼辦 What if I wake up underground and nobody can hear me? +他們還會生產那種內置鈴鐺的棺材嗎 Do they still make those coffins with the bells? +嗯... +我估計沒有了 Uh... +I don't believe they do. +那火葬吧 你打算怎麼處理那些骨灰呢? +Then cremated. +what do you do with the ashes? +把他們埋了還是撒了? +把他們放到架子上? +Do you bury them, scatter them, put them on a shelf? +扔進恆河順流而下找個安樂窩? +Float them down the ganges on a bed of flowers? +如果我感覺到火焰怎麼辦 What if I feel the flames? +但是我確定我會火葬 Well, I definitely want to have myself cremated. +也許我們應該像華特. +迪斯尼一樣把自己冷凍起來 Maybe we should go frozen like walt disney. +不好 還是火葬吧 No. +cremated. +把骨灰放到鐵罐裡 埋到風景秀麗的地方 Ashes put in a can, buried some place with a view. +鐵罐 嗯? +A can, huh? +是的 我不喜歡骨灰盒的說法 Yeah. +I never liked the sound of the word urn. +是嗎 難道你對地穴有特殊的感覺? +Really? +got any special feelings about crypt? +- +- +- +- +-====翻譯===== +- +- +- +-- 蕁香 卓為水蒙 蜀山天狼 Yancey 呂黎 校對: +小門柴 +嘿 沒有 Heh. +no. +沒有 對我來說一個舊的"巧克福納"牌咖啡罐就足矣 No, an old chock full o'nuts can will do me just fine. +"巧克福納" 天堂咖啡 Chock full o'nuts, "the heavenly coffee." +朋友 好的咖啡甚至是花錢都買不到的 Better coffee even your money can't buy, my friend. +別拿這打賭 Don't bet on it. +噢 好吧 Oh, right. +魯哇克香貓 Kopi luwak. +你為什麼不喜歡魯哇克香貓咖啡? +What do you got against kopi luwak? +跟我的品味太不搭了 Too fancy for my tastes. +噢 是的 對我的好搭檔"雷"來說 是很不搭 Oh, yeah. +too fancy for my main man, ray. +-陷阱 +-該死 +- Gin. +- goddamn it. +牌都被你拿光了 You get all the cards. +寶貝 這就是中國 This is china for you, baby. +太棒了 Whoo +-hoo! +yeah! +如果我們可以登上去看的話 肯定很壯觀 Be a lot more majestic if we could see it. +看到那個老女人了嗎 See that old woman? +真奇怪我們竟然會比她先死 Odds are we're gonna be dead before her. +想開點 Happy thought. +當然 如果有來生的話 Of course, she's probably got reincarnation going for her... +她很可能會去轉世 ...however that system works. +啊 佛教徒相信他們會不斷地轉世 Ah, the buddhists believe you keep coming back. +此生的所為 會決定他們上天還是入地 Moving up or down a level, based on how you lived your life. +瞧 這正是我所不明白的 See, that's where they lose me. +我的意思是 一隻蝸牛要怎樣做才能上升一個境界呢 I mean, what would a snail have to do to move up in the lineup? +用粘液畫出完美的軌跡 Lay down a perfect trail of slime? +要聽壞消息還是更壞的消息 So shitty news, or really shitty news? +A 第一個 A, the first one. +暴風雪要來了 There's a storm up there. +那謝謝你的提醒 湯姆 Well, thanks for the bulletin, tom, +我們現在沒看到那該死的 we can't even see the goddamn thing. +他們不會讓我們上山的 除非天氣變好了 They won't let us fly up until the weather clears. +那天氣什麼時候會變好? +when do they expect it to clear? +嗯 明年春天 差不多吧 Uh, next spring, sometime. +如果你們想知道的話 這就是個那個更壞的消息 That's the really shitty news, in case you were wondering. +好吧 那下次吧 Well, maybe next time. +只能這樣了 Yeah. +明年春天 Next spring. +我們現在幹什麼呢 So now what? +也許你的山在告訴我們某些事情 Well, maybe your mountain's trying to tell us something. +什麼意思 What do you mean? +也許我們離開的夠久了 Maybe we've been gone long enough. +離開的夠久了? +離開誰夠久了 Gone long enough? +gone long enough for whom? +噢 不 我明白了 Oh. +no, I get it. +山不是告訴我們該回去了 The mountain isn't telling us it's time for us to go home. +山是讓你告訴我 The mountain is telling you to tell me +我該回去了 是嗎 it's time for me to go home, right? +-是的 +-一派胡言 +- yeah. +- you shit. +你為什麼不管管你自己 Why don't you worry about your life, +我們各擔心各的 懂嗎 and let me worry about mine, okay? +好的 好的 你沒必要跟我發火 Okay, okay! +you don't have to get chippy with me. +-下一站是哪裡 +-下一站 香港 +-What's next? +-next, hong kong. +一套絲綢衣服 還有黑核桃仁冰淇凌 Silk suits and black walnut ice cream. +西藏人管他叫"修馬魯瑪" 雪的女神 Tibetans call it chomulungma, "goddess mother of the snows." +實際上是 宇宙的女神 "goddess mother of the world," actually. +根據傳統西藏語翻譯 In the traditional tibetan translation. +我認錯了 I stand corrected. +一杯加州葡萄酒 謝謝 Pinot noir, please. +我想你肯定去過那了吧 I take it you've been there? +呃... +呃... +嗯... +實際上我剛從那過來 Uh... +uh... +um... +I just left, actually. +我們打算要爬上去的 但是沒有 We tried to go up, but it wasn't... +你已經錯過了登山的季節 You're a little late in the season. +他們也是這樣告訴我的 So they tell me. +-我叫安婕列卡 +-噢 我叫卡特 +- my name's angelica. +- yeah, carter. +很抱歉 很唐突地問一下 I'm sorry if this sounds terrible... +爬那麼高的山 你的年紀是不是有點過呢? +but aren't you a little developed in years to be running up a giant mountain? +過 你是說我的年紀大了吧 "developed," now that's certainly one way of putting it. +其實我去上去過 Well, I've been up there, you know. +-是嗎 +-是的 +- really? +- mm +-hm. +在我們必須返回之前 我爬到了26000英尺高 I made it to 26,000 feet before we had to turn back. +-真的? +-當然 +- really? +- mm +-hm. +感覺怎麼樣? +What was it like? +好冷 大部分時候 Cold mostly +白天 天空黑壓壓的 During the day, the sky is more black than blue. +因為空氣太稀薄 不能反射陽光 There's not enough air to reflect the sunlight. +但是在夜裡 你從來都沒有看到過那麼多星星 But at night, you've never seen so many stars. +看上去觸手可及 耀眼奪目 Seems like they're just out of reach, and so bright. +就好像是天堂地板上的一個個小洞 They're like little holes in the floor of heaven. +-你聽到了嗎 +-聽到什麼 +- did you hear it? +- hear what? +我讀過一個人在山頂寫的描述 I read an account of a man who made it to the summit +當你站在世界世界之巔 and standing there at the top of the world +他經歷過這種異常的寧靜 he experienced this profound silence. +就像所有的聲音都靜默了一樣 It was like all sound just fell away. +這就是他聽到的 And that's when he heard it. +什麼? +What? +大山之音 The sound of the mountain. +他說他好像聽到了上帝的聲音 He said it was like he heard the voice of god. +我以前從沒這麼做過 I've never done this before. +這聽起來真是迂腐透頂 That sounds like such a cliche +不過我樓上有個房間 but I have a room upstairs. +那真是... +Well, that's... +我是說... +I mean... +我... +I... +我很榮幸 I appreciate that. +但你看... +But you see... +她真是個幸運的女人 She's a very lucky woman. +我寧願我比較幸運 Well, I rather think I'm the lucky one. +做得好 Good for you. +湯姆? +Tom? +等你老了以後 記住三件事 Three things to remember when you get older +得有一間浴室 Never pass up a bathroom +不要浪費每次勃起 別相信那些屁話 never waste a hard +-on, and never trust a fart. +等我老了以後我會記得的 I'll keep that in mind as I approach decrepitude. +嘿嘿 這就對了 Heh +-heh. +that's a good one there. +我們回家吧 Let's go home. +你說什麼 Excuse me? +我想現在回家 I want to go home now. +但我覺得... +那真絲西裝怎麼辦? +But I thought that... +what about the silk suits? +你很聰明 愛德華 That was very clever of you, edward. +你怎麼知道我不會進行到底? +How'd you know I wouldn't go through with it? +我不知道啊 I didn't. +我為你感到驕傲 I'm proud of you. +沒有人在乎你是怎麼想的 Nobody cares what you think. +美國 America. +嗨 湯姆 這不是去克蘭肖的路 Hey, tommy, this isn't the way to crenshaw. +10號公路發生了車禍 我們得繞道行駛 There's an accident on the 10. +we're taking the surface streets. +哦 Uh +-huh. +為什麼我們? +Why are we, uh? +哦 我的天哪 Oh, my god. +他一直在監視著她 就怕你萬一決定... +He's kept tabs on her. +just in case you decided to... +是你出的主意 湯姆? +This was your idea, tom? +不 是我的主意 是我跟他說的 No, it was my idea. +I talked him into it. +-是啊 是你跟他說的 +-喂 +- yeah, talked him into it. +- hey. +等等 愛德華 愛德華? +等等 Wait a minute. +edward. +edward? +wait a minute. +愛德華 你在怕什麼 Edward. +what are you so afraid of? +我告訴過你 我的事不用你瞎摻和 Just because I told you my story does't invite you to be a part of it. +哦 就像酒吧裡的那個女人? +Oh. +like the lady in the bar? +-那不一樣 +-告訴我怎麼不一樣了 +- that's different. +- tell me how. +-就是不一樣! +-怎麼不一樣了? +- because it is! +- how is it different? +你他媽的根本不知道我是誰! +You have no fucking idea who I am! +我從一無所有到家產萬貫! +I built a billion +-dollar business up from nothing! +連總統都有向我徵求過意見 Presidents have asked my advice. +我和皇室一起用餐 我甚至會被寫進書裡 I have dined with royalty and I'm supposed to make out like +但別以為這次旅行會對我有多大影響 this trip was supposed to mean something to me? +改變我? +Like it was gonna change me? +你到底是怎麼想的 卡特? +How did you see it playing out, carter? +我去敲門 她出來開門 I knock on the door, she answers. +她感到驚訝 然後轉而憤怒 She's surprised and angry +但我卻告訴她 我有多愛她多想她 but I tell her how much I love her and miss her. +然後說 "哦 順便告訴你 我快要死了 And, "oh. +by the way, I'm gonna be dead soon. +所以我來找你 因為我不想孤獨終老"? +so I'm reaching out to you because I don't wanna die alone"? +每個人都害怕孤獨終老 Everyone is afraid to die alone. +我不是每個人 I'm not everyone! +這本來應該很開心的 This was supposed to be fun. +現在再也不會了 That's all it ever was. +不 你別上車 打車去 No, you don't get in. +call a cab. +親愛的上帝 我們由衷地感謝你今天 Dear heavenly father, we just want to thank you for this day +讓我們一次又一次團聚 for having our family here together, once again. +主啊 感謝你帶回了我的丈夫 And, lord, we just want to thank you for returning my husband +他們的父親 主啊 their father, lord, to us. +他是在哭嗎 is he crying? +不知道啊 I don't know. +他一直都很開心的啊 He's usually so much fun. +-等一下 +-幹嘛? +- wait a minute. +- what? +-我準備了好東西 +-哦? +- I got something for us. +- oh? +我不確定是否有必要 I wasn't sure I'd need it. +當然有必要啦 Sure. +噢! +Ow! +heh. +好的 Okay. +你知道有多久了嗎 You know how long it's been? +你覺得我想知道嗎 Do I wanna know? +已經很久很久啦 Well, it's been longer than that. +知道嗎 我感覺自己像年輕人 像我們的第一次 You know, I feel like a teenager. +like our first time. +如果我們還是年輕人 if we were teenagers, +我們才不會在臥室呢 we never would've gotten out of that living room. +我還記得第一次呢 I remember the first time. +不會踮起腳走路哦 There was no tiptoeing around. +你對我就像... +這樣 You were on me like... +that. +卡特? +Carter? +哦 你在和我玩捉迷藏對吧 好的 Oh, you playing hide +-and +-seek now, huh? +okay. +卡特! +Carter! +在把康復中心賣給飛利浦醫藥醫藥後 which resulted in a 15 percent increase in cash assets +現金資產增加了15% following the sale of the recovery center to phillips medical. +寇爾先生? +Mr. +cole? +寇爾先生? +Mr. +cole? +你讀過神曲嗎? +You ever read the divine comedy? +抱歉 先生? +Excuse me, sir? +神曲 但丁. +亞利基利的地獄之行 The divine comedy, dante alighieri's journey into hell. +也許我們該休息一下 Maybe we should take a break. +我們不需要休息 We don't need a break. +我在請求寬恕 我是他媽的醫學奇跡 I'm in remission. +I'm a goddamn medical miracle. +我只是問你們 I'm simply asking +有沒有讀過神曲 if you ever read the divine comedy. +先生 你有電話 Sir, you have a phone call. +湯米 現在不是時候 Tommy, not now. +我覺得你應該聽一下 I really think you should take this. +愛德華 Hey, edward. +他怎樣? +What's the prognosis? +已經轉移到他的腦部了 It's metastasized to his brain. +轉移了... +能動手術嗎? +Metast... +operable? +成功率不高 不能動手術 The odds aren't what we'd like them to be. +成功率 Odds. +上帝啊 Jesus. +他現在怎麼樣? +How's he doing? +沒事了 He's doing okay. +他要我把這個給你 he wanted me to give you this. +我本來想等到 I was supposed to wait until after +但是後來我想 but then I thought +她從來就不聽我話 She never listened to me before. +為什麼改變遊戲規則啊? +Why change a winning formula? +你看起來像坨屎 雷 You look like shit, ray. +不甚感激 Thanks. +他們怎麼款待你的? +How they treating you? +還是噁心的濃豌豆湯 Pea soup still sucks. +我會和負責人談談的 I'll have a word with the owner. +去吧 You do that. +能給我喝點水嗎 Can I have some water? +你不能喝水 You can't have water, +但我給你弄點檸檬棉簽 擦擦嘴好嗎 but I'll get you some of those lemon swabs, okay? +好的 All right. +你還在喝那種咖啡? +You still drinking that fancy coffee? +幹嘛? +What? +怎麼了你 很奇怪嗎? +What are you, obsessed? +唸唸 Read it. +"魯哇克香貓咖啡 是當今世界最昂貴的咖啡 "kopi luwak is the world's most expensive coffee. +儘管如此 它仍被歸類為"好到難以致信"的行列 Though for some, it falls under the category of too good to be true +在這種咖啡豆的故鄉蘇門答臘 In the sumatran village where the beans are grown +生長著一種野的樹貓 lives a breed of wild tree cat. +這些貓將咖啡豆吃下 經過它們的消化和 These cats eat the beans, digest them and then +排泄 defecate. +隨後 村民們會收集加工這些糞便 The villagers then collect and process the stools. +正是咖啡豆與樹貓胃液的混合物 It is the combination of the beans and the gastric juices of the tree cat +給予了魯哇克香貓獨一無二的口味... +that give kopi luwak its unique flavor... +與芬芳" and aroma." +你這是噁心我 You're shitting me. +還是貓提點了我 Cats beat me to it. +-有筆嗎 給我支筆 +-什麼 +- you got a pen? +give me a pen. +- what? +什麼 What? +給你 Here. +還沒完呢 It's not finished. +這可不是一人計劃 It's not a one +-man deal. +恐怕是的了 I'm afraid it'll have to be. +我們準備就緒了 We're ready. +我會在這裡等你出來的 I'll be here when you get back. +聽起來真棒 Sounds good to me. +親愛的愛德華 在最後的日子裡 我一直在猶豫 Dear edward, I've gone back and forth the last few days +是不是該給你寫這封信 trying to decide whether or not I should even write this. +最後 我意識到如果我沒有寫的話 我將抱憾終身 In the end, I realized I would regret it if I didn't +所以我就寫了 so here goes. +我知道我們最後一次在一起時 I know the last time we saw each other +沒有完成那份清單 we weren't exactly hitting the sweetest notes. +這真的不是我希望旅行結束的方式 It certainly wasn't the way I wanted the trip to end. +我覺得責任在我 所以很抱歉 I suppose I'm responsible, and for that I'm sorry. +但是說實話 如果有機會重來 我還是會那麼做 But, in all honesty, if I had the chance, I'd do it again. +弗吉尼亞說我撇開了一個陌生人 回來繼續做她的老公 Virginia said I left a stranger and came back a husband. +這都歸功於你 I owe that to you. +對於你為我做的一切 我沒什麼好報答的 There's no way I can repay you for all you've done for me +所以我試著 so rather than try, +想讓你再為我做一件事 i'm just going to ask you to do something else for me. +找到你生命中的真諦 Find the joy in your life. +你曾經說過 你不代表所有人 You once said you're not everyone. +是啊 Well, that's true. +你當然不是所有人 You're certainly not everyone. +但是每個人 就是所有人 But everyone is everyone. +我父母常說 "我們的生活就像溪水... +My parents always says, "our lives are streams... +殊途同歸 flowing into the same river +朝著遠秋霧靄中天堂的方向 行進吧" towards whatever heaven lies in the mist beyond the falls." +嗨 親愛的 Hello, sweetie. +hi. +找到你生命中的真諦 愛德華 Find the joy in your life, edward. +我親愛的摯友 My dear friend +閉上雙眼 讓流水帶你歸去吧 close your eyes and let the waters take you home. +下午好 我是愛德華. +寇爾 Good afternoon. +my name is edward cole. +我不知道大部分人在這種場合會說什麼 因為... +I don't know what most people say at these occasions, because... +說實話 我... +in all honesty, i... +我一直都很逃避 I've tried to avoid them. +簡單地說... +The simplest thing is... +我愛他 我想他 i loved him and I miss him. +卡特和我一起遊遍了整個世界 Carter and I saw the world together. +那真是太美妙了 Which is amazing. +尤其是 在三個月前 when you think that only three months ago +我們還完全是陌生的兩個人 we were complete strangers. +我希望... +I hope... +這聽來不會讓你們覺得我很自私 that it doesn't sound selfish of me... +但是他生命中的最後幾個月 but the last months of his life +是我生命裡最快樂的日子 were the best months of mine. +他拯救了我的生活 He saved my life. +而且在我做之前 他就已經知道 And he knew it before I did. +我真為這個男人感到驕傲... +I'm deeply proud that this man... +他覺得他值得來解讀我 found it worth his while to know me. +最後... +In the end... +我可以很肯定地說 i think it's safe to say that +我們給別人的生活帶去了快樂 we brought some joy to one another's lives. +所有 某一天 So, one day, when... +當我最後的安息時 i go to some final resting place +如果我碰巧醒轉 看到一扇生命之門時 if I happen to wake up next to a certain wall with a gate +我希望卡特就在那兒 i hope that Carter's there +等著我 to vouch for me +給我看繩索的另一端 and show me the ropes on the other side. +愛德華. +佩瑞曼. +寇爾在5月去世 Edward perriman cole died in may. +那是星期天的下午 It was a sunday, in the afternoon +天空萬里無雲 and there wasn't a cloud in the sky. +他享年81歲 He was 81 years old. +即便是現在 我還是無法明白生命的度量 Even now, I can't claim to understand the measure of a life. +但我可以這樣告訴你 but I can tell you this +我知道當他離去之時 他的雙眼是閉著的 I know that when he died, his eyes were closed +而他的心靈卻是敞開的 and his heart was open. +而且我很確定 他對安息地非常滿意 And I'm pretty sure he was happy with his final resting place +因為他被埋在了山頂 because he was buried on the mountain +而那卻是違法的 and that was against the law. +好吧,我拆不开 +好啦,准备好了吗? +祝你圣诞快乐 +我就是想要这种脚踏车耶 +对,喜欢吗? +是那种吗? +那就好,圣诞快乐 +新曲棍球杆 +尺寸对吗? +对,很适合我 +挥杆给我看 +别打到桌上的东西 +非法制裁 +我最厉害 非法制裁 +我最厉害 非法制裁 +非法制裁 +放马过来吧 +等一下 +准备好了吗? +好了,用力挥 +你还好吧? +你还好吧? +好了,你自己骑 +天哪! +路克! +宝贝! +小心那棵树啊 +耍花招 +耍花招 +你多以他为傲? +天哪,他好了不起 +那是妈妈画的吗? +说实话,是妈妈画的吗? +你看 +我只有一个疑问... +这是什么? +是抽象画啦 +我和球队签约就买新房子送你 +这栋房子有什么不好? +准备好了吗? +可恶! +好了,许愿吧 +妈,你几岁? +我几岁? +只是好奇嘛 +你很漂亮 +看起来不过才... +爸,快说啦 +很好 +布兰登休姆,你当选MVP了 +第一名... +点蜡烛吧 +叫醒以后能不能巴他? +不行 +拜托嘛 +他会杀了我们 +惊喜! +惊喜! +生日快乐,路克 +生日快乐,路克 +生日快乐 +14岁了 +感觉和昨天13岁没差啊 +你要现在被揍14下? +还是... +待会儿啦,等我清醒再说 +走开! +我差点就赢你了 +应该遗忘旧识 +永远不再想起吗? +应该遗忘旧识 +和两小无猜的往日时光吗? +打扰一下 +才提到曹操,曹操就来了 +好吧 +有何贵干? +安妮要我请你签核 +这个人在海星做了6年 +但他老婆死了,没小孩,没遗嘱 +我想把他的退休金纳入抚恤金 +让他好过点 +拜托,我不想搞得太复杂 +要照规定做 +等他死了大家才知道我们有尽责 +你说得对,省麻烦 +我懂了,抱歉 +不是,我们要尽责 +好好安顿我们的员工 +别让他死不瞑目 +你讲的〝宇宙的秩序〞是什么? +保户花了30万美元 +依据这份新图表、新调查资料 +新社会 +谁才是好员工? +谁怎么死的? +几时死的? +我们拿到资料知道他们表现多好 +你知道调查结果如何吗? +有小孩的人比没小孩的人更长寿 +有两个小孩比一个小孩的更长寿 +抽烟不好 +超速不好 +家里有丧事不好,离婚不好 +只不过很高兴能证明 +这些陈腔滥调还是事实 +你知道吗? +你家的小孩就很棒啊 +布兰登,你很狗腿耶! +我是天赋异禀,没办法嘛 +天哪,妈,我好想死啊 +我知道 +我可以先失陪吗? +不行 +我有个白痴老哥 +我有个孬种老弟 +好了,别吵啦 +你早该知道会这样 +怎样? +一家人要相亲相爱 +我能说不吗? +不行 +我要求豁免权,我要找律师 +好,我要提出告诉 +我回来了 +现在就要 +抱歉晚回来了,错过晚餐了吗? +没有,菜还很多,我去热给你吃 +爸,礼拜六载我去市区 +市区? +对,这是交换比赛 +我又要先发了 +真的吗? +太好了 +对啊 +华教练一定爱死你了 +对,因为他很狗腿 +狗腿有好处啊,大家都要去吗? +不行,路克要踢足球 +对,但我不是先发,你们可以... +也许你狗腿一点就不会这么逊了 +爸,他开玩笑啦,只是耍白痴 +不准骂他白痴 +路克,你有个忠诚又疼你的哥哥 +说得对 +忠诚又疼我的狗腿 +大家能不能文明一点? +不然我要杀人了哦 +我无所谓啦,卑鄙小人 +最好是啦,卑鄙小人 +路克... +盘子 +兔崽子,给我过来 +放手! +知道不回家会错过什么了吧? +对,至少他们没互扔食物 +打得好啊,我以你为傲 +打得好啊 +谢谢... +我喜欢你拿球杆的架势 +很帅气 +我们队上有人在考虑 +要去加拿大念大学 +加拿大? +加拿大很远耶 +你们还有路克嘛 +还真欣慰啊 +不是啦,我开玩笑的 +不跟小孩闹着玩就老得快 +你以后就会懂 +你这场球打得漂亮 +好几场都打得好 +但职业曲棍球... +这是你要的吗? +或许吧,我不知道 +这可是有风险的 +这是你当职业球员的经验谈? +还是... +不是,是我的高风险职业经验谈 +多谢你了 +风险、责任、人生的残酷面 +不对,那是你的人生 +你充满刺激的人生 +别开你老爸的玩笑 +你只有我一个爸爸耶 +再找华教练谈谈吧 +你可以多研究加拿大的学校 +找个人来教我们打曲棍球 +哪里比学法律好 +爸! +干嘛? +教我们? +我只是想打曲棍球 +开大灯 +爸,你觉得呢? +我们再详细研究看看吧 +好吧 +请别跟你妈说 +我不会啦 +高速公路在哪里? +〝汽油量: +低〞 +这下可好了 +〝故障〞 +你要去哪儿? +我想喝东西 +好吧,又要喝冰沙了 +应该有卖吧? +不然就喝更垃圾的饮料罗 +你有钱吗? +有 +好吧,快去快回,要回家了 +好 +老婆,是我,我只是想告诉你 +我们儿子要去加拿大打曲棍球了 +我们不想十八相送 +就直接载他去机场了 +他说会打电话回来 +但我们可能再也见不到儿子了 +但只要他快乐就好了嘛 +先这样 +我爱你 +马上就回家,再见 +小心啦 +让开,搞屁啊 +趴下! +不然我轰烂你的脑袋! +给我趴下! +就是他! +就是他! +他要来找死了 +快啊,比利 +天哪! +杀了他! +就是他了 +快动手,否则不能入帮! +快! +你做得到的 +乔! +快杀了他 +这才对嘛 +快闪! +快闪! +把枪给我! +我们走! +快上车! +妈的! +他妈的! +干! +操你娘的... +布兰登! +布兰登! +天哪 +救命啊! +帮我! +快来帮我! +救命啊! +乔呢? +他现在是男子汉 +可以搭地铁了 +快找人帮忙 +谁能救救我们? +快来人啊! +医生! +把床推过来! +他被割喉了,有人割他... +打开呼吸道,帮助他呼吸 +他是我儿子 +那是我儿子 +梅姬! +好了,带他去旁边 +布兰登,我们到医院了 +他们会替你治疗 +把你治好 +你很快就会好起来 +先生,抱歉,你不能进去 +什么? +让医生去处理吧 +我知道,但我不能进去? +抱歉 +好吧,他会没事的 +他是我儿子 +他叫布兰登 +5号 +是5号 +他是乔达利 +他是... +还是个小孩 +他只是个子矮,快23岁了 +他是个禽兽 +明天应该会有... +正式开庭前的侦讯庭 +他们要我出庭作证 +要不要一起去? +你去 +让那个禽兽去坐牢 +警察也是这样形容他 +禽兽 +西装要不要脱掉? +校方说要办告别式 +在下一场比赛的时候 +球队想做点什么事 +他们真窝心 +他本来也应该去比赛的 +直到我的身躯化成灰 +直到我的灵魂不复存在 +我将会爱你 +爱你 +直到太阳开始哭泣 +月亮化为腐朽 +我将会爱你 +爱你 +但我要知道 +你会不会一直留在我身边 +永远不离开? +那么我将全心付出 +直到生命的最后 +永远不渝 +今天很顺利 +我要你出庭吓得他良心不安 +法官问你,你就把话重述一遍 +当庭指认达利 +懂吗? +我提呈你的证词,加上你出庭 +公设辩护律师就会吓得半死 +5分钟能达成协议 +今天就送他进牢,很简单 +协议? +等一下 +等一下,这是什么意思? +什么协议? +我要这家伙在牢里关一辈子 +不可能 +保证能关3到5年,顶多这样 +我指的是保证 +不是也许,不是看陪审团的心情 +好过求刑十年至无期徒刑 +结果他逃过法网 +你想这样吗? +他杀了我儿子耶 +休姆先生,我有你这个目击者 +很好 +但只有一个目击者的案子 +你知道有多少我不想协议吗? +开山刀莫名其妙消失了 +在那个混蛋身上只找到 +他被车撞留下的血迹 +你又挑中美国唯一 +没装监视器的加油站 +只有你的证词 +还不错,我可以吓得他同意协议 +你拿我儿子的死当游戏 +我送一个混混进牢 +一年后有人替我行天道 +他没活着出狱,我无所谓 +他改信宗教,我无所谓 +但我们硬要严惩求刑 +即便我非常乐意 +辩方也会开始问我们: +〝你上次几时检查视力? +〞 +〝你对市区青少年有成见吗? +〞 +说什么他们在暴力中成长不公平 +被迫杀人加入帮派,不然就没命 +你要陪审团同情这个烂人? +你要他获释? +等一下,你说... +为加入帮派而杀人 +这不是抢案吗? +只是看起来像抢案 +这是入帮仪式 +为了加入帮派而随机杀人 +这是入帮的代价 +你意思是布兰登被杀 +是让那个混混自觉更像男子汉? +让他加入什么帮派? +很遗憾,这种事你不接受就拉倒 +庭上,我要提呈目击者的证词 +在案发当时作的笔录 +他是被害人的父亲 +贝林先生,正式开庭时再提出吧 +庭上,若今天提出 +辩方就会改口认罪了 +省得检方浪费时间金钱来开庭 +那就是证词? +休姆先生? +休姆先生? +你作证这位达利先生在你面前 +攻击你儿子导致他死亡? +你愿意在开庭审讯时作证? +不是这样的,庭上 +什么? +当时很暗 +对方人很多 +我不确定是谁 +贝林先生... +除了休姆先生以外还有证人吗? +没有了,庭上 +我要撤销这件案子 +达利先生,我判决你当庭获释 +你可以在法警陪同下回到拘留所 +取回你的私人物品 +有份短口供,你想看吗? +在我这儿,明天来看看吧 +放心,只要时间足够... +乔! +你赢了! +无罪开释! +真有你的! +赞哦! +我们走,快走吧! +你无罪开释,我以你为傲 +这下子谁有种? +我知道 +上车 +好了,动手吧 +我们去那边 +跟这个妞儿好好享受吧 +好 +可以吗? +我以你为傲 +没问题吧? +爸? +嗨 +你在干嘛? +没有啊 +你在干嘛? +别乱拿,放下 +那里... +是一座... +...加油站吗? +布兰登被杀的地方? +对,是加油站 +问这个干嘛? +我只是... +想知道他在哪里死的 +好吧 +那是... +郊区的一个休息站 +你... +你觉得他害怕吗? +对,路克 +我想他是很害怕 +结果怎样? +他当庭获释了 +什么? +为什么? +我觉得不是他 +你说是他啊,说他被捕了 +他们会继续调查吗? +会,他们说会 +天哪 +对不起,你要我怎样? +对不起 +我有东西忘在公司,我去拿 +现在? +尼克! +我会尽快回来 +天哪 +我明天再打电话给你 +天哪,我在干嘛? +真他妈的 +干! +天哪! +干! +你吓死我了 +等一下 +不可能吧 +是你? +干! +干! +干! +干! +天哪 +天哪 +干! +干! +你知道妈妈很完美 +这是当然罗 +没有,我无言以对 +爸,我想跟你一样 +这句话真令人欣慰 +这件事我拖了好几个月 +谢谢你这么体贴地帮忙 +我觉得你很狗腿耶 +嗨 +嗨 +出了什么事? +我在车道上滑倒了 +老公,天哪,看看你 +你好狼狈 +没事,只是手受伤了 +还好吧? +很好,没事啦 +没事才怪 +我去冲个澡 +好吧,我去拿绷带,待会儿上去 +你怎样? +还好吧? +我很好 +大概吧 +新年快乐! +那就好 +那就好 +我去冲个澡 +布兰登休姆,你当选MVP了 +你有什么话想说? +可以拿走吗? +可以吗? +第一名... +布兰登休姆,争气的宝贝儿子 +老公 +天哪 +天哪 +宝贝,没事了 +对不起 +天哪 +没事了 +对不起 +没事了 +没事了 +对不起 +〝邦斯修车厂〞 +比利! +小心那些零件 +拜托,零件很值钱 +不像你一文不值 +你死哪儿去了? +这像话吗? +今晚就赚这些 +我可怜你和你那些低能朋友 +给你们几个门路去赚钱 +你最好多赚点钱给我 +被我知道你A钱,我就宰了你 +在哪儿风光是你的事 +你要是敢A我的钱 +我就他妈的宰了你 +我对你够有耐心了 +好啦 +你可以滚了 +真他妈的低能 +干嘛? +干嘛? +谁来告诉我出了什么事 +你听说了吗? +乔出事了 +有人杀了他 +他死了 +什么? +少骗人 +他死了啦 +嗨 +你们还好吧? +节哀顺变啊 +我们很好 +总是要想办法调适嘛 +人生就是这样,有失必有得 +日子总得过下去 +换作是我遇到这种事,我会... +不知道,我大概会崩溃吧 +没遇到真的不知道会怎么做 +自己也会吓一跳 +打扰了,尼克 +沃里斯警探找你 +好,请她进来 +嗨,很抱歉打扰你工作 +没关系啦 +我们怀疑杀死令郎的嫌犯 +有人杀了他 +怎么了? +帮派仇恨吗? +大概是吧 +真是老天有眼 +可以这么说啦 +我想你也许会想知道 +说不定凶手真的就是他 +谢谢你来告诉我 +那你忙吧 +我也不必说什么了 +但需要的话公司会支付谘询费用 +我们过得去啦 +谢了,欧文 +不客气 +他不是死得活该,不能让他白死 +他是个正港的斗士 +为乔干一杯 +他是个好孩子 +真他妈的好孩子! +我们就这样做? +怎么不至少尊重一下? +难怪你们一事无成 +难怪你们都是俗辣 +因为你们宁可喝酒 +吸大麻把自己搞成智障 +智障又孬到极点 +是我不好 +我们... +乎干啦 +杯子给我举起来! +每个人都要! +乔只是不适合混帮派啦 +他跟我们不一样 +对,跟你们不一样 +他跟你们不一样 +他比你们好! +我们从小就像兄弟一样 +你却讲这种话? +现在我配不上你了? +乔也像我的亲兄弟啊 +他像我的亲兄弟,你也是 +好吧 +我要抓到杀他的王八蛋 +非抓到不可 +没问题 +去帮乔报仇 +是谁干的? +不是竹联帮,不然我一定知道 +除非你嗑了药 +我没嗑药 +不是四海帮,比利 +不是万华帮,不是帮派干的 +我妹说她看到穿西装的人 +在那里晃来晃去 +这种鸟地方有多少穿西装的人? +这就好笑了 +我们混帮派的被杀就不会上报 +但海星企业资深副总裁的儿子... +〝白领父子遇袭,子惨遭杀害〞 +去问问你妹 +你那天晚上看到的是他吗? +对 +你确定? +爱咪,你好啊 +我要回家了 +没事吧? +需要什么吗? +没有,我很好 +完成这份风险分析报告就要... +麻烦你出去的时候 +顺便把这个拿给欧文 +好 +谢谢你,晚安 +〝主大楼1801号〞 +〝阿斯匹灵〞 +等一下! +抓住他! +快! +快点! +抓住他... +抓住他! +他在哪里? +快... +快... +快点! +1801号怎么走? +主大楼1801号,往哪边? +从锅炉室过去,那边 +他跑哪儿去了? +海可、阿狗、史宾,去拦他 +杀了他! +快! +快! +快! +快! +他人呢? +你有找莎莉谈吗? +有 +天哪,好了 +可恶 +让开! +快走! +汤米,快! +杰米,你这只蜗牛给我死过来 +你唬不了我的啦 +干! +比利,我们快走吧 +比利,快离开这里,快点 +走! +快点! +妈的,天哪 +老婆,抱歉我迟到了 +什么? +等一下,怎么会找不到他? +他人呢? +有没有打去问他朋友? +天哪 +我再回你电话 +我应该知道他在哪里 +8 +- 8 +- 14,没问题 +好了 +采集指纹,比对出来再告诉我 +快去彻底搜索调查 +有必要就去街头找人 +一定有人看到什么 +现在有紧急状况 +派两组人过来 +派两组人 +请2组人员处理这件事 +路克! +路克,你在干嘛? +你妈担心死了,快上车 +不要 +我叫你上车 +不要,我不想上车 +快给我过来 +去你的! +路克! +这里不安全 +对,我明知故犯嘛 +死的是我会比较好吗? +是这样吗? +总比失去争气的宝贝儿子布兰登 +更容易接受吧? +路克... +请你上车 +走吧 +路克,马上给我上车! +马上上车! +天哪 +宝贝,老公 +对不起 +不准再这样吓我了 +我们要杀他? +〝海星企业,1500号〞 +访客要先登记 +先生,访客要先登记 +快递包裹在这里签收 +不行,我要亲手交给他 +给尼克休姆 +请你按照规定登记和托收 +打电话给楼上 +可恶! +尼克休姆! +快点! +尼克休姆! +尼克休姆! +天哪,警察来了 +办公室不赖嘛 +你想干嘛? +那是自由的礼物 +先生,要不要请他出去? +先生? +让你不必再想自己会怎么死 +不必再想自己会孤单地死 +请他出去 +因为你回归造物主怀抱的时候 +就能享受喜悦与荣光 +放手! +王八蛋,你在哪里? +我捡到你的皮夹,你要赏我吗? +快说你在哪里 +不对,我要说的是你在哪里 +你走投无路了 +谁死谁活由我决定 +你最好快点搞懂 +因为我不会再警告你 +我要来享受天伦之乐了 +不行,你听我说 +你敢动我家人 +我就把你大卸八块 +像我杀了你朋友那样,听见没? +他不是我朋友 +他是我弟弟 +我现在要杀光你全家 +你刚才给他们判了死刑 +等一下 +不要! +干! +干! +干! +〝洁西卡沃里斯警探〞 +尼克,出了什么事? +快接啊... +尼克? +老婆,你没事吧? +路克放学回家了吗? +对啊,我们很好 +那就好,在家里等警察到 +答应我 +为什么? +怎么了? +你只管待在家里等警察到 +我马上回去 +快接啊... +请问沃里斯警探在吗? +沃里斯警探! +马上叫沃里斯警探来接! +可恶 +重案组,我是沃里斯 +他们威胁要杀我全家 +休姆先生? +那个下三滥... +威胁要杀我全家 +好吧,你家人在哪儿? +在家里 +两个都在家里 +请你救我们 +海伦? +路克? +尼克? +天哪 +到底出了什么事? +老公,为什么警察要来? +尼克,你吓坏我了啦 +天哪 +尼克,跟我说啊 +爸,出了什么事? +尼克! +出了什么事? +你待在这儿 +谢天谢地你终于来了 +令郎是打曲棍球的 +对 +警车今晚会守在门口 +休姆先生,我想你现在应该 +告诉我到底谁对谁做了什么 +你惹毛了不敢惹的人吗? +是这样吗? +你以为住在这里 +杀了小混混就没事吗? +你在胡说什么? +尼克,她在说什么啊? +我没做错事 +那你为什么不告诉我 +比利达利怎么会这么气你? +是你要我帮你的 +好吧 +好吧 +先熬过今晚再说,休姆先生 +还活着就该感恩了 +但你要是引发了战争 +就只能听天由命了 +你做了什么? +我要怎么阻止? +你有起头吗? +听我说... +我自己怎样都无所谓 +只要家人平安就好 +告诉我该怎么阻止他们 +首先,他们说什么都照做 +逐一去做 +放心吧,休姆先生 +我们在通缉比利那帮人了 +我居然没发现你做了什么傻事 +你怎么可以这样? +你以为这样就能一命抵一命? +恢复宇宙的秩序? +我失去了我们的儿子 +你儿子 +你是个好爸爸 +这是什么也改变不了的事实 +我爱你 +永远爱你 +幸好你快要摆脱了 +是啊 +快! +走啊! +不! +妈! +滚出去! +妈! +过来! +过来! +比利,怎样? +不! +不! +不! +走吧,都死了啦 +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +你知道你不孤单 +医生! +医生! +压住他的腿! +镇定剂! +压住他! +能不能关掉? +关掉机器? +还是你的心脏? +我去问医生 +这件事到此为止 +天晓得你怎么还活着 +但你有自新的机会 +你以为那位警官是在保护你? +他是不让你害死自己 +我一声令下,他就把你送进牢里 +你要报仇 +杀了几个混混,结果呢? +战争中的每个人都自以为是对的 +最后还不是死光光 +你永远赢不了的,休姆先生 +谁也赢不了 +我害死了他们 +我害死了我的家人 +你儿子还活着 +什么? +昏迷不醒 +他在哪里? +在这家医院? +人呢? +别激动,等一下 +路克! +路克! +路克? +他没事,让他去吧 +路克? +先生,回床上躺好 +我儿子呢? +快说我儿子在哪儿! +他在206病房 +路克? +路克? +我们会照顾令郎的 +路克? +他会清醒吗? +现在不能确定 +以暴制暴是没完没了的 +你说什么? +以暴制暴 +有时候真是太乱了 +世界就是这么乱 +让我和他独处一下 +拜托你 +我去外面等 +路克,你听得见吗? +能不能动动手指? +儿子,听得见就动动手指 +路克,我知道... +你觉得... +我对你的关爱不如对你哥哥 +天哪,我... +我不知道,或许最初是这样 +你也知道的 +我和你妈... +刚有了布兰登的时候 +他实在是... +我觉得他很了不起 +他简直是个奇蹟 +但我一直都很了解他 +后来又有了你 +不知道,我本来以为... +你会是布兰登的翻版 +我期望你像他一样 +结果你不是 +你们截然不同 +和他不一样,和我不一样 +你真的是很像... +太像你妈了 +顽固又... +太过于热情 +你妈就是这样 +她是我这辈子最重要的人 +你也是 +我只是想跟你说我爱你 +我好爱你 +我爱你哥,也爱你妈 +我爱我们全家人 +我... +对不起 +我不能当个更好的爸爸 +对不起 +我没能保护你们 +可恶 +你快去叫医生来... +医生! +欧文 +帮我查一个电话号码 +对,5550128 +去查别的资料库,想办法查到 +存款也要领出来啊 +对,全部都要 +所有的钱 +连小孩的教育基金也要? +喂? +尼克,我是欧文 +电话号码查到了 +是酒吧,叫〝四朵玫瑰〞 +尼克,出了什么事? +要不要我打电话求助? +谢了,再见,欧文 +尼克? +我要找比利达利或他朋友 +〝西班牙语〞 +我说我不会讲英文啦,你聋子哦 +懂了吗,老兄? +〝西班牙语〞 +我把你的猪脑袋砍下来 +寄给你妈 +说不定她会认得出你 +但我很怀疑,老兄 +操你娘的! +干! +干! +闪边! +放开我... +告诉我比利达利在哪里 +现在就说 +快说! +你不会想找比利达利的啦 +我有事要找他 +好,放开我 +放开我! +〝西班牙语〞 +他的同伙海可住在附近113号 +他通常晚餐时间会在嗑药 +可以了吧? +〝西班牙语〞 +还有一件事 +我要买枪 +有事吗? +我要买枪 +我不认识你 +我是从〝四朵玫瑰〞来的 +据我猜测... +你应该不属于这里吧 +别让我闻到你有恐惧的味道 +敌人才要恐惧 +恐惧 +和子弹 +爆炸多的子弹 +这是最凶悍的一把枪 +.357口径 +保证一枪毙命 +这把枪不错 +这是标准的. +45口径 +火力超强 +这是冤仇够深才要用 +这把枪的火力是天王级的 +既是大炮,也是正义之剑 +带这把枪去圣地 +就可以展开圣战了 +不管是哪一把枪 +都保证能让你把烦恼 +抛到九霄云外 +那一把呢? +这把? +好,我要这把和这几把 +买这些枪要花你3千大洋 +你有那么深的仇恨吗? +这是5千美元 +那你就是我的VIP了 +再送你一些小东西 +因为我直觉你很需要 +你身上散发出一股杀气 +真的 +你是想杀我儿子比利的那家伙? +他是你儿子? +所以乔也是你杀的罗? +你杀了我小儿子 +现在又要追杀比利 +对,我要杀他 +比利不是什么好东西啦 +他做的事都与我无关 +有人想要某人付出代价 +以消胸口的一股怨气 +那找比利就对了 +杀了那个混蛋 +看看对我会不会有什么差 +咱们当爸爸的私下讲 +我也是知道的啦 +去找他吧 +我忍他够久了 +你又是个付现的好顾客 +但别以为我会跟你说比利在哪里 +敢问我就杀了你 +去忙你的吧 +愿上帝与你同在 +一整袋的枪也与你同在 +〝布兰登的东西〞 +我要专心想着痛 +那个... +搞什么? +搞什么? +你是谁? +你? +不是被我们干掉了吗? +搞什么? +给我滚出去! +比利人呢? +去你的 +那是我的牙齿耶! +王八蛋! +快说他在哪里 +办公室 +是什么鬼地方? +废弃的精神病院 +我们在那里做毒品 +在冥府街的桥边 +听见没? +冥府街! +打给他 +幸好你爸有赞助你车子 +你就不用溜冰来这里买毒给你妹 +她光顾了我好一阵子 +我也经常去光顾她 +干他妈的 +海可,你这个没用的家伙 +我这礼拜第2次帮你收烂摊了 +比利! +那个王八蛋没死,比利 +你在胡说什么? +他说你死定了 +那又怎样? +就这样啊,操你妈的 +今晚要惹什么事? +你又想干嘛? +好像赶着去投胎 +你知道帮你擦屁股有多累吗? +我还得安抚那个送钱上门的阔佬 +叫他杀了你,你以为我爽吗? +你根本就不懂 +我很关心你的事 +因为会拖累我 +你还需要什么指示吗? +不用了,谢谢老爸 +车子我开走了 +搞什么? +妈的! +阿狗! +那个王八蛋来了! +往你那边去! +我的腿! +阿狗! +快! +去追那个王八蛋! +去抓他! +快啊! +快点... +〝欢迎来到地狱〞 +你知道你会死在这里! +妈的 +瞧瞧你 +你跟我们没两样 +我把你变成杀人魔了 +准备好了吗? +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +我不孤单 +有新年新希望吗? +不对,你知道妈妈很完美 +这倒是 +我没什么新希望啦 +5、4、3、2、1! +新年快乐! +新年快乐! +好吧,你今年有什么期望? +你儿子 +他有在动了 +应该能撑得下去 +好吧,你先唱,起音别太高 +应该遗忘旧识 +永远不再想起吗? +我们要共饮一杯酒 +敬两小无猜的往日时光 +比利,我们快走吧 +比利,快离开这里,快点 +走! +快点! +妈的,天哪 +老婆,抱歉我迟到了 +什么? +等一下,怎么会找不到他? +他人呢? +有没有打去问他朋友? +天哪 +我再回你电话 +我应该知道他在哪里 +8 +- 8 +- 14,没问题 +好了 +采集指纹,比对出来再告诉我 +快去彻底搜索调查 +有必要就去街头找人 +一定有人看到什么 +现在有紧急状况 +派两组人过来 +派两组人 +请2组人员处理这件事 +路克! +路克,你在干嘛? +你妈担心死了,快上车 +不要 +我叫你上车 +不要,我不想上车 +快给我过来 +去你的! +路克! +这里不安全 +对,我明知故犯嘛 +死的是我会比较好吗? +是这样吗? +总比失去争气的宝贝儿子布兰登 +更容易接受吧? +路克... +请你上车 +走吧 +路克,马上给我上车! +马上上车! +天哪 +宝贝,老公 +对不起 +不准再这样吓我了 +我们要杀他? +〝海星企业,1500号〞 +访客要先登记 +先生,访客要先登记 +快递包裹在这里签收 +不行,我要亲手交给他 +给尼克休姆 +请你按照规定登记和托收 +打电话给楼上 +可恶! +尼克休姆! +快点! +尼克休姆! +尼克休姆! +天哪,警察来了 +办公室不赖嘛 +你想干嘛? +那是自由的礼物 +先生,要不要请他出去? +先生? +让你不必再想自己会怎么死 +不必再想自己会孤单地死 +请他出去 +因为你回归造物主怀抱的时候 +就能享受喜悦与荣光 +放手! +王八蛋,你在哪里? +我捡到你的皮夹,你要赏我吗? +快说你在哪里 +不对,我要说的是你在哪里 +你走投无路了 +谁死谁活由我决定 +你最好快点搞懂 +因为我不会再警告你 +我要来享受天伦之乐了 +不行,你听我说 +你敢动我家人 +我就把你大卸八块 +像我杀了你朋友那样,听见没? +他不是我朋友 +他是我弟弟 +我现在要杀光你全家 +你刚才给他们判了死刑 +等一下 +不要! +干! +干! +干! +〝洁西卡沃里斯警探〞 +尼克,出了什么事? +快接啊... +尼克? +老婆,你没事吧? +路克放学回家了吗? +对啊,我们很好 +那就好,在家里等警察到 +答应我 +为什么? +怎么了? +你只管待在家里等警察到 +我马上回去 +快接啊... +请问沃里斯警探在吗? +沃里斯警探! +马上叫沃里斯警探来接! +可恶 +重案组,我是沃里斯 +他们威胁要杀我全家 +休姆先生? +那个下三滥... +威胁要杀我全家 +好吧,你家人在哪儿? +在家里 +两个都在家里 +请你救我们 +海伦? +路克? +尼克? +天哪 +到底出了什么事? +老公,为什么警察要来? +尼克,你吓坏我了啦 +天哪 +尼克,跟我说啊 +爸,出了什么事? +尼克! +出了什么事? +你待在这儿 +谢天谢地你终于来了 +令郎是打曲棍球的 +对 +警车今晚会守在门口 +休姆先生,我想你现在应该 +告诉我到底谁对谁做了什么 +你惹毛了不敢惹的人吗? +是这样吗? +你以为住在这里 +杀了小混混就没事吗? +你在胡说什么? +尼克,她在说什么啊? +我没做错事 +那你为什么不告诉我 +比利达利怎么会这么气你? +是你要我帮你的 +好吧 +好吧 +先熬过今晚再说,休姆先生 +还活着就该感恩了 +但你要是引发了战争 +就只能听天由命了 +你做了什么? +我要怎么阻止? +你有起头吗? +听我说... +我自己怎样都无所谓 +只要家人平安就好 +告诉我该怎么阻止他们 +首先,他们说什么都照做 +逐一去做 +放心吧,休姆先生 +我们在通缉比利那帮人了 +我居然没发现你做了什么傻事 +你怎么可以这样? +你以为这样就能一命抵一命? +恢复宇宙的秩序? +我失去了我们的儿子 +你儿子 +你是个好爸爸 +这是什么也改变不了的事实 +我爱你 +永远爱你 +幸好你快要摆脱了 +是啊 +快! +走啊! +不! +妈! +滚出去! +妈! +过来! +过来! +比利,怎样? +不! +不! +不! +走吧,都死了啦 +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +你知道你不孤单 +医生! +医生! +压住他的腿! +镇定剂! +压住他! +能不能关掉? +关掉机器? +还是你的心脏? +我去问医生 +这件事到此为止 +天晓得你怎么还活着 +但你有自新的机会 +你以为那位警官是在保护你? +他是不让你害死自己 +我一声令下,他就把你送进牢里 +你要报仇 +杀了几个混混,结果呢? +战争中的每个人都自以为是对的 +最后还不是死光光 +你永远赢不了的,休姆先生 +谁也赢不了 +我害死了他们 +我害死了我的家人 +你儿子还活着 +什么? +昏迷不醒 +他在哪里? +在这家医院? +人呢? +别激动,等一下 +路克! +路克! +路克? +他没事,让他去吧 +路克? +先生,回床上躺好 +我儿子呢? +快说我儿子在哪儿! +他在206病房 +路克? +路克? +我们会照顾令郎的 +路克? +他会清醒吗? +现在不能确定 +以暴制暴是没完没了的 +你说什么? +以暴制暴 +有时候真是太乱了 +世界就是这么乱 +让我和他独处一下 +拜托你 +我去外面等 +路克,你听得见吗? +能不能动动手指? +儿子,听得见就动动手指 +路克,我知道... +你觉得... +我对你的关爱不如对你哥哥 +天哪,我... +我不知道,或许最初是这样 +你也知道的 +我和你妈... +刚有了布兰登的时候 +他实在是... +我觉得他很了不起 +他简直是个奇蹟 +但我一直都很了解他 +后来又有了你 +不知道,我本来以为... +你会是布兰登的翻版 +我期望你像他一样 +结果你不是 +你们截然不同 +和他不一样,和我不一样 +你真的是很像... +太像你妈了 +顽固又... +太过于热情 +你妈就是这样 +她是我这辈子最重要的人 +你也是 +我只是想跟你说我爱你 +我好爱你 +我爱你哥,也爱你妈 +我爱我们全家人 +我... +对不起 +我不能当个更好的爸爸 +对不起 +我没能保护你们 +可恶 +你快去叫医生来... +医生! +欧文 +帮我查一个电话号码 +对,5550128 +去查别的资料库,想办法查到 +存款也要领出来啊 +对,全部都要 +所有的钱 +连小孩的教育基金也要? +喂? +尼克,我是欧文 +电话号码查到了 +是酒吧,叫〝四朵玫瑰〞 +尼克,出了什么事? +要不要我打电话求助? +谢了,再见,欧文 +尼克? +我要找比利达利或他朋友 +〝西班牙语〞 +我说我不会讲英文啦,你聋子哦 +懂了吗,老兄? +〝西班牙语〞 +我把你的猪脑袋砍下来 +寄给你妈 +说不定她会认得出你 +但我很怀疑,老兄 +操你娘的! +干! +干! +闪边! +放开我... +告诉我比利达利在哪里 +现在就说 +快说! +你不会想找比利达利的啦 +我有事要找他 +好,放开我 +放开我! +〝西班牙语〞 +他的同伙海可住在附近113号 +他通常晚餐时间会在嗑药 +可以了吧? +〝西班牙语〞 +还有一件事 +我要买枪 +有事吗? +我要买枪 +我不认识你 +我是从〝四朵玫瑰〞来的 +据我猜测... +你应该不属于这里吧 +别让我闻到你有恐惧的味道 +敌人才要恐惧 +恐惧 +和子弹 +爆炸多的子弹 +这是最凶悍的一把枪 +.357口径 +保证一枪毙命 +这把枪不错 +这是标准的. +45口径 +火力超强 +这是冤仇够深才要用 +这把枪的火力是天王级的 +既是大炮,也是正义之剑 +带这把枪去圣地 +就可以展开圣战了 +不管是哪一把枪 +都保证能让你把烦恼 +抛到九霄云外 +那一把呢? +这把? +好,我要这把和这几把 +买这些枪要花你3千大洋 +你有那么深的仇恨吗? +这是5千美元 +那你就是我的VIP了 +再送你一些小东西 +因为我直觉你很需要 +你身上散发出一股杀气 +真的 +你是想杀我儿子比利的那家伙? +他是你儿子? +所以乔也是你杀的罗? +你杀了我小儿子 +现在又要追杀比利 +对,我要杀他 +比利不是什么好东西啦 +他做的事都与我无关 +有人想要某人付出代价 +以消胸口的一股怨气 +那找比利就对了 +杀了那个混蛋 +看看对我会不会有什么差 +咱们当爸爸的私下讲 +我也是知道的啦 +去找他吧 +我忍他够久了 +你又是个付现的好顾客 +但别以为我会跟你说比利在哪里 +敢问我就杀了你 +去忙你的吧 +愿上帝与你同在 +一整袋的枪也与你同在 +〝布兰登的东西〞 +我要专心想着痛 +那个... +搞什么? +搞什么? +你是谁? +你? +不是被我们干掉了吗? +搞什么? +给我滚出去! +比利人呢? +去你的 +那是我的牙齿耶! +王八蛋! +快说他在哪里 +办公室 +是什么鬼地方? +废弃的精神病院 +我们在那里做毒品 +在冥府街的桥边 +听见没? +冥府街! +打给他 +幸好你爸有赞助你车子 +你就不用溜冰来这里买毒给你妹 +她光顾了我好一阵子 +我也经常去光顾她 +干他妈的 +海可,你这个没用的家伙 +我这礼拜第2次帮你收烂摊了 +比利! +那个王八蛋没死,比利 +你在胡说什么? +他说你死定了 +那又怎样? +就这样啊,操你妈的 +今晚要惹什么事? +你又想干嘛? +好像赶着去投胎 +你知道帮你擦屁股有多累吗? +我还得安抚那个送钱上门的阔佬 +叫他杀了你,你以为我爽吗? +你根本就不懂 +我很关心你的事 +因为会拖累我 +你还需要什么指示吗? +不用了,谢谢老爸 +车子我开走了 +搞什么? +妈的! +阿狗! +那个王八蛋来了! +往你那边去! +我的腿! +阿狗! +快! +去追那个王八蛋! +去抓他! +快啊! +快点... +〝欢迎来到地狱〞 +你知道你会死在这里! +妈的 +瞧瞧你 +你跟我们没两样 +我把你变成杀人魔了 +准备好了吗? +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +我不孤单 +有新年新希望吗? +不对,你知道妈妈很完美 +这倒是 +我没什么新希望啦 +5、4、3、2、1! +新年快乐! +新年快乐! +好吧,你今年有什么期望? +你儿子 +他有在动了 +应该能撑得下去 +好吧,你先唱,起音别太高 +应该遗忘旧识 +永远不再想起吗? +我们要共饮一杯酒 +敬两小无猜的往日时光 +好吧,我拆不开 +好啦,准备好了吗? +- 祝你圣诞快乐 +- 我就是想要 +这种脚踏车 +对,喜欢吗? +是那种吗? +那就好,圣诞快乐 +新冰球杆 +尺寸对吗 +对,很适合我 +挥杆给我看 +别打到桌上的东西 +我最厉害 +我最厉害 +片名: +《死亡裁决》 +放马过来吧 +等一下 +准备好了吗? +好了,用力挥 +你还好吧 +你还好吧 +好了,你自己骑 +天哪! +路克 +宝贝 +小心那棵树啊 +玩个花样 +玩个花样 +你以他为荣? +对啊,他好了不起 +那是妈妈画的吗 +说实话,是妈妈画的吗? +你看 +我有个疑问... +这是什么? +是抽象画 +我和球队签约就买新房子送你 +这栋房子有什么不好? +准备好了? +可恶 +好了,许愿吧 +妈,你几岁 +我几岁? +只是好奇 +你很漂亮 +看起来不过才... +爸,快说啦 +布兰登・休姆,你当选MVP了 +争气的宝贝儿子 +第一名... +点蜡烛吧 +可以用手掴醒他吗? +不行 +好吗 +他会杀了我们 +惊喜! +惊喜! +生日快乐,路克 +生日快乐,路克 生日快乐 +14岁了 +感觉和昨天13岁没分别 +你要现在被揍14下? +还是... +待会儿啦,等我睡醒再说 +走开 +我差点就赢你了 +怎能忘记旧日朋友 +心中能不怀想? +旧日朋友岂能相忘 +友谊地久天长 +打扰一下 +你觉得怎么也找不到规律的时候 规律就藏在你眼皮底下 +好吧 +有何贵干? +安妮要我请你签核 +这个人在海星做了6年 +但他老婆死了,没小孩,没遗嘱 +我想把他的退休金纳入抚恤金 +直截了当 +拜托,我不想搞得太复杂 +要照规定做 +等他死了大家就知道我们尽到了责任 +你说得对,省麻烦 +我懂了,抱歉 +不是,我们要尽责 +好好安顿我们的员工 +别让他死不暝目 +你讲的"宇宙的规律"是什么? +我们的保险公司花了30万美元 +建立这个新的数学模型、新调查资料 +新社会 +怎样的人才是理想员工? +谁怎么死的? +几时死的? +他们把资料送来了,让我们看看成果 +你知道报告内容吗? +有小孩的人比没小孩的人更长寿 +有两个小孩比一个小孩的更长寿 +抽烟不好 +超速不好 +家有丧事不好,离婚不好 +还好的是 +这些陈腔滥调始终是事实 +布兰登,你很滑头啊 +我是天赋异禀 没办法嘛 +- 天哪,妈,我好想死啊 +- 我知道 +- 我可以先失陪吗 +- 不行 +我有个白痴阿哥 +我有个没屌的弟弟 +好了,别吵啦 +- 你该懂点事 +- 怎么? +家人要相亲相爱 +- 我能说不吗? +- 不行 +我要求豁免权,我要找律师 +- 好,我要提出起诉,现在就要 +- 我回来了 +抱歉回来晚了,错过晚餐了吗? +没有,菜还很多,我去弄热给你吃 +爸,礼拜六载我去市区 +市区? +对,这是交换比赛 +我是先发球员 +真的吗? +- 太好了 +- 对啊 +华教练一定爱死你了 +对,因为他是狗 +也不坏啊,大家都要去吗 +不行,路克要踢足球 +对,但我不是先发 +也许你该多亲几个人的菊花... +或者口交时候别太用力 +- 我听说这样管用 +- 喂,喂,喂! +爸,我开玩笑的,他简直是白痴 +不准骂他白痴 +路克,你有个忠诚又疼你的哥哥 +说得对 +忠诚又疼我的狗 +大家能不能文明一点? +不然我要杀人了 +我无所谓啦,卑鄙小人 +最好啦,卑鄙小人 +路克... +碟子 +衰人,给我过来 +放手 +知道不回家会错过什么了吧? +对,至少他们没互扔食物 +打得好啊,我以你为傲 +打得好啊 +谢谢... +我喜欢你拿球杆的架势 +很帅气 +我们队上有人在考虑 +要去加拿大念大学 +加拿大? +加拿大很远呢 +你们还有路克嘛 +还真欣慰啊 +不是啦,我开玩笑的 +不跟小孩闹著玩就老得快 +你以後就会懂 +你这场球打得漂亮 +好几场都打得好 +但职业冰球... +这是你要的吗? +或许吧,我不知道 +这可是有风险的 +这是你当职业球员的经验谈? +- 还是... +- 不是,是我的 +高风险职业经验谈,多谢你了 +风险、责任——人生的残酷面 +不对,那是你的人生 +你充满刺激的人生 +别开你老爸的玩笑 +你只有我一个爸爸 +再找华教练谈谈吧 +你可以多研究加拿大的学校 +找个人来教我们 打冰球和上法律学校哪个好 +- 爸 +- 干嘛? +教我们? +我只是想打冰球 +开大灯 +爸,你觉得呢? +我们再详细研究... +看看吧 好吧 +请别跟你妈说 +我不会的 +高速公路在哪里? +"汽油量: +低" +这下可好了 +"故障" +你要去哪儿? +我想喝东西 +好吧,又要喝冰沙了 +应该有卖吧? +不然就喝更垃圾的饮料啰 +- 你有钱吗? +- 有 +好吧,快去快回,要回家了 +好 +老婆,是我,我只是想告诉你 +我们儿子要去加拿大打冰球了 +我们不想十八相送 +就直接载他去机场了 +他说会打电话回来 +但我们可能再也见不到儿子了 +但只要他快乐就好了 +先这样 +我爱你 +马上就回家,再见 +小心啦 +让开,死鬼 +趴下! +不然我打爆你个头! +给我趴下! +就是他! +就是他! +他想拿枪,比利! +杀了他! +就是他了 +快动手,否则不能入帮! +快! +你做得到的 +祖! +快杀了他 +这才对嘛 +快闪! +快闪! +把枪给我! +我们走! +- 那祖怎么办? +- 快上车! +妈的! +他妈的! +干! +操你娘的... +布兰登 +布兰登 +天哪 +救命啊! +帮我! +快来帮我! +救命啊! +祖呢? +他现在是男子汉了 +可以搭地铁回去 +快找人帮忙 +谁能救救我们? +快来人啊! +医生! +把床推过来! +他被割喉了,有人割他... +打开呼吸道,帮助他呼吸 +他是我儿子 +- 那是我儿子 +- 梅姬! +- 好了,带他去旁边 +- 布兰登 +我们到医院了 +他们会替你治疗 +把你治好 +先生,抱歉 +- 你不能进去 +- 什么? +- 让医生去处理吧 +- 我知道 +但我不能进去? +抱歉 +好吧,他会没事的 +他是我儿子 +他叫布兰登 +5号 +是5号 +他是祖·达利 +他是... +还是个孩子 +他只是个子矮,快23岁了 +他是个禽兽 +明天应该会有... +正式开庭前的侦讯庭 +他们要我出庭作证 +要不要一起去? +你去 +让那个禽兽去坐牢 +警察也是这样形容他 +禽兽 +西装要不要脱掉? +校方说要办告别会 +在下一场比赛的时候 +球队想做点事 +他们真有心 +他本来也应该参赛的 +直到我的身躯化成灰 +直到我的灵魂不复存在 +我将会爱你 +爱你 +直到太阳开始哭泣 +月亮化为腐朽 +我将会爱你 +爱你 +但我要知道 +你会不会一直留在我身边 +永远不离开? +那么我将全心付出 +直到生命的最后 +永远不渝 +今天的事很好办 +我要你出庭吓得他良心不安 +法官问你 你就把跟我们说过的话重答一遍 +当庭指证达利 +懂吗? +我提呈你的证词,加上你出庭 +官方辩护律师就会吓得半死 +5分钟能达成协议 +今天就送他进牢,很简单 +协议? +等一下 +等一下,这是什么意思? +什么协议? +我要这家伙坐一辈子的牢 +不可能 +保证能关3到5年,顶多这样 +我指的是保证 +不是也许,不是看陪审团的心情 +好过不切实际地求刑十年或无期徒刑 +结果他逃过法网 +你想这样吗? +但他杀了我儿子 +休姆先生,我有你这个目击者 +很好 +但只有一个目击者的案子 +你知道有多少我连协议都懒得试吗? +凶器莫名其妙消失了 +在那个混蛋身上只找到 +他被车撞留下的血迹 +你又挑中美国唯一 +没装监视器的加油站 +只有你的证词 +还不错,我可以吓得他同意协议 +你拿我儿子的死当游戏 +我送一个混混进牢 +一年后有人替我行天道 +他没活着出狱,我无所谓 +他改信宗教,我无所谓 +但我们硬要严惩求刑 +即便我非常乐意 +辩方也会开始问我们: +"你上次几时检查视力?" +"你对市区青少年有成见吗?" +说什么他们在暴力中成长不公平 +被迫杀人加入帮派,不然就没命 +你要陪审团同情这个烂人 +你要他获释? +等一下,你说... +为加入帮派而杀人 +这不是抢劫案吗? +只是看起来像抢劫案 +这是入帮仪式 +为了加入帮派而随机杀人 +这是入帮的代价 +你意思是布兰登被杀 +是让那个混混自觉更像男子汉? +让他加入什么帮派? +很遗憾,这种事你不接受就拉倒 +法官大人,我要提呈目击者的证词 +在案发当时作的笔录 +他是被害人的父亲 +贝林先生,正式开庭时再提出吧 +法官大人,若今天提出 +辩方就会改口认罪了 +省得检方浪费时间金钱来开庭 +那就是证词? +休姆先生? +休姆先生? +你作证这位达利先生在你面前 +攻击你儿子导致他死亡? +你愿意在开庭审讯时作证? +不是这样的,法官大人 +什么? +当时很喑 +对方人很多 +我不确定是谁 +贝林先生... +除了休姆先生以外还有证人吗? +没有了,法官大人 +我要撤销这件案子 +达利先生,我判决你当庭释放 +你可以在法警陪同下回到看守所 +取回你的私人物品 +祖! +你赢了! +无罪释放! +真有你的 +劲哦! +我们走,快走吧! +你无罪释放,我以你为荣 +这下子谁有种? +我知道 +上车 +跟这个妞儿好好享受吧 +- 好 +- 可以吗? +我以你为荣 +没问题吧? +爸? +爸? +你在干嘛? +没有啊 +你在干嘛? +别乱拿,放下 +那里... +是一座... +...加油站吗? +布兰登被杀的地方? +对,是加油站 +问这个干嘛? +我只是... +想知道他在哪里死的 +好吧 +那是... +郊区的一个休息站 +你... +你觉得他害怕吗? +对,路克 +我想他是很害怕 +结果怎样? +他当庭获释了 +什么? +为什么? +我觉得不是他 +你说是他啊,说他被捕了 +他们会继续调查吗? +会,他们说会 +天哪 +对不起,你要我怎样? +对不起 +我有东西遗忘在公司,我回去拿 +现在? +- 尼克! +- 我会尽快回来 +天哪,我在干嘛? +真他妈的 +干! +天哪! +干! +你吓死我了 +等一下 +不可能吧 +是你? +干! +干! +干! +干! +天哪 +天哪 +天哪 +你知道妈妈很完美 +这是当然罗 +没有,我无言以对 +爸,我想跟你一样 +这句话真令人欣慰 +这件事我拖了好几个月 +谢谢你这么体贴地帮忙 +嗨 +嗨 +出了什么事? +我在车道上滑倒了 +老公,天哪,看看你 +你好狼狈 +没事,只是手受伤了 +还好吧 +很好,没事啦 +没事才怪 +我去冲个澡 +好吧,我去拿绷带,待会儿上去 +你怎样? +还好吧? +我很好 +大概是吧 +那就好 +那就好 +我去冲个澡 +布兰登·休姆,你当选MVP了 +你有什么话想说? +可以拿走吗? +可以吗? +第一名... +布兰登·休姆,争气的宝贝儿子 +老公 +天哪 +- 天哪 +- 宝贝,没事了 +对不起 +天哪 没事了 +对不起 没事了 +对不起 +"邦斯修车厂" +比利! +小心那些零件 +喂,零件很值钱的 +不像你一文不值 +你死哪儿去了 +这像话吗? +今晚就赚到这些 +我可怜你和你那些低能朋友 +给你们几个门路去赚钱 +你最好多赚点钱给我 +被我知道你偷钱,我就宰了你 +在哪儿风光是你的事 +你要是敢偷我的钱 +我就他妈的宰了你 +我对你够有耐心了 +好啦 +你可以滚了 +真他妈的低能 +干嘛? +干嘛? +谁可以告诉我出了什么事 +你听说了吗? +祖出事了 +有人捅了他 +他死了 +什么? +少骗人 +他死了啦 +嗨 +你们还好吧? +节哀顺变啊 +我们很好 +总是要想办法适应 +人生就是这样,有失又有得 +日子总得过下去 +换作是我遇到这种事,我会... +不知道,我大概会崩溃吧 +没遇到真的不知道会怎么做 +自己也会吓一跳 +打扰了,尼克 +沃里斯警探找你 +好,请她进来 +嗨,很抱歉打扰你工作 +没关系 +涉嫌杀死令郎的疑犯 +被人杀了 +怎么了? +帮派仇杀吗 +大概是吧 +真是老天有眼 +可以这么说啦 +我想你也许会想知道 +说不定凶手真的就是他 +谢谢你来告诉我 +不打扰你了 +我也不必说什么了 +但需要的话公司会承担咨询费用 +我们应付得来 +谢了,奥云 +不客气 +他不是死得活该,不能让他白死 +他是个真斗士 +为祖干一杯 +他是个好孩子 +真他妈的好孩子 +我们就这样做 +怎么不给点尊重? +难怪你们一事无成 +难怪你们都是贱精 +因为你们宁可喝酒 +吸大麻把自己搞成弱智 +智障又孬到极点 +是我不好 +我们... +干杯吧 +杯子给我举起来! +每个人都要! +祖只是不适合混帮派啦 +他跟我们不一样 +对,跟你们不一样 +他跟你们不一样 +他比你们好! +我们从小就像兄弟一样 +你却讲这种话? +现在我配不上你了 +祖也像我的亲兄弟啊 +他像我的亲兄弟,你也是 +好吧 +我要抓到杀他的王八蛋 +非抓到不可 +没问题 +去帮祖报仇 +是谁干的? +不是14K,不然我一定知道 +除非你啪了药 +我没啪药 +不是新X安,比利 +不是和胜X,不是帮派干的 +我妹说她看到穿西装的人 +在那里流连 +这种鸟地方有多少穿西装的人? +这就好笑了 +我们帮派的被杀就不会上头条 +但海星企业资深副总裁的儿子... +"白领父子遇袭,子惨遭杀害" +去问问你妹 +爱美,你好啊 +我要回家了 +没事吧? +需要什么吗? +没有,我很好 +完成这份风险分析报告就要... +麻烦你出去的时候 +顺便把这个拿给奥云 +- 好 +- 谢谢你,晚安 +"主大楼1801号" +"阿司匹林" +等一下! +抓住他! +快! +快点! +抓住他... +他在哪里? +快... +快... +快... +快... +快点... +1801号怎么走? +主大楼1801号,往哪边? +从锅炉室过去,那边 +他跑哪儿去了? +海可、阿狗、史宾,去拦截他 +杀了他! +快! +快! +快! +快! +他人呢? +天哪,好了 +可恶 +你有找莎莉谈吗? +有 +让开! +快走 +汤美,快! +杰米,你这只蜗牛给我死过来 +你唬不了我的啦 +干! +比利,我们快走吧 +比利,快离开这里,快点 +走! +快点! +妈的,天哪 +老婆,抱歉我迟到了 +什么? +等一下,怎么会找不到他? +他人呢? +有没有打去问他朋友? +天哪 +我再复你电话 +我应该知道他在哪里 +好了 +收集指纹,比对出来再告诉我 +快去彻底搜索调查 +有必要就去街头找人 +一定有人看到什么 +路克! +路克,你在干嘛? +你妈担心死了,快上车 +不要 +我叫你上车 +不要,我不想上车 +快给我过来 +去你的! +路克! +这里不安全 +对,难道我会不知道? +死的是我会比较好吧? +是这样吗? +总比失去争气的宝贝儿子布兰登 +更容易接受吧? +路克... +请你上车 +走吧 +路克,马上给我上车! +马上上车! +天哪 +宝贝 +对不起 +不准再这样吓我了 +我们要杀他? +访客要先登记 +先生,访客要先登记 +快递包裹可放这里签收 +不行,我要亲手交给他 +给尼克·休姆 +请你按照规定登记,把包裹放下 +打电话给楼上 +可恶! +尼克·休姆! +快点! +尼克·休姆! +尼克·休姆! +办公室不错 +你想干嘛? +那是让你解脱的礼物 +先生,要不要请他出去? +先生? +让你不必再想自己会怎么死 +不必再担心自己会孤单地死 +请他出去 +因为你回归造物主怀抱的时候 +就能享受喜悦与荣光 +放手! +王八蛋,你在哪里? +我捡到你的钱包,你要赏我吗? +快说你在哪里 +不对,我要说的是你在哪里 +你走投无路了 +谁死谁活由我决定 +你最好快点搞清楚 +因为我不会再警告你 +我要来享受天伦之乐了 +不行,你听我说 +你敢动我家人 +我就把你开膛破肚 +像我杀了你朋友那样,听见没有? +他不是我朋友 +他是我弟弟 +我现在要杀光你全家 +你刚才给他们判了死刑 +等一下 +不要! +操! +操! +操 +"洁西卡沃里斯警探" +- 尼克,出了什么事? +- 快接啊... +- 尼克? +- 老婆,你没事吧? +路克也没事吧? +- 对啊,我们很好 +- 那就好,呆在那里,等警察到 +- 叫路克不要回家,好吗? +- 为什么? +怎么了? +你只管待在那里等人来 +- 答应我 +- 谁要来? +快接啊... +请问沃里斯警探在吗? +沃里斯警探! +马上叫沃里斯警探来接 +可恶 +重案组,我是沃里斯 +他们威胁要杀我全家 +休姆先生? +那个流氓... +威胁要杀我全家 +好吧,你家人在哪儿? +他们在学校里! +圣巴索洛缪中学 +请你救我们 +海伦? +路克? +尼克? +天哪 +到底出了什么事? +老公,为什么警察要守在门口? +尼克,你吓坏我了啦 +天哪 +尼克,跟我说啊 +爸,出了什么事? +尼克! +出了什么事? +你待在这儿 +谢天谢地你终于来了 +令郎是打冰球的 +对 +警车今晚会守在门口 +休姆先生,我想你现在应该 +告诉我到底谁对谁做了什么 +你竟敢太岁头上动土? +是这样吗? +你以为住在这里 +杀了小混混就没事吗? +你在胡说什么? +尼克,她在说什么啊? +我没做错事 +那你为什么不告诉我 +你怎么会惹到比利·达利的? +是你要我帮你的 +好吧 +好吧 +先熬过今晚再说,休姆先生 +还活着就该感恩了 +但你要是引爆战争 +就只能听天由命了 +你做了什么? +我要怎么阻止? +是你引发的吗? +听我说... +我自己怎样都无所谓 +只要家人平安就好 +告诉我该怎么阻止他们 +首先,他们说什么你都照做 +逐一去做 +放心吧,休姆先生 +我们在通缉比利那帮人了 +我居然没发现你做了什么傻事 +你怎么可以这样? +你以为这样就能一命抵一命? +恢复宇宙的秩序? +我失去了儿子 +你儿子 +你是个好爸爸 +这是什么也改变不了的事实 +而且,我爱你 +永远爱你 +幸好你快要摆脱了 +是啊 +不! +妈! +滚出去! +妈! +过来! +过来! +比利,怎样? +不! +不! +不! +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +你知道你不孤单 +医生! +医生! +压住他的腿! +镇定剂! +压住他! +能不能关掉? +关掉机器? +还是你的心脏? +我去问医生 +这件事到此为止 +天晓得你怎么还活著 +但你可重头再来 +你以为那位警官是在保护你? +他是不让你害死自己 +我一声令下,他就可送你进牢房 +你要报仇 +杀了几个混混,结果呢? +战争中的每个人都自以为是对的 +最后还不是死光 +你永远赢不了的,休姆先生 +谁也赢不了 +我害死了他们 +我害死了我的家人 +你儿子还活著 +什么? +昏迷不醒 +他在哪里? +在这家医院? +人呢 +别激动,等一下 +路克! +路克! +路克? +他没事,让他去吧 路克? +先生,回床上躺好 我儿子呢? +快说我儿子在哪儿! +他在206病房 +路克? +路克? +我们会照顾令郎的 +医生,让他去吧 路克? +他会清醒吗? +现在不能确定 +冤冤相报是没完没了的 +你说什么? +冤冤相报 +有时候只是混乱 +世界就是这么乱 +让我和他独处一下 +拜托你 +我去外面等 +路克,你听得见吗 +能不能动动手指? +儿子,听得见就动动手指 +路克,我知道... +你觉得... +我对你的关爱不如对你哥哥 +天哪,我... +我不知道,或许最初是这样 +你也知道的 +我和你妈... +刚有了布兰登的时候 +他实在是... +我觉得他很了不起 +他简直是个奇迹 +但我一直都很了解他 +后来又有了你 +不知道,我本来以为... +你会是布兰登的翻版 +我期望你像他一样 +结果你不是 +你们截然不同 +和他不一样,和我不一样 +你真的是很像... +太像你妈了 +顽固又... +太过于热情 +你妈就是这样 +她是我这辈子最重要的人 +你也是 +我只是想跟你说我爱你 +我好爱你 +我爱你哥,也爱你妈 +我爱我们全家人 +我... +对不起 +我以前未能当个好爸爸 +对不起 +我没能保护你们 +可恶 +你快去叫医生来... +医生! +奥云 +帮我查一个电话号码 +对,5550128 +去查别的资料库,想办法查到 +存款也要领出来? +对,全部都要 +所有的钱 +连孩子的教育基金也要? +喂? +尼克,我是奥云 +电话号码查到了 +是酒吧,叫"四朵玫瑰" +尼克,出了什么事? +要不要我打电话求助? +谢了,再见,奥云 +尼克? +我要找比利·达利或他的朋友 +"西班牙语" +我说我不会讲英文啦,你聋子哦 +懂了吗,老兄? +"西班牙语" +我把你的猪脑袋砍下来 +寄给你妈 +说不定她会认得出你 +但我很怀疑,老兄 +操你娘的! +干! +干! +死开! +放开我... +告诉我比利·达利在哪里 +现在就说 +快说! +你不会想找到比利·达利的 +我有事要找他 +好,放开我 +放开我! +"西班牙语" +他的同伙海可住在附近113号 +他通常晚餐时间会啪药 +可以了吧? +"西班牙语" +还有一件事 +我要买枪 +有事吗? +我要买枪 +我不认识你 +我是从"四朵玫瑰"来的 +据我猜测... +你应该不属于这地头吧 +别让我闻到你有恐惧的味道 +敌人才要恐惧 +恐惧 +和子弹 +超多子弹 +这是凶枪中的凶枪 +点357口径 +保证头也打爆 +这把枪不错 +这是标准的点45口径 +火力超强 +这是血海深仇才要用 +这把枪的火力是天王级的 +既是大炮,也是正义之剑 +带这把枪去圣地 +就可以展开圣战了 +不管是哪一把枪 +都保证能让你把烦恼 +抛到九霄云外 +那一把呢? +这把? +好,我要这把和这几把 +买这些枪要花你3千大洋 +你有很多深仇旧恨吗? +这是5千美元 +那你就是我的VIP了 +再送你一些配件 +因为我直觉你很需要 +你身上散发出一股杀气 +真的 +你是想杀我儿子比利的那家伙 +他是你儿子? +所以祖也是你杀的啰 +你杀了我的小儿 +现在又要追杀比利 +对,我要杀他 +比利不是什么好东西 +他做的事都与我无关 +有人想要某人付出代价 +以消胸口的一股怨气 +那找比利就对了 +杀了那个混蛋 +看看会不会影响我心情 +咱们当爸爸的私下讲 +我也是知道的啦 +去找他吧 +我忍他够久了 +你又是个付现款的好顾客 +但别以为我会跟你说比利在哪里 +敢问我就杀了你 +去忙你的吧 +愿上帝与你同在 +一整袋的枪也与你同在 +"布兰登的东西" +我要专心想著痛 +那个 +搞什么? +搞什么? +你是谁? +你? +不是被我们干掉了吗? +搞什么? +给我滚出去! +比利人呢? +去你的 +我的牙呀! +王八蛋! +快说他在哪里 +办公室 +是什么鬼地方? +废置的精神病院 +我们在那里做毒品 +在冥府街的桥边 +听见没? +冥府街! +打给他 +幸好你爸赞助你车子 +让你不用溜冰来这里买毒给你妹子 +她光顾了我好一阵子 +我也经常去光顾她 +干他妈的 +海可,你这个没用的家伙 +我这礼拜第2次 +- 帮你收烂摊... +- 比利 +那个王八蛋没死,比利 +你在胡说什么? +他说你死定了 +那又怎样? +就这样啊,操你妈的 +今晚要惹什么事? +你又想干嘛? +好像赶著去投胎 +你知道帮你擦屁股有多累吗? +我还得安抚那个送钱上门的阔佬 +叫他杀了你,你以为我爽吗? +你根本就不懂 +我很关心你的事 +因为会拖累我 +你还需要什么指示吗? +不用了,谢你喇老爸 +我去拿车了 +搞什么? +妈的! +阿狗! +那个王八蛋来了! +往你那边去! +我的脚! +阿狗! +快! +去追那个王八蛋! +我杀了你,王八蛋 +去抓他! +快啊! +快点... +"欢迎来到地狱" +你去那里,绕到他后面 +你知道你会死在这里! +妈的 +瞧瞧你 +你跟我们没两样 +我把你变成杀人魔了 +准备好了? +我今晚连动的力气也没有 +你走过去看著我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +有新年新希望吗? +5、4、3、2、1! +新年快乐! +你儿子 +他在动了 +应该能撑得下去 +永远不再想起? +好吧,我拆不开 +好啦,准备好了吗? +祝你圣诞快乐 我就是想要 +这种脚踏车 +对,喜欢吗? +是那种吗? +那就好,圣诞快乐 +新曲棍球杆 +尺寸对吗? +对,很适合我 +挥杆给我看 +别打到桌上的东西 +我最厉害 +我最厉害 +《死亡裁决》 +放马过来吧 +等一下 +准备好了吗? +好了,用力挥 +你还好吧? +你还好吧? +好了,你自己骑 +天哪! +路克! +宝贝! +小心那棵树啊 +耍花招 +耍花招 +你以他为荣? +对啊,他好了不起 +那是妈妈画的吗? +说实话,是妈妈画的吗? +你看 +我有个疑问. +这是什么? +是抽象画 +我和球队签约就买新房子送你 +这栋房子有什么不好? +准备好了? +可恶! +好了,许愿吧 +妈,你几岁? +我几岁? +只是好奇 +你很漂亮 +看起来不过才 +爸,快说啦 +布兰登休姆,你当选MVP了 +争气的宝贝儿子 +第一名 +点蜡烛吧 +可以用手掴醒他吗? +不行 +好吗? +他会杀了我们 +惊喜! +惊喜! +生日快乐,路克 +生日快乐,路克 生日快乐 +14岁了 +感觉和昨天13岁没分别 +你要现在被揍14下? +还是 +待会儿啦,等我睡醒再说 +走开! +我差点就赢你了 +可否忘怀旧雨 +永远不再想起? +可否忘怀旧雨 +祝友谊永固? +打扰一下 +才提到曹操,曹操就来了 +好吧 +有何贵干? +安妮要我请你签核 +这个人在海星做了6年 +但他老婆死了,没小孩,没遗嘱 +我想把他的退休金纳入抚恤金 +直接了当 +拜托,我不想搞得太复杂 +要照规定做 +等他死了大家就知道我们有尽责 +你说得对,省麻烦 +我懂了,抱歉 +不是,我们要尽责 +好好安顿我们的员工 +别让他死不瞑目 +你讲的宇宙的秩序,,是什么? +保户花了30万美元 +依据这份新图表、新调查资料 +新社会 +谁才是好员工? +谁怎么死的? +几时死的? +我们拿到资料知道他们表现多好 +你知道报告内容吗? +有小孩的人比没小孩的人更长寿 +有两个小孩比一个小孩的更长寿 +抽烟不好 +超速不好 +家有白事不好,离婚不好 +还好的是 +这些陈腔滥调始终是事实 +你知道吗? +你家的小孩就很棒啊 +布兰登,你很滑头啊! +我是天赋异禀 +没办法嘛 天哪,妈 +我好想死啊 +我知道 +我可以先失陪吗? +不行 +我有个白痴阿哥 +我有个超样衰细佬 +好了,别吵啦 +你早该知道会这样 +怎样? +一家人要相亲相爱 +我能说不吗? +不行 +我要求豁免权,我要找律师 +好,我要提出起诉 +我回来了 现在就要 +抱歉回来晚了,错过晚餐了吗? +没有,菜还很多,我去弄热给你吃 +爸,礼拜六载我去市区 +市区? +对,这是交换比赛 +我是先发球员 +真的吗? +太好了 对啊 +华教练一定爱死你了 +对,因为他是狗 +也不坏啊,大家都要去吗? +不行,路克要踢足球 +对,但我不是先发 +你们可以". +或者你发癫就" +不会这么渣了 +爸,他开玩笑,简直是白痴 +不准骂他白痴 +路克,你有个忠诚又疼你的哥哥 +说得对 +忠诚又疼我的狗 +大家能不能文明一点? +不然我要杀人了 +我无所谓啦,卑鄙小人 +最好啦,卑鄙小人 +路克 +碟 +衰人,给我过来 +放手! +知道不回家会错过什么了吧? +对,至少他们没互扔食物 +打得好啊,我以你为傲 +打得好啊 +谢谢 +我喜欢你拿球杆的架势 +很帅气 +我们队上有人在考虑 +要去加拿大念大学 +加拿大? +加拿大很远呢 +你们还有路克嘛 +还真欣慰啊 +不是啦,我开玩笑的 +不跟小孩闹着玩就老得快 +你以后就会懂 +你这场球打得漂亮 +好几场都打得好 +但职业曲棍球. +这是你要的吗? +或许吧,我不知道 +这可是有风险的 +这是你当职业球员的经验谈? +还是". +不是,是我的" +高风险职业经验谈,多谢你了 +风险、责任、人生的残酷面 +不对,那是你的人生 +你充满刺激的人生 +别开你老爸的玩笑 +你只有我一个爸爸 +再找华教练谈谈吧 +你可以多研究加拿大的学校 +找个人来教我们打曲棍球 +哪里比学法律好 爸! +干嘛? +教我们? +我只是想打曲棍球 +开大灯 +爸,你觉得呢? +我们再详细研究 +看看吧 好吧 +请别跟你妈说 +我不会的 +高速公路在哪里? +汽油量: +低, +这下可好了 +故障, +你要去哪儿? +我想喝东西 +好吧,又要喝冰沙了 +应该有卖吧? +不然就喝更垃圾的饮料啰 +你有钱吗? +有 +好吧,快去快回,要回家了 +好 +老婆,是我,我只是想告诉你 +我们儿子要去加拿大打曲棍球了 +我们不想十八相送 +就直接载他去机场了 +他说会打电话回来 +但我们可能再也见不到儿子了 +但只要他快乐就好了 +先这样 +我爱你 +马上就回家,再见 +小心啦 +让开,死鬼 +趴下! +不然我打爆你个头! +给我趴下! +就是他! +就是他! +他要来找死了 快啊,比利 +杀了他! +就是他了 +快动手,否则不能入帮! +快! +你做得到的 +祖! +快杀了他 +这才对嘛 +快闪! +快闪! +把枪给我! +我们走! +那祖怎么样 快上车! +妈的! +他妈的! +干! +操你娘的 +布兰登! +布兰登! +天哪 +救命啊! +帮我! +快来帮我! +救命啊! +祖呢? +他现在是男子汉 +可以搭地铁了 +快找人帮忙 +谁能救救我们? +快来人啊! +医生! +把床推过来! +他被割喉了,有人割他 +打开呼吸道,帮助他呼吸 +他是我儿子 +那是我儿子 梅姬! +好了,带他去旁边 布兰登 +我们到医院了 +他们会替你治疗 +把你治好 +先生,抱歉 +你不能进去 什么? +让医生去处理吧 我知道 +但我不能进去? +抱歉 +好吧,他会没事的 +他是我儿子 +他叫布兰登 +5号 +是5号 +他是祖达利 +他是 +还是个细路 +他只是个子矮,快23岁了 +他是个禽兽 +明天应该会有 +正式开庭前的侦讯庭 +他们要我出庭作证 +要不要一起去? +你去 +让那个禽兽去坐牢 +警察也是这样形容他 +禽兽 +西装要不要脱掉? +校方说要办告别会 +在下一场比赛的时候 +球队想做点事 +他们真有心 +他本来也应该参赛的 +直到我的身躯化成灰 +直到我的灵魂不复存在 +我将会爱你 +爱你 +直到太阳开始哭泣 +月亮化为腐朽 +我将会爱你 +爱你 +但我要知道 +你会不会一直留在我身边 +永远不离开? +那么我将全心付出 +直到生命的最后 +永远不渝 +今天很顺利 +我要你出庭吓得他良心不安 +法官问你,你就把话重述一遍 +当庭指证达利 +懂吗? +我提呈你的证词,加上你出庭 +官方辩护律师就会吓得半死 +5分钟能达成协议 +今天就送他进牢,很简单 +协议? +等一下 +等一下,这是什么意思? +什么协议? +我要这家伙坐一辈子的牢 +不可能 +保证能关3到5年,顶多这样 +我指的是保证 +不是也许,不是看陪审团的心情 +好过求刑十年至无期徒刑 +结果他逃过法网 +你想这样吗? +但他杀了我儿子 +休姆先生,我有你这个目击者 +很好 +但只有一个目击者的案子 +你知道有多少我不想协议吗? +凶器莫名其妙消失了 +在那个混蛋身上只找到 +他被车撞留下的血迹 +你又挑中美国唯一 +没装监视器的加油站 +只有你的证词 +还不错,我可以吓得他同意协议 +你拿我儿子的死当游戏 +我送一个混混进牢 +一年后有人替我行天道 +他没活着出狱,我无所谓 +他改信宗教,我无所谓 +但我们硬要严惩求刑 +即便我非常乐意 +辩方也会开始问我们: +你上次几时检查视力? +, +你对市区青少年有成见吗? +, +说什么他们在暴力中成长不公平 +被迫杀人加入帮派,不然就没命 +你要陪审团同情这个烂人? +你要他获释? +等一下,你说 +为加入帮派而杀人 +这不是抢劫案吗? +只是看起来像抢劫案 +这是入帮仪式 +为了加入帮派而随机杀人 +这是入帮的代价 +你意思是布兰登被杀 +是让那个混混自觉更像男子汉? +让他加入什么帮派? +很遗憾,这种事你不接受就拉倒 +法官大人,我要提呈目击者的证词 +在案发当时作的笔录 +他是被害人的父亲 +贝林先生,正式开庭时再提出吧 +法官大人,若今天提出 +辩方就会改口认罪了 +省得检方浪费时间金钱来开庭 +那就是证词? +休姆先生? +休姆先生? +你作证这位达利先生在你面前 +攻击你儿子导致他死亡? +你愿意在开庭审讯时作证? +不是这样的,法官大人 +什么? +当时很暗 +对方人很多 +我不确定是谁 +贝林先生 +除了休姆先生以外还有证人吗? +没有了,法官大人 +我要撤销这件案子 +达利先生,我判决你当庭释放 +你可以在法警陪同下回到拘留所 +取回你的私人物品 +祖! +你赢了! +无罪释放! +真有你的! +劲哦! +我们走,快走吧! +你无罪释放,我以你为荣 +这下子谁有种? +我知道 +上车 +跟这个妞儿好好享受吧 +好 可以吗? +我以你为荣 +没问题吧? +爸? +爸? +你在干嘛? +没有啊 +你在干嘛? +别乱拿,放下 +那里 +是一座 +.油站吗? +布兰登被杀的地方? +对,是油站 +问这个干嘛? +我只是 +想知道他在哪里死的 +好吧 +那是 +郊区的一个休息站 +你 +你觉得他害怕吗? +对,路克 +我想他是很害怕 +结果怎样? +他当庭获释了 +什么? +为什么? +我觉得不是他 +你说是他啊,说他被捕了 +他们会继续调查吗? +会,他们说会 +天哪 +对不起,你要我怎样? +对不起 +我有东西遗忘在公司,我回去拿 +现在? +尼克! +我会尽快回来 +天哪,我在干嘛? +真他妈的 +干! +天哪! +干! +你吓死我了 +等一下 +不可能吧 +是你? +干! +干! +干! +干! +天哪 +天哪 +干! +你知道妈妈很完美 +这是当然啰 +没有,我无言以对 +爸,我想跟你一样 +这句话真令人欣慰 +这件事我拖了好几个月 +谢谢你这么体贴地帮忙 +嗨 +嗨 +出了什么事? +我在路上滑倒了 +老公,天哪,看看你 +你好狼狈 +没事,只是手受伤了 +还好吧? +很好,没事啦 +没事才怪 +我去冲个澡 +好吧,我去拿绷带,待会儿上去 +你怎样? +还好吧? +我很好 +大概是吧 +那就好 +那就好 +我去冲个澡 +布兰登休姆,你当选MVP了 +你有什么话想说? +可以拿走吗? +可以吗? +第一名 +布兰登休姆,争气的宝贝儿子 +老公 +天哪 +天哪 宝贝,没事了 +对不起 +天哪 没事了 +对不起 没事了 +对不起 +邦斯修车厂, +比利! +小心那些零件 +喂,零件很值钱的 +不像你一文不值 +你死哪儿去了? +这像话吗? +今晚就赚到这些 +我可怜你和你那些低能朋友 +给你们几个门路去赚钱 +你最好多赚点钱给我 +被我知道你偷钱,我就宰了你 +在哪儿风光是你的事 +你要是敢偷我的钱 +我就他妈的宰了你 +我对你够有耐心了 +好啦 +你可以滚了 +真他妈的低能 +干嘛? +干嘛? +谁可以告诉我出了什么事 +你听说了吗? +祖出事了 +有人杀了他 +他死了 +什么? +少骗人 +他死了啦 +嗨 +你们还好吧? +节哀顺变啊 +我们很好 +总是要想办法适应 +人生就是这样,有失又有得 +日子总得过下去 +换作是我遇到这种事,我会 +不知道,我大概会崩溃吧 +没遇到真的不知道会怎么做 +自己也会吓一跳 +打扰了,尼克 +沃里斯警探找你 +好,请她进来 +嗨,很抱歉打扰你工作 +没关系 +涉嫌杀死令郎的疑犯 +被人杀了 +怎么了? +帮派仇恨吗? +大概是吧 +真是老天有眼 +可以这么说啦 +我想你也许会想知道 +说不定凶手真的就是他 +谢谢你来告诉我 +不打扰你了 +我也不必说什么了 +但需要的话公司会支付咨询费用 +我们应付得来 +谢了,奥云 +不客气 +他不是死得活该,不能让他白死 +他是个真斗士 +为祖干一杯 +他是个好孩子 +真他妈的好孩子! +我们就这样做? +怎么不给点尊重? +难怪你们一事无成 +难怪你们都是贱精 +因为你们宁可喝酒 +吸大麻把自己搞成弱智 +智障又孬到极点 +是我不好 +我们. +干杯吧 +杯子给我举起来! +每个人都要! +祖只是不适合混帮派啦 +他跟我们不一样 +对,跟你们不一样 +他跟你们不一样 +他比你们好! +我们从小就像兄弟一样 +你却讲这种话? +现在我配不上你了? +祖也像我的亲兄弟啊 +他像我的亲兄弟,你也是 +好吧 +我要抓到杀他的王八蛋 +非抓到不可 +没问题 +去帮祖报仇 +是谁干的? +不是14K,不然我一定知道 +除非你啪了药 +我没啪药 +不是新X安,比利 +不是和胜X,不是帮派干的 +我妹说她看到穿西装的人 +在那里流连 +这种鸟地方有多少穿西装的人? +这就好笑了 +我们帮派的被杀就不会上头条 +但海星企业资深副总裁的儿子 +白领父子遇袭,子惨遭杀害, +去问问你妹 +爱美,你好啊 +我要回家了 +没事吧? +需要什么吗? +没有,我很好 +完成这份风险分析报告就要 +麻烦你出去的时候 +顺便把这个拿给奥云 +好 谢谢你,晚安 +主大楼1801号, +阿斯匹灵, +等一下! +抓住他! +快! +快点! +抓住他 +他在哪里? +快 +快 +快 +快 +1801号怎么走? +主大楼1801号,往哪边? +从锅炉室过去,那边 +他跑哪儿去了? +海可、阿狗、史宾,去拦截他 +杀了他! +快! +快! +快! +快! +他人呢? +天哪,好了 +可恶 +你有找莎莉谈吗? +有 +让开! +快走! +汤美,快! +杰米,你这只蜗牛给我死过来 +你唬不了我的啦 +比利,我们快走吧 +比利,快离开这里,快点 +走! +快点! +妈的,天哪 +老婆,抱歉我迟到了 +什么? +等一下,怎么会找不到他? +他人呢? +有没有打去问他朋友? +天哪 +我再覆你电话 +我应该知道他在哪里 +好了 +收集指纹,比对出来再告诉我 +快去彻底搜索调查 +有必要就去街头找人 +一定有人看到什么 +路克! +路克,你在干嘛? +你妈担心死了,快上车 +不要 +我叫你上车 +不要,我不想上车 +快给我过来 +去你的! +路克! +这里不安全 +对,难道我会唔知? +死的是我会比较好吧? +是这样吗? +总比失去争气的宝贝儿子布兰登 +更容易接受吧? +路克 +请你上车 +走吧 +路克,马上给我上车! +马上上车! +天哪 +宝贝 +对不起 +不准再这样吓我了 +我们要杀他? +海星企业,1500号, +访客要先登记 +先生,访客要先登记 +快递包裹可放这里签收 +不行,我要亲手交给他 +给尼克休姆 +请你按照规定登记和把包裹放下 +打电话给楼上 +可恶! +尼克休姆! +快点! +尼克休姆! +尼克休姆! +办公室不错 +你想干嘛? +那是自由的礼物 +先生,要不要请他出去? +先生? +让你不必再想自己会怎么死 +不必再想自己会孤单地死 +请他出去 +因为你回归造物主怀抱的时候 +就能享受喜悦与荣光 +放手! +王八蛋,你在哪里? +我捡到你的银包,你要赏我吗? +快说你在哪里 +不对,我要说的是你在哪里 +你走投无路了 +谁死谁活由我决定 +你最好快点搞清楚 +因为我不会再警告你 +我要来享受天伦之乐了 +不行,你听我说 +你敢动我家人 +我就把你五马分尸 +像我杀了你朋友那样,听见没有? +他不是我朋友 +他是我弟弟 +我现在要杀光你全家 +你刚才给他们判了死刑 +等一下 +不要! +顶! +顶! +顶! +洁西卡沃里斯警探, +尼克,出了什么事? +快接啊 +尼克? +老婆,你没事吧? +路克放学回家了吗? +对啊,我们很好 +那就好,在家里等警察到 +答应我 +为什么? +怎么了? +你只管待在家里等警察到 +我马上回来 +快接啊 +请问沃里斯警探在吗? +沃里斯警探! +马上叫沃里斯警探来接! +可恶 +重案组,我是沃里斯 +他们威胁要杀我全家 +休姆先生? +那个流氓 +威胁要杀我全家 +好吧,你家人在哪儿? +在家里 +两个都在家里 +请你救我们 +海伦? +路克? +尼克? +天哪 +到底出了什么事? +老公,为什么警察要来? +尼克,你吓坏我了啦 +天哪 +尼克,跟我说啊 +爸,出了什么事? +尼克! +出了什么事? +你待在这儿 +谢天谢地你终于来了 +令郎是打曲棍球的 +对 +警车今晚会守在门口 +休姆先生,我想你现在应该 +告诉我到底谁对谁做了什么 +你竟敢老虎头上动土? +是这样吗? +你以为住在这里 +杀了小混混就没事吗? +你在胡说什么? +尼克,她在说什么啊? +我没做错事 +那你为什么不告诉我 +比利达利怎么会对你火滚? +是你要我帮你的 +好吧 +好吧 +先熬过今晚再说,休姆先生 +还活着就该感恩了 +但你要是引爆战争 +就只能听天由命了 +你做了什么? +我要怎么阻止? +是你引发的吗? +听我说 +我自己怎样都无所谓 +只要家人平安就好 +告诉我该怎么阻止他们 +首先,他们说什么都照做 +逐一去做 +放心吧,休姆先生 +我们在通缉比利那帮人了 +我居然没发现你做了什么傻事 +你怎么可以这样? +你以为这样就能一命抵一命? +恢复宇宙的秩序? +我失去了儿子 +你儿子 +你是个好爸爸 +这是什么也改变不了的事实 +我爱你 +永远爱你 +幸好你快要摆脱了 +是啊 +不! +妈! +滚出去! +妈! +过来! +过来! +比利,怎样? +不! +不! +不! +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +你知道你不孤单 +医生! +医生! +压住他的腿! +镇定剂! +压住他! +能不能关掉? +关掉机器? +还是你的心脏? +我去问医生 +这件事到此为止 +天晓得你怎么还活着 +但你可重头再来 +你以为那位警官是在保护你? +他是不让你害死自己 +我一声令下,他就可送你入册 +你要报仇 +杀了几个混混,结果呢? +战争中的每个人都自以为是对的 +最后还不是死光 +你永远赢不了的,休姆先生 +谁也赢不了 +我害死了他们 +我害死了我的家人 +你儿子还活着 +什么? +昏迷不醒 +他在哪里? +在这家医院? +人呢? +别激动,等一下 +路克! +路克! +路克? +他没事,让他去吧 路克? +先生,回床上躺好 我儿子呢? +快说我儿子在哪儿! +他在206病房 +路克? +路克? +我们会照顾令郎的 +医生,让他去吧 路克? +他会清醒吗? +现在不能确定 +以暴制暴是没完没了的 +你说什么? +以暴易暴 +有时候只是混乱 +世界就是这么乱 +让我和他独处一下 +拜托你 +我去外面等 +路克,你听得见吗? +能不能动动手指? +儿子,听得见就动动手指 +路克,我知道 +你觉得 +我对你的关爱不如对你哥哥 +天哪,我 +我不知道,或许最初是这样 +你也知道的 +我和你妈 +刚有了布兰登的时候 +他实在是 +我觉得他很了不起 +他简直是个奇迹 +但我一直都很了解他 +后来又有了你 +不知道,我本来以为 +你会是布兰登的翻版 +我期望你像他一样 +结果你不是 +你们截然不同 +和他不一样,和我不一样 +你真的是很像 +太像你妈了 +顽固又 +太过于热情 +你妈就是这样 +她是我这辈子最重要的人 +你也是 +我只是想跟你说我爱你 +我好爱你 +我爱你哥,也爱你妈 +我爱我们全家人 +我 +对不起 +我以前未能当个好爸爸 +对不起 +我没能保护你们 +可恶 +你快去叫医生来. +医生! +奥云 +帮我查一个电话号码 +对,5550128 +去查别的资料库,想办法查到 +存款也要领出来? +对,全部都要 +所有的钱 +连孩子的教育基金也要? +喂? +尼克,我是奥云 +电话号码查到了 +是酒吧,叫四朵玫瑰, +尼克,出了什么事? +要不要我打电话求助? +谢了,再见,奥云 +尼克? +我要找比利达利或他的朋友 +西班牙语, +我说我不会讲英文啦,你聋子哦 +懂了吗,老兄? +西班牙语, +我把你的猪脑袋砍下来 +寄给你妈 +说不定她会认得出你 +但我很怀疑,老兄 +操你娘的! +干! +干! +死开! +放开我 +告诉我比利达利在哪里 +现在就说 +快说! +你不会想找到比利达利的 +我有事要找他 +好,放开我 +放开我! +西班牙语, +他的同伙海可住在附近113号 +他通常晚餐时间会啪药 +可以了吧? +西班牙语, +还有一件事 +我要买枪 +有事吗? +我要买枪 +我不认识你 +我是从四朵玫瑰,,来的 +据我猜测 +你应该不属于这地头吧 +别让我闻到你有恐惧的味道 +敌人才要恐惧 +恐惧 +和子弹 +超多子弹 +这是最凶悍的一把枪 +点357口径 +保证头也打爆 +这把枪不错 +这是标准的点45口径 +火力超强 +这是血海深仇才要用 +这把枪的火力是天王级的 +既是大炮,也是正义之剑 +带这把枪去圣地 +就可以展开圣战了 +不管是哪一把枪 +都保证能让你把烦恼 +抛到九霄云外 +那一把呢? +这把? +好,我要这把和这几把 +买这些枪要花你3千大洋 +你有很多深仇旧恨吗? +这是5千美元 +那你就是我的VlP了 +再送你一些配件 +因为我直觉你很需要 +你身上散发出一股杀气 +真的 +你是想杀我儿子比利的那家伙? +他是你儿子? +所以祖也是你杀的啰? +你杀了我的小儿 +现在又要追杀比利 +对,我要杀他 +比利不是什么好东西 +他做的事都与我无关 +有人想要某人付出代价 +以消胸口的一股怨气 +那找比利就对了 +杀了那个混蛋 +看看会不会影响我心情 +咱们当爸爸的私下讲 +我也是知道的啦 +去找他吧 +我忍他够久了 +你又是个付现款的好顾客 +但别以为我会跟你说比利在哪里 +敢问我就杀了你 +去忙你的吧 +愿上帝与你同在 +一整袋的枪也与你同在 +布兰登的东西, +我要专心想着痛 +那个 +搞什么? +搞什么? +你是谁? +你? +不是被我们干掉了吗? +搞什么? +给我滚出去! +比利人呢? +去你的 +我的牙呀! +王八蛋! +快说他在哪里 +办公室 +是什么鬼地方? +废置的精神病院 +我们在那里做毒品 +在冥府街的桥边 +听见没? +冥府街! +打给他 +幸好你爸有赞助你车子 +你就不用溜冰来这里买毒给你妹 +她光顾了我好一阵子 +我也经常去光顾她 +干他妈的 +海可,你这个没用的家伙 +我这礼拜第2次 +帮你收烂摊. +比利! +那个王八蛋没死,比利 +你在胡说什么? +他说你死定了 +那又怎样? +就这样啊,操你妈的 +今晚要惹什么事? +你又想干嘛? +好像赶着去投胎 +你知道帮你擦屁股有多累吗? +我还得安抚那个送钱上门的阔佬 +叫他杀了你,你以为我爽吗? +你根本就不懂 +我很关心你的事 +因为会拖累我 +你还需要什么指示吗? +不用了,谢你喇老豆 +我去拿车了 +搞什么? +妈的! +阿狗! +那个王八蛋来了! +往你那边去! +我只脚! +阿狗! +快! +去追那个王八蛋! +我杀了你,王八蛋 +去抓他! +快啊! +快点 +欢迎来到地狱, +你去那里 +你知道你会死在这里! +妈的 +瞧瞧你 +你跟我们没两样 +我把你变成杀人魔了 +准备好了? +我今晚连动的力气也没有 +你走过去看着我死 +但我知道你心里更难受 +因为爱把你击垮了 +对,承认吧 +我不孤单 +有新年新希望吗? +不对,你知道妈妈很完美 +这倒是 +我没什么新希望啦 +5、4、3、2、1! +新年快乐! +新年快乐! +好吧,你今年有什么期望? +你儿子 +他在动了 +应该能撑得下去 +可否忘怀旧雨 +永远不再想起? +法国大文豪米歇尔. +德. +蒙田曾经说过 +我认为吃活人比吃死人 +更加野蛮 +至理名言 +当你还是个不谙世事的孩子时 +大人们告诉你世界是由坏人和好人构成 +我一直喜欢坏人 +我喜欢疤面人胜过超人 (疤面人是美式漫画中的坏蛋) +对摩尼教徒的我来说 +堕落的哲学比起仁义道德 +更加能激起我的兴趣 +其实 善恶并非那么泾渭分明 +就我来说 +我送人一个拇指表达其实是仁慈 +三周前 +你给了我个"D" 我从没有得过"D" +你的作业只能够得"D" 我也是那么给分的 +我们正在做爱 伊莱 +-什么 你和我做爱是为了得到个好成绩 +-当然不是 +我给你们留道题目 +一个加利福尼亚奶农谋杀了三个年轻女孩 +在她们的尸体上留有性侵犯的痕迹 +然后吃掉了她们大腿上的一部分肉 +你们认为这个奶农疯了吗 +见鬼 当然 +给你你们一点提示 这个问题 +没有例如"是" "否"或者"见鬼 当然"这样的确切答案 +空的 空的 空的 +你今天有买过一杯咖啡吗 +出于好奇心 你拿这个破杯子 +来我们这儿蹭牛奶喝 有多久了 +-三天了 +-所以我要没收你的杯子 +别 +巴克利・迈克尔逊 人文社会学博士生 +这感觉太爽了 +伊莱・迈克尔逊博士 化学教授 (当博士好爽啊 叫兽 我说的对不对? +) +周一把作业交到我桌上 要至少三页 +谢谢各位 +莎拉・迈克尔逊 医学博士 刑事精神分析专家 +你等等 如果你下次再迟到 +我会把你带出去 扭断你的大拇指 +你懂了吗 +麦克斯・马瑞尔 侦探 +这个冷漠的世界 就是为了让你的灵魂堕落 +这至始至终不会改变 +这个冷漠的世界 就是为了让你的灵魂堕落 +这至始至终不会改变 +这个冷漠的世界 就是为了让你的灵魂堕落 +这至始至终不会改变 +这个冷漠的世界 就是为了让你的灵魂堕落 +这至始至终不会改变 +撒迪厄斯・詹姆斯 自学成才者 (笝衾衄跺腴悝盪腔賸... +×姊×b犒) +我正处于人生的低谷 简直是地狱一般 +你也看到了 我正在做我的博士论文 +每周只有父亲给的$35零用钱 你明白吗 +我最多只能花$4.40买... +一杯摩卡咖啡和一根法式面包 +我时常会想起塞缪尔・约翰逊的诗句 +为什么给"你的挚爱"一个"D" +柏斯・查普曼 研究生 +柏斯 我非常失望 +你居然期望我会特殊照顾你 +胡扯 伊莱 胡扯 +你这是故意的 +你故意给我"D"好让我和你上床 +"这里记载着学者们的生活中的遭遇 +辛劳 嫉妒 贫困 赞助人和牢狱" +-你好 请说 +-办公室来了个电话 +好像你的丈夫获得了诺贝尔奖 +那会让他更加自大的 +不是每天都有人赢得保龄球奖杯的 +更别提诺贝尔奖了 +巴克利・迈克尔逊 你父亲刚打电话过来 +他说他获得了诺贝尔奖 +真他妈的走运 +祝贺你 +祝贺你 迈克尔逊博士 你真棒 +谢谢 谢谢 +如果这件屋子里还有人质疑我超凡的智力 +或者质疑能够当我的学生是多么幸运 +那么现在可以吻我的屁股了 +-祝贺你 伊莱 +-恭喜你 伊莱 +干得好 +伊莱 我觉得这证明了诺贝尔奖不是什么大众流行奖 +这是一件好事 西蒙 +如果诺贝尔奖是大众奖的话 你也可以去参选了 +-你看上去真棒 +-谢谢 +这领带没问题吧 +是不是有人忘记告诉老爸这只是半正式场合 +他知道的 +这么穿是为了显示他很特殊 +吃的东西在哪里 +我们每个人都为你感到自豪 伊莱 +我得了诺贝尔奖这真是一件美事 +因为现在你会发现想解雇我是很困难的 +我从没有威胁要解雇你 伊莱 +我是一个科学家 哈维 +根据我对周围的观察表明 +这里没有人喜欢我 +我喜欢你 +伊莱 听着 我也是个科学家 +根据我的观察到的证据 +早在我要解雇你之前就有人在诋毁你 +有人说你和小女生 我什么都没看见 +你真的认为那个化学系的追星小丫头 +和我那个顽固又专制的老爸有一腿? +-老妈 +-不 等等 +很高兴你能来 柏斯 我喜欢你这件衣服 +离期末考试还有两周 +如果考试没得"A" 我就把关于 +我和你的那些丑事抖出去 +不幸的是 +这将是第一次诺贝尔奖得主牵涉性丑闻 +对 对 不过考虑到卡尔顿・ 格瑟特博士和他的密西西比男孩们 +我认为他们才是第一个性丑闻事件 +我可是认真的 +不就是个"A"嘛 你得到了 +我喜欢你这样 柏斯 +你是多么淘气 +当我从斯德哥尔摩回来 +我何尝不想立刻撕破你的衣服 +欣赏你娇小柔美的身躯 但现在 你得离开这里 +她担心期末考试前两周 +我会缺课 +因为那两周我正在做去斯德哥尔摩前的准备工作 +看到吗 西蒙 至少我的学生喜欢我 +谢谢各位今晚出席 你们有人出于自愿 +有人出于被迫 +但无论怎样 明天我就要去接受我的诺贝尔奖 +我的妻子 莎拉 会和我同行 +这些年来她是唯一 +一个能够忍受 +我的臭脾气和怪癖的人 +因为他对"疯狂"的定义是那么狭窄 +她居然说服陪审团认为杰弗瑞・达摩没有疯 +于是杰弗瑞・达摩精神失常的辩护被驳回 +他也被送入了监狱 +莎拉 +我们会和我们的独生子巴克利同行 +作为普林斯顿大学 +的优等生 +也就是他证明了我在单分子光谱的研究 +将会是后继无人 +他现在又把兴趣放在了研究食人主义 +还有挑战游戏机记录 +现在他终于知道怎么谋生了 +当然用的不是他那冷门的专业 (这人真欠抽啊) +巴克利 +在1975年当"爱使我们相聚"... +-走吧 我会给你打掩护的 +-谢了 +祝你和那个女孩交往顺利 她的名字是 +这把戏不错 老妈 +9: +00赶到那里 飞机11: +30起飞 +在那一刻我意识到 +通过凝聚相来 +观察单分子光谱 +是可行的 也是必要的 +是的! +是的! +嗅着潮湿的气息 +我感觉自己回到了海边 +在一瞬间 我明白了啄木鸟的思想 +-她朗诵了吗 +-还没有 +山雀! +山雀! +山雀! +山雀! +山雀 +谢谢 +大家好 我叫西提・豪 (好奇怪的名字) +今晚我将朗诵我的诗歌"小老鼠" +西提・豪 诗人 艺术家 +在小老鼠思维 +空间深处的角落里 +邪恶 如同寄生虫一般在此偷生 +你也许会把它当作畜生 把它当作草芥 +你对阿谀奉承假装不理不睬 +但你深知 +在你自身四维空间深处 +的角落 +这是你自身散发腐臭味的黑暗面 +在这绝无仅有的精神渣滓中沸腾 +你还记得我吗 巴克利 +几周前我向你做过自我介绍 +我只是想说你真是 +-天啊 太棒了 +-谢谢 +我有时也能说出完整的句子 +比方说"在那里" +吮吸我的嘴唇 打开你的内心来征服我 +我想有机会能和你谈谈 +一些关于你创作灵感的事或者其它任何什么 +-好的 +-好吧 就像我们现在这样谈? +-当然 +-好的 +我本希望能够请你吃个汉堡或者其它什么 +-可惜我现在身无分文 +-我是个素食者 +那是好事 特别当我不得不吃掉你的时候 +因为素食者比肉食者尝起来美味 +我正在做关于食人风俗的博士论文 +-食人主义 +-没错 +-我周围的人都在贬低它 但还有很多... +-谁这么做? +那些残忍的 思维狭隘的 +父母是共和党? +是民主党 不过其它你都说对了 +你父亲 +我的父亲 +他在我15岁时发现了我的日记 并把它烧了 +我的诗歌 我的思想 +我的绘画 我所拥有的一切 +都被焚毁了 +天哪 +-你之后再怎么面对他? +-不必了 他后来死了 +"在受伤孩子的眼中 +爱和痛交融在一起" +"地狱为孩子而生" 帕特・本纳塔的歌 (格莱美音乐奖得主) +自行车呢 +靠 +我开车来的 +-万圣节用的? +-我自己做的 +现在我用它们在十字路口吓唬人 +我试试 +-送给你了 +-算了 你太慷慨了 +我不能接受 +不要摘下来! +它是我送你的 +你一定要戴着 +-你真的是穷的叮当响? +-当然 +证明给我看 我想看你的存款余额 +-你在开玩笑? +-我是说真的 +可你必须要戴着面具 +-我把它送给你了 戴上吧 +-这也太疯狂了 +疯狂只是一种选择 巴克利 +好吧 好吧 +快点 巴克利! +我饿了! +你没有撒谎 巴克利 +我们去我家吧 +我们可以叫木须肉外卖 我付账 +你知道你有多天才吗 +这太棒了 +我觉得作为你所谓的肉食者 你尝起来不错 +我保证你比我美味多了 +来见见马沃 他是个小偷 +-在晚上他会变成一只猫? +-不是 +他就是只小偷猫 +他会偷走你乱扔的东西 +而且让你再也找不到 +这可让我有点儿担心 +巴克利 +我漂亮吗 +毫无疑问 +不要伤我的心 +不会的 西提 我保证 (让我心仪的文艺女青年啊... +) +放松心情 +放松心情 +放松心情 +放松心情 +-我得走了 +-不要 +我今天得去斯德哥尔摩 +上飞机前我会给你打电话的 好吗 +要不在飞机上打 还是打两个吧 +留下来吧 +像昨晚那样抚摸我 求你了 巴克利 +好吧 再过半小时我必须得走了 +我希望他没发生意外 +他没事 可能他有事耽搁了 +他老是迟到 +他很少迟到 在梅雷迪斯之后他就再没约会过 +他和梅雷迪斯那场3分钟的婚姻花了我$20,000 +他们的婚姻保持了一年 +他去见鬼吧 +如果他这么没有责任感 我们就自己出发 +伊莱 +我把墙纸去掉了 +乔治・格斯那 改过自新的强制症患者 +-这里没有墙纸 我很喜欢 +-事实上 +我发现墙纸流下的胶水 +促进了微生物的生长 +这个地方看起来妙极了 乔治 +我喜欢这里 花花草草让这里生机勃勃 +到处都是花粉 +我很... +轿车来了 我们现在要走了 +我会给植物浇水的 +清扫垃圾 +我会确保房子外的灯是亮着的 +-很好 +-我会给你一份详细的报告的 +-谢谢你 乔治 +你能再帮我一个小忙吗 +什么忙 +如果见到巴克利 +你能告诉他票在桌子上吗 +在厨房电话旁的桌上 +巴特 他不是要和你们一起去吗 +我们这会儿找不到他 +我想他随时可能回来 +他可以自己开车去机场 +他可以把车停在那儿 +告诉他我会付停车费 好吗 +我会 我会找到他的 +-谢谢 +-我通常能听到他骑车回来 +因为他把车挂起来时 整个地板都在抖 +-谢谢你 乔治 +-74分钟之后我就得走了 +-好的 +-莎拉 莎拉 +如果我听不到他回来怎么办 +糟了 +鞋子哪儿去了 +查一下帕萨迪纳 出租公司号码 +出租车 快走 +十块 +零钱做小费吧 +妈妈 爸爸 +你好 迈克尔逊家 听到滴声后留言 +巴克利 我是西提 +我就知道你不会像你保证的那样 +给我打电话 因为你是一个伪君子 +昨晚 你发誓你没有钱... +但是 今天早上你却有钱打的 +巴克利 我从窗户里都看见了 +既然没钱的事是撒谎 其他估计都是谎言... +我们的关系就此结束吧 +我不会犹豫 再见 巴克利 +你好 迈克尔逊家 听到滴声后留言 +你在笑吧 巴克利 +我能听到你的声音 +你是个没有理想 没有灵魂的人 +所以你才会如此对我 没有丝毫愧疚 +你好 这里是 +够了 你他妈有完没完 +巴克利 我是你爸爸 我很生气 +我希望你为改掉那些 +让人愤怒的行为 +-都是有必要的 +-哦 你生气了 +去死吧 伊莱 我更生气 +我那让人愤怒的行为才会是更加必要的 +乔治・格斯那 +改过自新的强迫症患者 +现在面临这一个巨大个人挑战 +你能做到的 乔治 你能做到的 +忘了巴克利 忘了那担心他的母亲 +开着你那环保电力车去上班吧 +好样的 乔治 好样的 +在比立沃斯精神病院呆这么多年 +总算有点儿用 +如果是占线 那么他就在家里 +该死 伊莱 我说过我们要开通呼叫等待 +-我们得登机了迈克尔逊先生 +-是迈克尔逊博士 +思沃森女士是在礼貌的告诉我们 +飞机就要起飞了 +而我 作为一名乘客 想上飞机了 +迈克尔逊博士 +机长说他很荣幸... +你能搭乘这班航班 先生 +是因为我赢得了诺贝尔奖... +还是因为我激起了他潜在的同性恋倾向? +我很抱歉 +他脑袋里面装的都是那些天才想法 +而教养之类的已经没有地方装了. +所以才导致了她这种让人生厌的反社会行为 +带我去见机长 +他可以亲自告诉我 +先生 请您坐下来 +安全带的指示灯亮了 +恭喜您获奖了 +远远 +离开 +单身 激情 +看我们起舞 +感受它的热度 +撞击你的灵魂 +它是如此美妙 +它是如此清晰 +在这无边的夜 +它是如此美妙 +它是如此清晰 +在这无边的夜 +它是如此清晰 +它是崭新的世界 +你能感觉得到 在这无边的夜 +它是如此美妙 +它是如此美妙 +你好 伙计 +我不知道你在说什么 +什么 +离这儿四英里才有电话 +还好我对电气很在行 +我希望你喜欢橙子 屋子后面有一棵树 +上面结了好多橙子 +接住了 这儿 +你得趴下来吃 +趴下来吃 +你好 请给我接伊莱・迈克尔逊博士 +救命 救我 求你救救我 +-安静 +-快救救我 +你能稍等一下吗 +救命 救我 求你救救我 +别再吵了 +媒体见面会四点... +在瑞典皇家科学院举行 +然后在那儿 我们会参加一个招待会 +还有一个鸡尾酒会 +-然后是晚宴 +-行了 行了 去哪儿无所谓 +我只想问 +这个冰箱里的东西谁付账 +是我 还是那该死的硝化甘油的发明者 (这里指诺贝尔) +伊莱・迈克尔逊 诺贝尔获奖者 +你好 博士 你儿子在我手里 +要想他活 除非我收到200万没记号的钱 +得了 巴克利 别耍了 +赶紧给我滚到瑞典来 +-我想和他说话 +-不好意思 +如果不想迟到 我们最好马上出发 +他挂了 +我要你的拇指 +-什么 +-我们会把你的拇指寄给他 +-这样他才会明白事关重大 +-不 +不 不要 +大拇指 不要 +它是灵长类特有的手指 +它不仅是个手指 更是人区别于野兽的标记 +不 不要 求你了 +求求你 我求求你 不要啊 +不要 听着 让我给他打电话 +他是我的爸爸 他会听我的 +我爸爸是个混蛋 但他会听我的 +求你让我和他说 +他确实是混蛋 但他会听我的 让我打给他 +我会让他明白事情的严重性 +我会让他知道你是认真的 +那是什么 +爸爸 千万别挂 +哦 这回没有调音器 听起来好多了 +不 那不是我 那是 +绑架我的人 +求你 听我说 好吗 +我被一个野蛮人绑架了... +如果你不答应他的条件... +他会切掉我的拇指还会杀了我 +爸爸 我有麻烦了 +麻烦 你确实如此 +你知道我得付多少钱 +改签原本免费来斯德哥尔摩的机票? +我很害怕 +别耍我了 快坐飞机滚过来 +越! +快! +越! +好! +你在教堂干什么 +-妈妈在吗 我和想她说话 +-你想... +爸爸 爸爸 +切拇指时间? +-是巴克利是吗 +-他在路上 +-希望他能及时赶到 +-他真的在路上吗 +他让我向你问好 莎拉 +他在教堂干什么 +哪有父亲这样对待自己的骨肉的 +他是个坏父亲 现在得了诺贝尔奖... +-情况只会更糟 +-他不配得诺贝尔奖 +是的 不错 我知道 +我相信肯定有别人更适合这个奖项 +不 那不是他的成果 是他偷的 +也许 你也知道 他是个卑鄙的家伙 +他从谁那儿偷的? +-哈瑞曼・詹姆斯 +-谁 +你父亲的好朋友 他已经死了 +哈瑞曼・詹姆斯是我父亲 +对不起 +真的很抱歉 +-我知道我父亲是个混蛋 +-你懂个屁 +你根本不懂你父亲是个什么样的人渣 +妈的 +珍妮特・波兰尼 计算科学学生 2005年9月拍的 +瑞娜・拉曼尼 地球生物学教授 2006年1月 +海瑟・菲利普斯 行政部门的 +不会吧 +柏斯・查普曼 三个星期前拍的 +那个男人是个畜生 +这是我妈妈 +那时候她已经和哈瑞曼・詹姆斯结婚了 +他是哈佛化学系的毕业生... +他对宽视野显微镜下... +利用激光诱导来观测单分子的... +荧光排放有一套完整的概念 +这是哈瑞曼的实验笔记 72年9月 +第9到16页 +单分子光谱分析的起源? +哈瑞曼・詹姆斯和伊莱・迈克尔逊曾是最好的朋友 +那么 我父亲和你母亲也有染? +当我母亲怀孕了... +哈瑞曼・詹姆斯自杀了 +因为他知道自己没有生育能力 +-我父亲知道这件事吗 +-他当然知道 +-你认识他吗 你见过他吗 +-没有 +等下 那么你是我的... +哥哥 +同父异母的哥哥 +你叫什么名字 +萨德斯... +詹姆斯 +听着 我知道你为什么来 萨德斯... +某种意义上说 拿走他所有的诺贝尔奖奖金 +我甚觉得你是对的 +似乎是为你的父亲哈瑞曼・詹姆斯 +报仇的 +最佳方式 +知道吗 +更好是 让全世界知道谁才应该得那个奖 +-不是吗 +-没错 +你说得都很对 巴克利 +-但现在我需要你的拇指 +-萨德斯 我们是兄弟 +-不 我们是同父异母兄弟 +-求你了 不要 +我想和你一起干 我们是一伙儿的 +一起 做搭档 不要 不要割我的拇指 +上帝啊 +我打赌国王是在他的私人轿车里放屁的 +在很多场合 如果他每晚都那样猛吃 +我打赌他得有个男仆... +而他的职责就是为国王的屁承担责任 +这是什么 +那是下午到的 给迈克尔逊太太的 博士 +是吗 我会有什么东西 +打开看看 别怕 邮寄炸弹的家伙们都在监狱 +你来开吧 +如果想让你儿子活命 准备100万现金 等通知 +哦 上帝啊 +是的 这件事很蹊跷 +我在斯德哥尔摩和乔纳森谈过 +测试结果出来前 +他们不会归还拇指 +-那得多长时间 +-我不知道 +你们可以找个新的容身之所 +现在住的地方太暴露了 +-我们在那儿住了20年 +-好吧 +所以你幸运了20年 伊莱 +现在你的运气用光了 +我走的时候是10: +15 我已经迟到了 +我必须在10: +09离开去上班 +我一直等到10: +15 +我通常都在10: +09离开 +我以为他们说没有警察 +-先生 你们开通呼叫等待了吗 +-没有 +只是一个问题而已 +-探长 +-瑞乐 +我们查了圣盖博谷所有对外开放的教堂 (位于加州 亦称中国谷) +毫无进展 +-对不起 女士 +-比尔 我们得检查一下这些线索 +我在脑子里一遍遍的想 +我肯定他说过 +他要去赤道书店去见一个女孩儿 +她的名字叫... +凯裴拓・希尔还是什么来着 +我们去赤道书店看看 +我没听到自行车的声音 我没听到他进去 +我听了 莎拉 我听了 +我做些吃的给你 你一整天没吃东西了 +-麦克斯 我 我不饿 +麦克斯・马瑞尔的顶级炒鸡蛋 +和烤土司的味道 +会让你饿的 +必须要烤吗 +对于你 可以例外 +-你真好 麦克斯 +-不 +不是对每个人 我为你着迷 +对不起 +但是我很担心 +你知道 那个拇指 还有那些暴力行为 +但也很有可能那根本不是巴克利的拇指 +在洛杉矶 过去三周 +有四宗与拇指有关的案件 +我希望是他的拇指 +如果是别人的拇指... +这个绑架者就真是个狡猾的变态 +他步步为营 +而且不想让俘虏过于痛苦 使自己过得不爽 +所以他理性的 +截掉了某人的拇指... +随机的受害者 +使得他躲藏更加容易 +另一方面 +如果这是巴克利的拇指... +那么这帮人就太稀疏平常了 +他们一定藏身在某处... +和我流着血快崩溃的孩子 +他可能很痛 +可能还大量失血 +使他们快要发疯 +这样就会比较容易 +去找到或阻止他们 +或其他什么的 +但这样巴克利就不能打好高尔夫 +因为那需要大拇指 (好冷的笑话 +-_ +-! +) +我躺在那享受着我的粪便浴 +刺激的芳香迎鼻而来 +生命底线的味道 +早晨的阳光流过百叶门 +我感觉需要洗澡 +很有力 对吧 +凯裴拓・希尔 +听过这个名字吗 +有个叫西提・豪的读过这本书 +-为懦弱贫穷人 +-你认识那个人吗 +哦 这是巴克利・迈克尔逊 +那是他的桌子 +他一天到晚坐在那 +玩他的GBA 乱想一些食人的事 +-食人 +-对 他的正题 +怪人 +我跟他说他爸获得诺贝尔奖 +你猜他怎么说 +"那个婊子养的混蛋走大运了" 你相信吗 +你要是遇到他爸你就会相信 +还有什么吗 +对了 还有辆自行车 +一直放在那 我猜是他的 +-谢谢 +-到我了 +失陪 +大家好 我是克里福德 +我今天带来的诗叫"服毒自杀" +四岁时拜仁第一次小试了一口 +-好像比你的贵75美分 +-无咖啡因 无脂 +无害 低能量 +还有盒麦圈 +-我看上去比你更俗吗 +-便宜? +我花了8.83美元啊 (cheap的双关 译者猜的) +好吧 你想知道什么 +她叫西提・豪 这可能是她的化名 +你猜的吗 +祝他妈的圣诞快乐 +混蛋们 我树底下准备了礼物 +圣诞老人给你们准备了痛苦之餐 +快去给你家买点圣诞蛋糕 +去北极吧 +你他妈的在看我吗 圣诞快乐 +滚吧 混蛋 来坐到我大腿上啊 +小太妹把我的弟弟搞硬了 +嘿 你这个秃头的混蛋 +你他妈在看什么东西 +白痴... +我们来双飞吧 这个圣诞老人很下流 给麋鹿吹箫 +弯下腰来 让我把你袜子装满 (此处过于下流 就不译那么清楚了) +节日快乐 +你好 +-嗨 莎拉 +-嗨 麦格 +现在不是说话的时候 +-你好 +-你给我听好了 +我只说一遍 +你给我准备无法追查的俩百万美元 +钱放在女式衣箱中 +星期六早上把钱放在赖加达・希尔斯商场中央 +九点整 +然后你们就可以打道回府来等我的指示 +到时候我会让你们找到哀嚎悲惨的儿子 +我要是看到警察 我就撕票 +-我想跟我儿子说几句 +-他没事 +我要跟他说几句 我想跟儿子说话 +-妈妈 +-巴克利 +快救我 快把我弄出去 +行了 +我们就去了 巴克利 +两天前 +我给你父母送了根断指 +你给我父母送了根断指 +那你认为我应该怎样使他们相信 +只有你一张拿着报纸的照片 +谁的拇指 +要是我砍的是你的拇指 +你会流很多血 +你就会变得疯狂 +这样对我就没用了 +难道吃死人比截指容易些吗 +巴克利 你做人生观有点问题 +-我会为此不安的 +-只有孩子才不安 +-你说什么 +- 这是派特・百那特说的 +我们跟着他们 然后落网 我们动身吧 +-那是什么意思 +-巴克利没有大拇指了 +这点我已经知道 +事情就像我预想的这样 +当你爸在客厅踱步 +考虑是否该放弃你时 +帕撒德那的警察闯入了错误的房子 +别动 卧倒 +错了 +此时 商场 +我靠 +我跟他们说了在完成构架前不准货运 +我们现在怎么办 +建筑组正在准备 +周六晚上的啤酒 +和星期天的休假 +不用 我来付 +用直升飞机将迷你轿车放入厅中央 +于此同时警察搞了一次不让他们更丢脸的行动 +他站的位置 无路可逃 +想要穿过去 +简直就是没门 +7: +50时 +西南门就会给雇员打开 +给了我几乎一小时来重装车 +什么都没有 +不管如何 +我们不能暴露身份 +巴克利・迈克尔逊的死活 +完全取决于我们行动的准确性和耐心 +他在干吗 +我哪知道 +等下 跟上她 +我要把这个送过去 +等会 +你觉得把这带到商场去 +还要把这个箱子丢进那个 +千百人投入奖券的车中是一件很爽的事情吗 +这是我们的全部啊 +这不是我们的全部 我们还有儿子 +他才是我们这个世界上的最爱 +-现在没有选择 +-莎拉 +混蛋 +我只能告诉你 +高处不胜寒 +先生 +不是天才 你真的很幸运 +你儿子会没事的 迈克尔逊博士 我们都是天才 +早上九点整 +你可以听见200多尖叫的人拥进来 +抢着成为前百名来获得Mp3 +一旦东西丢进去 好戏就正式开始了 +只是一次尽情的狂欢 +这只是其中的一件事 +只是其中的一晚 +只是其中一美好的旅行 +只是其中一晚 +怎么会这样 +头 他开走了 +只是其中的一件事 +这是个圈套 他们在干吗 +电话不时响起 只是其中的一件事 +只是其中的一晚 +这只是其中一次奇妙的飞行 +这很有趣 但只是其中一件事 +我猜它在往走西北跑 +我们跟住他了 他无路可逃 +没人在车里 他是谁 +只是其中的一件事 +停下来 别 +只是其中一件事 +只是其中一晚 +只是一次漂亮的飞行 +登月之旅 +只是其中的一件事 +这只是其中的一件事 +只是一次疯狂的狂欢 +只是其中的一个电铃 不时的响起 +只是其中的一件事 只是其中一晚 +-天啦 +-哦 +只是其中的一件事 +只是其中一次狂欢 +只是其中一个电铃 不时响起 +只是其中一件事 +只是其中一件事 +只是其中一次狂欢 +只是其中一个电铃 不时响起 +只是其中一件事 +只是其中的一晚 +只是一次难以置信的飞行 +这很有趣 但是只是其中一件事 +我把荧光灯修好了 +他们在不停的闪 +回去 快 +我抓到他了 +头 你来看看吧 +你真是反复无常 +所以你被选中 +你真是反复无常 +所以你被选中 +全在这了 +一百万一份 +天啦 这钱真他妈的多啊 +这将是我一生中最高的成就 +这个比第一次伊利安・赛泽 +给我吹箫的钱还多 +她是第十届高阶乐队吹大号的红人 +比我第一辆车还贵 +比我第二次吹箫工资还好 +但那次没拿到工资 我妈找到我了 +它比你的婚礼用费还高吗 +那个蓝眼专业修俄语的妞 +梅雷迪斯 马 +-斯? +-你他妈怎么知道梅雷迪斯的 +-我就是知道 +-你他妈还知道什么 +-还知道... +我知道不能勃起 +所以她就到别处觅食了 +算心理补偿 对吧 +嗯 +-兄弟不应有秘密 +-操你妈 +操 +操你妈 操你妈 +我拿了钱就回家 +你要是现在就回家 +我就杀了你 +什么 你要杀我 +但是你不会吃我 +你会吗 +-你哪弄的车 +-跟拿到上一辆在一个地方 +星期六 教堂 人们都忙这做礼拜 +-你偷的 +-别搞的像犯罪似的 +过来 +你好 +现在 +-吞下去 +-什么 +当他们找到你 他们会搜你身 +你现在吞下去之后就会拉出来 +滚你妈的 +你要是不吞下去以后拉出来 +我就从你后面塞进去 +随你 +你现在要是花其中的一分钱 +他们就会马上找到你 +我们现在不该再说话 +至少是之后的俩年 +我会想你的 +有个兄弟真有趣 +我根本不需要兄弟 我要爸爸 +相信我 你要是没有伊莱的话会更好 +我妈就是因为我总提起父亲而很讨厌我 +好的 随你 +好的 +你干吗 +你不想让他们怀疑你被绑架是装的吧 +唔哦 +我是凯利・兰格 此刻我正站在 +伊莱・迈克尔逊博士家门口 +他们本是要参加诺贝尔颁奖典礼的 +可这一周诺贝尔奖获得者心里却七上八下 +他们不得不缩短了 +和瑞典皇室的庆典 +来面对这次 +孩子被绑架的邪恶之举 +我钱没了 巴克利也没找到 +更甚至的是巴克利杳无音信 +现在门口这么多媒体 +让我怎么出门 +谁通知他们的 +你好 +我是KLPK的凯利・兰格 +兰格女士 你现在是站在我家门口吗 +是的 +莎拉 把枪放下 +现在迈克尔逊也在线 +她孩子以前也被绑架过 +她说她当时也 +- 兰格女士 +-什么 +我先在拿着把枪正对着你的头 +你他妈的现在要是不 +马上离开 我就开枪了 +天哪 她拿着枪 +要是他通知我们等的话 就另有文章了 +你好 +你妈和我希望你能去医院检查一下 +我们只是想确认下你没事 +我想回家 +好的 我们回家 +天啦 你能看到你回来真的太好了 +见到你我也很很高兴 妈妈 +你的大拇指怎么都没事 +要是真没了 +你才觉得那两百万物有所值吗 +莎拉别扯了 你跟我说说 +送到斯德哥尔摩那根手指是谁的 +如果不是巴克利的 +他们恐吓我要砍我大拇指 +他们总共有几个人 +俩个 +你记得他们长什么样吗 +他们头上套了东西 +粗麻布袋子 当时很黑 +我很渴 他们给我水我甚至都不能喝 +巴克利 你告诉我西提・豪干了什么 +西提 +她和这事儿一点关系也没有 +估计她现在恨死我了 +我们能明天再谈吗 麦克斯 +反正我们抓不着那些人的 +现在他们肯定早就跑了 +跑哪儿去了 +我哪儿知道 +他们又没告诉我逃跑路线 +看看我 +看这儿 +我没注意 +那么告诉我 +你知道西提的真名叫什么吗 +当然 莎隆・豪 +别把她扯进来 麦克斯 +她很脆弱 +而且正对我很生气呢 我答应过要打电话给她 但是没打... +因为我他妈的被绑架了 +-能向我保证吗 +-你是在西提家外被绑架的 对吧 +不是 在这儿 +这儿? +比尔 我们得叫法医过来 +-为什么? +-我们搞错了 +巴克利是在这里被绑架的 +可能就在你们离开之后 +绑匪进到这里? +别跟我说钥匙又放花盆底下了 +我是卡尼帕警官 叫法医过来 +-9.99 +-伟哥改变了我的生活 +我在圣盖博谷 +途乐公司附近的洛杉矶机械工具展会里工作 +我要取点钱到汤米汉堡店 (洛杉矶汉堡老店) +买点儿吃的 那儿整晚都营业 +快告诉我们的观众 +告诉我们接着发生了什么 +我正在用自动取款机 +这时一个带着纸袋面具 +手拿屠刀的人袭击了我 +这个人拿走了我的钱 +和我的拇指 +什么样儿的纸面具呢 +普通的食品袋 上面有星形的眼睛 +像地毯一样的大眉毛 和圆形的大红鼻子 +巴克利 +就像你会在夏天露营时做的事儿 +巴克利 宝贝儿 没什么事儿吧 +嗯 没事儿 +巴克利怎么样了 +说实话他看起来像个混蛋 +要是有什么我和派姆能帮得上忙的 可别客气 +我儿子伊森 在牛津大学教语言学 +他从英国泰晤士报上知道了你的事儿 +他为巴克利感到难过 +还记... +记得他们小时候 +常在一起玩儿吗 +还记得他们骑着车 +一起栽进汤姆森的鱼池吗 +那阻碍了伊森在牛津大学教语言学? +迈克尔逊博士 我很难过 +谢谢 +-看呀 +-来了 来了 来了 +小巫见大巫 +-真是不错 +-是我太残忍了 +我在他答录机中留下了粗鲁的话语 +因为他没有给我打电话让我觉得很受伤 +他保证过会打给我的 +然后他并没打给我 我就想让他觉得痛苦 +因为他让我很痛苦 +他本来要打的 +你不觉得吗 侦探先生 +是啊 +可能是 +-他喜欢我 不是吗 +-是的 +他喜欢我的思想 +-我的作品 +天啊 他喜欢我的胸部 +12月8日你和巴克利 +计划有个约会吗 +没有 他的自行车在书店外被偷了 +他要搭车 +被偷了? +-你把他带回家了? +-没有 +好像是我们先是接吻然后 +突然干柴烈火 激情燃烧 +好像整个世界都不存在了 +只剩下我们的欲火 +和对彼此的渴望 这让我们精疲力竭 (无语了 文艺女青年都不太正常吧) +好了好了 然后呢 +说说你带他回家后的第二天早上 +很奇怪 +-什么? +-他打车走了 +那有什么奇怪的? +如果那晚他一分钱也没有 +那早上哪儿来的钱打车呢? +非常抱歉打搅你 豪小姐 +非常感谢您能抽出时间来见我 +西提・豪原创 +你觉得她和这宗绑架有关系吗 +真是神经病 +但是 那首在赤道书店读的诗 +倒也不是没用的疯话 +"老鼠生活在没有罪恶的星球上" +那是安妮・赛克斯顿的墓志铭 (美国自白派诗人) +是首回文诗 +确实是 +我要吃鸡肉沙拉 +那个我请客 迈克尔逊博士 +毕竟你经受了那么多痛苦 这是我们仅仅能做的一点小事儿 +我还要吃丁骨牛排 三分熟 谢谢你 +-他要来和我们坐一起 +-把那把椅子推开 +给他个机会吧 他到鬼门关走了一趟 +伊莱 我请你吃午餐 +罗比已经请了 把你这顿排到明早如何? +我刚才看见院子里都是记者 +要是再扩大点宣传 +你就能进行巡回演讲来赚钱了 +你认为一个诺贝尔奖 +就会令你臭名远扬 +我... +蜗牛吃我的罗勒呢 +看这些有瘢痕的叶子 +一个星期前这些叶子还是肥厚多汁 很光滑呢 +你什么也没听到 +我是在留意自行车的声音 +但是你从未听到类似挣扎打斗的声音 +我没有注意听有没有打斗的声音 如果我留心听的话 +应该能听到打斗的声音 +-也许我没听到 +-对啊 +我要杀了他们 +杀谁 +蜗牛呀 我要他们去死 +等一下 +你和西提・豪说你的自行车被偷了 +是被偷了 +你的车现在在仓库里 +我把它从赤道书店弄回来的 +不会的 我告诉你那车是被偷了 +我跟你说啊 +你并不是第一个 +用撒点小谎的手段让姑娘上套的人 +我让你离她远点的 +她为你痴狂 +听到你的遭遇之后她哭哭啼啼疯疯癫癫的 +我倒是不担心她 +除非她有需要我担心的地方 +我记得呢 +那孩子只有20美元 +我没有整钱 就找了他14元的硬币 +他很着急 上窜下跳的 +我都数不清了 +乔治・格斯那 +如果他没骑自行车 +我就听错了 +乔治・格斯那 +从柴可沃催精神病院 +转院到比尔沃斯精神病院 +中间还在弗瑞克心理诊所待过一阵儿 +你不是来问自行车的事儿的 对吧 +你要进来吗 +你要到里面来吗 +你要进来吗 +西提 +我以为你不会再出现了呢 +-抱歉 +-我也是 +我好想和你做爱 +我就想让你这样说 +但是 +我不能 +别 我们去别地儿 +我现在和另一个人在一起 +什么 +那你还来这儿干吗 +我想和你说声对不起 +你真是反复无常 +所以你被选中了 +你真是反复无常 +所以你被选中了 +巴克利 +怎么了 +为什么我没想到会发生这儿事 +这边 这边走 +这是壁炉和厨房 +还有浴室 +我本来不想这么快就把它租出去的 +但是我们现在真的缺钱 +他看上去是个不错的年轻人 +很可靠 是做二手车买卖的 +不错 +也许你应该帮他搬东西 +看来他自己一个人能搞定 +你好像不怎么欢迎他 +只是 我的背整天都在痉挛 +自从我被绑架后就一直疼 +我想我真帮不上什么忙 +我还没告诉他乔治在房间里自杀了 +不过好像也不会给他造成困扰 +是啊 有的人就是这么现实 +他在这儿有个很可爱的女朋友 看 就在哪儿呢 +天哪 +我没事儿 +不错的一对儿 +你这么看 是呀 +是的 +真是重大进展啊 真的 +使量子点具有生物相容性 +就能侦测到活细胞中的单分子 +你是做二手车买卖的 +我本来在俄亥俄州立大学化学系念书 +但我... +但我没钱读完 +所以 现在我在汽车行业 +但是你的学识 +可比化学系本科生强多了 +萨德斯就像一颗恒星 +却被周围环绕的 +一堆小行星掩盖了光芒 +莎隆是诗人 +但我是一个自学成才的人 +所以当得知我的新房东 +是伊莱・迈克尔逊博士时 +我兴奋异常 +巴克利连单分子有多大都不知道 +是不是啊 巴克利 +是 +一般来说是的 +很明显取决于分子的结构 +以及原子的数量 +但至少也要和原子 +的键距差不多大 巴克利 +一般是 +一到两埃 (波长单位 一亿分之一厘米) +真不错 +你要有空来我的实验室看看 +应该会对你有所帮助 +真的吗 +太棒了 +你他妈的要干什么 +-他是个好人 +-什么 +我能让他感到骄傲 +我会追随他的脚步 +伴他左右 +-继承他的事业 +-萨德斯 我们可没这个计划 +滚 +他会像父亲爱儿子那样爱我 +抱歉 兄弟 我哪儿也不去 +我要... +滚 +也许该滚的是你 +快点儿 巴克利 我饿了 +快点儿 巴克利 我饿了 +快点儿 巴克利 我饿了 +喂 +早上好 博士 +-看这一桌 +-你干吗不坐下 +博士 +-是请客啊 谢谢你 萨德斯 +-这是我的荣幸 +叫我伊莱 +我会爱上这种烹调做法的 +-除非是个家传秘密 +-我觉得我们是一家人 +包括我吗 +去哪儿 +看起来 +在那个可疑的晚上 你用过取款机 +我是从西提的钱包里拿了20元 +因为你发现自己的户头里只有2.57元了 +我查了银行记录 +你说你从西提那儿偷了20元 +-我没偷 我打了张欠条 +-她可 +一点儿也没有提起过欠条 +你看见她的猫了吗 +她那只猫是个... +贼 +-真有意思 +-什么有意思 +当晚威尔・凯威乐在取款机 +被袭击了 +袭击者头戴纸带子 +割走了威尔・凯威乐的拇指 +-那又怎样 +-纸带球形鼻子的碎屑 +在起居室墙炉里发现了 +凯威乐先生的血迹 +那天早上我回家 +发现壁橱起火了 +-我之前就告诉你了 麦克斯 +-天 +看着我 +你不会觉得我能... +听着挺夸张的 +听着 +你的红靴子 +上面带有威尔・凯威乐的血迹 +-那双鞋我丢了 +-什么时候 +就那晚 在她家过夜那晚 +-可笑 +-什么可笑 +我们在你壁橱的鞋盒里发 +现了鞋子 +埋在最后面 +这怎么可能 +巴克利 亲爱的 我们得谈谈 +好的 +任何感情都无法堪比母爱 +妈妈说服麦克斯给我个机会澄清清白 +也是帮我们自己 +现在我得想出个让萨德斯显原型的办法 +我挺爱她的 +你在这干吗 +她触及了我心中最深的秘密 +你明白那种感觉 +你把她从我身边抢走 +莎拉 +你能告诉巴克利 +离我房子远点 +他闯进你的房间 +是的 +你告诉我一个人在那里自杀 +-可没告诉我你儿子精神不正常 +-他干吗了 +他威胁我 +要知道 很抱歉 不会发生了 +我会跟他谈谈 好吗 我保证 +抱歉 能递给我量杯吗 +抱歉 +我真的很喜欢住在这里 他毁了我的心情 +我想要这上面的指纹 +没打招呼没问好 +虽然不太在乎这些 但是你这样对我感觉很不好 +尽量快给我啊 +就这样 温柔点说话 我很容易征服的 +三年前 莎隆 +也叫西提・豪 +从格里森医院逃走 +因精神病犯罪 +她因活生生烧死父亲而被判罪 +在那里她认识了病友 +萨德斯・詹姆斯 +好像你爸爸和我 +很久以前认识詹姆斯一家 +是联邦调查局工作 不能细谈 +什么时候回来 +要几天吧 +周五晚上在派得森斯家有鸡尾酒会 +我没回来就带上你柏斯小朋友 +老天 +我只是帮她 她有点跟不上进度 +萨德斯・詹姆斯 马瑞尔侦探 +侦探先生 我能帮你什么吗 +巴克利・迈克尔逊曾威胁过你 +他妈莎拉・迈克尔逊告诉我们 +要知道 这孩子 +看上去没什么危害 但是 +我来告诉你他很厉害 +从过去的事情能看出来 +我知道你看出来 +迈克尔逊对莎隆・豪很痴迷 +如果你在乎她 +我会远远带她离开这里 +你好 兄弟 +别担心 我消过毒了 +现在你已经发现西提的爱液了 +她的确挣扎了一下 但是 +她现在 我们叫 +屈服了 +听着 我绑架了我们老爹 +要放他我要一百万 +你慢慢想 我不着急 +品尝西提・豪够我活几个星期 +如果西提的肉吃光了 +我还没有拿到钱 +那时候我会着手 +享用老爸味道略逊的美味 +那得多用点卤汁 +你疯了吗 巴克利 +你也得尝尝绑架的感觉 +开始吧 +哈瑞曼・詹姆斯 +你干了他老婆 偷了他的成果 逼他自杀 +什么玩意 +格莱尼斯・詹姆斯挺漂亮 她跟很多男的有一腿 +但我跟她没关系 +你怎么解释这些支票 +什么支票 +这些年你寄给她的支票 +哈瑞曼・詹姆斯是我朋友 +他留下了怀孕的老婆 +一穷二白 +我力所能及的帮助她 +很感人 真的 +我不明白你怎么对她那么好 +你这他妈一辈子没对谁好过 +因为我不帮助那些 +可以自救的人 比如你 +我的怒火狂烧 +我感觉很绝望 +几乎每件事情都这感觉 +知道怎么回事吗 +因为作为你这个混蛋的儿子 +-你说什么呢 +-哈瑞曼・詹姆斯 +跟你诺贝尔奖 +单分子光谱学一点没关系 +他研究的不着边际 我成功了 +你真的觉得 +拿到赎金就完事了 +再说 谁会给你钱 +你妈破产了 巴克利 +萨德斯会交出来的 +-萨德斯 +-萨德斯・詹姆斯 +你儿子 +其实他不是我儿子 就算他是 +他拿什么给你钱 +他只是个汽车供应商 +他上哪里有那么多钱 +萨德斯绑架了我 +如果是真的 +为什么现在才告诉我 +因为现在 萨德斯有证据 +我明白他说的都是实话 +你和哈瑞曼的事情 +看这个 认得吗 +我扫描过 +几分钟就能发到网上 +你跟他聊得不管用 +巴克利是我儿子 我爱他 +但我觉得你应该报警 +不用报警 +他会 +他只是吓唬我们 +送给萨德斯・詹姆斯 +这里签字 +晚安 +我没买什么啊 +烤箱预热350度 +烤制20分钟至到金黄 +什么 +天呢 +变态 +我觉得是西提的 +不会吧 +他曾说要对梅雷迪斯这样 +我没想到他真的会 +我刚找到我爸 +决不允许那个混蛋吃了他 +-你好 +-你好 兄弟 +想要配方吗 是祖传秘方啊 +把钱放在 +莉莉姑妈老米黄色背包 +妈会找给你 +去死亡谷烟囱井的汽车站 +开车6个小时左右 +把钱放在126柜子 +关好 锁上 +偷辆车 回家 +7点整 接电话 +-否则老爸会被煮熟了 +-他妈的 +食人肉说 +朋友就是石棺 +怎么样 +照片 来自萨德斯・詹姆斯 +你玩弄的女性真不合我口味 +妈妈应该配更好的男人 +不是真的吧 +我永远爱你 伊莱 因为你让我生了巴克利 +请相信我 +我只爱过你一个人 +我们离婚 伊莱 我送你去清洁工那里 +这样 +祝你好运 +我不需要好运 +DNA测验证实萨德斯是你儿子 +哈瑞曼的笔记会让你 +诺贝尔奖的荣誉受到质疑 +想象一下那种侮辱 +我打赌是你的主意 整个绑架事件 +不是 巴克利的主义 +聪明孩子 我们的儿子 +估计从你那里遗传来得 老爸 +不敢相信烫衣服的钱 +都要老妈出 +那钱我们五五分 +麦克斯? +是你的 +如果我正是给你 +-伊莱离婚会得到一半 +这样呢 +我们可以一起分享 +我们在蒙大拿州好好生活 +我想继续工作 +也好 +巴克利 +麦克斯 +商场的监控录像 +装得不错 +我得问你 +那个乳房 +有豆子在旁边那个 +杏仁糖做的 +杏仁糖乳房 +一点假血 在洛杉矶什么都能买到 +至于西提 老妈安排回到 +吉尔森医院精神病犯罪处 +我相信在那里她的作品得不到欣赏 +吉尔森医院 精神病犯罪处 +这都是我们的选择 对吧 西提 +有时候别人为我们选择 宝贝儿 +我完成了论文 +发表了 +吃掉死人并不可恶 +这叫循环 +真正的可恶是吃掉活人 +迈克尔逊博士 +我有点不明白 +动力学怎么从 +利用光子技术 +自相关功能演化过来 +光子 是啊 +就像麻疹分子 人类可以 +从地位闪耀 +转化为没人理睬 +之后 +分子与其他分子作用 +很有潜力 +发光 +先生 我不明白? +我今晚有空 +你有空不 +伊莱・迈克尔逊 诺贝尔奖得主 +-=YTET +-伊甸园字幕组=- 翻译: +Sade Eurydice 校对: +ketty 时间轴: +在美国每天有大约一万人死亡 其中大部分都发生在城市里 这样算来每个生活在城市里的人每天都 可能遇到多达1.7个在当天将要死去的人 +-北美统计学会 +-2002年 +在美国平均每天有774例濒死体验 这种体验指的就是一个人在被宣布死亡后 看到眩目的白光然后再被救醒 +-国家死亡研究中心 +-1992 +我保证你会喜欢 +好棒! +哦 Abe 我很喜欢 +你选的 当然你会喜欢 +- 那好 打开你的礼物 +- 好的 +- 你早就知道了吧? +- 才没! +- 他没告诉你? +- 没有 我跟上帝发誓 +有其父必有其子 你们两个都是一个模子里造出来的 +真爱九年 一生不变 +周年快乐 +周年快乐 +你还好吧? +- 你正晚都翻来覆去没有睡好 +- 我知道 我也不知道是怎么回事 +走吧 我们去吃早餐 +- Danny 你饿了吗? +- 当然 +来吧 我们去吃点东西 +Danny 如果你要玩早餐 +至少也要玩得有趣些 +这样 现在如何? +- 你还好吗 伙计? +- 我感觉不太好 +亲爱的 你还好吗? +走吧 我们离开这里 +谁能帮帮我们? +放松 坐下 +让我来帮你 +我很抱歉 +鬼讯号 白光 +3个月后 +其中的原因让我百思不得其解 +为什么我们那一天那一刻 会出现在那个餐馆? +为什么那个疯子会去想杀死 我的妻儿? +为什么不把我也杀死? +我是说 为什么留我一个活口? +为什么? +这一切都... +如此随机 +好样的 +我是国王 +爸爸要抓住你啦 +- 你最好丢得远一些 +- 不要杀死我 +怎么回事? +小心 +我看见你啦 +我爸爸教我游泳 +你觉得爸爸很高还是很矮? +很矮? +我们这些矮人的皮肤非常厚 因为不用拉伸成那么高的尺度 +之所以我的妻儿被杀害... +都是因为我 +因为在他们最需要我的时候 我没能伸出援手 +周年快乐 +我本该救他们 +我本该救他们... +慢动作 +耶! +胜利者 胜利者! +我知道这很让人沮丧 +但我必须要和我的妻儿一起 +再见 +老天啊 Abe 不要做蠢事 好吗? +我马上就过来 +- 这就是用药过量的患者? +- 是的 +- 你知道他吃了多少计量? +- 我不知道 伙计 +用正常含量的盐水输液 +脉搏47 还在下降 +- (心电图)就要成直线了 +- 心率下降 他快不行了 +给他一针阿托品 加大盐水流量 +- 给他整个剂量的单磷酸腺苷 +- 他就要不行了 +- 心脏无收缩反应 +- 看他是否有呼吸 +进行心脏复苏术 快 +- 他就要死了 +- 坚持住 +- 依旧只有心室纤维震动 +- 没有脉搏 +- 你有没有给他整个剂量的单磷酸腺苷 +- 打过 他没有反应 +不要死... +继续心脏复苏术 +没有反应 要不要宣布死亡? +可能是良性心室纤维震动 把电击手柄给我 +充电到200 +充电到200 +让开 +- 充电到300 +- 充电到300 +让开 +充电到360 让开 +- 充电到360 +- 充电到360 +让开 +- 出现窦性心律 +- 血压上升 +终于有反应了 +没事了 我们把你抢救回来了 +检查血液的氧饱和度 +氧饱和度正常 +血压高压140低压60 +嗨 你醒了 +我是Sherry Clarke 你正在圣 +-伊丽莎白医院的深层护理病房 +- 你是我的医生? +- 好过他们 我是护士 +亮光刺眼 +- 我在这里多久了? +- 几天 +Karras医生一直都在监护你 你是他最近的一个病例 +你想看电视吗? +- 有什么想看的节目吗? +- 没有 +哦 伙计 算你好运 这可是我一直都喜欢的电影 +我们终究一死 +你好 Abe 我是Karras医生 我来给你检查一下 +- 你还好吗? +- 我好多了 +还记得你为什么来这里吗? +你当时回天乏术 但是算你走运 当今的医术无所不能 +-我死过? +- 严格来说 是的 你曾见陷入NDE状态 +- 我不知道你说的什么意思 +- 濒死体验 +我是这方面的专家 我费了很大劲 才把你争取到 让我猜猜看 +你看见一团白光将你吞没 好像在竭力让你留下的样子 +是的 没错... +你怎么知道这些? +研究结果显示在十个有过濒死体验的人中 就有有八个说见到过那团白光 +- 很可怕 嗯? +- 那我现在见到的白光呢? +- 可能只是光环 某种后遗症罢了 +- 这算正常吗? +我得说我们早已超越了正常的边界 但是 是的 +症状会随着时间逐步减轻的 直至最终消失 +她和我们在一起 +她和我们在一起 +她和我们在一起 +一切看起来正常 +你的颅内没有肿块也没有 任何不正常现象 +但是过去的这几天中我见到3次 +- 见到什么? +- 白光 +还有一些其他事情 你或许会以为我疯了 但是... +我看见并听见一些类似电流的东西 +EVP的意思就是 电流音频现象 +你所见到的有预知性的白光 就是超自然现象的一种 +- 我已经得到研究此类事情的批准 +- 到底电流音频现象是怎么回事? +就是死者通过干扰如电视和收音机 这样的仪器来发出音频的现象 +有些人认为电流音频现象就是 往生者在我们身边的存在方式 +一些人认为 不过是电磁场的效应 +但另外一些人认为 这是死者在试图和我们交流 +说实话 谁知道呢? +只要我们还没有搞清楚 +他们就会继续为我的 试验投钱 +你在这儿做什么? +这... +就是我的电流音频现象室 +这些录影都被干扰过 因此我录了下来 看看有没有捕捉到什么信号 +看来那是你工作中的重要部分? +那个? +哦 我也不想然那段被干扰 +那是"改变习惯"(猫王的电影) 录下这一段是为研究之用 +我认为自己能从猫王身上 得到些启发 +- 你不太喜欢这一段? +- 不 就是... +我在屏幕上看到那种东西 +电流音频现象的信号只有在被录制下来后 回放的时候才能被肉眼看到 +在猫王最后一个特写镜头 +我看到一个扭曲人型的 静电团出现 +- 你现在要做什么? +- 重新设定并干扰 +看看你还能不能看到那东西 +在那 在那 就是这个 就是这个 +就是这个 我看到的就是这个 +- 真令人难以置信... +- 这到底什么意思? +或许当你有过濒死体验后 你本身就犹如一个调频接收器 +你能看见超自然信号发送 和电流音频现象 与往生者交流等等 +根本不需要这些仪器的帮助 +你的双眼能看到未被人探索过的地域 +你有很多机会看到让人毛骨悚然的东西 +我要走了 我还有和医生的预约 +当然可以 你慢慢办妥那些事情 嘿 我还在收集关于那次枪击事件的剪报 +还有相关文章 +我不想再听到关于我妻儿被 残酷杀害那日的任何事情 好吗? +我只是... +现在无力承受这些事情 +我不愿意 +嗨 Karras医生要我... +怎么了? +Karras医生过世了 +- 什么? +- 他今早心脏病突发 +我很抱歉 +- 那好 所以这个所谓的... +- 电流音频现象 +电流音频现象 +让你开始注意到白光 +当你看到光 你认为那就代表了... +你说它代表了什么来着? +表示有人将要死去 就好像Karras医生 可能几天之后死去 +也可以像公园里那个女人 数小时后死去 甚至可以是几分钟 取决于白光的强度 +我不知道 但是我看得越多 心情就越烦躁 好像扮演上帝一般 +- 我替你担心 Abe +- 但你怎么解释这一切? +如果我说"我不知道"呢? +这个城市里 我们和将死的人擦身而过 这是很平常的事情 +- 我们无从知晓 +- 如果我知道呢 Marty? +万一我知道某人何时会死怎么办? +- 现在你拥有这种超能力 +- 这不是什么超能力 +随便你怎么叫它 但在我看来 就是一套超级英雄的废话 +不要再胡言乱语了 +快动 你这个蠢东西 +快越过铁轨 +- 哦 跟我开玩笑吗? +- 快动 +嘿 +你得离开那里 +快! +离开那里 +快走! +嘿! +- 离开那里! +- 我动不了 我的脚被卡住 救我! +救我! +离开铁轨! +快走! +我很抱歉 +- 什么事? +- 嘿 Marty 我现在过去 好吗? +Abe 呃... +好的 什么时候? +如果我现在就要过去 成吗? +谢谢 +怎么... +? +不会吧 +该死的 +打扰一下 先生 +- 该死的 +- 先生 你得出来 +算了吧 孩子 我掉了几根螺丝 我自己能搞定 +我觉得保险杠支持不住了 你得出来 +我不需要什么毛孩子告诉我 该怎么做 好吗? +你这个到处风流的家伙还是 回到你得雅皮车里... +- 哇哦 +- 你要做什么? +- 保险杠就要... +- 离我远点 +你救了我的命 +不 Marty 我跟老天发誓 我没事 +那好 那好 或许你该... +我不知道 休息一段时间还是怎样 +- 我希望你别太勉强自己 +- 好了 我会考虑的 谢谢 +你今晚救了别人一命 +- 你觉得爸爸是高还是矮? +- 不 不 很矮 +很矮? +- 无意冒犯 +- 我们矮人的皮肤很厚 +因为不必拉伸出高大的尺寸 +是的 的确 +看看这位奥地利教练 看来他就要跳跃了 哈哈 做得好 +该死 +- 两个星期? +还早呢? +- 我知道 +- 我一定会去的 +- 好的 +呃 好了 午餐喝了三杯马丁妮 我差不多要走了 +我会弹点好听的曲子的 +- 上帝啊 +- 我很抱歉 我很抱歉 对不起! +-别担心 你现在就可以补偿我 +- 别这样 +或许我还会让你在酒店房间多逗留一会儿 你明白我的意思吗? +- 嘿 别这样 +- 算了 +好了 这太过头了 +- 停手 +- 打他 +停手 你们会弄伤他的 停手 你们会弄伤他的 +嘿 嘿 +- 嘿! +- 该死 嘿 伙计们! +嘿! +- 救命 救命! +- 我们走 +我就要滑下去了! +求你 拉我上去 +拉我上去 +你还好吗? +是的 他会没事的 +至于我 我就不知道了 +Abe 我今天在办公室还在想你 看来你还是决定要休息一下了 +有时间就电话我 好吗? +再见 +又扮了一天的上帝 +- 喂? +- 嘿 Marty +我正要去看我之前救下的那个年轻人 +- 你要不要去那里见我? +- 好 可以 +很好 还有... +你替我收集的那些东西... +能不能带过来 +我准备好了 +- 好的 没问题 +- 谢谢 +嘿 +嘿 +- 感谢你能来见我 +- 小意思 伙计 +这些东西可能会揭开无数个伤口 +- 你确定你准备好了 +- 我确定 +- 那好 +- 谢谢 +- 嘿 如果有什么需要就电话我 +- 我会的 +嘿 +- 哦 嘿 Dale先生 +- 我来看看Kurt的伤势如何 +缝了几针 几处擦伤和瘀痕 +我们让他留院一晚 确保他没有脑震荡 +但是他会没事的 +谢谢 +哦 不是吧... +不要说话 +你这个贱人 +嘿 嘿 你还好吗? +还好 +还好 +你刚刚救了我的命 +就快成该死的习惯了 相信我 没什么大不了的 +- 老兄 那可是我的命啊 +- 我知道 我不是那个意思 +是你啊 +是的 是的 你是我的护士 +摔坏了 +我很抱歉 +没关系 +- 你受伤了 让我看看 +- 没事 +嘿 +让我帮你包扎 让我多多少少帮你一些 拜托 +不过是表皮伤口 缝几针 加上点抗菌素一切都搞定 +你要么是在看我的戒指 要么就是在欣赏我的胸 到底在看哪个? +- 在看戒指 我... +- 我开玩笑呢 +这是我的旧结婚戒指 我丈夫几年前过世 +所以我想把戒指紧贴在心口 +你一定非常的爱他 +是的 +他是圣心小学的音乐教师 +那些孩子崇拜他 +他用独特的方式俘获了他们的心 不是随便哼哼 而是每年都组织演唱会 +让孩子们学唱鲍伊 平克・佛洛依德 拉什 海滩男孩和简的癖好 +- 凡是你能说得出来的 +- 听上去太神奇了 +是啊 难以置信 +但是最后... +命运突如其来 +某天我们还好端端活着 明白吗? +然后 突然间 他死于非命 +真可怕 +是的 +但是... +我醒来 +突然闪出个念头 +我的心得放开Tommy +总有一天我会跟他重逢 在此之前 +得接受命运的安排 +- 你们有孩子吗? +- 没有 +但为纪念他 我每年举办演唱会 +过几天就有一场 +- 你绝对应该来 +- 也许吧 +给 +拿上这个 仔细考虑一下 +如果有兴趣就打我电话 +嗨 警察来了 +好吧 告诉他们 他们来的真不是时候 +这是结婚周年你买给爸爸的礼物吗? +我可以看看吗? +可以吗? +我猜不是你爸爸指示你这么做的 对吧? +才不是 我不过好奇 我打赌就是他想要的那块表 对吗? +你得让爸爸等 +再说 没剩下几天了 +- 你还好吗? +- 我很好 妈妈 那个人救了我们的命 +谢谢你! +没关系 +没关系 +男子枪杀两人 饮弹自尽 +Henry Caine +不该救 不该救 +不该救 不该救 +不该... +救 +- Julia Caine吗? +我是Abraham... +- Abraham Dale +我就知道你会来 请进 +家里乱七八糟别介意 我们正要搬家 +很抱歉我丈夫杀死了你妻子和孩子 +从没有象Henry这样 脚踏实地 什么都不质疑的人 +那么 嗯... +发生了什么事? +他 嗯... +他经历了濒死体验 +他被一个醉鬼迎面开车撞了 +那晚他一定死过三次 可凌晨被救活了 +一个星期后我们带他回家 +然后怪事频频发生 +他举止诡异 对生与死产生了古怪离奇的想法 +对超自然现象着了魔 +超自然电子异象 白光 预知 诸如此类 +甚至认为自己可以拯救别人 +起先我还能理解 毕竟他差点没命 +但事情开始变得一发不可收拾 +你说一发不可收拾是什么意思? +我带你去看 +看到了吗? +你自己看吧 +警方确认失踪妇女已糟绑架 +摆渡事故死亡人数仍在增加 +如果你救了某人 就要对其负责 +哦 见鬼! +Henry在里面时总会烧断保险丝 +真的? +嗯... +你知道E代表什么吗? +不知道 +介意我拿一部分回去看看吗? +当然可以 这里我什么都不想要 +听着 我为我丈夫所做的再次向你道歉 +我无法相信他到底离死有多远 +- 你说什么? +- 你是什么意思? +- 你说"离死" +- 那么? +你不是指"死"了? +他已经死了? +你不知道? +- Henry还活着 +- 我看到他饮弹自尽 +他活了下来 远在贝尔蒙郡 +精神病院 +我们把他关在楼上 自打从昏迷中苏醒后 +他已经在这里呆了几个月了 +如果你要问 他是绝对不用服法的 +为什么? +老Henry +能看见死人... +别介意 我不过呆这儿 确保你们别闹起来 +我妻子和儿子 +你为什么这么做? +为什么杀害他们? +救之 必杀之 +天哪 你真是疯得无可救药了 +救之 +要负责 +为什么而负责? +后果 +可怕的后果 +什么后果? +如果你允许他介入 这事会没完没了 +你再不能将死者隔开 +死者会骚扰你 直到你纠正过去的行为 +如果你救了人 必须.. +必须杀掉 +第三天 +第三天 +- 第三什么? +- 第三天! +救之 必杀之 +救之 必杀之 +救之必杀之 救之必杀之! +是3 +3和魔鬼的签名有什么关系? +- 嗨 Abe +- 嗨 +我刚排练完跟你说过的演唱会 +就在附近晃悠 +就... +嗨 +- 希望别介意我贸然来访 +- 不不 我不介意 +我不介意... +但是为什么? +你上一次... +喝便宜的葡萄酒是什么时候? +你真是太客气了 但你不用这么做 +我知道用不着这么做 +可我想 +我结婚了 +但还是谢谢你 +Abe 我看过你的档案 +我知道为什么第一次见到你 是在重症病房 +我知道Rebacca和Danny发生了什么事 +那天晚上你救了我 +我很想报答你 +- 我喜欢毛发的颜色 很漂亮 +- 紫色很迷人 但是... +- 跟葡萄酒色相映成辉 +- 没错 +这很好 真的 +非常感谢 +- 为了劣酒和好伙伴 +- 哦 真劣 +你得经常出来透透气 象这样 +只有这样才能从痛苦中解脱 +Danny和Rebecca是我的一切 +Tommy也是我的一切 +你不能就这样向命运低头 Abe +- 来吧 +- 去哪儿? +O'Malley酒吧 +为了弄回买酒的2.5美金 我要跟你玩撞球 把你打得落花流水 +2.50美金? +你被骗了 +八号球 角袋 +好的 +要么双倍加钱要么全部勾销怎么样? +好吧 +大显身手吧 高手 +- 对不起 +- 没关系 +不 我... +不该这么做 +- 至少今晚不可以 +- 没关系 这的确疯狂 但是没关系 +重大新闻 市中心发生交通惨剧 +六人丧生 数人受伤 +一个老人驾驶一辆橙色货车... +...冲进拥挤的候车棚 到目前为止... +你还好吗 Abe? +有关目击者称 货车似乎 故意突然转弯冲向人群 +还好 嗯... +Sherry 我得走了 +- 你认识其中谁? +- 是的 +我会打你电话的 好吗? +救之必杀之 救之必杀之 +"第三天"? +警方发现George Sutter坐在厨房 丝毫不掩饰杀人企图 +妻子和两个孩子的尸体被发现捆绑在床上 由于被摧残得血肉模糊 +不得不借助牙医记录核实身份 +Sutter以前从未实施过家庭暴力 +指控他时无法解释他为什么谋杀了... +Beverly Ann Cloy做了27年的护士 +今晨闷死了14个病人 之后打卡下班 若无其事地... +无法解释Dickon怎么会在驾驶飞机时失控... +导致9人死亡... +- ... +绝对没有理由 +- ... +无法解释 +总是在第三天... +Caine拯救他们之后 +警方还是不明白一个老人 为什么会驾车冲入候车棚 +据称没有明显的隐藏动机 +第三天 基督会从死里复活 +那魔鬼呢? +魔鬼呢? +他第三天干了什么? +第三天究竟发生了什么? +启示录13章18节 +凡聪明的 可以算计兽的数目 +凡聪明的 可以算计兽的数目 +因为这是人的数目 他的数目是六百六十六 +圣经写于罗马时代 对象是讲古希腊语的受众 +所有的希腊文和古希腊文的 +...字母都有相对应的数字" +总是在第三天 +那魔鬼呢? +魔鬼呢? +他在第三天做了什么? +第三天... +在Caine拯救他们之后 +圣经写于罗马时代 对象是讲古希腊语的受众 +"所有希腊文和古希腊文中的字母 都有相对应的数字 +第三天 +第 +-第 +-第三... +天 +-天 +-天... +路西法在拉丁语里是予光者的意思 +天使长被逐出天庭 +因为想为己夺取上帝的权柄 +一度高居天庭的路西法 +现在则是众所周知的 +大地上的魔鬼 +第三天是魔鬼的签名 +我在天桥上救下来的孩子 +今天是第三天 +帮助你那天 我把他送进了医院 我得知道他的下落 +我真的不该这么做 Abe +他似乎拉近了我们的关系 Sherry +是的 +好吧 Kurt Green +- 阿尔弗雷德爵士饭店 +- 阿尔弗雷德爵士饭店 当然 谢谢 Sherry +- Abe +- 是的 +我们之间没什么问题吧? +但愿如此 +- 再见 +- 再见 +- 你好 +- Abe +听着Marty 我明白Caine为什么这么做了 +他觉得非这么做不可 他别无选择 +- 做什么? +- 我救了老人 结果他开车冲进了候车棚 +我救了那个孩子 不知道他要干什么 但我知道 +依据白光拯救某人后的第三天 就会发生恐怖的事情 +- 你听到自己说什么吗 老兄? +- 不 你听着 +也许是路西法 也许是魔鬼 也许是鬼魂 +不管是谁 我都无法阻止它 Marty +在别人受到伤害之前 +你是我的好伙计 对吗? +我爱你 真的爱 +我不愿看你折腾自己而袖手旁观 我不能 我不会这么做 +我们有事要做 我不能一个人干 老兄 我们还有事要做 +就是这个车站 +Marty Marty 我... +再说一遍 我听不见 +救之 必杀之 +必杀之 必杀之 必杀之 +Kurt Kurt +Kurt! +我感到万分抱歉 +我表示诚挚的歉意 +对不起 我道歉 +- 哇 哇! +- 趴下! +他有枪! +我们走! +- 放下枪 +- 到另一边去 到另一边去 +- 别紧张! +- Kurt! +快走! +现在! +我抓住他了 我抓住他了 +- 保持冷静! +慢慢离开大楼 +- 请这边走 +等等 Kurt! +Kurt 怎么了? +Kurt! +Kurt! +第三天 +你要你立即下楼 拨打911 +为什么? +我认为你不该救我 +7: +30 +Sherry +必杀之 救之必杀之 +救之必杀之 救之必杀之 杀 杀 +你来了 +- 我为你提心吊胆 +- 为什么? +我听说酒店发生的事了 +那个孩子一开始是你救的 可接着... +你一定很难过 Abe +Sherry 我得跟你谈谈 +关于什么? +- 去外面 我们出去谈 +- 你可以在这里跟我谈 +- 我不能当着这么多人的面解释给你听 +- 为什么不? +救之必杀之 +- 这是怎么回事 Abe? +- 必杀之 +- 你得跟我来 +- 你在干什么? +你弄疼我了 +- 我得这么做 +- 做什么? +Sherry 我不该救你 +- 冷静点 +- 你不... +- 冷静点 +- 你不明白 +- 放开她! +- 这不关你的事! +听我说 Sherry! +Sherry! +很多人会死 很多人会死 +很多人会死 很多人会死 +别 别是这儿 其它任何地方都行 +这是菜单 马上为您点餐 +那个害死一大片的老人 你救了他 +饭店那孩子也是你救的 +然后你救了我 +真对不起 Sherry +别难过 +那个人有枪 +警察 放下枪! +照他说的办 先生 没人愿意受伤 对吗? +放下枪! +请阻止这事儿吧 +你... +你得死 +女士 +请别管他了 +救之必杀之 +杀 杀 杀 +把她交给我吧 +杀 杀 杀 +她快昏倒了 把她带出去 +杀 杀 +来 +见鬼! +- 我从没碰到过这种事 +- 记下时间 给她打镇静剂 +下午7: +29分 +- 注射2cc +- 让她住嘴 +究竟怎么回事? +第三天 +Tommy +你还好吗? +来这里 +鬼讯号2: +白光 +-=结束=- 谢谢观看 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- 本论坛字幕仅翻译交流学习之用 禁止任何商业用途否则后果自负 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- +-=YTET +-伊甸园字幕组=- 翻译: +Sade Eurydice 校对: +ketty 时间轴: +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- 本字幕所有权益归制作人所有 纯属翻译爱好者交流学习使用 谢绝它用,否则一切后果自负 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- +片名: +皇家卫兵 +在古代的摩呵婆罗多时代... +部落里有个小男孩... +想学习射箭术 他想拜崇高的大师德鲁格瑞亚为师 +可德鲁拒绝了他 +他是王子和国王的指导者 怎能教地位卑贱的人呢? +小男孩只有回到丛林 +他制作了一尊德鲁的雕塑... +把它当作自己的老师 日复一日地练习射箭术 +一天 德鲁外出打猎 +突然... +他的狗停止了吠声 +七支箭牢牢地封住了它的嘴 +射手能达到如此高超的技艺... +...以致于狗没有疼痛 也没有流一滴血 +不痛苦 不流血... +德鲁万分震惊 这个射手到底是谁? +神射手? +- 你知道是谁吗? +- 伊克洛维亚! +他名叫伊克洛维亚 你的名字也叫伊克洛维亚 +是啊 我的妈妈给我取了这位伟大射手的名字 +- 然后呢? +- 然后 德鲁很困扰 +这个贱民的技艺超过了他最好的学生 王子阿尔杰 +他必须制止 +德鲁说 "孩子啊 你在我的雕塑面前练习... +...要请我当你的老师 你得先付我报酬" +伊克洛维亚笑了笑回答 "无论你要求什么都行 老师" +- 你知道德鲁要求什么吗? +- 什么? +- 伊克洛维亚右手的大拇指 +- 他的大拇指! +为什么? +没有了手指 伊克洛维亚怎么握住弓弦呢? +他永远也无法胜过王子阿尔杰了 +伊克洛维亚没有切断他的拇指吧? +伊克洛维亚只是微笑 然后切断了拇指 献给了他的老师 +不痛苦 不流血... +...不 娜蒂妮 痛之入骨 到处都是血 +毫无畏缩 伊克洛维亚履行了... +...他的誓约 他害怕责任 +- 什么律法? +都是错的 我不 +伊克洛维亚错了 +伊克洛维亚错了 +"我怎么能够把你来比作夏天? +你不独比它可爱也比它温婉 +狂风把五月宠爱的嫩蕊作践 +夏天出赁的期限又未免太短 +天上的眼睛有时照得太酷烈... +它那炳耀的金颜又常遭掩蔽 +被机缘或无常的天道所摧折 +没有芳艳不终于雕残或销毁" +还记得这首十四行诗吗? +你第一次来这里的时候 我读给你听过 +而你送了我这朵花 +它现在都枯萎了 +"但是你的长夏... +但是你的长夏永远不会雕落 +也不会损失..." +妈妈在叫伊克洛维亚 +亲爱的儿子啊 上帝保佑 皇后恢复了知觉 +至今忧伤包围着我 +只有借这笔纸以安慰自己 +只有借这些信件 才能与我的心交谈 +工作之余总是太寂静 +除我之外 就只有城堡的砖墙 +我的存在只为了保护国王 +我的生命何尝不是这城堡的一块砖 +而这城墙已随岁月逐渐腐朽 +曾经敏锐的目光也已变得模糊 +可我的的耳朵却依旧灵光 +它在渴望着什么? +或许 是你的声音在呼唤着我 +当年迈父亲的双手开始颤抖... +...他儿子的职责便是伸出援助之手 +你在哪? +我的儿子 +水? +要喝水吗? +我的皇后 +妈妈说 要见伊克洛维亚 +妈妈说 要见伊克洛维亚 +- 喝点水吗? +- 伊克洛维亚 +- 叫谁? +亲爱的 +- 伊克洛维亚 +- 谁? +- 伊克洛维亚 +不! +不! +妈妈死了 现在我们不再需要伊克洛维亚了 +伊克洛维亚! +快来皇后的房间 快点! +召唤我的儿子 伊克洛维亚 +去叫我的儿子! +马上! +爸爸 +你的眼睛怎么了? +很好啊 +好? +一点都不好 王子 +刺眼的阳光几乎让他失明了 +瑞秋带他去看医生 +他说他的眼睛..."有光感" +是的 妈妈在信里提到过 我去找医生谈谈 +- 瑞秋还好吗? +- 她很好 谢谢 +瑞秋一直在皇后身边照料 +她说皇后真的很想念你 +过来 +快点! +一个王子怎么能这样公开展示自己? +一个皇后怎么能这样拉王子的耳朵? +是吗? +她不能吗? +那你想要她怎么办呢? +厉害的小王子 +- 她应该说对不起 +- 对不起 对不起 好了吗? +你回来就好 哈什 +没能在你母亲最需要你的时候出现 真是羞愧 +无论如何 现在说什么都晚了 +来 进去吧 +- 为你祈福 +- 她一直叫你的名字 +直到离开人世 +我说"我在这里! +你的丈夫 叫我的名字" 她却始终没有 +只呼唤你的名字 +你知道那是什么感觉吗? +我感觉... +只呼唤着你的名字... +然后离去 +大哥 +温柔的心被伤透了 她有所恢复 可还是... +去吧 去准备 +葬礼必须在日落前开始 +要束白色腰带 都放在你房间里了 +是这里的习俗 人人都很敏感 我们走吧 +妈妈 你最后的遗言 "要照顾好哈什" +给予了我力量... +...去减轻他的悲痛 +指引我吧 妈妈... +- 他怎么样? +- 为何如此担忧啊? +孩子 +看见那城堡了吗? +你的心上人越不过那么高的城墙... +...他向你问过我吗? +- 他问了 +- 他问什么了? +- "瑞秋还好吗?" +知道了 +上帝啊 请保佑我的女儿吧 +她是如此纯洁 如此天真 +请别伤她的心吧 +娜蒂妮 +娜蒂妮 你在哪儿? +噢 亲爱的国王 娜蒂妮公主在家吗? +娜蒂妮公主不在这里 +噢! +她去哪里了? +她和她的妈妈去神殿了 +请转告她 她的哥哥哈什来看她了 +她会的... +我是说... +我会的 +那好吧 我回伦敦去了 +你真笨! +你真笨! +你怎么没想到? +妈妈死了 我怎么和她一起去神殿呢? +- 我不这么认为 +- 别再说你要离开了 +每个人都离开我 +除了瑞秋 可她每天晚上还是要离开我 +瑞秋在这里呆到晚上 我一个人害怕 +陪着我好吗? +瑞秋 +- 你好吗? +瑞秋 +- 我很好 +你的父亲告诉我 你一直在照顾我的母亲 +瑞秋一直陪在她身边呢... +皇后一直很想念你 +她留这封信给你 +她让你回去再看 +她一定说"照顾好哈什" 对不对? +瑞秋 +亲爱的儿子... +希望当面问候 却只能用信件问候... +...你的归来 +我小心翼翼地喘息 担心生命就此结束 +我多么希望能再抱你最后一次 +恐怕我等不到那一刻了 这封信... +...会告诉你一切 关于你身世的秘密 +儿子 杰维尔国王不是你的亲生父亲 +他一直被蒙在鼓里 +被发现的话 他一定不会将王位传给你... +...你的祖母采取古老的传统... +...只有贤明的人才能继承王位 +在这些众多人才中 +伊克洛维亚同我们一起 +皇后认为伊克洛维亚最可靠 他超过所有别的人才 +我也这么认为 +你和娜蒂妮有个贵族父亲 他就是伊克洛维亚 +我现在告诉你 因为你的父亲很需要你 +他年纪也大了 眼睛也几乎失明 +要是你父亲知道我泄露了这个秘密... +...他会认为我亵渎了我们的誓约 我没有尽到守约的神圣职责 +但我相信 誓约是... +如同古代的摩呵婆罗多所说的 +"誓约 智慧 真理" +誓约生于理由 +誓约也生于智慧 +那便是你的思想灵魂所认为正确的东西 +誓约是你的灵魂所能接受的真理与圣洁 +我已完成了我的誓约 +现在 我的儿子... +你也必须完成你的誓约 +承诺我 你会照顾好你的父亲 +我承诺 妈妈 +我真想砍掉伊克洛维亚的头颅 把它挂在城门上 +他污染了王室的血统 +你以前怎么没告诉我? +我自己都不知道 +这些年 我一直信任我们的母亲 +她说过 她选择的是我 +我信任她 +皇后生下一对龙凤胎 +其中一个患有精神问题的女儿 +即使如此 我也接受了 +可今天我才发现... +...一个没用的保安... +...我孩子的父亲 +他和我的皇后睡了 +杰伊提 他是我孩子的父亲 +我的妻子... +和我的保安! +这些年那么顺从 卑躬屈膝 +他一定乐坏了 +嘲笑我不育 嘲笑我所有的缺点 还有这个 杰伊提! +伊克洛维亚来了 +混蛋! +殿下? +告诉他 杰伊提! +殿下刚才收到一封死亡威胁信 +信里说 我们必须归还农民的土地... +...否则国王就会死于非命 +这怎么可能? +他们没还清欠款 我们收回了他们的土地 +彼克... +他们的头儿 被发现死在... +...铁轨上 还有一封自杀遗书 +可他们控告我们谋杀 那群混蛋! +现在就去 出去! +去通知我的儿子 他父亲的生命处于危险之中 +谁的命? +他的亲生父亲 快去! +杰伊提! +我把真相说出来了 对吗? +不管谁是哈什的父亲... +- ... +都得死 +- 放心吧 哥哥 +明天日落前 伊克洛维亚将躺在他的火葬柴堆里... +...就像皇后那样 +王子 我到处找你 你一个人在这里干什么? +妈妈也是独自一人 伊克洛维亚 每个人都抛弃她 +你愿意和我们在一起吗? +- 她会因此而高兴的 +- 你得回去了 +你的父亲收到了一封死亡威胁信 +我的父亲? +我有父亲吗? +你见过我的父亲吗? +我想见他 +想告诉他 我和妈妈在这里很寂寞 +想告诉他 我很想念他 他会来陪我们吗? +对他来说 妈妈算什么? +无关紧要? +他力不从心? +我们走吧... +...王子 +我很想哭 伊克洛维亚 +却哭不出来 +你能给我力量吗? +可以吗 +儿子 别这样伸出你的手 +如果我握紧了你的手 会招来灾难的 +那次决定性地甄选... +你的母亲和我形同陌路 直到最后 +我们决定 不让我们的孩子知道... +...我是孩子们的亲生父亲 +娜蒂妮无邪的笑声... +击碎了我的心啊 +我多么想抱着她大声呼喊 "我是你的爸爸啊" +但这是绝不允许的 +绝不 +哈什! +你在哭吗? +哈什 +为什么? +别哭啊 你想妈妈了吗? +傻瓜 她一直在我们身边 我们有好多的妈妈啊 +一,二,三,四... +想见见她们吗? +看看? "妈妈在排灯节" 她可爱吗? +"妈妈的生日" 你看啊 +"妈妈在寺院" +"闪闪发光的妈妈" +还有这个是... +不... +不是这个 +- 画错了的 +- 给我看那张画 +不! +很恐怖的 +- 有血 +- 好吧 乖 +告诉我 怎么回事? +这个秘密不能传出那个房间 他会杀死我的 +- 谁? +- 我不能告诉你 +要是这个秘密离开那个房间 他就会杀死我的 +哪个房间? +要是这个秘密离开那个房间 他就会杀死我的 +哪个房间? +现在 这个秘密绝对不会离开妈妈的房间了 +但是门是打开的 +你紧张吗? +巴布鲁 +别担心 我们生在民主主义社会 这些国王不过是纸娃娃 +我的警棍远比他们的剑有势力 +嘿 巴布鲁 看见那城墙了吗? +我的祖父被那城墙活埋了 +就像剪断开幕式上的绸带一样... +...这些国王杀死我们贱民以求好运! +见过我的祖父 卡洛维加尔 +若不是因为想念伊克洛维亚... +...我也不会坚持到现在 +进去吧 +先生 还记得我吗? +我是帕努 帕努加尔 达南加尔的儿子 +上帝保佑你 +还记得那个市集吗? +我就是接到铃铛的男孩 +还记得吗? +你那时好厉害 我整晚都没谁这 +我当时就想 长大以后要和你一样厉害 +现在的我 警察长官帕努加尔 +谢谢你 先生 +我真想再看一次你的精湛技艺 +可以吗... +求你了? +我不确定现在能否做到 孩子 +尝试一下 +先见过陛下 走吧 +就一会儿 答应我? +好吧 来 +那些该死的农民发疯了 他们威胁要杀了我 +做笔录了吗? +巴布鲁 +别以为我不了解状况 陛下 +为什么有麻烦的国王 只敢藏在巨大的官邸? +他害怕愤怒的农民? +难道他不知道这有多懦弱? +你胆敢嘲弄我? +别忘了 我是这里的国王 +而你只不过是... +- 贱民? +我不想谈这个 +民主社会里 歧视就是一种犯罪 +是哪个法案规定的? +巴布鲁 +不管哪个法案 手铐会说明事实 +世世代代 我们制定法律 你胆敢在这里跟我说手铐? +我们统治了两千多年了 +而我们因此受苦五千年 +我的祖父 被这城墙活埋了 +算你走运! +我是那些贱民的孩子 他们的手都被切下来... +...只因为摸了一下圣洁的书本 +受够了历史! +你的保安得跟我离开一个小时 +一小时? +陛下 民主的意思 就是自由意志 明白? +很多警察在茶摊 糖果店也有 +用他们来换这点时间 不愿意? +先告辞了 +可以吗? +先生 +- 现在就开始吗? +- 别太早放弃啊 帕努 +你怎么看待一个贱民成为高级官员? +- 巴布鲁 蒙眼罩! +- 我不需要 +太阳光够刺眼的了 +带上眼罩 看上去更令人佩服 +那好吧 +准备好了吗? +- 是的 +我们睁着眼睛都无法做到 而你带上眼罩也行 +淹没... +...我的父亲为保护国王溺水 +我在湖水边找了他一整晚 +后来妈妈来了 +- 儿子 +这是属于你父亲的 现在由你来保管它了 +从这一天起 他会时刻陪伴着你 +今后 你只有一个誓约 保护好你的国王 +违反誓约的话 我们家族就没落了 +如同坚强的伊克洛维亚 你必须坚决顺从你的誓约 +那天以后 她叫我伊克洛维亚... +...而我父亲的武器 也成为我唯一的武器 +没人知道这件事 我也布知道为什么要告诉你 +我知道为什么 因为我们俩都一样 +先生 国王收到威胁信的时候你在场吗? +没有 只有他的弟弟杰伊提在那 +就是住在红瓦平房那儿的人 在铁路附近的? +再见 先生 +伊克洛维亚快来陪你了 那时候 你会很快乐了 +我该怎么办 我的皇后? +你总是给我指引 +我该给杰伊提打电话吗? +陛下还没有打电话来 +"陛下..." +每次你一叫"陛下" 我就血液沸腾快发疯了 +要是哈什也让我这么叫他 我会用枪爆他的头 +尤迪 我看起来怎么样? +"陛下""如你所愿 陛下" +你怎么叫得出来 我都不好意思叫他叔叔 +你叫了他多久的叔叔? +27年了 +- 52年! +52年的"是的 陛下" "好的 陛下" +"你的心愿就是我的职责" "我的陛下" +你好 杰伊提 +- 是的 陛下 +警察刚才来过了 +好的 陛下 我们半小时后到 +现在什么时间? +- 下午5: +25 +快了四分钟 请调一下 +我们下午6: +10见 陛下 6: +10准时 +爸爸... +有客人 +吹走了 吹走了 瑞秋的风筝没了! +切断它! +把风筝线切断! +瑞秋故意输给娜蒂妮 娜蒂妮很高兴 +瑞秋是个好女孩 奥迈克 +你把她养育得那么好 +- 很艰辛啊 +每日忙碌 来回为皇室开车... +...我都没注意 小女孩就变成大姑娘了 +她很可爱 我担心她以后会嫁谁 +一切顺其自然 奥迈克 +马斯克曼先生... +...告诉你吧 +要是你有个英俊的儿子... +...我就不担心了 +他们坠入爱河 我们就是亲戚了 是吧 +瞧! +王子来了 +让我看看 +国王怎么对待这么优秀的儿子? +皇后死后 他一直很孤独 +真想给他一个拥抱 +父亲 +不 小王子 别叫我父亲 +我没有权力 我只是个卑微的保安 +我也很想抱抱他 +可是我不能 我没有权力去做 +我只是个卑微的保安 +你把她照顾得很好 谢谢你 +看见她高兴 我也开心 现在你来了 那我先退下了? +请等等 +你还记得妈妈唱的那首歌吗? +月亮颂? +- 是的 +能为我唱一曲吗? +在这儿? +现在? +- 拜托 +我很想念妈妈 +听见什么了吗? +只能用望远镜看看 马斯克曼先生 不是听 +她在唱歌 +"我的孩子 我的月亮" +"柔软的微笑 我的月亮孩子" +"轻轻地走来..." +"... +我的眼眸是你的天空 在这里快乐直到永远" +"轻轻地 噢... +柔柔地" +"乘着风 乘着云 还有满载的微笑" +"微笑吧 我的月亮孩子!" +"柔软的微笑 我的月亮孩子" +"轻轻地走来..." +"... +我的眼眸是你的天空 在这里快乐直到永远" +"柔软的微笑 我的月亮孩子" +"在这里快乐直到永远" +殿下传召你们两人,马上过去! +马上? +要去哪里? +"吾可否将汝比作夏日璀璨?" +"汝可是更加温婉,惹人怜爱" +王后最爱这首十四行诗 +莎士比亚写的 +她去世的时候还在听它 +"吾可否将汝比作夏日璀璨? +汝可是更加温婉,惹人怜爱" +"狂野之风摧残五月蓓蕾娇媚" +"夏日匆匆离去,毫不停留" +EKlavya,你想在哪里火葬? +殿下? +我也不愿这样想,可要是你死于意外 +你希望在哪里火葬? +殿下... +我想在我的家乡Dhachigam +那怎么行! +你忠心侍候了我们这么多年 +你的火葬将在皇家之地 +挨着你的王后 +趴下,殿下 +杀了他! +杀了他! +你在磨蹭什么? +快杀了他! +你聋了吗? +立刻杀了他! +遵命,殿下 您的心愿就是我的职责 +殿下... +殿下... +殿下,他们抓走了我的弟弟 他们说我们谋杀了国王 +他们要绞死我们的儿子 -他们叫我们是农民 +可我们甚至没有足够的土地来做自己的墓地 +他们先是夺走了我们的土地 现在又夺走我们的儿子 +我们曾试着抗议 可他们却杀了我们的带头人BhiKu +还宣称那是自杀 殿下,请听我们说 +我们是被冤枉的,这是个阴谋 +够了! +我们再也不能忍受了! +这骆驼是谁的? +这骆驼是谁的? +回答我! +Rajjo? +我会娶Rajjo为妻 +愿您赐福于我 +我可以进来吗? +这儿现在是你的家了,Rajjo 你可以自由来往进出 +谢谢 +谢什么? +谢谢您让我的父亲含笑而去 +您的结婚承诺让他走得很安详 +我看见了他的微笑 +可现在他已经不在了 +我不想用那个承诺绑住您 +Rajjo,我... +- 请听我说完 +并不是我不想嫁给您 +在我还是孩子的时候 我就梦想着能做您的新娘 +梦想着我们能够在一起 +爸爸总说我太天真 +可我仍然抱着这个信念 +我的眼前总是浮现着... +...我的梦想因您的爱而成真的情景 +而不是您的施舍,或您的怜悯 +现在可以轮到我说了吗? +Rajjo... +为什么妈妈信任地将她最后一封信交给你? +为什么Nandini这么喜欢你亲近你? +每当听到你的名字时 她的脸上就会燃起神采 +事实是... +我对你的感觉和她们相同 +可我选择保持沉默 我无法表达自己 +而Nandini可以 +她是这个城堡里唯一心智健全的人 +你知道这城堡... +它对人们来说很可怕 +这里数不清的传统、风俗和礼教让我发疯 +Rajjo... +我已不再是你梦中的Harsh了 +五十年来,你在这城堡里享尽厚待 +可当国王最需要你的时候 你却躲在了骆驼后面! +Uday! +那杀手踢掉你手里的枪时 你在干吗? +唱赞美诗吗? +Uday! +对EKlavya尊重点 +他们家族世代保护着我们的国王 +是刺眼的阳光让他目不能视 火车的声响阻碍了他的听力 +否则那些没用的农民根本不可能接近殿下 +长官,你查到了什么? +我们现在只知道 那骆驼是个叫Hariya的农民的 +他现在正在接受讯问 +敲碎Hariya的膝盖,他就会老实点 +那些人不是农民 +EKlavya? +你看这是几根手指? +才五英尺远你就看不见 你又怎么知道那些人不是农民? +EKlavya的父亲为保护国王献出了生命 +他的故事被唱成民谣传颂 +告诉我,EKlavya 你是怎么躲开那些子弹的? +是那些农民饶了他吧 +他和他们一样 血管里流着低贱的血 +啊! +我明白了 原来是贱民之间的手足情深啊 +长官,请带他出去做个笔录 +先生... +您不能因为口头上的侮辱就拔枪相向 +他们问我 当杀手踢掉我手里的枪时... +...我是不是忙着唱赞美诗 +为了这个,您就想杀了他? +是的! +先生,这是不理智的 为什么? +我并没和任何人说过... +...我的枪被踢掉了 +他们怎么知道的? +您什么意思,先生? +是他们刺杀了我的国王 +我认得他鞋上的钉,就是他们 +你让开! +-先生... +先生,请冷静下来 +把他们交给我 这次让我来,他们是我的那只"鸽子" +你做不到的 给我让开 +我向您保证,我会抓到他们 我会找到方法的 +不管是用旁门还是用正道 +您知道是他们杀了BhiKu,那个农民的头儿吗? +他的自杀遗言是伪造的 他们也会遭到和这一样的命运 +死在同一段铁轨上 带着伪造的自杀遗言 +这是我的工作 我会解决的 +你让开,Pannalal +如果我让你过去了,你会杀了他们 然后因此被绞死 +那又怎样? +我不在乎... +-如果必要,我会逮捕您 +如果必要,我会杀了你 +把枪给我 +血已经流得够多了 把枪给我 +我的盲眼都能看见的东西,您却看不见 +他们谋杀了国王,接下来就会轮到您 +他们会为了王位而杀了您 +外面有辆吉普车 开车离开这里吧 +在你的家乡 每个月你都会收到一份养老金 +你自由了,你走吧 +离开? +带着国王未报的仇恨离开? +我只是这座城堡的城墙 +我的存在只是为了保护国王 我生命中的... +"我生命中的每一刻 都是这城墙中的一块砖" +"可如今,这城墙已随岁月日渐腐朽" +"曾经巡视着这城堡的敏锐目光在渐渐模糊" +您看了我的信? +是的 +这里面的每一个字都是写给我的,是吗? +谁... +是谁告诉您的? +是妈妈 +她违背了誓约! +她犯了罪! +我这辈子都在掩藏这个秘密 +王后犯了罪啊! +- 不 +妈妈并没有犯罪 +看看她的信 +"信乃心之所选" +"信条源自情理" +"那是你的心、你的思想认为正确的东西" +妈妈实践了她的信条 +而现在,我 ,您的儿子... +...将实践我的 +请离开这里吧 +您... +你... +孩子... +你不能这样放逐我 +你不能! +一个儿子怎么能放逐他的父亲呢? +但一位国王... +可以解雇他的皇家护卫 +我,Harshwardhan国王 带着最高的敬意... +命令你,EKlavya 马上离开Devigarh城堡 +是,殿下! +爸爸,回到您那平静的村庄去吧 +好好享受简单而快乐的田园生活 +我会把您接回这城堡的 但在那之前... +我要先清除那些疯狂叫嚣的"信条"和"责任" +然后替换上您孙子欢乐的笑声 +我想看到您的笑容 您以前受的苦太多了 +Harsh! +Harsh,村民们告诉我 你命令EKlavya离开这里 +真的吗? +为什么? +看这个 +嘿! +谁在那儿? +是你? +你来这儿干什么? +Harshwardhan国王他... +- 说什么呢 +大声点! +Harshwardhan国王把我开除出了他的城堡 +我在另找工作 +没有适合我的工作的话 +给您擦鞋也行 +出去! +我说滚出去! +别让我再看见你的脸 +您的心愿就是我的职责 +立刻滚出去! +黑暗已经遮住了我的脸,Udaywardhan +可我却清楚地看见你的 +我看见了杀死国王的凶手的脸 +你的子弹用光了 +现在任何一种声响... +...都会意味着你的死亡 +我仍然能听见你,Udaywardhan 我听见了你的每一次呼吸 +小声点儿 +安静些,别出一点儿声 +安静才能活命 +要是你现在呼吸了 我就能追随着我的信条而行了 +你的死亡就是我的责任 +你怎么来了? +Harshwardhan国王把我开除出了他的城堡 +我给您带了一份离别礼物 +很好,就放在门口吧 +您不看看吗? +我说了... +这里面是什么? +打开 +Uday? +你对我儿子做了什么? +他在哪儿? +Uday在哪儿? +他正沿着铁轨散步呢 您要和他一起吗? +你见过EKlavya笑吗? +没人见过... +除了我 +那时他解救了挨打的我 +谁打你? +-我爸爸 +你一定是干了什么坏事 -不是我,是你 +我? +我干了什么? +你不记得了? +- 我想不起来了 +王后那时揪着你的耳朵 +你大喊着 "一位王后怎么能这样揪住她的王子的耳朵?" +哦,是啊 那时我在大家面前亲了你 +后来EKlavya在爸爸揍我的时候解救了我 +他带我去骑骆驼,还给我番石榴吃 +可我还是很难过 - 为什么? +我说,"我还没有回亲他呢!" +当他听到这句话的时候 +他笑了 +就像现在的你一样 +我得告诉你一些事 +什么事,Harsh? +这是我父亲的枪 +要不是为了你和Nandini +我向神明起誓,我... +你吓到我了 +我还害怕... +怕你会离开我 +绝对不会的,我保证... +等等,先听完我要说的话 +然后再作承诺 +你干了什么? +你杀了我儿子! +他杀了我的国王 +我不过是实践了我的信条 - 实践了你的信条? +干得好! +非常好! +那就去杀了那个下令刺杀国王的人啊 +告诉我他的名字 +我就会带他的头来见你 +你会带你儿子的头来见我? +好! +很好! +是Harshwardhan下的刺杀命令 让我看看你怎么取他的人头! +是Harsh! +Harshwardhan,你的儿子! +砍下你儿子的头吧,实践你的信条 +是Harshwardhan! +别走,Rajjo +求你了 +这是为谁? +你杀了我爸爸,Harsh +你以职责之名杀了我儿子 现在就以职责之名,去杀了你儿子吧 +你说谎! +! +-这是事实,他... +Nandini睡了吗? +是您? +您在这儿干什么? +在等你 +您的脸上有血 +是谁的? +我不知道 +Udaywardhan的... +Jyotiwardhan的... +我把他们都杀了 +而现在您来这里杀我? +是的 +但在我的短剑射中目标之前 +我必须听你说出真相 是你下令杀了国王吗? +是我 +那么我,这个城堡的皇家护卫 +同时也是你的父亲 +必须履行我神圣的职责 +准备受死吧 +我的亲生父亲来杀我 +多么好的死法 +我准备好了 +为什么你要这么做? +我从没想过,你会为了王位杀人... +您竟以为我杀他是为了王位吗? +那就动手吧 把你的短剑刺入我的心脏 +来啊! +您无法投出那把短剑 +因为您知道您的儿子绝不会这么下作 +那是为了什么? +为什么要犯下这么可怕的罪? +为什么? +信乃心之所选 +我选择救您的命 +看看这幅画,他杀了我妈妈 +他用他的双手扼死了她 +您知道为什么吗? +因为她的双唇一直呼唤您的名字 +我知道下一个死的会是您 +您知道您的身价是多少吗? +只有两千五百万! +我用十倍的价钱救了您的命 +谎言! +! +都是谎言! +这不是真的! +我的国王绝不会这么做 +永远不会 +他不会的 +你听到的都是Nandini的一面之词 +这有可能都是她的幻想 +就像她画的那些飞马 +你别想动摇我的决心 +那就别让它动摇啊,EKlavya +切下你的拇指,实践你的信条 +信条? +信条超越所有的疑问 +信条是无可争议的 +如果这时我的信条动摇了 +我家九代人都会在地狱承受焚身之痛 +妈妈告诉我要履行自己的职责 就像那个坚定的EKlavya +你的死亡... +...就是我的职责 +可是,您的手在颤抖 +当年迈父亲的双手开始颤抖 +他儿子的职责就是伸手帮他一把 +我的儿子啊,你身在何方? +- 我迷失了方向 +但我会找回我的路 +我的双手沾染了鲜血 +那是Rajjo父亲的血 +我永远也无法洗刷干净 +就让这些血迹随着我一起燃烧殆尽吧 +好好对待Nandini +告诉她,妈妈一个人太寂寞了 所以我去和她作伴了 +我会告诉妈妈,我履行了我的诺言 +我还要乞求Rajjo父亲的宽恕 +我会完成您的职责 +您的职责... +就是我的死亡 - 住手,Harsh! +住手! +这是我的职责 +我的手也许在颤抖,可我的心很坚定 +我的眼睛看不清了 +可我的耳朵不会遗漏任何动静 +一句... +只要... +...一句话... +我的短剑就会找到你 +爸爸 +爸爸 +我以为您从不会失手 +我没有失手,这是我投得最好的一次 +与其砍下我的拇指 +我选择弄伤那只想要杀死我儿子的手 +你是对的,孩子 +EKlavya做错了 EKlavya做错了 +EKlavya做错了 +错得离谱 +妈妈,请赐予我力量 +让我能追随您的脚步 +愿我的良知能指引我 +我的心要我原谅Harsh +他是做错了事,但他的心灵是纯洁的 +他本想用他的生命来赎罪 +已经有太多的生命消逝,太多的鲜血流淌 +如果必须有人来阻止这一切 +就让我来吧 +请保佑我,妈妈... +让我能减轻他的痛苦,让他忘记... +好好照顾他吧,孩子 +他有一颗高尚的心灵 看看他为我们做了什么... +整个村庄都在这儿感谢他 +他归还了我们的土地 +Harshwardhan国王万岁! +. +万岁... +...Harshwardhan国王! +Harshwardhan国王万岁! +我归还你们的土地是出自我的私心 +我想让我的父亲感到自豪 +今天,你们所有人都是我的见证 +我在此承认EKlavya是我的父亲 +孩子 +爸爸 +警察怎么来了? +- 是来逮捕我的 +是时候抵偿被我杀死的那两条人命了 +恐怕我有些坏消息要宣布 +我已经准备好了,走吧... +- 等等 +今天,我们搜查了Udaywardhan的房间 +在DVD盒里找到了一封自杀遗言 +Bablu... +您看 +真是皇室的耻辱 +他们知道我就快逮到他们了 于是就找了个简单的解脱方法 +他们跳到一辆飞奔的火车前面,自杀了 +真可惜 他们终究还是逃出了我的掌心 +我不会宽恕他们的 +这字挺好的,对吧 +很好 +好极了! +是不是,爸爸? +陛下叫你们俩去 马上! +现在? +去哪儿? +皇后喜欢十四行诗 +莎士比亚 +她去世的时候 我正给她念 +伊克洛维亚 你想在哪里火葬? +陛下? +苍天不容 要是你死于意外... +...在哪里火葬你? +陛下... +我的家乡 +那怎么行! +你服侍了我们那么久 +你的火葬... +应该有皇室的排场 +躺在你的皇后的旁边 +趴下 陛下... +杀死他! +杀死他! +你在干什么? +杀了他! +你聋了吗? +快动手! +是的 陛下 你的心愿就是我的职责 +陛下... +陛下... +陛下 他们抓走了我的弟弟 他们说是我们杀了国王 +他们要绞死我们的孩子 +- 他们说我们是农民 +可我们连耕地都没有 +刚开始没收我们的土地 现在又抓我们的孩子 +我们想反抗 他们却杀死了我们的领袖彼克... +...还说他是自杀的 陛下 听我说 +我们被陷害了 +够了 我再也不能忍受了 +谁的骆驼? +这是谁的骆驼? +回答我! +瑞秋... +? +我会和瑞秋结婚 +上帝保佑你 +我能进去吗? +现在这里是你的家了 瑞秋 你可以来去自由的 +谢谢你 +谢什么? +谢谢你让我的父亲没有留下遗憾 +你的承诺 让他走得很安详 +我看见他笑了 +现在他走了... +我不会要求你实现承诺 +瑞秋 我... +- 请听我说完 +但我并不因你的承诺而高兴 +当我还是个小女孩... +...我就梦想有一天能嫁给你 +现在梦想实现了 +父亲总认为我很天真 +可我有这信念 +我总是觉得... +...你会真的爱我 +而不是你的同情和可怜 +我能说话了吗? +瑞秋... +为什么妈妈信任地把最后一封信交给你? +为什么娜蒂妮那么爱你? +一听见你的名字 她都很高兴 +事实是... +...我也有同样的感觉 +可是我依然保持沉默 我不能表达自己 +娜蒂妮可以 +她是城堡里唯一坦白的人 +你知道这里... +对每个人而言都是危险的 +这座城堡里的各种礼教约束 很让我头疼 +瑞秋 ... +我再也不是你理想中的哈什了 +这五十年来 你在这里享尽了优待 +当国王最需要你的时候 你却躲在驼群后面 +尤迪! +凶手踢掉你的枪时 你在打瞌睡? +尤迪! +你得尊重伊克洛维亚 +他们家族世代保护我们的国王 +他耳聋眼瞎的 +否则那些没用的农民也碰不到陛下 +警官 你查到什么了吗? +我们查出 驼群是一个叫哈瑞亚的农民的 +他正在接受审问 +砍掉哈瑞亚的腿 那能让他老实点 +凶手不是农民 +伊克洛维亚? +这里有几个手指? +这么近都看不见 又怎么判断凶手不是农民? +伊克洛维亚的父亲为保护国王而牺牲 +很多人唱民谣歌颂他 +告诉我 伊克洛维亚 你怎么就躲过那些子弹了? +那些农民饶了他 +同样的贱民 +噢! +我明白了 那些混球的兄弟伙 +警官 请暂时带他出去 +先生... +你不能用枪去反驳 +他们说凶手踢掉你的枪时... +...我在打瞌睡 +因此你就要杀了他们? +是的! +先生 那是不理智的 为什么? +我并没有跟谁说过... +...我的枪被凶手踢掉了 +他们怎么会知道? +你说什么 先生? +他们暗杀了我的国王 +我认出了他鞋上的钉 就是他们 +- 让我去 +- 先生... +请冷静 +让我去解决 这是我的职责 他们是我的"猎物" +你解决不了 给我让开 +我向你保证 我会逮捕他们 不管... +正当与否 +你知道他们杀了农民领袖彼克? +他的自杀遗书是假的 他们会使一样的招 +一样的铁道口 一封伪造的自杀信 +这是我的工作 我会解决的 +让我去 帕努 +要是我让你去了 你杀了他们 会被判绞刑的 +那又怎样? +我不在乎... +- 那我不得不拘捕你了 +那我不得不先杀了你 +把枪给我 +够多的伤亡 给我 +你不清除我眼睛盲的程度 +他们杀了国王 你会是下一个 +他们一样会在驼群后杀你 +外面有辆吉普车 开车离开这儿 +那边会有人接你 +你自由了 走吧 +走? +杀国王的凶手还没有抓到 +我就是这城堡的墙 +我的存在只为了保护国王 每一刻... +..."我的生命何尝不是这城堡的一块砖 +而这城墙已随岁月逐渐腐朽 +曾经敏锐的目光也已变得模糊" +你看过我的信? +是的 +每个字都是写给我的 对吗? +谁... +谁告诉你的? +妈妈 +誓约! +她违反了! +我承诺一生隐埋秘密 +皇后违反了誓约! +- 不 +妈妈没有 +她的信 +"誓约 智慧 真理" +誓约生于理由和智慧 +誓约是你的灵魂所能接受的真理与圣洁 +妈妈履行了她的誓约 +而我 你的儿子... +...也将履行我的誓约 +请离开这个地方 +陛下 +先生 +儿子 +你不能流放我 +你不能! +一个儿子怎么会流放父亲? +而一个国王... +...可以流放王室守卫 +我 哈什国王 以最崇高的权力... +命令你 伊克洛维亚 马上离开这里 +遵命! +父亲 回到那平静的乡村 +享受简单快乐的农村生活 +我会接你回来 那时候... +...我会甩掉脑子里那些发狂的 "誓约"和"职责" +取而代之的是欢庆 和你孙子带来的快乐 +我希望看见你的笑容 你太苦了 +哈什! +哈什 村民们告诉我 你命令伊克洛维亚离开这里了 +真的吗? +为什么? +看这个 +嘿! +是谁? +你? +你来这儿干什么? +哈什国王... +- 说什么 +大声点! +哈什国王让我离开了城堡 +我得另谋职业 +什么工作都行 +我可以为你擦皮鞋 +出去! +给我滚出去! +别再让我看见你的脸 +你的愿望就是我的工作 +快出去! +黑暗淹没了我的脸 尤迪 +可我却看得清你的脸 +我看见杀死国王的凶手的脸 +你的子弹用尽了 +再发出一点声音... +...就是你的死期 +我听着呢 尤迪 我能感觉你的呼吸 +安静 +安静 别出声 +安静才能活命 +要是你再喘息 我就解决你 +让你死是我的职责 +你来这儿干什么? +哈什国王让我离开了城堡 +我给你送来了告别的礼物 +那好 放在门口就离开吧 +你不看看? +我说... +是什么? +打开 +尤迪? +你对我儿子干了什么? +他在哪儿? +尤迪在哪儿? +他在铁轨旁徘徊 要和他一起吗? +你见过伊克洛维亚笑吗? +没人见过... +除了我 +我挨打的时候他帮了我 +谁打你? +- 爸爸 +你一定做了坏事 +- 不是我 是你 +我? +我做了什么? +你不记得了? +- 不记得了 +皇后扯你的耳朵 +你哭喊着 "一个皇后怎么能这样拉王子的耳朵?" +是啊 我当众亲你 +伊克洛维亚帮我不挨爸爸的打 +还带我去骑骆驼 给我买石榴吃 +但我还是很可怜 +- 为什么? +我说"我不会去亲回来了" +他听了... +...就笑了... +...就和现在的你一样 +我得告诉你一些事 +什么事 哈什? +这是我父亲的枪 +要不是为了你和娜蒂妮... +...我向上帝发誓 我... +你别吓我 +我也吓得要命 ...担心你会离开我 +不会的 我保证... +...等等 先听我说... +...然后再承诺 +你干了什么啊? +你杀了我的儿子! +他杀了我的国王 +我履行我的职责 +- 履行你的职责? +干得好! +非常好! +现在去杀了那个人 那个谋划杀死国王的人 +告诉我他的名字 +我去取他的人头 +你去取你儿子的人头? +好啊! +太好了! +哈什安排的谋杀 让我等着你取他的人头! +哈什! +哈什 你的儿子! +砍掉他的头 履行你的职责 +哈什! +等等 瑞秋 +求你了 +为谁? +你杀了我的父亲 哈什 +职责让你杀了我的儿子 为了职责 去杀你的儿子啊 +谎言! +- 是真的 他... +娜蒂妮睡了吗? +你? +你来这里干什么? +等你 +你脸上有血 +谁的血? +我不知道 +尤迪的... +杰伊提的... +我杀了他们俩 +现在你来这里杀我 +是的 +在我的匕首确定目标之前... +...我必须知道真相 是你谋划杀了我的国王吗? +是我 +那么我 城堡的守卫... +...以及你的父亲... +...必须履行我的职责 +准备受死吧 +我的亲生父亲将杀了我... +...多么好的死法 +我准备好了 +为什么这么做? +我无法想像 在驼群那儿你几乎杀了我... +...你认为是我... +...在驼群后面? +继续吧 把你的匕首插入我的心脏 +来吧! +你做不到 +因为你知道你的儿子决不会退缩 +为什么? +为什么这么罪恶? +为什么? +"誓约 智慧 真理" +我救了你的命 +看这个 是他杀了妈妈 +他的双手杀了她 +知道为什么吗? +因为她一直呼唤着你的名字 +我知道他们会杀了你 +而你的王子为你做了什么? +两千五百万! +我给了他们十倍让你活命 +撒谎! +全在撒谎! +不可能是真的! +我的国王不会这么干 +永远不会 +他不会的 +这些只是娜蒂妮的话 +这可能是她的幻想... +...她的胡思乱想 +别试图改变我的决心... +...醒醒吧 伊克洛维亚 +砍掉你的拇指 履行你的誓约 +誓约? +誓约的前提是事实 +誓约站在真理这一边 +要是这一刻我的誓约有所动摇... +...违反誓约的话 我们家族就会被埋葬 +妈妈告诉我履行自己的职责 就像坚强的伊克洛维亚一样 +你的死... +...是我的职责 +可是 你的手在颤抖 +当一个年迈的父亲双手开始颤抖... +...他儿子的职责便是伸出援助之手 +你在哪 我的儿子? +- 我迷失了方向 +但我会回来 +我的双手沾满了血 +瑞秋的父亲 +一辈子也洗不干净 +让这些血迹随我的火葬一起被焚毁 +请照顾好娜蒂妮 +告诉她 妈妈很孤单 所以我离开她去陪伴妈妈 +我可以告诉妈妈 我履行了我的承诺 +我可以祈求瑞秋父亲的宽恕 +我可以完成我的使命 +你的职责... +就是我的死亡 +- 住手 哈什! +别! +这是我的誓约 +尽管我的双手颤抖 但我内心坚定 +我眼瞎但... +...我的耳朵好使 +我... +只要... +...一句话 ... +...我的匕首会找到你 +父亲 +父亲 +我以为你从不会失手 +我没有失手 那是我最好的一掷 +"砍掉我的拇指... +...我的职责是你的死亡" +...那会杀了我的儿子 +你是对的 儿子 +伊克洛维亚错了 +伊克洛维亚错了 +错得那么严重 +妈妈 给我力量... +...追随你的脚步 +给我指引 +我的心告诉我应该原谅哈什 +他支支吾吾 可他的心是纯洁的 +他愿意为此付出一生的代价 +太多的生命消逝 太多的血流失 +必须有人制止 +交给我吧 +祝福我吧 妈妈... +...让我去减轻他的痛苦 帮他忘记所有的难过... +...好好照顾他 孩子 +他有着高尚的心灵 看看他为我们所做的一切... +...所有村民都来感谢他 +他归还了我们的土地 +哈什国王万岁 +万岁... +- ... +哈什国王! +哈什国王万岁! +我归还你们土地有自私的原因 +我想让我的父亲感到自豪 +今天 所有在场的人们都是我的见证人... +...我在此证实 伊克洛维亚是我的父亲 +儿子 +父亲 +警察来干什么? +- 来逮捕我的 +是时候以命抵命了 +恐怕我有些坏消息要宣布 +我准备好了 走吧... +- 等等 +今天 我们调查了尤迪的房间... +...在DVD盒里发现了自杀遗书 +巴布鲁... +看看吧 +皇室的人渣 +他们知道我要抓他们 所以他们选择了更简单的解脱... +...往高速行驶中的火车上跳 系自杀 +太遭了 终究还是逃出了我的掌心 +我心里是怎么都无法宽恕他们的 +先生 好手迹 不是吗? +很好 +太好了! +不是吗? +爸爸 +在远古的摩诃婆罗多时代 +有个低种姓的男孩... +渴望能学会射箭的技艺 他想拜入伟大的导师Dronacharya门下 +可是Drona拒绝了他 +他是王子和国王的老师 怎能去教导一个底层阶级的卑贱之人呢? +男孩儿回到了丛林 +制作了一尊Drona的雕像 +并尊这座雕像为师 然后夜以继日地苦练箭术 +有一天,Drona外出打猎 +突然,他的猎狗不再叫唤 +七支箭矢牢牢地封住了它的嘴 +这位射手的技艺是如此高超 +以至于那狗都没有感受到痛楚 也没有流下一滴血 +没有痛楚,没有流血 没有痛楚,没有流血 +Drona震惊万分 这个技艺高超的射手是谁? +是个不可思议的神射手吗? +你知道是谁吗? +- EKlavya! +他叫EKlavya 你的名字也叫EKlavya +是啊 我妈妈就是照着那个伟大的射手给我取的名字 +片名: +「皇家护卫」 +然后呢? +-然后,Drona很困扰 +这个贱民的技艺 超过了他最好的学生Arjun王子 +他必须得加以阻止 +Drona说"孩子,你在我的雕像前练习箭术..." +"... +把我认作你的导师 这样你就得付给我报酬" +EKlavya笑着说 "您想要什么都可以,我的老师。" +你知道Drona要了什么吗? +-什么? +EKlavya的右手拇指 -他的拇指! +为什么? +没有了拇指,EKlavya怎么拉弓弦呢? +这样他就永远不能盖过Arjun王子的光采 +EKlavya没有切下拇指,对吗? +EKlavya仅仅笑了一下,切下了拇指 然后呈在了他老师的脚下 +没有痛楚,没有流血 没有痛楚,没有流血 +不,Nandini 是痛入骨髓,血流如注 +但是,EKlavya毫不退缩地实践了他的信条... +...他神圣的责任 -这是什么信条? +这个信条是不对的 要是我就拒绝 +EKlavya做错了 +EKlavya做错了 +"吾可否将汝比作夏日璀璨?" +"汝可是更加温婉,惹人怜爱" +"狂野之风摧残五月蓓蕾娇媚" +"夏日匆匆离去,毫不停留" +"苍天之明眸时而过于灼热" +"而其金色脸容亦常蒙上荫翳" +"一切优美之形象总不免褪色" +"遭遇偶然摧折,抑或自然老去" +还记得这首十四行诗吗? +你第一次来Devigarh的时候 我念给你听过 +你还送了我这朵花 +它现在都已经枯萎了 +"而汝之长夏..." +"而汝之长夏却永远繁茂不凋" +"秀雅风姿将..." +妈妈在叫EKlavya +我亲爱的儿子,神明保佑 王后的病情有所好转 +可是阴郁仍吞噬着我 +提笔写信是我唯一的慰藉 +我的心只有通过这些文字诉说衷肠 +剩下的则是沉寂 +我只是这座城堡的城墙 +我的存在只是为了保护国王 +而我生命中的每一刻都是这城墙中的一块砖 +可如今,这城墙已随岁月日渐腐朽 +曾经巡视着这城堡的敏锐目光在渐渐模糊 +而我的耳朵却不会遗漏任何动静 +它在渴望着什么? +也许,是想听到你对我的呼唤 +当年迈父亲的双手开始颤抖 +他儿子的职责就是伸手帮他一把 +我的儿子啊,你身在何方? +水? +要喝水吗,我的王后? +妈妈说,让EKlavya来 +妈妈说,让EKlavya来 +你要喝点儿水吗? +-EKlavya +你要叫谁,亲爱的? +-EKlavya +谁? +-EKlavya +不! +不! +妈妈死了 现在我们不需要叫EKlavya了 +EKlavya! +快来王后的房间,马上! +去传召我儿子,EKlavya +去叫我儿子! +快点! +爸爸 +您的眼睛怎么样了? +很好啊 +很好? +一点儿也不好,王子 +刺眼的阳光让他几乎失明 +Rajjo带他去看了医生 +医生说他的眼睛是... +"光敏性" +是啊,妈妈在她的信里提到过 我会去找医生谈谈 +Rajjo还好吗? +-她很好,谢谢关心 +王后生病时,Rajjo一直悉心照料 +她说王后真的很想念您 +过来 +快点! +一位王子怎么能这样出去抛头露面? +一位王后怎么能这样揪住她的王子的耳朵? +哦? +她不能这样吗? +那你想让她怎么做啊,厉害的小王子? +她应该说对不起 -对不起,对不起,可以了吗? +你回来真是太好了,Harsh +没能在你母亲最需要你的时候出现 你真该羞愧 +无论如何,现在说什么都太晚了 +走,进去吧 +望您赐福 -她一直在叫着你的名字 +然后离开了我们 +我说,"我在这里!" +"你的丈夫就在这儿,叫我的名字" 可她却始终没叫 +只是一直唤着你的名字 +你知道这是什么样的感觉吗? +我感到很... +只呼唤着你的名字 然后... +她就走了 +大哥 +温柔的心总是受伤 她本来有所好转,可还是... +去吧,去准备一下 +葬礼必须在日落之前开始 +去换上白色的缠腰布 已经在你房间里准备好了 +这是这里习俗,他们很在乎这个的 走吧 +王后啊,您在临终前说"好好照顾Harsh" +请您赐与我力量 +让我能减轻他的悲痛 +请您指引我,王后... +他怎么样了? +-怎么这么着急啊,孩子? +看见那座城堡了吗? +你的爱比不过那高高的城墙... +他问起我了吗? +-问了 +他问了什么? +-"Rajjo还好吗?" +看吧 +神啊,请保佑我的女儿 +她是这么单纯,这么天真 +请不要伤她的心 +Nandini +Nandini,你在哪儿? +国王啊国王,Nandini公主在家吗? +Nandini公主不在 +哦! +那她会在哪里呢? +她和她的妈妈去神庙了 +那请告诉她,她的Harsh哥哥来看过她 +她会的... +我是说... +我会的 +好吧,那我就回伦敦去了 +你笨蛋! +笨蛋! +你难道不知道吗? +妈妈死了 我怎么和她一起去神庙呢? +我没想到 -不要再跟我说什么离开了 +所有人都离开我 +只除了Rajjo 可她每天晚上还是会离开我 +Rajjo,晚上留在这里吧 我一个人害怕 +你会留下吧,Rajjo? +你还好吗,Rajjo? +-我很好 +你爸爸都告诉我了 你把我妈妈照顾得很好 +Rajjo一直陪在她身边... +一直一直 +王后真的很想念您 +她给您留了一封信 +她嘱咐说让您独自拆阅 +然后她说:"好好照顾Harsh" 是吧,Rajjo? +亲爱的儿子... +不知我或者我的这封信... +能不能在你回来的时候祝福你 +我每一次呼吸都小心翼翼 深怕那会是我的最后一口气 +我多么希望能活着抱你最后一次 +但我恐怕是等不到那一刻了 只能用这封信... +...来告诉你,你的身世之谜 +儿子啊,Jaywardhan国王并不是你的生父 +他也不可能是 那是神所不乐见的 +当他被发现无法为王国带来继承的子嗣时 +你的祖母求采取了一个古老的传统 +就是从一位贤者那儿得到一个继承人 +这个追求将我们带到了圣河甘戈特里的岸边 +EKlavya也和我们在一起 +王太后信任EKlavya更甚于任何贤者 +我也一样 +你和Nandini有个高尚的父亲 就是EKlavya +我现在将一切告诉你,是因为你的父亲需要你 +他日渐衰老,眼睛也几乎失明 +如果你父亲知道我向你泄漏了这个秘密 +他一定会觉得我亵渎了我们的誓约 我违背了我的信条,我神圣的职责 +但我相信 信条应该是如伟大的《摩诃婆罗多》所说 +"信乃心之所选" +信条源自情理 +信条源自智慧 +那是你的心、你的思想认为正确的东西 +信条是你的灵魂所能接受的真理和圣洁 +我已经实践了我的信条 +现在,我的儿子... +你必须实践你的 +答应我,你会好好照顾你的父亲 +我答应您,妈妈 +我要砍下EKlavya的脑袋 然后把它挂在城门上! +他玷污了我们皇室高贵的血统 +为什么你以前不告诉我? +那时我自己都不知道 +这么多年来我一直相信着我们的母亲 +她说那人是甘戈特里的一位贤者 +我相信了她 +王后生下了双胞胎 +其中有一个 是神志有问题的女儿 +即使那样,我也接受了 +可是今天我才发现 +一无是处的护卫... +他才是我的孩子的父亲 +他和我的王后睡过 +Jyoti,他生下了我的孩子 +我的妻子... +和我的护卫! +这么多年来他是多么顺从啊 卑躬屈膝的 +他心里一定是笑翻了 +笑我的不育,笑我的一切缺点 甚至还有这个,Jyoti! +EKlavya来了 +混账东西! +殿下? +告诉他,Jyoti! +殿下刚才收到了一份死亡威胁 +来人说,我们必须把农民的土地归还他们 +否则国王就会死于非命 +怎么会这样? +他们无法还清欠下的债务 我们就收了他们的土地 +BhiKu,他们的头领 被发现死在了铁轨上 +身上还有一封自杀遗言 +可他们控诉是我们谋杀 这群狗杂种! +你现在就去,去啊! +去找我的儿子,然后告诉他 他父亲的生命正处于危险之中 +谁的生命? +是他父亲的 快去! +Jyoti +我说的是实话,对吗? +不管Harsh的父亲是谁 +他都会死 -这毋庸置疑,大哥 +明天日落之前 EKlavya就会在他的火葬柴堆上被烧焦 +就像我们的王后一样 +王子,我到处找您 您一个人在这儿干什么? +妈妈现在孤身一人,EKlavya。 +所有人都遗弃了她 +你能陪我们坐会儿吗? +她会因此而高兴的 -您现在需要返回城堡 +您父亲收到了一份死亡威胁 +我父亲? +我有父亲吗? +你见过我父亲吗? +我想见他 +告诉他,我孤单地坐在这儿陪着我的妈妈 +告诉他,我想念他 他能来陪我们吗? +妈妈对他来说算什么? +无关紧要吗? +他连这都做不到吗? +我们走吧... +...王子 +我想大哭一场,EKlavya +可是却流不出眼泪 +你能给我些支撑吗? +拜托了 +儿子啊,请别这样伸出你的手 +如果我握住了你,就会招来灾难! +在那次宿命的甘戈特里之旅后 +你的母亲和我就形同陌路,直到最后 +我们起过誓,不会让我们的孩子知道... +我才是他们的亲生父亲 +Nandini天真无邪的笑声啊... +击碎了我的心 +我多想抱着她大喊"我是你的爸爸啊" +但这是决不允许的 +决不 +Harsh! +你在哭吗,Harsh? +为什么? +别这样 你是想妈妈了吗? +她一直在我们身边啊,傻瓜 我们有很多的妈妈 +一,二,三,四... +你想见她们吗? +看到了吗? +"排灯节的妈妈",她很漂亮对吧? +"过生日的妈妈" 你看啊 +"在神庙的妈妈" +"一闪一闪亮晶晶的妈妈" +还有这个是... +不,不是这张 +这张画得不好 -给我看那张画 +不要! +这张很可怕 +上面有血 -好了,好了 +告诉我,那上面是什么? +这个秘密不能传出那个房间 他会杀了我的 +谁? +-我不能告诉你 +如果这个秘密传出了那个房间 他就会杀死我 +哪个房间? +如果这个秘密传出了那个房间 他就会杀死我 +哪个房间? +好了,这个秘密永远不会离开妈妈的房间 +可是门是开着的 +你很紧张吗,Bablu? +别担心,我们生活在一个民主的社会 这些个国王不过是纸老虎 +我的警棍比他们的剑更有威力 +嘿,Bablu 瞧见这城墙了吗? +我的祖父就被活埋在这墙里 +就好像新建筑开幕时要剪断彩带一样 +这些国王杀死我们这些贱民以求好运! +来见过我的祖父,Kalwa Chohar +要不是我渴望再见到EKlavya +我甚至都不愿在这破城堡撒尿! +来吧 +先生,还认识我吗? +我是Pannu,Pannalal Chohar Dhannalal Chohar的儿子 +愿您赐福 +您还记得那次十胜节的集市吗? +我就是那个抓下铃铛的男孩 +想起来了吗? +你那时好厉害 我整晚都睡不着觉 +我那时就想,我要成为像您那样杰出的人 +而现在我做到了 我,警察局长Pannalal Chohar +谢谢您,先生 +只要能让我再看一次您那精湛的技艺 我愿付出一切 +可以吗? +求您了 +我不确定现在还能否做到,孩子 +试试又何妨 +先去见过殿下吧 请进 +等等 您能保证吗? +是的,进来吧 +这些该死的农民都疯了! +他们威胁说要杀了我 +你在做笔录吗,Bablu? +不要以为是我做不好笔录,殿下 +为什么有麻烦的国王要躲在他巨大的宫邸里? +他是害怕那些贫穷赤裸的农民的激愤吗? +难道他不明白"时光变迁,岁月无情"吗? +你竟敢嘲笑我? +别忘了,我是Jaywardhan国王 +而你只不过是个... +-贱民? +我可不愿这么说 +在我们民主的社会里,歧视可是犯法的 +是哪个法案规定的来着,Bablu? +别管是哪个法案了,手铐会说明事实 +世世代代,我们就是法律 你竟敢在这里和我说手铐? +我们已经统治了2000年了 +而我们已经受了5000年的苦了! +我就是那个被活埋在这城堡里的 低种姓男人的孙子 +你是生得命好! +而我是那些贱民的孩子 他们的手被砍断了 +只因为他们触碰了圣书 +真是受够历史了! +你的保安会在一小时内到达 +一小时? +让我来告诉你"民主"的意思,殿下 就是"自由意志",明白了? +有的警察会在茶棚里,有的在甜品店 +集合他们需要时间,不是吗? +我告退了 +可以吗,先生? +现在可以展示给我看了吗,先生? +-你还真不容易死心,Pannalal +您以为一个贱民是怎么变成一个高阶官员的? +Bablu,眼罩! +-不需要了 +这阳光就已让我目不能视 +可那时您就是戴着眼罩的 那让人更印象深刻 +好吧 +准备好了吗,先生? +-是的 +我们睁着眼都无法做到 您戴着眼罩是怎么做到的? +淹溺... +我的父亲为了保护他的国王而淹溺在湖里 +我在湖里找了他整晚 +然后妈妈走了过来 -孩子 +这曾属于你的父亲 现在由你来接受并继承它 +从今天开始,他将通过你重生 +从此以后,你就只有一个信条 就是保护你的国王 +如有违背 吾家九代将会在地狱接受焚烧之痛 +如同那位坚定的EKlavya 你也必须追随你的信条 +从那天以后,她就叫我Eklavya... +而我父亲的利剑成了我唯一的伙伴 +没有人知道这个故事 我也不知道我为什么会告诉你 +我来告诉你为什么 因为你跟我是一样的人 +先生,国王受到威胁的时候您在场吗? +没有,只有他的弟弟Jyoti在 +就是住在那铁轨附近的红房子里的人,是吗? +后会有期了,先生 +日落的时候,Eklavya就会来陪你了 到时你想和他做什么都行 +我该怎么办呢,我的王后? +一直以来你都是我的指引者 +我该不该给Jyoti打电话呢? +殿下还没打电话来 +"殿下!""殿下!" +每次听你叫那个太监"殿下" 我就血液沸腾想发火 +如果Harsh这么对待我 我早拿枪打爆他的头了 +Uday,我看起来怎么样? +"殿下!""如您所愿,殿下!" +你怎么对他叫得出"殿下"? +连叫他"伯伯"都让我觉得羞愧 +你叫他"伯伯"叫了多少年? +27年了 -我叫了52年了! +整整52年都是"是的,殿下" "不,殿下" +"您的心愿就是我的职责,殿下" +喂,Jyoti -是的,殿下 +警察已经来过了 +那很好,殿下 我们半小时内就动身 +你的表现在几点? +-下午5: +25 +快了4分钟,请您调一下 +我们下午6: +10见,殿下 6: +10准时 +爸爸... +我们有客人了 +飞走了,飞走了 Rajjo的风筝飞走了! +我剪了它! +我剪了风筝线! +Rajjo故意输了放风筝比赛 Nandini很高兴 +Rajjo是个好姑娘,OmKar +你把她养育得很好 -恰恰相反啊 +我整日忙于为皇室成员开车 +都没注意到 我的小姑娘何时已经长大了 +她很可爱 我现在担心的是她会嫁给谁 +顺其自然吧,OmKar +神射手先生 +这么多年来我一直和你念叨 +要是你肯结婚,然后生个英俊的儿子 +我就没必要担这个心了 +他们会相爱结婚 我们就会成为亲家了,我亲爱的神射手 +看啊! +王子来了 +让我看看 +国王都作了什么啊? +竟修来这么优秀的儿子 +王后的去世让他很孤单 +我真想给他一个拥抱 +爸爸 +不,小王子 您不能叫我爸爸 +我没有那个资格 我只是个卑微的仆人 +我也很想抱抱他 +可我不能,我没有那个资格 +我只是个卑微的仆人 +你把她照顾得很好,谢谢你 +看到她开心,我也高兴 现在您来了,我就先退下了 +请等一下 +你还记得妈妈唱的摇篮曲吗? +月之歌? +-是的 +你能唱给我听吗? +在这里? +现在? +-求你了 +我很想念妈妈 +你听到了吗? +用望远镜你只能看,神射手先生 不是听 +她在唱歌 +"月亮啊,我的月亮" +"温柔地对着我们微笑" +"缓缓地,缓缓地" +"投给我们一瞥后又悄悄躲起来" +"月亮啊,我的月亮" +"温柔地对着我们微笑" +"缓缓地,缓缓地" +"投给我们一瞥后又悄悄躲起来" +"缓缓地,缓缓地" +"在云彩的掩映下看着我们" +"缓缓地,缓缓地" +"在云彩的掩映下看着我们,轻轻微笑" +"月亮啊,我的月亮" +"温柔地对着我们微笑" +"缓缓地,缓缓地" +"投给我们一瞥后又悄悄躲起来" +"温柔地对着我们微笑" +"投给我们一瞥后又悄悄躲起来" +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- 本字幕所有权益归制作人所有 纯属翻译爱好者交流学习使用 谢绝它用,否则一切后果自负 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- +片名: +皇家卫兵 +在古代的摩呵婆罗多时代... +部落里有个小男孩... +想学习射箭术 他想拜崇高的大师德鲁格瑞亚为师 +可德鲁拒绝了他 +他是王子和国王的指导者 怎能教地位卑贱的人呢? +小男孩只有回到丛林 +他制作了一尊德鲁的雕塑... +把它当作自己的老师 日复一日地练习射箭术 +一天 德鲁外出打猎 +突然... +他的狗停止了吠声 +七支箭牢牢地封住了它的嘴 +射手能达到如此高超的技艺... +...以致于狗没有疼痛 也没有流一滴血 +不痛苦 不流血... +德鲁万分震惊 这个射手到底是谁? +神射手? +- 你知道是谁吗? +- 伊克洛维亚! +他名叫伊克洛维亚 你的名字也叫伊克洛维亚 +是啊 我的妈妈给我取了这位伟大射手的名字 +- 然后呢? +- 然后 德鲁很困扰 +这个贱民的技艺超过了他最好的学生 王子阿尔杰 +他必须制止 +德鲁说 "孩子啊 你在我的雕塑面前练习... +...要请我当你的老师 你得先付我报酬" +伊克洛维亚笑了笑回答 "无论你要求什么都行 老师" +- 你知道德鲁要求什么吗? +- 什么? +- 伊克洛维亚右手的大拇指 +- 他的大拇指! +为什么? +没有了手指 伊克洛维亚怎么握住弓弦呢? +他永远也无法胜过王子阿尔杰了 +伊克洛维亚没有切断他的拇指吧? +伊克洛维亚只是微笑 然后切断了拇指 献给了他的老师 +不痛苦 不流血... +...不 娜蒂妮 痛之入骨 到处都是血 +毫无畏缩 伊克洛维亚履行了... +...他的誓约 他害怕责任 +- 什么律法? +都是错的 我不 +伊克洛维亚错了 +伊克洛维亚错了 +"我怎么能够把你来比作夏天? +你不独比它可爱也比它温婉 +狂风把五月宠爱的嫩蕊作践 +夏天出赁的期限又未免太短 +天上的眼睛有时照得太酷烈... +它那炳耀的金颜又常遭掩蔽 +被机缘或无常的天道所摧折 +没有芳艳不终于雕残或销毁" +还记得这首十四行诗吗? +你第一次来这里的时候 我读给你听过 +而你送了我这朵花 +它现在都枯萎了 +"但是你的长夏... +但是你的长夏永远不会雕落 +也不会损失..." +妈妈在叫伊克洛维亚 +亲爱的儿子啊 上帝保佑 皇后恢复了知觉 +至今忧伤包围着我 +只有借这笔纸以安慰自己 +只有借这些信件 才能与我的心交谈 +工作之余总是太寂静 +除我之外 就只有城堡的砖墙 +我的存在只为了保护国王 +我的生命何尝不是这城堡的一块砖 +而这城墙已随岁月逐渐腐朽 +曾经敏锐的目光也已变得模糊 +可我的的耳朵却依旧灵光 +它在渴望着什么? +或许 是你的声音在呼唤着我 +当年迈父亲的双手开始颤抖... +...他儿子的职责便是伸出援助之手 +你在哪? +我的儿子 +水? +要喝水吗? +我的皇后 +妈妈说 要见伊克洛维亚 +妈妈说 要见伊克洛维亚 +- 喝点水吗? +- 伊克洛维亚 +- 叫谁? +亲爱的 +- 伊克洛维亚 +- 谁? +- 伊克洛维亚 +不! +不! +妈妈死了 现在我们不再需要伊克洛维亚了 +伊克洛维亚! +快来皇后的房间 快点! +召唤我的儿子 伊克洛维亚 +去叫我的儿子! +马上! +爸爸 +你的眼睛怎么了? +很好啊 +好? +一点都不好 王子 +刺眼的阳光几乎让他失明了 +瑞秋带他去看医生 +他说他的眼睛..."有光感" +是的 妈妈在信里提到过 我去找医生谈谈 +- 瑞秋还好吗? +- 她很好 谢谢 +瑞秋一直在皇后身边照料 +她说皇后真的很想念你 +过来 +快点! +一个王子怎么能这样公开展示自己? +一个皇后怎么能这样拉王子的耳朵? +是吗? +她不能吗? +那你想要她怎么办呢? +厉害的小王子 +- 她应该说对不起 +- 对不起 对不起 好了吗? +你回来就好 哈什 +没能在你母亲最需要你的时候出现 真是羞愧 +无论如何 现在说什么都晚了 +来 进去吧 +- 为你祈福 +- 她一直叫你的名字 +直到离开人世 +我说"我在这里! +你的丈夫 叫我的名字" 她却始终没有 +只呼唤你的名字 +你知道那是什么感觉吗? +我感觉... +只呼唤着你的名字... +然后离去 +大哥 +温柔的心被伤透了 她有所恢复 可还是... +去吧 去准备 +葬礼必须在日落前开始 +要束白色腰带 都放在你房间里了 +是这里的习俗 人人都很敏感 我们走吧 +妈妈 你最后的遗言 "要照顾好哈什" +给予了我力量... +...去减轻他的悲痛 +指引我吧 妈妈... +- 他怎么样? +- 为何如此担忧啊? +孩子 +看见那城堡了吗? +你的心上人越不过那么高的城墙... +...他向你问过我吗? +- 他问了 +- 他问什么了? +- "瑞秋还好吗?" +知道了 +上帝啊 请保佑我的女儿吧 +她是如此纯洁 如此天真 +请别伤她的心吧 +娜蒂妮 +娜蒂妮 你在哪儿? +噢 亲爱的国王 娜蒂妮公主在家吗? +娜蒂妮公主不在这里 +噢! +她去哪里了? +她和她的妈妈去神殿了 +请转告她 她的哥哥哈什来看她了 +她会的... +我是说... +我会的 +那好吧 我回伦敦去了 +你真笨! +你真笨! +你怎么没想到? +妈妈死了 我怎么和她一起去神殿呢? +- 我不这么认为 +- 别再说你要离开了 +每个人都离开我 +除了瑞秋 可她每天晚上还是要离开我 +瑞秋在这里呆到晚上 我一个人害怕 +陪着我好吗? +瑞秋 +- 你好吗? +瑞秋 +- 我很好 +你的父亲告诉我 你一直在照顾我的母亲 +瑞秋一直陪在她身边呢... +皇后一直很想念你 +她留这封信给你 +她让你回去再看 +她一定说"照顾好哈什" 对不对? +瑞秋 +亲爱的儿子... +希望当面问候 却只能用信件问候... +...你的归来 +我小心翼翼地喘息 担心生命就此结束 +我多么希望能再抱你最后一次 +恐怕我等不到那一刻了 这封信... +...会告诉你一切 关于你身世的秘密 +儿子 杰维尔国王不是你的亲生父亲 +他一直被蒙在鼓里 +被发现的话 他一定不会将王位传给你... +...你的祖母采取古老的传统... +...只有贤明的人才能继承王位 +在这些众多人才中 +伊克洛维亚同我们一起 +皇后认为伊克洛维亚最可靠 他超过所有别的人才 +我也这么认为 +你和娜蒂妮有个贵族父亲 他就是伊克洛维亚 +我现在告诉你 因为你的父亲很需要你 +他年纪也大了 眼睛也几乎失明 +要是你父亲知道我泄露了这个秘密... +...他会认为我亵渎了我们的誓约 我没有尽到守约的神圣职责 +但我相信 誓约是... +如同古代的摩呵婆罗多所说的 +"誓约 智慧 真理" +誓约生于理由 +誓约也生于智慧 +那便是你的思想灵魂所认为正确的东西 +誓约是你的灵魂所能接受的真理与圣洁 +我已完成了我的誓约 +现在 我的儿子... +你也必须完成你的誓约 +承诺我 你会照顾好你的父亲 +我承诺 妈妈 +我真想砍掉伊克洛维亚的头颅 把它挂在城门上 +他污染了王室的血统 +你以前怎么没告诉我? +我自己都不知道 +这些年 我一直信任我们的母亲 +她说过 她选择的是我 +我信任她 +皇后生下一对龙凤胎 +其中一个患有精神问题的女儿 +即使如此 我也接受了 +可今天我才发现... +...一个没用的保安... +...我孩子的父亲 +他和我的皇后睡了 +杰伊提 他是我孩子的父亲 +我的妻子... +和我的保安! +这些年那么顺从 卑躬屈膝 +他一定乐坏了 +嘲笑我不育 嘲笑我所有的缺点 还有这个 杰伊提! +伊克洛维亚来了 +混蛋! +殿下? +告诉他 杰伊提! +殿下刚才收到一封死亡威胁信 +信里说 我们必须归还农民的土地... +...否则国王就会死于非命 +这怎么可能? +他们没还清欠款 我们收回了他们的土地 +彼克... +他们的头儿 被发现死在... +...铁轨上 还有一封自杀遗书 +可他们控告我们谋杀 那群混蛋! +现在就去 出去! +去通知我的儿子 他父亲的生命处于危险之中 +谁的命? +他的亲生父亲 快去! +杰伊提! +我把真相说出来了 对吗? +不管谁是哈什的父亲... +- ... +都得死 +- 放心吧 哥哥 +明天日落前 伊克洛维亚将躺在他的火葬柴堆里... +...就像皇后那样 +王子 我到处找你 你一个人在这里干什么? +妈妈也是独自一人 伊克洛维亚 每个人都抛弃她 +你愿意和我们在一起吗? +- 她会因此而高兴的 +- 你得回去了 +你的父亲收到了一封死亡威胁信 +我的父亲? +我有父亲吗? +你见过我的父亲吗? +我想见他 +想告诉他 我和妈妈在这里很寂寞 +想告诉他 我很想念他 他会来陪我们吗? +对他来说 妈妈算什么? +无关紧要? +他力不从心? +我们走吧... +...王子 +我很想哭 伊克洛维亚 +却哭不出来 +你能给我力量吗? +可以吗 +儿子 别这样伸出你的手 +如果我握紧了你的手 会招来灾难的 +那次决定性地甄选... +你的母亲和我形同陌路 直到最后 +我们决定 不让我们的孩子知道... +...我是孩子们的亲生父亲 +娜蒂妮无邪的笑声... +击碎了我的心啊 +我多么想抱着她大声呼喊 "我是你的爸爸啊" +但这是绝不允许的 +绝不 +哈什! +你在哭吗? +哈什 +为什么? +别哭啊 你想妈妈了吗? +傻瓜 她一直在我们身边 我们有好多的妈妈啊 +一,二,三,四... +想见见她们吗? +看看? "妈妈在排灯节" 她可爱吗? +"妈妈的生日" 你看啊 +"妈妈在寺院" +"闪闪发光的妈妈" +还有这个是... +不... +不是这个 +- 画错了的 +- 给我看那张画 +不! +很恐怖的 +- 有血 +- 好吧 乖 +告诉我 怎么回事? +这个秘密不能传出那个房间 他会杀死我的 +- 谁? +- 我不能告诉你 +要是这个秘密离开那个房间 他就会杀死我的 +哪个房间? +要是这个秘密离开那个房间 他就会杀死我的 +哪个房间? +现在 这个秘密绝对不会离开妈妈的房间了 +但是门是打开的 +你紧张吗? +巴布鲁 +别担心 我们生在民主主义社会 这些国王不过是纸娃娃 +我的警棍远比他们的剑有势力 +嘿 巴布鲁 看见那城墙了吗? +我的祖父被那城墙活埋了 +就像剪断开幕式上的绸带一样... +...这些国王杀死我们贱民以求好运! +见过我的祖父 卡洛维加尔 +若不是因为想念伊克洛维亚... +...我也不会坚持到现在 +进去吧 +先生 还记得我吗? +我是帕努 帕努加尔 达南加尔的儿子 +上帝保佑你 +还记得那个市集吗? +我就是接到铃铛的男孩 +还记得吗? +你那时好厉害 我整晚都没谁这 +我当时就想 长大以后要和你一样厉害 +现在的我 警察长官帕努加尔 +谢谢你 先生 +我真想再看一次你的精湛技艺 +可以吗... +求你了? +我不确定现在能否做到 孩子 +尝试一下 +先见过陛下 走吧 +就一会儿 答应我? +好吧 来 +那些该死的农民发疯了 他们威胁要杀了我 +做笔录了吗? +巴布鲁 +别以为我不了解状况 陛下 +为什么有麻烦的国王 只敢藏在巨大的官邸? +他害怕愤怒的农民? +难道他不知道这有多懦弱? +你胆敢嘲弄我? +别忘了 我是这里的国王 +而你只不过是... +- 贱民? +我不想谈这个 +民主社会里 歧视就是一种犯罪 +是哪个法案规定的? +巴布鲁 +不管哪个法案 手铐会说明事实 +世世代代 我们制定法律 你胆敢在这里跟我说手铐? +我们统治了两千多年了 +而我们因此受苦五千年 +我的祖父 被这城墙活埋了 +算你走运! +我是那些贱民的孩子 他们的手都被切下来... +...只因为摸了一下圣洁的书本 +受够了历史! +你的保安得跟我离开一个小时 +一小时? +陛下 民主的意思 就是自由意志 明白? +很多警察在茶摊 糖果店也有 +用他们来换这点时间 不愿意? +先告辞了 +可以吗? +先生 +- 现在就开始吗? +- 别太早放弃啊 帕努 +你怎么看待一个贱民成为高级官员? +- 巴布鲁 蒙眼罩! +- 我不需要 +太阳光够刺眼的了 +带上眼罩 看上去更令人佩服 +那好吧 +准备好了吗? +- 是的 +我们睁着眼睛都无法做到 而你带上眼罩也行 +淹没... +...我的父亲为保护国王溺水 +我在湖水边找了他一整晚 +后来妈妈来了 +- 儿子 +这是属于你父亲的 现在由你来保管它了 +从这一天起 他会时刻陪伴着你 +今后 你只有一个誓约 保护好你的国王 +违反誓约的话 我们家族就没落了 +如同坚强的伊克洛维亚 你必须坚决顺从你的誓约 +那天以后 她叫我伊克洛维亚... +...而我父亲的武器 也成为我唯一的武器 +没人知道这件事 我也布知道为什么要告诉你 +我知道为什么 因为我们俩都一样 +先生 国王收到威胁信的时候你在场吗? +没有 只有他的弟弟杰伊提在那 +就是住在红瓦平房那儿的人 在铁路附近的? +再见 先生 +伊克洛维亚快来陪你了 那时候 你会很快乐了 +我该怎么办 我的皇后? +你总是给我指引 +我该给杰伊提打电话吗? +陛下还没有打电话来 +"陛下..." +每次你一叫"陛下" 我就血液沸腾快发疯了 +要是哈什也让我这么叫他 我会用枪爆他的头 +尤迪 我看起来怎么样? +"陛下""如你所愿 陛下" +你怎么叫得出来 我都不好意思叫他叔叔 +你叫了他多久的叔叔? +27年了 +- 52年! +52年的"是的 陛下" "好的 陛下" +"你的心愿就是我的职责" "我的陛下" +你好 杰伊提 +- 是的 陛下 +警察刚才来过了 +好的 陛下 我们半小时后到 +现在什么时间? +- 下午5: +25 +快了四分钟 请调一下 +我们下午6: +10见 陛下 6: +10准时 +爸爸... +有客人 +吹走了 吹走了 瑞秋的风筝没了! +切断它! +把风筝线切断! +瑞秋故意输给娜蒂妮 娜蒂妮很高兴 +瑞秋是个好女孩 奥迈克 +你把她养育得那么好 +- 很艰辛啊 +每日忙碌 来回为皇室开车... +...我都没注意 小女孩就变成大姑娘了 +她很可爱 我担心她以后会嫁谁 +一切顺其自然 奥迈克 +马斯克曼先生... +...告诉你吧 +要是你有个英俊的儿子... +...我就不担心了 +他们坠入爱河 我们就是亲戚了 是吧 +瞧! +王子来了 +让我看看 +国王怎么对待这么优秀的儿子? +皇后死后 他一直很孤独 +真想给他一个拥抱 +父亲 +不 小王子 别叫我父亲 +我没有权力 我只是个卑微的保安 +我也很想抱抱他 +可是我不能 我没有权力去做 +我只是个卑微的保安 +你把她照顾得很好 谢谢你 +看见她高兴 我也开心 现在你来了 那我先退下了? +请等等 +你还记得妈妈唱的那首歌吗? +月亮颂? +- 是的 +能为我唱一曲吗? +在这儿? +现在? +- 拜托 +我很想念妈妈 +听见什么了吗? +只能用望远镜看看 马斯克曼先生 不是听 +她在唱歌 +"我的孩子 我的月亮" +"柔软的微笑 我的月亮孩子" +"轻轻地走来..." +"... +我的眼眸是你的天空 在这里快乐直到永远" +"轻轻地 噢... +柔柔地" +"乘着风 乘着云 还有满载的微笑" +"微笑吧 我的月亮孩子!" +"柔软的微笑 我的月亮孩子" +"轻轻地走来..." +"... +我的眼眸是你的天空 在这里快乐直到永远" +"柔软的微笑 我的月亮孩子" +"在这里快乐直到永远" +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- 本字幕所有权益归制作人所有 纯属翻译爱好者交流学习使用 谢绝它用,否则一切后果自负 +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +-- +片名: +皇家卫兵 +在古代的摩呵婆罗多时代... +部落里有个小男孩... +想学习射箭术 他想拜崇高的大师德鲁格瑞亚为师 +可德鲁拒绝了他 +他是王子和国王的指导者 怎能教地位卑贱的人呢? +小男孩只有回到丛林 +他制作了一尊德鲁的雕塑... +把它当作自己的老师 日复一日地练习射箭术 +一天 德鲁外出打猎 +突然... +他的狗停止了吠声 +七支箭牢牢地封住了它的嘴 +射手能达到如此高超的技艺... +...以致于狗没有疼痛 也没有流一滴血 +不痛苦 不流血... +德鲁万分震惊 这个射手到底是谁? +神射手? +- 你知道是谁吗? +- 伊克洛维亚! +他名叫伊克洛维亚 你的名字也叫伊克洛维亚 +是啊 我的妈妈给我取了这位伟大射手的名字 +- 然后呢? +- 然后 德鲁很困扰 +这个贱民的技艺超过了他最好的学生 王子阿尔杰 +他必须制止 +德鲁说 "孩子啊 你在我的雕塑面前练习... +...要请我当你的老师 你得先付我报酬" +伊克洛维亚笑了笑回答 "无论你要求什么都行 老师" +- 你知道德鲁要求什么吗? +- 什么? +- 伊克洛维亚右手的大拇指 +- 他的大拇指! +为什么? +没有了手指 伊克洛维亚怎么握住弓弦呢? +他永远也无法胜过王子阿尔杰了 +伊克洛维亚没有切断他的拇指吧? +伊克洛维亚只是微笑 然后切断了拇指 献给了他的老师 +不痛苦 不流血... +...不 娜蒂妮 痛之入骨 到处都是血 +毫无畏缩 伊克洛维亚履行了... +...他的誓约 他害怕责任 +- 什么律法? +都是错的 我不 +伊克洛维亚错了 +伊克洛维亚错了 +"我怎么能够把你来比作夏天? +你不独比它可爱也比它温婉 +狂风把五月宠爱的嫩蕊作践 +夏天出赁的期限又未免太短 +天上的眼睛有时照得太酷烈... +它那炳耀的金颜又常遭掩蔽 +被机缘或无常的天道所摧折 +没有芳艳不终于雕残或销毁" +还记得这首十四行诗吗? +你第一次来这里的时候 我读给你听过 +而你送了我这朵花 +它现在都枯萎了 +"但是你的长夏... +但是你的长夏永远不会雕落 +也不会损失..." +妈妈在叫伊克洛维亚 +亲爱的儿子啊 上帝保佑 皇后恢复了知觉 +至今忧伤包围着我 +只有借这笔纸以安慰自己 +只有借这些信件 才能与我的心交谈 +工作之余总是太寂静 +除我之外 就只有城堡的砖墙 +我的存在只为了保护国王 +我的生命何尝不是这城堡的一块砖 +而这城墙已随岁月逐渐腐朽 +曾经敏锐的目光也已变得模糊 +可我的的耳朵却依旧灵光 +它在渴望着什么? +或许 是你的声音在呼唤着我 +当年迈父亲的双手开始颤抖... +...他儿子的职责便是伸出援助之手 +你在哪? +我的儿子 +水? +要喝水吗? +我的皇后 +妈妈说 要见伊克洛维亚 +妈妈说 要见伊克洛维亚 +- 喝点水吗? +- 伊克洛维亚 +- 叫谁? +亲爱的 +- 伊克洛维亚 +- 谁? +- 伊克洛维亚 +不! +不! +妈妈死了 现在我们不再需要伊克洛维亚了 +伊克洛维亚! +快来皇后的房间 快点! +召唤我的儿子 伊克洛维亚 +去叫我的儿子! +马上! +爸爸 +你的眼睛怎么了? +很好啊 +好? +一点都不好 王子 +刺眼的阳光几乎让他失明了 +瑞秋带他去看医生 +他说他的眼睛..."有光感" +是的 妈妈在信里提到过 我去找医生谈谈 +- 瑞秋还好吗? +- 她很好 谢谢 +瑞秋一直在皇后身边照料 +她说皇后真的很想念你 +过来 +快点! +一个王子怎么能这样公开展示自己? +一个皇后怎么能这样拉王子的耳朵? +是吗? +她不能吗? +那你想要她怎么办呢? +厉害的小王子 +- 她应该说对不起 +- 对不起 对不起 好了吗? +你回来就好 哈什 +没能在你母亲最需要你的时候出现 真是羞愧 +无论如何 现在说什么都晚了 +来 进去吧 +- 为你祈福 +- 她一直叫你的名字 +直到离开人世 +我说"我在这里! +你的丈夫 叫我的名字" 她却始终没有 +只呼唤你的名字 +你知道那是什么感觉吗? +我感觉... +只呼唤着你的名字... +然后离去 +大哥 +温柔的心被伤透了 她有所恢复 可还是... +去吧 去准备 +葬礼必须在日落前开始 +要束白色腰带 都放在你房间里了 +是这里的习俗 人人都很敏感 我们走吧 +妈妈 你最后的遗言 "要照顾好哈什" +给予了我力量... +...去减轻他的悲痛 +指引我吧 妈妈... +- 他怎么样? +- 为何如此担忧啊? +孩子 +看见那城堡了吗? +你的心上人越不过那么高的城墙... +...他向你问过我吗? +- 他问了 +- 他问什么了? +- "瑞秋还好吗?" +知道了 +上帝啊 请保佑我的女儿吧 +她是如此纯洁 如此天真 +请别伤她的心吧 +娜蒂妮 +娜蒂妮 你在哪儿? +噢 亲爱的国王 娜蒂妮公主在家吗? +娜蒂妮公主不在这里 +噢! +她去哪里了? +她和她的妈妈去神殿了 +请转告她 她的哥哥哈什来看她了 +她会的... +我是说... +我会的 +那好吧 我回伦敦去了 +你真笨! +你真笨! +你怎么没想到? +妈妈死了 我怎么和她一起去神殿呢? +- 我不这么认为 +- 别再说你要离开了 +每个人都离开我 +除了瑞秋 可她每天晚上还是要离开我 +瑞秋在这里呆到晚上 我一个人害怕 +陪着我好吗? +瑞秋 +- 你好吗? +瑞秋 +- 我很好 +你的父亲告诉我 你一直在照顾我的母亲 +瑞秋一直陪在她身边呢... +皇后一直很想念你 +她留这封信给你 +她让你回去再看 +她一定说"照顾好哈什" 对不对? +瑞秋 +亲爱的儿子... +希望当面问候 却只能用信件问候... +...你的归来 +我小心翼翼地喘息 担心生命就此结束 +我多么希望能再抱你最后一次 +恐怕我等不到那一刻了 这封信... +...会告诉你一切 关于你身世的秘密 +儿子 杰维尔国王不是你的亲生父亲 +他一直被蒙在鼓里 +被发现的话 他一定不会将王位传给你... +...你的祖母采取古老的传统... +...只有贤明的人才能继承王位 +在这些众多人才中 +伊克洛维亚同我们一起 +皇后认为伊克洛维亚最可靠 他超过所有别的人才 +我也这么认为 +你和娜蒂妮有个贵族父亲 他就是伊克洛维亚 +我现在告诉你 因为你的父亲很需要你 +他年纪也大了 眼睛也几乎失明 +要是你父亲知道我泄露了这个秘密... +...他会认为我亵渎了我们的誓约 我没有尽到守约的神圣职责 +但我相信 誓约是... +如同古代的摩呵婆罗多所说的 +"誓约 智慧 真理" +誓约生于理由 +誓约也生于智慧 +那便是你的思想灵魂所认为正确的东西 +誓约是你的灵魂所能接受的真理与圣洁 +我已完成了我的誓约 +现在 我的儿子... +你也必须完成你的誓约 +承诺我 你会照顾好你的父亲 +我承诺 妈妈 +我真想砍掉伊克洛维亚的头颅 把它挂在城门上 +他污染了王室的血统 +你以前怎么没告诉我? +我自己都不知道 +这些年 我一直信任我们的母亲 +她说过 她选择的是我 +我信任她 +皇后生下一对龙凤胎 +其中一个患有精神问题的女儿 +即使如此 我也接受了 +可今天我才发现... +...一个没用的保安... +...我孩子的父亲 +他和我的皇后睡了 +杰伊提 他是我孩子的父亲 +我的妻子... +和我的保安! +这些年那么顺从 卑躬屈膝 +他一定乐坏了 +嘲笑我不育 嘲笑我所有的缺点 还有这个 杰伊提! +伊克洛维亚来了 +混蛋! +殿下? +告诉他 杰伊提! +殿下刚才收到一封死亡威胁信 +信里说 我们必须归还农民的土地... +...否则国王就会死于非命 +这怎么可能? +他们没还清欠款 我们收回了他们的土地 +彼克... +他们的头儿 被发现死在... +...铁轨上 还有一封自杀遗书 +可他们控告我们谋杀 那群混蛋! +现在就去 出去! +去通知我的儿子 他父亲的生命处于危险之中 +谁的命? +他的亲生父亲 快去! +杰伊提! +我把真相说出来了 对吗? +不管谁是哈什的父亲... +- ... +都得死 +- 放心吧 哥哥 +明天日落前 伊克洛维亚将躺在他的火葬柴堆里... +...就像皇后那样 +王子 我到处找你 你一个人在这里干什么? +妈妈也是独自一人 伊克洛维亚 每个人都抛弃她 +你愿意和我们在一起吗? +- 她会因此而高兴的 +- 你得回去了 +你的父亲收到了一封死亡威胁信 +我的父亲? +我有父亲吗? +你见过我的父亲吗? +我想见他 +想告诉他 我和妈妈在这里很寂寞 +想告诉他 我很想念他 他会来陪我们吗? +对他来说 妈妈算什么? +无关紧要? +他力不从心? +我们走吧... +...王子 +我很想哭 伊克洛维亚 +却哭不出来 +你能给我力量吗? +可以吗 +儿子 别这样伸出你的手 +如果我握紧了你的手 会招来灾难的 +那次决定性地甄选... +你的母亲和我形同陌路 直到最后 +我们决定 不让我们的孩子知道... +...我是孩子们的亲生父亲 +娜蒂妮无邪的笑声... +击碎了我的心啊 +我多么想抱着她大声呼喊 "我是你的爸爸啊" +但这是绝不允许的 +绝不 +哈什! +你在哭吗? +哈什 +为什么? +别哭啊 你想妈妈了吗? +傻瓜 她一直在我们身边 我们有好多的妈妈啊 +一,二,三,四... +想见见她们吗? +看看? "妈妈在排灯节" 她可爱吗? +"妈妈的生日" 你看啊 +"妈妈在寺院" +"闪闪发光的妈妈" +还有这个是... +不... +不是这个 +- 画错了的 +- 给我看那张画 +不! +很恐怖的 +- 有血 +- 好吧 乖 +告诉我 怎么回事? +这个秘密不能传出那个房间 他会杀死我的 +- 谁? +- 我不能告诉你 +要是这个秘密离开那个房间 他就会杀死我的 +哪个房间? +要是这个秘密离开那个房间 他就会杀死我的 +哪个房间? +现在 这个秘密绝对不会离开妈妈的房间了 +但是门是打开的 +你紧张吗? +巴布鲁 +别担心 我们生在民主主义社会 这些国王不过是纸娃娃 +我的警棍远比他们的剑有势力 +嘿 巴布鲁 看见那城墙了吗? +我的祖父被那城墙活埋了 +就像剪断开幕式上的绸带一样... +...这些国王杀死我们贱民以求好运! +见过我的祖父 卡洛维加尔 +若不是因为想念伊克洛维亚... +...我也不会坚持到现在 +进去吧 +先生 还记得我吗? +我是帕努 帕努加尔 达南加尔的儿子 +上帝保佑你 +还记得那个市集吗? +我就是接到铃铛的男孩 +还记得吗? +你那时好厉害 我整晚都没谁这 +我当时就想 长大以后要和你一样厉害 +现在的我 警察长官帕努加尔 +谢谢你 先生 +我真想再看一次你的精湛技艺 +可以吗... +求你了? +我不确定现在能否做到 孩子 +尝试一下 +先见过陛下 走吧 +就一会儿 答应我? +好吧 来 +那些该死的农民发疯了 他们威胁要杀了我 +做笔录了吗? +巴布鲁 +别以为我不了解状况 陛下 +为什么有麻烦的国王 只敢藏在巨大的官邸? +他害怕愤怒的农民? +难道他不知道这有多懦弱? +你胆敢嘲弄我? +别忘了 我是这里的国王 +而你只不过是... +- 贱民? +我不想谈这个 +民主社会里 歧视就是一种犯罪 +是哪个法案规定的? +巴布鲁 +不管哪个法案 手铐会说明事实 +世世代代 我们制定法律 你胆敢在这里跟我说手铐? +我们统治了两千多年了 +而我们因此受苦五千年 +我的祖父 被这城墙活埋了 +算你走运! +我是那些贱民的孩子 他们的手都被切下来... +...只因为摸了一下圣洁的书本 +受够了历史! +你的保安得跟我离开一个小时 +一小时? +陛下 民主的意思 就是自由意志 明白? +很多警察在茶摊 糖果店也有 +用他们来换这点时间 不愿意? +先告辞了 +可以吗? +先生 +- 现在就开始吗? +- 别太早放弃啊 帕努 +你怎么看待一个贱民成为高级官员? +- 巴布鲁 蒙眼罩! +- 我不需要 +太阳光够刺眼的了 +带上眼罩 看上去更令人佩服 +那好吧 +准备好了吗? +- 是的 +我们睁着眼睛都无法做到 而你带上眼罩也行 +淹没... +...我的父亲为保护国王溺水 +我在湖水边找了他一整晚 +后来妈妈来了 +- 儿子 +这是属于你父亲的 现在由你来保管它了 +从这一天起 他会时刻陪伴着你 +今后 你只有一个誓约 保护好你的国王 +违反誓约的话 我们家族就没落了 +如同坚强的伊克洛维亚 你必须坚决顺从你的誓约 +那天以后 她叫我伊克洛维亚... +...而我父亲的武器 也成为我唯一的武器 +没人知道这件事 我也布知道为什么要告诉你 +我知道为什么 因为我们俩都一样 +先生 国王收到威胁信的时候你在场吗? +没有 只有他的弟弟杰伊提在那 +就是住在红瓦平房那儿的人 在铁路附近的? +再见 先生 +伊克洛维亚快来陪你了 那时候 你会很快乐了 +我该怎么办 我的皇后? +你总是给我指引 +我该给杰伊提打电话吗? +陛下还没有打电话来 +"陛下..." +每次你一叫"陛下" 我就血液沸腾快发疯了 +要是哈什也让我这么叫他 我会用枪爆他的头 +尤迪 我看起来怎么样? +"陛下""如你所愿 陛下" +你怎么叫得出来 我都不好意思叫他叔叔 +你叫了他多久的叔叔? +27年了 +- 52年! +52年的"是的 陛下" "好的 陛下" +"你的心愿就是我的职责" "我的陛下" +你好 杰伊提 +- 是的 陛下 +警察刚才来过了 +好的 陛下 我们半小时后到 +现在什么时间? +- 下午5: +25 +快了四分钟 请调一下 +我们下午6: +10见 陛下 6: +10准时 +爸爸... +有客人 +吹走了 吹走了 瑞秋的风筝没了! +切断它! +把风筝线切断! +瑞秋故意输给娜蒂妮 娜蒂妮很高兴 +瑞秋是个好女孩 奥迈克 +你把她养育得那么好 +- 很艰辛啊 +每日忙碌 来回为皇室开车... +...我都没注意 小女孩就变成大姑娘了 +她很可爱 我担心她以后会嫁谁 +一切顺其自然 奥迈克 +马斯克曼先生... +...告诉你吧 +要是你有个英俊的儿子... +...我就不担心了 +他们坠入爱河 我们就是亲戚了 是吧 +瞧! +王子来了 +让我看看 +国王怎么对待这么优秀的儿子? +皇后死后 他一直很孤独 +真想给他一个拥抱 +父亲 +不 小王子 别叫我父亲 +我没有权力 我只是个卑微的保安 +我也很想抱抱他 +可是我不能 我没有权力去做 +我只是个卑微的保安 +你把她照顾得很好 谢谢你 +看见她高兴 我也开心 现在你来了 那我先退下了? +请等等 +你还记得妈妈唱的那首歌吗? +月亮颂? +- 是的 +能为我唱一曲吗? +在这儿? +现在? +- 拜托 +我很想念妈妈 +听见什么了吗? +只能用望远镜看看 马斯克曼先生 不是听 +她在唱歌 +"我的孩子 我的月亮" +"柔软的微笑 我的月亮孩子" +"轻轻地走来..." +"... +我的眼眸是你的天空 在这里快乐直到永远" +"轻轻地 噢... +柔柔地" +"乘着风 乘着云 还有满载的微笑" +"微笑吧 我的月亮孩子!" +"柔软的微笑 我的月亮孩子" +"轻轻地走来..." +"... +我的眼眸是你的天空 在这里快乐直到永远" +"柔软的微笑 我的月亮孩子" +"在这里快乐直到永远" +陛下叫你们俩去 马上! +现在? +去哪儿? +皇后喜欢十四行诗 +莎士比亚 +她去世的时候 我正给她念 +伊克洛维亚 你想在哪里火葬? +陛下? +苍天不容 要是你死于意外... +...在哪里火葬你? +陛下... +我的家乡 +那怎么行! +你服侍了我们那么久 +你的火葬... +应该有皇室的排场 +躺在你的皇后的旁边 +趴下 陛下... +杀死他! +杀死他! +你在干什么? +杀了他! +你聋了吗? +快动手! +是的 陛下 你的心愿就是我的职责 +陛下... +陛下... +陛下 他们抓走了我的弟弟 他们说是我们杀了国王 +他们要绞死我们的孩子 +- 他们说我们是农民 +可我们连耕地都没有 +刚开始没收我们的土地 现在又抓我们的孩子 +我们想反抗 他们却杀死了我们的领袖彼克... +...还说他是自杀的 陛下 听我说 +我们被陷害了 +够了 我再也不能忍受了 +谁的骆驼? +这是谁的骆驼? +回答我! +瑞秋... +? +我会和瑞秋结婚 +上帝保佑你 +我能进去吗? +现在这里是你的家了 瑞秋 你可以来去自由的 +谢谢你 +谢什么? +谢谢你让我的父亲没有留下遗憾 +你的承诺 让他走得很安详 +我看见他笑了 +现在他走了... +我不会要求你实现承诺 +瑞秋 我... +- 请听我说完 +但我并不因你的承诺而高兴 +当我还是个小女孩... +...我就梦想有一天能嫁给你 +现在梦想实现了 +父亲总认为我很天真 +可我有这信念 +我总是觉得... +...你会真的爱我 +而不是你的同情和可怜 +我能说话了吗? +瑞秋... +为什么妈妈信任地把最后一封信交给你? +为什么娜蒂妮那么爱你? +一听见你的名字 她都很高兴 +事实是... +...我也有同样的感觉 +可是我依然保持沉默 我不能表达自己 +娜蒂妮可以 +她是城堡里唯一坦白的人 +你知道这里... +对每个人而言都是危险的 +这座城堡里的各种礼教约束 很让我头疼 +瑞秋 ... +我再也不是你理想中的哈什了 +这五十年来 你在这里享尽了优待 +当国王最需要你的时候 你却躲在驼群后面 +尤迪! +凶手踢掉你的枪时 你在打瞌睡? +尤迪! +你得尊重伊克洛维亚 +他们家族世代保护我们的国王 +他耳聋眼瞎的 +否则那些没用的农民也碰不到陛下 +警官 你查到什么了吗? +我们查出 驼群是一个叫哈瑞亚的农民的 +他正在接受审问 +砍掉哈瑞亚的腿 那能让他老实点 +凶手不是农民 +伊克洛维亚? +这里有几个手指? +这么近都看不见 又怎么判断凶手不是农民? +伊克洛维亚的父亲为保护国王而牺牲 +很多人唱民谣歌颂他 +告诉我 伊克洛维亚 你怎么就躲过那些子弹了? +那些农民饶了他 +同样的贱民 +噢! +我明白了 那些混球的兄弟伙 +警官 请暂时带他出去 +先生... +你不能用枪去反驳 +他们说凶手踢掉你的枪时... +...我在打瞌睡 +因此你就要杀了他们? +是的! +先生 那是不理智的 为什么? +我并没有跟谁说过... +...我的枪被凶手踢掉了 +他们怎么会知道? +你说什么 先生? +他们暗杀了我的国王 +我认出了他鞋上的钉 就是他们 +- 让我去 +- 先生... +请冷静 +让我去解决 这是我的职责 他们是我的"猎物" +你解决不了 给我让开 +我向你保证 我会逮捕他们 不管... +正当与否 +你知道他们杀了农民领袖彼克? +他的自杀遗书是假的 他们会使一样的招 +一样的铁道口 一封伪造的自杀信 +这是我的工作 我会解决的 +让我去 帕努 +要是我让你去了 你杀了他们 会被判绞刑的 +那又怎样? +我不在乎... +- 那我不得不拘捕你了 +那我不得不先杀了你 +把枪给我 +够多的伤亡 给我 +你不清除我眼睛盲的程度 +他们杀了国王 你会是下一个 +他们一样会在驼群后杀你 +外面有辆吉普车 开车离开这儿 +那边会有人接你 +你自由了 走吧 +走? +杀国王的凶手还没有抓到 +我就是这城堡的墙 +我的存在只为了保护国王 每一刻... +..."我的生命何尝不是这城堡的一块砖 +而这城墙已随岁月逐渐腐朽 +曾经敏锐的目光也已变得模糊" +你看过我的信? +是的 +每个字都是写给我的 对吗? +谁... +谁告诉你的? +妈妈 +誓约! +她违反了! +我承诺一生隐埋秘密 +皇后违反了誓约! +- 不 +妈妈没有 +她的信 +"誓约 智慧 真理" +誓约生于理由和智慧 +誓约是你的灵魂所能接受的真理与圣洁 +妈妈履行了她的誓约 +而我 你的儿子... +...也将履行我的誓约 +请离开这个地方 +陛下 +先生 +儿子 +你不能流放我 +你不能! +一个儿子怎么会流放父亲? +而一个国王... +...可以流放王室守卫 +我 哈什国王 以最崇高的权力... +命令你 伊克洛维亚 马上离开这里 +遵命! +父亲 回到那平静的乡村 +享受简单快乐的农村生活 +我会接你回来 那时候... +...我会甩掉脑子里那些发狂的 "誓约"和"职责" +取而代之的是欢庆 和你孙子带来的快乐 +我希望看见你的笑容 你太苦了 +哈什! +哈什 村民们告诉我 你命令伊克洛维亚离开这里了 +真的吗? +为什么? +看这个 +嘿! +是谁? +你? +你来这儿干什么? +哈什国王... +- 说什么 +大声点! +哈什国王让我离开了城堡 +我得另谋职业 +什么工作都行 +我可以为你擦皮鞋 +出去! +给我滚出去! +别再让我看见你的脸 +你的愿望就是我的工作 +快出去! +黑暗淹没了我的脸 尤迪 +可我却看得清你的脸 +我看见杀死国王的凶手的脸 +你的子弹用尽了 +再发出一点声音... +...就是你的死期 +我听着呢 尤迪 我能感觉你的呼吸 +安静 +安静 别出声 +安静才能活命 +要是你再喘息 我就解决你 +让你死是我的职责 +你来这儿干什么? +哈什国王让我离开了城堡 +我给你送来了告别的礼物 +那好 放在门口就离开吧 +你不看看? +我说... +是什么? +打开 +尤迪? +你对我儿子干了什么? +他在哪儿? +尤迪在哪儿? +他在铁轨旁徘徊 要和他一起吗? +你见过伊克洛维亚笑吗? +没人见过... +除了我 +我挨打的时候他帮了我 +谁打你? +- 爸爸 +你一定做了坏事 +- 不是我 是你 +我? +我做了什么? +你不记得了? +- 不记得了 +皇后扯你的耳朵 +你哭喊着 "一个皇后怎么能这样拉王子的耳朵?" +是啊 我当众亲你 +伊克洛维亚帮我不挨爸爸的打 +还带我去骑骆驼 给我买石榴吃 +但我还是很可怜 +- 为什么? +我说"我不会去亲回来了" +他听了... +...就笑了... +...就和现在的你一样 +我得告诉你一些事 +什么事 哈什? +这是我父亲的枪 +要不是为了你和娜蒂妮... +...我向上帝发誓 我... +你别吓我 +我也吓得要命 ...担心你会离开我 +不会的 我保证... +...等等 先听我说... +...然后再承诺 +你干了什么啊? +你杀了我的儿子! +他杀了我的国王 +我履行我的职责 +- 履行你的职责? +干得好! +非常好! +现在去杀了那个人 那个谋划杀死国王的人 +告诉我他的名字 +我去取他的人头 +你去取你儿子的人头? +好啊! +太好了! +哈什安排的谋杀 让我等着你取他的人头! +哈什! +哈什 你的儿子! +砍掉他的头 履行你的职责 +哈什! +等等 瑞秋 +求你了 +为谁? +你杀了我的父亲 哈什 +职责让你杀了我的儿子 为了职责 去杀你的儿子啊 +谎言! +- 是真的 他... +娜蒂妮睡了吗? +你? +你来这里干什么? +等你 +你脸上有血 +谁的血? +我不知道 +尤迪的... +杰伊提的... +我杀了他们俩 +现在你来这里杀我 +是的 +在我的匕首确定目标之前... +...我必须知道真相 是你谋划杀了我的国王吗? +是我 +那么我 城堡的守卫... +...以及你的父亲... +...必须履行我的职责 +准备受死吧 +我的亲生父亲将杀了我... +...多么好的死法 +我准备好了 +为什么这么做? +我无法想象 在驼群那儿你几乎杀了我... +...你认为是我... +...在驼群后面? +继续吧 把你的匕首插入我的心脏 +来吧! +你做不到 +因为你知道你的儿子决不会退缩 +为什么? +为什么这么罪恶? +为什么? +"誓约 智慧 真理" +我救了你的命 +看这个 是他杀了妈妈 +他的双手杀了她 +知道为什么吗? +因为她一直呼唤着你的名字 +我知道他们会杀了你 +而你的王子为你做了什么? +两千五百万! +我给了他们十倍让你活命 +撒谎! +全在撒谎! +不可能是真的! +我的国王不会这么干 +永远不会 +他不会的 +这些只是娜蒂妮的话 +这可能是她的幻想... +...她的胡思乱想 +别试图改变我的决心... +...醒醒吧 伊克洛维亚 +砍掉你的拇指 履行你的誓约 +誓约? +誓约的前提是事实 +誓约站在真理这一边 +要是这一刻我的誓约有所动摇... +...违反誓约的话 我们家族就会被埋葬 +妈妈告诉我履行自己的职责 就像坚强的伊克洛维亚一样 +你的死... +...是我的职责 +可是 你的手在颤抖 +当一个年迈的父亲双手开始颤抖... +...他儿子的职责便是伸出援助之手 +你在哪 我的儿子? +- 我迷失了方向 +但我会回来 +我的双手沾满了血 +瑞秋的父亲 +一辈子也洗不干净 +让这些血迹随我的火葬一起被焚毁 +请照顾好娜蒂妮 +告诉她 妈妈很孤单 所以我离开她去陪伴妈妈 +我可以告诉妈妈 我履行了我的承诺 +我可以祈求瑞秋父亲的宽恕 +我可以完成我的使命 +你的职责... +就是我的死亡 +- 住手 哈什! +别! +这是我的誓约 +尽管我的双手颤抖 但我内心坚定 +我眼瞎但... +...我的耳朵好使 +我... +只要... +...一句话 ... +...我的匕首会找到你 +父亲 +父亲 +我以为你从不会失手 +我没有失手 那是我最好的一掷 +"砍掉我的拇指... +...我的职责是你的死亡" +...那会杀了我的儿子 +你是对的 儿子 +伊克洛维亚错了 +伊克洛维亚错了 +错得那么严重 +妈妈 给我力量... +...追随你的脚步 +给我指引 +我的心告诉我应该原谅哈什 +他支支吾吾 可他的心是纯洁的 +他愿意为此付出一生的代价 +太多的生命消逝 太多的血流失 +必须有人制止 +交给我吧 +祝福我吧 妈妈... +...让我去减轻他的痛苦 帮他忘记所有的难过... +...好好照顾他 孩子 +他有着高尚的心灵 看看他为我们所做的一切... +...所有村民都来感谢他 +他归还了我们的土地 +哈什国王万岁 +万岁... +- ... +哈什国王! +哈什国王万岁! +我归还你们土地有自私的原因 +我想让我的父亲感到自豪 +今天 所有在场的人们都是我的见证人... +...我在此证实 伊克洛维亚是我的父亲 +儿子 +父亲 +警察来干什么? +- 来逮捕我的 +是时候以命抵命了 +恐怕我有些坏消息要宣布 +我准备好了 走吧... +- 等等 +今天 我们调查了尤迪的房间... +...在DVD盒里发现了自杀遗书 +巴布鲁... +看看吧 +皇室的人渣 +他们知道我要抓他们 所以他们选择了更简单的解脱... +...往高速行驶中的火车上跳 系自杀 +太遭了 终究还是逃出了我的掌心 +我心里是怎么都无法宽恕他们的 +先生 好手迹 不是吗? +很好 +太好了! +不是吗? +爸爸 +陛下叫你们俩去 马上! +现在? +去哪儿? +皇后喜欢十四行诗 +莎士比亚 +她去世的时候 我正给她念 +伊克洛维亚 你想在哪里火葬? +陛下? +苍天不容 要是你死于意外... +...在哪里火葬你? +陛下... +我的家乡 +那怎么行! +你服侍了我们那么久 +你的火葬... +应该有皇室的排场 +躺在你的皇后的旁边 +趴下 陛下... +杀死他! +杀死他! +你在干什么? +杀了他! +你聋了吗? +快动手! +是的 陛下 你的心愿就是我的职责 +陛下... +陛下... +陛下 他们抓走了我的弟弟 他们说是我们杀了国王 +他们要绞死我们的孩子 +- 他们说我们是农民 +可我们连耕地都没有 +刚开始没收我们的土地 现在又抓我们的孩子 +我们想反抗 他们却杀死了我们的领袖彼克... +...还说他是自杀的 陛下 听我说 +我们被陷害了 +够了 我再也不能忍受了 +谁的骆驼? +这是谁的骆驼? +回答我! +瑞秋... +? +我会和瑞秋结婚 +上帝保佑你 +我能进去吗? +现在这里是你的家了 瑞秋 你可以来去自由的 +谢谢你 +谢什么? +谢谢你让我的父亲没有留下遗憾 +你的承诺 让他走得很安详 +我看见他笑了 +现在他走了... +我不会要求你实现承诺 +瑞秋 我... +- 请听我说完 +但我并不因你的承诺而高兴 +当我还是个小女孩... +...我就梦想有一天能嫁给你 +现在梦想实现了 +父亲总认为我很天真 +可我有这信念 +我总是觉得... +...你会真的爱我 +而不是你的同情和可怜 +我能说话了吗? +瑞秋... +为什么妈妈信任地把最后一封信交给你? +为什么娜蒂妮那么爱你? +一听见你的名字 她都很高兴 +事实是... +...我也有同样的感觉 +可是我依然保持沉默 我不能表达自己 +娜蒂妮可以 +她是城堡里唯一坦白的人 +你知道这里... +对每个人而言都是危险的 +这座城堡里的各种礼教约束 很让我头疼 +瑞秋 ... +我再也不是你理想中的哈什了 +这五十年来 你在这里享尽了优待 +当国王最需要你的时候 你却躲在驼群后面 +尤迪! +凶手踢掉你的枪时 你在打瞌睡? +尤迪! +你得尊重伊克洛维亚 +他们家族世代保护我们的国王 +他耳聋眼瞎的 +否则那些没用的农民也碰不到陛下 +警官 你查到什么了吗? +我们查出 驼群是一个叫哈瑞亚的农民的 +他正在接受审问 +砍掉哈瑞亚的腿 那能让他老实点 +凶手不是农民 +伊克洛维亚? +这里有几个手指? +这么近都看不见 又怎么判断凶手不是农民? +伊克洛维亚的父亲为保护国王而牺牲 +很多人唱民谣歌颂他 +告诉我 伊克洛维亚 你怎么就躲过那些子弹了? +那些农民饶了他 +同样的贱民 +噢! +我明白了 那些混球的兄弟伙 +警官 请暂时带他出去 +先生... +你不能用枪去反驳 +他们说凶手踢掉你的枪时... +...我在打瞌睡 +因此你就要杀了他们? +是的! +先生 那是不理智的 为什么? +我并没有跟谁说过... +...我的枪被凶手踢掉了 +他们怎么会知道? +你说什么 先生? +他们暗杀了我的国王 +我认出了他鞋上的钉 就是他们 +- 让我去 +- 先生... +请冷静 +让我去解决 这是我的职责 他们是我的"猎物" +你解决不了 给我让开 +我向你保证 我会逮捕他们 不管... +正当与否 +你知道他们杀了农民领袖彼克? +他的自杀遗书是假的 他们会使一样的招 +一样的铁道口 一封伪造的自杀信 +这是我的工作 我会解决的 +让我去 帕努 +要是我让你去了 你杀了他们 会被判绞刑的 +那又怎样? +我不在乎... +- 那我不得不拘捕你了 +那我不得不先杀了你 +把枪给我 +够多的伤亡 给我 +你不清除我眼睛盲的程度 +他们杀了国王 你会是下一个 +他们一样会在驼群后杀你 +外面有辆吉普车 开车离开这儿 +那边会有人接你 +你自由了 走吧 +走? +杀国王的凶手还没有抓到 +我就是这城堡的墙 +我的存在只为了保护国王 每一刻... +..."我的生命何尝不是这城堡的一块砖 +而这城墙已随岁月逐渐腐朽 +曾经敏锐的目光也已变得模糊" +你看过我的信? +是的 +每个字都是写给我的 对吗? +谁... +谁告诉你的? +妈妈 +誓约! +她违反了! +我承诺一生隐埋秘密 +皇后违反了誓约! +- 不 +妈妈没有 +她的信 +"誓约 智慧 真理" +誓约生于理由和智慧 +誓约是你的灵魂所能接受的真理与圣洁 +妈妈履行了她的誓约 +而我 你的儿子... +...也将履行我的誓约 +请离开这个地方 +陛下 +先生 +儿子 +你不能流放我 +你不能! +一个儿子怎么会流放父亲? +而一个国王... +...可以流放王室守卫 +我 哈什国王 以最崇高的权力... +命令你 伊克洛维亚 马上离开这里 +遵命! +父亲 回到那平静的乡村 +享受简单快乐的农村生活 +我会接你回来 那时候... +...我会甩掉脑子里那些发狂的 "誓约"和"职责" +取而代之的是欢庆 和你孙子带来的快乐 +我希望看见你的笑容 你太苦了 +哈什! +哈什 村民们告诉我 你命令伊克洛维亚离开这里了 +真的吗? +为什么? +看这个 +嘿! +是谁? +你? +你来这儿干什么? +哈什国王... +- 说什么 +大声点! +哈什国王让我离开了城堡 +我得另谋职业 +什么工作都行 +我可以为你擦皮鞋 +出去! +给我滚出去! +别再让我看见你的脸 +你的愿望就是我的工作 +快出去! +黑暗淹没了我的脸 尤迪 +可我却看得清你的脸 +我看见杀死国王的凶手的脸 +你的子弹用尽了 +再发出一点声音... +...就是你的死期 +我听着呢 尤迪 我能感觉你的呼吸 +安静 +安静 别出声 +安静才能活命 +要是你再喘息 我就解决你 +让你死是我的职责 +你来这儿干什么? +哈什国王让我离开了城堡 +我给你送来了告别的礼物 +那好 放在门口就离开吧 +你不看看? +我说... +是什么? +打开 +尤迪? +你对我儿子干了什么? +他在哪儿? +尤迪在哪儿? +他在铁轨旁徘徊 要和他一起吗? +你见过伊克洛维亚笑吗? +没人见过... +除了我 +我挨打的时候他帮了我 +谁打你? +- 爸爸 +你一定做了坏事 +- 不是我 是你 +我? +我做了什么? +你不记得了? +- 不记得了 +皇后扯你的耳朵 +你哭喊着 "一个皇后怎么能这样拉王子的耳朵?" +是啊 我当众亲你 +伊克洛维亚帮我不挨爸爸的打 +还带我去骑骆驼 给我买石榴吃 +但我还是很可怜 +- 为什么? +我说"我不会去亲回来了" +他听了... +...就笑了... +...就和现在的你一样 +我得告诉你一些事 +什么事 哈什? +这是我父亲的枪 +要不是为了你和娜蒂妮... +...我向上帝发誓 我... +你别吓我 +我也吓得要命 ...担心你会离开我 +不会的 我保证... +...等等 先听我说... +...然后再承诺 +你干了什么啊? +你杀了我的儿子! +他杀了我的国王 +我履行我的职责 +- 履行你的职责? +干得好! +非常好! +现在去杀了那个人 那个谋划杀死国王的人 +告诉我他的名字 +我去取他的人头 +你去取你儿子的人头? +好啊! +太好了! +哈什安排的谋杀 让我等着你取他的人头! +哈什! +哈什 你的儿子! +砍掉他的头 履行你的职责 +哈什! +等等 瑞秋 +求你了 +为谁? +你杀了我的父亲 哈什 +职责让你杀了我的儿子 为了职责 去杀你的儿子啊 +谎言! +- 是真的 他... +娜蒂妮睡了吗? +你? +你来这里干什么? +等你 +你脸上有血 +谁的血? +我不知道 +尤迪的... +杰伊提的... +我杀了他们俩 +现在你来这里杀我 +是的 +在我的匕首确定目标之前... +...我必须知道真相 是你谋划杀了我的国王吗? +是我 +那么我 城堡的守卫... +...以及你的父亲... +...必须履行我的职责 +准备受死吧 +我的亲生父亲将杀了我... +...多么好的死法 +我准备好了 +为什么这么做? +我无法想象 在驼群那儿你几乎杀了我... +...你认为是我... +...在驼群后面? +继续吧 把你的匕首插入我的心脏 +来吧! +你做不到 +因为你知道你的儿子决不会退缩 +为什么? +为什么这么罪恶? +为什么? +"誓约 智慧 真理" +我救了你的命 +看这个 是他杀了妈妈 +他的双手杀了她 +知道为什么吗? +因为她一直呼唤着你的名字 +我知道他们会杀了你 +而你的王子为你做了什么? +两千五百万! +我给了他们十倍让你活命 +撒谎! +全在撒谎! +不可能是真的! +我的国王不会这么干 +永远不会 +他不会的 +这些只是娜蒂妮的话 +这可能是她的幻想... +...她的胡思乱想 +别试图改变我的决心... +...醒醒吧 伊克洛维亚 +砍掉你的拇指 履行你的誓约 +誓约? +誓约的前提是事实 +誓约站在真理这一边 +要是这一刻我的誓约有所动摇... +...违反誓约的话 我们家族就会被埋葬 +妈妈告诉我履行自己的职责 就像坚强的伊克洛维亚一样 +你的死... +...是我的职责 +可是 你的手在颤抖 +当一个年迈的父亲双手开始颤抖... +...他儿子的职责便是伸出援助之手 +你在哪 我的儿子? +- 我迷失了方向 +但我会回来 +我的双手沾满了血 +瑞秋的父亲 +一辈子也洗不干净 +让这些血迹随我的火葬一起被焚毁 +请照顾好娜蒂妮 +告诉她 妈妈很孤单 所以我离开她去陪伴妈妈 +我可以告诉妈妈 我履行了我的承诺 +我可以祈求瑞秋父亲的宽恕 +我可以完成我的使命 +你的职责... +就是我的死亡 +- 住手 哈什! +别! +这是我的誓约 +尽管我的双手颤抖 但我内心坚定 +我眼瞎但... +...我的耳朵好使 +我... +只要... +...一句话 ... +...我的匕首会找到你 +父亲 +父亲 +我以为你从不会失手 +我没有失手 那是我最好的一掷 +"砍掉我的拇指... +...我的职责是你的死亡" +...那会杀了我的儿子 +你是对的 儿子 +伊克洛维亚错了 +伊克洛维亚错了 +错得那么严重 +妈妈 给我力量... +...追随你的脚步 +给我指引 +我的心告诉我应该原谅哈什 +他支支吾吾 可他的心是纯洁的 +他愿意为此付出一生的代价 +太多的生命消逝 太多的血流失 +必须有人制止 +交给我吧 +祝福我吧 妈妈... +...让我去减轻他的痛苦 帮他忘记所有的难过... +...好好照顾他 孩子 +他有着高尚的心灵 看看他为我们所做的一切... +...所有村民都来感谢他 +他归还了我们的土地 +哈什国王万岁 +万岁... +- ... +哈什国王! +哈什国王万岁! +我归还你们土地有自私的原因 +我想让我的父亲感到自豪 +今天 所有在场的人们都是我的见证人... +...我在此证实 伊克洛维亚是我的父亲 +儿子 +父亲 +警察来干什么? +- 来逮捕我的 +是时候以命抵命了 +恐怕我有些坏消息要宣布 +我准备好了 走吧... +- 等等 +今天 我们调查了尤迪的房间... +...在DVD盒里发现了自杀遗书 +巴布鲁... +看看吧 +皇室的人渣 +他们知道我要抓他们 所以他们选择了更简单的解脱... +...往高速行驶中的火车上跳 系自杀 +太遭了 终究还是逃出了我的掌心 +我心里是怎么都无法宽恕他们的 +先生 好手迹 不是吗? +很好 +太好了! +不是吗? +爸爸 +== Srt 字幕转制: +中國影視論壇 阿龍 == +你喜欢热天吗 +是的 +我没怎么想过 +可是... +好像有点是的 +因为有那样的工作 +工作出色 +前面是永川 +没下雨吧? +是的 +那个 +我一直拿着伞 +很喜欢 +是伞吗? +折叠伞 +我喜欢折叠伞 +只有在需要的时候变大 +我很喜欢 +我走这边 +一点都不好 +挺乱的 +是的 +是伞吗 +没什么 +欢迎光临 +你养着猫吧 +不,不是养的 +它偶尔来玩的 +是野猫吗 +是怎样呢 +不知道是从哪里来的 +要是说野猫的话 +全都是野猫 +但是到了我这里来后 +就不认为它是野猫了 +这么说的话,我也是野的 +活着的东西全都是野的 +是那样吗? +这是干燥的嫩芽 +是很好吃的 +我非常喜欢 +浸在水里会膨胀变得很大 +很好吃的 +这个什么都行 +比方说撒在这上面 +我很喜欢吃 +是增加味道的 +你总是自己做饭吗 +是的,我很喜欢自己做饭 +喜欢那个味道 +经常这样 +你妻子不做吗? +现在是那样 +不在一起 +不会做 +没有一起住吗 +是的 +有点 +她和女儿住在一起 +和我想法不同 +你有女儿吗 +我有个女儿,哪里都一样的 +她几岁? +20岁 +一个女儿吗 +是的 +对了,月薪多少? +要说吗 +那个... +20万的工资 +再加上副收入共30万 +要供房吗 +是的 +你一般去哪里玩? +那个... +要是能得到的话,还是想要的 +可是我不是说这种话的立场 +不是那样的工作 +80左右吧 +欢迎光临 +我要乌东面 好的 +要一碗乌东面 +一般多久来一次 +是的,一周2,3次吧 +2,3次? +是常客吧 +是的 +总是吃乌东面吗? +总是吃乌东面 +除乌东面外? +除乌东面外,都没吃过其他的 +没有吗? +除乌东面外没有其他的 +一般是什么时候来的 +我不记得了 +最近来的多 +你知道他是大日本人吗? +不知道,原来如此 +很棒吧 +是的,人不可貌相 +你经常来这个公园吗 +是的 +我女儿经常来这里 +那个 +很怀念 +看到这里的时候 +其实 +我想要个男孩 +你喜欢男孩吗? +与其说是喜欢 +不想在我这一代结束 +有那样的责任感 +有那样的 +当然我还没有放弃 +还想生一个吗? +与其说是再生一个 +当然并不是说女孩不行 +我是这个打算 +想要这么相信 +现在也来玩吗 +和女儿? +现在... +每月一次吧 +做怎样的事玩? +就是那个 +很普通的 +去看电影 +不去旅行吗? +不去旅行 +总之 +不知道什么时候要工作 +我女儿要上学 +必须要马上行动的状态 +因此 +不能去旅行 +不能去海外吗 +从没去过海外 +我没有护照 +那个... +想要放弃 +那是 +并不是有反美情绪 +我并喜欢 +保护日本的说法 +那是很少的 +你不喜欢美国吗 +要是说反美情绪的话 +当然 +在这个时代 +没有敌对的事 +这样的教育 +稍微接受了点吧? +有点感觉到 +不要想太多 +这种事 +你怎么了 +喂 +不好意思,可以吗 +可以停下相机吗 +为什么 +是工作方面上的事 +喂 +喂 +是么 +好像是的 +那是关于角色吗 +哪里? +是角色的事吗 +知道了 +知道了 +那么赶快 +是,我等你 +是 +怎么了 那个... +或许 +会起作用也不知道 +作用? +我在等联络 +是么 有可能要走 +那么可以继续下去吗 +要继续吗 是 +好 +你喜欢欧洲吗 +是欧洲吗? +那个,对不起 +我接一下电话 好 +喂 +喂 +可以吗 +原来如此,是,知道了 +是,第二 +知道了 +请多关照 +怎么了 +我要走了 现在吗 +是的,我必须要去 +在这里吗 +不,我必须要回去了 +是工作的事吗? +是工作 +山城先生 +山城先生 +我来晚了 +我接到命令赶来了 +知道了 +对不起,等等 +我正在采访 +让我进去好吗 +不要 只是一下子 +可以吗 +可以进去吗 不行 +很快就结束 +不行,对不起 拜托了 +不行 +那么可以在这里拍吗,从这里 +好 +封闭的野兽 +偶尔会出来 +把人吓一跳 +展现它的习性 +可以吗 +所以大家都看nhk +原来如此 +这是很好的 +可是这不太好 +你做经理多久了 +从2002年 +4,5年? +是的 +很忙吗 +还行 +最近收视率不是很好 +不是最近 +长大后怎么回来? +不管他,他就会回来 +是男孩吗 +什么都不会 +那么很小吧? +是的 +不断的... +好像是那样的 +有多小? +2,3天吧 +可是在回来之后 +很快就会走 +你的袜子很漂亮 +是么 +那是什么? +是龙 +很烫 +好棒 +这个是床 好大 +说过不可以进来这里 +还在睡 +那么我也要回去了 +还有有赞助人要来 +下次不要这样 +再见 +这个是大日本人,怎么样 +感觉很好 +建造起来 +看了吗 没有看 +不喜欢吗? +会给我添麻烦 +看过一次 +很大的麻烦 +虽然很好玩 +之前的很漂亮 +完全恢复到从前了吗? +是的 +我觉得是恢复了 +自己也不是很清楚 +大概猫不找也会回来 +打了一次会累吗 +那要看情况 +可以到下一个怪兽出来 +都可以休息 +不知道,或许是今天 +也不知道地点 +不能休息 +要准备好 +这里有很多照片 +这个大的是谁? +啊,那个是 +第四代 +第四代? +第四代 +就是 +总之 +是我的爷爷 +啊,是你爷爷吗? +就是那个 +那个是泡沫经济好的时代 +每晚大家都聚在一起狂欢 +佣人是那个 +有50多个人 +现在呢? +第四代 +不,佣人 +没有佣人了 +完全没有佣人 +那工资还行吧 +并没有那样的情况 +所以,想去赏花的时候 +一个月去很多次 +自己付钱也不可惜 +大家会抢着出钱 +现在呢 +自己会出钱 +以前为什么那么受欢迎? +那是因为 +因为怪兽的数量很多 +怎么说呢 +这样的产业是少见的 +现在只有我 +大家对于怪兽... +认为非常有活力 +现在不会出现怪兽 +以前没有处理过吗 +我不是很清楚 +是黄金时期 +好像有过 +有很多人看过 +现在是深夜放送 +是的,深夜 +是的 +2点多 +是2点多 +收视率还好吧 +我不知道 +今天去哪里吗 +今天是 +听说中部地区有怪兽出现 +那里有很多电线 +我要去那边 +全国有几个地方? +现在是... +全国有几个地方 +还有在青森的八王子有个地方 +那里几乎没有被使用 +以前很多吗 +整个世纪听说有52个地方 +52个地方? +在都内 +一个地方也没有了 +在都内的话,变身不是快吗 +特意去那里变身吗 +大佐藤先生被人称为兽吧? +是的 是怪兽吗 +一般是叫怪兽吧 +总之就是 +对我们而言 +不是怪兽 +并不是可疑的 +现实中我们必须对抗 +要是有什么可疑的话 +融合其中 +一般叫兽 +在高中时 +想过这样的事 +我想一定是那样的 +不确认吗? +不确认吗? +是否那样 +光是想 +另一方面出动自卫队 +不是更好? +有这样的意见吧? +那个 +这种无心的意见 +我偶尔会听见 +那是没意义的 +传统这种东西 +应该怎么想? +当然是很复杂的 +结果是 +生物和生物对抗 +然后弱的生物 +死去的样子 +给生物们看 +这种文化 +我绝对不能轻视 +最后的生物是谁吗? +总之 +是独角仙之类的 +像是玩具一样的 +那些能控制的东西 +想要收拾掉的一代 +是孩子们吗? +孩子们... +包含孩子们 +不是很清楚 +这里能进去吗? +我想没事吧 +你稍等? +好 +我是大佐藤 +辛苦了 +他是来采访的 +可以让他进去吗? +没事的 好 +你好 +你好 +开始 +我进来了 +退下 +变身的时候,总是这样的感觉吗 +是的,这样的感觉 +没错 +总是这个样子 +是的 是的 +总之,最近 +有点堕落 +这个仪式 +在从前是比较隆重的 +是很正规的 +在更早之前就开始了吗 +是的,从很久之前 +就开始了 +仪式必须要正规的 +现在不做也行吗? +也不是说这样 +时代有了很大的改变 +没有规则 +必须在这里变身 +不... +他偶尔来这里 +不是这里也行吗 是的 +必须要举行仪式吗 +没有仪式也行 +不举行也行吗? +那为何要举行仪式? +那个... +因为这样最好 +因此... +对不起,对不起 +能再来一次吗? +能再来一次吗? +从那里开始 +不好意思 +开始 +进来了 +请退下 +你们认为正义是什么? +正义? +正义是... +正如字面意思 +就是... +正义 +是很难的吧 +怎么样 +正义 +正义... +有正义正义之说 +所谓正义 +谁说是正义呢? +个人有个人的看法 +大家认为自己是正确的 +我想那就是正义 +因此 +这是不是就是正义? +在这个世界上 +是 +你们认为生命是什么,生命? +是生命吗? +所谓生命 +是很难的 +所谓生命 +自己的生命在这里 +生命本身 +还是... +世世代代继续下去 +那个连续就是生命 +说自己是生命 +死亡 +只是自己死 +自己死亡这件事 +是很重要的 +是不是有更重要的事 +比起生命 +生命当然是重要的 +生命本身 +杀人 +受伤 +不管是不是垃圾,都是生命 +动物也是 +这种东西 +是最... +弹跳兽 +从高空跳下来 +会叫着,盛,盛 +这是弹跳兽的习性 +拜托不要遮住胸口 +德拉. +阿默雷 +德拉. +阿默雷开始了 +谢谢 +谢谢 +就要开始了 +大佐藤先生经常来吗 +是的,在长野工作的时候 +经常来 +对不起,你们是什么关系 +我们吗? +是朋友 +青梅竹马的朋友 +从以前起关系非常好 +是好友的感觉 +你是怎么看待 大佐藤先生的工作的 +是很辛苦的 +我也看见了 +他的身体 +会变形吧 +那是不是很痛 +充电后,要是我变大的话 +变大后,救人 +有没有这样的 +想要帮助人 +妈妈桑,你几岁了 +怎么了,你看我像几岁? +50... +50? +你太过分了 +你是不是太过分了 +不说是20岁 +50岁太过分了吧 +48岁左右 讨厌 +妈妈桑呢? +对不起 妈妈桑不去吗 +妈妈桑不去吗 +危险 不要一直拍 +小心点 谢谢 +再见 +小心点 +妈妈桑,你小心点 +明天见,晚安 +再见 +京子小姐,你很大 +嗯? +好大 +是的 多少公分? +87公分左右 +她还小,不能对比 +牙齿在矫正吗 +是的,矫正中 +是她的社长? +是她的社长 +社长 社长 +社长 +社长 社长 +社长 +讨厌,你在这里,再见 +春 +有人吗 +你好,我是大佐藤 +你好 +这个 谢谢 +是三号室吧 +是的 +== Srt 字幕转制: +中國影視論壇 阿龍 == +是三号室吧 +是的 +失礼了 +来这里多久了? +爷爷 +三年左右 +是不是在发呆 +年纪大了 +是么,有什么奇怪的行动吗? +是的 +他会嘴里絮叨 +晚上会转来转去吗 +有点 +爷爷很辛苦吧 +是不是吃太多药了 +在年轻的时候 +吃太多药了 +有来自国家的补助吗 +顺便说一下,你父亲怎么了 +结果我爸爸 +他也有责任 +或许是有责任的 +我爸爸死了 +年轻的时候 +想要更大的 +因为做过头了 +猝死的 +取而代之的是 +我家的第四代爷爷 +连儿子的份 +都要长久下去 +这是我的判断,我是这么想的 +什么都变得很大 +突然之间改变的 +这有点不好 +因此另外也有问题 +因为头脑聪明 +而溜走了 +实际上变大了吗 +没有 +喂 爷爷出去了 +从医院逃出去了 +东京塔对大日本人 +这个怎么办? +就是那样 +这是第四代做的事 +这跟第几代做的无关 +我再怎么努力 +赞助人都不见了 +我为此感谢你 +但我怎样都行 +你在说什么? +赞助人都是当官的 +那个我不知道 +那是作为经纪人的你做的 +我? +是第四代? +你是第四代吧? +是第四代 这到底是什么 +像这样的? +有你不知道的情况 +你家里的情况 +请要和睦点 +我正在这样努力着 +总之关于赞助人的事 +这个月或下个月 +我要回去 +我不行 +不要让我一直说 +只有我不行 +这样不是很好吗 +这是最后一次 +我心里知道 +你在说什么,现在的你 +赞助人是不会来的 +你给我适可而止 +我说了现在不行 +那请你想想办法 +不行的事你不要那么说 +你别对我生气 +这绝对是不行的 +那是我的政策 +不管别人怎么说, 这绝对不能让给别人 +要是做我的经纪人的话 +你要好好记住这一点 +瞪眼兽 +瞪着敌人 +位于新宿 +有瞬间沉睡的特征 +这是瞪眼兽的习性 +那是什么怪兽? +我不知道 +下次是什么时候? +数字很好 +是的 +平时是7% +是的 +太好了 +我很想看 +早上好 早上好 +能和你谈一下吗 +这辆车很好 +是,很好吧 +是你买的吗 是 +新车? +嗯 +多少钱? +500万? +好棒 +已经付清了吗? +一半一半 +付清了吗? +你的狗好大 +它叫什么名字? +它叫新桥 +在下面的是叫德尔加希 +德尔加希? +你现在是去工作吗? +是 +带着狗? +嗯 +不要紧吧 +嗯,它很乖的 +哪只? +两只都很好 +德尔? +哪只是德尔? +你上次看了数字吗? +是的,我看了 +非常好 +托你的福 还做那个吗? +是的 +要是附近还有就好了 +要和大日本人打怎么样? +我看了我看了 +怎么样? +那不太好 +那不太好? +我也看了 看了? +比起被人打 +喜欢打人 +是同样的 +不要太儿戏 +想看正经点的 +有点可悲 +日本人要再振作点 +是的,那样就好了 +当然我会支持,觉得很好 +你有车吗? +还没有买吧 +还没有买 +你想说什么 +就是那个 +我想让你调查调查 +我现在正在调查 +尽可能的告诉我 +那个时候不逃走就知道了 +我知道 那个时候 +逃走不好吗? +你是经纪人 +不要说我逃走 +很奇怪吧 因为你逃走了 +让我看的很清楚 +那非常好 +我不是逃走,那个时候 +只有那样做 +你看见了也知道吧 +总之看来不像日本人 +那个 +是哪个国家的? +不晓得 +我们的邻国日本 +惹恼了将军 +要惩罚大日本人 +是那个 +是那个 +是很难的 +那个 +给我女儿的礼物 +给女儿的礼物 +不知道买什么好 +我买了帽子 +帽子 +是给我女儿的 +我女儿说过喜欢的 +我不知道哪里有卖 +你看来很开心 +不是这样的 +跟平时一样 +我想尽快 +看到女儿的脸 +多久没见了? +是一个月左右 +总是来这家店吗 +是的 +我老婆的老家就在附近 +我从以前起就来这里 +不认为是大男人主义 +这是碰巧 +你很开心 不是这样的 +是很普通的 +是的 +我想看见女儿 +一月一次 +可是我有工作 +不能一直来这里 +可能的话,每天... +我想女儿是这么想的 +是很难的 +喂 +你在干吗? +怎么了 不知道 +我没跟你说要拍摄下来吧 +没事吧 别紧张 +一点事都没有 +你是不是化妆了 +在做什么 +你做那种奇怪的工作 +怎么了 +你说吧 +由你来说明不是很好吗 +对不起 +我会带来女儿 +可以的话,希望你别拍她的脸 +今天不知道要被拍摄下来 +可以的话,用马赛克 +不需要用马赛克 +要是被人知道了, 她在学校会被人欺负的 +不会被人欺负的 +你声音太大了 +怎么了,没有什么害羞的事吧 +要是大马赛克的话就行 +我也打,她也打要是打马赛克, 就不知道什么意思 +只要拍下你不就行了,我们不要了 +不要打马赛克 +没有其他的方式马 +你喜欢爸爸吗 +不知道 +你是怎么看待爸爸的工作的? +不知道 +你想要爸爸吗? +怎样都行 +多久见一次面? +是半年一次吧 +半年? +是 +不死一月一次吗 +不,半年一次很好 +他是说一月一次 +那是限度吧 +没有离婚吧 +打算离婚的 +我 +我打算离婚 +不知道他是怎么说的 +和小孩还有联系 +对孩子倾注的爱 +不会倾注吧 +是的 +大佐藤先生说女孩也没关系 +那绝对不行的 +这不是不好吗 +怎么看都觉得不好 +绝对讨厌 +你现在做什么工作? +我现在在朋友的店里帮忙 +是 +那里的社长是我的朋友 +竞争是比较激烈的 +原来如此 +是 +这个录影带 是 +能给佐藤先生看吗 +是,那当然了 +是这样的感觉 +感觉好吗 +不是这样的打算 +是这样的情况 +你丈夫是怎样的人? +是很普通的日本人 +夏 +好热 +是的 +今天大概不会下雨 +保险起见 +很热吧 +是的 +很热 +出现怪兽了 +怪味兽 +身体会发出怪味 +这是怪味兽的习性 +怎么回事 +你在干吗 +什么? +因为你在这里 +有多不方便你知道吗? +我做怪味兽很多年了 +不用你来说 +总之你不能来城市 +你快逃到郊外去 +你这算什么 +拿着棒 +那是什么? +恐怖的表情 +彼此彼此 +罗嗦 +我说,那个 +大婶,在这种时候 +谁是大婶? +什么? +什么? +我不知道你的年龄 +你光是站在这里 +就会让交通阻塞 +这个我不管,把车这样不就行了 +你别这样 +会给汽车添麻烦的 +别... +别这样 +你不要弄碎玻璃 +去死 +我是保护这个国家的 +你闭嘴 +你是从哪里来的 +关西 +滚回去 +我刚来 +你的目的是什么? +不能告诉你 +你快滚 +你看看 +一直跟着我来的 +等等 +那是什么? +是想和谁较量吗? +是的,想和我打 +一直跟着我 +不... +这不行 +在这里发生那样的事绝对不行的 +你看着 +他还是小孩,才10几岁 +绝对没事的 +不... +别这样 +绝对不行 +我知道了 +谁会理他 +他只是个傻瓜 +可是他很有热情 +只有那个 +要开始了 +声音变大了 +你真烦 +等等,你想说什么 +你也对他说说 +你 +你,请别这样 +你在做什么,你啊 +不管有多兴奋 +完全感觉不到你是个女人 +这算什么 +童之兽 +要回到郊外 +这是童之兽的习性 +还有任务 +妈妈 +妈妈 +我要快点 +这个怎么说呢 +是不同的东西 +在转最后一圈的时候 +相差很多 +即使相差没有那么多 +头脑中还是知道的 +向着终点 +总之 +就是这么回事 +妈妈 +我要快点 +好痛 +事情变得很严重 +什么? +什么 +你杀了小孩 +上次的事 +这次... +杀了无抵抗的孩子是事实 +对他的印象有了很大的改变 +想要对他采访 +他没有来让我很吃惊 +我没杀人 +原本那种事,没事的,你喝吧 +谢谢 原本是那样的 +我没杀人 是么 +只是时机不好 +一周一次吧 +相反的为何不行 +我没做什么坏事 +他咬了你奶子 +杀死他也是... +奶子是很重要的 +还有那里 +下次你什么时候回去 +不要 +为什么,请做吧 +数字很好 +你别再说什么数据了 +不是这种事吧 +快到终点了 +我不感兴趣 +这是很好的 +我一点都不感兴趣 +你害怕吗 +什么什么? +杀了孩子 +我为何要害怕? +像是恐惧 +我之前就想跟你说的 +是 +并不全都是可怕的 +是么? +总之 +要是我有什么不测的时候 +那么... +我最在意的是 +谁来照看第四代 +要是我遇到不测的时候 +第四代 +由谁来照看? +送到老人院吗? +不能送去老人院 +上了年纪吧 +不是那个,是心意 +我受过第四代的照顾 +他对我有恩 +恩义? +我要表表心意 +对了,还没有问你小时候的事 +我不喜欢 +是怎样的孩子? +是怎样的孩子呢? +是个很普通的孩子 +很胖吗 +有点,只是一点点 +多少? +是个健康优良儿 +有没有减肥 +没有 +第五代,我父亲的教育 +是叫我不停的吃 +你有一天必须要成为大日本人 +有这样的教育方针 +你父亲去世了吧 +也有不好的方面 +为何那样? +因为眼睛不好 +喜欢出格的事 +你害怕吗? +那是很过分的 +总之对身体还没有完全发育的 小孩的我 +那个 +想要给我通电 +没事吧 +不是没事 +我还没有做好心理准备 +还是小学生 +痛吗? +我很害怕 +不知道是怎么回事 +那个... +是古怪的吗 +是第四代的爷爷 +在通电前阻止就没有意义了吧 +被电到了吧 +可是 +通电了吧 +要是没通电的话 +更加悲惨吧 +你很强 +什么 +酒量 +什么啊,不仅是酒量 +什么 +我要回去了 你没事吧 +什么 在下雨 +我有这个 +那是什么? +是折叠伞 +你今天带来了吗 跟你说了一直带着 +你真行 +我是大日本人 +喂 +我刚刚出来了 +接下来请看拍摄实况 +美国英雄超级贾斯特斯! +超级贾斯特斯之父! +母亲. +斯特乌兹米 +青春期的妹妹德塔齐米! +婴儿毕玛宝宝! +超级贾斯特斯开始射击 +不要输,超级贾斯特斯 +我看见了,贾斯特斯 +很高兴见到你 +我赢了 +我赢了 +组合... +组合 +是 组合 +组合 +组合 不要了 +一定要 +是 +那么 +组合 +没什么关系 +组合 +我要回去了 +谢谢 组合 +不,我不会飞 +组合 +组合 +一定要 +好 +没事吧,我害怕 +没事吧 +组合... +组合 +对不起,对不起 +我的鞋子 +剧终 +主演松本人志 +主演竹内力 +务必尝尝 +不好意思 +干杯 +什么 刚刚做了什么? +不行吗? +让我看看 +是很普通的 +是什么 +除我之外的没有94分的 +不是这样吧 +一开始是怎样的? +开巴士来 +突然间巴士变成红色的 +一般是巴士吧 +有使用动物的作业 +作为英雄是很棒的 +那么是什么? +一般是这样的 +你太守旧了 +跟新的不同 +一开始就要战斗吧? +从那里开始吧 +不是的,是巴士 +突然间是很难明白的 +你听我说 +我说了这是很难看的 +突然开巴士来 +首先是拳击 +还有踢,先从基础开始 +中间或许有巴士 +一开始绝对不能用巴士 +是么 +不管怎么看,都不好 +非常的丑陋 +哪里? +从整体来看 +是么,感觉... +你是怎么想的 +像是这样的感觉 +你在听我说吗 我在听 +我并没有生气 +还有你 +必须一个人干下去 +我不能一直都照顾你 +我知道,妈妈 +知道吗? +我知道 +顺序不好,看来很丑陋 +希望你做的顺利点 +我是说这个 +原本 +宝贝是第一的 +那是决定好的 +我觉得这样很好 +最后你的踢脚 +踢的很好吧 +我踢到了 踢到了就结束了吧 +我踢到了 +有客人在,你不要那么大声 +我生气了 +一般当然是给小孩了 +结果是这样 +你不觉得很土吗 +不仅如此 +我知道 我很生气 +我知道 +一定要 +你不明白 +你真烦,我明白了 虽然你总是这么说 +但其实不明白吧 +我都听见了 你完全没有听见 +不是的 +那个时机不好 +对不起 +你觉得这样很好吗 +不要怪我 你是傻瓜 +不要怪我,不要这么大声 +不觉得害羞吗 +你总是这样子 +适可而止 +一定要 +太好了 +打一拳就好了 +的确如此 +我觉得很害羞 +为这样的孩子感到丢人 +什么 +太不像话了 +最后你想怎样? +想要打人吧 +你要清楚点 +太不像话了 一定要 +要像这个人 +顺序不好 +太过分了 +这么说是他吧 +你别用手指指人 +是他 别用手指指人 +在加入的时候 +全都是他不好 +你是叫佐藤吧 +是吧,你 +所以大家组合的时候是什么 +你说了什么 +为什么那么做? +不,那个是 +他不知道 +一般会知道的吧 +一般是不知道的 +你要清楚点 +适可而止 +一定要 +希望你伸出手 +客人没有说 +今后必须要保护 +这是无关的 +希望你进去 +先跟你说清楚 你要到最后 +全体在一起的时候 +我也在 +一定是那样的 +你在旁边做什么? +你一直在说什么吧 +那是什么 +那有点丑陋 +或许不知道 +我们在飞起来的时候 +是没有意识的 +所以向旁边看的话 +是不是很丑陋 +要看周围 +所以有点害羞 +你为何一直说这个 +我要杀了你 +杀人不行 +杀人是不好的 +坐下来 +一定要 +导演松本人志 +如今 +我们迷路了 +没有 +这是近路... +亲爱的 我们都开了一小时了 但一辆车影都没见到 +Molly 我会看地图 知道吗? +不久前刚经过一个加油站 +调头回去问问别人 +那可是40分钟前了 +我可不回去 +别这样 +又为这些事争吵吗? +男人也会有问路的时候的 +不 我们不回去 +男人天生就这样 +路线我清楚得很 +哦 那好 在哪? +99号高速路 行了吧? +就快到了 +99号高速路 嗯? +你瞧 到处看看风景也不错 +David +今天是我们结婚纪念日 就这样耗在兜圈上吗? +我知道 +我很抱歉 +那我来补偿一下 行吗? +过来 +别 我生气了 +哦 过来 Molly +嘿 你会喜欢的 +不 我不想 +你真混 +David 我说真的 +Molly! +David? +David? +David? +David? +Da David? +! +David? +! +David? +嗨? +有人吗? +嗨? +是你 +你没事吧? +我很抱歉 +当时没看见你 +你... +你受伤了? +先生? +凶鬼恶灵 第二季 第16集 时间轴: +何何 @人人影视 +停车! +停车! +该死... +你们得帮帮我 +求你了 +求求你! +好的 好的 +冷静点 冷静点 +告诉我们发生了什么 +我.. +猛打方向盘 之后车失控了 +当我醒来 车毁了 我丈夫不见了 +我去找他 可是之前路上的那人追了过来 +他看起来是不是像被割的七零八落的 +你怎么知道? +我猜的 +女士 你叫什么? +Molly +Molly Mcnamara +或许该和我们一起走 +我们把你送到镇上 +我不能 +我得找到David +他也许会回到车那儿去 +我们先把你送到安全的地方 +之后Dean和我会回来 +帮你寻找你丈夫 +不 +找不到他我哪儿也不去 +请把我带到自己的车那里 行吗? +没问题 +上车 +"公路杀手" +就在那儿 +我不明白 +我肯定当时就在这里的 +我们就撞到那棵树 +这... +怎么可能 +Dean 我们要敢紧离开这 +Greeley随时都可能再出现 +我们怎么和她说? +实情? +她会离开 跑到别处去的 +我知道听起来叫人难以置信 但是我当时真的撞到这棵树 +不知道谁把车移走了 +整辆都被移走了 +你们必须要相信我 +Molly 听着 我们相信你 +所以想帮你离开这里 +那David怎么办? +一定有什么事情发生 +我要去报警 +报警 好主意 +我们带你去警察局 +快来吧 +对你和你丈夫都好 +好的 +我们本该在太浩湖了 +你和David? +我们的5周年结婚纪念日 +可怜的周年纪念 +不久前 我们还在冷战 +当我们被困在车里时 才能真正的吵上几句 +是啊 +我很清楚那种感觉 +你知道我最后一句说的什么吗? +我说他是个混球 +哦 天啊 +万一那是我和他说的最后一句话怎么办? +Molly... +我们会查清楚你丈夫出了什么事 +我保证 +- 是你? +- 不是 +你这么说我还真有点担心 +这首歌 +什么? +我们出车祸时也在放这首歌 +她是我的 +她是我的 +她是我的 +那是什么? +坐稳 +你在做什么? +那是什么... +刚才怎么回事? +别担心 Molly +没事的 +言之过早 Sammy +我想他不会放过她的 +这不可能 +哦... +相信我 已经发生了 +哦... +那好 +多谢帮忙 但我想我该告辞了 +等等 +Molly Molly 稍等一下 +离我远点 +别这样 听我说 +别过来 +我们遇见你完全是个巧合 不是吗? +你是什么意思? +要不是遇见你的话我们也不会在此 +早就离开了 +猎杀 +猎杀什么? +鬼怪 +别... +对她说真话 +你们疯了 +是吗? +比流着肠子消失的家伙更疯狂吗? +你清楚自己看见的 +那人名叫Jonah Greeley +是个当地农民 15年前死于这条路上的车祸 +别说了 +每年中在他的忌日的夜晚 他就在这条路上作怪 +这就是我们来这的原因 Molly +来阻止他 +那我想这个幽灵也把我的车弄没了 +恐怕更糟 +嗯? +知道吗? +我可没发疯 +我自己去报警 +说句难听的 我觉得你根本走不远 +你是什么意思? +就是计划A是把你带走 +显然没成功就因为 嗯 这个农夫马路杀手 +Moly 我们说的都是实话 +Greeley是不会放过你的 +你们... +说真的 是吗? +绝对 +每年 Greeley都会他的死而杀人 +今晚选中了你 +为什么是我? +我没做什么 +跟这些无关 +有些幽灵看见谁就盯上谁 +你们的意思是 Greeley绑走了我丈夫? +哦 天哪 +Molly 我们会帮你的 +但是首先 你得帮我们 +帮你们? +怎么帮? +就是这里 我在这见到他的 +一定曾经是他的杀人乐园 +真是个温柔的家伙 +外边没有墓碑之类的 +你找Greeley的坟墓? +是的 +为什么? +我们可以挖出尸体撒上盐然后烧毁 +哦 +当然 +这是消灭幽灵的途径之一 +这能救David吗? +你们俩个都能救 前提是找到尸体 +那我们怎么找? +嗯 不大肯定 +Greeley死后 他的妻子领走了遗体 +之后她也没再出现过 +猜得没错的话他被埋在这里 +但这可有上千英亩土地 +埋在哪里都有可能 +你们就是干这个的 +鬼怪克星 +是啊 +除了没穿紧身衣 +让你着迷的故事还有很多 +但这条路上的幽灵每年只出现一次 得赶在日出前解决他 +所以边走边说 好吗? +太好了 +我们找什么? +Greeley的房子 +他可能埋葬在那里 +注意道路或是小径之类的 +跟紧些 +好的 +那好 +Molly? +Molly 救救我 +Molly? +David? +David? +David? +嘿! +你没事吧? +那个该死的家伙是不是这样抓走我丈夫? +别太紧张 好吗? +你会再见到David的 +一定会 +嘿 +沿着这条恐怖的砖路走吧 +走吧 +那枪射的是盐块? +是的 +简单的盐就能驱鬼? +小东西往往能派上大用场 +在多数文明里 盐是纯净的象征 能驱除不洁之物 +和驱赶抓住你的那个是同样的道理 +知道吗 我还是头一回想在这种地方 看到一间好房子呢 +外面有墓碑吗? +是啊 +哪有这么简单? +我猜也是 +你们两个检查楼上 +看看能不能找到他埋在哪儿的线索 +我在这边看看 +太棒了 +看这个 +是Greeley和他妻子 +这是他写的情书 +我的天 写的真美 +真不明白这样的人怎么会变成那种妖怪 +像Greeley这样的鬼魂 他们... +就像受伤的动物 +迷失在... +无尽的痛苦之中 他们要宣泄 +为什么? +为什么要留在这儿? +他们的一部分 +把他们留在现世 +比如遗体 或者 呃... +未了的心愿 +对 +也许是复仇 +也许是爱 +或是仇恨 +不管是什么 他们太过于执着 +无法放手 +他们被困住 +陷入无尽的循环 +同样的悲剧一遍又一遍的重演 +你好像很同情他们 +因为他们并不是坏人 你知道 +很多本性善良 +只不过... +发生了一些事 +他们不能控制的事 +一说到这种事 Sammy就像J Love Hewitt一样 +Jennifer Love Hewitt: +鬼语者的主演 +我呢 可一点也不喜欢他们 +也绝不会向他们道歉 +楼下什么也没有 +你找到什么线索了吗? +呃 只有他们以前的信和账单之类的 +我翻了翻 还没找到有关坟墓的 +什么? +后面有东西 +拿着 +从里面锁上了 +闻起来像个老太婆的房间 +这就说得通了 +现在我们知道为什么没人再见过她了 +她不想一个人独活 +Dean 帮个忙 +来真的? +你要干嘛? +不能就这样把她留在这儿 +为什么不? +她应该得到安息 Dean +见鬼... +如果你们能让Greeley安息... +他们会怎么样? +女士 这个问题可超过我们的能力了 +你们猎杀这些鬼魂 却不知道他们会怎么样? +反正没有一个回来过 +这就行了 +当他们放弃了让他们留在这里的东西 不管是什么 他们就... +就这样走了 +希望他们去了更好的地方 但我们不知道 +没人知道 +你们烧了他们的尸骨以后会怎样? +我爸说过 就像鬼魂的死一样 明白么? +可是... +事实是 我们还是不知道 +没法确定 +也许这就是我们拚命求生的原因 +死者也是如此 +我们都只是害怕自己不了解的东西 +我唯一害怕的是失去David +我得再见他一面 +一定要 +我觉得咱们应该告诉她她丈夫的事 +不行 +Dean 这太残酷了 她这么想她丈夫 +我不想瞒着她 +这是为了她好 +我知道你觉得内疚 可是咱们得按计划行事 +带她离开这儿 +然后再告诉她 +告诉我什么? +你们瞒着我什么? +是关于David的对不对 你们知道他怎么了 +Sam 别... +别什么? +别告诉我 因为我会搞砸你们的行动? +你们根本不关心我或我丈夫 +不是的 +真的? +那就告诉我 不管是什么 求你了 +他来了 +和她呆在一起 +Dean! +他抓走了Molly! +这家伙真死心眼 +我们得找到Molly +我们得找到Greeley的尸体 +还有 呃 不是催你 不过离天亮只剩下不到两小时了 +嘿 +找到什么了? +1992年2月6日 +车祸之前2个星期左右 对吧 +对 +看起来像是狩猎小屋 可是... +我敢肯定他们站的这个地方有颗树 +早该想到了 +什么? +这是一种乡村的老传统 Dean +种树作为墓标 +你简直是个活的怪事大百科 +是的 我知道 +David在哪儿? +你把他怎么了 +你不用担心他 +哦 天啊 +你该担心你自己 +我又没对你做什么 +哦? +我知道 我知道你妻子的事 +就算折磨我也不能让她回来 +我妻子已经不在了 +我只剩下... +折磨你了 +求 求求你 +放我走吧 +走? +你哪儿都别想去 +永远别想离开 +去救Molly +哦 感谢上帝 +叫我Dean就好 +这家伙真把我惹急了 +快点 Sam! +哦 心肝儿 今晚真够漫长 +好了 +咱们离开这儿 +我哪儿都不去 除非告诉我我丈夫怎么样了 +Molly... +我一直在找他 你们知道... +你们知道Greeley杀了他 对吧? +他死了? +不 Molly +David还活着 +什么? +你确定? +是的 +我们带你去见他 +来吧 +他就在那边的房子里 +我不明白 +你会的 +这不... +不可能 +怎么回事? +那是谁? +David的妻子 +对不起 Molly +15年前 你和你丈夫开车撞死了Jonah Greeley +David活了下来 +你在胡说什么? +我们是说41号公路上不只有一个鬼魂 +而是两个 +Jonah Greeley 还有你 +在过去的15年里 每年的那个晚上你都会出现在公路上 +不 这不可能 +昨天是我们结婚一周年纪念日 2月22日 +1992年 +对 +Molly 现在是2007年了 +哦 天啊 +好了 说说41号公路吧 +15年里发生了12起事故 +5起有人死亡 所有的事故都发生在同样的晚上 +那我们找的是 州际死亡地带? +幽灵搭车客? +还是什么? +不完全是 +每一年目击者说是同样的东西害他们出事 +一个女人出现在路中间 被一个浑身是血的男子追赶 +两个幽灵? +Molly葬在哪里? +她 她没有被土葬 +她被火化了 +她的尸体被火化 +对 是什么让她还留在世上? +有些鬼魂只看得到自己想要的 +David? +David? +停车! +快停车! +帮帮我 +Dean 我想她还不知道自己死了 +求求你! +开门! +求你了! +好了 好了 +冷静点 +告诉我们出什么事了 +你要告诉她什么? +实话 +她会跑走的 +有些鬼魂太过于执着 +无法放手 +那Greeley呢? +每年他都要把自己的死怪罪在别人身上 追杀他们 +折磨他们 +每年 这个人都是你 +但我什么都不记得 +因为你看不到事实 Molly +这就是为什么他不让我离开公路 +因为... +是我杀了他 +我把我们两个都害死了 +为什么不在看到我的时候就告诉我? +为什么要等到现在? +你不会相信我们的 +而且你们要我当诱饵 +对 我们需要你 +David +Molly 我们带你来这儿是为了让你能放手 +我得告诉他 +告诉他什么? +你爱他? +还是你很抱歉? +Molly 他已经知道了 +要是你想进去 我们不会拦着你 +对 但是你会吓坏他 +吓死他的 +David已经用他的方式说了再见 Molly +现在轮到你了 +这就是你未了的心愿 +我该怎么做? +只要... +放手 +David和所有的一切 +你那么做... +我觉得你就能走了 +可是你们不知道会去哪儿 +不 +Molly 你不属于这个世界 +难道你还没有受够折磨? +时候到了 +是你离开的时候了 +我觉得她还不错 +作为一个鬼 +你真的觉得她会去一个更好的地方? +希望如此 +我猜我们永远不会知道 +直到我们自己亲身体会到 是吧? +无所谓 Dean +希望是最重要的 +好吧 Haley Joel +[饰演《第六感》里的那个小孩的演员] +上路吧 +你不会相信 我替你杀的人会复活 +罗洛托尔斯 你欠债 你一定要还债 +否则你不能活着 看我是否说实话 +欠债? +你认为我欠你多少? +克伦斯说你知道 +我从17岁就没有 被人用枪指着头 +而今晚 +今晚 +今晚还没有结束 +你不能离开 +你活不久 +不管你是谁 +你不知道我是谁 +这本来是友善的拜访 托尔斯先生 +你的烦恼都结束了 你应该松一口气 +你的还没有结束 我保证 +谁都不能对我这样! +没有人这样对你 +你没有办法阻止 +一遍又一遍又一遍 +做好了再做 +刚开始就结束 +手骨 人手 骨头人 +一遍又一遍又一遍 +做好了再做 +刚开始就结束 +刚开始就结束 +刚开始就结束 +刚开始就结束 +想看魔术吗? +你有问题 +问题? +居然用枪指着他的头 你这个疯混蛋! +我不会砍头 我同意时跟你说过 +我说过让我处理 +你应该处理 +这全是误会 还来得及到那里然后 +我不会回那里 +才怪! +你看不到全貌 +关系到的不只是我们的命 +关系到什么? +克伦斯 那个人是谁? +为什么尽快解决这麽重要? +没时间解释 +你在那里等五分钟 让我有机会跟他谈 +我不会在这里等 +这里是敌区 +我挂了电话马上离开 +那麽五分钟后 打电话到糖果店给我 +我没有带零钱 +那就打对方付费电话 +听好 混蛋 +你害我们惹上麻烦 要给我机会解决 +我五分钟后离开 +你最好打电话给我 +(主演 戴伦威尔) +(主演 艾德奥罗斯) +片名 杀手无名 +接线生 要打几号? +史丹菲66286 +请等一下 我替你接 +谢谢 +好了 不要再按铃了 该死! +我来了 第一次就听到了 +我来了! +我还没有聋 该死! +当然是你 莫迪曼先生 +不然还有谁? +让我猜猜 你的钥匙又弄丢了? +对不起 你大概弄错人了 +如果你想表示什么 我不明白 +如果是笑话 我并没有笑 +我一点都不知道你在说什么 +我15分钟前发现 挂在门柄上 +门开着而且没有行李 +我看你想溜走 +对不起 +对不起 我不知道头在哪里 +很漫长的一个夜晚 +先生 你连一半都不知道 +你再弄丢就不给你了 我保证! +谢谢你 对不起 +嗨 莫迪曼先生 +房间在哪边 记得吗? +狗屎! +笨蛋 你懂什么? +一秒钟前你以为是糖果 +我虽然不知道它的名字 但不表示不知道是什么 +它不是一个人 +你不知所云 +对 我不知道 +我甚至不知道你说什么 +这场谈话让我头痛 +我什么都不想说 但我闻到尿味 +好 你走吧 +我好像没听到 +你听到了 把你的臭嘴带走 +把小甜甜也带走 他让我毛骨悚然 +把门关上 +贝马许和柯威尔在湖上 +唐保姆和法兰科在船屋里 +我刚在码头上见到班吉 +最后还有我们 +我告诉你 罗洛 +接下来几小时谁都动不了你 +你只要确定比我先死 +耶稣 我在地狱里 +拜托 主啊 让我熬过今天晚上 +我求你 +如你所愿 +谁呀? +是谁呀 该死! +罗洛? +伏斯柏? +老天 伏斯柏 +你在干什么? +你开枪打谁? +没什么 +没什么 只是意外 +意外! +罗洛 你 +关掉该死的灯! +关掉! +好 关掉了! +别紧张 +现在出来 +好 你要装子弹时叫一声 +我的枪 +我的枪在哪里? +在哪里? +在哪里? +我的枪在哪里? +你在这里 +是的 +嗯 你想怎样? +我已经办好了 +你没有 你跟克伦斯在一起 +是的 +老天! +你是怎么进来的 +老天! +我以为你 +你夺走我的枪 +你在开枪 +我 +我以为你是别人 +我不是 +你说的别人也不是 +什么意思? +他死了吗? +他死了 我活着 +确定是他吗? +他脸上戴了黑面纱 +是他 老天! +头在哪里? +我离开时还在他肩膀上 +胡说! +胡说! +我跟克伦斯说过 我要他的头 我告诉他 +我建议你自己去砍吧 +我相信你有东西给我 +是的 +我有东西给你 +我要问这是什么吗? +一块钱 混蛋! +为你没有做的事付的钱 +并不是我欠你的 +你误会了我的角色 托尔斯先生 +我不是你做的协议 讨价还价的人 +我不是来谈判的 +你想吓我吗? +你连脸都不敢露 +这不表示你不该害怕 +你这个可恶的家伙 +你不相信我并不会使 我替你杀的人复活 +罗洛托尔斯 你欠债 你一定要还债 +否则你不能活着 看我是否说实话 +欠债? +你想我欠你多少? +克伦斯说你知道 +我从17岁就没有 被人用枪指着头 +而今晚 +今晚 +今晚还没有结束 +你不能离开 +你活不久 +不管你是谁 +你不知道我是谁 +这本来是友善的拜访 托尔斯先生 +你的烦恼都结束了 你应该松一口气 +你的还没有结束 我保证 +任何人 +谁都不能对我这样! +没有人这样对你 托尔斯先生 +你没有办法阻止 +接线生 要打几号? +史丹菲66286 +请等一下 我替你接 +谢谢 +克伦斯? +你在吗? +我听得到你的呼吸声 可恶的混蛋! +趁还能的时候享受吧 +因为只要我还能活一天 +我对天发誓 +我就会用想得到的最刻薄手段 让你从地球上消失踪 +对你那个狗屁贼要加倍! +我知道出了差错 我知道! +他没有杀任何人! +人头还接近在会呼吸的脖子上 所以他不能拿回来 +他还活着! +听到没有 活死人? +他还活着 +还活着! +这里就是了 +他拿着一把开山刀 站在坟墓上 +他戴着面纱 +混蛋! +每次都这样! +他们好像在外面看着我 等我 +停! +不要按铃了! +该死! +我来了! +第一次就听到了! +我来了! +我还没有聋 +你需要什么? +我很抱歉打扰你 但我的房间钥匙又丢了 +朋友 我们这里没女人 +要女人就自己找 +我们整夜都开 价目表在墙上 +不问问题 没有列外 +我不要女孩 也不要另外开房间 +我姓莫迪曼 +我住223号房间 +我的房门钥匙又弄丢了 +又一次? +是的 +223房的钥匙? +是的 +挂在223钩子上的钥匙吗? +你比自己还快 莫迪曼先生 +不知你住的地方怎样 +但这里的人要先租房间 然后才能拿钥匙 +权利都写在墙上 不问问题 没有列外 +我要223房 +早说呀! +223房 +走楼梯上去到左边 然后第一个弯左转 +罗洛托尔斯! +你大概是开玩笑 +什么? +这地方跟别处一样好 +我们离岸30尺 柯威尔 +那麽? +冰融化怎么办? +有人在这里游泳 知道吗? +这里会有小孩玩水 +他会踢到其中一人的脸 +你看到水桶多大 +你知道谁要把它们提到这里 +你想走多远? +要远到他们的头 不会从洞里伸出来 +可怜虫最后跪在教堂前的地上 乞求上帝 +主啊 我一辈子都是好人 +我遵首尾每一条规矩 做你叫我做的所有事 +你每次都诅咒我 +你夺走我的一切 我的家人 我的家 +我的视力 我的腿 我的整个世界 +我还是赞美你的名 +你为什么一直这麽惩罚我? +然后尖塔倒在他身上 +他向上看时 最后看到的东西 +喂 伏斯柏 不想听吗? +第一次听就不好笑 +小心不要踢到这个 +说什么 班吉? +你以为呢? +小心别踢到这个! +好 好 +几点了? +我没有手表 +沙漏就在你面前 +这是沙漏 看不出时间 只能看时间过了多久 +想想过了多久时间吧 +然后从开始的时间算起 +我不知道几点开始的 +老天! +你看看这个! +太厚了 像是假的 +我怎么跟你说的? +不要靠近窗口 +没有人能看到我 +你不能确定 +当然可以! +如果我能看到外面 表示这里比外面黑 +这表示外面的人看不到我 +除非脸贴在窗子上 +香烟怎样 大教授? +那有多黑? +你远离窗口 好吗? +你让我紧张 +所有的事都让你紧张 +唐保姆和法兰科怎样? +他们不会有事 他们天生要看水泥变干 +其他人呢? +真想知道吗? +昆西当然是发疯了 +法兰科说他们用扳手 打他的头整整两分钟 +他们还比他先累 +至于其他两个人 装在袋子里很难说 +女的好像已经死了 小孩的头还在上面 +在哭吗? +没有听到 或许吓得不敢哭 +换了我也会 +你说都不要说 +这不是笑话 +什么是笑话? +我还是不知道 为什么要在这鬼东西上 +你用不着知道 只要安静的坐着 +你连这都做不对 +你看""小甜甜"" +你没有听到他唠叨 +""小甜甜""不会唠叨 +你看他 几乎不在这里 +他在这里 +他在做叫他做的事 +相信我 如果事情 跟我想的一样 +你会感激我让你坐在船上 +不浮在水上就不是船 +这里的水在五尺厚的冰下面 +他们最后才会到这里找 +他们是谁? +克伦斯吗? +别管克伦斯 我们要做就做吧 +说真的 罗洛 我从来没见过你这麽 +没看过我怎样? +犹豫! +没看过你像这样犹豫 +你这麽紧张 我也该紧张吧? +只是我不知道要紧张什么? +知道因果是什么吗 伏斯柏? +因果? +好像是一种糖果 +不是糖果 白痴 +那是宇宙的平衡 +宇宙的平衡 +你在看什么鬼书? +相信你这辈子做的事 下辈子会报应在你身上吗? +我相信就不会在这里 +没有宇宙对抗你 你就已经够危险了 +几小时前我会同意你的话 +什么东西让你改变主意? +头上撞了一个包吗? +不是东西 +而是人 +谁 罗洛? +因果不是人 +唯一的人是在黑暗里的你和我 +你懂什么 笨蛋 +一秒钟前你还以为是糖果 +我不知道它的名称 不表示不知道是什么 +它不是一个人 +你不知所云 +对 我不知道 +我甚至不知道你说什么 +这场谈话让我头痛 +我什么都不想说 +但我闻到尿味 +好 你走吧 +我好像没听到 +你听到了 把你的臭嘴带走 +把小甜甜也带走 他让我毛骨悚然 +贝马许和柯威尔在湖上 +唐保姆和法兰科在船屋里 +我刚在码头上见到班吉 +最后还有我们 +我告诉你 罗洛 +接下来几小时谁都动不了你 +你只要确定比我先死 +这不是我要的东西 +跟一个疯子玩""追随领袖"" 该死! +是谁呀 该死! +罗洛? +你在干什么? +你开枪打谁? +没什么 只是意外 +意外! +罗洛 你 +关掉该死的灯! +关掉! +好 关掉了! +别紧张 +现在出来 +好 你要装子弹时叫一声 +混蛋 +我的枪 +在哪里? +你在这里 +是的 +嗯 你想怎样? +我已经办好了 +你没有 你跟克伦斯在一起 +是的 +老天! +你是怎么进来的 +老天! +你差一点 +你夺走我的枪 +你在开枪 +我以为你是别人 +我不是 +你说的别人也不是 +什么意思? +他死了吗? +他死了我活着 +没有发生这种事 +此刻的任何事都不可能 +不可能发生 +也许我在做梦 也许我在别人的梦里 +不知道是什么没关系 +知道不是什么就够了 +这不真实 +没有关系 +我不会丧失踪理智 +不会丧失踪理智 +我感觉他在这里 +我开始走路 +这些是事实 +我走过的世界不理性 荒谬 +即使如此还是世界 还是有一套规则 +不论规则多麽荒谬不理性 +如果能找出规则 在体系内运作 +我就不再是世界的 无知受害者 +就是这里 +疯狂循环就在这里被打断 +它为我打开过一次 再也不会了 +看得到我的人 我不存在 我是谁? +没有用 宝贝 +停止是锁 谜是钥匙 答案不是免费的 +又是你 +欢迎你回来 欢迎客人 +这次有零钱吗? +有什么可以施舍给瞎婆子吗? +还是你带答案来了? +什么的答案? +谜! +看得见我者 我不存在 我是谁? +要玩才能通过 付费才能玩 通过要付费 +让路吧! +图案需要三个人 其中一人是我 +这里是我家 孩子 +这是我的路 +安静! +无名小卒不能说""不"" +唱同样悲怆的歌 一遍又一遍 +留声机和断骨 +唱同样悲怆的歌 一遍又一遍 +你有问题 +我不会砍头 我同意时跟你说过 +你应该处理 +我不会回去 +我五分钟就走 +想看魔术吗? +看得见我者 我不存在 我是谁? +没有用 宝贝 +停止是锁 谜是钥匙 答案不是免费的 +又是你 这是你做的! +开门! +你回答我的问题 门就会自己打开 +来吧 别说你忘了 +这不是游戏 +不是游戏 是谜! +想想其实很简单 +看得见我者 我不存在 我是谁? +我没有答案 +白银 这会有帮助 闪光是线索吗? +给穷苦残障的人一点钱 +我没有 +等一等! +留声机和断骨 +唱同样悲怆的歌 一遍又一遍 +一遍又一遍又一遍 +知道吗? +两个人做会快很多 +好主意 +我去找人来 +混蛋! +不能跟他说话 小甜甜 +不可能! +知道要怎么处理吗? +只能跟着罗洛七上八下 直到他把自己累垮 +然后让他睡觉 我们回家 +家 说到这个字就让我 眼皮沉重 +几点钟了? +小甜甜? +小甜甜? +小甜甜 +我自言自语多久了? +小甜甜 +小甜甜 +小甜甜 +哈 有收获了 搞什么 +法兰科! +法兰科! +什么? +你可以到这里吗? +为什么? +只管出来! +不 我要躺下 +你会错过 +你会错过 +错过什么? +我会错过什么? +你快点好吗? +最好值得! +如果我出去 而只是兔子 那种愚蠢的东西 +我会要你付大代价 +那个混蛋! +拿起电话吧! +小甜甜! +来吧! +我不需要你对我发疯 +小甜甜? +小甜甜 你在里面吗? +说话呀 笨蛋! +你像这样溜走时最好出声 +否则我要把铁罐绑在你的 +老天! +时间到了 混蛋 +有什么好笑吗? +好像似曾相识 +真的? +可惜没有早一点发生 +我知道他撒谎! +那个该死的混蛋 +你派他来杀我 +不然要我怎样? +我知道你迟早会回来 你自己说的 +我从来没有回来 罗洛 +是你的行动把你带到我这里 +现在怎样? +接下来会怎样? +你知道因果是什么吗? +从来没有听过 +东方人相信宇宙平衡 +相反而相等的力量 +你这辈子做的事 下辈子会报应到你身上 +你觉得怎样? +不知道 +别把它想成宇宙或神秘的事 +想成简单的因果关系 简单的物理学 +我会想 +希望别想太久 +我不能等到下辈子 +把电话拿起来 +打电话给谁? +你以为呢? +我不能 +为什么不能? +我不知道他是谁? +你怎么找到他的? +跟我找到你一样 +透过克伦斯? +克伦斯 对 +打电话给克伦斯 +我试了半个钟头 但他没接电话 +再试一次 +他不会接电话 +我现在就告诉你 +如果我是你 我会往正面想 +如果他接电话要我说什么? +随便你说什么 +我告诉你不可克伦斯? +克伦斯 你在吗? +我听得到你的呼吸声 可恶的混蛋! +趁还能的时候享受吧 +因为只要我还能活一天 +我对天发誓 +我就会用想得到的最刻薄手段 让你从地球上消失踪 +对你那个狗屁贼要加倍! +我知道出了差错 +我知道! +他没有杀任何人! +人头还连接在会呼吸的脖子上 所以他不能拿回来 +他还活着! +听到没有 活死人? +他还活着 +当时很暗 +我连他的脸都没有看到 +他用枪指着我的头 +然后就消失踪了 +我不知道他到哪里去了 +我知道 +你能告诉我的事 我不知道的很少 +我只是自卫 +你把包里给他了 +不是我给的 是他拿的 +里面什么都没有 +他活该! +他不知来干什么 所以活该! +他来干什么? +确认! +所以你要我的人头吗? +回答! +我对天发誓不知道 +因为这个晚上 这个恶梦 +老天! +回答! +回答我! +否则我从你的大脑里挖出来 +证明 我需要证明 +证明什么? +证明我死了吗? +证明你曾经存在 +上帝 我在地狱里 +求你让我醒来 +我愿意做任何事 +只要让我现在醒来 +在自己家的床上! +罗洛 +如果你在外面 醒来吧 醒来吧! +转身! +我不想看到你的脸! +我想看你的 +转过来! +老天! +跪下! +上帝 求你别杀我 +我不想死 +今晚不想! +经历过这些之后不想 +求求你 我可以做你要我做的任何事 +我愿意做任何事 +求你不要杀我 +瞧瞧你自己 +骄傲而无情的罗洛托尔斯 +跪着像小孩一样哭泣 +求人饶命时尿湿了裤子 +怕你的如果看到你现在 +托尔斯先生 你现在是新人 +但你不会活着欣赏改变 +我今晚要回克劳斯公园 +不论死活我都会出来 +我发誓不论世界怎么运转 +接下来我要找你 +到那时之前 这是你生命的证明 +你不会绕道踩死人行道上的虫 +如果虫跑到你脚底 你也不会让它 +罗洛 +你是虫子 罗洛托尔斯 +罗洛 +罗洛 如果你还在的话 +请你醒来 +从现在开始 你活着的每一刻 +都要知道你还活着 是因为没有重要到必须死 +请你醒醒 +一切都有秩序 +必须有一条途径 让事件自然发生才有可能 +我并不期望你了解这些 +我不确定自己是否了解 +喂 罗洛! +我醒了! +我醒了! +老天 罗洛! +发生什么事? +我们以为你死了 +没死 +我没死! +发生什么? +我昏迷多久? +你几分钟前停止尖叫和躁动 +我进来看你是否安静下来了 +但你倒在地上 全身是血而且在流口水 +老天 真龌龊! +谁替他包扎一下 +扶我起来 +法兰科 替他拿点东西来 +扶我起来 +我猜你被什么绊倒 然后撞破了头 +这是尿吗? +班吉和昆西回来了 +他们找到他吗? +找到他了 +克劳斯公园 +你说什么? +你没听到法兰科的话吗? +班吉和昆西回来了 +他们去哪里? +你是开玩笑吗? +他们在哪里? +在船屋里 要叫他们来吗? +知道要做什么再说 +你出了什么事? +小鬼咬我 +老大 下一步要做什么? +让他们穿水泥鞋子 +柯威尔 找人开始凿冰 碰到水之前不要停 +你开玩笑吗? +你刚才说什么? +你刚说什么? +罗洛 只是一个孩子 +一个小男孩 我家也有一个 我不能做 +好 好 +好 +他也一样 +搞什么? +罗洛! +罗洛! +好 你听到他的话了 +拜托 +这是怎么回事? +罗洛? +你还好吧 +别说话 只管听 +我们抓到你的太太和孩子 +正在替他们穿水泥鞋 懂吧? +别跟我胡扯 +你知道只有一条出路 +今晚此刻 他正要到克劳斯公园 +因为是他告诉我的 +我不要你叫他取消 +我要那个混蛋死 +然后找更厉害的人 +这是你闯的祸 克伦斯 +找人办事吧 +否则我会让你的漂亮老婆 +看你的漂亮男孩 像大石头一样 +沉到寒冷阴暗的湖底 +你明白吗? +还有一点 +我要他的人头 +听到没有? +我要他该死的人头 +给你一小时 +到底发生什么事? +把灯关掉 +就是这里 +他拿着一把开山刀 站在坟墓上面 +他戴着面纱 +就是这里 +他拿着一把开山刀 站在坟墓上面 +他戴着面纱 +你在这里 +是的 +你要做什么? +我已经做了 +我以为你是别人 +我不是 +你的别人也不是他 +什么意思? +他死了吗? +他死了我活着 +做好了 好了 得到了银子 +跟开始一样结束 +他多了一块钱 +他有耳朵听得见另一只 +- +- +- +- +-====翻译: +===== +- +- +- +-- 梅格 紫米稀饭 潇湘夜雨 月生白水 小门柴 校对: +火精灵 +老兄 你他妈的想什么呢 +嗨 伙计 +你还好吧 +不好意思我来晚了 钱带来了吗 +你不买饮料的话 下次就不要来这 +-什么 +-我上周告诉你了 +-该死的别碰我 +-我会报警 滚出去 +你是不是把我当傻瓜? +滚 你这个白痴 +滚 再也别来这 否则我就报警 +我会报警 +你来不来? +-你到底来不来? +-别碰我的窗户 +-再也别回来 +-妈的 整死你 +老兄 你到底来不来? +我没时间 我很忙 +快点过来 +我都安排好了 +我在这呆了一晚上 就是给你安排这事 +没事 没事 +你一般不会在国王路见到我 +警察对那里的乞丐管得挺紧的 +但这里是我的地盘 从十岁起就在这了 +这是我的地盘 勇敢人的家 +那些年我管着这里呢 +我想进商店买点喝的 行不? +老兄 +知道吗 +我把钱忘在家了 +借我一块钱 行不? +就一块 回家就给你 +保证回家就还你 +就一百便士 老兄 快给我 +我就拿50便士 行吗 我马上回来 +白痴 你看什么呢 +真是个笨蛋 +-看 +-混蛋 +-谢谢你 肯恩 +太爽了 我们走 +你在国王路干什么 +-我在附近工作 +-你肯定有份体面的工作吧? +看 那是我以前的家 +挂粉帘子的那个 +我过去用的是蓝帘子 不是粉色的 +-凯拉 你没事吧 +-没事 +-好 不错 +-你去哪 +和这个家伙谈点生意 +-我一会来看你 好吗 +-好 +那是麦凯拉 +她妈妈是妓女 就住在那边 +每次她妈妈有客人 就把她赶出来消磨时间 +你知道最惨的是什么? +老兄 人人都知道 +想象一下 麦凯拉知道每个人都知道 +这是我家 老兄 知道吗 +也... +不算我家 但是我每次吸毒 都来这 +老兄 没有人知道这个地方 +这就象是... +我的秘密窝 +-我帮你把衣服挂起来吧 +-我不会呆很久 +-什么 +-我办完事就走 +老兄 脱下衣服 休息一下 +酷 酷 +告诉过你 我就知道是巴宝莉牌的 +日子真不错 这正是我想要的 +老兄 正是我想要的 +干嘛不和我说你有伏特加 早知道就带可乐来了 +可乐加伏特加 我最喜欢的饮料 +我在索霍区俱乐部里就喝这个 +你不介意吧? +太棒了 太爽了 +太高兴了 +坐 休息一下 你怎么了 +喝点东西 +休息休息 +过来 +你寂寞还是怎么的? +-什么 +-你寂寞吗 +-你想说什么 老兄 +-我只想结束这一切 +好吧 他妈的 +他妈的 把钱给我 +不错嘛 +750块 +什么 +750块 +-我是说800块的 +-昨天给你50了 +-你没给 +-我给了 +-你没给 +-我给了 +呃 那50呀 那50块只是余款 +-什么 +-余款 +道上就是这么办事的 老兄 明白吗? +-那不是余款 +-是 是余款 +-余款是 是一种诚信的体现 +-嗯 嗯 诚信 +诚信的契约 一种礼貌 +-也就是头期款 +-对 +如果那是头期款 这是剩下的钱 +富佬 别自作聪明 +那50块只是保证我能替你解决问题 你出得起钱 +我查过了 你不是警察 +你也查过我不是警察吧 +-什么 警察? +-嗯 警察 +警察 差佬 公安 条子 Po +-po, 条子, five +-oh, one time. +我想每个人都看得出你不是警察 +你想说什么 +妈的 你这个自大的家伙 +你在我地盘呢 富佬 我的地盘 +你觉得我看上去很穷 就以为我是个傻瓜? +我路子多着呢 +妈的 死白痴 +-妈的 +-麦克 怎么了 +麦克? +怎么了 +你要去哪 +出去 +什么意思 我不明白 怎么了 +麦克 求你了 +-你要去哪 +-出去 +麦克 你打不打算告诉我发生了什么了吗 +发生了什么 你要去哪 你要去哪 +塔妮雅 看在上帝的份上 +你要把这东西带到哪 我不问别的 +有点事 现在出去解决 +听懂了吗 现在就去 +麦克 +你少给了50块 告诉过你是800块 +我只有750 +-我们去提款机取 +-不行 +-为什么不行 +-我没带卡 +你还带什么了 你身上还带什么了 +这是什么 +照片不错 看上去你不太舒服 +霍... +霍.. +霍拉提奥 +赫莱西奥 +赫莱西奥・班布赖吉 +你说你叫汤姆 +你会四处告诉别人你叫赫莱西奥吗? +当然 +-这是什么 +-我的工作证 +我要它有什么用 白痴 +别跟我搞鬼 +老兄 我告诉你 我认识的人多着呢 +-你不能这样出去 +-你他妈的让... +-让开 +-你不能走 +-让开 +-不 +-让开 +-不 +你他妈的让开 +-妈的 +-麦克 +麦克 麦克 你冷静一下 +我担心你 我担心我们 +麦克 听着 +我不管你去哪 +我不介意 我理解 你有生意要做 +麦克 你要冷静 +否则你会做坏事的 +那天晚上 这么做管用了 +不 亲爱的 管用了 +求你了 再试一次 为我 +再试一次 +就是这样 就是这样 +再试一次 亲爱的 亲爱的 +阿弥陀佛 +南无... +阿弥陀佛 +阿弥陀佛 +看到了吧? +就是这样 就是这样 +阿弥陀佛 +阿弥陀佛 +南无阿弥陀佛 +-就是这样 +-南无阿弥陀佛 +南无阿弥陀佛 南无阿弥陀佛 +南无阿弥陀佛 南无阿弥陀佛 +你在外面小心点 好吗 +南无阿弥陀佛 南无阿弥陀佛 +南无阿弥陀佛 +南无阿弥陀佛 南无阿弥陀佛 +阿弥陀佛 +南无阿弥陀佛 +南无阿弥陀佛 +南无阿弥陀佛 +他妈的 +那个戒指 +-什么 +-你口袋里的戒指 +-它不只值50 +-跟我有什么关系 +事实是你少了50块 +如果我没得到我想要的 你也不会得到你想要的 +-金子做的是不是? +-是 +-手表呢 +-什么 +-手表 +-你没开玩笑吧? +-该是我的就是我的 +-妈的 +你要去哪? +老兄 +老兄 +老大 +别这样 别这样 +冷静点 好吗 +我刚刚只是试试你 好吗 +看 你把戒指给我了 +750块我就做了 行不 +-兄弟 你去哪儿 +-关你什么事 +我要给迪弄个t +鹦鹉还在窗户那里吗 +那只该死的鹦鹉还在他妈的窗户那吗 +-没有 +-是吗 +-不 没在 +-没在 你这个他妈的杂种 +但是 兄弟 我正爽呢 今天是发失业金的日子 +-我有钱 老兄 +-去你妈的 +我们现在在做生意 伙计 +来 碰一下 喝一口 +来吧 兄弟 +你准备交钱了吗? +我想看看我买的东西 +先交钱 兄弟 +-看到我要买的东西才给钱 +-先交钱 +不行 +好吧 +好 行啦 你想这样玩吗 +你会把事情搞砸的 +知道吗 会搞砸 +看这个 +搞砸了 +该死的你 +-谁 +-霍德维克 +-克里斯托 +-霍德维克 怎么样啊 +-很长时间没见到你了 +-你看见迪了吗 +他昨晚来过 +发生什么事了 小迪给自己找麻烦啦 +算了 +-我不感兴趣 迪身上有钱吗 +-霍德维克... +相信我 要是迪没钱他是走不出那道门的 +-他有多少钱 +-50镑 +50... +他妈的50镑 +现在真的很无聊 +想和我谈? +怎么啦 笨蛋 +真他妈的 +英国他妈最坏的牙买加人 +你死定了 +对啊 那能行 +800镑买这个很便宜 你知道吗 +750 真是物美价廉 +麦凯拉 今天你看见迪了吗 +麦凯拉 +你今天看见迪了吗 +你今天看见迪了吗 +你看到没 +是的 他和一个人在一起 +他跟谁在一起 +-以前没见过他 +-他长什么样 +白人 迪说他要帮他解决问题 +妈的 +操你 迪 +没事 没事 麦凯拉 +没关系 没事的 没事的 +这个白人张得什么样子? +他们去哪儿啦 +你知道 就像 你妈妈有时候给我钱 +你知道 因为她需要我 +那么 我需要你为我做点事 +你得告诉我迪在哪儿 +我得看看 +它就在这儿啊 +是啊 但可能是仿制品 +这是一只38口径的抢 +特别是周六晚上 +老兄 你知道吗 用这个可是能造成很大破坏的 +-他们上那儿去了 +-另外一个家伙也去了? +是的 +相信我 粗鲁的男孩 +你把简单的事情搞复杂了 +-我可是个神枪手 兄弟 +-给我看看枪就行了 +-看了我满意的话 我会付钱的 +-我是个刺客 +-我保证 +-什么 什么 +好吗 付了钱就走 +好吗 +只要我一走 你就能 +你就可以到这儿的烟馆去 抽上一整盒 +怎么样? +-把钱放在桌上 老兄 +-哦 别这样 +别这样 我看起来像会了枪打你吗 +不 不 你不会 +但那不是你要问你自己的问题 +事实上 +我看起来像要射你的人吗 像吗 +像吗 +你干嘛要以貌取人呢 有钱人 +我可是个嗜血的烟鬼 +也就是说我是个危险人物 +你笑什么 +你他妈究竟在笑什么 +我向上帝发誓 不要试探我 知道吗 有钱人 +知道吗 老兄 我已经杀了很多人了 +滚回你的地盘 要知道你和个携抢的烟鬼 +起了点小摩擦 竟然还能活着离开 +听懂啦 +把钱放在桌上 给我滚出去 +-把枪给我 +-你他妈... +-不 +-给我 +-滚开 你他妈在干嘛 +-你他妈把枪给我 +你真是疯了 +你他妈这个肮脏的杂种 把枪给我 +给我! +给我 给我 你 +-你这个杂种 +-你在做什么 +迪 +滚开 +你他妈的同性恋 +上帝啊 迪 把那小东西收好 +霍斯! +发生什么事了 老兄 +还好吗 +那他妈的是谁? +你从什么时候起开始当鸭了 +你从什么时候起开始当鸭了 +-霍斯 兄弟 我没有 +-是吗 +那我进来的时候你们在干什么 +-你赚了多少钱? +-我说过了... +我知道你挣钱了 昨晚你到克里斯托那儿去了 +-你为什么不告诉我? +-我没有在当鸭 +不告诉我是因为你欠我钱 你他妈的烟鬼 +你他妈的欠我钱 +给我他妈的下楼去 +不 等等 +我有几句话要跟迪说 +要是在走之前再看到你 +我会他妈毁了你的 +同性恋 +霍斯 兄弟 轻点 轻点 +你他妈在干什么 两星期前怎么跟你说的 +-不是让你躲起来吗 +-我躲了 那儿都没去 +那你那个小白脸是哪里来的? +-我在街上遇到他的 +-他该死的到底从哪儿来的 +-我是在街上遇到他的 +-哦 是吗 +在他妈的街上碰到的? +轻点 嘿 霍斯 求你 别打了 +-你他妈笨蛋... +-我发誓 我什么都没告诉他 +妈的 你要干什么 霍斯 不要 妈的 +-这看起来像什么 +-妈的 妈的 +在我们干那事后三个礼拜以后 +你竟然随便把个变态同性恋给带回来了 +你他妈不要 +-冷静点 +-我这么做只是为了活命 +霍斯 可我什么都没做啊 兄弟 +-伙计 +-不 你他妈做了 +妈的 +妈的 它在这儿 妈的 +上帝啊 一直在我脑子里 +迪 那个男人可能是特别行动组的 +哦 妈的 +好了 兄弟 呼吸 +南无阿弥陀佛 南无阿弥陀佛 +南无阿弥陀佛 南无阿弥陀佛 +南无阿弥陀佛 +好了 问你个问题 +是不是关于你的钱? +我欠你的钱? +霍斯 我一直在想办法弄钱 但佷不顺利 +我一直在想办法弄钱 我发誓 +一切都搞砸了 记得吗 我去了你家 +-你在那儿很安全 记得吗 +-确实 +昨晚你在我东西边上打转了 是不是 +是吗 +是吗 +那么我的枪他妈在哪里 +我的枪他妈在哪里 +我不知道你的枪在哪儿 +-我没有拿你的枪 我发誓 +-上帝 好吧 +原来我的0.38好端端的在我的浴缸底下 +昨晚你来了 然后今天早上 它就没了 +我发誓 霍斯 我发誓 我没有去过浴室 +我更本没进过浴室 霍斯 我一直都在前厅 +记得么 我一直都在前厅 +求你了 我发誓 我真没拿... +妈的 去你的 +等等 老大 我发誓 那一定是赛夫的手下 +他们来过的 +老大 还记得么 他们来过的 +赛夫是来买白粉的 +他和2个你从未见过面的人一起 +雷和格雷 +格雷很擅长使用武器 霍斯 我发誓... +-妈的 混球 +-我发誓! +那几个从来没来过的混帐怎么可能 +知道枪在哪里? +老大 因为是雷 听我说 +他住的那个公寓 +他们住的那个公寓 剑桥塔公寓 +和你住的公寓一模一样 我妈的发誓 +你也知道 那把枪能带来好运 +它跟了我他妈的至少15年 +-在哪里? +-天哪 +迪 他妈的枪在哪儿? +操! +够了! +他欠你多少? +多少钱? +如果我帮他还 能放了他吗? +多少钱? +270英镑 +我没告诉你叫你呆在那儿吗? +你以为他妈的是谁? +警察? +过来抓我的吗? +是吗? +来呀 快来 来抓我呀 死条子 +快来啊 来铐我呀 死条子 +嘿? +来铐我呀! +哦 不 不 我明白了 +你这死同性恋是过来花钱享乐的 +来操男人 真不要脸 +觉得自己有钱? +啊? +从口袋拿出钱扔我是吗? +啊? +那好 看看吧 +妈的好好看看吧 +霍斯... +霍斯... +霍斯 +看到了吗? +我说过了 他不是警察 不是吗? +我还让你得到这些钱呢 老大 +我只是想... +为了老大你 我出卖自己的肉体 +出卖自己的肉体 帮你赚到这些钱 +我没拿过你的枪 +老大 我说了 是雷干的 是雷! +他住在... +住在... +剑桥塔公寓 +和你住的地方一模一样 +所以他知道浴室的事 +喂? +赛夫 是我 霍斯 +等等 等下 好吗 +霍斯 请等一下 好吗 +-你在干吗呢? +-你看到我的耐克上衣了吗 +我在打电话 给我滚出去 +出去 +妈 +霍斯 怎么了 +你在哪里? +在我妈家里 怎么了 老兄 +没什么 我要过来 +在剑桥公寓外见 +叫雷和那个昨晚一起来我公寓的 +叫格雷的小家伙一起过来 +霍斯 老兄 不行 我学校有事呢 +我管你什么学校 给你10分钟 +你最好慢慢祝福祈祷... +是雷拿了我的枪 +南无阿弥陀佛 南无阿弥陀佛 +雷 我是赛夫 你和格雷一起吗? +霍斯想要见我们 +不是好像 是要马上 +我他妈的什么都不清楚 +马上去车库 切记叫上格雷 +你他妈的怎么了? +老兄 你不用这么害怕霍斯的 +相信我 钱 再找几个家伙抢过来就行了 +那你也相信我 抢过来后 买把枪放身边 +-你说什么? +-我说 +找几个疯子 蠢蛋 抢完钱 买把枪防身 +妈的跟我有什么关系 +告诉你 我会打爆你的头 +该死的胆小鬼 +知道他是谁吗? +霍斯 老兄 是 霍德维克 +他妈的我才不怕他 +疯子我可见过不少 +但像你刚刚那样的疯子还真没见过 +我要这把枪 +滚蛋吧 我不会把该死的枪给你的 +你知道吗 +你还是走吧 +-你该走了 +-我要枪 +-我不会给你的 +-我给你钱 +-不行 +-我帮你还了债了 +你自找的 我可没叫你那么做 让开 +你在干什么 你滚吧 你要我一枪杀了你吗 +我他妈的早就跟你说了 这可不是闹着玩儿的 +你还想让我再揍你几拳吗 +求你了 我可是说真的 赶紧滚吧 +从哪来回哪去吧 你到底怎么了 赶紧滚吧 +那要不这样 你呆在这儿等霍德维克过来 +-我跟你拜拜了 有钱人 +-把该死的枪给我啊 +把枪给我 +把枪给我 +把那该死的枪给我啊 +我操 +你他妈的饶了我吧 +我操 我操 我操 我操 我操 +别踢了 +我操 我操 你这个混蛋 我操 +操死你 +有钱人 你在干什么 +你这该死的 我操死你 +操死你 +他妈的 +啊 +有钱人 +我不知道哪招惹你了 +求你了 兄弟 +我只是个小烟鬼 +有钱人 +你这蠢蛋 +你这该死的... +我哪知道他怎么突然要见我们 +-你生什么气呀 +-别问我了 我他妈的不知道 +-他听上去是不是很生气? +-他妈的谁知道 +我操 +霍斯 怎么啦 +-你从我浴室里拿走了什么 +-什么都没拿 +-你拿了什么 +-什么都没拿 霍斯 +-我他妈的枪在哪 +-我什么都不知道啊 +-啊 +-我的枪在哪 +-他妈的枪在哪 小混蛋 +-我不知道什么枪啊 +-那怎么迪说你知道 +-什么? +-为什么迪说你偷了我的枪 +-我不知道你在说什么 +谁都不许动 +喂 保罗 你好吗 +恩 +是今天吗 我以为是... +我以为是明天 +不 没问题的 +没问题 为了你会让鹦鹉一直在窗台上 +我大概10分钟就可以到了 +你只要敲门就行了 +塔妮雅在那儿 她会招待你喝咖啡的 +10分钟好吗 那再见 保罗 +-我们不知道枪的事 +-他妈的闭嘴 +我的枪不见了 我得找回来 +不管谁出面 总之得拿回来 +什么型号的枪 +是什么... +什么型号的枪 +是一个. +38 +哪种 像个塌鼻子吗 +对 +-好的 +-是的 就得这样 +我要拿回我的枪 +我才不管是谁去帮我拿回来的 +我们真没拿 肯定是迪干的 +-那就去找迪 +-要是找不到他呢 +这烟鬼到处乱窜 连个住所都没有 +你知道那个大仓库吗 +-在糖果屋大道上的那个 +-知道了 +10分钟前 他在那儿做鸭子呢 +-做鸭子 +-是的 +什么意思 迪真是个疯子吗 +雷 他太恶心了 +所以我是你们的话 我会尽快过去 +就用我的表计时 +给你们一小时 +我发誓 兄弟 +我发誓 要是你再这样冲过来的话 +我会他妈的开枪的 +我会他妈的杀了你的 伙计 +听到了吗 有钱人 +有钱人 跟你说话呢 +我随时都可以开枪 +兄弟 会射到你的 +-我觉得事情有点不对头 +-那还能怎么办 +-是的 但是... +-不 你看看我 +我可没拿那把枪 你也没有 +格雷也没有 所以肯定是迪干的 +我不能就这样被他妈的白打了 +我们不用去打迪 只要拿回枪就行了 +-我们一定要给他点颜色看看 +-我们只要... +他妈的 迪诬告我 他是个混蛋 +我要去揍他 说到做到 +格雷该死的跑到哪里去了 +上帝啊 你给我开门 +我找不到我的白粉了 +什么? +我有一大袋的 可是找不到了 +什么? +去你的白粉 格雷 我们要干大事 +操 就知道吸毒 +你给我该死的快点 +你还真是磨磨蹭蹭的 +但你知道我要干嘛 别管了 看看这些 +双节棍不错啊 伙计 +-是我的 真粗鲁 +-拿来 +什么? +你有T型棍啊 +做工很好的 很棒 +我不去 +-什么? +-我可不会带着武器跑过去 该死的 +-我以为你是我兄弟呢 +-我是啊 +-那就拿着T型棍 +-你说什么? +你不来? +-我们要去拿枪啊 +-拿着 赛夫 +现在就拿 +听着 +伙计 保持冷静 行吗 +行吗 +我不想再惹麻烦了 有钱人 +我只想要这把枪 仅此而已 +给我枪我就走 +-求你了 +-不行啊 你不会想要枪的 +我一直在告诉你 有钱人 +你的商业伙伴出卖你了 还是怎么了? +你想杀了他吗 不值的 兄弟 +等等 +是不是和戒指有关? +你妻子离开你了 是吗 +所以你才到这里来? +你想... +你想杀了他的相好? +是不是? +想杀了那个杂种 +不值得的 伙计 +-你根本不知道在说什么 +-我知道 +我知道我在说什么 伙计 好不好? +没有女人值得你 +为了她毁了一辈子 +听着 伙计 +我和你说件事 +你这样做是没用的 +没用的? +! +我给了那个女人6年的时光 +你知道什么 +你可能从来没给过别人什么 +-我给很多人东西 兄弟 +-比如说? +我一直给麦凯拉东西 +我还给了布莱妮一些香水 +她很好满足 +第二天 她走过来和我说 "迪..." +"迪 我只有19岁" +"我已经开始堕落了 无路可退了" +"上瘾了" +"但还有人送我香水" +是不是就是她被杀了? +什么 啊? +-那个女孩 我在海报上看到的 她... +-别说了 +我发誓 事实上 你还在这呆着干嘛呢 +你觉得被女人抛弃了 自己好像个小丑吗 +你觉得这事不可能发生在你身上 +-闭嘴 闭嘴 闭嘴 +-你猜猜发生什么了 +-就是发生在你身上了 +-你给我闭嘴 +你要买把枪去杀她的相好 +别这样 伙计 你要向前看 嗯? +我不能继续走下去 +你可以 你老婆出走根本不能与我经历的事相比 +-我和那个女人有个女儿 +-这理由不错 +不过就这理由来说 你就更不该 +要这个东西 你有个女儿啊 +对 就是这么回事 对吧? +就是这么回事 +她不是我的女儿 她不是我的女儿 +现在你懂了没 +两年了 +两年来 我一直以为我是她的爸爸 +现在却发现我不是 +整整两年了 +别人才是她的爸爸 +那个人我认识 +我竟然认识他 +我竟然认识那个男人 +最后我老婆为了他离开了我 +你知道那是什么感觉吗 +我... +她是我女儿 她却不是我亲生的 +我辗转难寐 +我看完我以前日记 +我想知道到底什么时候开始的 我疯了吧 +操 +给你 兄弟 +有钱人 给你 +拿着 伙计 这是你的 +我知道你生气的原因了 +我知道你生气的原因了 我明白的 +但用枪 伙计 +这可绝不是什么好办法 +兄弟 你得学着怎么来应对这烂事 +向前看 对吧 +我挺过来了 +千万不要孩子气 +我从十岁起就在孤儿院 +那时只有我和我妈妈 兄弟 +嗯 她干得可真是不错 +-对不起 +-你刚才说什么 +-你刚才说了什么 +-我不是有意的 只是... +-只是顺口说说 对不起 +-我妈妈尽了力 +我会到孤儿院的唯一原因是她死了 +想想我的感受 +被丢到了孤儿院 +没有爸爸 妈妈也死了 +我十岁的时候就完了 +为什么我现在成这样了 因为我的过去 +而你 你是我见过的最有权势的人 +-他妈的 +-听着 我不... +不 不 不 +操你妈 操你妈 +如果你的人生和我一样 你也不过是个烟鬼 +如果我有你的人生 即使我知道 也不会这样 +你他妈个瘾君子 你他妈个贱人 +你完了 伙计 +兄弟 你要干嘛 你要干嘛 兄弟 +你这个贱人 过来 +好 我知道 我知道 +低点 放到这儿 +保罗 注意你的手放在哪儿 +你摸的可是我的女人 +你感觉到了吗 +嘿 你过来 +快追 雷 快追 +快点过去 +格雷 伙计 冲过去 +看 兄弟 看着我 +坚持住 伙计 别这样 +我抓到他 我抓到他了 伙计 +操 +过来 你这个小... +全城最棒的 +快点 +-我在这 兄弟 +-伙计 快点! +打开那扇门 +-我来了 +-他跑不了 +他妈的贱人 +雷 他把门锁了 +雷 +你跑不了的 伙计 +妈的 +他脱了衬衫看起来真壮 +他看起来真棒 +看那个 +-准备好了? +-好了 +你觉得很有趣吗 +哈 看看他 +麦克·杰克逊! +现在怎么办 嗯? +干他 +你跑不了 +跑得可真够远的 我要把你从这扔下去 +-别 伙计 别 +-你要干什么 兄弟 +我没带武士刀算你运气好 +看他呀 +放开他 +我说 放开他 +-你以为你能... +-雷 格雷 +雷 格雷 +-我说放开他 +-好 把枪放下 伙计 +放下 好吗 +-我们得去找霍斯 +-操 +听着 我不过卖些白粉来付我的大学学费 +-我可不是什么骗子 +-你会没事的 +赛夫 +你是我的同伴啊 赛夫 +你为什么那么做 我简直不敢相信 +-做什么 +-你让他们看到枪了 +-这全都是你的错 +-为什么 +因为如果昨晚你没有来问我买枪 +我们就不会卷进这事里 +天哪 麦克 鹦鹉又不在窗台上 +我得走了 +轻点 轻点 把我放在这 +啊 啊 轻点 操 +操 你他妈是怎么回事 +该死的脖子 +操 +你他妈在干什么 +我看起来像在干什么 啊? +我在找... +粉 行吗 +我记得 我发誓 我记得昨晚我在这丢了一些粉在这 +看 我真的... +我可不认为那样能解决一切 +你 你在说什么 我要振奋一下 伙计 +你不认为你该走了? +我说 你该走了 +你说过他还会回来 +我他妈的能去哪儿 +我去哪里? +我能往哪儿去? +啊? +呃 我只是... +我不知道 总会有你能去的地方 +你还不明白 对吧 +你有钱 所以你可以活下去 +不 这不光和钱有关 +不 就是钱的问题 兄弟 +我们之间最大的不同是什么? +钱 他妈的钱 +操 保罗 +肯定出事了 伙计 +行了 如果我说给你点钱的话? +-什么? +-如果我说给你钱呢? +你觉得你就可以离开了吗? +你说过你再也搞不到钱给我了 +-对 我说过 +-那你到哪儿给我搞钱? +用这个 +我可不干持械抢劫的事儿 +不 不 不 我不是这个意思 +那你是什么意思? +他干嘛到处找这把枪呢? +为什么他这么急着找这把枪 啊? +行了 行了 我听见你们的对话了 +-他说了什么 +-他说这把枪是一件凶器 +那又怎样? +所以 如果这把枪落到警察手里呢? +我不会把枪给警察的 +把枪还给我 +我可没说要把它交给警察 +那你到底什么意思? +我们手里是有霍德维克的枪 +那又怎样 +拿着枪去勒索他吗 +赫莱西奥 赫莱西奥 +他不会买自己的枪的 伙计 +干嘛不? +因为你不能 +-为什么 +-因为他是个杀手 +他妈的 上帝啊 +你... +我操你老娘 +操你老娘 +你凭什么说他花钱拿回枪后 +不会一枪毙了你 +-我把子弹拿掉 +-什么? +我会把子弹取下来的 +他只是要枪 又不要子弹 +他妈的 +你就不能帮帮我吗? +-我在找白粉 +-别管那破东西了 +-在这儿你找不到的 +-我都快得痴呆了 +你不是痴呆 而是疯了 +我疯了? +疯的人是你 是你要把枪卖还给那个杀手 +现在这才是明智的 你知道吗 +听我说 我们必须离开 就现在 +太棒了 +我找到了 现在看看是谁疯了 +所有人都将见证巴比伦王朝的覆灭 +回见 兄弟 +我操你妈 +你他妈的死定了 你这小混蛋 +退后 他妈的给我退后 +别他妈的干蠢事 同性恋 +给我他妈的退后 +把枪放下 然后滚开 +滚开 把枪放到地上 然后滚开 +我和你可没什么瓜葛 同性恋 +不 +想要枪的话 用钱来换 +我知道你干嘛急着要这把枪 +-你他妈的跟他说什么了 +-给钱吧 +是的 把钱给足了 +不然我马上就报警 +好吧 好吧 好吧 +过来拿钱 +你他妈的过来拿... +这笔钱啊 +去啊 +拿啊 +你敢碰一下我就杀了你 +我不能 +他妈的 +哦 同性恋 +-你他妈的放下他 +-你死定了 我操死你 +-放下他 +-我要杀了你... +他妈的放了他 +冷静点 迪 冷静 +把刀放下 +他妈的给我把刀放下 +-快啊 +-好吧 +拜托 你看 我... +. +我知道你想要还我钱的 这我明白 +求你了 迪 求你了 +想想塔妮雅 我马上就要... +做爸爸了 +求你了 迪 别做蠢事 +想想我们还能一起拿白粉 就我们俩 +不是吗 +到克里斯托那儿去坐坐 +拿半袋白粉 再到我家里 +-吸上一口 真是太棒了 +-够了 闭嘴 +多么棒的烟啊 +你知道那种深吸一口烟的美味 +棒极了 迪 +太美了 太棒了 +把同性恋给杀了 +来吧 迪 你行的 +把该死的同性恋杀了 你就没事了 +别 迪 +来吧 把同性恋杀了 他知道得太多了 +他就要逃走了 杀了他呀 迪 +开枪啊 +-和你开枪杀wee briony一样 +-求你了 迪 别 +我可没杀她 +当然是你干的 +不 不 不 不 +是你开枪杀了他 +-拜托 +-不 是你开的枪 +迪 我们是一帮啊 你和我 迪和霍德 +来吧 杀了这该死的同性恋 +当时可没说要杀她 老兄 +和讲好的不一样 +可你想想 迪 布莱妮当时在威胁我 +她从我这儿偷了钱还要去报警 +她要勒索我 你让我怎么办 我都快有孩子了 +-所以她必须死 +-你怎么能这样说她 兄弟 +那可是我的女人啊 +-霍斯 我爱她 +-你爱他? +她是个不要脸的贱婆娘 +为了白粉她能跟男人上床 +是我的错 +我把她引到地下室 +他就在那儿等着 +我以为他只是吓吓她而已 +他该死的说话不算数 +接着他就发疯了 杀了她 +就这么一枪杀了她 +迪? +迪 +我们该走了 马上走 +不 赫莱西奥 不 你走吧 +你走吧 +这不是你该呆的地方 兄弟 +我们有钱了 可以走了 +去哪 兄弟 我他妈的能去哪呢 +我犯事儿了 你不明白吗 +他妈的走吧 我杀了很多人 你知道吗 +-你走不走? +-好吧 好吧 +好吧 +好吧 +-这儿我看着 +-好吧 我走 我走 +你走吧 +拜托 迪 你也必须得走啊 +她躺在地上时的眼神历历在目 +你猜她眼睛告诉我什么了 +以为我和你会永远在一起 +永远不分开 +我试图救她的 +但还是死了 +只有她的眼睛在说话 +她说 "为什么 迪" +"为什么 迪" +这就是我唯一得到的 唯一 +你得听着 杀人什么好处都没有 +我一直和你这么说 +所以他妈的收手吧 忘了这一切 +我没想过要杀人 +我只想杀了我自己 +为什么 赫莱西奥 +你又没做过坏事 +我就不一样了 +你仍有重拾美好生活的希望 +而我却没有 +所以你收手吧 +求你了 汤姆 +走吧 +走吧 +我们都能继续前进 +可以继续下去 +继续生活 +-=TLF字幕组=- 翻译: +mortia xaon 校对: +haha168 +片名: +地牢围攻 +我就知道你会来 +我早告诉你了 +我意思是,我感觉到了 +你来之前我能感觉到 +你的力量在慢慢变强,玛丽安娜 +我们在一起的时间终于开始有用了 +等等 +你必须走了 +你希望如此吗? +我们每次这样见面,我都觉得... +无力。 +觉得被吸干了一样 +可能爱情就会让女人这样吧 +你知道什么是爱? +我知道诗人们都愿以一死来交换 +- 你会以死交换吗? +- 可能吧 +在诗里 +我父亲会怎么说? +世上的事情你父亲不知道的很多 +让这个也变成其中之一吧 +渎神,这太疯狂了,盖伦 你太过分了 +神救救我们吧 +用力拉,扎夫 +用腿的力气 +它不想出来 +最大的都是最顽固的 +看吧,有价值的东西都不会轻易到手 +你没打中 +我不想杀了他们 +只要它们不吃庄稼 +猪来了,还是老价钱吧? +冬天的玉米换这猪? +老价钱,不变 +是个挺旱的一季吧 +- 更旱的我也见过 +- 国王在招兵 +兵的待遇都很好 +我有这块地,还不够吗? +你老了后,你就会厌倦只是这么活着 +你不想挑战一下你的勇气吗? +我意思是,这样的生活有什么勇气可言? +我靠,法莫,说说话你会死吗? +我的意思是,我们又不是动物。 +人就应该跟别人说话啊 +诺瑞科,如果我能把这些甘蓝说出来 我肯定会的 +雨一来,地就变成块 +那时候你都不能把它们说出来了 +这就是为什么我喜欢你爸,扎夫 +他总是知道怎么来扫兴 +- 带诺瑞科去我们放玉米的地方 +- 好 +给,扎夫,给你这头猪 +你留下来吃晚饭吧? +嗯,既然你都开口了... +诺瑞科,能看到你太好了 你应该常来 +嗯,我觉得法莫小时候已经看厌我了 +现在既然他成家了, 就应该稍微调整一下 +诺瑞科觉得父亲应该不种田,而去参军 +等等,我没这么说啊 +他说国王的战士都拿很多钱 +法莫,你没诚心想这个吧? +你们是我的家人。 +我哪儿也不去 +- 你得到答案了,诺瑞科? +- 我只是说说 +- 只是说说 +- 嗯,人人都有特长嘛 +只是说说看来是你的特长 +出卖朋友看来是你的 +- 我能来点鸡肉吗? +- 别给他 +把鸡肉给我! +说点好听的给我听 +告诉我你多爱我 +你知道的 +我只知道你告诉我的... +你却什么都没告诉我 +看看这双手,为养活我们而开裂 +这双手比话语更说明问题 +告诉我有什么损失吗? +你还想要什么呢? +每个女人都想要的 +一点点激情 +- 一点点激情? +- 嗯哼 +我想想我能怎么办 +- 该走了 +- 你为什么不跟我们一起去? +我还有很多地要清理 +记住,当人从辛勤劳动中创造生活时 +勇气永不灭 +对了 +我讨厌睡觉时没有你 +小心点 +石桥镇而已,我们当然会很安全的 +为什么别人都叫父亲法莫? +他没名字吗? +你父亲相信人跟他所做的事情密切相联系 +他很小的时候,诺瑞科把他带到石桥镇 +那诺瑞科是他的父亲? +整个镇子收养了他 +不同的时候有不同的家庭收养他 +但是诺瑞科总是关注着他 +他现在有个家了 +我真高兴是我们和他一起组成的这个家 +嗯,我也这么觉得 +将军 +报告给你的国王 +陛下,克鲁格人... +野蛮的军队,克鲁格人... +它们用剑打仗 +这太可笑了,就好像你在说持武器的狗一样 +它们像人一样打仗 它们把整个侦察队都杀了 +如果将军没命令我会来报告的话 我也死了 +这是某种魔法 +外婆! +外婆! +扎夫,是你吗? +抓住你了 +终于! +放你进烤箱 +我不喜欢烤箱 +烤箱又干又暖和 +你不想我们把你生吃了吧? +你为什么要吃了我? +今晚,我向你外公保证... +要做他最喜欢的菜 +- 集市上卖得怎么样? +- 不错 +当然,男人都想来占我便宜 因为我是女人 +我就让他们多付钱 因为我是女人 +我们还小的时候你总是当头 +- 总是当头 +- 不,我知道我要什么,就这样 +直到她遇到你父亲 +你父亲放荡不羁 +- 外公呢? +- 在钟塔 +- 我们去看看? +- 我们得小心点 +钟塔是为战时而建的 +你不想拉错绳子而引起场战争吧? +什么耽搁了你这么久? +哈! +他们没那么容易被吓跑的 +这真是疯了 +克鲁格人是野兽 他们没有盔甲和武器的 +我要用你的马,诺瑞科 +- 你去哪儿? +- 石桥镇 +- 索拉娜和扎夫在那儿 +- 我跟你一起 +法莫没来? +没,我丈夫喜欢让我来做买卖 他好种地 +你为你丈夫做得很好 +他很爱你 +对,我相信他是很爱我的 +新郎新娘接吻时,鸣钟五次... +给整个镇子他们结婚的消息 +走,现在就走,带扎夫回家 +带他走! +你能保护他,父亲 保护他 +- 准备好了吗,我的女士? +- 从来都是 +等等 +这么快就认输了? +你进步神速啊,令人印象深刻 +如果艾柏能有更多像你这样的剑士 +让我加入你的军队,你就有了 +我不确定艾柏的军队是否准备接受女兵了 +而且,你父亲会怎么说? +我父亲从不让我做我想做的 +泰利斯! +准备好你的军队,准备出发 +克鲁格的散兵在抢掠我们的土地 +噢,太阳刺痛了我的皮肤 +你在胡说什么? +你服从命令就行了 +我只听从国王的 +你应该... +学习怎么尊敬别人 +敬意是赢得的 +错了,敬意是我天生的 +回镇子! +所有人都是! +- 索拉娜在哪? +- 她在敲钟 +别担心,扎夫,我会找到她 +- 父亲! +- 巴斯蒂安! +拿着我的剑 +- 进去,堵住门 +- 快点 +- 谢谢你,父亲 +- 去吧 +我们在镇子里找 +大家快走! +快点 +干得好 +有种的人? +放开他们 +你今天杀了我一次了 但是我们又见面了 +爸爸! +跑,儿子! +看! +它们撤了 +扎夫! +- 它们撤到高地上去了! +- 扎夫! +别让它们跑了 +我还要给索拉娜做个标记 +没人看到她,没人知道 +我们没找到她,她可能跑了 +他说得对,法莫 +盖伦! +你去哪儿了? +我一直在找你 +我很忙 +- 很忙 +- 我们达成了协议的 +我让你进出我的城堡 我们就能合作 +我守着承诺 +我肯定最近这些消息都能表明 我有多么的忙 +对,你确实稍微搅和了一下 +搅和? +告诉我,公爵 +你对一个叫法莫的人了解多少? +石桥镇的镇民们 +艾柏的军队同情你们 +这样的惨剧会被复仇的 +克鲁格人来的时候,国王的军队呢? +农民,不要忘了你在和谁说话 +在你的世界里,你不对国王鞠躬吗? +在我的世界里,国王的军队是来保护国家的 +不是只是城堡 +被克鲁格带走的人怎么办? +- 克鲁格抓了人质? +- 安静! +如果克鲁格人带走了人质... +它们的目的就很不明确 +国王的军队召集任何一个 能打仗的人 +- 谁来? +- 然后怎么样? +国王有军队和城墙 +被克鲁格抓走的人就只有我们 +- 你敢违抗国王的意愿? +- 我跟你走,法莫 +- 卫兵! +- 让他们走 +这不是艾柏之道 +- 你违抗国王,冒很大的风险 +- 不比你冒的大 +- 我没有选择,她是我的妻子 +- 她是我的姐姐 +好,我们开始吧 +留下来,跟着艾柏的军队走吧 +你想过军队生活,不是吗? +不。 +我不喜欢制服 +- 你有马吗? +- 有匹母马 +老,但是很强壮 +老... +但是仍然很强壮 +你挡我路了 +我们以前见过吧? +说些好听的给我听 +告诉我你有多爱我 +你知道的 +- 我是梅里克,国王的大法师 +- 我听说过你 +孩子们关于魔法的故事 +你的国王需要你 +嗯,我的儿子也需要我 +但是我让他失望了 现在我的妻子需要我,如果她还活着 +你有没有想过,法莫 +在国家处于非常时期的时候... +我们个人的爱和得失难道更重要吗? +不,但是和我无关 +好好活着吧,法莫 +你的国王需要你 +远远超过他目前的所知道的 +你怎么知道这座桥的? +小时候我在这些地方玩耍 +这就是我怎么浪费我的时间 +- 如果我们绕过这个峡谷,我们就浪费了一天 +- 你觉得呢? +我们能过 +让我们先把马上的装备拿下来 +你什么意思? +我们就这么放了它们? +你担心我们会伤了它们感情? +回去吧! +走! +来吧 +- 好,我要去了 +- 你是个勇敢的老头 +我只是不想你在我之前先 弄坏了绳子 +- 快点 +- 好,走吧,快! +你更关心你的马 +我喜欢我的马 但是我不确定我喜欢不喜欢你 +嗯,等你了解我再说 +这的确节省了我们不少时间 +噢! +- 陛下 +- 站起来,士兵 +多少人在守卫着? +我在守卫着,陛下 +嗯,你在守卫着? +法罗公爵,你非常,非常坏 +你让我胸痒痒的 +我要告诉你妈妈 +你们在干什么 +我的侄子在王座上玩耍 +你觉得配吗? +你在国王和他的军队 +出去进行招兵活动的时候玩耍... +而你唯一的工作 +就是保证城堡的安全 +而守卫城堡的人... +等于零! +陛下... +去调查偏僻地区的事务 +你给我消失 +快,别让我推你 +拿开你的手 你都不配去吻我的袍子 +你不配弄脏你叔叔的王冠 +除非国王特别下令... +你不能碰我 +皇家法律 +是个我最喜欢的 +玩具 +- 一切都在按计划进行 +- 我等不了了 +我受不了那个老山羊的控制 +实施那个 +你想快速解决? +好! +我们就来快速的 +好 +盖伦 +你一定要突然悄无声息的出现吗? +我没有 +我是突然从某个地方出现的 +你不受邀请就进来我的房间 这样有些过了 +你以前的热情好客我现在都得不到了吗? +你不能想来就来,想走就走 +然后突然消失 +我不是你的妓女 +你为什么这么想? +你很清楚什么我必须这么安静地出现 +我不能在我爱人的门上重叩,对不对? +你怎么能想来就来... +你又被我父亲认为是国王的敌人? +我有我的朋友,我有我的关系 +为什么我父亲这么恨你 +他是一个很谨慎的人 +问题! +我不是来被责问的 +你父亲恨我是因为我不会 +对伟大的国王和大法师鞠躬作揖 +因为我可以从他那里得到我想要的 +甚至是他女儿的纯洁 +你离开我的房间 +离开我的生活 +你也在驱逐我吗? +在我们完成了那么多事情之后? +我没帮助你发现你的力量,你的预感吗? +- 你只是教会了我小把戏和恶梦 +- 收声! +帮帮我! +陛下 +再次请求你接受我最深的歉意 +我错误理解了你的命令 +错误? +- 那个是错误? +- 对 +我可以坐吗,陛下? +仆人! +我知道,退下 +我知道我在几个场合都辜负了你的信任 +而且我可能让你和整个王国很失望 +但是我会改变 +我会在这个战争年代摆脱 年轻的愚蠢 +我会证明自己是个合格的王储 +吃吧 +我的侄子,你对适时的外交 +有独特的理解 +那就是点优点 +我能敬你吗? +可以吧 +在早上喝酒并不是表达改正决心的 +最好方式 +没错 +对,没错 +国王万岁 +是 +克鲁格人攻击了南部的石桥镇 +对,然后这片山 +会迫使他们北上,绕过沼泽 +然后我们进攻 +那是基于如果克鲁格人按他们应该的习惯 而行动的话 +我不喜欢这里,法莫 +没人去塞奇威克森林 +森林在山脉之间 +我们会在板岩道和克鲁格人会面 +塞奇威克森林里不止有灌木和树 +你不能想穿就穿啊 +你不想在这里过夜的 +- 我们点火炬 +- 火炬会吸引东西的 +- 让他们来吧 +- 法莫! +你知道人们怎么说的。 +塞奇威克森林里有东西 +人们说神保佑无辜者 +人们说很多事现在都对我们没用,诺瑞科 +快,我们还有很多路要走 +我看不到路 +- 本来就没路 +- 那我们怎么知道怎么走呢? +等等 +你说对了,诺瑞科 +这个也是意料之中吗,法莫? +- 放我们下去 +- 我想放就放 +滚出我们的森林,你们与这里无关 +我们恨你们的武器和你们的杀戮 +- 我们只是穿过这里 +- 那就穿过去 +别再回来 +我们迷路了 +人类,不仅没用,也很无助 +陛下 +我想要知道我父亲的消息 +- 你父亲为他的王去办件小事去了 +- 求你了 +发生什么了? +我担心他有极大的危险 +国王的大法师有很多的责任 +他并不需要一个总是用绯闻 +来惹麻烦的女儿 +我父亲觉得把我锁在城堡里 能减轻我的担忧 +他错了,我感受到宫廷里的气氛 从来都没有这么困扰过 +黑暗威胁着 +我们的国家 +从魔法中生出的黑暗 +走! +快 +你父亲在寻求原因... +- 和解决方法 +- 陛下? +陛下? +- 你的父亲... +- 陛下! +盖伦! +我觉得我要死了 +你跟国王吃得好吗? +你干了什么? +我以为你想要加速呢 +我想我可能对国王的吃的做了手脚 +你给我下毒了,你杀了我了 +别这么戏剧化 +没什么不能弥补的 +求你 +求你 +希望我们都记得谁在这里有着最大的权力 +好 +我觉得我救了你一命 +你应该为我做点什么呢? +国王被下毒了 +能救吗? +可能吧,如果还不迟的话 +性命保证 +私下谈一下 +法罗逃出了城堡 +还带走了两个军团 +那我们就知道谁给国王下毒了 +准备北上,和我们的新同盟会师 +我们联合的力量... +将使我们享有世代的和平和安宁 +我能感到盖伦跟这个有关 +为什么泰利斯长官没有跟我们提到过这次行动? +还有想要犯叛国罪的人吗? +- 还剩下多少军队? +- 三分之一 +嗯 +我看到克鲁格人在大量集结 +盖伦在召集军队 +- 大量的军队 +- 怎么会? +一个人怎么可能会造成如此大的破坏呢? +我亲生女儿背叛我,投进死敌的怀抱 +你这么恨我吗? +我以为我爱他 +他混入了我们的血缘 +你把魔法的平衡偏向了他的一方 +因为你,这个王国可能灭亡 +对不起,对不起 +对不起,对不起 +你们为什么这么恨外来人? +你们互相敌视,我们为什么不能敌视你们呢? +我们躲藏在森林里,避开你们的战争和争端 +和你们愚蠢的劳动 +但是你们还是在这里 对准我们的树射箭 +伤害就是你们生活的一部分 +你们最危险的地方就是你们自己 +我最远只能送到这里 +好运 +我们有计划吗? +你醒了吗? +是,我醒了 +你会发现杀死一个国王没那么容易 +我们要进攻 +但是,陛下,你被下毒了 +- 可能你还没认清形势 +- 我认清了 +我也有我的头脑 +克鲁格人不会料到我们会攻击 所以我们就一定要攻击 +谁给我下的毒? +我认识是你的侄子,法罗公爵 +噢 +更坏的是 +他逃离了城堡 +带走了第11和第12军团 +我们要进攻 +拂晓,集结你的军队 +我还能活多久? +你的生命即将结束 +但是剩下的时间足够了 +你确定吗,诺瑞科? +一点也不 +她在这里,诺瑞科 +- 我感觉得到 +- 我觉得你是对的 +嘿,慢点 +索拉娜? +索拉娜! +今天... +我们为国王而战 +我们的国王骄傲地 +为艾柏而战 +陛下 +起立! +神佑为荣耀和真理献身的人! +我对你很好奇,法莫 +我能感觉到你很危险 +我看不透你 +我能看到大多数的人,就像 阅读活着的书一样 +但是你,我都看不透你紧锁的眉头 +为什么? +你是谁? +有些谜不值得去解开 +你在这里 +我以为是个噩梦 +法莫呢? +扎夫呢? +巴斯蒂安,扎夫在哪儿? +跟我们父母一起吗? +对 +他是跟他们一起,但是 +他没逃出来 +你被带走的那天,他就被杀了 +对不起 +我的宝贝 +他死得安逸吗? +告诉我 +对 +他死得安逸 +法莫会来的 +他会找到你的 +你怎么知道? +因为他必须这样 +因为他需要你 +再怎么说,你也是他真正需要的 +法莫别死 +你要做的事情还有很多 +你看上去不怎么好啊 +啊,这个 +来试试 +- 味道怎么样? +- 这是什么? +药。 +快起来 +回家真好 +我不是你的妓女 +他用你来毁灭... +我知道诗人们说... +他以玩弄感情为乐,你还不吸取教训? +不是我帮你提升你的力量,你的预感吗? +小姐? +我是我父亲的累赘 +我阻碍了一切 +但是你父亲很爱你啊 +我小女孩般的愚蠢伤害了他 +自杀会伤他更重的 +可能你是对的 +我想要我的父亲以我为荣 +他已经是这样了 +他只是以这个想法为荣而已 +准备迎接你们的新盟军吧 +这是克鲁格人 +顺从,无情且不犹豫 +你看到的是一个强大的军队 +带走这个人 +把他放在王国的营帐里 +保证喂饱我的马 +等等 +这是你的紧急事务? +这是法莫,石桥镇的 +对 +为什么一身泥土味的不尽忠的 石桥镇农民 +会让国王的大法师怎么挂念? +因为国王对这个农民有特殊挂念 +我怎么不知道 +国王也不知道 +我觉得现在你们应该好好认识一下 +我们见过了 +上次,他拒绝了我 +去做他需要做的事情 +我以为陛下会对这个农民感兴趣 +从我们见过以后,他经历了许多事情 +大家都一样 +什么让他这么特殊? +因为,陛下 +他是你儿子 +法莫的朋友诺瑞科 +是管理王后马匹的人 +上次在石桥我认出他来了 +在牛草地小道的屠杀后,这个诺瑞科 +在战场上找到一个3岁大的小孩 +牛草地小道只有一个小孩 +你觉得这个故事怎么样,法莫? +一个老人以为他认出了一个30年没见的人 +这就是你们选国王的方式? +你是国王的儿子,王位继承人 +我没父亲 +没父母 +我与这里无关 +你的意思是那个傲慢的混蛋是我的儿子? +他30年来 +住在石桥的农场里? +就是这样 +就是这样,你告诉我他已经死了! +你说他们全死了! +神对我开了 +什么样的玩笑啊 +有时候神知道什么对我们最好 +那是什么意思? +你记得我们那个时候混乱的状况吗? +到处是战争,到处是敌人 +如果这个孩子带回了艾柏城堡 +他能活多久? +在石桥长大 +他很健壮 +离敌人很远 +敌人随时都可能 +除掉你的儿子和王储 +亲爱的朋友 +你最好是对的 +你最好心里有数 +国王需要所有有能力的士兵 +- 这不是我的问题 +- 他的王国被侵略了。 +你的王国被侵略了 +我不认识这个国王 +索拉娜是我的亲人 +诺瑞科和巴斯蒂安,他们是我的亲人 +你住在哪儿呢? +嗯? +如果王国落入盖伦之手... +你又能为你妻子提供什么样的未来? +想想吧 +制作: +jesseding +字幕来源: +Shooter +片名: +末日危城 +我就知道你会来 +我就说我会来的啊 +我是说,你来之前我就感觉到你要来了 +索罗娜,你的力量还在成长 我们在一起的时间太少了(意译) +好了,你差不多该走了 +你想要我走吗 +我觉得不太舒服... +就像是被榨干的感觉 +也许那是你爱我的一种表现(意译) +你知道什么是爱? +我只知道诗人会为爱而牺牲 +你会为爱牺牲吗? +-可能 +在诗里 +不知道我爸会怎么想 +这个世界上有很多事情是你爸不知道 +就让这件事也变成其中之一吧 +高卢人 +你太过分了 +夭寿... +用力拉啊,柴夫 +用你脚的力量 +干,就是拔不出来 +大萝卜是比较难拔... +你看 +不是很简单吗 +你没打中耶 +我吓吓他们而已,让他们不要吃我们的作物 +一切如昔 +给猪准备冬天的食物吗 +-是啊 +没多大改变 +机八的干旱,对吗 我早看到了诺尔克 +国王在招兵买马 他可以让你们没后顾之忧 +这片土地,他破坏的还不够吗? +你搞的这么累也只是要苟延残喘而已吧(意译) +你的GUTS去哪里了 +你为了苟延残喘浪费掉你的胆识 +该死的我只是想跟你谈一会儿, 我没这么可怕,你总得跟我说说话吧(意译) +我比较想跟老天抱怨 +老天不下雨,河流都变干了 +就算是你也不能跟上天说话吧 +这是我喜欢你的地方, 你总是很幽默 +儿子,把菜拿回去吧 +来牵着阿偷 +要一起吃晚餐吗 +除非你求我啊 +诺尔克,见到你真高兴,你应该经常来绕绕啊 +喔我突然了解到原来我们的法墨已经长大了 而且我自己也有家人,就给彼此一些空间吧 +诺尔克说服法墨去参军 +等一下,我可没有那样说 +当士兵可以有很多钱 +你不是认真的,是吗? +你是我的家人,我哪里都不去 +是你自己要去的吧,诺尔克. +我只是随便说说 +哦,那真是太好了... +...谈谈你自己就好了 +用法语说的话就是你的问题啰(法语也是yours,自以为幽默) +给我点鸡肉. +-别给他 +把鸡肉给我 +我想听些好话 +告诉我你有多爱我 +你自己知道 +你不告诉我怎么知道... +. +...你什么都不告诉我 +你看我的手, 虽然没啥力气却养活我们(意译) +我的手就代表一切了 +你告诉我有什么难处? +你想要什么 +我想要什么, 一点激情 +激情... +你会感觉到的 +该走了 +你不能跟我们一起吗? +我还要忙,还有很多事情... +. +你要记得,勇气长存心中... +永不凋零 +没错 +我想跟你喇寄... +(我不知道这句要翻成什么XD) +小心点 +嗯我们会小心的 +人们为什么那样叫父亲(farmer有农夫的意思)? +有什么意思吗? +你父亲觉得他就该当个农夫 +村庄的人都这么认为,我们只是其中一份子 +诺尔克的父亲也是? +他们都是被村里的人收养的,不同的家, 不同的时间 +我们都一样 +我真高兴我也是一份子 +傻瓜 +将军 +跟陛下报告 +陛下,库格军大举入侵 +他们带着剑 +这真是豪洨,你们只是警犭吗 +他们真的很厉害,简直不可抵抗 还把我们侦查队歼灭了 +要不是我拼死回来报告,我应该早就死了 +不可思议 +奶奶奶奶 +扎菲,是你吗? +终于看到你们了﹗ +我好想你喔 +天气这么温暖,看到你们真是太好了 你们不想错过这美好时光吧? +你什么意思? +今晚我答应你爷爷做一些好东西给你们吃 +菜市场还好吧? +-不错 +当然他们想占我的便宜,因为我是女人,所以我就让他们付更多钱 +谁叫他们小看我是女人 +女人在市场上永远是佼佼者 +没什么,我只是不想被人小看而已 +如果是你爸的话... +...你爸是最不会作生意了 +爷爷呢? +他去钟塔了 +要去看看他吗 +我们要小心点 现在正值战争时期 +你也不想出去被打吧 +你怎么这么久才来? +他们不是很容易对付 +真是夭寿 +是库格兽,他们都没武装 +诺尔克我要借你的马一用 +你去哪里? +我要去石桥 +-我跟你去 +法墨没来. +-没有 +他有事要做,叫我先过来 +他是个好丈夫,我看的出来他很爱你 +是啊... +...他是很爱我 +新郎新娘喇寄的时候,我们会敲五下钟 +象征他们在村子见证下成婚 +快,快带他走 +快带他走,我相信你能保护他们的 +你准备好了? +-我准备好了 +等等 +这么快就放弃了? +你的剑术进步的好快... +...甚至比我的士兵好多了 +那就让我加入你的军队 +我不确定我的士兵是不是可以接受女战士 +还有... +你父亲会怎么想? +我父亲从来不让我做任何我喜欢的事 +塔里什,库格军快打过来了... +...你要赶快整顿你的军队 +干... +这阳光真是刺眼 +你应该没资格命令我吧? +你是指挥官 +我只属于国王 +你能不能给一点点尊重... +. +我只给该尊重的人 +你错了 打从我一出生你就该尊敬我了 +她在钟塔上 +柴夫你在这里等着,我去找你妈 +父亲﹗ 巴斯丁,等等 +带上我的剑 +全部进去关上门 +快点 +谢谢你父亲 +我们快走 +快点 +有胆识 +放开她 +我已经让你杀我一次了, 不可能再有第二次 +父亲﹗ +救命﹗ +他们撤退了 +扎菲﹗ +我必须去找索萝纳 +没人知道索萝纳在哪 +没人知道 +我们没发现尸体, 说不定她逃过一劫 +没错 +高卢人,你去哪里了? +我一直在找你 +我一直很忙 +非常忙 +我们达成协议, 我给你最后一座城堡,我们一起合作 +我遵守承诺了 +我真的很忙 +这听起来有点牵强 +牵强? +? +告诉我公爵. +你知道关于那个叫做法墨的人的事吗? +石桥的人们 +军队需要你们 +我们会替你们报这个仇 +村子被屠杀的时候你们在哪 +喂! +别忘了你在跟谁说话 +你该尊重一国之君 +国王应该保护整个王国 而不祇是一座城 +那些被抓走的村民怎么办 +库格人抓村民当俘虏? +? +安静 +我们还不知道它们抓人的动机 +军队需要骁勇善战的人加入 +谁要加入我们? +加入军队就不必了,被俘虏的村民有我们去救就够了 +违背国王的意志就是死 +我跟你一起走,法墨 +护卫! +不,让他走,道不同不相为谋 +你知道违背国王是犯法的 你不也一样 +我别无选择,她是我妻子 她是我姐姐啊 +好吧,我们一起吧 +你确定吗 +你不是想加入军队吗? +不 +我不喜欢穿制服 +你有马吗? +有,不过年纪大了,但还算强壮 +老了,但还强壮着 +你挡到我的路了 +我们曾见过面,诺尔克 +告诉我一些好事情. +告诉我你有多爱我 +你知道的 +我是国王的巫医 +巫医? +你想跟我说魔法之类的荒谬事吗? +你的国王需要你 +是吗,我儿子才需要我 +我让他失望了,我的妻儿都失去了 +你想有没有可能... +...有些东西是比失去挚爱更重要的(勇气、信念之类的) +不 +我不这么想 +别死喔,法墨, 国王需要你 +超乎你想象的需要... +你怎么知道那个桥? +那是他们必经之路 +如果我们绕道会多花一天 +那你觉得? +我们可以过 +我们先把马儿放走 +你什么意思? +我们就这样把它们放生吗? +怎么? +你伤心吗? +快走 +来吧 +好吧,换我了 +他真够胆的 +他只是比我先过去而已,没什么大不了的 +快来 +快点快点 +你不是担心你的马吗 +我很担心啊,还用你说吗 +(喃喃自语)... +还好你的马离开你了 +我说这真是不错的尝试 +陛下! +起来士兵 +这里有多少卫兵 +就只有我一个,陛下 +只有一个卫兵? +真是太棒了宝贝 +你真是太淘气了 +来吧宝贝 +等等 +抱歉打扰你的娱乐, +"国王" +王位坐的还舒服吗 +你这个败家子 +为什么你没来参加军事演习 +而且就连你唯一的工作... +保护这座城堡的安全 +都做不到... +简直是空无一人! +! +陛下您听我说 +我一直在调查... +. +让他从我眼前消失 +不要 +来吧 +放开我,你根本不能这么对我 +你,你才不配我动手 +除非你有国王的命令... +. +不然你根本不能碰我 +国有国法 +你根本不能动我 +我们应该要照计划慢慢来 +我再也忍不下去了 +我不能忍受他高高在上指挥我 +赶~快~完~成~ +你想一步登天吗? +好啊! +那我就顺你心意啊! +很好 +你都这样突然出现的吗? +是啊 +我可以在任何地方出现 +我只是... +看到你突然出现有点吓到 +你忘记我们过去的情谊了吗 +你高兴要来就来,要走就走 +反正你总是连个屁都不放就走了 +不要当我是笨蛋 +你怎么会这么认为? +你知道我要低调 除了你我也不可能随便出现在其他女人房间吧 +你大可随意进出我房间 但你别忘了我父亲把你视为仇敌 +我有帮手 +这对我没用 +我父亲除了恨你 +已经对你没有其它的想法了 +闭嘴! +我不是来这里让你审问的 +你爸爸憎恨我 我是不可能向他妥协的,这个国家迟早是我的 +我会夺走你父亲的一切 +包括他女儿... +我会跟你在一起 +我早就是你的一部分了 +你也想走了吗 +等我们事成之后... +我会给你无限的力量... +与洞察一切的眼光 +你是想告诉我你想要... +. +打败他 +救命 +快来救我 +主人. +我错估您的命令 请让我再致上最深的歉意 +错估? +是这样吗? +是的! +主人我能坐下和你谈谈吗 +来人 +我知道... +. +我知道我让你失望了,我让整个国家蒙羞, +不过我会改变的 +我愿意为你去战斗 我想证明自己我是名战士 +吃吧 +我可以给你一次机会,亲爱的外甥 +让你来证明自己 +你还想说什么 +我们来一杯好吗 +或许 +早上喝酒好像不太好 +没错 +是的没错 +国王万岁﹗ +好 +库格军驻扎在石桥那,他们应该会往北绕道去沼泽地 +. +这就是他们的行军路线 +我们猜对就走运了(意译) +我觉得这树林不太对劲,没人敢走进这片树林 +地图上是这样画的啊 +应该没什么吧 +树这么多,总不能全砍了开路 你也不想晚上被困在这吧 +点火把不就行了吗 +火把会引人耳目 +法墨! +! +! +你知道人们说什么吗? +他们说... +这森林有怪东西 +人都是以讹传讹... +谣言对我们没好处吧,诺尔克 +快走吧,我们还要赶路呢 +根本没有路嘛 现在走的不是路吗 +这根本不知道通去哪... +等一下 +你还好吗诺尔克 +这也是计划之一吗,法墨? +放我们下来 +我高兴再放 +快点离开这,这没你们的事 +我讨厌你的武器 +我们只是路过 +那就快走,永远不要再来 +可是... +我们迷路了 +你们啊... +. +...真是逊咖 +我就送佛送上天吧 +国王陛下 +有我父亲的消息吗? +他在外帮我打理一些事 +请告诉我... +. +发生了什么事情? +我感觉他现在很危险... +你父亲肩负许多责任 +你是他女儿,应该要清楚,不要让他为你担心 +我父亲一直把我关着 不让我的魔法解禁 +但他错了 +我根本不会给他惹麻烦 +黑暗力量... +可能会袭击全国... +黑暗力量有魔力... +快,快 +你的父亲致力于解决... +. +你的父亲... +. +国王陛下! +! +高卢人,我怎么觉得快挂了 +你想跟国王一起挂吗 +你到底做了些什么? +我觉得你太急躁了... +...急着投胎 +干! +我没跟你说要注意国王吃的食物吗? +(超贱) +你想毒杀我吗 +别这么神经质嘛 +任何事都有补救的办法 +求你了 +救救我 +我希望你记住谁是老大 +是 +我已经救了你的狗命 +你现在要为我做些什么? +国王被下毒了 +陛下还有救吗 或许有救 +现在还不迟 +你说的是真的吗? +我发誓 +我想私下和你谈谈 +法罗自己带兵出去了 +那... +我们知道是谁想毒死陛下了 +我们会退到北边,证明我们是同一阵线的 +我们会证明我们是爱好和平的 +我早就觉得奇怪了... +为什么指挥官没跟你一起来 +还有谁有意见? +我们还剩多少士兵 +三分之一 +我之前有看到为数众多的库格军... +...看来高卢人正在招募军队 +一个人怎么能号召一支军队? +我唯一的女儿背叛了我,去帮我的敌人 你就这么恨我吗 +对不起父亲,我爱他 +他一直在对你说谎... +你的力量都被他吸走了 +因为你,国家可能会被他毁了 +对不起 +对不起... +. +为什么这么讨厌陌生人 +你们都彼此憎恨了... +凭什么叫我们不恨你们 +我们躲在树林里, 就是为了躲避你们的互斗,战争 +但还是一样 +树林变成战场,很多树都中了箭 +许多人的生命 就在这里葬送掉了 +我只能带你们到这了 +祝你们好运 +有计划吗 +你醒来了? +是的 +你知道身为一个国王不是这么容易就被干掉 +我该起来了... +阁下你中毒了,应该再休息一下 +我休息够了, +我答应要保护人民不受库格人骚扰 那是我现在该做的 +谁给我下毒? +我想是你的外甥法罗 +更糟糕的是他抛弃他的城堡 把大部份士兵带走了 +好吧,你先去整顿剩下的士兵 +我还有多少时间? +你的生命即将走向尽头了 +不过对你来说,足够了 +你确定这烂方法行的通吗 +也没这么烂吧 +她在这,我感觉的到 +我也这么觉得 +索拉纳? +索拉纳? +今天... +. +我们为了国王齐聚此地... +护主... +是你们该做的 +国王万岁﹗ +陛下 +起! +上帝会保佑我们,以及我们荣耀! +安心上路! +法墨,我对你很好奇 +你对我是个威胁 +我看不透你 +大部分的人,我只要有他们的血,就能看透他们 +而你... +. +为什么我看不透你的过去? +你到底是谁? +你再嘴硬啊 (太豪洨了) +你也在这... +. +就像噩梦一般 +法墨人在哪? +他在哪? +巴斯丁他在哪? +她跟爸妈他们在一起吗 +是的 +他们是在一起,不过... +他们没逃出来... +你被抓那天他就已经... +对不起 +噢天啊 +他是安然死去的吗(意译) +告诉我 +嗯... +法墨会来救我们的 +他会来找我们的 你怎么知道 +他一定会来,他需要你... +就算他会死... +他也会找到你 +想我吗,法墨? +你还好吗 +你看起来气色不错啊 +试试这个 +尝起来怎样? +这是啥? +哈哈这是伟哥,喝吧 +哈哈哈回家真好 +我不会让他得逞 +他一定要死 +小姐? +你看我对父亲做了什么好事 +我把一切搞砸了 +你父亲非常爱你 +我本想以死谢罪... +这么做只会伤害他更深 +没错! +我要让父亲感到骄傲 +他本来就以你为傲 +他引以为傲的是乖乖牌的我 +前面这些就是你们的新盟友 +他们是库格人 +废话,还用说吗 +你将会看到前所未见的强大军队 +把这个人带到王帐去 +对他好一点 +来 +这就是你的大英雄? +? +他不是石桥那个农夫吗 没错 +为什么国王这么器重他 +因为国王对他有兴趣 +我怎么不知道? +你可以去问国王 +是时候该介绍你们认识了... +我们见过面了 +上次他背对我(对我不敬) +那是因为他什么都没做 +我想你误会陛下了法墨 +他为了石桥村做了很多事 +没有其他人了吗? +为什么挑上他? +因为... +他是你儿子(老梗) +他有个朋友,叫诺尔克 以前隶属皇后护卫队 +我在石桥村认出他来了 +当年在皇宫的战役,诺尔克捡到一个三岁的小男孩 +而皇宫里只有一个人不见了 +法墨你觉得这是真的吗 +你要我相信一个老人说他认出三十年前的故人 +还说我是国王的儿子 +你的确是国王的儿子,没什么好说的 +我没有父亲,没有父母 +那这里就没我的事了 +你告诉我这个混蛋是我的儿子吗 +过去的30年里住在一个小小的农场 +我认为是的 +你说他死了 +你说他们全死光了! +! +上天是跟我开什么玩笑啊 +有时候心腹... +知道什么对你最好 +你到底是什么意思? +你记得在威登的混战吗 +到处是战争,招惹了很多敌人 +如果这个孩子在那时候回来 他会活多久 +如果在石桥村长大,他会变强壮 +而且如果敌人知道你儿子死了, 就不会去注意到他 +我的朋友... +. +你最好是对的 +最好确定是对的 +国王需要每个人参加这场战争 +这不关我的事 +这个国家正遭受威胁 也就是你的国土遭到威胁 +我不在乎 +我只为家人 +不惜一切只为家人 +那你要去哪里? +国王输了,你老婆怎么办 +想想吧 +法罗你犯了叛国罪 +如果你们跟法罗一样,听从他的话,那就一样有罪 +我们不会原谅叛徒! +! +各位听我说,这个人曾经想背叛国王 还叫我跟他一起,哈 +你的野心还不是普通小的 +现在,王国是我的囊中物 我也绝对不容许你们在我之下撒野 +你不可能会成王的 +不管是现在还是未来... +都不可能... +第十一队为陛下卖命 +懦夫! +这些库格人没有感情,什么都不怕, +他们为数众多, +但我们是尊贵的皇族战士 +他们什么都不是,只是冷血的野兽 +你来还是不来? +我选择战斗 +跟你一起战斗我感到光荣 这样我才能监视你 +去侦查一下﹗ +射﹗ +射﹗ +没事的! +出发吧 +大家出发! +跟狗打架一样 没错 +上﹗ +预备﹗ +射﹗ +射﹗ +这些人是我要杀的 +那我去杀老大好了... +你们赢了这场不算什么 +我们会一直赢下去的 +那这些就送给你们吧,我会派更多手下 +温德山... +这鬼地方就是我们的终点吗? +不,诺尔克 +我们不会死在这的 +你放心好了 +停! +国王 +擒贼先擒王 +射﹗ +卫兵﹗ +快! +快把国王带走 +再见了,我的好叔叔,我们走! +哈哈哈,干掉你只是时间问题 +我不想跟他们一样 我们早就像他们一样变奴隶了 +我就是不想变他们的奴隶 +诺尔克,沉住气 +为什么我们要走这? +从这儿过是快捷方式,敌人根据地就在左方 而且没敌人守着,我们就可以来个瓮中捉鳖 +快离开这个鬼地方 +停﹗ +看看这是谁啊,不是我们家族的成员之一吗 +树林这么大,你不觉得很巧吗 离我远点! +! +你倒是对自己很有自信嘛 +- +-而你的行为举止都只像个胆小鬼 +行为? +端正? +这些话等你在皇宫的时候再说吧 这里没这些规定啰 +特为你准备的 谢谢 +每个地方都有规则的公爵先生 +你真是让你的家族蒙羞 +我要带他走 +快跑 +诺尔克﹗ +这就是你要的,死得其所 +你是个真男人 +快跑 +没事,我还好 +你今天很英勇 +杀他们是小事一件,一群有勇无谋的家伙... +虽然你这么说,但还是很出色 这不是难事 +我... +也差不多该把王位交出去了 +你想今天你这么威猛,靠的是什么? +你觉得是... +运气吗? +你有潜力 +领导的潜力,而且... +最重要的... +你会坚持自我 +让你变的更强 +智慧就像是把铁锤 +而勇气就像是钉子 +人就是这样盖起自己的一切 +勇气永不灭 +你有听过吗? +你小的时候, 这句话... +是我每天晚上都会说给你听的 +我没跟别人说过 +孩子,未来的路会更难走 +我只是个农家孩子 没错,没错 +所以我不会是国王 +你知道以前这附近有个小村子吗 +村民一年只种两种作物 +这么做会伤到土壤... +他们没伤到土壤,因为有海草的关系 +海草让土变的更肥沃 +你可以试试 +你是怎么知道的? +因为我是国王 +因为我希望你成为... +一国之君 +这位子只有你可以接 +一日为王,终生为民 +你要保护你的人民 +但这场战争不会结束的 只会带来更多的伤害 +那就为和平而战吧 +和平 +是大家的梦想 +也该是你的梦想 +人人的梦想,永世的和平 +你不明白 +这战争夺走我的孩子 +我何尝不是呢? +吾儿... +将军 +是,统领 +叫侦查队去树林北边, 看看有没有敌人在等我们 +是,统领 +司令你看 +嗯... +这真是天上掉下来的礼物 +我带法罗来领罪了 +你们的国王应该还没挂吧 +布莱克将军,把你的剑给他 +不准戴盔甲 +哥们 +真谢谢你了 +你还记得小时候我们一起做过什么事吗,塔里什? +我们至少一起喝过酒啊 +没人要给国王戴护甲吗? +笨蛋﹗ +哥们,差不多该做个了结了 +国王驾崩,国王驾崩 +不可能 +我是国王了﹗ +你去吃你的大便吧 +塔里什将军,你该对我效忠 +你绝对不能杀了你们的新国王 +你这懦夫... +你们新国王的愿望就是... +国王万岁! +! +把剑放下 +别听他的 +大家听我说 +就在不久前,你们挚爱的国王... +已经去世了 +被这个... +一心要谋朝篡位的侄子 给杀了 +按照律法, 王位必须由直系血亲来继承 +请让我来介绍... +你们的新国王 故王的最后一个儿子── +他就是... +法墨 +请起 +都起来﹗ +国王虽仙逝 +却不是白白牺牲 +他的勇敢精神与我们同在 他想让大家知道,要相信自己,并勇敢面对 +今晚我们好好休息,安葬死者 +明天我们就去温德山放手一搏 +胜利是我们的 +天佑吾王! +! +干什么干什么 +带他们来这干嘛,还不快带走! +! +等等,把她留下来 +退下 +我好像看过你 +你... +你是法墨的... +哈哈,他会来救你,太好了,我只要在这等他就行了 +我对你没用 你当然对我有用 +你比法墨还重要 +应该说... +你对我来说比法墨还危险 +他马上就来了 +我认识你吗 +别动... +我感觉到了... +你已经怀了他的孩子 +你怀了他的孩子... +你哪里人? +克拉森,我在家里被抓走的 +我们会逃出去的 +我们都会死在这儿 +再见了,我的朋友 +你觉得要怎么打败这么庞大的军队? +他们的边界薄弱,我们可以挖隧道 +我们没时间挖隧道了 +你要知道一点小错误就会全盘皆输 +你要快的话,只能直取源头 +如果我遇的到那个高卢人,我就可以干掉他 +长官,恕我冒犯,为了一个女人... +会让整个国家身陷危机 +如果国王能把他马子救出来,那么他也能干掉高卢人 +只要把他杀了,国家就有救 +梅耶拉,妳的机会来了 +陛下,我想参与你的计划,仅供您差遣 +好好,现在不是说这个的时候,你先回城堡去吧 +我身为父亲的女儿 +我只想尽我的一份力,就像父亲那样 +你有带国王赐给你的铠甲 +是的将军 +或许有帮助 +我收了 +有其他人愿意帮我们 +哪里? +这儿 +你还活着啊 +死不了 +跟你们战斗的那些人,控制库格的那些人 +我会帮助你们找到他们的 +你们不是不想介入战争吗 我们知道这场仗快结束了 +我们的树林可能会被烧了 我别无选择 +我们跟你一起奋战,今晚我们就一起走 +温德山... +以前是马甲人所盖的避难所 +避难所? +但没有门可以进去 +你有办法进去吗 马甲人不需要门就能进去了 +我会想办法 +你不觉得人有机会活着很幸运吗... +我就这么觉得 +活着... +你不觉得兴奋吗? +跟我一起来的那些人 你干嘛不放了他们? +你不想让全世界的人知道你有多厉害、多仁慈吗 +你什么都不了解! +! +我早不需要仁慈这种东西了 +我早就超越善与恶 这些事是小孩子才会谈的,我在改变这个世界命运 +这样我还需要你朋友去宣传我的仁慈吗 +说不定... +不可能破例, +包括你,妳那亲爱的老公, 还有那些被我抓来的笨蛋 +杀了我,杀了我 +我不会杀你 +我还蛮享受的 +如果你会流血,就代表你也会死 +或许吧,但我一定不会死 +我还有很多事没完成 +准备! +! +射﹗ +射﹗ +推﹗ +那里有个洞穴 +你们可以从那进去 +我差不多该走了 +我不想你一个人去 +如果那个疯子还有一点良知, 那我就必须跟他沟通 +他早就没救了梅里克 +也许我可以转移他的注意力 +我就知道你会来 +我的老朋友 +我们曾经是朋友 +只不过你变太多了 +是吗 +梅格之力只能用来保护国王 +你怎么能违背诺言,反而对国王不利 +喜欢我的库格军吗 他们只是一群冷血的野兽 +库格军没有国王 你猜怎么着 +我不想猜 +我自己就是国王了 +库格军的国王! +! +我现在只让一个人卖命 +那就是我! +! +够了! +! +高卢人,妳跟我是仅存的马甲人 +我求你不要再疯下去了 +你根本不知道... +...我有多疯 +在我的地盘,没有疯这个字 +我都叫它── +神力﹗ +冲﹗ +喔,他来了 +他还真是不怕死 +梅若亚 +喔你来啦 +我不知道我怎么办到的 +我怎么会这么白痴? +原谅我 +我把体内最后的力量传给你 +跑 +这边 +这边 +法墨! +! +好久不见法墨 +我知道你成了国王 +一山不容二虎,你是知道的吧 +一定会彼此争斗 +直到见血胜利为止 +那你就来吧! +你的小魔术用完了吗 +我说过我会报仇的 +不﹗ +你要用什么身分来报仇? +一个父亲? +一个丈夫? +还是一个国王? +我是为了我的孩子报仇! +! +怎么了? +我有话要说 +我爱你 +-=结束 谢谢观赏=- 制作: +jesseding +导演: +维. +鲍尔 +主演: +拉森. +斯塔萨姆 +片名: +末日危城 +制作: +jesseding +你只是争取到了点时间而已 +我不会像他们那么活的 +我们已经是他们了,我们是奴隶 +- 我不会当奴隶的 +- 收声,诺瑞科 +我们为什么要进入塞奇威克森林? +我们要从森林走近路去艾柏城堡 +没军队没卫兵,城堡随便拿下 +我们快离开吧 +看看,一个家里的朋友 +我非常高兴 +独自在这个森林里你不觉得容易受伤吗? +- 你离我远点 +- 你从不相信我,是吗,玛丽安娜? +你的举止从来都没赢得过尊敬 +举止? +礼貌? +这都是城堡的言谈 +我们不在城堡里 +这里也没有规矩 +给你的特别礼物 +谢谢 +到处都有规矩的,我的公爵 +你喜欢打破规矩的这种天赋 最终还是没用啊 +我带这个走 +跑! +索拉娜,跑! +快跑! +我会找你的,走! +诺瑞科! +诺瑞科! +这是你一直想要的吧 +光荣战死 +你是个勇猛的老人 +索拉娜 +巴斯蒂安? +靠后 +不,我没事 +你今天很不错 +杀野兽 +- 需要狠下心来 +- 没错 +不管什么出现 +- 你都能战胜它 +- 我做苦活习惯了 +当你是国王的时候 +将会更有用 +你怎么看待你今天 +战斗得这么好? +我意思是,难道这仅仅只是 +运气? +你有天赋,你知道的 +领导能力,然后,当然 +你实话实说 +这会让你更好的为国家服务 +智慧是我们的武器 +谨慎则是我们的盔甲 +当人在诚实劳动中 +建设生活 +勇气不灭 +你从哪儿听到的这些? +当我儿子还小的时候 +我每天晚上 +都对他这么说 +别人都不知道 +现在开始你生活会变得更加艰苦 +- 我只是个农民 +- 是,是 +- 我只知道这个 +- 你知道,这里不远的地方 +有个小村子 +他们一年收两季稻子 +- 那会破坏土壤的 +- 不 +这样不会破坏土壤因为有海草 +你知道,海草从海里来 +给土增肥 +你该试试 +你怎么知道这些 +因为我是国王 +因为我应该知道 +关于土地的一切 +就像你将来也会那样 +只要有国王 +只要有土地 +他们就会发动战争抢夺 +抢夺荒芜的田地 +如果战争不结束那会是什么? +他们为和平而战 +和平,梦想而已 +但是你如果当国王 +可能 +就能实现 +你不懂 +战争夺取了我的儿子 +你忘了他们夺去了我的儿子了么 +我的儿子 +海力特将军 +在 +带队侦察队去这片树林的北边 +- 我们要看看我们什么在等待着我们 +- 好的 +- 将军? +- 是 +看 +嗯,这个... +是个令人惊奇的收获 +法罗公爵来受到裁决了 +我猜国王还活着 +贝克勒将军 +把你的剑给他 +不要护甲 +决斗 +可爱 +你记得我在你还是小孩子的时候对你 做过的事吧,泰利斯? +我能喝口酒吗? +没人会帮国王解下护甲吗? +禽兽 +这个决斗会是你最后的决斗了,法罗 +我杀了你 +我要杀了你 +国王死了! +国王死了! +康里得国王死了! +不,不,不可能 +我是你的国王 +- 不,你就是这个国家的诅咒 +- 泰利斯将军 +非常忠诚 +他永远不会杀了艾柏的新国王 +懦夫 +艾柏的子民们 +国王万岁 +收起来 +艾柏的子民们 +艾柏的勇士们 +片刻前 +我们敬爱的王康里得去世了 +被他的侄子谋杀了 +他想篡权 +根据这国家的法律 +国王的继承人必须有血缘关系 +我给你们介绍我们的新国王 +康里得失散的儿子 +卡姆登 康里得 +有人也叫他法莫 +起来吧 +站起来,请站起来 +国王召唤你们来冒死而战 +现在还活着的人已经从死亡 那里得到了奖赏 +但是我们的敌人还活着 +他会重建军队,重新攻击 +今晚我们疗伤 +葬死 +明天我们袭击克里斯英得要塞 +- 直捣恶魔的老窝 +- 直捣恶魔的老窝! +天佑吾王! +什么? +你要什么? +带他们走 +带他们一起走 +等等 +把她带来 +退下 +我在你身上 +感受到他 +那个农民 +他会来找你的,太好了 +- 我会等他的 +- 我对你没价值 +对,但是他对我有价值 +不仅仅只是一个农民 +比一个农民更加危险 +现在他会来找我 +你怎么认识我? +怎样? +别动 +别动 +我在你身上 +感受到他了 +因为你 +怀了他的儿子 +你怀了他的儿子 +你从哪儿来? +格拉森。 +他们从我家里把我带走了 +我们会送你回去的 +我们会死在这里的 +再见了,老朋友 +你怎么与那么大的军队对抗? +大剑失利的地方,小剑就得利 +大法师,没时间猜谜语了 +一小组人会溜过克鲁格人的防守线 +然后在根源解决问题 +带我到这个盖伦那里 +我就能杀了他 +先生,我很尊敬你 +但是我们在王国危急之时去救一个女人? +如果国王要救他的妻子,就得杀了盖伦 +如果他杀了盖伦,王国就得救了 +玛丽安娜 +就是现在 +陛下 +我想加入你 我想要尽我的义务 +好,你已经说了 回城堡吧 +我是我父亲的女儿 +我会尽忠国王,就像他一样 +你带来了谋杀国王的人 +他落入了我手 +一个人需要他所有能得到的帮助,大法师 +我接受你了 +- 还有其他人也想帮忙 +- 什么其他人? +我带你去 +- 你还活着啊 +- 我一直远离这里 +你们对抗的人,控制着克鲁格人人的人 +我们帮你战斗 +以为你们不参与人类的纷争呢 +这战争完不了,我们看出来了 +当我们的森林被侵略被烧毁时 +我们也没其他选择 +我和你们一起战斗,然后 我们希望还是不被打搅 +克里斯英得 +- 当作是法师的避难所而建 +- 很坚固吗? +嗯,门从里面开 +你能进去吗? +- 一个法师无需门就能进去 +- 我会找条路的 +你觉得你还活着很幸运吗? +对 +生活 +从来没这么刺激过 +跟我一起来的人 +为什么不放了他们? +你不想让整个世界都知道你有 无穷的力量和慈悲吗? +你理解不了吗? +我超越了慈悲 +我超越了好和坏 +这些是孩子气的思想而已 +我在改变世界的结构 +如果我给你的朋友发了慈悲, 我会怎么样? +- 那可以... +- 没有例外! +没有例外。 +你不是。 +那农民也不是 +你那个尖叫着被我撕开的孩子也不是 +杀了我 +杀了我 +我不会杀了你 +我很喜欢你 +如果你能流血,你也能死 +可能吧,但是我不会 +我还有很多事情要做 +泰利斯 +弓箭手准备 +放! +就是现在! +上面有个山洞 +是用来通风的 +我得走了 +我不想你一个人走 +如果那个疯子心里还有一丝理智 我就得去试试 +你不能跟恶魔讲理啊,梅里克 +但是我最少可以分散他注意 +我知道你会来的 +老朋友 +我们曾经是朋友 +但是你变了很多 +噢? +一个大法师的力量 +是和他为国王做的服务紧密相联的 +你做为国王的敌人,你的力量成长的怎么样了? +你觉得我的克鲁格人怎么样? +可憎的野兽而已 +克鲁格人很好笑 +他们没有国王 +猜猜我干了什么,老朋友 +- 我不敢猜 +- 我封自己为国王 +克鲁格人之王 +现在我辅佐着一个我万分敬仰的国王 +- 我自己 +- 够了 +盖伦,你跟我是最后的大法师 +我求你,意识到你现在疯癫的情况吧 +你根本不知道 +疯癫 +可以有多么强大 +我的王国里,没有疯癫这个词 +我们就简称为 +力量 +冲! +嗯,他来了 +他到了 +我找不到理由继续打这场战争了 +玛丽安娜 +玛丽安娜 +你在这里 +我不知道发生什么了 +我怎么这么愚蠢? +原谅我 +大法师 +接受我最后的力量吧 +- 杀了他们 +- 帮帮我们 +小心后面! +走! +跑! +快走,我们走 +这边,法莫 +这边 +法莫! +你给我造成了很多麻烦,法莫 +我知道你当上国王了 +一个王国不容两个国王不是吗? +国王一对一的战斗 笑饮死敌之血 +这样的事情多久才会发生一次呢? +你想打,还是想说死我? +想用魔法跟我打? +你的荣耀心呢? +我会复仇的 +不! +你现在享受什么样的复仇呢,法莫? +一个父亲的复仇 一个丈夫的 +还是一个国王的? +你忘了一个母亲的复仇 +发生什么了? +我一直想告诉你 +我爱你 +片名: +末日危城 王者之役 +我知道你会来 +我告诉过你 +我意思是我感觉到了 +你还没来之前我就有感觉 +你力量愈来愈强了,慕黎拉 +我们在一起还是有好处 +不行 +你得离开 +你希望我走? +每次我们偷偷碰面,我觉得... +好虚弱,好无力 +恋爱中的女人可能都这样 +你知道爱情多少? +我知道诗人说愿意为爱而死 +那你愿意吗? +或许... +在诗句中 +家父发现会怎样? +世上有许多事令尊不知道 +这件事也瞒着他吧 +悖理逆天! +盖里恩你疯了,你走火入魔了 +愿众神拯救我们 +继续拔,瑟夫 +脚用力 +甘蓝不想出来嘛 +最难的总是最好的 +看吧 有价值之物不是简单就能得手 +懂了 +你没射到 +我不想杀它们 +只是不让它们偷吃作物 +我带猪来了 相同的交易吗? +冬季谷物换猪? +相同交易 说好就不改变 +这种干燥季节还真不好过 +我遇过更吃不消的 国王在召募新兵 +士兵的待遇很好 +我有这块土地 这样就够了 +你变老之后会厌倦这种生活的 +你不是想展现勇气吗? +种田生活可不需要勇气 +可恶,农夫 讨论一下会要你的命吗? +我们不是动物,人类需要沟通的 +诺瑞克,你先说服甘蓝出来 +等到下雨,土壤会变得泥泞 +到时候谁都无法说服甘蓝出来 +你老爸就是这么固执,瑟夫 +他很懂得自得其乐 +别有样学样,我们走吧 好 +瑟夫,猪牵走 +你大概会留下来用餐吧 +好吧,既然你邀请我 +诺瑞克,真高兴见到你 你应该常来的 +我想农夫从小就看腻我 +现在他有自己的家就该好好享受 +诺瑞克叫爸不要种田 应该加入国王的军队 +等一下,我不是这样说的 +他说国王的士兵挣很多钱 +农夫,你不是真的在考虑吧? +你们是我的家人 我哪里都不去 +诺瑞克,这回答你的问题了吧? +我只是随便说说而已 人各有所长 +我想你拿手的就是随便说说 +你拿手的则是打小报告 +我想吃点鸡肉 别给他 +鸡肉拿来 +说点甜言蜜语 +告诉我你多爱我 +你知道的 +我只知道你说的话 +但你什么都不说 +看我的手 为了养家粗糙不堪 +我的手比我的话还具说服力 +亲口说又不会损失什么 +你想要什么? +每个女人都想要的 +一点激情 +一点激情 +我来试试看 +该出发了 你为何不一起走? +我需要整理作物,记得吧? +男人本来就该负责苦力 +勇气会长存 +没错 +我不喜欢一个人睡觉 +小心安全 +我们要去史东布基 当然很安全的 +为什么大家都叫爸农夫? +他没有名字吗? +你父亲相信人做什么就会像什么 +他很小就被诺瑞克带到史东布基 +所以诺瑞克是他父亲? +镇上的人领养他 +每户人家轮流收留他 +但诺瑞克一直对他特别照顾 +爸现在有家庭了 +我很高兴是我们 +我也是 +将军 +向国王报告 +王上 库拉格人 +残暴且武装的库拉格人 +他们用刀剑攻击我们 +太荒谬了 你好像在说一群凶暴的野狗 +他们像人一样 杀掉我们所有巡守队士兵 +若不是将军命令我回来通报 我应该也殉难了 +一定是巫术 +外婆! +瑟夫,是你吗? +我抓到你了 +总算能把你放进我的烤箱 +我讨厌烤箱 +又干燥 又温暖 +你不希望我们生吃你吧? +你干嘛要吃我? +今晚我答应外公 +准备他喜欢的菜 +市场价格如何? +男人当然想占我便宜 因为我是女人 +所以我开更高的价 因为我就是女人 +你总是这么强悍 +不,我只知道我想要什么 +直到遇见你父亲 +你父亲才不会乖乖听话 +外公呢? +在钟塔上 +我们去找他吗? +小心点 +钟塔是宣告战争的装置 +你别拉错绳子启动战争喔 +你怎么这么久才来? +对他们狠一点 +太疯狂了 +库拉格人就像野兽 他们没穿盔甲,徒手搏斗 +我得借你的马,诺瑞克 +你要去哪里? +史东布基 +索拉娜和瑟夫在那里 我跟你去 +农夫没来 +他希望我交易,他照顾农地 +你是他的好妻子 +他也很爱你 +对,我相信他是 +新郎和新娘接吻时 摇这个钟五下 +向镇上的人报佳音 +快走 带瑟夫回家 +爸,带他走,你能保护他 +小姐,准备好了吗? +我随时都准备好了 +停手! +这么快就放弃了? +你的进步... +好神速 +真希望艾柏王国能多一些 像你一样强的士兵 +那就让我加入军队 +我想艾柏军队不欢迎女战士吧 +况且令尊一定有意见 +家父禁止我做任何事 +塔利斯 +叫你的军队准备出发了 +一群库拉格人正在侵略王国 +太阳刺得我皮肤好痛 +你在胡说什么? +还不服从我的命令 +我只听从国王的命令 +你最好... +学会一点尊敬 +人受尊敬要名符其实 +你错了 我凭家世就值得受尊敬 +索拉娜正在摇钟 +别担心,瑟夫 我会找到你妈 +爸! +巴士汀 +拿我的剑 +进来把门闩上 快拿去 +爸,谢谢 快走 +他们正在劫掠村庄 +厉害 +你很有种嘛 +放他走 +你今天已经杀了我一次 但我们又对上了 +爸 +快跑,瑟夫 +看,他们在撤退 +瑟夫! +瑟夫! +我还要替索拉娜建立墓碑 +没人看见索拉娜 没人听说 +没发现她的尸体,她可能逃了 +没错,农夫 +你去哪里了? +我一直找不到你 +我很忙 +非常忙 我们有协定 +我帮你潜入城堡以利我们联手 +我正在进行我的工作 +最近的灾难相信能显示 我是多么地忙碌 +的确,你引起不少骚动 +引起骚动? +告诉我,公爵 +你知道一个叫农夫的人吗? +史东布基的人民 +艾柏王国的军队同情你们 +这场重大悲剧会被平反的 +正当库拉格人屠杀民众时 国王的军队在哪里? +农人! +别忘了自己的身份 +我认为 你应该在国王面前低头吧 +我认为 国王的军队应该保护国土 +而不只是城堡 +被库拉格人掳走的人怎么办? +库拉格人掳走村民? +安静! +就算库拉格人俘虏村民 +我们也不知道他们的目的何在 +国王军队需要所有能作战的男人 +谁要加入? +国王有自己的军队 +那些俘虏只有我们 +你竟敢违抗国王的诏令 我支持你,农夫 +卫兵! +让他们走 +艾柏王国是民主的 +你竟敢冒险违抗国王 你更冒险 +我没有选择,她是我妻子 她是我姊姊 +好吧,我们去找人 +你留下来 跟军队待在艾柏王国 +你想要当军人,对吧? +不 我不喜欢穿军服 +你有马吗? +一只母马 +她老了但仍很强壮 +老了 但仍很强壮 +你挡住我了 +我们见过面吧? +说点甜言蜜语 +告诉我你多爱我 +你知道的 +我是梅里克,国王的术士 我听过你 +你会小孩的魔法玩意 +你的国王需要你 +是啊,我儿子也需要我 +我却辜负他 我妻子若活着也需要我 +农夫,你有想过吗? +人生可能有更伟大的事... +比起你爱或你失去的人? +不,我没想过 +努力活下去,农夫 +你的国王需要你 +可能连他自己都不知道 +你怎么知道有这座桥? +小时候我常在这附近玩 +我童年就在这里渡过的 +如果我们绕过峡谷会耗掉整天 你有什么馊主意? +我们越过去 +把马具拆下 +什么? +要把马留下来? +你怕伤马的感情吗? +回家! +快点! +过去吧 +好,我先来 +你真是勇敢的老男人 +我只是不想绳子被你弄断 结果轮不到我 +快点 好,我们过去吧 +你对马还比较关心 +我喜欢我的马 至于你,我就不确定 +你跟我熟之后就会喜欢我 +这样省了我们不少时间 +王上 站稳,士兵 +这里有多少人在看守? +我正在看守,王上 +你还真尽忠职守呢 +法罗公爵,你真调皮 +你弄得我酥胸好痒 +我要跟你妈告状 +你要去哪里? +我的侄儿正在自得其乐 +你觉得这样适当吗? +国王和军队出征时你还在玩乐 +你的唯一工作就是... +守卫城堡 +结果却完全没人在看守 +王上 +我刚才在调查... +奇风异俗之事 +别让他出现在我眼前 不 +别碰我 +你连碰我衣服都没资格 +那你更没资格玷污国王的王位 +除非国王确实命令你 +你不准碰我 +帝国法律 +正是我的挡箭牌 +事情正依照计划进行 我等不及了 +我受不了那些老臣的规矩 +快实现我的目标 +你想加快进行的速度? +没问题 +我们应该加快脚步 +很好 +盖里恩 +为何你总是无声无息突然出现? +我没有 +我的出现其来有自 +你自以为能擅自闯进我的闺房 +我喜欢你以前欢迎我的方式 +你不能想来就来,想走就走 +然后什么都没说就消失 +我不是你的娼妇 +你怎么会这样想? +你了解我必须无声无息地出现 +我不方便敲大家闺房的房门吧? +你不能随便出现 +况且家父还认为你是国王的敌人 +我有朋友 我有影响力 +为何家父如此鄙视你? +他不常厌恶别人 +干嘛质问我? +我不是来这里接受你审问的 +你父亲厌恶我 +因为我从不在国王和他面前低头 +因为我从他身上夺去我要的东西 +甚至他女儿的贞节 +滚出我的房间 +滚出我的人生 +你也要驱逐我吗? +我们一起做过许多事 +我还发掘你的力量 以及你的理想 +你只带给我小把戏和噩梦 别说了 +王上 +请再度接受我最诚恳的歉意 +我糟蹋你的命令了 +糟蹋? +你承认过错了? +对 +王上,我能坐下吗? +仆人! +我明白... +下去! +我明白我辜负你的信任好几次 +你与全国人民可能都对我失望 +但我会改变 +我会抛掉我的年少轻狂 +在吾国面临此伟大战役之际 我会证明我是够资格的继承者 +吃吧 +你真是舌灿莲花,侄儿 +很适合外交 +这方面你有本领 +我能敬您一杯吗? +下次吧 +改过自新的人不该早上就喝酒 +有道理 +没错,有道理 +国王万岁! +真会说话 +库拉格人上次攻击南部史东布基 +对,因地形险恶他们会... +往北部沼泽地移动 +我们应该进攻 +库拉格人的行动只是假设 +我不喜欢这样,农夫 +没人想进去塞吉维克森林 +这座森林刚好在群山之间 +这样我们就可以追上库拉格人 +塞吉维克森林不仅只有草木而已 +你不能随便穿越 +你不会想晚上被困在这里的 +我们可以点火炬 火炬会引起注意 +我不在乎 +农夫,你听过传闻 塞吉维克森林有怪东西 +我也听说上帝会保护无辜者 +传闻现在对我们没用 +快点,我们还有很多路要走 +我根本没看到路径 +没有路径 那我们怎么知道通往哪里? +有动静 +诺瑞克,你没事吧? +农夫,这在你的计划之内吗? +放我们下来 我得看情形 +离开我们的森林 你们不能干扰这里 +我不喜欢你们的武器和杀戮 +我们只是通过而已 那就赶快通过 +别再闯进来 +我们... +迷路了 +人类啊 不仅没用还很无助 +王上 +我请求您告诉我家父的消息 +你父亲为我出任务 拜托您 +发生什么事? +我担心他面临重大危险 +国王的术士肩负很多责任 +他的女儿不需要烦恼男人的事 +家父以为把我关在城堡 我的心灵能够平静 +他错了 我能感受到王宫的紧张气氛 +现在遇上天大的困难 +黑暗 +判决 +我知道魔法酿成了黑暗势力 +快跑 +你父亲去寻求来源 +还有解决之道 +你父亲 王上! +盖里恩 我感觉我快死了 +你跟国王一起用餐? +你干了什么事? +我以为你很急 想加快进行的速度 +我对国王的食物动了手脚 +你毒害我,你竟然杀我 +别自哀自怜了 +任何事都能解决 +拜托 +希望你记得谁才真正握有大权 +我会记得 +我救了你一命 +那你该为我做什么? +国王被下毒了 +他能得救吗? +或许 只要不会太晚 +我保证 +能私下谈一下吗? +法罗逃出城堡并带走两大军团 +现在我们知道是谁下毒了 +我们是北军 我们会在北方跟新盟友会合 +我们集结的兵力 +会为各世代带来和平与安宁 +我感觉到盖里恩的魔掌 +为何不是塔利斯宣告这场任务? +有人想叛国吗? +还剩多少兵力? +三分之一 +我感到库拉格人的势力在扩张 +盖里恩正在召集军团 +巨大的军团 难以致信 +他一个人怎么可能 造成如此大的毁灭 +我自己的女儿 竟然跟敌人暗通款曲 +你这么恨我吗? +我原本以为我爱他 +他渗入我们的血统 +你也拥有他部分的力量 +因为你 王国可能会灭亡 +对不起... +你们为何讨厌外来者? +你们互相憎恨 为何我们不能恨你们? +我们安身在森林避开你们的战争 +还有争夺及愚蠢的野心 +你们闯进来 箭射进我们的树林 +彼此伤害是你们人类的天性之一 +你们不了解自己多么危险 +我只能带你们到这里 +祝好运 +下一步呢? +你醒了吗? +是,我醒了 +他们会发现害死国王没这么容易 +我们要进攻 +可是王上 您中毒了 +您也许会撑不下去 我撑得下去,指挥官 +而且我有智慧 +库拉格人不会料到我们会进攻 所以我们要行动 +谁下毒的? +恐怕是你侄儿法罗公爵 +更惨的是 +他弃城逃走 +并带走卫兵及两大军团 +我们进攻,展开第一场战役 +召集你的军队 +我还有多少时间? +你的生命所剩不多 +但时间还够 +诺瑞克,你确定吗? +不太确定 +她在这里,诺瑞克 +我感觉得到 我想你是对的 +别激动! +索拉娜? +索拉娜! +今天 +我们为国王而战 +国王也要一起奋战 +以艾柏王国之名 +王上 +出发 +上帝祝福为荣耀而死之人 以及真理! +我对你很好奇,农夫 +你让我感到危险 +我读不出你的心 +我读得出多数人的心 +读出他们的全部,但是你? +我读不出你的过去 +为什么? +你是谁? +有些谜不值得解 +你们来了 +我以为我做了一场恶梦 +农夫呢? +瑟夫呢? +巴士汀,瑟夫呢? +他跟我们父母在一起吗? +是,他们都在一起 +他也遭不幸了 +你被抓走那天他们被杀了 +我很遗憾 +我的儿子,天啊 +他死前没受苦吧? +告诉我 +没有 +他死得很快 +农夫会来 +他会找到你 +你怎么知道? +因为他必须如此 +因为他需要你 +在末日之际 他最需要的就是你 +别死,农夫 +你还有许多使命 +你看起来不太好 +来 +喝一点 +感觉怎样? +这是什么? +是药 +回家真好 +我不是你的娼妇 +他用你来毁灭... +我知道诗人们说... +他以玩弄感情为乐 你还没得到教训吗? +不是我帮你提升你的力量 你的预感吗? +小姐 +我伤害了父亲 +我危害整个王国 +你父亲不会改变对你的爱 +我做了一堆蠢事 +你自杀只会伤他更深 +或许你是对的 +我希望父亲以我为荣 +他本来就是 +他对我有期许 +准备跟新盟友会合吧 +他们是库拉格人 +服从 别再质疑了 +他们是强大的军队 +照顾这男人 +带他去国王的帐篷 +喂饱我的马儿 +这就是你的紧急任务? +他是史东布基的农夫 +没错 +为何一个只顾情爱的背叛者... +会赢得国王术士的青睐? +因为他对国王有特殊意义 +我不懂有何意义 +国王也不懂 +我想你们该好好认识对方了 +我见过他 +上次他违抗我 +我只是做我该做的事 +我想他对王上有意义 +上次之后他受了许多苦 +大家都是 +他有什么特别? +王上,因为... +他是你儿子 +农夫有位朋友叫诺瑞克 +他以前负责看顾王后的马 +我在史东布基认出他 +奥斯里大屠杀之后 +诺瑞克发现一个约三岁的男孩... +在战场上徘徊 +当时奥斯里的男孩只剩王子 +农夫,你对这故事有何看法? +一个老男人自以为记得 30年前的事 +难怪他当不上国王 +你是国王之子 王位的继承者 +我没有父亲 +没有父母 +这里不关我的事 +你是说这个狂人是我的儿子? +他住在史东布基农地30年 +表面上是 +表面上是 你说我儿子死了 +你说我家人都死了 +众神在开我什么玩笑? +有时众神知道怎样对我们最好 +究竟什么意思? +记得那时多么混乱吗? +到处都是战事 被敌人包围 +若这孩子被带回艾柏城堡 +他能活多久? +他在史东布基成长茁壮 +远离那些极力夺取... +王子和王位的敌人 +我的好友 +你最好没认错 +你最好能确定 +国王需要有能力的人帮他作战 +这不是我的问题 +他的王国被威胁了 你的王国被威胁了 +我不认识国王 +索拉娜才是我的家人 +诺瑞克与巴士汀也是 +你们打算住哪里? +王国要是落入盖里恩的手中 +你能给你的妻子什么未来 +你想清楚 +法罗,你犯了叛国罪 +你在这里没有权力 +跟随你的士兵也被视为叛徒 +我们不饶恕叛国者 +各位 +塔利斯指挥官毒害了国王 +却指控我叛国,真好笑 +你的野心真大,塔利斯 +艾柏王国属于我的控制 +我们不会让他掌权 +你绝对当不成国王,侄儿 +因为你缺乏勇气 +现在没有,永远也不会有 +11与12军团跟随您,王上 +懦夫! +库拉格人没有弓箭手 但他们也不怕死 +现在他们人数较多 但我们是人类 +我们效忠一个高尚的王国 +他们是残暴贪欲的野兽 什么都不是 +你前来尽自己的义务吗? +我决定为国而战 +我有幸跟你一同奋战 这样我才能监视你 +保持警戒 +指挥官 +率领军队 +发射! +发射! +别怕,乖马儿 +将军,打起战旗 +士兵们,快走 +他们像狗一样凶猛 +是的 +我们走 +准备好 +发射! +发射! +这些库拉格人丧心病狂了 +他们一定还有很多人 +为了战胜,一切在所不惜 +我们不会输的 +不管你们杀多少库拉格人 +我只会召唤更多人手来 +魔灵地 这里是我们的赎罪之地吗? +不,诺瑞克 +这里是我们的贞洁之地 +这里使人坦然面对罪恶 +国王 +别乱动,亲爱的叔父 +射击! +卫兵 +快点! +护送国王离开战场 +真棒,我的好叔父 +你们只争取到一点时间 +我不想过这种生活 +我们身在其中,我们是奴隶 +我不想活得像奴隶 诺瑞克,别说了 +我们为何进入塞吉维克森林? +我们穿越就能抵达艾柏城堡 +没有军队没有警备 我们等着城堡到手 +我们快离开这里 +真想不到,看谁来了 +遇到家族成员真开心! +独自一人在森林 你不觉得害怕吗? +别靠近我 慕黎拉,你从未信任过我对吧? +你的德行绝对不会获得信任 +德行? +端正? +这些都只适用于城堡 +我们现在又不在城堡 +这里没有任何规矩 +不! +送你一件大礼 +谢谢 +哪里都有规矩,公爵 +你破坏规矩的下场就是失败 +我带走这个 +索拉娜,快跑! +快点,快走! +诺瑞克! +你一直想要得到... +壮烈的牺牲 +你是一个勇敢的老男人 +索拉娜! +巴士汀? +快跑! +站在我后面 +我不饿 +你今天很勇猛 +杀掉野兽 +这种勇气很残忍 +不管这代表什么 +你会完成使命 我只是一个辛苦农人 +迟早会有意义的 +在你当上国王之后 +不然你认为你... +今天为何如此勇猛? +难道是... +好运? +你知道自己的资质 +领导力 +当然还有你的坦诚 +这些都会助你一臂之力 +智慧是我们的榔头 +审慎是我们的钉子 +当人类吃得苦中苦... +勇气会长存 +勇气会长存 +你哪里听到这些话? +我告诉我儿子 +当他还小时我每晚跟他说 +我只告诉过他 +现在开始你的日子会更艰难 +我只是一个农夫 我懂 +我只知道这样 你听过一个小村庄... +离这里不远 +他们一年种植两次作物 +这样会破坏土壤 不 +他们没有破坏土壤 因为有海藻 +海藻来自大海 +能使土壤肥沃 +你该试试 +你怎么会知道这些事? +因为我是国王 +因为我应该了解... +这块土地 +你也应该这样 +只要国王存在 +只要国土存在 +人民就会努力奋战 +这样会让土地更贫瘠 +战争不断有何意义? +你为和平而战 +和平 这是梦想 +这个梦想也许得靠你... +身为国王... +带来永远的和平 +你不了解 +这些战争夺去我的孩子 +你忘了也夺去我的孩子 +吾儿 +哈雷特将军 +是,长官 +派巡守兵去森林北边 +探测我们将会面对怎样的敌人 是,长官 +指挥官 什么事? +你看 +真是突来的访客 +法罗公爵来这里接受审判 +我想国王没死吧 +贝克勒将军 +你的剑给他 +不用盔甲 +决斗啊 +真友善 +记得小时候我怎么教训你的吧? +至少让我喝一口酒吧? +我没有盔甲怎么保护我的国王? +一群猪 +这场决斗 是你的最后一战,法罗 +我会杀掉你 +我应该杀掉你 +国王死了! +国王死了! +康瑞德国王驾崩了! +不,不可能 +我是你们的国王 +你是第一位继承者 +塔利斯指挥官是遵守荣誉的人 +你绝不会杀掉艾柏的新国王 +懦夫 +我的艾柏子民 +国王万岁 +好! +好! +万岁! +好! +好! +万岁! +把刀放下 +艾柏的人民 +艾柏的士兵 +几刻钟前 +我们深爱的康瑞德国王驾崩了 +被他的侄儿谋杀 +为了夺取王位 +依照我国的法律 +国王的继承者必须是他的血亲 +我向大家宣布我们的新国王 +康瑞德国王失散的儿子 +一般人称他为农夫 +平身 +请起立 站起来 +国王召请各位面对死亡 +留下的人要以生命为代价 +我们的敌人仍活着 +他会重建力量再度发动攻击 +今晚我们包扎我们的伤口 +埋葬我们的牺牲者 +明日我们前往魔灵地 +深入恶魔的巢穴! +深入恶魔的巢穴! +上帝拯救国王! +什么? +干嘛? +把他们带走 +跟其他人关在一起 +等一下 +把她带过来 +滚! +我感觉到他... +在你身上 +那个农夫 +他会来找你 +太棒了,我等他来 我对你没用 +对,但他对我有用 +他不只是农夫 +比农夫危险多了 +过来我这里 +你如何认出我的? +如何? +别动 +别动 +我感觉到他... +在你身上 +因为你怀着... +他的孩子 +你怀着他的孩子 +你从哪里来的? +葛罗森 他们把我从家中掳走 +我们会送你回家 +我们会死在这里 +再见,我的老友 +我们如何对抗那么庞大的军队? +阔剑失败的地方,短刀会成功 +别猜谜了,术士 +弱势军队能溜过库拉格人的阵线 +解决根源的问题 +帮我找到盖里恩 +我要干掉他 +长官,冒昧问您 +我们的计划是救一个女人 却不顾整个王国的安危吗? +国王救妻子,必须干掉盖里恩 +干掉盖里恩,王国就得救 +慕黎拉 +军队要出发了 +王上 +我希望跟您一道作战 我希望为您服务 +我们说好了 你回城堡去 +身为父亲的女儿 +我要跟他一样为国王服务 +你抓来杀国王的凶手 +他落入我的手中 +男人需要任何帮手,术士 +我接受你的请求 +还有其他人想帮忙 什么人? +我带你去 +你存活下来了 而且没再干扰你们 +你们对抗的敌人 控制库拉格人的敌人 +我们会帮你们对抗他们 +但你们不希望介入人类的战争 +我们知道这场战争不会结束 +等到我们的森林被烧毁及入侵 +我们连选择都没有 +我们跟你们齐肩并战 之后再平静过生活 +魔灵地 +盖得像坚不可破的密所 多坚固呢? +门只能从里面开 +你能潜入吗? +术士不需要从门进入魔灵地 我也会想办法进去 +你认为自己活着很幸运吗? +我是 +人生 +没这么令人兴奋过 +跟我一起被掳来的那些人 +为何不释放他们? +你不希望世人知道你同时 拥有神力和慈悲吗? +你不懂吗? +我超越慈悲 +我超越善与恶 +这些都是幼稚的想法 +我要改变世界的结构 +事情会没完没了 假使我对你朋友表现慈悲 +我可以 没人能豁免 +你不能 农夫不能 +被我剥夺梦想的男孩都不能 +杀掉我! +杀掉我! +我不会杀你 +我欣赏你 +你只要会流血,你就会死 +或许我会 但不会发生 +我还有许多事未完成 +射击! +弓箭手准备好 +射击! +放下石头! +上面有一个洞穴 +空气可以进入 +现在我要离开你了 +我不想要你一个人过去 +如果那个狂妄之徒还有一点理智 我一定试图感化他 +你无法说服那个魔鬼,梅里克 +但至少我能分散他的注意力 +我就知道你会来 +我的老友 +我们曾是朋友 +但你完全变了 +是吗? +术士的力量是就要帮助国王 +你却坐大成为国王的敌人 +你认为我的库拉格人怎样? +他们是残酷的恶兽 +库拉格人很奇怪 +他们没有国王 +好友,猜我做了什么事? +我不想猜 我让自己成为国王 +库拉格人的国王 +这是我最热中帮助的国王 +我自己 够了 +盖里恩 我们两人是仅存的术士 +我求你承认你已陷入疯狂 +你不懂 +疯狂是多大的一股力量 +我的王国中 没有所谓的疯狂 +我们称疯狂为... +权力 +进攻! +他在这里 +他来了 +看来事情不必再拖了 +慕黎拉 +慕黎拉 +你来了 +我不懂我怎么过来的 +我一直太愚蠢了 +原谅我 +术士传人 +吸纳我最后的力量 +谁来救我们,拜托 +快跑! +快走! +跟他走! +这边,农夫 +这边 +你令我心神不宁,农夫 +我知道你成为国王 +吾国一山不容二虎吧? +两个国王只会造成战乱不止 +彼此争得你死我活 +你是想决斗,或是说服我就范? +你想用魔法跟我决斗吗? +你的荣誉呢? +我要复仇 +不! +你想要复什么仇? +身为父亲或丈夫的仇? +还是身为国王的仇? +你忘记身为母亲的仇 +怎么回事? +有句话我一直想告诉你 +我爱你 +法罗,你犯了叛国罪 +我们不讲条件 +任何听从你指挥的人 +也将被视为叛国者 +我们不饶恕叛国者 +先生们 +泰利斯将军毒害了国王 +还说我叛国 +你野心无边啊,泰利斯 +艾柏之国现在由我统治 +我们,也不讲和 +我的侄子,你永远也当不上王 +因为你没胆量 +现在没有,将来也没有 +第11和第12军团归您统管,陛下 +你们这些懦夫 +克鲁格人没弓箭手,也不会害怕 +现在他们比我们人多,但是我们是人 +我们忠于一个高贵的国家 +它们是野兽,嗜血的野兽,仅此而已 +那么,你来尽责吗? +我决定了要一战 +有你们在我身边一起我很骄傲, 我也会留意你的 +中尉 +将军 +走吧 +弓箭手 +放! +放! +没事的 +将军,包抄侧面 +勇士们,出发 +它们像疯狗一样打仗 +对啊 +我们走 +预备 +放! +放! +这些克鲁格人人不用脑子打 +它们的脑子在这里 +你赢得一时,不算什么 +我们赢得一世! +你杀了这些 +我就招出更多的 +克里斯英得,这是我们偿还罪孽的地方吗? +不,诺瑞科 +这是我们偿还美德的地方 +罪孽比美德在这里要吃香 +国王 +别动,好叔叔 +放! +卫兵! +卫兵! +快 +把国王抬离战场 +快 +永别了,好叔叔 +走 +你只是争取到了点时间而已 +我不会像他们那么活的 +我们已经是他们了,我们是奴隶 +- 我不会当奴隶的 +- 收声,诺瑞科 +我们为什么要进入塞奇威克森林? +我们要从森林走近路去艾柏城堡 +没军队没卫兵,城堡随便拿下 +我们快离开吧 +看看,一个家里的朋友 +我非常高兴 +独自在这个森林里你不觉得容易受伤吗? +- 你离我远点 +- 你从不相信我,是吗,玛丽安娜? +你的举止从来都没赢得过尊敬 +举止? +礼貌? +这都是城堡的言谈 +我们不在城堡里 +这里也没有规矩 +给你的特别礼物 +谢谢 +到处都有规矩的,我的公爵 +你喜欢打破规矩的这种天赋 最终还是没用啊 +我带这个走 +跑! +索拉娜,跑! +快跑! +我会找你的,走! +诺瑞科! +诺瑞科! +这是你一直想要的吧 +光荣战死 +你是个勇猛的老人 +索拉娜 +巴斯蒂安? +靠后 +不,我没事 +你今天很不错 +杀野兽 +- 需要狠下心来 +- 没错 +不管什么出现 +- 你都能战胜它 +- 我做苦活习惯了 +当你是国王的时候 +将会更有用 +你怎么看待你今天 +战斗得这么好? +我意思是,难道这仅仅只是 +运气? +你有天赋,你知道的 +领导能力,然后,当然 +你实话实说 +这会让你更好的为国家服务 +智慧是我们的武器 +谨慎则是我们的盔甲 +当人在诚实劳动中 +建设生活 +勇气不灭 +你从哪儿听到的这些? +当我儿子还小的时候 +我每天晚上 +都对他这么说 +别人都不知道 +现在开始你生活会变得更加艰苦 +- 我只是个农民 +- 是,是 +- 我只知道这个 +- 你知道,这里不远的地方 +有个小村子 +他们一年收两季稻子 +- 那会破坏土壤的 +- 不 +这样不会破坏土壤因为有海草 +你知道,海草从海里来 +给土增肥 +你该试试 +你怎么知道这些 +因为我是国王 +因为我应该知道 +关于土地的一切 +就像你将来也会那样 +只要有国王 +只要有土地 +他们就会发动战争抢夺 +抢夺荒芜的田地 +如果战争不结束那会是什么? +他们为和平而战 +和平,梦想而已 +但是你如果当国王 +可能 +就能实现 +你不懂 +战争夺取了我的儿子 +你忘了他们夺去了我的儿子了么 +我的儿子 +海力特将军 +在 +带队侦察队去这片树林的北边 +- 我们要看看我们什么在等待着我们 +- 好的 +- 将军? +- 是 +看 +嗯,这个... +是个令人惊奇的收获 +法罗公爵来受到裁决了 +我猜国王还活着 +贝克勒将军 +把你的剑给他 +不要护甲 +决斗 +可爱 +你记得我在你还是小孩子的时候对你 做过的事吧,泰利斯? +我能喝口酒吗? +没人会帮国王解下护甲吗? +禽兽 +这个决斗会是你最后的决斗了,法罗 +我杀了你 +我要杀了你 +国王死了! +国王死了! +康里得国王死了! +不,不,不可能 +我是你的国王 +- 不,你就是这个国家的诅咒 +- 泰利斯将军 +非常忠诚 +他永远不会杀了艾柏的新国王 +懦夫 +艾柏的子民们 +国王万岁 +收起来 +艾柏的子民们 +艾柏的勇士们 +片刻前 +我们敬爱的王康里得去世了 +被他的侄子谋杀了 +他想篡权 +根据这国家的法律 +国王的继承人必须有血缘关系 +我给你们介绍我们的新国王 +康里得失散的儿子 +卡姆登 康里得 +有人也叫他法莫 +起来吧 +站起来,请站起来 +国王召唤你们来冒死而战 +现在还活着的人已经从死亡 那里得到了奖赏 +但是我们的敌人还活着 +他会重建军队,重新攻击 +今晚我们疗伤 +葬死 +明天我们袭击克里斯英得要塞 +- 直捣恶魔的老窝 +- 直捣恶魔的老窝! +天佑吾王! +什么? +你要什么? +带他们走 +带他们一起走 +等等 +把她带来 +退下 +我在你身上 +感受到他 +那个农民 +他会来找你的,太好了 +- 我会等他的 +- 我对你没价值 +对,但是他对我有价值 +不仅仅只是一个农民 +比一个农民更加危险 +现在他会来找我 +你怎么认识我? +怎样? +别动 +别动 +我在你身上 +感受到他了 +因为你 +怀了他的儿子 +你怀了他的儿子 +你从哪儿来? +格拉森。 +他们从我家里把我带走了 +我们会送你回去的 +我们会死在这里的 +再见了,老朋友 +你怎么与那么大的军队对抗? +大剑失利的地方,小剑就得利 +大法师,没时间猜谜语了 +一小组人会溜过克鲁格人的防守线 +然后在根源解决问题 +带我到这个盖伦那里 +我就能杀了他 +先生,我很尊敬你 +但是我们在王国危急之时去救一个女人? +如果国王要救他的妻子,就得杀了盖伦 +如果他杀了盖伦,王国就得救了 +玛丽安娜 +就是现在 +陛下 +我想加入你 我想要尽我的义务 +好,你已经说了 回城堡吧 +我是我父亲的女儿 +我会尽忠国王,就像他一样 +你带来了谋杀国王的人 +他落入了我手 +一个人需要他所有能得到的帮助,大法师 +我接受你了 +- 还有其他人也想帮忙 +- 什么其他人? +我带你去 +- 你还活着啊 +- 我一直远离这里 +你们对抗的人,控制着克鲁格人人的人 +我们帮你战斗 +以为你们不参与人类的纷争呢 +这战争完不了,我们看出来了 +当我们的森林被侵略被烧毁时 +我们也没其他选择 +我和你们一起战斗,然后 我们希望还是不被打搅 +克里斯英得 +- 当作是法师的避难所而建 +- 很坚固吗? +嗯,门从里面开 +你能进去吗? +- 一个法师无需门就能进去 +- 我会找条路的 +你觉得你还活着很幸运吗? +对 +生活 +从来没这么刺激过 +跟我一起来的人 +为什么不放了他们? +你不想让整个世界都知道你有 无穷的力量和慈悲吗? +你理解不了吗? +我超越了慈悲 +我超越了好和坏 +这些是孩子气的思想而已 +我在改变世界的结构 +如果我给你的朋友发了慈悲, 我会怎么样? +- 那可以... +- 没有例外! +没有例外。 +你不是。 +那农民也不是 +你那个尖叫着被我撕开的孩子也不是 +杀了我 +杀了我 +我不会杀了你 +我很喜欢你 +如果你能流血,你也能死 +可能吧,但是我不会 +我还有很多事情要做 +泰利斯 +弓箭手准备 +放! +就是现在! +上面有个山洞 +是用来通风的 +我得走了 +我不想你一个人走 +如果那个疯子心里还有一丝理智 我就得去试试 +你不能跟恶魔讲理啊,梅里克 +但是我最少可以分散他注意 +我知道你会来的 +老朋友 +我们曾经是朋友 +但是你变了很多 +噢? +一个大法师的力量 +是和他为国王做的服务紧密相联的 +你做为国王的敌人,你的力量成长的怎么样了? +你觉得我的克鲁格人怎么样? +可憎的野兽而已 +克鲁格人很好笑 +他们没有国王 +猜猜我干了什么,老朋友 +- 我不敢猜 +- 我封自己为国王 +克鲁格人之王 +现在我辅佐着一个我万分敬仰的国王 +- 我自己 +- 够了 +盖伦,你跟我是最后的大法师 +我求你,意识到你现在疯癫的情况吧 +你根本不知道 +疯癫 +可以有多么强大 +我的王国里,没有疯癫这个词 +我们就简称为 +力量 +冲! +嗯,他来了 +他到了 +我找不到理由继续打这场战争了 +玛丽安娜 +玛丽安娜 +你在这里 +我不知道发生什么了 +我怎么这么愚蠢? +原谅我 +大法师 +接受我最后的力量吧 +- 杀了他们 +- 帮帮我们 +小心后面! +走! +跑! +快走,我们走 +这边,法莫 +这边 +法莫! +你给我造成了很多麻烦,法莫 +我知道你当上国王了 +一个王国不容两个国王不是吗? +国王一对一的战斗 笑饮死敌之血 +这样的事情多久才会发生一次呢? +你想打,还是想说死我? +想用魔法跟我打? +你的荣耀心呢? +我会复仇的 +不! +你现在享受什么样的复仇呢,法莫? +一个父亲的复仇 一个丈夫的 +还是一个国王的? +你忘了一个母亲的复仇 +发生什么了? +我一直想告诉你 +我爱你 +谢谢观赏 +你说对了,诺瑞科 +这个也是意料之中吗,法莫? +- 放我们下去 +- 我想放就放 +滚出我们的森林,你们与这里无关 +我们恨你们的武器和你们的杀戮 +- 我们只是穿过这里 +- 那就穿过去 +别再回来 +我们迷路了 +人类,不仅没用,也很无助 +陛下 +我想要知道我父亲的消息 +- 你父亲为他的王去办件小事去了 +- 求你了 +发生什么了? +我担心他有极大的危险 +国王的大法师有很多的责任 +他并不需要一个总是用绯闻 +来惹麻烦的女儿 +我父亲觉得把我锁在城堡里 能减轻我的担忧 +他错了,我感受到宫廷里的气氛 从来都没有这么困扰过 +黑暗威胁着 +我们的国家 +从魔法中生出的黑暗 +走! +快 +你父亲在寻求原因... +- 和解决方法 +- 陛下? +陛下? +- 你的父亲... +- 陛下! +盖伦! +我觉得我要死了 +你跟国王吃得好吗? +你干了什么? +我以为你想要加速呢 +我想我可能对国王的吃的做了手脚 +你给我下毒了,你杀了我了 +别这么戏剧化 +没什么不能弥补的 +求你 +求你 +希望我们都记得谁在这里有着最大的权力 +好 +我觉得我救了你一命 +你应该为我做点什么呢? +国王被下毒了 +能救吗? +可能吧,如果还不迟的话 +性命保证 +私下谈一下 +法罗逃出了城堡 +还带走了两个军团 +那我们就知道谁给国王下毒了 +准备北上,和我们的新同盟会师 +我们联合的力量... +将使我们享有世代的和平和安宁 +我能感到盖伦跟这个有关 +为什么泰利斯长官没有跟我们提到过这次行动? +还有想要犯叛国罪的人吗? +- 还剩下多少军队? +- 三分之一 +嗯 +我看到克鲁格人在大量集结 +盖伦在召集军队 +- 大量的军队 +- 怎么会? +一个人怎么可能会造成如此大的破坏呢? +我亲生女儿背叛我,投进死敌的怀抱 +你这么恨我吗? +我以为我爱他 +他混入了我们的血缘 +你把魔法的平衡偏向了他的一方 +因为你,这个王国可能灭亡 +对不起,对不起 +对不起,对不起 +你们为什么这么恨外来人? +你们互相敌视,我们为什么不能敌视你们呢? +我们躲藏在森林里,避开你们的战争和争端 +和你们愚蠢的劳动 +但是你们还是在这里 对准我们的树射箭 +伤害就是你们生活的一部分 +你们最危险的地方就是你们自己 +我最远只能送到这里 +好运 +我们有计划吗? +你醒了吗? +是,我醒了 +你会发现杀死一个国王没那么容易 +我们要进攻 +但是,陛下,你被下毒了 +- 可能你还没认清形势 +- 我认清了 +我也有我的头脑 +克鲁格人不会料到我们会攻击 所以我们就一定要攻击 +谁给我下的毒? +我认识是你的侄子,法罗公爵 +噢 +更坏的是 +他逃离了城堡 +带走了第11和第12军团 +我们要进攻 +拂晓,集结你的军队 +我还能活多久? +你的生命即将结束 +但是剩下的时间足够了 +你确定吗,诺瑞科? +一点也不 +她在这里,诺瑞科 +- 我感觉得到 +- 我觉得你是对的 +嘿,慢点 +索拉娜? +索拉娜! +今天... +我们为国王而战 +我们的国王骄傲地 +为艾柏而战 +陛下 +起立! +神佑为荣耀和真理献身的人! +我对你很好奇,法莫 +我能感觉到你很危险 +我看不透你 +我能看到大多数的人,就像 阅读活着的书一样 +但是你,我都看不透你紧锁的眉头 +为什么? +你是谁? +有些谜不值得去解开 +你在这里 +我以为是个噩梦 +法莫呢? +扎夫呢? +巴斯蒂安,扎夫在哪儿? +跟我们父母一起吗? +对 +他是跟他们一起,但是 +他没逃出来 +你被带走的那天,他就被杀了 +对不起 +我的宝贝 +他死得安逸吗? +告诉我 +对 +他死得安逸 +法莫会来的 +他会找到你的 +你怎么知道? +因为他必须这样 +因为他需要你 +再怎么说,你也是他真正需要的 +法莫别死 +你要做的事情还有很多 +你看上去不怎么好啊 +啊,这个 +来试试 +- 味道怎么样? +- 这是什么? +药。 +快起来 +回家真好 +我不是你的妓女 +他用你来毁灭... +我知道诗人们说... +他以玩弄感情为乐,你还不吸取教训? +不是我帮你提升你的力量,你的预感吗? +小姐? +我是我父亲的累赘 +我阻碍了一切 +但是你父亲很爱你啊 +我小女孩般的愚蠢伤害了他 +自杀会伤他更重的 +可能你是对的 +我想要我的父亲以我为荣 +他已经是这样了 +他只是以这个想法为荣而已 +准备迎接你们的新盟军吧 +这是克鲁格人 +顺从,无情且不犹豫 +你看到的是一个强大的军队 +带走这个人 +把他放在王国的营帐里 +保证喂饱我的马 +等等 +这是你的紧急事务? +这是法莫,石桥镇的 +对 +为什么一身泥土味的不尽忠的 石桥镇农民 +会让国王的大法师怎么挂念? +因为国王对这个农民有特殊挂念 +我怎么不知道 +国王也不知道 +我觉得现在你们应该好好认识一下 +我们见过了 +上次,他拒绝了我 +去做他需要做的事情 +我以为陛下会对这个农民感兴趣 +从我们见过以后,他经历了许多事情 +大家都一样 +什么让他这么特殊? +因为,陛下 +他是你儿子 +法莫的朋友诺瑞科 +是管理王后马匹的人 +上次在石桥我认出他来了 +在牛草地小道的屠杀后,这个诺瑞科 +在战场上找到一个3岁大的小孩 +牛草地小道只有一个小孩 +你觉得这个故事怎么样,法莫? +一个老人以为他认出了一个30年没见的人 +这就是你们选国王的方式? +你是国王的儿子,王位继承人 +我没父亲 +没父母 +我与这里无关 +你的意思是那个傲慢的混蛋是我的儿子? +他30年来 +住在石桥的农场里? +就是这样 +就是这样,你告诉我他已经死了! +你说他们全死了! +神对我开了 +什么样的玩笑啊 +有时候神知道什么对我们最好 +那是什么意思? +你记得我们那个时候混乱的状况吗? +到处是战争,到处是敌人 +如果这个孩子带回了艾柏城堡 +他能活多久? +在石桥长大 +他很健壮 +离敌人很远 +敌人随时都可能 +除掉你的儿子和王储 +亲爱的朋友 +你最好是对的 +你最好心里有数 +国王需要所有有能力的士兵 +- 这不是我的问题 +- 他的王国被侵略了。 +你的王国被侵略了 +我不认识这个国王 +索拉娜是我的亲人 +诺瑞科和巴斯蒂安,他们是我的亲人 +你住在哪儿呢? +嗯? +如果王国落入盖伦之手... +你又能为你妻子提供什么样的未来? +想想吧 +法罗,你犯了叛国罪 +我们不讲条件 +任何听从你指挥的人 +也将被视为叛国着 +我们不饶恕叛国者 +先生们 +泰利斯将军毒害了国王 +还说我叛国 +你野心无边啊,泰利斯 +艾柏之国现在由我统治 +我们,也不讲和 +我的侄子,你永远也当不上王 +因为你没胆量 +现在没有,将来也没有 +第11和第12军团归您统管,陛下 +你们这些懦夫 +克鲁格人没弓箭手,也不会害怕 +现在他们比我们人多,但是我们是人 +我们忠于一个高贵的国家 +它们是野兽,嗜血的野兽,仅此而已 +那么,你来尽责吗? +我决定了要一战 +有你们在我身边一起我很骄傲, 我也会留意你的 +中尉 +将军 +走吧 +弓箭手 +放! +放! +没事的 +将军,包抄侧面 +勇士们,出发 +它们像疯狗一样打仗 +对啊 +我们走 +预备 +放! +放! +这些克鲁格人人不用脑子打 +它们的脑子在这里 +你赢得一时,不算什么 +我们赢得一世! +你杀了这些 +我就招出更多的 +克里斯英得,这是我们偿还罪孽的地方吗? +不,诺瑞科 +这是我们偿还美德的地方 +罪孽比美德在这里要吃香 +国王 +别动,好叔叔 +放! +卫兵! +卫兵! +快 +把国王抬离战场 +快 +永别了,好叔叔 +走 +TLF字幕组出品 +Present By: +Shooter. +cn +字幕分割: +LiChangShun 时间轴调校: +天空的心 +片名: +末日危城 +我就知道你会来 +我早告诉你了 +我意思是,我感觉到了 +你来之前我能感觉到 +你的力量在慢慢变强,玛丽安娜 +我们在一起的时间终于开始有用了 +等等 +你必须走了 +你希望如此吗? +我们每次这样见面,我都觉得... +无力。 +觉得被吸干了一样 +可能爱情就会让女人这样吧 +你知道什么是爱? +我知道诗人们都愿以一死来交换 +- 你会以死交换吗? +- 可能吧 +在诗里 +我父亲会怎么说? +世上的事情你父亲不知道的很多 +让这个也变成其中之一吧 +渎神,这太疯狂了,盖伦 你太过分了 +神救救我们吧 +用力拉,扎夫 +用腿的力气 +它不想出来 +最大的都是最顽固的 +看吧,有价值的东西都不会轻易到手 +你没打中 +我不想杀了他们 +只要它们不吃庄稼 +猪来了,还是老价钱吧? +冬天的玉米换这猪? +老价钱,不变 +是个挺旱的一季吧 +- 更旱的我也见过 +- 国王在招兵 +兵的待遇都很好 +我有这块地,还不够吗? +你老了后,你就会厌倦只是这么活着 +你不想挑战一下你的勇气吗? +我意思是,这样的生活有什么勇气可言? +我靠,法莫,说说话你会死吗? +我的意思是,我们又不是动物。 +人就应该跟别人说话啊 +诺瑞科,如果我能把这些甘蓝说出来 我肯定会的 +雨一来,地就变成块 +那时候你都不能把它们说出来了 +这就是为什么我喜欢你爸,扎夫 +他总是知道怎么来扫兴 +- 带诺瑞科去我们放玉米的地方 +- 好 +给,扎夫,给你这头猪 +你留下来吃晚饭吧? +嗯,既然你都开口了... +诺瑞科,能看到你太好了 你应该常来 +嗯,我觉得法莫小时候已经看厌我了 +现在既然他成家了, 就应该稍微调整一下 +诺瑞科觉得父亲应该不种田,而去参军 +等等,我没这么说啊 +他说国王的战士都拿很多钱 +法莫,你没诚心想这个吧? +你们是我的家人。 +我哪儿也不去 +- 你得到答案了,诺瑞科? +- 我只是说说 +- 只是说说 +- 嗯,人人都有特长嘛 +只是说说看来是你的特长 +出卖朋友看来是你的 +- 我能来点鸡肉吗? +- 别给他 +把鸡肉给我! +说点好听的给我听 +告诉我你多爱我 +你知道的 +我只知道你告诉我的... +你却什么都没告诉我 +看看这双手,为养活我们而开裂 +这双手比话语更说明问题 +告诉我有什么损失吗? +你还想要什么呢? +每个女人都想要的 +一点点激情 +- 一点点激情? +- 嗯哼 +我想想我能怎么办 +- 该走了 +- 你为什么不跟我们一起去? +我还有很多地要清理 +记住,当人从辛勤劳动中创造生活时 +勇气永不灭 +对了 +我讨厌睡觉时没有你 +小心点 +石桥镇而已,我们当然会很安全的 +为什么别人都叫父亲法莫? +他没名字吗? +你父亲相信人跟他所做的事情密切相联系 +他很小的时候,诺瑞科把他带到石桥镇 +那诺瑞科是他的父亲? +整个镇子收养了他 +不同的时候有不同的家庭收养他 +但是诺瑞科总是关注着他 +他现在有个家了 +我真高兴是我们和他一起组成的这个家 +嗯,我也这么觉得 +将军 +报告给你的国王 +陛下,克鲁格人... +野蛮的军队,克鲁格人... +它们用剑打仗 +这太可笑了,就好像你在说持武器的狗一样 +它们像人一样打仗 它们把整个侦察队都杀了 +如果将军没命令我会来报告的话 我也死了 +这是某种魔法 +外婆! +外婆! +扎夫,是你吗? +抓住你了 +终于! +放你进烤箱 +我不喜欢烤箱 +烤箱又干又暖和 +你不想我们把你生吃了吧? +你为什么要吃了我? +今晚,我向你外公保证... +要做他最喜欢的菜 +- 集市上卖得怎么样? +- 不错 +当然,男人都想来占我便宜 因为我是女人 +我就让他们多付钱 因为我是女人 +我们还小的时候你总是当头 +- 总是当头 +- 不,我知道我要什么,就这样 +直到她遇到你父亲 +你父亲放荡不羁 +- 外公呢? +- 在钟塔 +- 我们去看看? +- 我们得小心点 +钟塔是为战时而建的 +你不想拉错绳子而引起场战争吧? +什么耽搁了你这么久? +哈! +他们没那么容易被吓跑的 +这真是疯了 +克鲁格人是野兽 他们没有盔甲和武器的 +我要用你的马,诺瑞科 +- 你去哪儿? +- 石桥镇 +- 索拉娜和扎夫在那儿 +- 我跟你一起 +法莫没来? +没,我丈夫喜欢让我来做买卖 他好种地 +你为你丈夫做得很好 +他很爱你 +对,我相信他是很爱我的 +新郎新娘接吻时,鸣钟五次... +给整个镇子他们结婚的消息 +走,现在就走,带扎夫回家 +带他走! +你能保护他,父亲 保护他 +- 准备好了吗,我的女士? +- 从来都是 +等等 +这么快就认输了? +你进步神速啊,令人印象深刻 +如果艾柏能有更多像你这样的剑士 +让我加入你的军队,你就有了 +我不确定艾柏的军队是否准备接受女兵了 +而且,你父亲会怎么说? +我父亲从不让我做我想做的 +泰利斯! +准备好你的军队,准备出发 +克鲁格的散兵在抢掠我们的土地 +噢,太阳刺痛了我的皮肤 +你在胡说什么? +你服从命令就行了 +我只听从国王的 +你应该... +学习怎么尊敬别人 +敬意是赢得的 +错了,敬意是我天生的 +回镇子! +所有人都是! +- 索拉娜在哪? +- 她在敲钟 +别担心,扎夫,我会找到她 +- 父亲! +- 巴斯蒂安! +拿着我的剑 +- 进去,堵住门 +- 快点 +- 谢谢你,父亲 +- 去吧 +我们在镇子里找 +大家快走! +快点 +干得好 +有种的人? +放开他们 +你今天杀了我一次了 但是我们又见面了 +爸爸! +跑,儿子! +看! +它们撤了 +扎夫! +- 它们撤到高地上去了! +- 扎夫! +别让它们跑了 +我还要给索拉娜做个标记 +没人看到她,没人知道 +我们没找到她,她可能跑了 +他说得对,法莫 +盖伦! +你去哪儿了? +我一直在找你 +我很忙 +- 很忙 +- 我们达成了协议的 +我让你进出我的城堡 我们就能合作 +我守着承诺 +我肯定最近这些消息都能表明 我有多么的忙 +对,你确实稍微搅和了一下 +搅和? +告诉我,公爵 +你对一个叫法莫的人了解多少? +石桥镇的镇民们 +艾柏的军队同情你们 +这样的惨剧会被复仇的 +克鲁格人来的时候,国王的军队呢? +农民,不要忘了你在和谁说话 +在你的世界里,你不对国王鞠躬吗? +在我的世界里,国王的军队是来保护国家的 +不是只是城堡 +被克鲁格带走的人怎么办? +- 克鲁格抓了人质? +- 安静! +如果克鲁格人带走了人质... +它们的目的就很不明确 +国王的军队召集任何一个 能打仗的人 +- 谁来? +- 然后怎么样? +国王有军队和城墙 +被克鲁格抓走的人就只有我们 +- 你敢违抗国王的意愿? +- 我跟你走,法莫 +- 卫兵! +- 让他们走 +这不是艾柏之道 +- 你违抗国王,冒很大的风险 +- 不比你冒的大 +- 我没有选择,她是我的妻子 +- 她是我的姐姐 +好,我们开始吧 +留下来,跟着艾柏的军队走吧 +你想过军队生活,不是吗? +不。 +我不喜欢制服 +- 你有马吗? +- 有匹母马 +老,但是很强壮 +老... +但是仍然很强壮 +你挡我路了 +我们以前见过吧? +说些好听的给我听 +告诉我你有多爱我 +你知道的 +- 我是梅里克,国王的大法师 +- 我听说过你 +孩子们关于魔法的故事 +你的国王需要你 +嗯,我的儿子也需要我 +但是我让他失望了 现在我的妻子需要我,如果她还活着 +你有没有想过,法莫 +在国家处于非常时期的时候... +我们个人的爱和得失难道更重要吗? +不,但是和我无关 +好好活着吧,法莫 +你的国王需要你 +远远超过他目前的所知道的 +你怎么知道这座桥的? +小时候我在这些地方玩耍 +这就是我怎么浪费我的时间 +- 如果我们绕过这个峡谷,我们就浪费了一天 +- 你觉得呢? +我们能过 +让我们先把马上的装备拿下来 +你什么意思? +我们就这么放了它们? +你担心我们会伤了它们感情? +回去吧! +走! +来吧 +- 好,我要去了 +- 你是个勇敢的老头 +我只是不想你在我之前先 弄坏了绳子 +- 快点 +- 好,走吧,快! +你更关心你的马 +我喜欢我的马 但是我不确定我喜欢不喜欢你 +嗯,等你了解我再说 +这的确节省了我们不少时间 +噢! +- 陛下 +- 站起来,士兵 +多少人在守卫着? +我在守卫着,陛下 +嗯,你在守卫着? +法罗公爵,你非常,非常坏 +你让我胸痒痒的 +我要告诉你妈妈 +你们在干什么 +我的侄子在王座上玩耍 +你觉得配吗? +你在国王和他的军队 +出去进行招兵活动的时候玩耍... +而你唯一的工作 +就是保证城堡的安全 +而守卫城堡的人... +等于零! +陛下... +去调查偏僻地区的事务 +你给我消失 +快,别让我推你 +拿开你的手 你都不配去吻我的袍子 +你不配弄脏你叔叔的王冠 +除非国王特别下令... +你不能碰我 +皇家法律 +是个我最喜欢的 +玩具 +- 一切都在按计划进行 +- 我等不了了 +我受不了那个老山羊的控制 +实施那个 +你想快速解决? +好! +我们就来快速的 +好 +盖伦 +你一定要突然悄无声息的出现吗? +我没有 +我是突然从某个地方出现的 +你不受邀请就进来我的房间 这样有些过了 +你以前的热情好客我现在都得不到了吗? +你不能想来就来,想走就走 +然后突然消失 +我不是你的妓女 +你为什么这么想? +你很清楚什么我必须这么安静地出现 +我不能在我爱人的门上重叩,对不对? +你怎么能想来就来... +你又被我父亲认为是国王的敌人? +我有我的朋友,我有我的关系 +为什么我父亲这么恨你 +他是一个很谨慎的人 +问题! +我不是来被责问的 +你父亲恨我是因为我不会 +对伟大的国王和大法师鞠躬作揖 +因为我可以从他那里得到我想要的 +甚至是他女儿的纯洁 +你离开我的房间 +离开我的生活 +你也在驱逐我吗? +在我们完成了那么多事情之后? +我没帮助你发现你的力量,你的预感吗? +- 你只是教会了我小把戏和恶梦 +- 收声! +帮帮我! +陛下 +再次请求你接受我最深的歉意 +我错误理解了你的命令 +错误? +- 那个是错误? +- 对 +我可以坐吗,陛下? +仆人! +我知道,退下 +我知道我在几个场合都辜负了你的信任 +而且我可能让你和整个王国很失望 +但是我会改变 +我会在这个战争年代摆脱 年轻的愚蠢 +我会证明自己是个合格的王储 +吃吧 +我的侄子,你对适时的外交 +有独特的理解 +那就是点优点 +我能敬你吗? +可以吧 +在早上喝酒并不是表达改正决心的 +最好方式 +没错 +对,没错 +国王万岁 +是 +克鲁格人攻击了南部的石桥镇 +对,然后这片山 +会迫使他们北上,绕过沼泽 +然后我们进攻 +那是基于如果克鲁格人按他们应该的习惯 而行动的话 +我不喜欢这里,法莫 +没人去塞奇威克森林 +森林在山脉之间 +我们会在板岩道和克鲁格人会面 +塞奇威克森林里不止有灌木和树 +你不能想穿就穿啊 +你不想在这里过夜的 +- 我们点火炬 +- 火炬会吸引东西的 +- 让他们来吧 +- 法莫! +你知道人们怎么说的。 +塞奇威克森林里有东西 +人们说神保佑无辜者 +人们说很多事现在都对我们没用,诺瑞科 +快,我们还有很多路要走 +我看不到路 +- 本来就没路 +- 那我们怎么知道怎么走呢? +等等 +-=THE LAST FANTASY= +- 荣誉出品 本字幕仅供学习交流,严禁用于商业途径 +-=TLF字幕组= +- 翻译: +mortia xaon 校对: +haha168 +片名: +末日危城 +我就知道你会来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I knew you'd come. +我早告诉你了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I told you I would. +l +- I felt it. +你来之前我能感觉到 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I felt it before you came. +Muriella. +我们在一起的时间终于开始有用了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Our time together is paying off. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Wind Whistling] +等等 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Stop. +你必须走了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You have to leave. +你希望如此吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Is that your wish? +I feel- +无力。 +觉得被吸干了一样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Weak. +I feel drained. +可能爱情就会让女人这样吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Whispering] Perhaps that is what love does to a woman. +你知道什么是爱? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What do you know of love? +我知道诗人们都愿以一死来交换 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I know that poets claim they would die for it. +- 你会以死交换吗? +- 可能吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Would you die for it? +- Perhaps. +在诗里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- In a poem. +- [Laughs] +我父亲会怎么说? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Chuckles] +- What would my father say? +世上的事情你父亲不知道的很多 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}There are many things in this world your father doesn't know. +让这个也变成其中之一吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Let this be one of them. +Gallian. +You go too far. +Screaming] +神救救我们吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] May the gods save us. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Indistinct Voices] +Zeph. +用腿的力气 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Use your legs. +它不想出来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Zeph] It doesn't want to come out. +最大的都是最顽固的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Grunts] +- It's those big ones that are always the toughest. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Grunts] +- [Chuckles] +看吧,有价值的东西都不会轻易到手 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}See? +Things worthwhile don't come easy. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Cawing] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Squawking] +你没打中 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You missed. +我不想杀了他们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I don't want to kill them- +只要它们不吃庄稼 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}As long as they don't eat the crops. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Pig Squealing] +猪来了,还是老价钱吧? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Brought the hog. +Same deal as always? +冬天的玉米换这猪? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Winter's corn for the pig? +老价钱,不变 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Same deal. +Deal never changes. +hasn't it? +- 更旱的我也见过 +- 国王在招兵 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- I've seen rougher. +- King's recruiting. +兵的待遇都很好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Soldiers get taken care of really well. +我有这块地,还不够吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I have this land. +Isn't that enough? 你不想挑战一下你的勇气吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Wouldn't you like to test your courage? +where's the courage in just surviving? +would it kill you to just talk for a little while? +we're not animals. +People actually do converse with one another. +I would. +this ground turns to clay. +那时候你都不能把它们说出来了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Not even you could talk 'em out of the ground then. +Zeph. +他总是知道怎么来扫兴 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He always knows how to set a mood. +- 带诺瑞科去我们放玉米的地方 +- 好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Show Norick where we stack his corn. +- Okay. +Zeph. +Have a pig. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Laughing] +- [Squealing] +你留下来吃晚饭吧? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Farmer] Guess you'll be staying for supper. +since you asked. +it is so good to see you. +You should come by more often. +I figure Farmer saw enough of me when he was growing up. +maybe he needs a little bit of a break. +诺瑞科觉得父亲应该不种田,而去参军 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Norick thinks Father should quit farming and join the king's army. +等等,我没这么说啊 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Gasps] +- Now hold on a second. +I didn't say that exactly. +他说国王的战士都拿很多钱 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He says the king's soldiers make a lot of money. +are you? +你们是我的家人。 +我哪儿也不去 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You're my family. +I'm not going anywhere. +Norick? +- I was just talking. +everyone's got a talent. +Woman Laugh] +出卖朋友看来是你的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Just ratting on his friends seems to be yours. +please? +- Don't give it to him. +har. +- [Zeph Laughs] +说点好听的给我听 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Tell me something nice. +告诉我你多爱我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Tell me how you love me. +你知道的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You know. +Sighs] +我只知道你告诉我的... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I only know what you tell me... +你却什么都没告诉我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and you tell me nothing. +看看这双手,为养活我们而开裂 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Look at these hands +- Broken to feed us. +这双手比话语更说明问题 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}These hands speak louder than words. +告诉我有什么损失吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What is the cost of telling me? +你还想要什么呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What more could you want? +每个女人都想要的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What every woman wants- +一点点激情 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A little passion. +- 一点点激情? +- 嗯哼 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- A little passion? +- Mm +-hmm. +let me see what I can do. +- 该走了 +- 你为什么不跟我们一起去? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Woman] It's time to go. +- [Zeph] Why can't you come with us? +我还有很多地要清理 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Farmer] I have all those fields to clear. +记住,当人从辛勤劳动中创造生活时 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Remember +-When men build lives from honest toil- +勇气永不灭 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Courage never fails. +- [Laughs] +对了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}That's right. +我讨厌睡觉时没有你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I hate sleeping without you. +小心点 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Be safe. +石桥镇而已,我们当然会很安全的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It's Stonebridge. +Of course we'll be safe. +为什么别人都叫父亲法莫? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Zeph] Why do people call Father Farmer? +他没名字吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Doesn't he have a name? +你父亲相信人跟他所做的事情密切相联系 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your father believes that people become what they do. +他很小的时候,诺瑞科把他带到石桥镇 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Norick brought him to Stonebridge when he was just little. +那诺瑞科是他的父亲? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}So Norick is his father? +整个镇子收养了他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The whole town adopted him. +不同的时候有不同的家庭收养他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Different families took him at different times. +但是诺瑞科总是关注着他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}But Norick +- He always kept a special eye out. +他现在有个家了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm glad he has a family now. +我真高兴是我们和他一起组成的这个家 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm glad it's us. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Mmm! +嗯,我也这么觉得 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Mmm. +So am I. +将军 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}General. +报告给你的国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Report to your king. +Krug- +野蛮的军队,克鲁格人... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Savage army. +The Krug- +它们用剑打仗 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}They +-They fight with swords. +这太可笑了,就好像你在说持武器的狗一样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This is ridiculous. +It's as if you were talking about armed dogs. +它们像人一样打仗 它们把整个侦察队都杀了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}They fight like men. +They killed off our entire scouting party. +I should be dead as well. +这是某种魔法 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This is some sort of sorcery. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chattering] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[No Audible Dialogue] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Low Rumble] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Rumbling Continues] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Rustling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Rumbling] +外婆! +外婆! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Zeph] Grandma! +Grandma! +is that you? +抓住你了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughs] I've got you. +终于! +放你进烤箱 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Finally! +Into the oven with you. +我不喜欢烤箱 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Laughs] +- I hate the oven. +it's warm. +do you? +你为什么要吃了我? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Why do you have to eat me? +I promised your grandfather... +要做他最喜欢的菜 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}we're going to eat a dish he really loves. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Rumbling Continues] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Muttering] +how were sales at the market? +- It was good. +the men tried to take advantage of me because I'm a woman... +我就让他们多付钱 因为我是女人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}so I make them pay more +- because I'm a woman. +我们还小的时候你总是当头 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Laughing] +- When we were kids you were always in charge. +that's all. +直到她遇到你父亲 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Until she met your father. +你父亲放荡不羁 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your father does not take orders very well from anybody. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +- 外公呢? +- 在钟塔 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Where's Grandfather? +- The bell tower. +- 我们去看看? +- 我们得小心点 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Shall we go? +- We have to be careful. +钟塔是为战时而建的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The bell tower was made for times of war. +do you? +Snarling] +Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] Hah! +什么耽搁了你这么久? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What took you so long? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +哈! +他们没那么容易被吓跑的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hah! +They don't scare easy. +Groaning] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Aaah! +- Aaah! +这真是疯了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] This is crazy. +克鲁格人是野兽 他们没有盔甲和武器的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Krug are beasts. +They don't have armor and weapons. +Norick. +- 你去哪儿? +- 石桥镇 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Where are you going? +- Stonebridge. +- 索拉娜和扎夫在那儿 +- 我跟你一起 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Solana and Zeph are there. +- I'm coming with you. +法莫没来? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Farmer didn't come? +没,我丈夫喜欢让我来做买卖 他好种地 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}No. +My husband likes to leave the trade to me so that he can farm. +你为你丈夫做得很好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You did well for a husband. +他很爱你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He loves you very much. +对,我相信他是很爱我的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Yes. +Yes. +I believe he does. +ring the bell five times... +给整个镇子他们结婚的消息 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}signaling their marriage for the village to hear. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +走,现在就走,带扎夫回家 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Go. +Go now. +Take Zeph home now. +Father. +Protect him. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Bell Clanging] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughs] +my lady? +- Always ready. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +等等 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hold. +这么快就认输了? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Giving up so soon? +你进步神速啊,令人印象深刻 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your progress is truly remarkable. +如果艾柏能有更多像你这样的剑士 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}If only Ehb had more soldiers of your caliber. +让我加入你的军队,你就有了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Let mejoin your army and you shall. +- [Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Both Laughing] +我不确定艾柏的军队是否准备接受女兵了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I am not quite sure that the armies of Ehb are ready for women warriors. +what would your father say? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +我父亲从不让我做我想做的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My father never lets me do anything I want. +泰利斯! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] Tarish! +准备好你的军队,准备出发 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Prepare your troops to ride. +克鲁格的散兵在抢掠我们的土地 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hordes of Krug are ransacking the land. +the sun is blistering my skin. +你在胡说什么? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What is this nonsense you speak? +你服从命令就行了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Just do as you're commanded. +我只听从国王的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I listen only to the king. +你应该... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It might behoove you... +学习怎么尊敬别人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}to learn a little respect. +敬意是赢得的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Respect is earned. +错了,敬意是我天生的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You are mistaken. +Respect is my birthright! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Clamoring] +Screaming] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Screams] +- [Snarls] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Clanging Continues] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Snarling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Gasps] +- [Snarls] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +everyone! +- 索拉娜在哪? +- 她在敲钟 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Where's Solana? +- She's +-She's sounding the bell. +Zeph. +I'll find her. +- 父亲! +- 巴斯蒂安! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Father! +- Bastian! +拿着我的剑 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Take my sword. +- 进去,堵住门 +- 快点 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Norick] Get inside. +And bolt the door. +- [Mother] Come quickly. +Father. +- Go. +Screaming Continue] +Snarling] +我们在镇子里找 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] We'll look for her in the village. +men! +Come on. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Hissing] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Scream Echoing] +干得好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughing] Well done. +huh? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Screams] +- [Krugs Snarling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Woman Screams] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Snorting] +放开他们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Snarling] +- Let 'em go. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Echoing Laughter] +here we are again. +爸爸! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Father! +- [Groans] +Son! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Screaming] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Panting] +看! +它们撤了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Look! +They're retreating. +扎夫! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Zeph! +- 它们撤到高地上去了! +- 扎夫! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Man] They're going to higher ground! +- Zeph! +别让它们跑了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man #2] Don't let 'em get away! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gulls Crying] +我还要给索拉娜做个标记 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I need a fourth marker for Solana. +没人看到她,没人知道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Nobody saw Solana. +Nobody knows. +我们没找到她,她可能跑了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We didn't find her body. +She could have escaped. +Farmer. +盖伦! +你去哪儿了? +我一直在找你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Gallian! +Where have you been? +I've been looking for you. +我很忙 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I've been busy. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Door Closes] +- 很忙 +- 我们达成了协议的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Very busy. +- We had an agreement. +我让你进出我的城堡 我们就能合作 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I gave you access to my castle so that we might work together. +我守着承诺 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And I'm keeping my end. +我肯定最近这些消息都能表明 我有多么的忙 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm sure recent events demonstrate how very busy I've been. +indeed. +You have managed to stir things up a bit. +搅和? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Stir things up? +Duke. +你对一个叫法莫的人了解多少? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What do you know of a man they call Farmer? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chattering] +石桥镇的镇民们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[King] People of Stonebridge. +艾柏的军队同情你们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The armies of Ehb sympathize with you. +这样的惨剧会被复仇的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This great tragedy will be avenged. +克鲁格人来的时候,国王的军队呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where were the king's army when the Krug came killing? +do not forget to whom you speak. +don't you bow before your king? +the king's army's expected to protect the kingdom. +不是只是城堡 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Not just the castle. +- [Woman Weeping] +被克鲁格带走的人怎么办? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What of those taken by the Krug? +- 克鲁格抓了人质? +- 安静! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Krug taking prisoners? +- Silence! +如果克鲁格人带走了人质... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}If these Krug have taken prisoners... +它们的目的就很不明确 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}it is not yet clear what their purpose might be. +国王的军队召集任何一个 能打仗的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] The king's army will require every man capable of combat. +- 谁来? +- 然后怎么样? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Tarish] Who is with us? +- [Woman] What will happen? +国王有军队和城墙 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The king has his armies and his walls. +被克鲁格抓走的人就只有我们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Those taken by the Krug only have us. +Farmer. +- 卫兵! +- 让他们走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Guards! +- [King] Let them go. +这不是艾柏之道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}That is not the way of Ehb. +- 你违抗国王,冒很大的风险 +- 不比你冒的大 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Farmer] You took a risk turning your back on the king. +- No more risk than you. +- 我没有选择,她是我的妻子 +- 她是我的姐姐 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- I have no choice. +She's my wife. +- She's my sister. +let's get to it. +留下来,跟着艾柏的军队走吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Stay here. +Go with the armies to Ehb. +didn't you? +不。 +我不喜欢制服 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Nah. +I didn't like the uniforms. +- 你有马吗? +- 有匹母马 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Do you have a horse? +- A mare. +but still strong. +老... +但是仍然很强壮 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Old... +but still strong. +你挡我路了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You're in my way. +have we not? +说些好听的给我听 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Solana's Voice] Tell me something nice. +告诉我你有多爱我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Tell me how you love me. +你知道的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Farmer's Voice] You know. +the king's magus. +- I've heard of you. +孩子们关于魔法的故事 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Children's stories about magic. +你的国王需要你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your king needs you. +my son needed me. +if she lives. +Farmer... +在国家处于非常时期的时候... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}that there may be events of greater importance... +我们个人的爱和得失难道更重要吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}than the loves and losses of our particular lives? +不,但是和我无关 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}No. +Doesn't occur to me. +Farmer. +你的国王需要你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your king needs you. +远远超过他目前的所知道的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Far more than he understands. +你怎么知道这座桥的? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] How did you know about this bridge? +小时候我在这些地方玩耍 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Farmer] As a child I roamed around these parts. +这就是我怎么浪费我的时间 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It's how I spent my days. +- 如果我们绕过这个峡谷,我们就浪费了一天 +- 你觉得呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- If we wind through the gorge we'll lose a day. +- What are you thinking? +我们能过 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We can cross it. +让我们先把马上的装备拿下来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Let's take the gear off the horses. +just like that? +你担心我们会伤了它们感情? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Are you afraid we're gonna hurt their feelings? +回去吧! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Go home! +Hah! +- Hah! +走! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Hah! +- Get out of here. +来吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Let's do it. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +I'll go. +- You're a brave old guy. +我只是不想你在我之前先 弄坏了绳子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I just don't want you weakening the rope before I've had my turn. +let's go. +Come on. +你更关心你的马 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You were more concerned about your horse. +我喜欢我的马 但是我不确定我喜欢不喜欢你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My horse I like. +It's you I'm not so sure about. +wait till you get to know me better. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Yells] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Both Yelling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Stops Yelling] +Yelling] +这的确节省了我们不少时间 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}That saved us a lot of time. +噢! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Oh! +soldier. +多少人在守卫着? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[King] How many men on guard here? +my king. +嗯,你在守卫着? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hmm. +You are on guard? +very naughty. +- [Giggling] +你让我胸痒痒的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You make my bosoms tickle. +我要告诉你妈妈 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm gonna tell your mommy. +你们在干什么 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where are you going? +我的侄子在王座上玩耍 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[King] My nephew amuses himself on the king's throne. +你觉得配吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Do you feel it suits you? +你在国王和他的军队 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You play while your king and his legions... +出去进行招兵活动的时候玩耍... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}are off on a military campaign... +而你唯一的工作 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and your only job... +就是保证城堡的安全 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}is the safety of this castle- +而守卫城堡的人... +等于零! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}which is guarded by... +no one! +陛下... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your Majesty... +去调查偏僻地区的事务 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}was off investigating outlandish claims. +Aah! +你给我消失 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Get him out of my sight. +- No! +before I make you. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Door Slams] +拿开你的手 你都不配去吻我的袍子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Unhand me. +You are not fit to kiss my gown. +你不配弄脏你叔叔的王冠 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And you +-You are not fit to tarnish your uncle's crown. +ah. +除非国王特别下令... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Unless the king specifically orders it... +你不能碰我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}you cannot touch me. +皇家法律 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Imperial law... +是个我最喜欢的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}is a toy... +玩具 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I shall never tire of. +- 一切都在按计划进行 +- 我等不了了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Things are progressing according to plan. +- I cannot wait any longer! +我受不了那个老山羊的控制 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I cannot stand the suffering rule of that senile goat. +实施那个 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Make it happen. +你想快速解决? +好! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You wish to accelerate things? +Fine! +我们就来快速的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We shall accelerate. +好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Good. +盖伦 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Gallian. +你一定要突然悄无声息的出现吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Must you always appear suddenly from nowhere? +我没有 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I don't. +我是突然从某个地方出现的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I appear so suddenly from somewhere. +你不受邀请就进来我的房间 这样有些过了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You assume too much entering my chambers unbidden. +你以前的热情好客我现在都得不到了吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm not welcome to the hospitality you've offered in the past? +你不能想来就来,想走就走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You're not welcome to come and go as you please... +然后突然消失 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and then vanish without a word. +我不是你的妓女 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm not your harlot. +你为什么这么想? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How could you think such a thing? +你很清楚什么我必须这么安静地出现 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You know very well why I must appear so quietly. +can I? +你怎么能想来就来... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How do you come and go as you please... +你又被我父亲认为是国王的敌人? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}when you're considered by my father to be an enemy of the king? +我有我的朋友,我有我的关系 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I have friends. +I wield influence. +为什么我父亲这么恨你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Why does my father despise you so? +他是一个很谨慎的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He's not known for his hasty opinions. +问题! +我不是来被责问的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Questions! +I did not come here to be interrogated. +你父亲恨我是因为我不会 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your father hates me because I will not bow and scrape... +对伟大的国王和大法师鞠躬作揖 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}before the almighty king and his magus. +因为我可以从他那里得到我想要的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Because I will take from him what I please- +甚至是他女儿的纯洁 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Even his daughter's virtue. +你离开我的房间 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Whispering] Begone from my chambers. +离开我的生活 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Begone from my life. +- [Chuckles] +你也在驱逐我吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Are you banishing me as well? +在我们完成了那么多事情之后? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And after all the work we've done. +your vision? +- 你只是教会了我小把戏和恶梦 +- 收声! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- You've introduced me to parlor tricks and nightmares. +- Be still. +Grunting] +帮帮我! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Woman] Help! +Please. +Please. +陛下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My liege. +再次请求你接受我最深的歉意 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Again allow me to offer my deepest apologies... +我错误理解了你的命令 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}for mistaking your orders. +错误? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A mistake? +- 那个是错误? +- 对 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Is that what it was? +- Yes. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hmm. +Your Majesty? +仆人! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Boy! +我知道,退下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I know +- Go. +我知道我在几个场合都辜负了你的信任 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I know I have failed your trust on several occasions... +而且我可能让你和整个王国很失望 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and perhaps I may be a disappointment to you... +but I will change. +我会在这个战争年代摆脱 年轻的愚蠢 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I will shed this youthful folly in this time of great battle... +我会证明自己是个合格的王储 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and I will prove myself a worthy heir. +吃吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Eat. +my nephew... +有独特的理解 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}for well +-timed diplomacy. +那就是点优点 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I guess that's something. +我能敬你吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}May I offer a toast? +可以吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Possibly. +在早上喝酒并不是表达改正决心的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Drinking wine in the morning is not a good way... +最好方式 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}to show... +reform. +没错 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Indeed. +indeed. +国王万岁 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Long live the king. +是 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chuckles] Yes. +in the south. +and this harsh terrain... +around the marsh. +然后我们进攻 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Then we should attack. +if the Krug behave the way they're supposed to behave. +Farmer. +没人去塞奇威克森林 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Nobody goes into Sedgwick Forest. +森林在山脉之间 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Farmer] The forest passes between the mountains. +我们会在板岩道和克鲁格人会面 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We'll come out at Slate Pass as the Krugs arrive. +塞奇威克森林里不止有灌木和树 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}There's more than brush and trees in Sedgwick Forest. +你不能想穿就穿啊 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You don't just cut through it when you please. +你不想在这里过夜的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You don't wanna be stuck here at night. +- 我们点火炬 +- 火炬会吸引东西的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- We'll light torches. +- Torches attract eyes. +- 让他们来吧 +- 法莫! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Let 'em look. +- Farmer! +你知道人们怎么说的。 +塞奇威克森林里有东西 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You know what people say. +There are... +things in Sedgwick Forest. +人们说神保佑无辜者 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}People say God watches over the innocent. +Norick. +快,我们还有很多路要走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Come on. +We've got a lot of ground to cover. +我看不到路 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] I don't see any path. +- 本来就没路 +- 那我们怎么知道怎么走呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- There is no path. +- So how do we know where we're going? +等等 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Whispering] Wait. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Whoa! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Oh! +Norick. +Farmer? +- 放我们下去 +- 我想放就放 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Let us down. +- When I'm ready. +滚出我们的森林,你们与这里无关 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Get out of our forest. +You have no business here. +我们恨你们的武器和你们的杀戮 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We hate your weapons and your killing. +that's all. +- Then pass through... +别再回来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and never come back. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Both Yelling] +uh +-We're lost. +but helpless as well. +陛下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your Majesty. +我想要知道我父亲的消息 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I beg of you news of my father. +- 你父亲为他的王去办件小事去了 +- 求你了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Your father has gone on an errand for his king. +- Please- +发生什么了? +我担心他有极大的危险 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What's happening? +I worry that he's in grave danger. +国王的大法师有很多的责任 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The king's magus has many responsibilities. +他并不需要一个总是用绯闻 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What he does not need is a daughter... +来惹麻烦的女儿 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}who's troubling herself with the affairs of men. +我父亲觉得把我锁在城堡里 能减轻我的担忧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My father thinks that keeping me locked in this castle will ease my mind. +他错了,我感受到宫廷里的气氛 从来都没有这么困扰过 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He's wrong. +I know the mood of this court. +It's never been more troubled. +黑暗威胁着 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Darkness threatens... +我们的国家 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}our empire. +从魔法中生出的黑暗 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Darkness that's spawned by magic. +走! +快 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Come on! +Hey. +你父亲在寻求原因... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your father seeks reason... +- 和解决方法 +- 陛下? +陛下? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- and remedy. +- Your Majesty? +Your Majesty? +- 你的父亲... +- 陛下! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Your father +- +- Your Majesty! +盖伦! +我觉得我要死了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Gallian! +I feel like I'm dying. +你跟国王吃得好吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Did you dine well with the king? +你干了什么? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- What have you done? +- [Chuckling] +我以为你想要加速呢 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I thought you were in a hurry to accelerate things. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +我想我可能对国王的吃的做了手脚 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I suppose I may have tampered with the king's food. +你给我下毒了,你杀了我了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You've poisoned me. +You've killed me. +别这么戏剧化 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Don't be so melodramatic. +- [Groans] +没什么不能弥补的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It's nothing that can't be fixed. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groaning] +求你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Please. +求你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Please! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chuckles] +希望我们都记得谁在这里有着最大的权力 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Let us hope you remember who has the real power here. +好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Yes. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Panting] +我觉得我救了你一命 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'd say I've saved your life. +你应该为我做点什么呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Now what shall you do for me? +国王被下毒了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The king has been poisoned. +能救吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Can he be saved? +if it's not too late. +性命保证 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}On my soul. +私下谈一下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A word in private. +法罗逃出了城堡 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Fallow has fled the castle... +还带走了两个军团 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and he's taken two full legions with him. +that tells us who poisoned the king. +where we shall meet our new allies. +我们联合的力量... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The strength of our combined armies... +将使我们享有世代的和平和安宁 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}shall allow for generations of peace and tranquillity. +我能感到盖伦跟这个有关 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I detect the hand of Gallian in this. +为什么泰利斯长官没有跟我们提到过这次行动? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Why has Commander Tarish not briefed us for this mission? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +还有想要犯叛国罪的人吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Anyone else care to commit treason? +- 还剩下多少军队? +- 三分之一 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- How much of the army remains? +- A third. +嗯 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hmm. +I have seen the Krug massing. +盖伦在召集军队 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Gallian is raising armies- +- 大量的军队 +- 怎么会? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- vast armies. +- How? +一个人怎么可能会造成如此大的破坏呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How is that possible +-That a single man can cause so much devastation? +我亲生女儿背叛我,投进死敌的怀抱 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My own daughter betraying me to my sworn enemy. +你这么恨我吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Do you hate me that much? +- [Moans] +我以为我爱他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I thought that I loved him. +他混入了我们的血缘 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He has tapped into our bloodline. +你把魔法的平衡偏向了他的一方 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You have tilted the balance of magic in his favor. +the kingdom may be lost. +对不起,对不起 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm sorry. +I'm sorry. +对不起,对不起 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Weeping] I'm sorry. +I'm so sorry. +你们为什么这么恨外来人? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] Why do you hate outsiders? +你们互相敌视,我们为什么不能敌视你们呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You hate each other. +Why shouldn't we hate you too? +我们躲藏在森林里,避开你们的战争和争端 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We stay in the forest to avoid your wars and your contests... +和你们愚蠢的劳动 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and your mindless enterprise. +shooting your arrows into our trees. +伤害就是你们生活的一部分 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Harm is but a way oflife for your people. +你们最危险的地方就是你们自己 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The fact that you don't realize it is what makes you so dangerous. +我最远只能送到这里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Woman] This is as far as I will take you. +好运 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Good luck. +Grunting] +我们有计划吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] Do we have a plan? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Bastian Groans] +Groaning] +你醒了吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Are you awake? +I'm awake. +你会发现杀死一个国王没那么容易 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You'll find it's not so easy to kill a king. +我们要进攻 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We will attack. +you have been poisoned. +Commander. +我也有我的头脑 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And I have my wits. +so that's exactly what we will do. +谁给我下的毒? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Who poisoned me? +Duke Fallow. +噢 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Oh. +更坏的是 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Sighs] +- And there's worse. +他逃离了城堡 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He has abandoned the castle... +带走了第11和第12军团 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}taken the guard and the 11 th and 12th legions. +我们要进攻 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We will attack. +拂晓,集结你的军队 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}First light. +Summon your troops. +我还能活多久? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How much time do I have? +你的生命即将结束 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your life is coming to a close... +但是剩下的时间足够了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}but there is time enough. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Thunder Rumbling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Thunderclap] +Norick? +一点也不 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Not at all. +Indistinct] +- Shh! +Norick. +- 我感觉得到 +- 我觉得你是对的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- I can feel it. +- I think you're right. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +hey! +Easy. +索拉娜? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Solana? +索拉娜! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Solana! +[Grunts] +今天... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Today... +我们为国王而战 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}we ride for our king. +我们的国王骄傲地 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And our king proudly fights... +为艾柏而战 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- in the name of Ehb! +- [Cheering] +陛下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your Majesty. +起立! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Ride! +神佑为荣耀和真理献身的人! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}God blesses those who die for honor and truth! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Cheering] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +Farmer. +我能感觉到你很危险 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I sense danger in you. +我看不透你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I can't read you. +like reading scrolls of flesh. +I can't see past your scowl. +为什么? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Why is that? +你是谁? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Echoing] Who are you? +有些谜不值得去解开 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Some riddles aren't worth solving. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Panting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Moans] +你在这里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You are here. +我以为是个噩梦 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I thought it a nightmare. +法莫呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where is Farmer? +扎夫呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where is Zeph? +where is Zeph? +Is he with our parents? +对 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Yes. +but... +他没逃出来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}he didn't make it. +你被带走的那天,他就被杀了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He... +was killed with them the day you were taken. +对不起 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm sorry. +我的宝贝 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Sobbing] My baby. +他死得安逸吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Did he die quickly? +告诉我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Tell me. +对 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Yes. +他死得安逸 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He died quickly. +法莫会来的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Farmer will come. +他会找到你的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He'll find you. +你怎么知道? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Solana] How do you know? +因为他必须这样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Norick] Because he must. +因为他需要你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Because he needs you. +you're all he really needs. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groaning] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Hoofbeats] +Farmer. +你要做的事情还有很多 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Much for you to do. +are you? +啊,这个 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] Ah. +There. +来试试 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Try a bit of this. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gagging] +- 味道怎么样? +- 这是什么? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- What's it like? +- What is it? +药。 +快起来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughing] That's medicine. +Come on. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Woman Moans] +Indistinct] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Woman] No! +- [Man Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gallian Chuckling] +回家真好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It's good to be home. +我不是你的妓女 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Muriella's Voice] I am not your harlot. +他用你来毁灭... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Merick's Voice] He has used you to destroy- +我知道诗人们说... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gallian's Voice] I know that poets claim- +他以玩弄感情为乐,你还不吸取教训? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Merick] He bends emotion for sport. +Have you learned nothing? +your vision? +小姐? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My lady? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Weeping] +我是我父亲的累赘 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I am my father's undoing. +我阻碍了一切 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I've jeopardized everything. +但是你父亲很爱你啊 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}But your father has nothing but love for you. +我小女孩般的愚蠢伤害了他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My girlish stupidity has damaged him. +自杀会伤他更重的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Taking your life would damage him further. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Exhales] +可能你是对的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Perhaps you're right. +我想要我的父亲以我为荣 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I would like my father to be proud of me. +他已经是这样了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He already is. +他只是以这个想法为荣而已 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He's proud of an idea of me. +准备迎接你们的新盟军吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Fallow] Prepare to meet your new allies. +这是克鲁格人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}These are Krug. +relentless and unquestioning. +你看到的是一个强大的军队 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What you see before you is a powerful army. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +带走这个人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Merick] Take this man. +把他放在王国的营帐里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Put him in the king's tent. +保证喂饱我的马 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}See that my horse is well fed. +等等 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hold. +这是你的紧急事务? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}So was this your urgent errand? +这是法莫,石桥镇的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This is the farmer... +from Stonebridge. +对 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- It is. +- [Exhales] +为什么一身泥土味的不尽忠的 石桥镇农民 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Now why does a disloyal dirt +-lover from Stonebridge... +会让国王的大法师怎么挂念? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}command such careful attention from the king's magus? +因为国王对这个农民有特殊挂念 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Because the king has a special interest in this... +dirt +-lover. +我怎么不知道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I know nothing of this interest. +国王也不知道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Neither does the king. +我觉得现在你们应该好好认识一下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I thought it was about time that you two were properly introduced. +我们见过了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We've met. +he turned his back on me. +去做他需要做的事情 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Turned to what needed doing. +我以为陛下会对这个农民感兴趣 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I thought Your Majesty would be interested in this farmer. +从我们见过以后,他经历了许多事情 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He's been through a great deal since we met him in Stonebridge. +大家都一样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}So has everyone else. +什么让他这么特殊? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What makes him so special? +Your Majesty... +他是你儿子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}he is your son. +法莫的朋友诺瑞科 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Merick] Farmer has a friend +- Norick. +是管理王后马匹的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Norick tended the queen's horses. +上次在石桥我认出他来了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I recognized him when we were in Stonebridge. +this Norick... +在战场上找到一个3岁大的小孩 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}found a boy about three years of age wandering in the battlefield. +牛草地小道只有一个小孩 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}There was only one boy at Oxley Pass. +Farmer? +一个老人以为他认出了一个30年没见的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}One old man thinks he recognizes another from 30 years ago. +这就是你们选国王的方式? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}That's how you determine who's king? +and heir to the throne. +我没父亲 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I have no father- +没父母 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}No parents. +我与这里无关 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I have no business here. +你的意思是那个傲慢的混蛋是我的儿子? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Are you telling me that that arrogant bastard is my son? +他30年来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He spent the last 30 years... +住在石桥的农场里? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}living over a Stonebridge farm? +就是这样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It would appear so. +就是这样,你告诉我他已经死了! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It would appear so. +You told me he was dead! +你说他们全死了! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You said they were all dead! +神对我开了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What kind of joke... +什么样的玩笑啊 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}do the gods play on me? +有时候神知道什么对我们最好 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Sometimes the gods know what is best for us. +那是什么意思? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What the hell does that mean? +你记得我们那个时候混乱的状况吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You remember the chaos we were in? +Hmm? +到处是战争,到处是敌人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}War everywhere. +Surrounded by enemies. +如果这个孩子带回了艾柏城堡 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}If that child had been taken back to Castle Ehb... +他能活多久? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}how long would he have survived? +在石桥长大 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Growing up in Stonebridge... +他很健壮 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}he grew up strong... +离敌人很远 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and far away from the enemies... +敌人随时都可能 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}who would have jumped at any opportunity... +除掉你的儿子和王储 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}to rid you of your son and heir. +亲爱的朋友 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Dear friend... +你最好是对的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}you better be right about him. +你最好心里有数 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You better be sure. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chattering] +国王需要所有有能力的士兵 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The king needs every able man he can get for this battle. +- 这不是我的问题 +- 他的王国被侵略了。 +你的王国被侵略了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- That's not my problem. +- His kingdom is threatened. +Your kingdom is threatened. +我不认识这个国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I don't know this king. +索拉娜是我的亲人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Solana's my family. +诺瑞科和巴斯蒂安,他们是我的亲人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Norick and Bastian. +They are my family. +你住在哪儿呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And where will you live? +嗯? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hmm? +如果王国落入盖伦之手... +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}When the kingdom falls to Gallian... +你又能为你妻子提供什么样的未来? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}what future will you be able to offer your wife? +想想吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Think about it. +you have committed treason. +我们不讲条件 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We offer no quarter here. +任何听从你指挥的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And anyone who follows under your command... +也将被视为叛国着 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}will likewise be considered as a defector. +我们不饶恕叛国者 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We will spare no traitor. +先生们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Fallow] Gentlemen... +泰利斯将军毒害了国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Commander Tarish has poisoned the king... +还说我叛国 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and accuses me of treason. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hah! +Tarish. +艾柏之国现在由我统治 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The Kingdom of Ehb is now subject to my rule. +offer no quarters. +my nephew... +因为你没胆量 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}because you have no valor- +not ever. +Your Majesty. +你们这些懦夫 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Fallow] You coward! +but they also have no fear. +but we are men... +我们忠于一个高贵的国家 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- and we serve a noble kingdom. +- [Troops Cheer] +with bloodlust. +Nothing more. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Cheering] +have you come to do your duty? +我决定了要一战 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I've decided to fight. +有你们在我身边一起我很骄傲, 我也会留意你的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'll be proud to have you fight by my side so that I might keep an eye on you. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Clicks Tongue] +中尉 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Mid guard. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +将军 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Jingles] +- Commander. +走吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Lead out. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunt] +弓箭手 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Archers. +放! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Fire! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Groaning] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Cheering] +放! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Fire! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Rumbling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Shouts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +没事的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Horse Blusters] +- It's okay. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Blusters] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Hoofbeats Approaching] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Hyah. +- [Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +take their flank. +move out. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Snarling] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Snarls] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +它们像疯狗一样打仗 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}They fight like dogs. +sire. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Growls] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Whoa! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Screaming] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughing] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Screaming] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Horse Whinnies] +- [Screaming] +我们走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Let's go. +预备 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Ready. +放! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Fire! +放! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Fire! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Groaning] +这些克鲁格人人不用脑子打 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}These Krug fight mindlessly. +它们的脑子在这里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Their minds belong to those. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Shouts] +it means nothing. +我们赢得一世! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We will win more than a day! +你杀了这些 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You have killed these. +我就招出更多的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I will simply beckon more. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +这是我们偿还罪孽的地方吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Christwind. +Is this where we pay for our sins? +Norick. +这是我们偿还美德的地方 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This is where we pay for our virtues. +罪孽比美德在这里要吃香 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Sins are more than welcome here. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Whoa. +国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The king. +good uncle. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +放! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] Fire! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Horse Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +卫兵! +卫兵! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Grunts] +- Guards! +Guards! +快 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Quickly. +把国王抬离战场 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Get the king off the field. +快 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] Come on. +good uncle. +走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Ride. +- [Grunts] +你只是争取到了点时间而已 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chuckles] You have won nothing but time. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +我不会像他们那么活的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I won't live like them. +我们已经是他们了,我们是奴隶 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We're already like them. +We're slaves. +be still. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Exhales Deeply] +sire? +我们要从森林走近路去艾柏城堡 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We shall cut though the forest to Castle Ehb. +the castle is ours for the taking. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Whoa. +我们快离开吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Let's get out of this place. +ho. +看看,一个家里的朋友 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Lookee here. +A friend of the family. +我非常高兴 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How delightful. +独自在这个森林里你不觉得容易受伤吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Alone in the forest does not make you feel vulnerable? +Muriella? +你的举止从来都没赢得过尊敬 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your comportment has never earned trust. +举止? +礼貌? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Comportment? +Decorum? +这都是城堡的言谈 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Those are words for a castle. +我们不在城堡里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We +-We are no longer in a castle. +这里也没有规矩 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- There are no rules here. +- [Horse Whinnies] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Groaning] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gasps] No. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Both Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hyah. +[Grunts] Hyah. +Hyah. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Whoa. +hyah! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Horse Whinnies] +- [Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +给你的特别礼物 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A special gift for you. +谢谢 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Thank you. +- [Grunts] +my duke. +你喜欢打破规矩的这种天赋 最终还是没用啊 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your talent for breaking them has failed you at last. +我带这个走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- I'm taking this one with me. +- [Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +go. +Go! +我会找你的,走! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'll find you! +Go! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Krugs Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gasps] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +诺瑞科! +诺瑞科! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Norick! +Norick! +- [Sword Clangs] +这是你一直想要的吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What you always wanted- +光荣战死 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}a courageous death. +you were a brave old guy. +索拉娜 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Bastian] Solana. +巴斯蒂安? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Solana] Bastian? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Grunting] +- [Clanging] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Oh! +- Come on! +靠后 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Gasps] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Shouting] +- Stay back. +不,我没事 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- No. +I'm good. +- [Chattering] +你今天很不错 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You fought well today. +杀野兽 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Slaying beasts... +- 需要狠下心来 +- 没错 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- can be a cruel courage. +- Yes. +不管什么出现 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Whatever presents itself... +- 你都能战胜它 +- 我做苦活习惯了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- you'll do it. +- I'm used to hard work. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chuckles] +that'll come in handy... +将会更有用 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}when you're king. +你怎么看待你今天 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How do you suppose it is that you... +战斗得这么好? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}fought so well today? +was it... +运气? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}luck? +you know. +of course... +你实话实说 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}you speak your mind. +这会让你更好的为国家服务 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This will serve you well. +智慧是我们的武器 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Wisdom is our hammer. +谨慎则是我们的盔甲 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Prudence will be our nail. +当人在诚实劳动中 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}When men build... +建设生活 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}lives... +from honest toil- +勇气不灭 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Courage never fails. +你从哪儿听到的这些? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where did you hear that? +当我儿子还小的时候 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I told it to my son... +我每天晚上 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}every night... +都对他这么说 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}when he was a little boy. +别人都不知道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And no one else. +现在开始你生活会变得更加艰苦 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Things are gonna be a lot harder for you from now on. +yes. +there's that little village... +有个小村子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}not too far from here. +他们一年收两季稻子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}They raise two crops a year. +- 那会破坏土壤的 +- 不 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- That would kill the soil. +- No. +这样不会破坏土壤因为有海草 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It does not kill the soil because of the seaweed. +the seaweed comes in from the ocean... +给土增肥 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and enriches the soil. +你该试试 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You should try that. +你怎么知道这些 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How do you know these things? +因为我是国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Because I am king. +因为我应该知道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Because I'm expected to know... +关于土地的一切 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}about the land. +就像你将来也会那样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Just as you will be. +只要有国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}As long as there are kings... +只要有土地 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}as long as there is land... +他们就会发动战争抢夺 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}they will fight over it. +抢夺荒芜的田地 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Battles fought for barren lands. +如果战争不结束那会是什么? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What are these wars if they never end? +他们为和平而战 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And they fought for peace. +和平,梦想而已 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Peace +- that's a dream. +但是你如果当国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A dream that maybe you... +可能 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}as king... +就能实现 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}can bring peace forever. +你不懂 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You don't understand. +战争夺取了我的儿子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}These battles have robbed me of my child. +你忘了他们夺去了我的儿子了么 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You forget they robbed me of mine. +我的儿子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My son. +海力特将军 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Chattering] +- [Tarish] General Hallette. +sir. +带队侦察队去这片树林的北边 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Take a scout to the north side of the woods. +sir. +- 将军? +- 是 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Commander. +- Aye? +看 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Look. +now this... +是个令人惊奇的收获 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}is a surprising delivery. +法罗公爵来受到裁决了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Duke Fallow's here to meet justice. +我猜国王还活着 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I assume the king lives. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Whimpers] +贝克勒将军 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}General Backler... +把你的剑给他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}give this man your sword. +不要护甲 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}No armor. +决斗 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A duel. +可爱 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How lovely. +Tarish? +我能喝口酒吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Can I at least have a lick of wine? +没人会帮国王解下护甲吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Will no man help his king with his armor? +禽兽 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Pigs. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +Growls] +Fallow. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +我杀了你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Tarish] I should kill you. +我要杀了你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I should kill you. +国王死了! +国王死了! +康里得国王死了! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] The king is dead! +The king is dead! +King Konreid has died! +this cannot be. +我是你的国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I am your king. +you are a curse to the throne! +- Commander Tarish... +非常忠诚 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}is bound by honor. +他永远不会杀了艾柏的新国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He'll never kill the new king of Ehb. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughing] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Sighs] +懦夫 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Coward. +艾柏的子民们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}My subjects of Ehb! +国王万岁 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Long live the king! +huzzah! +huzzah. +收起来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Put it away. +艾柏的子民们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Merick] Citizens of Ehb. +艾柏的勇士们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Soldiers of Ehb. +片刻前 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A few moments ago... +我们敬爱的王康里得去世了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}our beloved King Konreid passed away. +被他的侄子谋杀了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Man] No! +- Murdered by his nephew... +他想篡权 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}who sought to take his place. +根据这国家的法律 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}By the laws of our land... +国王的继承人必须有血缘关系 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}the king's successor must be related to him by blood. +我给你们介绍我们的新国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I give you your new king... +康里得失散的儿子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}the lost son of Konreid... +卡姆登 康里得 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Camden Konreid... +有人也叫他法莫 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}known to some of you as Farmer. +起来吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Stand. +please. +Stand up. +国王召唤你们来冒死而战 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The king called upon you to face death. +现在还活着的人已经从死亡 那里得到了奖赏 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Those still standing have cheated death of its prize. +但是我们的敌人还活着 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}But our enemy still lives. +他会重建军队,重新攻击 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He'll rebuild his forces and launch a renewed assault. +今晚我们疗伤 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Tonight we dress our wounds... +葬死 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}bury our dead. +明天我们袭击克里斯英得要塞 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Tomorrow we march on Christwind hold. +- 直捣恶魔的老窝 +- 直捣恶魔的老窝! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Gouge evil from its shell. +- [Man] Gouge evil from its shell! +天佑吾王! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}God save the king! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Cheering] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +什么? +你要什么? +带他们走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What? +What do you want? +Take them away! +带他们一起走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Take them with the others! +等等 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Wait. +把她带来 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Bring her over here. +退下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Begone. +我在你身上 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I sense him... +感受到他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}in you. +那个农民 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}The farmer. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Laughs] +他会来找你的,太好了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He'll come for you. +This is perfect. +- 我会等他的 +- 我对你没价值 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- And I will be expecting him. +- I'm nothing to you. +but he is something to me. +不仅仅只是一个农民 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}More than a farmer. +比一个农民更加危险 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Much more dangerous to me than a farmer. +现在他会来找我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Now he'll come to me. +你怎么认识我? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How do you know me? +怎样? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How? +别动 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Whispers] Don't move. +别动 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Don't move. +我在你身上 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I feel him... +感受到他了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}in you. +因为你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Because you're carrying... +怀了他的儿子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}his son. +你怀了他的儿子 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You're carrying his son. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Gasps] +- [Chuckles] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunting] +你从哪儿来? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where you from? +格拉森。 +他们从我家里把我带走了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Gloucern. +They took me from my home. +我们会送你回去的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We'll get you back home. +我们会死在这里的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We'll die here. +old friend. +你怎么与那么大的军队对抗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Farmer] How do you fight an army that large? +the dagger may succeed. +magus. +一小组人会溜过克鲁格人的防守线 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A small force might slip through the Krug lines... +然后在根源解决问题 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and solve the problem at its source. +带我到这个盖伦那里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Get me to this Gallian... +我就能杀了他 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and I'll kill him. +with respect... +但是我们在王国危急之时去救一个女人? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}are we making plans to save one woman when there is an entire kingdom at risk? +he must kill Gallian. +the kingdom is saved. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chattering] +玛丽安娜 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Muriella. +就是现在 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Now is the time. +陛下 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Your Majesty. +我想加入你 我想要尽我的义务 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I wish to join your mission. +I wish to be of service. +you've made your point. +Now go back to the castle. +我是我父亲的女儿 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I am my father's daughter... +我会尽忠国王,就像他一样 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}and I will serve the king just as he does. +你带来了谋杀国王的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You brought the king's murderer. +他落入了我手 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He fell into my hands. +magus. +我接受你了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I accept your offer. +- 还有其他人也想帮忙 +- 什么其他人? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- There are others who wish to help. +- Which others? +我带你去 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Muriella] Let me show you. +- 你还活着啊 +- 我一直远离这里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- You've managed to stay alive. +- I've stayed away. +those who control the Krug- +我们帮你战斗 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}we will help you fight them. +以为你们不参与人类的纷争呢 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Thought you didn't involve yourself in the conflicts of men. +这战争完不了,我们看出来了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This war isn't going away. +We can see that. +当我们的森林被侵略被烧毁时 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And when our forest is burned and invaded... +我们也没其他选择 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}we have no other choice. +and then we wish to be left alone. +克里斯英得 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Christwind. +- 当作是法师的避难所而建 +- 很坚固吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Built as a secure haven for magi. +- How secure? +the doors open from within. +你能进去吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You can get in? +- 一个法师无需门就能进去 +- 我会找条路的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- A magus does not need doorways to enter Christwind. +- I'll find a way. +你觉得你还活着很幸运吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Do you consider yourself lucky to be alive? +对 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I do. +生活 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Life... +从来没这么刺激过 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}has never been so exciting. +跟我一起来的人 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Those people who came with me- +为什么不放了他们? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Why not free them? +你不想让整个世界都知道你有 无穷的力量和慈悲吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You do not want the world to know that you have ultimate power and mercy? +你理解不了吗? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Do you understand nothing? +我超越了慈悲 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm beyond mercy. +我超越了好和坏 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm beyond good and bad. +这些是孩子气的思想而已 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}These are childish ideas. +我在改变世界的结构 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I'm changing the structures of the world. +如果我给你的朋友发了慈悲, 我会怎么样? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Where would I stop if I showed your friends mercy? +- 那可以... +- 没有例外! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- It could +- +- No exemptions! +没有例外。 +你不是。 +那农民也不是 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}No one. +Not you. +Not the farmer. +你那个尖叫着被我撕开的孩子也不是 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Not your poor screaming boy whose insides I tore out. +杀了我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Kill me! +杀了我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Kill me! +我不会杀了你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I won't kill you. +我很喜欢你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I enjoy you. +you can die. +可能吧,但是我不会 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Perhaps I can. +[Whispers] But I won't. +我还有很多事情要做 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I have too much work to do. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Thunderclaps] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Men Murmuring] +Indistinct] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Thunder Rumbles] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +弓箭手准备 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Archers ready. +放! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Fire! +就是现在! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Now! +上面有个山洞 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}There is a cave up there. +是用来通风的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}It allows the air to enter. +我得走了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}And now I must leave you. +我不想你一个人走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I don't want you to go alone. +then I must try to reach it. +Merick. +但是我最少可以分散他注意 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}But I should at least be able to distract him. +我知道你会来的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I knew you'd come. +老朋友 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Old friend. +我们曾经是朋友 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We were friends once. +但是你变了很多 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}But you have greatly changed. +噢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Oh? +一个大法师的力量 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}A magus's power is contingent... +是和他为国王做的服务紧密相联的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}on his service to a king. +你做为国王的敌人,你的力量成长的怎么样了? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How is it that you thrive as the king's adversary? +你觉得我的克鲁格人怎么样? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How do you like my Krug? +可憎的野兽而已 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- They are a cruel abomination. +- [Laughs] +克鲁格人很好笑 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Funny thing about Krug. +他们没有国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}They have no king. +old friend. +- 我不敢猜 +- 我封自己为国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- I dare not guess. +- I've made myselfking. +克鲁格人之王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}King of the Krug. +现在我辅佐着一个我万分敬仰的国王 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Now I serve a king who deserves my utmost devotion. +- 我自己 +- 够了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Me. +- Enough! +you and I are the last of the magi. +recognize that you have fallen into madness. +你根本不知道 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You have no idea... +疯癫 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}how powerful... +可以有多么强大 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}madness can be. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans Softly] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chuckles] +there will be no word for madness. +我们就简称为 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}We shall simply call it... +力量 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- power. +- [Groaning] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Men Shouting] +冲! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Charge! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +嗯,他来了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Hmm. +He's here. +他到了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}He's arrived. +我找不到理由继续打这场战争了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I see no reason to prolong this battle. +玛丽安娜 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groaning Softly] Muriella. +玛丽安娜 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Muriella. +你在这里 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You're here. +我不知道发生什么了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I don't know how it happened. +我怎么这么愚蠢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How could I have been so stupid? +原谅我 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Forgive me... +大法师 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}magus. +接受我最后的力量吧 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Take the last of my power. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Krug Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man Whimpers] +- 杀了他们 +- 帮帮我们 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Man] Kill them! +- [Man #2] Somebody help us. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Shouting] +- [Grunts] +小心后面! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Man] Look out behind you! +走! +跑! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Run! +Go! +快走,我们走 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Move it. +Let's go. +Go! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groaning] +Farmer. +这边 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}This way. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Chattering] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Thunderclap] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Men Shouting] +法莫! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Solana] Farmer. +Oh! +Farmer. +我知道你当上国王了 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I understand you've become king. +can we? +国王一对一的战斗 笑饮死敌之血 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}How often do two kings get to do battle one +-on +-one... +这样的事情多久才会发生一次呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}getting to taste the blood of one's true enemy? +你想打,还是想说死我? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}Are you gonna fight... +or talk me to death? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- [Chuckles] +- [Grunts] +想用魔法跟我打? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}You wanna fight me with magic? +你的荣耀心呢? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- Where's your honor? +- [Laughs] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Shouts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Grunts] +我会复仇的 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I will have my vengeance. +Shouting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Shouting] +不! +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}No! +Farmer? +the vengeance of a husband... +还是一个国王的? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}or the vengeance of a king? +你忘了一个母亲的复仇 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- You forget the vengeance of a mother. +- [Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Shouts] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Blood Trickles] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Groans] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Sighs] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[Coughing] +Grunting] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}[All Snorting] +发生什么了? +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}What's happening? +我一直想告诉你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}There's something I've always wanted to tell you. +我爱你 {\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}I love you. +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}##[Folk Rock] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Would you believe in a night like this # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#A night like this # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# When visions come true # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Would you believe in a tale like this # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#A lay ofbliss # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Praising the old lore # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Come to the blazing fire and see me in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#See me in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Songs I will sing of runes and rings # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Just hand me my harp this night turns into myth # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Nothing seems real You soon will feel # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# The world we live in is another skald's # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Dream in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Dream in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Do you believe there is sense in it # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Is it truth or myth # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# They're one in my rhymes # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Nobody knows the meaning behind # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# The weaver's line # +nobody else but the Norns can # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#See through the blazing fires of time and # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#All things will proceed as the child of the hallowed # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Will speak to you now # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#See me in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#See me in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Songs I will sing of tribes and kings # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# The carrion bird and the hall of the slain # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Nothing seems real You soon will feel # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# The world we live in is another skald's # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Dream in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Dream in the shadows # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Do not fear for my reason # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# There's nothing to hide # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#How bitter your treason How bitter the lie # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Remember the runes and remember the light # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#All I ever want is to be at your side # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# We'll gladden the raven # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Now I will run through the blazing fires # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# That's my choice # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# 'Cause things shall proceed as foreseen ## +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}##[Vocalizing] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}##[Ends] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}##[Pop Ballad] +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Pale +-face the innocent # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Will drown in blood # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Hurt and withdrawn # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Don't ever steal my grief # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#In this haze of green and gold # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#He's gone # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Blind my eyes and I still can see # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Through the mist to the very end # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# There I'll face what I fear the most # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Blind my eyes But it all doesn't matter right now # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#I will bury my dead # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#And keep on till the end # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#I won't give up # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#I won't give up # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#I'll turn to the red fields of none # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# There's a grave # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# There's a rose # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000} +- #Drift away # +- #I can hear me say # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Soon you all shall be free # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Carry the blessed home # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#No one's left here but me # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#And I will sing out your name # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Call me insane I know # +son # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#So pale turns the innocent # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#And all I feel # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Is pain # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Suddenly I understand # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#He's gone # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Blind my eyes and I still can see # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# Through the mist to the very end # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}# There I'll face what I fear the most # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#Blind my eyes But it all doesn't matter right now # +{\cHFFFFFF}{\3cH2F2F2F}{\4cH000000}#But it all doesn't matter right now # +伙计 你一定得听一下这个 +肉棒鼓 +嗯? +你想来点什么吗 +你有什么? +爆米花? +-嗯 +-好吧 给我来一碗 +上面撒一点... +凯普麦片 +伙计 怎么回事? +老兄 我又熬了一整夜 +我的血糖现在简直是... +露西尔小姐 你今天看上去真可爱 +那个手势是给我的吗? +嘿 嘿 拜托 还没加牛奶呢 等等 +尼尔 +嗨 伙计 老兄 +我没找到勺子 +给你 威利 +太好了 +-伙计 这太恶心了 +-嗨 +尼尔 +布鲁斯 +jets(一种燕麦圈)和wackies(一种燕麦圈) 有兴趣么 +jets 肯定不要 +wackies 肯定要 +香蕉味的燕麦片 +只有他们才生产这个 +九元四分 +好吧 九元整 +但是别忘了你还欠我$26.12的donkey kong(一种燕麦圈)玉米片 +-还有那个蜂巢门铃? +-当然 +-你听说过易趣上的cheerio么(一种燕麦圈) +-没有 +他们盒子里的一些cheerio都快有炸面圈大了 +图片有点模糊 很难说清是不是像真的cheerio那样爽口 +可能还是几块小的融成了一块 +也许是个双芯片相机拍摄的 +管它呢 +我竞标了 所以... +希望好运 +好吧 随时告诉我进展 +最初 它叫cheery燕麦 但是后来改名了 +通用面粉公司 1945 +现在我知道了 你想来点什么 +嗨 汤姆先生 +-又是一顶新帽子啊? +-澳大利亚牛仔帽 +我刚拿到的 +我不得不让我的擦鞋佬帮我加了个帽系 +是顶不错的帽子 +大家都说不错 +当然了 +谢谢 +好了 决定了么? +我要那个 +代言凯洛格公司(麦片公司)产品 +时间最长的的家伙 +太帅了 +我以为你不知道 +我也很惊讶我居然知道 +你有带狂欢节珠子的东西么? +你知道 紫色的 金色的 +当然 那种是挺不错的 可都是街上的人 +在胡说八道的 +我推荐包角质层的幼鳄脑袋 +那些游客干嘛要来这呢? +他们难道不知道佛罗里达才是他们的旅游圣地吗? +我应该回去扎染点东西了 +至少那些玩意还能卖出去一些 +尽管装饰的有点吓人 +-你好么 +-不错 +很好 那么 +这是个... +麦片吧? +还是... +-是的 +-很酷 很酷的主意 +太酷了 太酷了 +最畅销的是哪种? +这里 是所有的可可制品 +我们这有好多上瘾的人 +我想 全国范围内 应该是玉米片 +正确 玉米片 +最早的也是至今最畅销的 +玉米片不是最早的 伙计 +-最早大规模生产的 +-哦 +好吧 对了 大规模生产 +你知道我就是这个意思 +那么 最早的是什么 麦片吗? +不是 +麦片生产于1924年 +最早的麦片是凯洛格兄弟 +捣碎一捆小麦 +做成麦片一样的东西 +可以被分成更小的小片的 +那时起麦片就是一种健康食品了 +因为它的创造者是巴特尔克里克市的 +那些狂热宗教性健康迷(凯洛格兄弟来自巴特尔克里克市) +基督教科学派那个小妞的信徒 +玛丽·贝克·艾迪 +是啊 这不像一种幻觉么 伙计? +麦片是一种宗教 +感觉我们现在像在教堂里一样 +C. +w. +波斯特(早期麦片制造商)不是健康迷 也没什么高见 +他是个失败的投资家和蛇油贩卖商 +他是个傻瓜 +他在凯洛格兄弟对面建了一家工厂 +他们竟在大街上为了燕麦聚众闹事 +事实上你说的那次骚乱是因为垒球赛 +好吧 这地方太棒了 +不管你是哪一类人 +-人人都爱燕麦片 是吧 +-是啊 +八种基本维生素和均衡早餐的所有成分 +斯图尔特·泽里格 +尼尔·唐恩斯 +尼尔 幸会 +你想来点什么? +我不知道 那是什么? +-对 +-那是quake(一种燕麦圈) +在销售上曾经跟quisp's(一种燕麦圈)势均力敌 +-quisp's... +-它停产了 +-不再生产了 +-那你是从哪里搞来的? +那么... +你是店主了? +不 我是经理 +店主是那边穿睡衣的家伙 +哦 你好 +你... +他有没有考虑过特许经营? +怎么了? +听着 特许经营非常简单 +对特许经营人来说风险极低 +你们已经攻下了最难关 +现在你们只要再找到另外差不多50人 +来做你们已经学会的事 +然后你们就可以获得规模效益 +然后你们就可以赚大钱 +听上去不错 伙计 +我们可以把它们放在 +商场和加油站销售 +把小块麦片说成"超大型" +然后再给麦片起些拉丁名字 +我们可以成为产业巨人 +这就是没人喜欢我们的原因 伙计 +因为美国不管什么都要特许经营 +标准化 "麦片化" +直到它们变得一模一样 +我们是资本家 我们就是这样获利的 +我是说 你正在实践资本主义 +就是这样... +不用找了 看到了么... +这就是我想说的 +有人会因为这个好主意获益的 +你为什么不能成为那个人呢? +因为那样会让他窒息而死的 +你可以创造 也可以积蓄 +但你不可能一边照看你的灵魂 +一边照看一大堆钱 +你可以开一千家店 赚上十亿美元 +但你知道最终你会变成什么? +一个商人 +是啊 那有什么错呢? +看 我... +我完全晕掉了 +第四种魔力是什么? +心灵 月亮 星星... +还有... +车轴... +车轴草 +车轴草! +对! +绿叶车轴草! +谢谢 +他们加入了新东西 +把我完全弄糊涂了 +有点复杂了 +好吧 我很抱歉 +我想你可以继续做... +你现在做的... +直到你变成... +那样 +等等 +这还真... +-请让一下 +-慢用 +我要你现在下班 +-威利 +-怎么? +我下班了 +好的 +-你想做什么 ? +-握住你的手 +没问题 +谢谢你们的掌声 谢谢你们 +本来以为我们的CD永远出不来了 +结果它终于完成了 +你们想要的话 +到后门告诉杰伊一声 +谢谢 晚安 +尼尔! +尼尔! +你搞什么? +那些家伙开始做CD的时间比我晚的多 +你知道 我只是... +我不能... +我不能急于求成粗制滥造 你明白? +我是说 如果我的东西不够好 +如果它不够火爆 你知道 +那我只会成为另一个 +用笔记本电脑和麦克风 +制作CD的蠢材 你明白么 +那简直像vh1电台一样 让我浑身不舒服 +或许要变得火爆仅靠业余时间是不够的 +你要做的是 +到麦片店请一个周假把它做完 +我不能请一个周的假 那是我的工作 +你知道 那是我的饭碗 +你为什么不靠你攒下的钱生活呢 +不 那是用来出版发行和买盒子的 +如果我没那笔钱 就根本无法发行 +不可以 +我今天辞职了 +-你什么 +-我没告诉过你么 +没有! +你不摆摊了? +哦 好吧 很好 +怎么 你打算重新回到 +- +- +- +- +-====翻译===== +- +- +- +-- 鬼娃娃 Hanabi 黄小占 月舞 祁霖 校对: +亚力商大 总监制: +火精灵 +迪凯特大街上 +跟那些流浪汉们一起生活么 +不 我有个主意 给我在麦片饼干店找份工作 +什么? +那样你就可以有时间做完你的CD +我也能多赚点钱直到想好下一步的方向 +这主意棒极了 +不 一点也不棒 这是个烂主意 +你不能在麦片饼干店工作 完全不可能 +那样的话会不断发生利益冲突的 +-为什么? +-我怎么能指挥得了你? +我们怎么跟人解释说你不会因为 +跟我上过床而得到特别待遇? +好吧 如果这也是个问题 还真是搞笑 +这不是关键 好吧? +关键是... +关键是地狱之路已经开始 +对么 一小步已经踏出去了 +因为你有了该死的现金问题 +我不会让你那么做的 我不会让你出卖肉体 +出卖肉体? +上帝 尼尔 拜托 +事实上 这个主意倒也不错 +也许我是该去卖卖淫 那倒很有趣 +-那你一定得让我看看 +-我会让你看的 +-你知道我是对的 +-哦 对 你是对的 +当你70岁了 终于完成你的CD的时候 +你可以过来到纸板箱里看看我 +我会完成我的CD的 好么 +你也不会住在纸板箱里 +因为你还没听到我的好主意 +跟我住到一起 +跟你住到一起? +你疯了么? +你不能因为同情而同居 尼尔 +不是因为同情 我是想要你开心 +这会让我开心么 跟你住到一起? +-那会让我高兴的 +-那好吧 +等等 +当你说"那好吧" 那是指 +"那好吧 别再吵了" +还是"那好吧 我搬来和你住 你个笨蛋"? +你认为呢? +看箱子里 +我为我们的同居做了件礼物 +这些是你画的? +真不可思议 +那儿 +就像淘气的天主教徒同居一样 +几乎是了 +那是干嘛? +这个 +为什么 唐恩斯先生 那会让我一丝不挂的 +好主意 凯茨小姐 +流线型的靓车 +但它的颜色一定要闪亮 +不要暗灰的 要闪亮的 +然后我们要把它和... +和一辆 +巨大的老式厄尔拉多敞篷车连在一起 +我们要戴上 +配有无线电话的头盔 +-打开开迪车的喇叭 +-那是必需的 +我们要把车停在good sam露营地 +和沃尔玛停车场 +我们要用大量 +的摇滚乐 +使老人们一直清醒 +因为我们要用我们的打折卡 +买很多专辑 +让开迪的行李箱里只有CD和超强低音器 +没有人会怀疑 +那过时的流线型跑车里头的两个老人 +就是摇滚风潮的领引者 +著名的尼尔·唐恩斯先生 +和催眠者 +艺术界的传奇 普西·凯茨小姐 +同父异母的乱伦双胞胎 +关于吃的还能有什么新鲜的? +我不知道 也许是新吃法 +放进你的屁眼然后用后边消化 +那吃苹果会很困难的 +-那羊肉串呢? +-天哪! +喝汤会花很久 +是的 喝汤会花很久 +-吃羊肉串会很好玩的 +-是的 +伙计 你在干嘛? +做个棒子 +今晚和跳舞高手去参加个爵士乐演凑会 +-我必须会点 +-跳舞高手? +你怎么演奏那个铜管乐队的曲子? +-我弹全部 +-各位 +注意咯 +我有个好消息 +该死的 +一盒燕麦饼干? +在这? +不 不 不 这不是燕麦饼干 +这是在周六早上看老鼠 +在浴盆外吃冻鞭子 +那是什么... +那叮当声是什么? +-对极了! +-我要了 多少钱? +-30 +-成交 +30美元买一盒老的燕麦片? +得了吧 +可是会有人花三万买这个盒子里的东西的 +是的 一些傻瓜 +为了盒子里的童年? +谁的童年? +那些东西生产出来的时候你还没出生吧? +把这些算在你的账上? +地下天鹅绒乐队成名时我也还没出生呢 +但我肯定知道他们是谁 +拆开他们吧 +不 那是藏着非常时刻用的 +你好 +还记得我吗? +你称我为草莓 +我记得 你好 +你... +你把这个借给了我 +你觉得怎么样? +我的天哪 太让我吃惊了 +很变态 很不可思议 对吧? +他真是个天才 +我喜欢为我认识的人做mp3 +你做mp3? +你剽窃了吉尔·斯科特海伦? +我只是想... +我知道你在想什么 我是这么想的 +出去买上20张他的专辑 +然后他的孩子就有钱了 +你难道不认为一个70年代的黑人歌手 +还没有被他的商标骗够吗? +因为作为音乐人 +我们要考虑那种事 +因为将来某一天 +或者我们中的某些人 在不久的将来 +我们可能会靠版税生存 +事实上 对于尼尔 +这个日子已经不远了 +因为他会在一周内完成他的CD +从今天开始的一周内 这会引起轰动的 +不 一礼拜? +怎么可能... +那谁来打鼓 老兄? +-老兄 你为什么不... +-好吧 +在我告诉威利之前你要保密 +但我想我要请一礼拜假 +街对面是怎么回事 让我大吃一惊 +那不是个新概念 +见鬼 那不是一个新概念 +那是剽窃 +是谁竟敢... +-不可能 +-怎么了? +不可能 +是那个香蕉共和党人 +那个问我问题的男人 +原来一直我身上了解市场行情 +可能他早就租了那幢楼 +不是燕麦饼干 像是专利剽窃什么的? +威利会起诉那个混蛋的 +那混蛋是不值得我们去麻烦律师的 +跟我来 +走吧 我们必须去 +欢迎光临新原创麦片店 我能帮什么忙吗? +你当然能啦 斯图尔特 +我的朋友和我想吃点燕麦饼干 +可能想来点以前的 +你这有fruit brute(一种燕麦圈)吗? +是一种停产的怪物麦片 +我这有boo berry(一种燕麦圈) +你现在有了哈? +黛西(狗的名字)也有 +我这还有一盒... +yummy mummy(一种燕麦圈) +不 谢了 +Yummy mummy是怪物麦片里不太有名的 +我想我更想要 +一碗alpen(一种燕麦圈) +-那是牛奶什锦早餐 来自... +-加拿大 +瑞士口味 +你要大份 中份 还是小份? +特大份 +告诉你吧 +看在咱们是邻居的份上 第一碗我请客 +牛奶也一块请了吗? +他是个白痴! +没有牛奶 老兄 蓝色的牛奶和塑料汤匙? +看上去很好 虽说 但弄的很干净 +你不用担心 他够不成威胁 +他只有吃西北风的份 +不 他会吸纳游客的 +但他们不给小费 他们不会碰燕麦饼干的 +又不是我们的人 没门 +他们确实有yummy mummy那样的东西 +他们有c. +w. +波斯特(早期麦片制造商) +-就像巴特尔克里克一样 +-别大惊小怪的 威利 +别害怕 听我说 +这个男人会在几天之内破产的 +凯洛格兄弟就是被波斯特给搞垮的 +凯洛格弟弟接手过来 +然后全部售光 +害惨了凯洛格哥哥 +他们从不妥协! +-乌托邦? +没了! +-我们不是凯洛格兄弟 +-暴乱! +-我们不是凯洛格兄弟 好不? +这家伙是个饭桶 他有什么? +无非就是一些漂亮餐具和桌椅 +谁玩谁啊 他就是个小丑 +别这样 谁 +谁是这的老大? +得了吧 +谁是早餐界的冠军? +我要... +我要听你这么说 +威利 过来 过来 +我给你做份混合冷饮 +为什么不呢? +就一个礼拜 +因为那个冒牌骗人的 +原创燕麦饼干店 +让威利很抓狂 +我不能不管他 +我想那样做自私了点 +管好自己的事并不是自私 +我会给他说的 好吧? +只是刚好这礼拜不太合适 +那就让这礼拜合适啊 +雇佣我 +如果你不在那 +就没有利益冲突了 +你甚至不用付我薪水 +我只需要在你工作的时候 +照顾好那个老人 +你知道的 你的真正的工作 +我很肯定我能搞定怎么做麦片生意的 +你难道没听到我说的吗? +我听到了 +你只是很担心 +担心会搞砸 +担心是否会成功 +我知道担心的感受 +我一直都很担心 +而现在 我担心 +你是个做些音乐的燕麦饼干小子 +而不是在麦片店兼职的音乐人 +燕麦饼干小子? +多谢你那么说 宝贝 +多谢你的爱和支持 +这就是爱 +帽子不错 汤姆 夏洛克·福尔摩斯 diff --git a/bench/data/opensubtitles/zh-medium.txt b/bench/data/opensubtitles/zh-medium.txt new file mode 100644 index 0000000..a818ab2 --- /dev/null +++ b/bench/data/opensubtitles/zh-medium.txt @@ -0,0 +1,1465 @@ +魯哇克香貓咖啡 世界上最稀有的飲品 Kopi luwak. +the rarest beverage in the world. +嘗一小口 Take a whiff. +來 Go ahead. +寇爾先生 董事會已準備好聽你的提案 Uh, mr. +cole, the board is ready to hear your proposal. +等一下下 Hold on just a second. +來 繼續 Go ahead. +go on. +怎樣 Well? +真不錯 Really good. +真不錯 Really good. +寇爾先生? +Mr. +cole. +sir? +吉姆 你知道庸俗是什麼嗎 Do you know what a philistine is, jim? +先生 我叫理查德 Sir, it's richard. +沒錯 費爾 出動你的如簧巧舌吧 That's right, phil. +give them the spiel. +謝謝 主席先生 主管們 Thank you, mr. +chairman, fellow supervisors. +我們寇爾集團財務的管理不善 We at the cole group feel the decline of the winwood hospital... +直接造成了溫伍德醫院的衰敗 ...is a direct result of significant fiscal mismanagement. +請原諒 我們醫院... +I beg your pardon, this hospital... +日常開支近2倍 overhead costs are nearly double. +你們的租金和置業費用高得不可置信 Your lease and land costs were similarly overbid. +在科研分析 兒科 腫瘤學和核磁共振等領域的貢獻 Donations have atrophied to the point you've fallen far behind +萎縮到了有史以來曲線的最低點 the curve in research, pediatrics, oncology and mri. +7年來 寇爾集團私有化了15家公立醫院 The cole group has privatized 15 public hospitals in seven years... +每一家目前都為社區提供 或即將提供 ...each of which now provides, or will soon provide... +最高標準的醫療服務 ...the highest standard of medical care to their communities. +人手問題就不管了嗎 despite being grossly understaffed? +越好的醫生 越需要... +the better the doctor, the need... +床位怎麼辦 外面在傳你們收太多病人 What about beds? +there are rumors you increased the number +擠都擠不下了 of patients to the point of overpopulation. +病人的密度一直是... +Patient density has always been... +還有急診室 這可是眾所周知的... +And your emergency rooms, I mean, they are known... +我開的是醫院 不是健康療養所 I run hospitals, not health spas. +一個房間兩張床 無一例外 Two beds to a room, no exceptions. +聽著 我和米雪爾. +費弗約好了來這兒吃午飯 Look, I passed up a lunch with michelle pfeiffer to be here... +我們能否盡早停止惺惺作態 ...so can we desist from all of this inane posturing? +男孩女孩們 你們需要我 Boys and girls, you need me. +而我卻不需要你們 I do not need you. +這信封裡有一張大額支票 Now, there's a sizeable check in this envelope... +如果決定了就請隨便使用吧 ...let me know if you decide to cash it. +寇爾先生 你沒事吧 Mr. +cole, are you all right? +你在這兒幹嘛 What are you doing here? +為生命而戰鬥啊 你呢 Oh, you know, fighting for my life. +you? +我只是有點驚奇... +Uh, no, I was just surprised... +我並不在乎保險 and I don't care about the insurance! +去告訴那個腦子糊了屎的醫生 必須告訴我 And tell dr. +shit +-for +-brains i wanna know everything +為什麼一定要我打這一針光黴素 about this bleomycin drip he wants to get me on. +我聽說它會吞噬你的肺 I hear it eats your lungs. +等我下個月去國會座談時 When I address congress next month... +我不想通過喉嚨裡的洞來呼吸 ...i don't want to do it breathing through a hole in my throat. +-其實並不完全是這樣 +-這傢伙是誰 +- that's not exactly what happens. +- who the hell is this guy? +-湯馬斯在哪兒 湯姆 +-我在這兒呢 先生 +- where's thomas? +tom! +- in plain view, sir. +-你好 湯姆 +-我們要把你挪上床 +- hi, tom. +- we're gonna move you into the bed. +我能自己來 我還沒死呢 I can do it myself. +I ain't dead yet. +現在怎樣 How about now? +我最近炒你魷魚了嗎 Have I fired you lately? +自從奧普拉事件以來還沒有 Not since the oprah incident. +-他是個好人 +-對 好員工 +- that was a good one. +ha +-ha +-ha. +- yeah, it's good stuff. +那他媽是誰 Who the hell is that? +你他媽又是誰 Who the hell are you? +他說 "你他媽... +?" He said, "who the hell... +?" +天哪 我在哪兒 這是停屍房嗎 Oh, god. +what am i, in the morgue? +那是我第一次將目光停留在愛德華. +寇爾身上 That was the first time I laid eyes on edward cole. +一個不祥的開始 一定是這樣 An inauspicious beginning, to be sure. +放過我吧 親愛的上帝 Oh, spare me. +sweet jesus. +我討厭這些... +我討厭針管 I hate these... +I hate tubes! +要是接下來3個星期裡 I'll be damned if I'm gonna spend the next three weeks +我都挨著這個傢伙一起睡的話 我一定會死的 laying next to this guy. +怪人一個 像個半死人 Zombie boy. +looks half +-dead already. +你不能住單間 You can't have your own room. +不然會造成巨大的公關問題 It would create an enormous pr problem. +我沒有定過這樣的鬼規矩 I don't give a shit about pr. +我要住單間 這是我的醫院 沒天理啊 I want my own room. +it's my hospital, for chrissake. +別告訴我不能住單間 Don't tell me I can't have my own room. +無意冒犯 保爾 No offense, pal. +這政策你已公開辯護過無數次 You have publicly defended this policy countless times. +你開的是醫院 不是健康療養所 You run hospitals, not health spas. +一個房間兩張床 無一例外 two beds to a room, no exceptions. +我從前沒有生過病 I've never been sick before. +好吧 艾爾德瑞吉醫生馬上就要來給您打麻醉 Okay, dr. +eldridge will be in in a minute to dot you up, okay? +打麻醉 Dot me up. +上帝 Jesus. +湯馬斯 Thomas +麻醉時別讓我清醒著 don't let me wake up paralyzed. +我會竭我所能 I'll do what I can. +這真的是你的醫院嗎 This really your hospital? +是的 沒錯 Yeah, pretty much. +難喝的豌豆湯需要改進一下 Might wanna do something about the pea soup. +在早上的手術時發現 By the morning of the surgery, +癌癥已經擴散到愛德華的全身 the cancer had spread so far throughout edward's body +醫生們估計他只有5%的希望能活下來 that the doctors gave him only a 5 percent chance to survive +但他們卻未曾估計到他對他們有多生氣 But then, they didn't account for how pissed off they'd made him. +沒有人來看他嗎 No visitors come in to see him? +手術結束後他就一直睡著 He's been sleeping a lot since they brought him back. +哦 Mm. +我親自來護理你 還有一個原因 That's another reason I don't miss nursing. +你看病人要是那樣 是多麼可憐啊 It's always so sad seeing a patient like that, +還獨自一人 挺過手術 all alone after that kind of surgery. +至少他不嘮叨 At least he's quiet. +瑞秋今早來過電話 Rachel called this morning. +真的? +她怎麼樣 Really? +how's she doing? +她在為下學期在交響樂團當首席小提琴手做準備 She's auditioning for first violin in next semester's symphony. +那真是太好了 That's wonderful. +還要書嗎 Need any more books? +不用了 我很好 No, I'm... +I'm fine. +今晚的藥拿到了嗎 Got your meds for the night? +嗯 我已經吃過了 Mm +-hm. +I already took them. +枕頭怎麼樣 How about pillows? +我很好 弗吉尼亞 真的 謝謝你 I'm fine, virginia, really. +thank you. +如果你願意的話 我可以陪你待一會兒 You know, I could stay a while if you want me to. +沒必要把你也給拖累了 對嗎 No use both of us being useless in the morning, right? +好吧 Okay. +她走了? +She gone? +什麼 What? +作為公共健康專家之流 As something of a public health expert, +我相信更多的人死於探望者 而勝過死於疾病 I believe more people die from visitors than diseases +這種草莓 600塊 "it's the berries," for 600. +這種瑞典草莓和越橘一樣享有盛名 This swedish berry is also known as the cowberry. +-越桔又是什麼 +-越桔又是什麼 +- what is a lingonberry? +uh, what is a lingonberry? +正確 這種草莓 800塊 Correct! "it's the berries," for 800. +1956年熱賣前40名中 這草莓告訴貝多芬轉存 In a top 40 hit of 1956, this "berry" told beethoven to roll over. +誰是查克. +貝瑞 Who is chuck berry? +誰是查克. +貝瑞 對 Who is chuck berry? +yes. +嘿 Hey. +杜克 Duke? +你介意嗎 You mind? +哦 對不起 Oh. +sorry. +no. +-什麼是馬裡亞那海溝 +-什麼是馬裡亞那海溝 +- what is the mariana trench? +- what is the mariana trench? +早上好 愛德華 Good morning, edward. +-早 +-感覺怎麼樣 +- morning. +- how you feeling? +明擺著呢 Dumb question. +導管怎麼樣 How's that catheter? +真不知道沒有它的時候我是怎麼過來的 Don't know how I ever did without it. +幽默是個好兆頭 Ah, humor is a good sign. +你去死吧 Kiss my ass. +太粗魯了 這是你最大的愛好了 對吧 As is surliness. +it's one of your favorite flavors, right? +-對 +-看看這裡怎麼樣 +- yeah. +- let's see what we got here. +看起來不錯 It looks good. +手術很順利 好嗎 All right, so the operation went well, okay? +所有的術後腦掃瞄都很乾淨 All the post +-op brain scans are clean. +現在我們要乘勝追擊你體內剩餘的腫瘤 Now we go after the sarcoma in the rest of your body. +不幸的是 你的血壓很高 Now, unfortunately, your blood markers are extremely high, +我希望今早我們就開始化療 so I would like to begin chemo this morning. +喜歡早上化療的味道 Love the smell of chemo in the morning. +現代啟示錄 對嗎 Apocalypse now, right? +讓我感覺像個勝利者 Makes me feel like victory! +-我等會兒和你去辦手續 +-好的 +- I'll check in with you later. +- all right. +喂 大夫? +大夫? +Say, doc? +doc? +你可以來看一下... +You think you could just take a look at... +? +-對不起 我遲到了 你的醫生是誰 +-蓋比安醫生 +- sorry, I'm late. +who's your doctor? +- he's dr. +gibian. +我告訴護士 I'll let the nurse know. +謝謝 Appreciate it. +婊子 不是嗎 Bitch, ain't it? +-夸克是什麼 +-夸克是什麼 +- what are quarks? +- what are quarks? +你在這兒多久了 how long you been here? +進進出出幾個月了 In and out over the past few months. +把我當成試驗品 got me on an experimental treatment. +-二元方程式是什麼 +-二元方程式是什麼 +- what is the quadratic equation? +what is the quadratic equation? +有多痛苦 How rough is it? +化療? +Chemo? +不是很糟 Not too bad. +只要你不介意晝夜不停的嘔吐 If you don't mind around +-the +-clock vomiting... +看著你的血管變黑 ...watching your veins turn black... +感覺骨頭像是汽油膠化劑做的一樣 ...and feeling like your bones are made of napalm... +與在海灘上度假一日無異 ...it's a day at the beach. +那真是種欣慰 That's a relief. +當然 我聽說每個人的反應都不一樣 Of course, I hear people react to it differently. +今晚你自己就知道了 You'll know by tonight. +今晚? +Tonight? +聽著 Listen, um... +是否介意我八卦一下 ...you don't mind my asking... +那邊那個奇妙的裝置是什麼 ...what is that contraption you got over there? +是虹吸壺 煮咖啡用的 It's a siphon. +makes coffee. +它還能幹些什麼 What else does it do? +它還能幹些什麼呢 What else does it have to do? +你是否知道咖啡最初是由埃塞俄比亞的 Did you know that coffee was originally discovered +一個牧羊人所發現的 by a shepherd in ethiopia? +-不必說了 +-是真的 +- you don't say. +- it's true. +好像是他的山羊在一個陌生的灌木叢中吃漿果 Seems his goats were eating berries from an unfamiliar bush. +沒過多久 羊就到處跑跑跳跳 Before long, they were running and jumping all over... +度過了一段歡欣雀躍的時光 ...having a gay old time. +於是牧羊人帶了一些樹枝回到當地的修道院 So the shepherd took some of the branches to the local monastery +修道院長決定把樹枝烤熟 where the abbots decided to roast them. +烤著烤著 When the berries burned +裡面的豆子散發出了濃郁的香氣 the beans inside gave off such a pleasant aroma +他們把豆子放入燉鍋中釀造 they brewed them into a stew. +燉鍋 Stew, huh? +隨後的幾百年裡 咖啡流傳到了阿拉伯 歐洲... +And over the next few hundred years, it spread to arabia, europe... +甚至蘇門答臘島 正如你從那兒買的烈酒一樣 ...even sumatra, like that hooch you got over there. +它叫做魯哇克香貓咖啡 It's called kopi luwak. +我知道它的名字 I know what it's called. +是嗎 You do? +從來沒人逮住過我喝那玩意兒 Never catch me drinking that shit. +你喝過嗎 Have you ever tried it? +沒有 我更鍾情於速溶咖啡 No. +I'm more of a instant +-coffee man. +來 我來幫你 Here, here we are. +-謝謝 +-不客氣 +- thanks. +- no problem. +好了 給 There you are. +你一直有雀斑嗎 You always had those freckles? +是的 Far as I know. +挺好看的雀斑 Nice freckles +嗯 Hmm. +好了 我們有培根火腿和甜瓜 還有些意大利布拉塔乾酪 Okay, we got prosciutto and melons, some burrata mozzarella... +和一塊小牛排 ...and a veal paillard. +都是上好的意大利傳統膳食 The folks at toscana send their best. +你要全部吃完嗎 You sure you wanna eat all that? +是這麼打算的 That's the plan. +什麼 What? +哦... +Oh, uh... +要湯馬斯給你也來一盤嘛 You want thomas to make you a plate? +湯米 弄一盤給... +Tommy, uh, fix a plate for, uh... +卡特 Carter. +是姓還是名? +First name or last? +名字 First. +真的? +很有意思 Really? +interesting. +要來一盤嗎... +? +說不定能讓你振奮 So you want, uh... +? +might cheer you up. +不需要了 謝謝 No, thanks, I'll pass. +確定? +You sure? +好吃 好吃 Mm, yum, yum. +全洛杉磯最好吃的 Best in l. +a. +再也不是洛杉磯最好的了 It ain't the best in l. +a. +no more. +我的天啊 Oh, man. +瑪亞又是三好學生 Maya made the honor roll again. +我肯定她行的 Bet your ass she did. +我的天啊 My god. +還不如得個心臟病什麼的 Somewhere, some lucky guy's having a heart attack. +同志們 Fellows. +寇爾先生 Mr. +cole. +別管我 我只是在自言自語而已 Don't pay any attention to me. +I'm just, uh, talking to myself. +這是凱爾給你的 It's from kai. +他說長大後想成為像他爺爺一樣的機械師 Says he wants to be a mechanic like his granddad when he grows up. +希望你讓他打消這個念頭 I hope you talked him out of that. +我試過了 Well, I tried. +看看是什麼東西 What do we got here? +一部福特野馬350 It's a shelby 350. +-我一直想要一部 +-是啊 +- I always wanted one of those. +- yeah. +凱爾記著 kai remembered. +媽媽覺得你好像休息得不夠 Mom seems to think you're not getting enough rest. +恩 Mm +-hm. +她愛你 爸爸 She loves you, pop. +恩 Mm +-hm. +好 Okay. +檢查報告出來後 給我們打電話 好嗎 You'll, uh, call us when you get your test results, huh? +恩 Mm +-hm. +如果有結果的話 If that day ever comes. +好 Okay. +-保重 +-好 +- take care. +- okay. +你的長子? +He your oldest? +是 Yeah. +他做什麼的 What's he do? +-羅傑是稅務律師 +-哦 +- roger's a tax attorney. +- oh. +你看 Here. +他弟弟李 是個工程師 His brother, lee, is an engineer. +這個漂亮的小女孩是誰 Who's the pretty little lady? +那是瑞秋 三個中最小的 That's rachel. +youngest of the three. +年紀差得好大 Big age difference. +是啊 她是個驚喜 Yeah, well, she was a surprise. +她出生後 我兒子們都寧願呆在家裡照顧她 We'd hardly gotten the boys out of the house when she came along. +她小提琴拉得很棒 She's an outstanding violinist. +你有小孩嗎 You got kids? +這要看了 Depends. +-我的婚姻關係都不長 +-恩... +- never stayed married long enough. +- oh, well... +別擔心 對於我們兩個來說我結婚夠久了 ...don't worry, I've been married long enough for the both of us. +覺得怎麼樣 How's that going? +就這樣 It's going. +感覺不錯吧? +That good, huh? +這就是為什麼要發明電燈開關的原因了 Well, that's why they invented light switches. +別誤會 我愛婚姻生活 結過四次婚 Don't get me wrong, I loved being married, been there four times. +問題在於我鍾情於獨身 Problem is I love being single too. +魚和熊掌不可兼得 Hard to do them both at the same time. +人無完人嘛 Well, nobody's perfect. +我唯一成功的就是我的事業 Only successful marriage I had was me and my work. +我16歲時就開始賺錢... +I started making money when I was 16... +...之後就 ...and that was that. +沒有停過 Never stopped. +我比較倒霉 I'll be damned. +我原來想當歷史教授 I wanted to be a history professor. +人無完人啊 Nobody's perfect. +弗吉尼亞告訴我懷孕前 I made it through two months of city college... +我在城市學院做過兩個月 ...before virginia gave me the news. +然後... +And then, you know... +年紀小 黑人還窮 孩子又要生了 ...young, black, broke, baby on the way... +就接了第一份待遇還不錯的工作 Take the first decent job that comes along. +我一直想回去 I always meant to go back +但45年一晃就過去了 but 45 years goes by pretty fast. +時光飛逝 Like smoke through a keyhole. +該死 Shit! +不要睡著的時候給我打嗎啡 真是浪費 Don't give me the morphine while I'm sleeping. +it's a waste. +她可能是想把我們倆都殺了 你說呢 Maybe she's trying to kill us both. +you ever think of that? +贏了 Gin. +你是什麼 魔鬼嗎 What are you, the devil? +如果我已經失去理智了怎麼辦 What if I lost my mind already? +老天啊 不會吧 Jesus, no. +不 不 不 這不是祈禱 No. +no, no jesus, this is not praying. +我只是在自言自語 這是 I'm talking to myself out loud, that's... +你想過自殺嗎 You ever think about suicide? +自殺? +我? +Suicide? +me? +yeah. +沒有 no. +知道了 你是第一階段 Thought so. +stage one. +什麼 What? +有五個階段 但是... +The five stages, but... +否認 Denial. +然後是憤怒 抵抗 沮喪 接受 Then anger, bargaining, depression, acceptance. +所以你現在當然不會想到自殺 So of course you're not thinking of suicide. +你處於第一階段 否認 You're in stage one. +denial. +那你在哪個階段 What stage are you in? +否認 Denial. +想過自殺嗎 And thinking about suicide. +好吧 這只是一個... +Yeah, okay. +it's just a frame of... +看上去你好像不再需要這個了 Well, it looks like you won't be needing this anymore. +-結束了? +-第4個療程 也是最後一個 +- that's it? +- yep, fourth and final. +接下來做什麼呢 What's next? +醫生要先看看所有的檢查結果再決定 They have to run all the tests first, see where we stand. +-要多久 +-需要點時間 +- well, how long? +- takes a while. +我會讓蓋比安醫生安排檢查的 I'll get dr. +gibian to schedule them when I see him. +謝謝 Thanks. +我離下班還有一個小時 還有什麼需要嗎 I'm on for another hour, anything you need? +如果可以的話 我想要健康證明書 Clean bill of health if you got one. +堅持一下 卡特 Hang in there, carter. +我就是這麼做的 That's what I do. +到中心線 上壘... +And line to center, base hit... +將要打三個反彈球 ...kent will have to play it on three bounces... +得分 投球手向後... +...and alou will score. +the throw goes to the back... +啊呀抄近路 天啊 Hit the cutoff man, for crying out loud. +你看 這就是比賽癥結所在 You see that's the problem +沒有基本原則 No fundamentals. +有讀過這本書嗎 Did you ever read the time of your life? +-威廉. +薩洛揚寫的 +-是的 +- william saroyan. +- yeah. +"沒有基礎 完全沒有" "no foundation. +all the way down the line." +當我們長大後... +你在做什麼 When we were growing up... +what are you doing? +沒有 隨便寫寫 Nothing, scribbling. +寫點什麼 Scribbling? +what? +沒什麼 亂寫而已 Nothing. +just scribbling. +當然 這是你想做的 Oh, sure, that's what you wanna do +三壘的人 球偏了點 bounce a slider with a man on third. +現在的這些孩子... +These kids today, they... +戴耳機了 我原來在自言自語 Earphones. +I'm talking to myself, again. +-愛德華? +-醫生 +- edward? +- doc. +感覺如何 How's it going there? +愚蠢的問題 Dumb question. +檢驗報告出來了 I got the test back. +現在就說嗎 I'll just lay it out, huh? +只剩六個月 Six months. +幸運的話一年 A year if we're lucky. +我們有一個實驗性的療程 There is an experimental program that we've been conducting +但不要抱太大希望 and I don't wanna get your hopes up +只是覺得你比較適合來試試看 but I think you would be an excellent candidate +醫生 Hey, doc. +怎麼了 Yes? +你擋住我視線了 You're blocking my view. +哦 Oh. +對不起 Sorry. +如果你有什麼想問的 Anyway, if there's any questions +不管什麼時候 都可以來找我 day or night, you know where to find me. +有一個問題 One question. +當然 問吧 Sure, of course. +卡特 你有什麼要問霍林斯醫生的嗎 Carter, you wanna ask dr. +hollins something? +我其實對錢柏先生的病情不太瞭解 I mean, I'm not familiar with mr. +chambers'... +那就去瞭解一下 Well, get familiar. +我只是想知道我還能活多久 就這個 I just wanted to know how I stand, that's all. +好的 那我先去看看你的病情報告 Sure. +how about I'll go take a look at your chart, okay? +謝謝 Thank you. +愛德華? +Edward? +愛德華? +Edward? +曾經有一項調查 There was a survey once. +一千名被調查者被問到否願意 A thousand people were asked, if they could know in advance... +事先知道他們的死期 ...would they want to know the exact day of their death. +96%的人不想 Ninety +-six percent of them said no. +我我以為我就是那剩下的4% I always kind of leaned toward the other 4 percent. +因為如果能知道自己的生命還剩多少 I thought it would be liberating... +將會是一種解脫 ...knowing how much time you had left to work with. +最好的情況是1年 A year at best. +但其實... +我不是 It turns out, it's not. +想玩牌嗎 You want to play cards? +以為你再也不會問了 Thought you'd never ask. +太陽高高昇起 Rise and shine. +或者這樣 Or that. +讓我看看 Let me see that. +還有 湯馬斯 And, uh, thomas... +打電話給克裡斯蒂拍賣行的瑪麗 call marie at christie's and tell her +這個季度我不去競拍了 I won't be bidding this season. +知道了 I understand. +我不想冒犯你 Uh, sir, I don't mean to sound indelicate +但你要我怎麼處理你的... +but how do you want me to handle your? +遺產? +Death? +就當作你的遺產一樣處理 Treat it as if it were your own. +把所有的錢都留給我的助理? +So leave all the money to my assistant? +去給我買塊杏仁牛角麵包 Go get me one of those almond croissants that I like. +給我挑好的 And don't buy any green bananas. +-你在看什麼 +-這是什麼 +- what are you doing? +- what is this? +-快還給我 +-是什麼 +- come on, give it back. +- what is it? +還給我 Give it back. +地上撿的 我又不知道這是國家機密 It was on the floor. +I didn't know it was a state secret. +我大一時 有個哲學教授 Well, my freshman philosophy professor +給我們佈置過一份作業 關於人生規劃 assigned this exercise in forward thinking. +叫做"遺願清單" He called it a "bucket list." +我們要把一生中想做的事情列出一個清單 We were supposed to make a list of things we wanted to do +-在我們... +-翹辮子之前 in our lives before we... +- kicked the bucket. +真做作 Cutesy. +我列出來的是"成為百萬富翁" Anyway, I wrote things like "make a million dollars" +"當第一位黑人總統" 都是些年少輕狂的想法 "first black president," you know, young man's wishes. +我想重新列一張 但是... +I was gonna redo the list, but then... +"善意地幫助一位陌生人" "help a complete stranger for the good." +"大笑到流淚" "laugh until I cry." +不是要評論 但這也太弱了點 Not to be judgmental, but this is extremely weak. +現在也沒什麼用了 Well, it's pointless now. +我要從反面跟你理論一下 I would argue the exact opposite. +好吧 就這樣 All right. +that's it. +你在幹嘛 What are you doing? +只是稍微改一下 A little rewrite, that's all. +難道你不想去參加舞會 玩玩槍 I mean, don't you want to go out with some balls? +guns blazing? +找點樂子? +Have a little fun? +這可不是關於什麼槍什麼的 It was not supposed to be about guns blazing or anything like that. +你還沒弄明白 You're missing the point. +"欣賞宏偉的景色"這是什麼鬼東西 What the hell is "witness something majestic"? +你有去過喜馬拉雅山嗎 Have you ever been to the himalayas? +"駕駛福特野馬跑車" 這還不錯 "drive a mustang shelby." not bad. +想到一個 去跳傘怎麼樣 I got one. +all right. +how about skydiving? +現在我們有事做了 Now we're onto something. +我們有事請做了? +We're onto something? +-對啊 +-讓我看看 快點 +- uh +-huh. +- let me see that. +come on. +好 Fine. +"親吻世界上最美的女孩" "kiss the most beautiful girl in the world"? +你打算怎麼做到 How do you propose doing that? +大親特親 Volume. +"刺一個紋身" 這就是你的勇氣? +"get a tattoo." is that the sum of your ambition? +愛德華 我寫的可比你深刻 Edward, I've taken baths deeper than you. +比大一學生深刻是容易的 It's easy to be deep in freshman philosophy. +霍林斯醫生怎麼說的 What's dr. +hollins say? +我們只有幾個月了 對嗎 We got months, right? +也許一年 A year, maybe. +你覺得45年過得很快嗎 You think 45 years went by fast? +我們能去做這些事的 We could do this. +我們應該去完成這些願望 We should do this. +不行 我不能 No, I couldn't. +不要擔心錢 我有的就是錢 Don't think about money. +that's all I got is money. +但我不知道... +But I don't know. +I... +你不知道什麼 What don't you know? +我只是打比方而已 It was meant to be metaphorical. +-我只是想試著去處理... +-全是廢話 +- I'm just trying to get a handle on... +- blah, blah, blah. +打比方 Metaphors. +你光說不做 所以才會遺憾 現在機會來了 You're the one crying you never took a shot. +here's your chance. +什麼機會 把自己變成傻瓜 My chance to what? +make a fool of myself? +永遠不遲 Never too late. +你覺得接下來會怎麼樣 What do you think happens now? +我回去 然後聽別人說一大堆 I go back and sit around listening to people +關於融資理財和次級貸款 talking about mezzanine financing and subordinated debt +假裝關心很關心我那些該死的錢 pretending that I care about dead money. +你回到家去為你的死亡準備一個儀式 You go home to some ceremonial procession into death... +在你想安慰大家的時候 ...with everyone standing around watching you die... +他們卻都圍著看你離去 ...while you try to comfort them. +那就是你想要的嗎 被憐憫和憂傷所充斥著 Is that what you want, to be smothered by pity and grief? +我可不想 Well, not me. +卡特 我相信在你的內心深處你也不想這樣 And in your heart, carter, I believe not you either. +我們現在是同舟共濟 這個比喻怎麼樣 We're both in the same boat. +how's that for a metaphor? +我們現在有個很好的機會 We got a real opportunity here. +機會 Opportunity? +即使是對你來說 這麼講也太離譜 That is real twisted, even by your standards. +我們依然感覺不錯 對嗎 精力又回來了一點 We still feel good, right? +energy's coming back a little bit. +醫生說沒事了 Asymptomatic, the doc says. +照我的看法 我們可以躺在這兒 The way I see it, we can lay around here... +期待在某個爛科學實驗中發生奇跡 ...hoping for a miracle in some bullshit science experiment... +或者我們能更進一步 ...or we can put some moves on. +跳傘 對嗎 Skydiving, huh? +太好了 All right. +這是什麼醫院 居然連個醫學博士都沒有 What kind of hospital is this? +there isn't an m. +d. +within a mile. +弗吉尼亞 我們得談一下 Virginia, we have to talk. +醫院怎麼說的 What did they say? +錢柏太太 你們談 我出去一下 Uh, mrs. +chambers, I'm gonna give you two a little quiet time. +請原諒 Excuse me. +情況不太好 It's not good. +我就知道我們應該去加州大學附屬醫院 I knew we should have gone to ucla. +那兒的外科醫生和手術水平都更好 The surgeons are better. +post +-op is better. +-這沒什麼關係 +-你根本不懂 +- wouldn't have mattered. +- you don't know that. +我們絕不放棄 我有其他辦法 We're not giving up. +I want another opinion. +弗吉尼亞 virginia. +請接腫瘤科的維特裡醫生辦公室 Yes, oncology, please. +dr. +veteri's office. +弗吉尼亞 別打了 Virginia, no. +讓我來處理 Let me handle this. +維特裡醫生嗎 我是弗吉尼亞. +錢柏 Dr. +veteri? +virginia chambers. +是的 沒錯... +Yes, that's right... +我要離開一段時間 I'm going away for a while. +你在說什麼 What are you talking about? +我在說愛德華和我要出發了 I'm talking about edward and I are going away. +愛德華和你 Edward and you? +出發去哪裡 Going away where? +我不期望你能理解 I don't expect you to understand. +你說對了 我不理解 You're damn right I don't understand. +我不理解你怎麼能就這樣放棄 I don't understand how you can just give up like this. +你怎麼能就這樣... +放棄鬥爭 How you can just quit... +quit fighting. +-弗吉尼亞 +-為什麼你不和孩子們那樣去說 +- virginia. +- why don't you tell our children that? +當他們發現是你放棄了他們時 看他們怎麼說 See what they say when they find out you've given up on them. +放棄他們 Given up on them? +放棄他們 Given up on them? +我在引擎蓋下面修了45年的車 I've got 45 years greased up under the hood of a car... +那樣他們就不會來要求什麼了 他們確實沒有 ...so that they didn't want for anything, and they didn't. +我想我該給自己一點時間了 I think I've earned some time for myself. +去做什麼 和一個完全陌生的人離開 To do what? +run off with a total stranger? +他不是一個陌生人 He's not a stranger. +我是你的妻子 I'm your wife. +我是你的丈夫 他們的父親 And I'm your husband. +and I'm their father. +他們的祖父 還是一個該死的修車師 And I'm a grandfather. +and I'm a damn mechanic! +你是個傻子 And you're a fool. +你是個認為他會給你指一條 You're a fool who thinks he's figured out +不會得癌癥的路的傻子 a way how not to have cancer. +對不起 I'm sorry. +我丈夫不是用錢可以換走的 My husband is not for sale. +她恨我 She hates me. +你恨我嗎 Do you hate me? +目前還沒有 Not yet. +因此計劃就開始了 And so it began. +我常常害怕坐飛機 I've always been afraid to go up in an airplane +現在我就要在一個瘋子的幻想中跳下去 now I'm gonna jump out of one at the whim of a maniac! +想撿回來嗎 Wanna get it? +你怎麼能建議我們這樣做 How do you suggest we do that? +等等 Wait. +噢 Ow! +見鬼 Damn it. +閉嘴 Not a word. +回到座位上去吧 凱爾 Back to the seat, kyle. +你要原諒我 凱爾 You'll have to forgive him, kyle. +他在擔心家裡的那個女人 he's worried about the little woman. +這和我妻子沒有關係 This has nothing to do with my wife. +30秒後起跳 Thirty seconds to drop. +結局是這樣的 The sequel was like that. +她從未支持過我做任何事 She never backed me up on anything. +結局 The sequel? +我的第二任妻子 The second mrs. +edward cole. +天啊 那個女人恨死我了 God, that woman hated me. +可能是因為你叫她"結局" Maybe because you called her the sequel. +凱爾 我從來沒那樣想過 kyle, I never looked at it that way. +-15秒 +-不 不 +- fifteen seconds. +no, no. +-等一下 我不能這樣做 +-當然可以 +- wait! +wait, I can't do this. +- sure you can. +不 我真的不能 No. +I can't. +really. +你害怕的不是跳下去 It's not the jump you're afraid of. +當然不是 The hell it's not! +你只是在擔心你的降落傘不能打開 You're just afraid your chute won't open +然後你會像個煎蛋卷一樣 出現你自己的葬禮上 and you'll show up at your own funeral as a denver omelet. +不 我真的非常擔心降落傘不能打開 No, I'm pretty much just worried the chute won't open. +不 不 No, no! +他的嗓子不錯 對嗎 Man's got some lungs, huh? +讓我們用降落傘降落吧 Let's hit the silk! +我們是勇士 Geronimo! +哇塞 太漂亮了 Oh, yeah, beautiful! +啊 啊 Aah! +aah! +快拉 快拉繩索 Pull the thing! +pull the cord! +感覺怎麼樣 這才是生活 How about this, huh? +this is living. +我恨死你了 I hate your rotten guts. +向天空說投降吧 Surrender to the void! +這麼多繩索 哪條是用來拉的 Which one of these damn cords do you pull? +別碰他 我們還沒到降落地點 Don't touch it. +we're not in the drop zone yet. +我們可以借助風勢... +we could wind up in the... +好吧 打開降落傘吧 Okay. +let's deploy. +我有種感覺 我在降落 I got a feeling I'm falling +我們到了紅色區域了 拉繩索 We're in the red zone. +pull the cord. +我有種感覺 我在墜入愛河 I got a feeling I'm falling in love +快拉繩索 Pull the damn cord! +我曾擁有愛 I was in love once. +湯米 我們活著就為了某天死去 Tommy, we live to die another day. +我很走運 How lucky for me. +說真的 湯馬斯 記住那遺囑 它離你很近了 No jokes, thomas, remember the will. +you're so close. +我想問你點事情 Let me ask you something. +你是叫湯米還是湯馬斯 Uh, is it tommy or thomas? +實際上我叫馬修 但他覺得那名字太宗教化了 Um, it's actually matthew, but he finds that too biblical. +我們吃點東西吧 快來 Let's eat something. +come on! +他瘋了嗎 Is he insane? +時不時地 Depends. +你決定了嗎 So you decided? +不 我不想要任何 No, I couldn't think of anything +會困擾我永世的東西 I wanted to be stuck with permanently. +還永世呢 我們就要在五分鐘內死去了 What's permanently? +we're gonna be dead in five minutes. +-什麼 +-比喻說法 +- what? +- figure of speech. +不舉同盟旗 不信黑色耶穌 So no confederate flag, no black jesus. +不 我將要... +No, I'm gonna... +去世 當然會 Pass. +yeah, sure. +我向來不主張褻瀆自己的身體 Well, I never agreed to desecrate my body. +你在擔心他們不會把你葬在猶太人的公墓 You worried they won't bury you in a jewish cemetery? +擔心你妻子嗎 What, the wife? +這只是個紋身 It's a tattoo. +這與你在外搞婚外情是不同的 It's not like you're dumping her for another woman. +我從來沒和其他女人在一起過 I never been with another woman. +哇 Whoa. +那個必須要寫在清單上面 That's gotta be on the list. +不 我不這麼認為 No, no. +I don't think so. +66年 Sixty +-six years? +夥計 我們應該來次放縱 Man, oh, man. +we ought to have a big orgy. +不 No. +放縱並不等於是不忠 Orgy's not even being unfaithful. +不 No. +這只不過看上去更專業 It's just, like, professional. +不 No! +我從來沒去過那種地方 I don't even have to be there. +你好 親愛的 Hello, darling. +你要駕駛她還是給她買身漂亮衣服 you gonna drive it or buy it a dress? +只是讓我們彼此熟悉一下 Just getting to know each other. +你確信我們準備好了嗎 You sure we're cleared for this? +當然已經準備好了 要不然怎麼樣 Of course we're cleared for it. +what if we weren't? +只是檢查一下 Just checking. +快 加油寶貝 看看她到底如何 Come on! +tap it, baby! +let's see what she's got. +我們很棒啊 Ah, we're doing just fine. +你聽上去好像小孩要去參加大三的舞會 You sound like some kid going to the junior prom. +你聽上去好像誰正在等待扭屁股的勝利 You sound like someone looking for an ass +-whupping. +扭屁股勝利 哈 哈 Ass +-whupping? +ho +-ho +-ho +-ho. +-你一無所有 +-哈 哈 +- you got nothing! +- ha, ha. +有你就足夠了 快樂的吉姆 加速 Got enough for you, sunny jim, dangling. +開這麼快想證明你雞雞有多能幹嗎 Did you just make a penis reference? +如果我有呢 What if I did? +上帝 你要讓我們兩個送命嗎 Jesus! +you're gonna kill us both! +如果我要呢 What if I do? +見鬼 Goddamn it! +你給我帶來了麻煩 You're breaking evil on me. +麻煩 我給你表演一下麻煩 Evil? +I'll show you evil. +我來給你表演一下真正的飛車麻煩製造者 I'll show you evel goddamn knievel. +嘗嘗這個 膽小鬼 Pick up on this, chicken man! +耶 哈 Yee +-ha! +膽小鬼 哼 Chicken man, huh? +你能跑 但你不能躲起來 You can run, but you cannot hide! +接下去你想做什麼 What do you wanna do next? +你到底有多少錢 How much money do you have anyway? +沒人告訴過你 Didn't anyone ever tell you +議論別人的財產 是件很不禮貌的事情嗎 that it's rude to talk about someone else's money? +這麼有錢的人 我還是第一次認識 I never knew anyone with enough to ask. +很像病房啊 Medicinal. +這是難以形容的美麗 It's indescribably beautiful. +我喜歡在地球兩極上空飛行 I love flying over the polar cap. +在荒涼的上空 Above the desolation. +星星 The stars +是上帝所創造的美好事物之一 it's really one of god's good ones. +你認為是某種生命體創造了這些 So you think a being of some sort did all this? +你不這麼認為嗎 You don't? +你的意思是我是否相信當我仰望天空 You mean, do I believe if I look up in the sky +允諾這個或那個的時候 and promise this or that +上帝就會讓我們挽回生命嗎 the biggie will make all this go away? +不會 No. +那你的意思地球上95%的人都錯了 Then 95 percent of the people on earth are wrong? +生活告訴我 If life has taught me anything +這95%的人總是犯錯 it's that 95 percent of the people are always wrong. +這就叫信仰 It's called faith. +事實上我羨慕那些有信仰的人 I honestly envy people who have faith. +但我自己卻做不到 I just can't get my head around it. +也許你正在努力 Maybe your head's in the way. +卡特 我們聽夠了無數次類似的討論 Carter, we've all had hundreds of these discussions... +但每個人最終都遇到了同樣的問題 ...and every one of them always hits the same wall. +就是到底有沒有神靈的存在 Is there a sugarplum fairy or not? +沒人能夠回答這個問題 And nobody has ever gotten over that wall. +那你信仰什麼呢 So, what do you believe? +我拒絕所有的信仰 I resist all beliefs. +沒有大爆炸之後宇宙的存在 No big bang? +random universe? +我們活著 We live. +我們死去 We die. +生命的車輪在不停的前進 And the wheels on the bus go round and round. +如果你錯了呢 What if you're wrong? +我很高興自己是錯的 I'd love to be wrong. +如果我錯了 那我就贏了 If I'm wrong, I win. +我不確定這樣有沒有用 I'm not sure it works that way. +你不認為你知道一些我不知道的事 Well, you're not claiming you know something I don't. +恩 Mm +-mm. +我有信仰的 I just have faith. +哈雷路亞 夥計 Hallelujah, brother... +不談這個了 ...and pass the mustard. +-你知道他們是怎麼收穫魚子醬的嗎 +-不知道 +-Know how they harvest caviar? +-hit me. +當雌鱘魚被抓住的時候 When a female sturgeon is caught... +漁夫必須注意觀察 她死得是否很安詳 ...the fisherman has to take great care to see she dies peacefully. +-恩 +-只要她感覺到一點點的恐懼 +- mm +-hm. +- lf she feels the least bit threatened... +...她就會分泌一些酸液來破壞魚卵 ...she secretes a sour chemical that ruins the eggs. +聽上去像我第三任妻子 Sounds like my third wife. +她認為蛋黃醬是種出來的 Woman thought mayonnaise came from a plant. +我對此已經習以為常了 I could get used to this. +聽上去也像我的第三任妻子 Also sounds like my third wife. +這30年裡 我常來這裡 Thirty years I've been coming here. +和一個男人來這裡是第一次 First time with a guy. +我很榮幸 Well, I'm flattered. +艾米莉的十歲生日是最美好的 雖然... +Emily's 10th birthday was the best, though. +誰是艾米莉 Who's emily? +我的小... +My little, uh... +她已經不再是小姑娘了 Well, she's not so little anymore. +你有個女兒 You have a daughter? +-但是你說... +-是的 +- but I thought you said... +- yeah, well... +那時我還不認識你呢 i didn't know you then. +長話短說 Make a long story short, +我們不見面的 i don't see her. +你在幹什麼 What are you doing? +現在是時候了 It's time. +-不 不 把它劃掉吧 +-為什麼不去 +- no, no, no. +cross that off. +- why not? +-劃掉它 +-為什麼 +- cross it off. +- why? +為什麼 Why? +沒有什麼為什麼 There is no why. +-你怎麼了 +-請原諒 +- what's the matter? +- excuse me. +你去哪裡 Where you going? +真像個女人 Just like a broad. +喂 卡特 Look, uh, carter... +對不起 我知道 I'm sorry. +I know +有時我有一點傲慢和... +sometimes I get a little overbearing and l... +上帝啊 Jesus christ. +-沒事的 沒關繫了 +-什麼 什麼 +- it's all right. +it's okay. +- what? +what? +上面的導管流出來的 沒什麼 The top on the catheter came loose, that's all. +也許該送你去醫院 卡特 Well, maybe we should get you to a hospital, carter... +-我剛從醫院裡出來 +-嗯? +- I just busted out of the hospital. +- huh? +沒事了 看 已經不流了 我們出去吧 It's all right. +look, it's already stopped, see? +let's get out of here. +看上去很好 嗯... +It looks wonderful. +uh... +uh... +-也許我要去拿... +-我們直接走吧 +- maybe I'll get the... +- let's just go. +-你直接上車去 +-走吧 走吧 +- you go straight to the car. +- come on. +come on. +好吧 Okay, all right. +-湯米在哪? +在哪? +-在客廳 先生 +- where's... +? +where's tommy? +in the salon, monsieur. +噢 天哪 Oh, my. +你到底有多少錢呢 How much money do you have? +我可不會流血到地毯上 Well, I wouldn't bleed on the rugs. +我要找個地方好好洗個熱水澡 I'm gonna find someplace where I can take a nice hot bath. +洗得乾乾淨淨的 Be as good as new afterwards. +是的... +你... +好吧 Yeah... +you... +okay. +好吧 我們都準備好了 好的 okay, we're all set, okay +好了 雖然花了點功夫 但是我都重新安排好了 All right, it took some doing, but, uh, I rearranged everything. +明天去開羅 在坦桑尼亞呆兩天 Cairo tomorrow, tanzania for two days, +然後週六去約翰內斯堡 then johannesburg on saturday. +而且事先聲明 不准鬥牛 不准獵虎 And, as previously directed, no bullfight, no tiger hunt. +湯馬斯 我真的很想說你是不可替代的 Thomas, I'd really like to say you're irreplaceable +但是那是在說謊 but I'd be lying. +我也很想說你真的是個不錯的人 我熱愛我的工作 And I'd really like to say you're a gracious man, and I love my job +但是我 也是在說謊 but i, too, would be lying. +反擊得很合理 Turnabout is fair play. +肯定是跟我學的吧 I believe you learned that from the master. +嘿 過來看 他們遇到危險了 在浴室 Hey, look! +they got jeopardy! +in the bathroom! +電視上的 冒險者 On the tv. +jeopardy! +冒險者 在法國 Jeopardy! +? +in french? +喂 Hello? +是寇爾先生嗎? +我是弗吉尼亞. +錢柏 Mr. +cole? +virginia chambers. +噢 我知道了 嗯 你好 Oh. +yeah. +um, hi. +我幫你叫卡特接電話 Let me get carter for you. +實際上 我是打給你的 Well, actually, I called to speak to you. +噢 Oh. +他還好嗎 Is he all right? +噢 是的 他... +他很好 Oh, yeah. +he's... +he's fine. +我能問下你們在哪嗎 May I ask where you are? +法國 實際上 嗯 明天... +France, actually. +uh, tomorrow... +把他還給我 Give him back to me. +弗吉尼亞 我可以叫你弗吉尼亞嗎? +Virginia. +may I call you virginia? +我不確定我是否可以讓他 I'm not sure that I can make... +別拿他當借口 I'm not asking for his sake. +寇爾先生 Mr. +cole +我這一生的職業就是護士 I've been a nurse my entire adult life. +我親眼目睹了很多人的悲劇 Had a ringside seat to more human tragedy... +我比任何女人承受過的都要多 ...than any woman should ever have to bear. +現在 我早有了丈夫將亡的心理準備 Now, I'm prepared for my husband to die. +我只是沒準備 在他還活著的時候就失去他 I'm just not prepared to lose him while he's still alive. +-霍迪. +杜迪是誰? +-答對了 +- who is howdy doody? +-you got it. +-你來選 +-電視木偶類 400元 +- you pick. +- "tv puppets," for 400. +這兩個提線木偶 These two muppets... +是室友 他們長期在芝麻街節目中表演 ...are roommates on the long +-running show sesame street. +伯特和爾尼是誰 who are bert and ernie? +斯必羅. +阿格紐是誰 Who is spiro agnew? +斯必羅. +阿格紐是誰 Who is spiro agnew? +看來 Well... +你看起來 嗯 ...you're looking, uh... +很愉快 ...buoyant. +這是我第一次躺在一個沒有角的浴缸裡 This is the first time I was ever in a tub with no corners. +是嗎 Really? +嗯 卡特 其實我一直在想 You know, ahem, carter, uh, I've been thinking +剛才導管的事 還有其他的事 what with the catheter and everything +也許我們應該把旅行暫停一陣子 maybe we should put this on hold for a while. +拜託 我不是跟你說了嗎 別擔心 我現在很好 Come on, now, I told you, stop worrying. +I'm fine. +不 不 不是指那個 不是指那個 No, no, it's not that. +it's not that. +只是 我的意思是 或許我會讓你失望 It's just, I mean, if you're worried about letting me down +你知道 畢竟我更可能會死 you know, it's a lot easier for me. +你和弗吉尼亞談過了 是嗎 You talked to virginia, didn't you? +你認為我這麼做是為什麼 Why do you think I'm doing this? +因為我讓你這麼做的 Because I talked you into it. +愛德華 你是很厲害 但是沒有那麼厲害 Edward, you're strong, but you're not that strong. +知道嗎 Know. +自從瑞秋上大學後 我的生活就出現了個缺口 After rachel left for college, there was a hole. +我的意思是 你知道 不再有家庭作業 不再有社團 I mean, you know, no more homework, no more little league... +背誦 學校比賽 ...recitals, school plays... +孩子的哭聲 打鬧 摔傷膝蓋 ...kids crying, fights, skinned knees. +40年來我第一次看著弗吉尼亞 And for the first time in 40 years, I looked at virginia +周圍沒有絲毫吵鬧聲 沒有任何干擾 without all of the noise, without all of the distractions +我甚至記不起來那種感覺 and I couldn't remember what it felt like +那種不牽著她的手逛街的感覺 when I could not walk down the street without holding her hand. +我的意思是 她還是那個我深愛的女人 I mean, she was the same woman I fell in love with, +她沒有變 she hadn't changed. +但是不知怎麼了 一切都變了 But somehow everything was different. +一路走來 我們似乎失去了什麼 We'd lost something along the way. +你明白嗎 You know? +查理. +麥卡錫是誰 Who is charlie mccarthy? +獅子在今夜沉睡 "the lion sleeps tonight" +看 看 看 Look, look, look! +啊哈 Aah! +我很高興當愛德華決定 I was very pleased when edward decided +把單子上的第9條劃去 to eliminate item number nine +"獵虎" "hunt the big cat." +當然 他依然堅持要放幾槍 Of course,he insisted on discharging rounds from the big gun +其實一槍就夠了 One proved to be enough. +你知道嗎 Do you know +唯一一條被閃電擊中的狗 that the only dog ever struck by lightning +就是在這 在埃及 was right here, in egypt? +我真希望我能在被叛死刑前認識你 I wish I'd met you before we were dead. +這樣看來 You know, technically +我們可以劃去兩條了 we could cross off two items: +親眼目睹金字塔 "see the pyramids" +還有欣賞宏偉的景象 and "witness something majestic." +這裡已經很宏偉了 This is about as majestic as it gets. +還是等看到我的山再下結論吧 Wait till you see my mountain. +噢 好吧 Oh, yeah. +你的山 Your mountain. +不過 這裡確實不錯 Still, this ain't half bad. +古埃及人對於死亡有個美好的信仰 the ancient egyptians had a beautiful belief about death. +當他們的靈魂到達天堂的入口時 When their souls got to the entrance to heaven +上帝會問他們兩個問題 the gods asked them two questions. +他們的回答將決定他們能否進入天堂 Their answers determined whether they were admitted or not. +好吧 我想知道 Okay, I'll bite. +問了什麼問題 What were they? +你找到生命中的快樂了麼 Have you found joy in your life? +這個 Uh +-huh. +回答問題 Answer the question. +-我? +-是的 你 +- me? +- yeah, you. +回答問題 你找到生命中的快樂了麼 Answer the question, "have I found joy in my life?" +找到了 Yes. +你的生活給別人帶去快樂了麼 Has your life brought joy to others? +恩 這種問題 我 Ah, this type of question, l... +我不知道 嗯 I don't know, uh... +我不知道別人是怎麼想的 嗯 I don't think about how other people gauge, uh... +你問他們吧 Ask them. +我在問你 I'm asking you. +好吧 Fine. +好吧 Fine. +這麼跟你說吧 Let me put it to you this way. +離婚後 接著我就不再是爸爸了 After the breakup, and the ensuing fleecing of the dad +艾米麗和她母親一起生活 emily went to live with her mother. +你知道 雖想保持親近 但只能假期聚聚 You know, you try to stay close, but it gets down to holidays +偶爾打個電話 寄張生日卡什麼的 phone calls, birthday cards, you know. +總之... +Anyway... +艾米麗上大學了 加入了個拯救窮人 emily goes to college, joins one of her "save the poor people" +動物之類的 the animals, whatnot +遇見了個男人 而且愛上了他 meets a guy, decides she loves him. +那小子長得不錯 有野心 聰明 Good +-looking kid, driven, smart. +但是他有些問題 But there was something about him +所以她告訴我 他們要訂婚的時 我反對了 so when she said they were engaged I told her I was against it +但是不愧是我的女兒 於是 but being my daughter, naturally +她還是和他結婚了 she went ahead and married him anyway. +不用說 她沒有邀請我參加他們的婚禮 Needless to say, I wasn't invited to the wedding. +你肯定很傷心 That must have hurt. +你這麼認為 You think? +他第一次打她 她來找我 First time he hit her, she came to me. +我想打爆他的頭 I wanted to bash his brains in. +她阻止了我 She wouldn't let me. +說她愛他 這不是他的錯 他只是喝了點酒 Said she loved him, said it wasn't his fault, he'd had a few drinks +是她先惹他的 she was the one picked the fight. +他第二次打她時 她沒有來找我 Next time it happened, she didn't come to me. +前妻告訴我的 很高興又聽到她的消息 The ex told me. +nice to hear her voice again. +你做了什麼 What did you do? +盡為父所能 What any father would do. +我把他擺平了 I took care of it. +我找了個傢伙 他找了個專門處理這類事的人 I called a guy who called a guy who handles these kinds of things. +我不知道他說了什麼 做了什麼 I don't know what he said, don't know what he did +我只知道他沒有殺他 all I know is he didn't kill him +我女兒從此再沒有他的消息了 and my daughter never heard from him again. +她怎麼反應的 How did she react? +你無法相信他直呼我的名字 更糟的是 Called me names you wouldn't believe, and worse +她說對她而言我已經死了 Said I was dead to her. +我不為我所做的事情感到驕傲 I'm not proud of everything I did +但是我很肯定 要是能重來 我仍會那麼做 but I'm pretty sure I'd do it all again +如果他們因為我女兒恨我 so if they don't let me into egyptian heaven +而不讓我進入埃及的天堂 because my daughter hates me +我猜他們確實會這麼做 well, then I guess that's just the way it goes. +不管怎麼說 算是回答了你的兩個問題 However you answer your two questions. +我們怎麼從墳墓下去呢 How do we get down from this tomb? +皇后是莫臥兒帝國第5位國王 沙. +賈漢的妻子 The empress was the wife of shah jahan, the fifth mogul emperor. +雖然是包辦婚姻 但是他們深深愛著對方 Although it was an arranged marriage, they were deeply in love +在他們第14個孩子出生時她死了 and remained inseparable until she died +而他們的感情至死不渝 giving birth to their 14th child. +介意我叫你雷嗎 Do you mind if I call you ray? +大多數人叫雷 Main man ray. +你有在聽我講話嗎 Are you listening to anything I'm saying? +當然 Absolutely. +14個孩子 我聽著呢 Fourteen kids. +I'm with you. +這個建築耗費了20,000個工人22年的時間來建造 It took 20,000 volunteers 22 years to complete this structure. +這裡的一切都是賈漢親自設計的 Every square foot designed by the shah himself. +所以那是真愛 So that's true love. +那是真愛 That's true love. +肯定很幸福 Must be nice. +也許我會把這整個買下來 Don't know if I buy the whole "20,000 volunteers" business. +安排葬禮讓我很苦惱 Funeral plans tend to confuse me. +確切的說 是土葬好還是火葬好 Specifically, buried or cremated. +土葬吧 Take buried. +雖然我知道這無關緊要 但是我有幽閉恐懼癥 Now, I know it shouldn't matter, but I'm claustrophobic. +如果哪天我在地下突然醒了 沒有人聽到怎麼辦 What if I wake up underground and nobody can hear me? +他們還會生產那種內置鈴鐺的棺材嗎 Do they still make those coffins with the bells? +嗯... +我估計沒有了 Uh... +I don't believe they do. +那火葬吧 你打算怎麼處理那些骨灰呢? +Then cremated. +what do you do with the ashes? +把他們埋了還是撒了? +把他們放到架子上? +Do you bury them, scatter them, put them on a shelf? +扔進恆河順流而下找個安樂窩? +Float them down the ganges on a bed of flowers? +如果我感覺到火焰怎麼辦 What if I feel the flames? +但是我確定我會火葬 Well, I definitely want to have myself cremated. +也許我們應該像華特. +迪斯尼一樣把自己冷凍起來 Maybe we should go frozen like walt disney. +不好 還是火葬吧 No. +cremated. +把骨灰放到鐵罐裡 埋到風景秀麗的地方 Ashes put in a can, buried some place with a view. +鐵罐 嗯? +A can, huh? +是的 我不喜歡骨灰盒的說法 Yeah. +I never liked the sound of the word urn. +是嗎 難道你對地穴有特殊的感覺? +Really? +got any special feelings about crypt? +- +- +- +- +-====翻譯===== +- +- +- +-- 蕁香 卓為水蒙 蜀山天狼 Yancey 呂黎 校對: +小門柴 +嘿 沒有 Heh. +no. +沒有 對我來說一個舊的"巧克福納"牌咖啡罐就足矣 No, an old chock full o'nuts can will do me just fine. +"巧克福納" 天堂咖啡 Chock full o'nuts, "the heavenly coffee." +朋友 好的咖啡甚至是花錢都買不到的 Better coffee even your money can't buy, my friend. +別拿這打賭 Don't bet on it. +噢 好吧 Oh, right. +魯哇克香貓 Kopi luwak. +你為什麼不喜歡魯哇克香貓咖啡? +What do you got against kopi luwak? +跟我的品味太不搭了 Too fancy for my tastes. +噢 是的 對我的好搭檔"雷"來說 是很不搭 Oh, yeah. +too fancy for my main man, ray. +-陷阱 +-該死 +- Gin. +- goddamn it. +牌都被你拿光了 You get all the cards. +寶貝 這就是中國 This is china for you, baby. +太棒了 Whoo +-hoo! +yeah! +如果我們可以登上去看的話 肯定很壯觀 Be a lot more majestic if we could see it. +看到那個老女人了嗎 See that old woman? +真奇怪我們竟然會比她先死 Odds are we're gonna be dead before her. +想開點 Happy thought. +當然 如果有來生的話 Of course, she's probably got reincarnation going for her... +她很可能會去轉世 ...however that system works. +啊 佛教徒相信他們會不斷地轉世 Ah, the buddhists believe you keep coming back. +此生的所為 會決定他們上天還是入地 Moving up or down a level, based on how you lived your life. +瞧 這正是我所不明白的 See, that's where they lose me. +我的意思是 一隻蝸牛要怎樣做才能上升一個境界呢 I mean, what would a snail have to do to move up in the lineup? +用粘液畫出完美的軌跡 Lay down a perfect trail of slime? +要聽壞消息還是更壞的消息 So shitty news, or really shitty news? +A 第一個 A, the first one. +暴風雪要來了 There's a storm up there. +那謝謝你的提醒 湯姆 Well, thanks for the bulletin, tom, +我們現在沒看到那該死的 we can't even see the goddamn thing. +他們不會讓我們上山的 除非天氣變好了 They won't let us fly up until the weather clears. +那天氣什麼時候會變好? +when do they expect it to clear? +嗯 明年春天 差不多吧 Uh, next spring, sometime. +如果你們想知道的話 這就是個那個更壞的消息 That's the really shitty news, in case you were wondering. +好吧 那下次吧 Well, maybe next time. +只能這樣了 Yeah. +明年春天 Next spring. +我們現在幹什麼呢 So now what? +也許你的山在告訴我們某些事情 Well, maybe your mountain's trying to tell us something. +什麼意思 What do you mean? +也許我們離開的夠久了 Maybe we've been gone long enough. +離開的夠久了? +離開誰夠久了 Gone long enough? +gone long enough for whom? +噢 不 我明白了 Oh. +no, I get it. +山不是告訴我們該回去了 The mountain isn't telling us it's time for us to go home. +山是讓你告訴我 The mountain is telling you to tell me +我該回去了 是嗎 it's time for me to go home, right? +-是的 +-一派胡言 +- yeah. +- you shit. +你為什麼不管管你自己 Why don't you worry about your life, +我們各擔心各的 懂嗎 and let me worry about mine, okay? +好的 好的 你沒必要跟我發火 Okay, okay! +you don't have to get chippy with me. +-下一站是哪裡 +-下一站 香港 +-What's next? +-next, hong kong. +一套絲綢衣服 還有黑核桃仁冰淇凌 Silk suits and black walnut ice cream. +西藏人管他叫"修馬魯瑪" 雪的女神 Tibetans call it chomulungma, "goddess mother of the snows." +實際上是 宇宙的女神 "goddess mother of the world," actually. +根據傳統西藏語翻譯 In the traditional tibetan translation. +我認錯了 I stand corrected. +一杯加州葡萄酒 謝謝 Pinot noir, please. +我想你肯定去過那了吧 I take it you've been there? +呃... +呃... +嗯... +實際上我剛從那過來 Uh... +uh... +um... +I just left, actually. +我們打算要爬上去的 但是沒有 We tried to go up, but it wasn't... +你已經錯過了登山的季節 You're a little late in the season. +他們也是這樣告訴我的 So they tell me. +-我叫安婕列卡 +-噢 我叫卡特 +- my name's angelica. +- yeah, carter. +很抱歉 很唐突地問一下 I'm sorry if this sounds terrible... +爬那麼高的山 你的年紀是不是有點過呢? +but aren't you a little developed in years to be running up a giant mountain? +過 你是說我的年紀大了吧 "developed," now that's certainly one way of putting it. +其實我去上去過 Well, I've been up there, you know. +-是嗎 +-是的 +- really? +- mm +-hm. +在我們必須返回之前 我爬到了26000英尺高 I made it to 26,000 feet before we had to turn back. +-真的? +-當然 +- really? +- mm +-hm. +感覺怎麼樣? +What was it like? +好冷 大部分時候 Cold mostly +白天 天空黑壓壓的 During the day, the sky is more black than blue. +因為空氣太稀薄 不能反射陽光 There's not enough air to reflect the sunlight. +但是在夜裡 你從來都沒有看到過那麼多星星 But at night, you've never seen so many stars. +看上去觸手可及 耀眼奪目 Seems like they're just out of reach, and so bright. +就好像是天堂地板上的一個個小洞 They're like little holes in the floor of heaven. +-你聽到了嗎 +-聽到什麼 +- did you hear it? +- hear what? +我讀過一個人在山頂寫的描述 I read an account of a man who made it to the summit +當你站在世界世界之巔 and standing there at the top of the world +他經歷過這種異常的寧靜 he experienced this profound silence. +就像所有的聲音都靜默了一樣 It was like all sound just fell away. +這就是他聽到的 And that's when he heard it. +什麼? +What? +大山之音 The sound of the mountain. +他說他好像聽到了上帝的聲音 He said it was like he heard the voice of god. +我以前從沒這麼做過 I've never done this before. +這聽起來真是迂腐透頂 That sounds like such a cliche +不過我樓上有個房間 but I have a room upstairs. +那真是... +Well, that's... +我是說... +I mean... +我... +I... +我很榮幸 I appreciate that. +但你看... +But you see... +她真是個幸運的女人 She's a very lucky woman. +我寧願我比較幸運 Well, I rather think I'm the lucky one. +做得好 Good for you. +湯姆? +Tom? +等你老了以後 記住三件事 Three things to remember when you get older +得有一間浴室 Never pass up a bathroom +不要浪費每次勃起 別相信那些屁話 never waste a hard +-on, and never trust a fart. +等我老了以後我會記得的 I'll keep that in mind as I approach decrepitude. +嘿嘿 這就對了 Heh +-heh. +that's a good one there. +我們回家吧 Let's go home. +你說什麼 Excuse me? +我想現在回家 I want to go home now. +但我覺得... +那真絲西裝怎麼辦? +But I thought that... +what about the silk suits? +你怎麼知?? +帽子不错 汤姆 夏洛克·福尔摩斯 diff --git a/bench/data/opensubtitles/zh-small.txt b/bench/data/opensubtitles/zh-small.txt new file mode 100644 index 0000000..5b86454 --- /dev/null +++ b/bench/data/opensubtitles/zh-small.txt @@ -0,0 +1,28 @@ +魯哇克香貓咖啡 世界上最稀有的飲品 Kopi luwak. +the rarest beverage in the world. +嘗一小口 Take a whiff. +來 Go ahead. +寇爾先生 董事會已準備好聽你的提案 Uh, mr. +cole, the board is ready to hear your proposal. +等一下下 Hold on just a second. +來 繼續 Go ahead. +go on. +怎樣 Well? +真不錯 Really good. +真不錯 Really good. +寇爾先生? +Mr. +cole. +sir? +吉姆 你知道庸俗是什麼嗎 Do you know what a philistine is, jim? +先生 我叫理查德 Sir, it's richard. +沒錯 費爾 出動你的如簧巧舌吧 That's right, phil. +give them the spiel. +謝謝 主席先生 主管們 Thank you, mr. +chairman, fellow supervisors. +我們寇爾集團財務的管理不善 We at the cole group feel the decline of the winwood hospital... +直接造成了溫伍德醫院的衰敗 ...is a direct result of significant fiscal mismanagement. +請原諒 我們醫院... +I beg your pardon, this hospital... +日常開支近2倍 overhead costs are nearly double. +帽子不错 汤姆 夏洛克·福尔摩斯 diff --git a/bench/data/opensubtitles/zh-teeny.txt b/bench/data/opensubtitles/zh-teeny.txt new file mode 100644 index 0000000..ce6eed2 --- /dev/null +++ b/bench/data/opensubtitles/zh-teeny.txt @@ -0,0 +1 @@ +汤姆 夏洛克·福尔摩斯 diff --git a/bench/data/opensubtitles/zh-tiny.txt b/bench/data/opensubtitles/zh-tiny.txt new file mode 100644 index 0000000..cb19de1 --- /dev/null +++ b/bench/data/opensubtitles/zh-tiny.txt @@ -0,0 +1,3 @@ +谁是早餐界的冠军? +你突然来信说最近要搬到这里 +帽子不错 汤姆 夏洛克·福尔摩斯 diff --git a/bench/data/pathological/README.md b/bench/data/pathological/README.md new file mode 100644 index 0000000..92358a8 --- /dev/null +++ b/bench/data/pathological/README.md @@ -0,0 +1,54 @@ +These data sets are specifically crafted to try and defeat heuristic +optimizations in various substring search implementations. The point of these +is to make the costs of those heuristics clearer. In particular, the main idea +behind heuristics is to sell out some rare or edge cases in favor of making +some common cases *a lot* faster (potentially by orders of magnitude). The key +to this is to make sure that those edge cases are impacted at tolerable levels. + +Below is a description of each. + +* `repeated-rare-*`: This is meant to be used with the needle `abczdef`. This + input defeats a heuristic in the old bstr and regex substring implementations + that looked for a rare byte (in this case, `z`) to run memchr on before + looking for an actual match. This particular input causes that heuristic to + stop on every byte in the input. In regex's case in particular, this causes + `O(mn)` time complexity. (In the case of `bstr`, it does a little better by + stopping this heuristic after a number of tries once it becomes clear that it + is ineffective.) +* `defeat-simple-vector`: The corpus consists of `qaz` repeated over and over + again. The intended needle is `qbz`. This is meant to be difficult for the + "generic SIMD" algorithm[1] to handle. Namely, it will repeatedly find a + candidate match via the `q` and `z` bytes in the needle, but the overall + match will fail at the `memcmp` phase. Nevertheless, optimized versions of + [1] still do reasonably well on this benchmark because the `memcmp` can be + specialized to a single `u32` unaligned load and compare. +* `defeat-simple-vector-freq`: This is similarish to `defeat-simple-vector`, + except it also attempts to defeat heuristic frequency analysis. The corpus + consists of `qjaz` repeated over and over again, with the intended needle + being `qja{49}z`. Heuristic frequency analysis might try either the `q` or + the `j`, in addition to `z`. Given the nature of the corpus, this will result + in a lot of false positive candidates, thus leading to an ineffective + prefilter. +* `defeat-simple-vector-repeated`: This combines the "repeated-rare" and + "defeat-simple-vector" inputs. The corpus consists of `z` entirely, with only + the second to last byte being changed to `a`. The intended needle is + `z{135}az`. The key here is that in [1], a candidate match will be found at + every position in the haystack. And since the needle is very large, this will + result in a full `memcmp` call out. [1] effectively drowns in `memcmp` being + called at every position in the haystack. The algorithm in this crate does + a bit better by noticing that the prefilter is ineffective and falling back + to standard Two-Way. +* `md5-huge`: This file contains one md5 hash per line for each word in the + `../sliceslice/words.txt` corpus. The intent of this benchmark is to defeat + frequency heuristics by using a corpus comprised of random data. That is, + no one bytes should be significantly more frequent than any other. +* `random-huge`: Similar to `md5-huge`, but with longer lines and more + princpally random data. Generated via + `dd if=/dev/urandom bs=32 count=10000 | xxd -ps -c32`. + This was derived from a real world benchmark reported to ripgrep[2]. + In particular, it originally motivated the addition of Boyer-Moore to + the regex crate, but now this case is handled just fine by the memmem + implementation in this crate. + +[1]: http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd +[2]: https://github.com/BurntSushi/ripgrep/issues/617 diff --git a/bench/data/pathological/defeat-simple-vector-freq.txt b/bench/data/pathological/defeat-simple-vector-freq.txt new file mode 100644 index 0000000..0c6e1b1 --- /dev/null +++ b/bench/data/pathological/defeat-simple-vector-freq.txt @@ -0,0 +1 @@ +qjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjazqjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz diff --git a/bench/data/pathological/defeat-simple-vector-repeated.txt b/bench/data/pathological/defeat-simple-vector-repeated.txt new file mode 100644 index 0000000..497ff86 --- /dev/null +++ b/bench/data/pathological/defeat-simple-vector-repeated.txt @@ -0,0 +1 @@ +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzaz diff --git a/bench/data/pathological/defeat-simple-vector.txt b/bench/data/pathological/defeat-simple-vector.txt new file mode 100644 index 0000000..54bef6b --- /dev/null +++ b/bench/data/pathological/defeat-simple-vector.txt @@ -0,0 +1,10001 @@ +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqazqaz +qbz diff --git a/bench/data/pathological/md5-huge.txt b/bench/data/pathological/md5-huge.txt new file mode 100644 index 0000000..335f4f5 --- /dev/null +++ b/bench/data/pathological/md5-huge.txt @@ -0,0 +1,4585 @@ +60b725f10c9c85c70d97880dfe8191b3 +bf072e9119077b4e76437a93986787ef +87c0a0816ee34adc6ce9793e5a5d96ed +8880cd8c1fb402585779766f681b868b +a581613063c95fb4935d19159b0799b1 +644aeead8a88ee10fe6cc645e0199f25 +82ed9492853cc473a4e8dc7f673d34eb +7b0ded95031647702b8bed17dce7698a +76309e72a14a18c4b81838475e42d0d9 +f892dd1234a125341fb0a360e94a9d90 +c3f4404d9e95bf96376432c64dfa8a09 +ec7a597060023e6ba4af40f5ea7ba345 +3a1427698e2f4185d41b153131fb241b +2b2ac0980b42299be92fc2d87d1afbaf +76a113065092a9a470cbaf987b4a8de4 +98f539f0a304197d476373609994e67c +7433c432b96c3453472fa517e22038e0 +be1e4fb922301ea9f1b1216060cde087 +eee523a657c878eb29b5d7892124d3dd +71ff2f59c91dcb47ca91f8e09b855d1b +886639cd08e7422f60bc5eac67bc342f +7313943279f4e4534ed733f98ca863a2 +5cbbdfc92604901fa27100ccb797e75f +e4c4e06b5509ba7fdf5eb18a840ee4cc +f2dc435d2f5c9d2c203c9a6640308afe +a82b620e3d0ff46272c794c576f9040a +30f13bfe3401077e774cdda8bce30eba +e0e9447fc5e79a10575951c5daf34243 +b31d8967ca350c78b48576fc560f00d3 +a56ffd9f01fa749377cbaea011a57365 +de88250cdc0dd74177898dcffabd2e33 +cdb6ea9af3024dda46a1de71399186b5 +008385ed0301676efe2b9fafaca8b53d +6469c4cc93b804a280aaea80069757e6 +c1b09bd03a06efe7cebda886f95ff805 +e9548296b88648af18575cd711e9f47b +c7536598d6ff0038f4809e7727c52ef1 +240ac67e846e34a271d2556ab53512a2 +6c4c7897e335187e887b28c7a1a7c11d +822f6e178ad4734d1783388cca2b8ff2 +5d512a47d9f8d72cb9985a3eae0a8dd9 +bcaf33a6362a8ce9021391f8b52911d0 +f606400911af58f4f64de39892651bef +6f59def3ab19720f4680aa146812e0fb +bb4f79188a199a9454f93c8ea0a03759 +889ce7d6998cc10f5ff30a711fa3a350 +877888ad2655545c8ded167e63342150 +e741a1d54e5314ba9d08a9ba5ec27725 +258def64c72dae45f3e4c8516e2111f2 +1f0dc792a6ea9b2a28d79b6a588a23ee +63ad175f81016ceb978310ec21b6f5d2 +9d23dae2943cc97d14ec52785e6d08f3 +797c3f63b85f4f84fd0180089c970aa0 +b0df637c47e084aca5e9fe2f7dfa04dc +fcd76b5bbb9125499d7f0b3d168b6779 +c01c09984b9485cc0b822dae374fe5dc +b867cb6f00785fa3a9ad05e519b502e1 +26f5fcaa52a78b24770b3c8b2ced1270 +8657feb48dd552bb4b83003e34502bb1 +d1b20d81ffca1998d52000ccdc786e33 +c84f82f6fb4cb4947d288c2a5f799543 +0f38d1a543b96eb8d34b6fcdc9227445 +a4a391ede878f0bd1d8e0d0dee3659c9 +294209bb8a8bc9feb728c21a5d408cf1 +3abc35af06a4f4e894351af37da2ad7c +0efffb235da08727472ea69661a5b20b +bcd1a37a1a2c1348a76b22f8e2a18dae +d40f981befcd46cf54b075006baf1d95 +25e94a6564aec052dc88e9f43a63c3c2 +69a904ac9adfbefaa69a720e4c13780a +e0371468885829d9e686dbe15e2e578f +42973fa5b2696b23af739f73656c02b7 +2832e21254f4d3b0ed755a827d07ce58 +fb294d5e5d46694f74bd0fa498950830 +a65e0310033901ad76e3b05b5737531a +f8b8ebf2f3fca7e4999cef4eb839138a +5c8eea92f16062a5afc573043e60e274 +92c48aa4e3056e191c74a67dcb4cfe14 +eb0ec21a576bfac9c3bffe5879b15093 +f7d0e1b9fc3f163b363dcd2397a7f869 +5325905f99354c744ad981ffc9e8425d +2e593a7f2c3f2e5fc0b6ea1d4f03a2a3 +500d22de1b49239e5c67119d65fd2547 +218cb21622021006bd78f59596b2c03f +7ce4ef45b7c82cc0ea6ae5ba5d9eba1b +59b4c6f6f177674f94a7425a90c5196e +94a8593a689786dc5ecf7829a50fc19c +9602ff0475edf708f8e6a32c0760b67d +b3f20bb15665ba62380c2bad0823ff60 +8a5469910268f12754b160aa784d3b87 +da09e91459719b9f121b54e844cadf37 +d6638c2906f5d155f49e9278b47de829 +b561a32bd5802d379d01024ffe71923e +dd55c0c4871d184d250888915e5a18a1 +0e0b7f934de20fcc39caf2e81dfa2048 +ee5ab84f8fec9fe8fb2dd0b042808d52 +a6a9fdba23057a1dd5120b061e8515f9 +79d1f9df0adf9a1768f23c754d96bb4d +ebc8b0c58480a45374e89a9af9974a0f +2027ac6cd4c69d7564f1f9058b350763 +4e410b2e3d27530106b3a32d9f89c55b +abd148420a09b514d1f22464c6d2a2e9 +54e0f1b148db701b0e4ed218f2b734a2 +f49f7c2a99efe9bfc0be9021fc7a7041 +061f5d84c9831384a7fd29024d513108 +8c6ad61dd7c0b62e2a4c69e986f22377 +8cc5700dcec9acfcb5a2cf53437c10a0 +62d44974e2e296c42600ff067bfb2af0 +e544363876aa91c17334fc5148b14751 +34af6d580de3c6dec7ea2a0b594895b7 +f3d37d192079706862c46172ec96a8b4 +a1586235411d40cefaa4fec6c7d5a0b1 +6213c6bd99cde9f4b41cce96f7cdef94 +3119f6518eb8df5066bb2f9f6ccc5e61 +d34f66a023552954628ffd32b7c02e30 +001e01779591c3dbf3308f23355c8228 +3135e09770680a5ac905fa0d0e9ff773 +0592e796510980e915a6d5d4eef9b8d8 +5d0e87ec2e476bc61a25b5569fb43209 +99fd6b62bc270c9bc820dc111f370acd +eb41307a248a7d11b3999356c2831d6a +b86520e700cf383b6d69d463e4a9d81b +9a929dc52cdcb99b173e5183a3b7571c +d809a607f1feb76628431e6d355ca002 +2aa6dbe649c0237515c016619ea517c0 +3561f8c06784a5d67cf7d5bc89bd8ce6 +13901a622f2b2737658a9a8177f2031f +ef09247a0e23cdb6490d96a68433df3d +438049e5176b5d8aca1a066825482271 +aab170ad5b1651ca6776b12012a410df +798efc2e97cf3e2050d20f0ee5f00f9d +c3c6607fb0c1741ebe3835246dbf340a +25087751dffe29fe8dd72429a748eb04 +18fa1e27086d24af806d77d104756374 +869cdfb59eef781ebd6a3b78e43344e6 +2bbcfa3b295b759983ad8664cd388258 +1d5e22119f6b2bd06a4e461492dcbe56 +67dad48b5a62a151219620e2d7949f7c +32720294f6471da1d3bbfcb30a117a93 +ece3d9b6c3dc8de60adab39377db1f41 +76a397316335e4615acd439e1b7a5edd +393be782bc856e419fda05ea68170287 +c125dcf20660b5d3ec05c8733036e13e +4df9cc121afe1c00de4e9e396af4cdb1 +e149f60955e1f072ed4da29fc3c3752c +defa66ffa143368eb9bf6e28d9f36ed9 +366dbc71de2d7a1f6850baa739ed4059 +bc0b7cf32aa5e8e798d43f4382025715 +ac2c0c6ab5fcc23914811f6c27051068 +7fe7ace44e748c78651b19d76b6edb24 +7a6bf8fe0526d4e4a68b08a1756f6cda +9270f6ecabca29c8d25348b032f83976 +95845bbf4f294d4480e74090d1ed25fc +b35c38185e97afe11d3a53143c57d193 +8c8a4b4242487b9da61517dd39462710 +53fd2cfb1985189c8ac17f067216dddc +0ae32fc4ae993d09dfba9f0545e27d85 +c7fb8c988ff47ad625643c3bda727e3b +9772c4c2648437fa49454c62dc22af84 +667d5fa72f80788a5ed2373586e57ff6 +817a2ae9e6efb8aff87b1de5083a9181 +82e2aaa1bf110953161a0de4f7f84243 +e051015b7b858c79a9715e6e218578b2 +4f51f4c5062d1081776190e9a1636184 +9f5a84de4e6df01dc18a96489d54ff4e +9f13eadb35170b221815ee83ff8c64bd +9d4babfa77ab2bd1a3cefb6678e0921b +ba95f18e030b2f35c9cd41090518092f +a1b8c1873a66f158f0aa1584c9b5ef55 +c9350c9993b20a05bdffbeef153bafba +3e983042bce1b0c8b07c5433cc04dfc1 +57fcc5ec8be65ddc3f4f9dca56593346 +07ae20d0be677d0b35e9846f79fdb769 +12fa30d9fe153c0f2526f3da3f7ff0ad +421aa59085af3de8b07d14fc995e8566 +6f80dc929ddca7ad9f980606cea38bad +5e930f4078ec6770719b82e7cfbc8c73 +6c4d8a43cc2a976ce1de2c7bbdcd426e +c50368ae5e839e9224eb0947f06fc605 +b05afa5a38af95de08d3ea2b3bd78a84 +765d18c2508923e7de70b47fbf3b183b +5bccf43a5d06be572af2bf934df0aa59 +53fb844b56da888376ba98952e44165f +3e9ddeb7e698a4a5a5ec158ed2df5bf2 +19bf32b8725ec794d434280902d78e18 +bf71f08c7bd8624a228c05556cb3d8f7 +b140670bbb9e4cb457b941ba6eab9750 +f31b155a3d4f446f6b696077e8ce477d +3740570a423feec44c2a759225a9fcf9 +c50867a39874650a117304e749b4dcc6 +ba05a5b4d1c90e69b6da7da8b50a5c26 +d1ef05226d77bcc2d12f52b057bdc1f3 +1e60dbbad25e192a1c732411c017ae8e +3a5e0978ba80e9630664343e14895dba +7ea9fa4a980974c9f5c1cab9b0491de7 +0111522949b56c3e71bd5be437bb0fd5 +d24c711703fbfccba5db385176939345 +4f8cac94e8bc1f17fc4871ff26abdfa1 +d2b0651f86424ea8e74202fd37745933 +3c56ab9d65e1a1dfd4a6394026cf335e +ce806d916373a9bb80565f811e4c0dca +3fde6a56bf0a7f0aca5eb3f7231fed74 +7e8a1dc61a3c8e9528920253383e6fa9 +e8840c312112f9aa7568a77bfebb983d +98984e78fde3e2c9ad475438dbad815b +7f4d3e34dc8da98e10f188d7f14c54ea +2a97dd5683fe2d161936007b4e8ac1eb +e24281fa015e84ee99c49bc1ed2b073a +5adb1c7b2ac920e80b7cf28cf814abef +72f5ac05e0bb374a18d2fad9d089faf2 +2e0650a16cb4feeb9b5d7160027d2635 +8ed6c103906ab21b27fc2003440ba640 +33a3313205e7cbe1cf7fc3936b7f8067 +0e77d88887f2557bcd7d2b8034d91458 +84cfc36471a437eba211476c37dcf42f +f14e1cd3fdc24ae20c2a195d67041c35 +ae5fb44c28fd9df392ec1417c650d745 +ae92fefabc8e5d44a6a6ab78c5e234ec +162aad3402a59ada80fbd661aab729e9 +65059a3c815870df72e21d3f53819582 +aac3d6e704a2701320f88b62cd19a567 +09db734dfb9f2fde44c564ff3ac43727 +d1ba4d7f5b7689c8a8a2e8aa2b21be3d +3922d962b6f61c0aea39b0ce1677c5a0 +74949ef58bcb1bda3ccfbb1647de6e53 +6e06819ed31be0446adf1cd22514761e +eacbe4d1b2dee530eee7460477877c4d +9f198fc7cf9ed327ef12239ba9873e90 +702d7ed678164b4c7efee1358abf86ab +bbe80e26b5e6b61ceb584c99ff481adb +db7e8550fc25318cf7120af46408c62b +6832760c12105560a2bbb16eb556bd7d +8ac780c05999fa7f1605d272218449da +12f872b3b1e4120dc4ae7eb6d5051b96 +b3de8676221a4ef963de3d0f89a8cc98 +35ec570b5cf06db442d24817ba47a4ee +bdc5e31ecb60788c39fa8c9939c62d79 +573e8d0326f62b9a8f23c93b35093911 +e757cb8c6e57bd2f8b80eaab8f94e469 +b1f1c487c1dcf8c4d3c02a0381259873 +5a02255f16aaa1f2b1c47846fabf735b +a7cf24f7419fd981d559528c30eb815f +90978c8edad36d5faac226d8edc50226 +e1c44f9dd5454a5dda529f03e4843316 +b4e3ac6b7d6f0cbcc41f1314798fe45e +b9628c4ab9b595f72f280b90c4fd093d +84f3aeb7ef19b63b53716ae23dcade51 +12884e5ca2c9e27244f60438c02b5698 +60e20a6f0936b9805a6969ce96096dcc +c24f1a111cfc497ac7185d7b91f03422 +18d0cd1c73f72466b950e60760349cce +a4d059f7d13a47ad13fc9770de044579 +d7a403af9dee898144ce96676e3adb52 +6988f9f58fa9d01ed6c147466f09db29 +4cd638b44a9388b363add2905fb6240f +af5db9f454f570d6169dcba4bb1f246b +7974e7ad4633a7426fc13b3cf80da175 +f9057d95c99a4e287a2e903299618ba0 +cac7c16b018c62f7aa3b3d154134cc1f +53176aa91b2381819e1d8da7a765f7f5 +0ea04045156ec98752d69ab7c4b3f215 +e83b65d87ea5b50f88ec4829fe61c6ac +14f4e2f5123f67357ecb5a475255c697 +0cfef798bebb03ca7f9280a580478d59 +33c595f42483b4ad1c64680b32ef4b52 +5003509b9e91c3bc5667ca217ef41da9 +9e603676ad3ad683dec432a17d86e47c +c418df151dd4046575d7c83ab07f7661 +8bc5026b8b381bcd5915390a649d4671 +bea0094b9f201178db1b183f804f5de6 +2dc23baa9c532eb4a19973aeb3fc9292 +a3772124741fdf4e8a40984bbf4dab0e +d1d940769b09a44343942c00a814f510 +ade9ea04fd370026060d0d7647b5f087 +86ec01a566a2cb1164789669bf131be6 +2a9544b78ca6c8798091a6a32e89e8e0 +32135b36fd0fdeb23da1c17f7b21c160 +34db4741071c7ba0fda95ae6af6b5a78 +1c7eff6b97175d6770e781543513793d +bd4bec0de0eb14386554e60ba07824ab +611b6d5d3dcb7b0fbb50fb893a3d8438 +26cb36f0e04ea6270b331d352e0ee694 +4724c7a3abad11c8e588a654052b963d +585eab4bb8b80bd5af2978f2c973535b +c954d75b8b9b5b6cb8dee07b8d0ce1ed +64bebbfc021fc814c3a9c932b72215e0 +6bbecd52253d9934ce2e4f2c6e3f7b30 +92a18b5f4b93a54360fd7c3126c8a631 +8381c99f0d912d037a99eeac50363a7b +029f03e6624a67393424f5c0cb5b1087 +2720be193612aec156b3836018d89468 +81e6ab76f31d7069d83f2a500164d345 +411730635b02ec4c337d87d7c290dd45 +8e01478256c3b8110de5c6f01a767fb1 +9df6d2f14b7c14871c415ad0766142ca +f2e50d503396c297d13284d7849c9846 +510cff4360eb764e8b044b33503dd67e +75c345e1f775c5187a05700aab2dff98 +e8e4bbf6b9f97db11a5b23ddc7141701 +a943f5ff506ee6198e996333e0b672b1 +71527b1940635288412469089ccb3c64 +451e20aff0f489cd2f7d4d73533aa961 +ed2e2125f798e813ce37e92add49bd14 +19a8ded47af288b084dc9bf943a3dfc4 +8b485f74d3fdbb556da5a54885784e7c +e8a9d66a3824eb1985ebe2da5d626660 +4433035c9fedf71d01254faafa9b8850 +375f498d74e9d6007b53455099293822 +9639d6b5936e156abb9eafb2ee3eb1a4 +e8a3b06fb1d2688cf841a0a397714d32 +c88aa9bcff4f42f82ba914087b6c4f57 +276c2074d5334a6b9a3f84173a0be62f +f6728fefe0aa40d83e43039ad2fa990d +0f186d67e3ea726801526e6bd45a1b6e +db523bb90f560bf490cba45f26dd44f5 +dde283e42547027b70dd441361c89051 +a8bfcc7fdd9414c7bbddbadc8ebcb87a +3da2efec9e95ac38bfbd63a8351624da +6bbf6fbd2130b55b416f3c5f83124c04 +37087753a8af8805dfd02b99af1da7fc +912a74aea60b59718b56fd6a2c2942aa +ea38813ca046681a19efcefe5d2136de +005d7a55ce42c927d6ec4046bf5ec4b4 +645aedc8a285fef107aaa656bef82788 +7e980571597eb345a3edfb5f0b090f28 +3b5d5c3712955042212316173ccf37be +30cf3d7d133b08543cb6c8933c29dfd7 +be5150997fa0e113ecf457f099fb35a7 +8f877cc990b6c05632cbf24c02957e28 +b7ee3531c0640e07d45978804005b1a6 +12a3523941bd398900367f4a18a97562 +4bad2dd5c709fadeaee226acb4f65b48 +e5aeeb730fd2f0a69491cbe27585d123 +75b7355c2f04cc7f08003d029710a99a +c474302c13743e0e5632fb33300ba4b9 +ce771bb33a2a445c8e616a88ec29c517 +e69182d9fce334d351d1e0875f1fd871 +4d5ba9968ac99068d8b126e4edd447b3 +907b699b97abc727c0413aa86e2792e6 +145cafb4dd8c932143b72b08c7d8b6ee +8db8e4358f1f4480f9501ba3f82be09d +fd8d01f2d8226596278785a30dfed968 +146cd3d5e33fce539409b6411d9ebfd2 +e8c7a1827eafd0c6559fae70c10811ec +4491010d383d0a1a9bb70f8dc08e1aa8 +55b41eb3720ddd2ab0a37a77afacb26a +0a5387a0f82c4e5613d5a7baeb4f15f9 +84c805ca4fc0d0d9e47045df156b8d08 +0c2497c8d15a4319fe5eac2fba0975ca +bfacf1e22e8e792a929b74f5872f32d2 +90b3a5f70914589b360682c99456eb88 +0800c1ac3525303007a51fc477d21576 +dc34e14bac311c83916e86ddb09ea3cd +ab8d71b3fdce92efd8bdf29cffd36116 +3dff01cf122e6cfb840adfe0623a7bad +e7e1e4ea59a5b16f5eee88b81d8d041e +cc4922508743906e8b3f14f6dddb95fd +9c2cbd504ac61ea0db87a785b979ecf8 +81169b83100bbac4b44e4209e007cf05 +4f3dc24fb38437da00ac129987b6f23c +e5d0453e6d24c001a44e3f0c2e30f61b +2c3efb2c81465caa1956a82cdac0faac +9f649d576069d1b95773945d74e16a43 +631e6be633e541829635ab556a43e9ef +18e21ea395b983d41b788db29f300323 +d9bba6f9f1bb8fe13d9859bc23dc7e0b +3cf29afdc796e0ad36ada4abf96f3ac0 +ebbb5bdacb26fdd2cef48867e4a59558 +489715c5608f76b1b4e64c631d813a43 +35eb7f24570d077b889fbc684c1f985a +e9183f3e37c8bb045ccf033fcd73d4f4 +5532a2e760f3b0a8a96fb5103dfb4b67 +0d7774aca946c050fd8555e4b8769c99 +cfa0d236bb656e502d788202aed18449 +ff62741ba96c0b0501ee056d41c5237f +d8ead32e4da9fc0b1de7f533af386ac6 +8c7868d168fbacf6262f4631f72856b2 +70e97c324b0aeef136a2feb9baaa841d +7d3915f62ba14841036d7e5b9b8af65b +b3ca2da3b9ccd292662871ac36ef9efd +cbea9c4d4ef5f2e5c541e59bea296540 +6590b33a2eafe467c81e87f27338b08e +3b4df51f8f8f3229cb4b950d4f8b9175 +1c73c19ee0cf6582ee8d458bab1e2330 +1e59dd43bb6eb0ff21785aa255074fcb +224c7242ca5856fc63f2ae749062b105 +6ab8ac4cca99c0c7c9629adcc1c67b59 +3a3f3b6e914f44b37c6f00d17bffd76a +b35e5cb85601b7007f9eb635200ea488 +3156879b07b391d80de0ce8c437bc66b +85af4f7cb17735c516637445d513dc72 +6520bb961105290269b698f318edea99 +653f431628bae5b65c97afd728406d1c +4997759aaff28ee8e3afedd462ea3a16 +f7380998b99a23af0c4c4edf3e923b44 +df0e9fdf9333babc4a493eafde9630cd +adcb4621dc4a49ac5da1b073c4dbac21 +419d7f961416c4958dbd1b2dcd24946b +9c0da952b0fa5e39faa2f9a44b2b581f +a29bec6f5385ecbc761a9a047770c9bc +0c1c633cce6bb150afabdcd84ee4ac9e +ce3e4920b2764ce657ba9562292dbc36 +e066f68b3b991cb80a9744f56c798ad7 +1b6ac132209bf365156bedc3bb31e4a7 +cbf19975f168298c0d10f1b5380ba931 +ee931b43b77590e3ceb5c5c2c9df7a40 +fd9b17cc39d1cd808aeb629cddf8d217 +d9e44ab1a54eadafaa7ceff2bf6eda6e +dde264268c19f8fc2e64ce5cdfe24c1e +600fd931a2b28640280ae28bf1b31d81 +5a4444883a12ac73b5c074f24d7148f0 +5edd1d281b7e630f3c642460454ad14e +a11771b4da6c579b5cf6c2b0fa05d918 +7f5e05c17fc87ee964c612ccb4992642 +c459bdc27fcaad4acb4f51a9336fe7f3 +594a5d9356a8defbf5dac10cc06e9fda +4f98663772651c870e911982e991d0d9 +df0f926016e3ea1f5ffbe27788756898 +5a8a490b9035f1641149a15c2190a78c +85814f1e9c8b96a7199d1caf5531d2a0 +cba8daf74a2cdb83b76172b834dffa5c +ef505646c3218799c108906fe05e8345 +7e4d192900b29565450a90c350b1e7a8 +b55d448e88212f8f6ff3e6949e230d0e +c3a7806aecf1bd627f50d2c4bea5cb4f +1cd03c23edea3b571f3ede33cca21618 +c4f3d4eced61c6d57ecd3dd30791ffe8 +00e26edda4f39fb757953521cce74bd0 +64877f73ab73711f107f982fe16b66ab +19d955d1dd433d656b63d2dc267f3197 +5b02e2b85864662aeac6c0960ca6698a +2cdb0301c8e628a0503ddd7955efc9f1 +e4ef8847482d240d0a3ac612876ba8d1 +ece5a95b7001144527d7ccc645b6f29c +ccbb2ca3f38cbce9cda46767b2ad4516 +139c7130afacfdc952511c8979e1c4ab +8bccdb5b75987b19e5ec76bc2b285ed5 +475bcbf75f895f35f28605f0c94ca801 +c647a4a59653d8e296090433da7e26cf +7184935a166265c9f5e953482d3d102a +99df69f80e72a660346459fa63c31fd4 +87e0ba451e31e9f8133d684e924a3db0 +e1e790cbd81f5ddd9805764f24e36ba6 +b79e6957f5d6abefdf44cb317fcde740 +afa47615d8062713f2e07106e306934b +885b142d558300384c58032b53948abc +882a65083dac96f07ed4c3121f44582e +a63d1c69381a57c6007ace7215dcae81 +06fc88f1a4b29d7d1834affa8f8f3190 +a49547b8fa61cde57332fdfea1af18ea +3aa2cd35731e9a93e79fd1cde1a83b46 +39bf622a908b8b7772730b2402c0b974 +6205aba5357d5f5a134c269051da00c5 +d5ef04e2c7c44db101507e222496b290 +062d2b045f09378ceb59814098d27137 +6da70764e54687afd113510668d4930e +590b6c26778995e093b19cce11a28be7 +798e5e50fa3f5c2374d833d78a4da2d3 +3dcfcd4ad7ee36369f216980ce74d57f +053ae3fe7ad9cba05fc4247c5a334c93 +2366aba7b0eb699748edb25f514a7cf5 +a61e73978d2f471e5fdd288a2ed21398 +d30bfba83a84196423735e6eb604561f +2524f24ebb13b60f724d8e1f5857f5e0 +9a944aafb565387318ca04b7e60a5a04 +784249cedf45926260238a7b0533f495 +8e7a3dfe74492f7aeaccaa266d66c05d +e7c8fdfc609077984e2fa74212f6a748 +75907d8592cfc66fc06bc641f7dbeb65 +350c983f5d4be34834c3a7f826f82218 +5ab6fb8bc4e43974c6e06df8c90d3848 +ef7ecb543e4118f66a32e385f01187ce +3b429879780ca7737732b919fa0007bc +f68db142742c6ee83d68f3c8d6f13070 +93f17cb45a171ac173a7196f670a8339 +7834dadcdb71e148646ede9a42e7d1d4 +b63a2720e9616c4892b7275de8a305da +3f4bf553ce7fb7a748434863d4d5fb51 +d07dc549f06c9e32a33716553dfbcf4b +c737fe6f4f7f3652f660c6f647770f2a +1bdaf89255fc5013f0105bca68fbe3af +8add954a2134695b9cb3cc945fb9024d +dfaa66a6b4a619f18cf65bebf1b13d20 +c9f2f2f737a681ace48c1f330a8559a0 +987ddd03eb3f374d0d60e5d5b53852e5 +6437dbf5334ade3d492b69993e166f59 +a6d13cd69feab44de1a69a0221b0c575 +2ae6e105676f63934631a6c423743b20 +c9bb6ef03eeb2d87220e5250cb5cbccb +1725903835e8f0974acbb8e9031dbe98 +1b454cc4ad133b2a5395f5e969aba718 +5fbacc081126c48528341c89b877de7c +5543471f94fcfda2293d0b57e089ba1f +155ea5291f260b562fd70b20e64f08cd +2cd6ee2c70b0bde53fbe6cac3c8b8bb1 +b39bfc0e26a30024c76e4dcb8a1eae87 +21f241cccaa5cfa33190f56ff1510e37 +0a8bb56fc873c195bf7117af925c7f08 +b0fabbc9cc1abb944e3a4862267710a2 +9777e4cb6f78cf294c754fe71f24ca66 +7e8853a8645f6d6926df9a789efad80f +438dab4eddb2ce06cfda8778a0e16f81 +57c3808c5f394907f866d61f2d005893 +168b734173a337f5d513117e1fe433bd +6e56a420eb5f31c3dd8491872fa2d687 +655d72b032b06c02b6c973eb220bee1a +a349df2f34eb19b2983867796e011047 +660a21f8821c74d20587395c9aade447 +353a3c1df73c9e1c2caa2642c21b68e0 +6b72b1396ec951a35c2422f8d6e53e4d +72ab237210d032602bda88dcb4b845ca +2caba222b310eecbaefc511ffe708df9 +a4fff2b0beea011aaf5dcf0635a13b6d +cb1c057858afd1df5d96d199cafb1910 +30ee64599c34277d9cb28422a83381f4 +e76b25a75aa6fde9b13bb76dfd60deff +12a36a073da1482933e42a7ae789546a +a07d11cf317fcd61fd2cc1c482d92348 +7ea70bd4da4754db45b52c36c673b75b +f25c56c8372366cba86959e164da7380 +632217606a5333bd4ace6fcccf6e3ebe +73b6ce9500f783c59b1b739f2fb33ca7 +64cb645eae26cba95123cc8d81f44d90 +f7c4ef052eaa1bf8baf1d59f62a75c7e +fc7ebd1688f22b85ae243f2852a2e850 +b8d92886fde9201f6fe55dc667efb694 +daf45bab624ad7d4ce0f30b2e505ecbc +3757bda1c2a5146e2e58fe8bd7b3ea5e +06eca3bac3cec0b51e484c7288e61dfa +b8596978550a171a396b777057a53f16 +4146d121df055920cd2a1971ea0c68f3 +9c535410c73287a9b25a175d7df7af52 +55ffebfc109f2adff3117c9c12ad78a8 +42e7b6f9f73ff9c0e8d94753f3b7f4eb +2f300505b36b9cc5782db7e1f3409beb +d14d804f4fceabc77688b85044e7ad79 +6126eac0fa4a9f14b608d1fd75f2f833 +eabc75344b4cd1c04437f8b02e9412bd +a069a475f8555844edd07cf607547b59 +0a8d5195759ab66db4fb667f50f8c654 +f0300603ad3212b76a3af006960a471e +4bb31e1ce88a87a73fd7a5089cf54430 +a245ded7bdfab9e8c89351a576e132eb +0512553f40c5fb668b9c87d3c584b695 +9fe0dab21dd5a88f15caabc04ba921be +188dcd03b0287a162ddd547540b2eb74 +c13fcf332f9e43850422ec213531d222 +65e9d56a653a7040c681c30f472d1adb +5d4bb9c4f21f64970c49d0929e94f335 +a4729875bf34abd1901ad0cf5bc3a83e +582dbaef0ef6d6e1d1ada6dca3433cf5 +ec7f11b78c5d92eb5e27c294c7512b47 +aaf6aa594ff8675c7bea8e4f4513e6ac +870c06c00566c4fb1861bb10f34d1904 +b50ca9d003ff7611453a2f066eb1b949 +172a565f1c833634fd38176b4934e9ec +0c22f99bd4736d8ebbb0ecda75e7b254 +16277831884dcdd76345feb8ec873f04 +3a9334fdb39fd04400e4163ea4e3ef96 +0ac59710ee0bd76214e8bf8bdb5913a6 +bae539678db1c2d10aeca0fb88fab5df +dd69b5ce06c72e17b9aae7c8bdff212d +c8b2d0a42ff593b24fcf71f4409e94e3 +d787b98a724e5507c0aaf771d21b0707 +90c2e3f41a95f9fcd35174efc60bef4e +d63b21b1c4e41c138e4a1bc56e69de52 +85cc946febe51aedce1e449c8f85ad37 +b346244cf4e3e5622e5f4b088227a8f3 +162491aaf3aeb4aedc1a57d5c8d9e03c +7842933040fe211dabcc744273796423 +f3886e4264a02fcd3f0c8f7df9900d06 +04b0a0b4ae28443a21696f00f84fa041 +0b815c7c8313884c6b5a62c742c70f04 +e6cfd032e8349788ecf88e4b399c4697 +37fbac1d00038d4b23c48ff99416f620 +024806f2fa97902441809b55769a3504 +ab45692266285b0e96c6e0972220f445 +ec1bebaea2c042beb68f7679ddd106a4 +8324097cef4071d57ed0598d79c90454 +f2f43598425351e9f8ad38fef569861d +09f8d77d81471c6942d29bad3e877e3f +820db91ca24e2a85584f94ee8ac38a44 +910158dff61f2e7e3da9c50f8db65279 +36734ac8d0c7eb30975d0fd06c2a829c +32560b254cf740d40ffa08b88966aabc +c463e91ad6440efcf637a78054a11e06 +df986424e928faea635b4a184544e060 +9a1a61384c80a1b29d98d2795d72d1ef +dc0101afda6cb162a3637a91ca7a827f +2766df3ec0af8302635dfc78667b401c +2dc01cfdbdcb268cfbcf04f63527e762 +8671f7a34351d45cff3967427eebc400 +5e9b13ce8f6c99f3f510756be58d15fe +84cd2e898a12572835ee037140b08c08 +f4adb0274b7899917dc56079e3afeeb8 +a0780fb04e1ad0cae6fe5c95a049bb60 +472aa0a968778d3e7d69602a206a27db +bea14d5edce519452205a1f64cab030f +ec993e37366b1a07cc91b851f08fd80a +4ded49b9cd7972b7ca94ef9acb8fce57 +ddf9f78b3b3e80163db7175d75745b60 +7bec05fd83f3383338f6698d02654090 +ce2b608fe9b88c5a262ff3d471e555b5 +a5ad12eb6447538f19c5182a390514fa +3ac0e8403af6097c14e8083175483f67 +b42d16b09e2d87464ce31035600caf54 +18392125c194dd5cdd44f0215f561126 +8881311e3a950631029f84587e65a942 +023c93b041d7bf418cc63004a6b7901c +3b002f86d83e3a588cb4117e67187d46 +6f66ac531eb146efe2ec95860432cb85 +9925932ef174e7740582468f85c009c2 +79554b9d2cebe5dcb5e7b0850a71990b +c82efc885941f322df48ac4ab17e0d8e +4270fe89cd843b7c89b25bb7a4f7c8bb +3b1b1171ef7ef0fd8496239f075ebe50 +3b0811881fe50b3c02dc4d88ac6aebd2 +39496aae59747762fa8afa07eba66604 +20a882c5c27d7d7200ed5f431204314f +d04fa11f7880f330c284bff3f44f42fb +21f28a21be425954db1b9733becde51c +a09ccac39e223c74d65475c6ac6efd46 +5bd88970ded34f9fb49bd56506eff1e7 +4ae6151322c641f79976171e063432fd +e41fa4996f83af7a92f0766f598e73f3 +c947deefcce5fffe809a126c051d1a17 +ea02e278d682585f3701c2f70de84797 +05cac50f47bd9793a1578ddc85de1393 +f731a7e59ba590c321938604cf5261d0 +6d2f46756bc6ae75fd6da229bf2236fd +60d5ed1382ec436c76231088a23a886c +8b64d6a283ff6c0a06d162dfd2761bc3 +90a1d0ea3781f5a5e26ce683b0fc4680 +a75786122245112f9ef5f66dba74bd7e +c749bc8ed9ee74655dbb77131b128165 +867219bcf045d756843f8fe25c10dd05 +03f898cdeb1e74a793f06ba8e8b8d189 +39102a856fcf320ca699fbfa3518044c +e0245218c870303e62d86b3dd9263fe9 +489771d6be71fe00f9985977715b1fe5 +90543dbabc2d34ffa16a1854f41e6efc +4536a917c69224150c61d26d7b542017 +7f81229428fb73b082b73291dc6d9de5 +935a81b4624c9fc7ebbb6fe897fb422b +390a861939ab9c0648a077f2dbe16f8d +e7376bf7a5e1e85fd9e281d7ff155369 +9aa20ad2ce464d5cba2a1dd9110082e1 +f2c35a0cd41c7b2d68aeab03c21d236f +f2f9f0764e0f2f076ed48f58dc42a987 +172b65837ccd1720add44ed58c149229 +cfbe059b012cc037804c545e569abda1 +b0c0a0430bff443c69466277a164a082 +d8d5c2e8c563c0ce52066ef5250b2f38 +7844a93ad4b97169834dade975b5beff +3339c3b5d0f0a25b93f02e49df07d5e1 +228c88c6701bdfd0b1421a384b01d050 +0a3614ac2191733cc08ca94533e1a595 +88557f2ef5212999218bec54df8b07c7 +d4e997e0ed397b4f890b8372088980cc +e1855b2b72e259546e9d410871de7be1 +8b7f29715459bacc9b2025915ba2bb30 +70abbe62146ce9d168a28cf2a34f9abf +e56c4cb6aa23185090ac6206bb494757 +a4f0a7724629839d3c88c511ccef2168 +6c6743cdf63bc5947e48c9d5653756fb +57c01752c12b8ff1169a4a706963feb0 +76a804fb7666253284e297d58c388eb7 +cc7bbc4897158ad81a183f1e2d8cb4dc +28d07647484f1751aab8baa5f22b806b +60bfc2a7607f077ad33a75964b508494 +1f5e5e1209a69f3fee070d32a3df7008 +e08f79a86a97dfc31fc56c06cbaddfbf +bc626609a0d56cb6e13e92a5c3dc35b2 +36bdf4e45bcaf8ece61179de5eed3645 +576d2a9b1d1a083d47baf9bd5229d3a6 +482be40cbf880102c2c1914dccf7130d +53a5a9e0908dbf8e3389738abc627e5f +be64c52db00822470e4ec96de98e1f5e +c5b6b391bee206cedf9045309b331e8d +abdc582fd25c0c7b1782aa24c995c01e +220d922e3912de23b20b5ca4e3c661f5 +2dacd278744e75ce3c66a4de9382f029 +f8b7ee9d043526e763a4f9be12095a8d +db1a08ee5e167986ee10231a334ebbc1 +fd4f01d54d318fbb78940080bc03ea38 +0f33bf8340366f1bdabbbacd5a4a25d5 +0acf855839da006911413eb5bb07880b +f42f53a636441dd43451f4b652179bc9 +e860fd5fe8a726d23739d6b683fb41d6 +a20d5f61eb5e82bf21be35c03013681f +8c9c3dd552582bb0ee67f93792cd6ea5 +adbb4c8ee1705c7767b79b8a80b0f9a7 +4c4911bd82776420ecd63ed189959957 +313a40f227cabf2ce724274de7a13a56 +ae7ccd1fa8900966addf037d0c75f5d0 +7f4a5d5ffa93955d10121970174f6c6d +ebbe1ab92031af8fa803b4373bb57bbe +63d9123b6c4b87a5d00f1c44fcb2881b +6ce90c414e67272877c3c0d4c382ee40 +e9b3fbfd1075a3f48bcfbb41cf5ece1b +52b6ed30322060bceef6ff6a2ca15f89 +17fe18949c58b3773131d82fbe999f92 +371bd3cb7e2ba4a530f1055f376a72bd +a00fa0818334449eb754c47ee563ad8e +22ff89dddcf854bd06d5187e355f1171 +b5b61e4b59c55beb3dd82d7c9aac7054 +f1f417a295add7bd2ef3e3282837d6d2 +e32d0bf2283296a4640b2125d6f3d810 +c514939fdd61df26b103925a5122b356 +0d3c88fa0c0b58081785a12486cfeda9 +8cea315ee9ea02bb13b3041905448cd9 +914a3a4b3edbba0b371c91d8273b7332 +fa395ab7c87d964567e98ee752ac7550 +409d9509ff5f5d17516d0bd75590c175 +2b121a69e64651df9867a7232ea0498b +ec4ac1723672e1edb6011ae3a7119a5b +66ebc15e23071192ed21a827f2fa0641 +02f86e13cde03ea48467ef4003e5ebe9 +f4cb56a17064f07f1b094e0d783e491e +1df53155fb2189aeb683cb2ac19d68ac +36933361cd35db24380e88bd5b15a9d7 +66c25ef2b94c400f241dfd73581ac10b +091ddbed5d5b2d4575ada10b7f38e6f2 +2dbf88612e33e829e48b00e52447822b +1051591d17b70012589e63ae43ee2619 +e7d4b7f9663d84668deb11c8f75dcc5c +f536b6206f808e342036e3e184b31927 +2577b7ea7a278f17a763b8bd9aa28040 +339f04168b5eb298c563d01d647cde8a +dd94f18dedfabca95cfc6c00d1617188 +0fca8df25660b84f1a848c69bf62ca6a +dbf5e4b5b9bf693d19231117e582eeab +e61530dc961f3c0996e3ccff4c42a5f6 +295f7622a569f114ba19c3834c123820 +6d65a8ddb434a4bd8718c368e9121993 +9c38bfc2106cb5971bf605f766db4aa3 +b9f5460b267ab199022ec9676093dd2f +4f273d6517c65b735e5c2dcf2e68e3b2 +3d7303ee5a2e2b1d06e7fbddcc9f88e8 +eead6d82ef91e50a280b355c74f9376d +313ea8e87f1b1071cee5b5dac4b19d39 +fbebe22335c34280498c5fcef48ed6f3 +fdf7dc0a8881232b9b0d77ba088b6839 +f77c5cc9a274cfb9a9ae1ae5f880966a +49da2132b47a6616d6e7edc57c41f3f2 +25a6246164da98e1cd52814e945bb25f +e3182531929bfbfaf46cc5f87f6810ca +bc0c1ea54dcb4b55148df05c58daa9a7 +df7a3e7664b6d313f6d756404936a80f +fb12befa3647072c8fe7b6c615b999c4 +505e94aa203c27174b4aca88cfed3d45 +38aae23582c46ea07c279ac6811e621c +9684c07c27db459515d294a52fef60a9 +065423951c1e41c8e76642b4d78d4a0a +e31dd9f06fef4d4b20ca4f77a8f9beec +ee08f3bbbf97a564feb96ab8ced669d7 +11dffa03d71f256fde07b15bcbdf6e49 +1844f7ff0014e34ed84640c824e48562 +5986004ecb772a0d04466f414169f54a +2bd96edd4fb940e46066079a86a8e88b +826da96234df63dedcd1a6bb52dae0d4 +f46d5ae1f1684feec202815975b3b2a4 +310393cdc704baffff7f2f2ef3548e3a +ec6140f49ff3f383d464f60042e8d3c1 +6ab7488619c799d6c2a86559929aebc3 +ef6e2ed0862edd77b0e53d50fd100243 +94b6593af44236421c74082f0b06ac67 +c6f8db20bbbec121f5d61a40bbe458b9 +803b54502b403997d289059b522617b6 +58b61c700395612ff31bdfec6b6db18d +b97a77fc852aa62d29d2aaa9e793785c +a16a04b3f03fd908b85ffa36ad29422a +059e4e9de9219809fcd20d9946bad2ed +8b9b7b7e11582c3b9dae020ffc6c2af2 +98e7a008c4916bf75e3ee330c99955c5 +bb12f226944e0637e37992b472f5d28a +2f537882b03196eaf7e495077aa0b371 +d125f943c4d92c547992b509e5530cb3 +bb478d557c0fe1f98cb082f31e0f5a58 +71cd26051582343224bdfe70e77ac64b +11968a7e86e40aeef7e91750f282f8bf +a7ad0f0f33b2006e7363c0fdf45b3b90 +23394b5f1f60e0c30e6a9ce5d76c5122 +f75b8179e4bbe7e2b4a074dcef62de95 +e66545a2155380046fce3fdbd32a6b4f +68ba00eb6995aeecb19773a27bf81b3d +8f8691cd41a1c3d93c130e6e4435d9c5 +000e497a465ee1e6a23dda65fb9c746d +c645dea65bb482e04c8dda4e0c1def22 +b253bb6660601b0045d0de045b5ba70f +6210a07b13188cfcdd8541eaea599d73 +aec4c4a7fe9da9a76508d2b14812a58b +6413a26d41df3a7b075c32e18dcff634 +4158accc53d5e565ba5cfb26a071042c +bc461a38626c0e1f1c334674458216fd +f18dcf73916cb6e85520017448703763 +11fdab71a3283112484bffc827ede93d +84ce36d241b5793252fcc3e724e79a16 +afada380375374d22c05c8cbb3755e0a +3e70d8ab970694b058abe6c717cbe4b9 +36082ed73973bd473bade249d1a4683c +0fca532ffc85a953dab09f0b8f3898ba +27e791d563c8384f713fb41390bf91a9 +5a3dc9f27c53b1ba6e1487d00087f4f3 +9c37a33325cc4ac7ffe8ca5783020648 +f5633dde9ed6530ad661e7b97b9ad48e +a97f0a2410f3825a2d90d3e0f3b5cdd6 +6cad61ab61cda6ada9e01cd7ca300454 +5e3ed3a061f1407cb6e6f11de09501ca +108725b979eb469bb716566b809182e1 +684c18ba54604079a9c7911730529180 +441031a6ca69276ee7fd7977704fbfb9 +6ca0b3c905c0ddaba60e08bfa9a9b8bd +fe2cd1022800d7ff786c811be0648bfc +256c795ac8222d4f90ea836d69687b68 +d1eab9a647e0f9c5e330431a6895b48d +27bf4c857026a3b9fbaa495c58359c3e +28b1ccddf00a827b6bafb1817967c9ac +85a4cbb7b09a2bfef23a40dda6effd54 +e60d1020b0746b5e0b4a24793adcb5f0 +185b29e63044d9881d7f470a71a2f65e +6a01e6980d28d6786895fe27e4b4852c +5500d0c4c5038096da1559ab7e320ce0 +b86051bdf920328c2b30960d00a29cc6 +9dce8aadbffc34a760659c3c74719807 +e8f8382cc9f096625916049b1340e314 +a3572d01c1979d47e37ae47a795d04db +4cdcdc524a20b80627b9ef93fff5ed12 +a14df5247c82fcdd98f261769116aa72 +268d9b68d35cfdf0c169861f9e863ec5 +6fe6c516b4dfb05f29eaba7e31f34963 +ed990ce8195fa7ddfe206e15a8ea2d44 +392be9cf4cdb39539d1f20eaa62d5744 +c614739f701280cf1c20cc01beb3bd3a +76dec88889c576d7f888eea53f2cdf81 +74851aba1402e97a59a68fe50fcf59c1 +3d1edf44ee0e3753c85eda0032d8e50f +b86d08bd60d98401870b95e9520fea62 +971ff50db55ffc43bdf06674fc81c885 +ada9bd2575f98124f2114452eb4be591 +b7676de42cbef632c61df5b358eabd52 +aad5c034ac2d6757c1d4d5366ed492c2 +246dda05dcd994c9f779b07940eac844 +e0e49760d7a7a9faf7421e4b2725b828 +62a984af8203a5e93da7a5fc0612694a +014f932b5ede5ce8d8a7cfc68499c413 +432123b0d803afb0bb2e8a8cce40a1ad +05daa195d2a98bfc4016a3170671ab0e +0295fd033b59eebdaa4c94943f30d5b3 +0d63d8460f1b6e60fc25fbb2995a37ce +ebce85276ba5c0220aa00bf8b3916bc0 +2dc26abbf247104b3cbaf7480f62fefd +6cf42e9b9c0e20277f9e0c70f1e51182 +64ce1da966578e1165baca35674b2b83 +b871c46f60ed3b3e169f66118a2eee18 +cc32a0b1f42bfe935c9886a1980b3fd3 +09e093b88aa3d316d38494aa48365a36 +dd7623ae715d9ea6e3c064c9f7fdfbd9 +b1c438c9a8dac385bb580d121a88a698 +cc34d3f48cca9f9d7f9d1cc1dbb1582a +e13e949ba1f0210e2f6bbb81fbf7eaf7 +26cbb186accca3b8cf8b824e486b983e +0f2fa23471511c398c13d01b50f48d01 +6d60481a012b5d32c18f5b90bd913b56 +e546cab54b76511b36a8171a99410247 +3e3efcd1fc8d129dddb97ba92e670a32 +2a6e2bcca861fc1c32feb45798e5fc7b +b11d506999bef82d783cbaca10c539cb +2f76db193eac6ad0f152563313673ac9 +701f9749d62c039b304518c86e2d7851 +046abac5664b719c6c34cdebb9dec054 +651905064eb47bb8e32996209dd3c198 +708f8d0cdf905e771f8e18826cc4961b +a9ea6ded63bc1801a82624279a2f2ee1 +9d07fe45ab7045b0763d01234bab4b5e +bdb3494d7b6f955632e828e1fe60c7f0 +0333122ff4d05647d3d8e691402930eb +8aef595260cf440c67da223d5a9b3e74 +a083d7dafa9bf1c53b682c983a9a0a54 +8fae4b1fab2cf736ad8b6830a3e32c2a +04f7359edbea0f42ad98a082e060ccef +debda4f8462a72850924edbbb0a52a6f +35a4b1178a4bdeb4203ad38320e7780a +2c7f94c03bb80182f986399a5efecf78 +e2e065166717c5c296d71e0aeff1e915 +103f053710c05e5e2e1b3cd5d77ef80c +b1e1d39e4b347ae5a411f173f7caaab1 +be67006d75ec0aa7219aa4e4417ba0ef +d709e933ded0564f850bf95ee8b603b4 +a564ac418cd52cad3b3d20924b20b3e9 +ef25e829ec7d1f3ef96974da34a2651e +344f99d366ce1983be130a834f97f541 +f6da251269301c757029af3f663596fb +4dd7b509aa65550d637ceb41822b81c9 +31ca50fd5326ddf1c98efd51d1dabb51 +b302e4159e21fdbff71dab8d8be1a8c0 +83ff7e27e03901ceb2f16e1c14074cc9 +c2e08fa19a2c42cfc88f2611fc24ff25 +5ff01cf5a231158e8309858fbfe8cef4 +29b43ab8628fcb68047af30369c5c0c8 +1a95d48eb31c1832e9b1cc10e1e8c8d8 +e29311f6f1bf1af907f9ef9f44b8328b +57b8d745384127342f95660d97e1c9c2 +01703329b67a52286ef6e81f84643f85 +01e685ca444e598dee7f2fc508b9bd40 +a3769cf77a632d1f36eacd0a2aeb7aed +e1f8758225e5983e31eee315b61798b6 +c934204059aba504247c0522ad85d52d +6137cde4893c59f76f005a8123d8e8e6 +8e0421401db22a930150410f6a03bb3f +8f9a8158ab32b19ac82e727653cb6776 +a9564ebc3289b7a14551baf8ad5ec60a +6f36b833528ac861007e920fcd06df30 +3938971d2e66e083004fb0b31cdf7329 +2b50d2cd21bbda38f0b7cf5b1c1c2a43 +f648b5a4dc7cbda516c2149391552174 +0af464bb9e6ea54188eb4b221ab96029 +fd49f4794e84d32c0ff44a5aa64f009c +44774e8a2c71b1c3cc1211177d2c638e +bd9b2db635b47f753e401416cddc5d5d +50572592b75f8765d639d429a5588621 +213c06c51ed7df6f08e02866c7758cb8 +a6907cea5e9cf4a58b2fc0a7d54514fb +1204bde08617c65fbc54b085bb1b8eb2 +704b481de1af2852815629ab44080116 +f6afb7eef90fcbb623649951714f249d +a1269f45dab88615e9014e23f979db31 +f9aa7015dac694171ac0c906a37325a0 +dddc67806da99ac74af18c6797fd1119 +b406bedf762a7bcbd1512d8e4de839d3 +ac92b99ed4e343bdfcd209b52515ee56 +f8444e7f49687f6546d259b6ea271f6c +a9982061a2827a555b5fcbc0ada1bd6a +64677af9bd755f674e5e84b3b7acd82b +e6ad1ea292837594d21532a8acb579c8 +0f8c29ca2043513a64e9538d9e700af5 +ba0346eb5b13e970b1f6efc3a099ae97 +b242f17d31564e8e37d1dcacf9800592 +4617214e885f3b453d735977619e435e +8c900ccf8f35c561b651e22add513ce6 +036ecdf2ca5a2eb0c7e16e44396e4b6d +97866cbdb2037561292b53531360cdaa +c2f636bbb643da047d9a9f7dfac8f7ee +61c4675093b2719f8c16866ff52204f7 +de2b14ae7499f90736fc4a92327553a5 +8a7376b7c1f8816003559e6a3ddbba8d +1d678750144b505bab7845dbb47e9e6a +eb8cf3a7c31f3cf37e6a100ef3f9dc9c +089bc64bff3199b59952d800914798d4 +98f790e39e9754852ea16a876b8a0a56 +93edaf64d38cdcadff035a1d50825f8f +3c28d6d37709466e2d4a09fc979039c2 +b060ddfde826c0190e0a8030a28ef99a +91086569cb14dfc535d90cdcfe83bfa8 +4a65cc98964571888d186bf3a0d825c6 +b9a169b24b1f7c28dc4c91b411fb4c26 +81d3232c9756e8bacf6d91c09dcc6887 +aaa6f74cf1b82f0f34b039d4ba0e622b +26c93302493e6ddb90ba0704a3a62d75 +4f70aeff4b4f5693508bfcba725053d3 +08724e740ec01bc83c0660a983527d91 +b15221482cb94d787524d5d4cd79749a +24bcfe309b7bad8704fdf76d16fd07e1 +d82d1fc760737a9ab3af4d48a25600eb +f3caff39d0ef30ced2a7d3fa8065317a +4d742b2f247bec99b41a60acbebc149a +676aff885736c4133e985203c30a99e3 +a78ea01220dbfcc1310dbddac1cdd7e6 +9ed45e6658ed9785acd48fb66fb4cdd6 +400dc7079f085b337f7b3832c712bc12 +2e0279c1413e7bfbd23e22d89a0e3105 +4f3f7d303d6f72e6f107c2aaeaf6ef63 +3066ebd2ce3f5d2e804d829d9d38dddb +bcd197897d352c6dfc8146d205816fe4 +d591c86e5d3c3c0feaf3f037abbea160 +9d8f37e0c9fcc656ad620cd5cbe778a4 +29136dbdf4b2eea72929e5b8f839da66 +45f8355f6d467d6a31cf86e1853ad3f4 +4ea49b84f2ba58f0fbe8c4e90b29620d +273160aefbc66f5a9b78cd45e4fca6c0 +a5e10b209aa556df77c6469fec4a570a +b94a42e5722f58c423e84ff9584aface +3464e8d8dbe8f67c4203458c7dc35cfb +018c568f532d5fb21980ab8a57776c08 +0a22336b47960a21b3af4e372b2b3536 +a94f69232e52c563d28a75e0c480fd41 +af21629dd0c620abb1df82dc60c3605e +ca55f5b1d19aae0a019b8afb8d995ca9 +b0b33bc113dee07c003c1684774c77df +e147266d21628764329e9685364d48ad +be7d0f9991e2e4da75f06ec1339994d2 +957cea2b74c8a0203c18fc9c0f17978e +57458f7e3c2e93b984f77f63a304fdf3 +3546003fd73843cea535cdef6aaac814 +4e2ba63476ae19b9cb23f962fb88d131 +32a0c707d600993add35b1c640cbf43f +adede190e4a34e30b049c04f3939d5b1 +d86a25515f038f4dc8955b0a452ff4bf +46c0d366b93f168c9143ff7f169b9c0a +ae232214608e552f454e56264b823f30 +cf7c585bfe298c9632fc365f834af170 +215ae54c221a3d5805593a31246af3af +1ca2e4008dbf3c630f3824f00c67db88 +fa729cfe032a9cb6d531dbc8a16078bf +d82a8ab19578fe302003865b101cc6c1 +736fb96592d9d58161ab675d6e7787d6 +4a7de4c0bda1dceb1440a3d9ee8ef4fb +a7b6b19453b011ee6080c30b9943bdcb +a764c8c4770d91035947eb1ca90b448a +ad60b612a92ba95359f00b6425372673 +544d3e0d499c159c60a3e2957ccb50bd +3c211ccbc3cb16b4c5aa81bd9c09063f +dff077f2380f4c0733a46e554c93719c +fd4cda0c1609a4295ff6cf67d59d9b64 +d7d8660a90389231b05d6a34ee97e9bd +6d59d936b3d83e256f0151eec8b99c3f +672f56fd5d76dfadb097266dd8ae7be2 +9137195e2b56cd1658d420e58b9d3696 +8b129f7b5b8b58871176bd11e8a02a9c +1343eb86f2b664dedec652aaee952d84 +ce0d637ee0ea749393345dd3c6b786da +d2fb9cd6e4a607f96b2a628d817c0e68 +a0b79acc3a59b0aa06b9173513b9caf2 +cced5f5fb3d3e9ca127f0ee7ae8b99e0 +246c377c1682fa6d4cc52e60db4a53d1 +253b826397436dccdda292ef89077e50 +4f636b2093f38f7d46f6ca574c75cdfe +1ad5054c7e39fffa3859e3f38566b3bd +349e9f8017fe3a58a48bf3c7dfe4ae7f +82d4599df33da8d385fca6a0d15e73b8 +7efb4f4f50e296cb3eef7248df006ab6 +de72bba72d7783f7b5e55be9e7111169 +e42d5f60192d1f8f94ce446fff3113b0 +b069b3584c9753191f8c7c5ca64d6ab1 +756e5da9ebc198d3c3a146bdce2858ee +4573ab29e8ffc5a9b1c3a5d472225c94 +33c4439a987dfe3681cc91cbf07a710d +8a0623cff8ca2c95523b80568497d312 +a9dcf1b60445f33e1aa87e3e72d2b33a +dd69b32086f1e8856181a551d71aff0c +cc8d25e9cea8bc4fd8393a36bff98209 +e0d13ef4c966e5b0388185ac4c787c9a +cfede6be71d1002dfe737c7ac3b686fb +ddaa1f9d8ad3972c9ffb4c66b3f11f9b +6b69a4275bda2059a48c80fcbfce12e0 +d285e676f4a29aae50177a2629c56bfc +5e3b66114b9ecfc6ba7d8dd9c5e90452 +ad517beba2f5d57a2a3a7bd754b10492 +43a8a4b5447a60f2048603f5183f90b6 +16c1580cc085e0c8879515f75ffe4dfe +e77d9b8dcb84d1fcd21187b03eac74f1 +fb0677df22a91c5b141dcd572e860550 +cc3953712e935235a7c5be1d7ac68bf3 +28a9fce937a13389c8a5e9a7d5d1fbd9 +3e7845bc2fa17da1c4a093dbae141195 +760c444d3d6bfc5f8ce222448a87590d +e4283b40ca1a642804bd2409af8b2375 +e3eb3c8c39ad41a68bb182b00386c71a +ae381caaad86c0de9b810274803a79bc +0b9415e061fc4a9db4c0ffe038af4d55 +78f4ac72f60acd922a403bd00562251a +de5d84ccc559a94db4203e23afa90d54 +1e2011accf901e76548a1faf55684da8 +210b9c649145ca3e534c0076edefeb8b +5718e0e30db4c7ce8bc220a7ce2c172b +e4edbc12f4dc8146656716d63208a51c +13441e29b4210d9d48e69e28b9d7ccd7 +a92a52fa9e8d58da07ad51bf857c4308 +a193ac63bce2e2ed1c6378e2f1f6fa20 +73907cca5e5f4ea091bd96bd0cf388c8 +50ab4e04387497d32dbd87ef5e558b95 +81f7adaec9c242416ffd63621f1f5588 +eadfa32614c6ebf25f4c929607272a52 +33a817d24bccdb88f94b6174b7da11ec +d911007c3ef3957a7a1851e78825b375 +000848a969ca91f39a1da9f74f895122 +a68992c8883cb8ede10fc1c4434b75f3 +c9fc701e7dc1854a9dd035862a218d67 +3c703600d3cb906f6c7b80f9e2a56bde +f63ea0dcb3623601545f3bd1ff302f76 +f1441c3960c4cde01cd036d0181495e0 +9c5c240d94962aa58c4f01cd188e427e +d799d6625f37a65c939a72daa6b76747 +708f11a90f708391e5c855aa91e56ca2 +41ea81d6d670ac6ef9c83bd792057aff +3882275d653110ec0177e9ba7fc49a82 +50098d0d9694353d1980740837a8fe0f +452cbb1ea056919ad3747912e5a0254d +e937502ba8635acc6591c9e92e84cc0c +2e94f8590103ffef4fb35ecb70db62eb +e65e2ef52fa30dfbb0635269022184f0 +cb544c506b263b2c479a2e7d5d3b309f +83330d4408bcd5bb0b216cb78b00fe1a +6fc60c435119e7ff9de4a0cdb42f5cd2 +ea75acb6d51c02b4890c553dadb68652 +61e1b672a593741ff6e6d76ce5ab09cf +177db2fd00db5a05d5f39476b1ddc50b +da0d0718b9132afcd91b6f3efe73008b +e04ce07a6d46a1dbbfea836506f98a24 +50b6c8101a9ee6c55b044449d2429d78 +1d89a6712a13ec0ae4f1568cc42821a2 +2c710771322b8dcb1a3bcc8004f4c17c +28da591ac195b6c5ed7313333f2cefa8 +7d931e69a6d8d666843359cf6f56b0ca +8a9e6d1800f7b0675fd7ba73196292b3 +7bd4bb35a590604e34a76c18ca3e01b0 +c810c60ee4b02620e2eec207c4578610 +de33e7cd136d0cc5d6c575aba43d3168 +1b17a587ddc8713e7575740fddca6310 +f1441c1494bd57a98cdadb8886bb71e8 +2a2bc6c77e1e74919feb10c9e799c47d +285baee7b582268e8f730871cda9d814 +0c2e0121449e9c5edb92b7f349e41721 +0b0480ef5268e2cc9ce50169849d3e31 +f3b96ba1f712a19b473311455ddb717f +83dc38ab4e11b77fe818068fa13ebe3f +b69184cfd2242fcb417ce3bccb9a5b29 +302f8ecd23cda08dc30ea8faa2982773 +13859b9e208dffc3782c867f9bc8d121 +f9ebcf923ad909491da2b652164bb361 +39a74dfede4d6b782ed0b92a4e271c89 +b6048b3b94c10037955d5a6a9dcfa4d2 +f17775e21c8f5e9cc2c7ca36ed1df4d9 +e9437e60f9fc6c4e894d97ea43154026 +fd475d8c66d6c49697f4232caf31c90b +35d52ae8e5e6147049c5ad06a981ddf1 +306a6ca00f1afdec316489ddbbd83838 +e37a47cd6a29730492a24cb7aa21256f +b5a6743cbf02512be23fb30d11e2806e +088d0ac6caf4dd952817566f12b9c99d +fe2f093e55c6e01c88656217dc7eb0d3 +88d4e59c78f144b9c793f60c97e8b02d +b4ec42b014793afe67ab40002fa3ee1e +e59f74970d578320aa7236c0a7598980 +2058d27c5da9377252cd56eff65fbef5 +7fc33a6fb30899db6d36f97c106eec80 +dd0fb8fb1811b6d663e86679f9efc386 +a5a7da0dffc7ff6dee92bb7686bc929f +bf49ed1542fbcf2fc5ea0fced7b17ee1 +a2a1176feda046f884d871706a627be6 +78fa32905114b57fa4a868accbcde249 +45784b8c44ed69baa13e1f78a2063625 +678e5e019a79526d0fcca5e29f6e5f78 +40bc979fc51c312c66f13621c9c53e84 +1084f6e39a37c1d09e49d25bfaf46e58 +db836970ae594c868d260daa82d884b7 +37e040895d513605b94d7062c992e447 +b989ae8734e8a1a5afc365ed595ea7f0 +b112019db1fd9add9026b28fde65c816 +28e7a2905c7e95a52684ad2732230fcd +be0ab5e695645dfdbc2faab8fb249e97 +6792695b30bc77ce16eb245c9ecea930 +6888c17dbfc42c5b6e9f1aedcb4b9fda +96af09ba7e1d7e93bf8d4c8591fbc779 +deae7052d5300aa35707d9475244573a +70d89f93aaccb5d744f11b6b0bd1bae9 +7238c6374945ae4d46ee4c66d0a1c910 +5eccfe9ebc33b65f0a7714c03ae2a425 +a0aae535beab6756e3b69c3e78e1df04 +92e9e866dc16d1d6258aa980a9350717 +2d0d9e19256e9f1f7f310bbad3a2978d +734ab2ee41a74d5b6498d3bf55ac2e84 +8900167c19d6973b0baefe16d9da162d +cc446cd7c43e8147a577ce093948f422 +08914b150cdd6888bf32d668c9336169 +78ceda451495ba84d02c28f4608ba891 +d0f08cc3831a31d686189c4f784bf948 +059a1e9917fd3c3d46d3bca920a8b3cc +68727183f7a8dc1878b8947d845f04a8 +cfd0280493314f4c56aa5781a9bf3d8d +d0a736241ca5c490e465ff5edad43119 +a19c3d31ce299bebbbd53cd22f8a0898 +dc271e59edbc284444c05a0820e74e26 +2257daef930a33efc1b422d4f3d41890 +32703b9d0a14cb875c0946894098df19 +cb5ef2dffdb3b8314190b53fdfa737a7 +6bd0d82f90d3b3fc074f4de844a98f45 +be4f811c5218fbe546170e4a37bb8f3c +221791f6e1f14cb5404a7546912a1ff3 +3440216e970f39b5a0d0bb45f37ea45a +df09c2d28e03aea8285a50b47f6b96e0 +c766eadda04d957ab099bc37e60788c3 +45dc37389ab8f73957451b1ff2bfe0f9 +8d8bcb9f650ea8a443030ce0e8ae27c8 +4dc53fdffaa810544d048bebae90f836 +9ffbf43126e33be52cd2bf7e01d627f9 +787c9a8e2148e711f6e9f44696cf341f +f44a7986867fcace717975f132d9f1e0 +d1c421cc7efb17a0e755906d67b9e735 +b9b9fe92c46a98d70af3dc5e6f1d63c0 +e0fdb3a905da433d8eea3f59cf80db23 +8e5baa34d6c3869611929f18dfda326e +afaecdd59b3c26b63e9c8929f1e22749 +2edb7ee0981796d67b3be05384f25f3c +10fce144622b05eabda17fb6c45082f0 +d8ddf282ee7b6ad929b5b05e82a54025 +ce1ddd1a46197cab6b2c03f8d5526d09 +19bddbcc29b0dc865cdccde2cc2b96b1 +bef3fa9efb97837aa17bc678fbb942e5 +b0cd5f326931024d52d90e99d04adaa6 +11a0f80deaf7fb46838716ef2af6b99e +d7431d8f2c58b7575858c77b741d2da8 +bd4c1dc953466a6abd1a7694b55e4c83 +e2d42d6a75d9ecad45e345ada902579f +775dc00b4d1cf2fd2b03ce5bcf993362 +7ac90dcb1cb342cd526dc5a62ea7f782 +b925134746cb640b194f433bb153314a +6d2acce6399bc4e65b2b10f2aa6318c1 +4524ada27ac14f7102de28075bf026e9 +c78a221c90cf37cd47129652a72a73a7 +024a64e9056d4ea99e8b54a274f1ba51 +9425f633e1ffbb111751600b69e6d98e +e749be788b5fd679cf6311df8603dcd7 +9b970db22b77c3b62b8e842cb4fcf71f +e424f652ba533680703622140bf1416d +3f378a3edcdae4fcac582a4a33ad99b2 +e43fee1154bf41baed90b3d27a2b56a3 +b10f34bb50f1bdfa52644a4072d4712e +6c99651d62b6e038547caa974a79dd45 +e177e2e7fb6a7936deb3381f51678efd +069640eea5965a350fea04bebaceedb9 +5de63424c4ba7eea36b5516f9c5f9773 +31ffa42deb34c20afcdd930f9f99dcb6 +02133ac8d4516e0ee1cceda9dbdc7fb0 +f1c97fbbdc0eebf49753336fb81a7811 +ebca5a68338e106c0e4a581c51eca99d +14f6412380bf9cc2cfddf310b6f385c9 +b86de701ace341fa1e1e30ce14270287 +8ce2abb16fe865caef13b68875c8a87f +d9e07dab38bc124dc1c21ef0f0e1c11d +5b6375b647844bd55ab5b907e0e17151 +a32edb9e7ec7aeb9d0d271b71eac0c24 +aa674eb1ffb744954a45f2460666b469 +e4f9eaad46536469cf90c464e5e6d29d +432ddf71b89e729e0fcc63cf9ed88760 +b1cf7be6cdf68f3a5852d3f508920fdb +0900689cb2f1b4f9a29a089809ff3fcc +1ef68cb90d4241da14c923118bae2913 +d3751527d39ff2621d1f4c314ed7f3bb +93282146eca2470b432363e27a972f7d +5472db438a1dc3720478ccfb4f25c45d +c15a53d2373164585d68fd99881575ce +d356f6ffa70a748d08d8ca56e92b8541 +54967b0824da52fdbaf105a43264b6c1 +f9f3a5c9feadc80cb97a3710cfab9131 +7e7bc2edea94ddbae209e700c0017727 +8ed887d8804815b64c0d15e294c22863 +a65cf5c7be6fa9ebc322aadb7fa3d742 +923d6c94479b11c7e0ce7fa6755edbd0 +02b99311d7a05a8638890634809823e8 +ee7a0d63608efb5dc89b43934d79ce1b +30e468907b730405f108ebc6102decfa +393e648528f1c2ed89c9e36588f2f9e2 +c2fc1e40ab82a6f103048efda2a04f3f +bdb9079ce4a4e3ff76d459d4867da35a +ee880983f7dc16e8738ab3b7c7864126 +daa36d43d9ae5bc2559d916f0dda749d +ba332570cd89ffb290b3db270c10356d +c802eea3c74cc836301666cfa54eda61 +f013fe16b721f950d515c93370700035 +db5c3c9d348ce26169c56901a7606961 +f7f0795af3b4a135ca0c1e5f404c93bb +846753232d9cb2a86e8da4bbd63cbca2 +3a9d431ccb6844c5bad6eefc14b4d976 +c7ece1e21cd11e0531938c3114ece8c9 +bd47d9fe13eea8f41da16846e46a7aa0 +511fb255c56cbfaf7a0fc7bf763cb096 +cbb9adbd7f05c6bb7ed9cc8361160a37 +c3c155cd50d9c1b28016baca62ad0f0c +45b5847cf7f571b351997e694a116f54 +c4b42f5d67642ee9d98875eec7978e39 +daf09e67dd471efabcf51f270b25a0d8 +20566a24bb586ba4a412345dce266624 +b4f150685947cec6ed9b34220f85fbb9 +9c71025074220a10d617ced27117c27b +b0061974914468de549a2af8ced10316 +0819cf399cf613b5b222ac36e39b3b16 +2d2977d1c96f487abe4a1e202dd03b4e +b73a605172a4066b68330d8be34451f3 +6a852b6526d3d19a5c7dae8758035b61 +eae72900f1b298e87ac2d7feb6de61fa +459a32ee8d6a20cb7b7d1215168b519d +b165c11e1e6465ab556e50bac6e66bcf +d0ede336fa16bf3bd7cb729679b829a3 +d744712c3edbf7bea2a33841ee4bb0ad +5bfe1d03a67ee9898ca3bd8cfc00a49c +0a94fe962672ac051a9082e19bf693c0 +bfbb7d1faf68fdd648e32403ea4808e5 +02ef686766ab91168f3024ad49ec23cb +159ce6099d3ba326c0a18777324dac97 +97ebf397ee6d4032ac099ac5e660e4ca +18e6425c6e1e6c06814d27233ac486ca +d67e90da27bfb7d6690cdab0c242cf44 +404d5575d5e6eab179fec32ce4d4079f +7746260b994fcc1466800c0e85079445 +e8fa71ef544b988a772c98f3c9eb8dde +a97c4168d3631417d0c6fef4802776c1 +861b1ea05039a4d4a737a62d5977ddf2 +40f2f6d7d5696d4ba5bcad579b841503 +365dba6bcfdf291b63281db9802eb136 +764dc2c82c1856d13039f8c5b41762cc +b88cd71cae2bc8a0205506b79e5515b9 +34db1a2d42d25b8c0acbf0767b25f2d9 +014489f80844e7455967b59f9ca5f999 +301f35eaef32aac0cc9093772bc05fa4 +0b9252a99583764e0fd44af8a40e6b43 +c6b365ab168101f84493f58e9ebf97c7 +7ad7c0fc6d234e55adcaffd3b0fbab0c +5988995e490843f1d1fe0a492acaa412 +fb9dfcd9ff82c14aa6ba3e7ef111fe83 +a54950a9f40711703436a4ee7c20bd1d +e63c9b8ea3849ae32307ac78b7fcd178 +6a90b22538c72b6cb608355ab38b59bb +e757dee0b79a0130612bc52adb244464 +ea09837a78394a5f5e997755b25d6330 +fc8bd36d0b1cc5b58bd55e18859a7dfb +fb442c269d69704db7d730f450300e4a +eb64a78d3eecabec945cdd0c8756d36a +2ca7743ab32bf575c150828e7e4997e8 +72be1344cbf82ce786b0452ced2b6688 +1dc33b7370f5e00eb109ad539ad2f939 +faa87e73d53adedaea9db880752f26cd +9f1dfe11e92265f45857a89a2718d5a1 +a49537b2bf01cad03c35214cedfc3376 +702dca30d11b19ebd06055da4442df55 +bf8ac761ff948f2a51107eaf75f13b96 +0a77766c89a5ca8bb5ec3c090f4ab734 +2e79706cd317b5766cad3d8951f50b26 +0b9921e4081bebf8536cd9b72d19938c +899fb4c51d0d5a1f6794680c0815d7e9 +e3a49993ae9d968981ebac84c637c840 +777073f3cde34eb0efee5f7d1f3919b6 +11a2f64c1fcc7a3cc893efc1b415ed50 +334645f09074b2597a692e395b716a9c +3aae6bcd7d58678748bac3afca4bd167 +eb7bf8907f44f4aced8898ac721e008a +6378d4880df4ba2d5824cc52b663c03a +63413cc0c5427e087031eed1472affc6 +202158983a04b94daeb2295256d3efd9 +fbbfc285adaf96ebe0071b3f7436bd59 +b175c1bd55e63b1989e34bf8bedb2076 +cdf3a6fd896687284d6ba12766fd16bb +bdf6f83ea246fc2ab32b350161b34dae +aabc09526d1cc80ea4f5457a2d22f67a +e7ba016972e4204e55048824f6688875 +a97a19d2fb7ee1fba3c7276f256fded1 +07a1b1b04273db9b8b4929d6d7b62f5e +e81a881f006aefe01b865cf17d10ef01 +d4af3a20cd29907b909e390f5448ddba +82b99c5c78e5ea49e8e1bf476efd3db0 +f40ea7b78b48ae02a4b2b87f30c6771f +b4ae8df517989d653b2a611880d0ba2e +29edf0e0ddfc960b7420aa6f73338081 +be6f3a35a998804d2c6365ed6a3faa95 +9d2c38961d8534d72a46fad803d327bf +4effbb3e10cede82492f80e08db0f621 +b48417d96eb65b5e740ac3950dff2ee8 +39fafcc4d33109ce35ffcb5f00591dd4 +ed34bdc7b2cfd868b7bfc238dd1b7fab +3cc8f9e2ff74f872f09518ffd3db6f29 +783dae91eedb405162a191e1bab16ea5 +cb75daaaa21ba90ec2ee19a506309990 +1ced78f521333bb28c3681ab8cc35432 +b90c520ca3981ece3d9840a35d4dd26d +629c2868ffa3b7a11e1b122909c3098a +4c371f378eeefeaa166198befcfab316 +6e64d9638a4a23e60fc09108a946d893 +3e1904017b1253d6e81a6a44cd316128 +1475a2312eb2aa4419c3d25188fc3564 +f0f9ab7bce956f90679adb463e495419 +1d4f1d3c585bcff37adf7a4d83d07b77 +34ab9558f87b957f5508f7f033f0ec7d +b4fde836e3391bdc058341a9d5758b93 +ddce269a1e3d054cae349621c198dd52 +02fb126282cb0d596a9052bc21948326 +9f4ebce3b8214176c3cb49e52d9fdad7 +c1fb2df131f9b6be4e9c0868b3352fc0 +f6725e0f6458e24e28884866259c476e +b46a77874d7109d319bcabf68855c93c +72c081e030c7ca6d0ab3272b9889f51c +731fb425cccf8535adfda59e9a0c70c3 +bfe0acc55febaaed8a13c27017d22873 +8fec124afeefe87d95563ce96c3b9ea3 +f33904d37291f0bd3bf2aac4c74cab3d +a20b6bb2f9639bc39e64249c139aac03 +45f914c04f7926d9ca4bb3a842cfa8a9 +c0b8728cc463cc92c5ba091939531d8b +fb12eaccebfa07ddd15f920bb8742030 +45eed25fc087efadb092d4624675e1e9 +7e0daaf62e64da647669ddc836b740e2 +5c1033e1ad62e470dc57e92c02cb0a0b +ba880d966dfc73d0ce69fc7bacbcbf7f +21a83f074102c8d83d1def6b4007d713 +19057b6c3cdf4cb20507e0ee51974d80 +71982c046dba21cffcc7aa50d5e5bee0 +c74bdce650e7223f57cba6e557ef5306 +5d51e3cd68a73a2ffbea6204f37f108a +394fcfe03035d9c3780ff7a30a5642c6 +f5bdc1d9877830879e85442946a836eb +30b1fd6d5e242f208c0374b0441d89e0 +208035e6d611c0460e72e988797529e9 +59f5954cbed961e9c87ad9c480707012 +cd7f4277cd43e5376e81165422418db7 +1a1133011798c1e25cb68aba04d6708f +6880db2ba019cd4f617792565a88c144 +59a1b8fe536c21d19ad58664bbb0874b +fe2ce782751642eda33aa226eb5fd819 +f41634ebc5934c1c49998e19b110e964 +63f6f389b18215d3641446bb8b311e0e +70a188e117de412b6d2bdae137d3f484 +14f770ed795c6a29bf9bc636531e9a6e +cf36d76305927d785e8e6bf85664139c +97e8429c647dc1a526d6b992c384962c +6806a2fff13b2b0fdb451c63bdc0ea15 +bb12bc8ac2a57d7d089ad13415b52866 +de40e3d15c5140d4a77c3ad0d782d57b +2035d752af2b6a1f0604034d41b92821 +7ba6ca74b292aaa5d46bc407ac5be166 +f4b524261fce06c1fbd10b4681ad0b97 +18a9ac5318a994f12924c95a56dac084 +7b5fe05b5d76ffc77d753eebd97e955a +dbf84c0ebdd315a66956332c56813df5 +a2279d8ac31bad61b99bf85aa851158a +0e8efd8653318032219bc607bfaf3ddd +bd704c8fd28fb7b822c37420254c827a +79527fe12fa634afa7b01603e9033ef1 +be12a34ef2e73fcfd9593393527eae26 +5bb8be5058bce010317c26bc1fc8ec92 +8a42cb46a14ea5ee51df58dd3301563e +2e0cf0d361a8267a9653c0ea3e350229 +7e51926af3cde0666d5cc4d7ea95214f +bd76552563866f784861e636abdb9a59 +8e13717164014bdbef702c0cd50f042c +6c64917cc4a2b48514ce95bfed6c99cf +e959ac6d0f10c984d144b99993e36425 +2c4fadfb12a909852f0819ce50490137 +3e58d6bc1b1f48dd225561394e8fe06b +be6d6e915b8ee9a19ccd35091d3ef5ae +2a66785f66ada19c559b661e5da4eef2 +fe43a2d3915c48581833d7baa7b4aaec +8f0d14e836ebe38a69799fd343c86a4d +ba302e625207aef1b6613fe7fa2d41a5 +06d746840aaba77d33a87e6d023407e0 +b8139419209b17e4b9de3eaff5c25f87 +77e77db5c0d7aa06d43f7c9dddd15b05 +334590e821650296e64907677bf25409 +b96a10c8ee1cb4e3c92567f88ccfa0b7 +3088732582e2097de2288afab8a1d16d +76a5e3603d97732d12b89bff31b2a1df +c6b4af48bc616eddd6cf9adc809b97dd +87d12a5afd9b8ff62bffae326c54e4b2 +2e6d23d86e2a02a74b815434ca0919c5 +6ffe8c31161caf947216cd6a590e83ab +8e763b0b493d2fc2b2d8da2a728b58a5 +fe607df67c69301715abc0292448ecfc +156379d395d6e071ca29455a00dd00b7 +21ebda92dab1abfdbaaae16adf9dec6c +5e22989f2c7caf1c175a0caff0da5f57 +e038b815e21f40baeec9367040f8898a +c7055c2b2f79b8071753c9a29cd6efe0 +347560b25c5f2057ccd813b66489a356 +ea1d74cbb300cd1f321d5d4e0faa2d63 +3b93d8da768ac892843244bd9df6527f +51c8c98d5b82f4de2bd1504e254004f8 +af13937171d1851e0329f8c286de0f7e +0d643e526e61b23dfc37e8b7dc09c7bd +0badd879611422b214d8c53e19b4f2a3 +a17e14ce64d18ab070c1cb64589679b1 +07f42e2056dbcff5b7781afac8085081 +7b48666b13c02ffd7122df4275adc002 +0ebb77dca841e0c3254eb7005b1ccd57 +6e7bb525f12fc29a2b9f4c48a57bbc71 +b8985ea71ef23edac9f191b9898688f2 +3105b3483359b3a7bd8ff24cee3bc01c +56aab407dc017bc229b1a1208d1eec20 +d576165eb2549f04187c02b5adcd86d6 +5fcaf8ecdb537febc6dd46feaa45cbb8 +8f2ce0dcb162d1b2d88adfb552c8ae61 +d2a33790e5bf28b33cdbf61722a06989 +669168ea4d2c57173ea57f418b9c13a5 +11b339cde0534532c3c1a7d995440c44 +e9c0f1e6a18fa1ecce9cb7b38fe0ba91 +a9f445edea679b70a32a8cd8ffd23ae6 +fb697b0790ebaa204d9bffad490998af +8019f301e7c8a25c56c8c9121255980e +497a86d4c7adac14abb578b97ed0bc35 +e55a23376480ebacf5ecc81d8b8c3432 +74170928bae84bb0a107a0906596aa52 +1bcba98459ed84f2f5a8e102b95f4b38 +cfba99fe0d14214dc3e04a5ab5387fab +6c65f0577ed96c176f37ec3257824133 +85d372367fc6a5c183acf686abb857da +5d4d7d6bcf5d42a3df23e490627a1af3 +bdf7d7676d06f79044f240770db52cce +d42f2da1df5ecdf29be4ac27edda0c12 +45ce3b2543a563aac0f955d52767e570 +cae76e31d8c7942573e57de533c4c73e +5ac0b0278e11c2000dc3de3703b44c13 +0ce020a5c3c1f7524593fb5292419f93 +b3e19e47e6229d1e642d9e2a2f11678f +e716a99215e146e01a335804ca2e2785 +c0e4852b5be3ee1ee31c8c2f6c7ea676 +b8742dfd3b9fa3d9beeaac3a1a557617 +5a3e27488cae6470a51407d9036c04f3 +e2f7b2357146baf028641ff21fff9b0d +3588a0861ef7e00f1cef13b11ef93393 +43eda0dcecbd12f7f1e934bbaecf4115 +67200e5f08274ed1de00f01ac603c2f8 +5742a0b024dda4fa62858e60dce7796d +6b95ab7dd9f1c74afb538d8cc01f7f3b +c35c2d7e779f00e69e4b921f71b0004d +80e9f630bc3243e8230d6d2f8111772f +df73a54dabadc6734533fb7bbd56c36a +abc4a219b2c5a071200cb1911ad99629 +5f631560dbd4e7826a2b2c06a0bce497 +02b25fd6b283c84a45b167157a11c51f +b130d8ab92fb8dcec1781881fe73b25c +964827a6b27b6ff4b4992933fb247df2 +29ab85b5ff0fdb0a1239684df2519fa5 +f78bf9452aafb9f71f0577e4d9e55035 +0731e29a81c2ff526e8084baf217e975 +26ce53e25dcc15794c1a85badc423e80 +58bab5bfc8d55ef7ded3923f5ef0735f +81a0aecc785d7bf17030b82756445344 +c369555e08ee6931b91e555e8afcba12 +78e6ec4a5bc14d6eb3eeba1165e6ad53 +658a0621be2024d192728a263c8825d1 +8fb936ced7d446503e16465ef5ebd606 +7090a0880cb8ce159231f8b4f30edc9f +2a056eda406b2163a887385495f75973 +eeaf2bfa81d1f331d4edd2cff676b485 +90bb921144d85f5a3f09ef82ff9a61c2 +1b180d56f5dc8fd2c47bb842b6ad4e07 +8aee27ffbf986af186bd61d4007a1547 +e311c41b6f47ac74398821ed1300ccce +e7271b0a25dfa46fea5f8fd692b19d31 +fe290119dd1228bae350fc1347d6066c +4841a3de68aff231f06398a0184d5264 +9c95fc9c5243adf7bee912fbdb0cd00e +23ba36a48e38bd009c2b4e2fe924b4c9 +3fa692c8e3d878d724d39059476fa362 +fec90ab8084c030b6a8e959c5975dae2 +e4b1adbb95feef9774b17c04b90742e3 +92aeb0f371f961ffb9491c111989b836 +4e1d55e3c5ccb0ccbafc625c91347a92 +c3cb907bc65cd50e1162b827781b3578 +ea401502838075208731a4da556dcec4 +0544bdf8447f076fb8e0d66342d85adb +19dabecf732721eba4b0cf0dfc21a8d4 +2f2b7d9736c9670b4d6340aaa112571e +c4fc643c5a8d6b62c59bd9e900f41f58 +678dbe5fa567cceb0fd3c612d8f21bc8 +73b144cbc18af3747aeb1959170ae95b +bbe02f946d5455d74616fc9777557c22 +4ea7a509772658671857e9372c1880ba +a072a3258dac3f6a54cee0c0ce81f90b +4d3e52e8f66ded92a9ee0470d6d784a1 +38f5975ab63921453b8811252636b381 +f68ec4a88974d07606e78a104fb0ba6f +6cc967d7ff6b372356070a5512f0707d +c73f57a771f98f41ea0cbfd364899fee +75de4c4a4b65f2f076f31f691f3470b0 +e51f6a5c168fa9ef51a113c9a96b9e52 +612c38bb69e64de1ccc4c1e5961e9c3c +eb260e9ae827821beceeed4104f0ad89 +b9d779299b9b8df580850f5e82397e44 +cb13f4754b0826d6b5cd35be235ebe31 +4cc8121cb8bc8fc17a322daeecde3eaa +a9391ac7e39dd775943376dbe2dff158 +014835e36358e38c7f7897d6571e4529 +906f25b188bbe2a9e3a67708176b4259 +708837c1d238f0955c23a38051f5ebb7 +7861fdf36a9227f825bd486a335855f6 +6470e394cbf6dab6a91682cc8585059b +c6232ccf78437d606202f91502a7586e +734b12fac1c2875367114a1d42730610 +929022a1f0d6bc3245e522ce4ff43da3 +55ed7c8889ce911482e767e865620bfa +10d864114387ee85fe634c63505722fe +c9a5aa53b1891aa96b1bb76c7d4619b3 +06f3ae1264169a54b8ea8a7cd333d97f +0d403839540c5e01523181be590843ac +a91885ed640df6e5c8ec8d4c337a4383 +90d70dd894cdf88b4483f674ce0598fc +1c3d44e2c9d1326cbcdb9ae4dc8a0c15 +124c883428afcb134cb9a1e95656f180 +465325cded4332142dd94932951144d2 +db5a397ed75bf79c4dc244feabea0a77 +e1b844b7ff8e69ad10d8d28104627c33 +18a39ddef4b20e51595bb4176c90270b +50bb076a040843d741168883f6cb0612 +54994d6279d74c39155ca1477c406d25 +4d0cb3c137775c0dbd24e9d6f04dc63c +5df248d21614def6ddf71d9defa81920 +088cc6ebd1b471d593fd40e6399680d0 +91e454eba04c1aca45d1ef5d17c65285 +d5b29a51e55d1e935dc0712771475e09 +91764b3da36b9deef625f13e456ad96c +a40053051c978701fa8bb66f110fc487 +5d5ee8270ebcd3047e68700be54f425f +1714d2c7f34a8a0a74a143a40bc7fb80 +4ce6de95fd8d32e890aceab69396face +63e0c03e0b194867c7560b0d8ad450c9 +8d11393ca02d4ba48b8d70ce04a2f160 +04cbf5f31dad92fd9dee473b9dbad852 +1da8b6649162d7435430a3268387c79a +666eaf1e4ccc59a642524fc2cebd42a0 +3e7f660d6eca0f25be1b79d69e580cc7 +044c61236a612d311e7072440ce0201e +3b623e5210d81d1a0094196f5708924a +ef929b7b57d0465655d309075b9bc478 +7be6dab3286e9689626ab73d49a52b9c +a2f11e6571e711441f08831e78fc528b +91673a55aeac5583204794aa053519e8 +43d9e5d39b885568661cd31aba72c225 +bda916090cc0a05f70d22d30f821b60c +6412b72f4d5315d52a34bb138f3c6b14 +6fb1c9241f3ac8e63ec3b535ebbe25da +3bd78f157f1711e1c03f13368dc5ee47 +35527bd2f150f47c046894e6be3cab5f +5b5bcc270cc34f5b1ec8eb23723ae37a +75ffdb827341e578959bfcabde3789d8 +7a0ee20d8e1d0c5c22a2539fe30a9da9 +6ce322f62d42fd2625c6c509692cbe8c +6df2795d7e00e16971e249988495fdaf +583283b732969cc2bcb1218e2cb517b4 +32725ef162e52f232ef92c0b783b5af4 +cec2f7de1da7efa56fc27f18fe0a07dc +137500bcca0d3f1a979d198e9f8dabcd +bb7e48b926df72d53c5e7cf4c0e9bbfd +610387492db237a878b50b75ac41f6cc +5bc7f42b83b6020d2394fe96ee3441a2 +c259f6c41a8b665ed43c35ea15b6b516 +38b5a22bb376712b7c88b52d9429eb06 +a745d6158302ea63df7a38202af497df +c92bbce1cec8e4c3afc734b0a398dc14 +e3e5be88e2f84fe29333af8647c396de +a0531db54fa845d213fd40d3a3146d46 +1bb23b8766b8ccab5e08990bce0f862d +3d4f6ff35ef2ace5ded941142a0a5c39 +3b674de4febb3461f41ccbef8d2275ec +34c860db7290e016d5e34e428b16f47c +cd38e8bef8f412b4c4fcb776ddfc94e5 +dfbfc09aef387eeaf7158f8bb8c0be31 +7468081a0247a6f4bf1e85f3e17df420 +1eee21d45f2944760873bf8d8d93eb0a +4adb5fae002b16c059abea038130944d +5863d40b572db607b49a19fe56b56189 +a8def52788fd7f679f6adf5ea0c26cb2 +8891ab1e63bbbf002e998e5f7507b5dc +2e6a02dd6574311863f7b47021b0f330 +d84b70c244e7a6df2288182a648dec77 +2620362139e62d0607a9e3de3af4c57c +11c7c8b76546bcb175c62decee7a032c +d497e4f79ec5796e0de686ffdbe0b2ad +a8ef91fbb4477fb35be5ed9497c181a1 +b1ea142ee12cf0331fc2680240cd04f1 +2162f15df14c0588f1f67380de9b0652 +e79cfefcde6362f4f6fd60d6dc5d88b1 +f5302386464f953ed581edac03556e55 +a19f65f69d5ae486a7ecd8da66e69b83 +319a02032d34e3a582bcfbcb4f3a09cc +4d746dee9dde402658f4b0bedeba53d6 +3eb4cac8a194e533f369e9792fb19d34 +f596f2f69a76a824ec121692478ef043 +d700de499254e3959cbb5e7d670fd969 +92b2519cf64735043403c8c10347f4c7 +9e3359791b9058b3241953ca222ca37c +b33417394c9559d45a12ad9c53ebe9a5 +fad7aa65f9b2a35af671791f4d883839 +a4d4fab79769c4578d213c0ac823f31f +8128f7d6271391d1f0ca556bc3c37c22 +b47d5bf73350a54357901871df4cd703 +c24fcd72b8fccc2a5d722091b7786af2 +1f41b3fd6f7ae842d5bdb11a5c52a6dd +216f03835726c3cb3c10a7aa6e06e990 +7d83afa7cd77191878905a71587f8624 +7ba5a8d2df7be8121b694c5c00d0919a +242e3f5eb9fbbd77436f9bf9b0ab6999 +b55a9d92627c0ec4c675cac9edb2e52b +7871dc425c720b526fb6896aaee3418b +7faa6eaafca86ed52c493402d996417b +f1fc258e19d2e389b16985aa19a4f4a7 +de3e3503868a959979815d3424f4e4c1 +329ffba8af828e6cff655df25b259694 +af05669796eac419835d84d5791b4bfe +a17b58ae6c28bd31aba9224666cf10a4 +bf9091f4a58cec43e323883df9a02154 +9a3d761a55a30141a6a040c1b8bf5839 +e57cad92b86d48d821e849c362a9144f +b38f5ef047c56f6ecfbc9e117e6a8ac8 +0e22d6499715ef61dd8b367dcb3460e9 +ae1c9b1be162b3fa41f84e910aec0fc7 +eb89349f321d5ea8b124de70432f8e1b +e7c05fe46d6c243dad4d965fb7b19502 +08c3cdbcdbbd8da9cea5dbbf16f77f68 +3264376dd3e10997af454195f9253f93 +dad9094199ee8ba9cd5e3fb2fe27312d +118b0bf942a2f51ced599a6af1c49a5c +7990aaf8c0e898f6e5090449bf082663 +13ec5b8e14c3fc46a8d89fe81b122b19 +9dff798cacc420c2386cb9b16d34c93d +12018a223edee73ec79d6a70de6e855c +b6b3f51996c7da2d8adcbb44baa39750 +a9cff7f91e97a88e92ec296139e3f893 +f8ff3b25c583e5bfc98bbc6611c66805 +b3d0ae8cc6f8b0ea1c80736875d43759 +6d3a669bafbcf72e87277a27bfdf65ab +ad4e766c716d358344965c1c38d838ce +56d3c13f22a9e63d0a4ede416647269d +3c31f894e794a012744a06942ba03eae +253b4b351e64a0f134e55d227aa9ec3d +453e14325fa0df4006c9cc9c090f3ef2 +2f8cd9e9e969c3f4f7da005d9b3a2bcd +07be01d42ddde853b7922fe8fd42b7e4 +41ee388535a6c35d953d25c2afc4c3fa +498ef1f987dcd518fbd559b3f6e7f5e5 +60df5d647b0f2a1a1c5583ae78a802aa +5ed3578e6172fb621eddc76f5b735266 +5edaa3a9d2ad878c03e2fc540abd9fe0 +a7f8a33cbef694610e864deb0885ad0e +2b1b49e7a77f447b88f8dcad3abe3314 +25eb87ea0de507890c099df7c8c4e6b2 +8845febab90d9f1ec753e480f8b5a622 +543281460ccd25d91f383a816054443f +259776452cdbebfa9ac7a7f545fee88c +afda6124a134ca3277208470da1afde4 +fc3fb79b8f68df4ca197612b442d18ca +414b34fab9a686ddd7c09833790f246a +e353709054fe7d687aef9e8e5f5cf6cc +6ed3981d7bce6a268106493b3a234245 +a85110a55c1076d1fcf3703d3a7e1672 +87b0906f991ae7cc4f874ae1e3e1947f +5a6d85646e5000b67366641876aa5099 +566141ba5c78a7f6489cef7848882c72 +235919d96db1aa4cf754edb3bba2b0dc +4642371fc064150a577f10323b85a469 +ffe936239abd7017f7bfc6c0915609ca +afb984fd03784faa8815ddb740022594 +2b6739281f9372442df30e784b7dbdc7 +378be7ce4529375f3c1d14abc5b8fbed +0639759c5190547ca19cc8e5951e5e47 +59c5a07abe7bf0198a3455fb69efddd2 +2cb60802d24f41f7394bd1ed44ba69a9 +e5537bc980b7ca994095bf8cd85118f8 +7a3d0f862ba0ce66d0591ea017a5a94f +01fbdc44ef819db6273bc30965a23814 +c8a8a19969fcb59d1351de2b5a3cd7c6 +61094b11327dcbc2d3c3a44ee969e0e4 +c401d7ee7f4b11db784dbc395499af37 +968f3e9276f3aa6fef82ed8a61d04b81 +b22e22f7131dbba258932f12188ef7d2 +d5620306105b18413a36cd53d50116e3 +34ea4e858dc985a75bc61dcaff357b07 +1e961525c3b899886a6695cbb12d80b5 +2dc72d003e7b00cadd59a18c69891476 +d18f36de520a5e7b9865f36864cb1c64 +5ca7671731ff1731abbba7460d03a974 +1220392ce3f085c00b868d87660d68e7 +4e0d5fed7b5c900aca85475fab2a4bda +d3eaac23a80157018916fe6e4a56267a +3e1d6d3c13418bfb3e6eba70e32e26e5 +12e7cf990b2044b730065826365cd016 +973fbd39835ea18c59ebd76b199f070e +3ea95502df52152faa5f01e0a619970b +3275fb8da3a4a72be0f5a62a9c95c918 +1869e7d1ac1f6274db315a92f22a9efc +b98049008f3e8bc7aa0769b65b510e1a +0147652c1783a56e2f7ece44be2aab90 +d929f6a9ff59c5e60b59ccfd4433c5bb +45b758a4f518f3ff31363696132f5f5a +d225ebd657efbf277f35f056199d0fed +398f38098e892ef1765c6145d64c7c81 +bc98d84673286ce1447eca1766f28504 +1cffe198e119ee4a486a57f8df95452d +43203f05122ddc347bfb26c62364e2b1 +6e622dd961b9df26554a74575e482961 +5603c9ec50d89a0674fbfcd9cef41216 +52eaf68fadf470e9c993efb54a26ba35 +8143d18da0fd4c4ebf35ae9cf7046001 +ab1f046d57ebab648b540eff03d43f4d +3f686d154c4eb575205e7175efd83dc7 +d339ec7c5fe5332d889610bf0c6f0ced +dce1f198ab15efbacd9b68692f12da60 +01c3eee3fd9398f326e80d372041a405 +58832ac51d980fabe04165e9de493f1b +ce8c4b20653b2ef54f5abba8833ba809 +8eba6cef944ea7ad2e7d60f3670b8877 +9764928e722b2cfa738f8559197e32d5 +634d398e96eb1550956b8128cfeb0747 +e3eb5b9d9d55948ecb4501cb58386ff5 +99c5ec683c3e8b4634583e987c3eb824 +0ee2cdecd2d9ca288274eecdd87bd56c +a0fe2866c69f92b6ff34da7d773cdc8f +3c5b4e1e4ce6eb2322c25ecdccab39b2 +1ca122a8de138acdac472a6a05f1690b +cebf21f09c8755a7977ac0b66239c32b +fb0e782455a00cda10342c8727fca312 +a849550523fb4f524ce4b429f803a198 +da008760094ca2f2b175ca002de7c346 +c2e3013d05d58a9eb65541eb25e52198 +fa7e5c028672614f0f1c9acd70a24355 +f2bfce9c3ba5d173db870af344fe1829 +607b680fc39ff982e2bb6bc62452906c +fbb2c30027be158ad0ef7a06a556a733 +a39ad04e3d9a22056b2fcddb1e4a4ad4 +11ac264ac1dc20a70524799bf6f0db66 +2fd1b66d13f33d780b0d007c97f97347 +372e25f23b5a8ae33c7ba203412ace30 +32f8e0bb6944a6efe8b1351b72b8facc +d2f555a7c51bc4fc6df1f36da8feefe2 +ed52d6aa4c9fc48d5d0b22016abba54e +5fcbe3edfb7b66292463f66d5113277f +ed1aadd678bfbb12bdd9e63724a6751c +7e5ec2f64927098656f99a99667fe53b +f63da516ab4a8dc6fa5fff1660d7b033 +49f96038f20aa062772267b640a18d79 +7235c87511b978ef95e768196707e26d +20bbd391747b46634f4e8dd4b2855bc3 +c4ea4fb50bb5073f7a6fb78fae4f1929 +e7576c27844afc0a30690ae46a264bf2 +c78f003ed871f405091e3b00646dc6ea +24d79d62adf51f2d9ebf309a3cc1177e +95c7a3801edd45af1ed587260790dd11 +171aab4a1835b72067bf6657b8af2c26 +e727c733a6206fc7dc56b205fca0f4b6 +c7a26500d738a9a5d9663bc0e80477c0 +721064191c362794be96a678e11b49f2 +4e62887166c32d09ea77d8801f9ecabf +3f0331ed2e6dbb0d44ffb9ad9a561c04 +4550035e8e0ac0a4b42b9f8b4740f4f8 +b00ac137fb4a6c68e21fc3719282bcd7 +c7e0aa6868c12d905af7a01eaadc2f48 +0a1a18116596406a49b1479c3a914921 +24add36a4dfb560d7b443ef9e218efa6 +93d22f20e4687c8e23ea8d3ac33eeea3 +ae73145e0bf680f2da08d942e44c0146 +16dfe0d39bb143346e232014dd2eaed8 +19d041104bce2f5a357e13ef7491e128 +ca2d26f76e9d7fd2aa8ab8628cbfc4b3 +4207a6382322e1c1fc2396d0a0e6e119 +686f76e93eddfdaeca4d269b68565e2b +f78ffcb5c1e00ac6dc34b14f9971bf1b +58119fda499fcda0561b9b24ca9012b0 +2383bdb39e567976a9b3ed46dbdfdeca +daceded1ee5fa6109ac642ae0f5ead27 +099c1f1a68842ed1402eb4d2d3662775 +db48d522318c2875999ed53966f1efbc +561884418c8cd7ed1a49a30caf520595 +00a382f9911c71b529d999a4e2b62823 +6687f30a3a8a3ed2e92fc079d758bc92 +c6f5e2747df864bfd059436ca6e68a1b +afdb93f79ec175bf8f15b6cc3de97942 +aab7eb80b301fbfa31eebdbfda995d13 +87a6487a84aa350adf30b1673cce098e +410aa509dadacccb67d5b5c70c10e135 +b4bf6f6511edf7f2bce74646da879bb8 +4802fcebd761ca4f04c9a6320330fd10 +bf87ec0391761d03cd1d21e9c9a17f10 +5f0290631266d8cf3336f294a81ee799 +bee4c45b85f5534ed641745bdda41a11 +c06a5c04acce77ba50518e7362430b51 +3d7fc5be8c43c91508492f3501cdbca3 +228987342a7bef48edde0be78b71daf2 +4527d32c9fabc9e6bdabcf9b83fd47b9 +2bf8800b0a2bba388885341901ccbc59 +d58ead29f85f570f82ab256393aedcae +c40ad31eecb503cb54477ad751dbca6f +2b464e5c68c99c05f953edcd4b8c8683 +5a25edd2ea311630c3c82997dcaa6a49 +760206273e41a2d58fd4be7260f6b931 +3df4cbacc7e187b09c03b3acd7b4c6d7 +926f71a9891c85d00e8191bddf464b87 +ff52f447a6f7c75430a79da06ba39d0f +afba515d96a4a5b9817d5220eac4894f +b84280964d75ae6ac958aea8d61d81d6 +d258f7c463e37bc0db94c47cbec6f684 +221f82ebfdfa80c05488abda273a4592 +5871900c24691e816067652ca07a0d86 +2c5e2268c8fc17961b808a0545c762fe +06fbd43d8d56f6db8f3fde9f0a84cf21 +3a82b89a4629394832124542aaee4cb5 +50dfc2dc02d6fa642c48fbc745c07fa9 +2b57cb9126bad18148236c9e2797457a +b4dc9b4cabac11fde1835c7b9a0b7704 +026ee57926afb2f653879ec8384edc94 +03b5c6443bf8fad832a0ea7de6cb4197 +a30ee1b159f992b90e1754663bd718f1 +60e5926142fbac1cff424ae3c217edc7 +87cde4c3ea8d74711428501214195bf1 +d055161ae59aa73b046962ef93f604f0 +ba8d2b9408ed255ee92a112fe7ba59be +a51f028bf4caf6ef18d8ecfd5e453270 +a759f684e27357ca4bac1c1fecf39802 +c05ad0f9e272d01009ce9f31c219ef25 +d5b018f1d227cf6f98bafc06930a2413 +ca10b868cfca745de0fe393d5e8a6b4a +616a72d9aafb3704653d199a334013f9 +a534f12a50feb1b9fbdb6cf0a8fb1d67 +e8604fea9f67dc12bd9184deb7edaf33 +b2a486541730498dd126e9d458440ce8 +976ab48c6751502bf5f2fea0dfb5310f +47be009181fb3492c6d5e5469753f6af +67ecac800d846566d1765e8e06844903 +50f5cdaf8918be25f8878eb8c0623f2f +b0ce784bc47018b3ce79441b3a662ab2 +81aef75b9275f71d450b12c1a0857526 +ef35f00480338b2dac9c1950682eaeb2 +154eacfc6b2f572377ff267a1b52ce66 +100f5bedb1471c6b227badc20149099c +6d55b307200e6b208beac695f0306405 +246f03826f7f765877b9cdcea9073df0 +f582422487fef5728d153eec1c45c3bb +ed85b9e4b2b8c0d8276823683af997ab +5edadb206bb695a5a762cb0c63a91dbb +648471725ad75f53de5f828da8d855c2 +cb825aeb9be9efd1c77f908145302978 +57ec194eef46063bd6271476d64ff4fe +0323a4cd8b03d3be4318aa4e30994b59 +283bcecab9682860627bea8e19c619fa +beea4e795d094f655ec348e579a88d6e +a9f45098d1ca97e579d8bfcebbdaa9ee +6915021b8d237a184b0ff9c1ad810c25 +e3b3f56d021563fafcdc30b0be5d1ef5 +b20d99a2fe8036c41ec7888c9c5372bc +1d58e6036fe0ebe3815b8ef130e93337 +caf7e7bf96a799f0547469cb698bfb68 +06807d36f025df31dde07eccfc8c3510 +124174340885a661df08acdd0dd19c7d +fb0b808fa7492d29be6089d0272bbf20 +7692814314e133783da6f832fdcfe39e +6e0ee5760ff87bcd311a86b04eb61441 +3e5444070552e2883b1fdcdae291460a +efd1d613b76045979bf9df4affceda8c +94091285603e6b8f0d8e564c4ecd21eb +051794625459cb29e70d1c40b5d9dba1 +d956888c748032e94bdd8f55f4095828 +ab84583fd6bc84dc0c21912dbf68d3a6 +e79bb1ecfb8dfcfdb697895c9a19c579 +f868779475a07fc4fb4a407e6b26b8a9 +eae60d5667189b9515b2280c4b920940 +d46268bc1722e00e20486fba1ef04278 +fa426057fd9b1335d037b5217f52d973 +61fe954f427208941a17d4905722f044 +cef87bccb142c421ab8f108a1e5299f5 +d637cf0e13353d6118ea2d584a50be90 +6d1dc4c6b9e16db400974f4ec8fabc62 +2745de855cf97e8c05070ff11d226fb2 +985c64488c8d38b8494cb3c267ba6676 +ecaa6a131ad56cd4b8251e9432dcb85e +4a3bcdfcfb0f8bc7f03a9e729d85c35c +690148668c6f8e55b0b82f9ac32167e0 +f4c31e2da6db4fd31b8497af7e8360ef +1c3d77e696ad903f3ec5f7351d437660 +1d894655a5dd22ba103f0a3d731a6737 +e507c1077a8a217eaadd54b426714bc9 +c973b01a7f2dd08bcedfbdcee3c8612f +2dfcc0c8313299cc65cd40177c1d62e8 +7f812d21ff175aca1e1cb1a4a139b3a1 +2e472204c1163e52546ca2fb02488149 +c975707b18c75550a8def14dc0df9797 +3339654e37c35a19149197755b7a2af4 +031b845f225dc2d5f21757dc66d14f4b +ffbc95a2902738cab6e91b61df16e3b3 +4b804e57dd6f5b73e952851ea11fa658 +ff6cbaeae5f9c1b34b5b30ef045b4d97 +0abc9e0202dc3cbaa73b151bc3719ebc +a8ba672d93697971031015181d7008c3 +7be81d84ed999c2a9801674656d8d667 +875bd36b125dc2bffa5cad53cc421ba8 +7cac0309f7b501fd028e77a588168b08 +7b5088027e9209563fb557eea0e73354 +efe3e10b0df2bb7eb42f90d42fd6baed +215162c09042bfce4ada6fb34952a398 +3163a1b778215fd9e58f9160d1eb5812 +89773bcfd5c2a22982c25be54eae85fe +345f75dbbe4977adfdbc5b6792a34e9b +6f7e99ec47f23c1fce78ff4dd08b3532 +9fdf3da54f2ea563ffe733fdeb360e83 +96e23f7ca3a59099ff1918181c6245cd +a95825ffa9e59bdd730890c7d04d2ace +40a9e2d6dd6c5a7898e3a803dcba38b0 +7720d86e3e282ffd4420f58ef736f620 +76e5bfc9d525db667772a5aa76923aad +1f5600c3a4762d1dc289dda464225c12 +ec9187a89c2f150e910b6db5f37521b9 +c957531b1025032ea0b305f420a17ece +9b1eff0bbab045693a1cdaa05cb750ed +571f9ba3a66b0d23d6cd7f5f4480b261 +6f5ac41e79f4fd5cbe18781709195276 +5d4a98f3ea0bfa10d373f22834933dea +831630c87f4d7739be3f1f4caeea3c7e +c0e63aa286d31e0c48a731e19549d66a +d4e49e3bbe872055ffed6e3720d8bb17 +9c2fdbed9bbd30efbaec3f758e845864 +9e398542b559c4384bbe685f908ea073 +c76472ba190d1b56c59c51b6295e0677 +484779989b0a3242a29d6636ef24b03a +147c263ec80caa6852d3f843e36108d6 +77f84342263e968e8e74bf24b2e885ed +f9fd2c3b3ecf2473f64e746d4e2f41c3 +fc9e730b2ae47b866a61e83749cbbc21 +a91bead9c31c09f26f32077ece04e9c9 +bbe0a60071eafc8ad1b0ba55423c3ac0 +921fc888d48899615a4cd3e0f8c108a7 +f1d98b6f97581cd027672675a5b2bd89 +2a546549969e90c558cb5cda11449e10 +95f49907f8266e97e38772f847278d50 +4e64a2cece05dbdcbc9decbff0f9c860 +61ef37866a52db902a968f9331f456de +9f0f344a49d55a7ab2636abc29a3a756 +112abdd5361c239b238c819e178c5d3a +62b40735525d1d736bffd8298d550a22 +fec2d0600bf363a510034e2619519212 +4a095b96b2690d29b900c4b86c3d6d6e +8f8a25a4f2e14ddf4e97b3ffaff97546 +c45f40d2c8cbeea673e8cbf4881bc417 +1450e96f901e8c3188d29695de805309 +82a290bc010cf4cad62980f3ac82ba1d +c7c503064f68b789e383e50141315705 +24fa3f103d0a6d0bd036acf8b7cff5fb +024cf805805f3c07d952fe4606171774 +c6eec19d700059831b4628a64d1a9171 +fc893fd3da38b57c4f2d985631cb0bde +f6a7a941596b33fd83fdbd54873e6b42 +e3f109f2fd5bfbfd96e8db6bffd7e9ce +a846ccc3030d009a44cb7c4551e53004 +2951a829beffd6765d13216740da4bcf +a1e2322e740926668d55a60e796f6c4a +aadcf99dc8b28b754c36024009b43be9 +ebac4e3e401ca8df928f025689c04569 +fdae74a398298b67ad08f4f7306f9362 +c376211c029ac0fa681fa8087fd5b74b +3dd32690103e06b4c27a5bc666964213 +d3cba2942555c79ce5b73193fd6f5614 +ab611e7b91297147dbbb7300a82364a1 +31d5b594ccbe8bcf025adce255a9d4dc +87f57692433ac98b1b7fd464008dd287 +f74d93768789d739b2e553ab76e4bd18 +fddc2eccda62e39b21a1bf03fd2d4523 +28b86339c5162eb29cee1b06597c2b5b +08c6867990c271cbce016e1435f0363d +59a076e1d1223fe3c5c0e562e207ec0b +3609691c5cde44a006be3dac8a653f20 +4ddca3de3374dd72105f100481107d7b +191e2d774b290acbf86948b235f458c4 +9bc60394ea559841f7e4bedb076da4ef +dac69e0eaa66e877099618b3eb0b9dbe +796ce9e364a2992a66fc4982fc9ef974 +190cd06ff7f62478d2b233ed5117119c +aecf1364e40ebedb1f7666f51db810de +da1aed05ff8282a04c9096d6bd22b9e2 +db72ae991ecdf140d7658c6b91657dcc +462329601a362f9896649e99a48c480b +ddab5e501d28d9b63e1ba61c309b557a +3448e2fc2b3bffac02fd72de681f5b45 +15cc77c86a29c7f23fb6ee97d274c869 +7649b357a9fc44ffe7210f34110fc68c +d383b6f75fe0faada84971fdb4fadec3 +ffffcd5f135ed7face975a1ae193b91c +6cfc388981b56ea67830c4d57389a93b +ed0866e0eae0bda71f5c081b319336b6 +e626d55222fb76824e8301ed04ca5a47 +cabdd692bb2801c749b701e3272a4bb4 +ae7acc250e6847d31578a2dc79bddbf8 +e463968a883d2913e8db185b5e894685 +fad2b170366926d9ab4ca66559d708d9 +7e657108543acdb0ca300bbb4bf16740 +8935e69ebecdb8d1b61fd8100a52a909 +3fde56c331c137f5370a1ba381134239 +fde48a683649e9ae3bb7f644ef38e7f2 +be1f9c368a33f545ac6296add9f81f81 +c9e7b3aebfaa0f2dd9808bd88d5e97c5 +ecd6997281b753c028b143c04a7a449b +f276e94913daca36d5e418675cc0c64c +31cef7f095875771819b4480f379b9c5 +95d77e79c0f38dcf50d23c777c3d8854 +49982bc8a97a515bda01d9254898e5f6 +9dbce9b99a2877ba56e2b71e0ac72298 +14077b2405cb31a0d1b2d5cc472e5d4f +53980deec2db643c8cc059800eaecdae +3f3457fb065323b7eda1d2611c3b5f6f +554cd12e1688bad17864b491f2168c91 +cf57437eb38925b61c2ffb53a9ad4e6c +ca16628ee17c61b344710e611e5abf79 +8076af946e28cd3b4065ab8f67baf747 +7ac8b9fa9b68473237ef9f3977cf1427 +97671a537ada0581fd57011ea6c61865 +080705be45c5e36946656736e76f6bad +8ae48890daa96bda48e64d4f5f5755be +2b8d8327280c8e2dc3382830cbbc9da1 +7f272b132d5aa2642141fe23f25ce3a6 +bb044bc87de2ddc29bd89ee26f1fa24f +7bfb18ad4d709bc23b68b1ee8db932c4 +94e8794150d35113649de8f20deccd53 +a26d6509446e18b9c29e37f5eaa51c39 +e30e349f0c5ca79f4918cf00ff95560f +d341727f85ea83e238fc2e19f0796725 +a7eb8d0b9f446f1548572fc71c92716f +96452428dcce695a01e793c0deb79b7f +920709894c018e5a0e04160e88627319 +db999c9ce1580bfb9b8f33cf28966165 +44dc72330bec71270eb0bbe607a9a527 +95df388254a4e2859e8fb8a18f7a24ce +ab0d67603ac05c2353b52f4d6a868315 +e66806021b38eae258aaea7511f4cd34 +4de7e7acc3acd53a7aeab77bf71909e4 +20a0a7cb6e0b8f438a2f4dba32573dd9 +bcd47d1f96655a43d67b3291b092e0ac +6d71c1f1478e0b8106868bda4711ebdb +c0ed477d68d9d214d7c21695e96126c9 +eb79a35e0213e20fdb6573e6bec5c17e +9b8b4b42e4dbc9edb04efe14e645a759 +61c038e75ed495f88f10d6b5afee19a8 +ffbc21ba7911d146b23422abeeb8944d +fe3d46a81398831a527e95871223962d +7e1b6dbfa824d5d114e96981cededd00 +864d9ebaffc24ef9bf37b35c565769eb +7c0c0577834d29be479910502833588a +2b42811d70264d52965ed3ca6bcccb15 +b400ff1a4e962c4e2822f323a8fc9b47 +c222f4fc698d00e3b1f58941c760a51e +0f962ed52174a5468ae28697f08402b2 +bab4bf9d91e82ae12998b53b3050419d +23b9ec1f564e4f438de99c7bc4eabc6a +a8dc2edd7978520d4e807607a411a399 +064283853646e8a89c3ce967771bec28 +452654966c6d3addb9fdce005a66bb1d +aac9ed1d22c81ffd6c84db03b975de59 +04399da03fb2bf7333c9b252c872d66d +a2630d23f73a02f52b1926bc979bbcfc +de0121a27337474fd0f92167924a92f0 +a65ff54b2a9e1198173495219c3b23ea +33bc051ef7c58fb8a8c717ed7b685ece +da122f4d6b3058ce387e72f886145f47 +ba1065e873c08bb49da7f5176f14efdc +a1a687b803f4fa8b6ee53de862614613 +d23762d6a59655795b47189465a736e8 +d533763f78b2df74901b8486f32cf509 +ccd960d65399c1bf4f0e47804d4c3d54 +2fa08f7852b342125aa3001592109be9 +0950de4f7b17cf153474c2c0b8c24a5c +66eef281ac174799a73e174098eaa253 +846b993eaca299d38c1522a026e63720 +76b0b0b60246f4e8e92a39ef7dbea194 +01aa32191c80c02cb3bcde3927af1a9b +9f35891f4e5d295a18d368d43e394eac +f51c6775ae00a9d966be700e8a6d677f +d2f1f6074fbc84f2bfbb458d14c22b0a +adcbd69c315865166519892f2330c881 +514a7a73aaf4c555dcf420ebeefd12c9 +0833a57db49abc11baebadbd92ed09df +402944ed743251abf17c3895a5f71959 +f1e2d52298c6d48092107dd89e31f1a3 +9cbb0ac0f3b5c9d644ff7f5d06953c03 +52836b2719ed26c47bfd915a8ef1ecb0 +b00a3bc97f34ea956a87fbd96a32cb4e +07f96bb9bb342a1e6703673cf470e482 +9a0460cb0110ea14d03d273a56944311 +c339bd366387b6336fb6644f5c162e50 +09f11ae0c5e5b5539659fdea259f71fd +9fd32358f9428860237a68cfb34fcd80 +faa02eea8839eba5310d66d6ba7fb482 +6eaca5bb9e7dde5966fec1d5bff308df +e630c63c31e650468673ccd97fa2c320 +b68e00644250808662537b72d9444841 +76bec7c55bb1f8c6a320945d36a6fe76 +22e42251f36fd9fd255f2a071ac14e14 +88e25c69cf9b4c411958a2de130990b9 +c4ccd6ec73f501da1474614ffff5c83b +523e630a56abcc021ef527129a7a77ca +4a72d722d3244db68366a09031c54401 +b265a781c6c9e6e2a84fc33a930fc936 +8b60d733bed585f5b897db1bf278ff80 +b5f34fa794a90456f479e865aa1d0565 +3e4fc13da2cfb425b77918206e6a8af4 +0ca111ebd97759a593c952f6038200df +d4fc56135110ec004894fd597208c9d3 +12b22148a30a8b885cf940f2c94566bf +2d16952cad2b406861f4700667e815d6 +700d730968e88c3b7e9155472abf32c7 +f578de31afb37c4cfae26cd9581a4c97 +b4f0afd12a000593a170d36e1df180be +633108d7beb80bc6937b7080614cb2f5 +041afa6660dbc5ef949e2dc364fbe57b +27895eaa69332f5838f1e39ddfdf357e +81e4a73a8d726c400813b984aa771f06 +f5a34c048fdef80e5eafb2ab34935fe6 +ddf584f99b8a1560f1f37ba3d31481c6 +62d9f7384486301f29bdb34892960e15 +138615dfca9bd7debe5cc4a2ca0c3a29 +0fd3e295adac4eb8c2c974596cb0bfc1 +fde32792c6e1438108279b2b1217bef3 +46028609922581afcfc377a820ab5684 +d0a8e7af23e9c036f14f92fe04633a07 +e9372e73589d60f3c5ac3908cb5d31b6 +cdaf68b769386d35613969a715fea7ee +2374b8d2e1a7be35583a3f2a80754e6e +3015d0e2f66dc5863bf5ba73f28ffd4b +542a15317bc58e13db1115d4c05c5936 +146c07ef2479cedcd54c7c2af5cf3a80 +daca6f5f6def6b2b9ae72359f71bb37b +842659618853c79c4790f9b6ec0bd31d +c8051456110d7255ee1184923b7bfd6f +7ba370fb466a987577504adf88534418 +7f42b10a4be8ce633aef426511980053 +44e444b4429f7d44faac23db92cfb1e2 +d545d2d430ac8a26a2f0d2549b970449 +38b86a456d1f441008986c6f798d5ef9 +0a056faed2e9decfb2c355f380991dfe +240b8a86ad30adccbea703fc6edbef01 +42f463c8479642e92eaf6a151ebcf9d8 +41cc0e4945e162021cfdd993f4c1104d +3fc45e97ece3a6d14e9826afc4746a45 +5e790dc9486602b8667091e867d20dc1 +0e2ffe9471ed9172d76f80003b527a6b +218ee1a4aef9503d73e71779aa7d0d9a +0944b3a57aed6b439c78cc4cd8f26cf8 +6de38ee68596592a3c3d62a7cbd44c98 +5ee45602a9850408b639e1fb4c38822a +b7c81951d322cd9f461ef988322389a0 +1296633fbfc8a045ad5722f89cb337b8 +5887841545986b5f4b22a87cb49f5ebf +3943e85eb605124efee8b5aa64819c63 +4e86d530212a0800bafef2f0ea6ca76c +a567843b87da3e95b12164e999d9ae3f +545ad9c244c7dd51ce3095e1e19dc97f +c9620546a7f3dd52238863736188f7a6 +6961d7607f40a71bc7f0111a7c0bb443 +aaeb1ad1a7a3a65f3a43068c3b739561 +5cbf96a18c53170abdc28195c6a82d60 +ce03cee6411a3e5cb00d8af4dea091ae +cf50063bd1845008d6517fc11c9caecd +2c70028d3868f800c891bef563bb6fe2 +b22cb184c5a56569be6e52b33cd3eac5 +20f1d2255fe0ce004a3049a234bf42e5 +441ae7a4a7d4fd143180ee0043076fe3 +0d3bb8c2a405f0729430a488c3473ddc +5e4ecf641a1adc17618c0d56066468d3 +b8f7d4e6339c33ebc0c883d8cae3ddd6 +1acec837ea80f1921650825127a5a3ce +6f6a922aebd20842c704df7c7571feef +e4caf530758740298491ebe0750e4200 +5b623c59af783c1a2448385c8225c820 +77b07e55404c260105f8007a0c93a85d +36ae58fb5c5dc933ed046dcdfd20d55e +a3f811f4d29ac814d52ddbfe6c00ee05 +184d720ff26f5629a1e91a8f3e9c5f68 +0e7b5ca5d2fcf18507b663a73ca17000 +f9d71f3723f29a8deed471e0ecd8fdf0 +e46730fd7a686c5d02df8db4b3154d38 +16c678dc239dabf760f8a7d4369f2015 +14252c4e8730223487160e248889ef3a +02ead54d7641d63752e368936d9b0b01 +8aa5e3dc1a10b5a62cdd4961e4eb1176 +345c182979ce8de0f6e5700a6bdfc63a +46304e75e0dc89bfd7cd0b00131d5a64 +b916b9bed6d25bd7124682a4467a55c6 +40e1042a312806f4612152d057cdb09f +11c4e0112ceaaf294dcf8ccd0d8ac1d5 +7ff71f01249a43aa214b90c6aec673c8 +9cf56f394795d96b937a6a5e9929ea9d +be998e41de1ff6960247cc9cf1cd7ae6 +894a2b27f47f98c8f6638e0dbe4eb837 +9c9aa89000ec58377140a70677ea6837 +58f18c8440f530a99c0baae01c89a70f +baecdfc57b70f54a42a243914ba0402b +5d35608db8e6daa18e1a8aaec9395a8c +17c537fbc72988fffeba154efa43223a +8de3c4eaa0b44000e4e957d4b4ca8d07 +e9e943b5d15c5eed56b7f67737f62f8e +dc732e6bb0437202d731d46f30d5d7e6 +f55700efc94b8238d8e4d08d82d0c846 +91f867cbb6ce00f2d7d251d969dfd198 +02d79ec7f989d13fb958b9d5028a2f1f +3e53c1b98588b7baf6a852d9b5812bf5 +b70d2ad95db6549744dc246d670a056e +bf9aeb8ef1a073b96c0bb30a938ab987 +a3fc0f88c3833c3238e856e65fe323ce +22d6d44483ec48a8d1aaf3418b70ce32 +fc02b49d5eae32177a1a6af6587458fb +e0beb4ef2fedd4e9726e3e9e11b5ac48 +2939dbe554e1a5a69863f5496cc3e2c9 +6a574bd992ea888e5df52406176c4207 +27101f43db5eb7a34f5dff66e57a001b +852b449965294cf2fa8150babc29739d +f138af416eb00a1018450f3523f608cc +ad3d188d83b2ade122564faeec73d0bd +87a210fc32d104e28ad89831311891c8 +65a55cb301a640d98e574bf82ab6b132 +e5221ed7b3f7c9ac421fc264b6a23900 +eefeed2507792246ff3e00c9c8a7a95a +e2b77905c722aa8dc39119f2f33f4b36 +3568ae9a3f9b551942124acb8675e4a5 +e1deb9ac5c8e416b78ee2b07502df3c6 +58c3885f4d3e646222796cfd375ee909 +b2f57c09022bc371e7b2558ac9b49cce +3a205ab2a2f5106007d17c1875bb8d3c +98f32faa17e4468705e3863a7365fb42 +84d6041b5969b734b9a99de45bd397d7 +ec5932106e6b1bccd0f80bd2d7c7b306 +5b4bd9815cdb17b8ceae19eb1810c34c +e78250b058473688408c02e2f1f5fd13 +5637c8d7e7222930cbfdca101220c296 +0ac87f9e53597c7cc8ca9f4efe2706b3 +3fb162a4fe05c08ca2401e1d3c73b27b +18d24eecf375d4f34d8fe52afce4c083 +9bdaad751b444ea899521e4999ae2020 +dab367425750482a00e39f5af7b3833d +f7fd99903cb3bd3f06330e9733e477a5 +efa9007524bc13baf940e7a803e58a73 +87db8aa204d6bb80fb8e69ad73aae22b +2df03f2a9c30b82c552d8a42d6e99146 +8dd0b7dd0bb33d657a13f546df2cb0ff +c6c0a1d798b33e1651d8a372222dbd22 +4832ccd3b64ccacfa63929722867decf +43be2f60a6db7bf23ed742e2b13ab659 +14c93a357701b53f60882eb60496f89d +ab5b741f88e45c9907f5dfb284e6ba93 +b2c1ca005e5f997a94c2a2d423d9a0cf +2c8341f56c3dccd94c433a74374f6072 +5fbd4849eaa0410391f92c0b804cb0f6 +53b5b773231a0d69213a5658ee37f9db +950918db657f08b7aeed5377d9859807 +9113090666e1b8bfd8b4dc59710a8a00 +ce407db965dccc652097b371cd0a5a49 +33a1633a08ceadb490f1da4faa9af861 +3593a7462865d783ea6f935465c1a3a6 +6a58e8cc4eda4f4171e0f6d861b47790 +1663c12de46424c19644a5cfb2d27fb3 +cafba385846bc9bac506aaeecbd8bd19 +e045e90337603a7102d928534a2d248b +d4a84ed3c304a7e852a4e38315c2fd8c +f7743358a1dc1ac99adf0d322d728bf1 +c368fa5d0ff0f6e336db6a66d9a63d0a +19ace289bfa6ef492630ef71f27f1c9c +264bdf14bc0415619dfff38e959b0427 +e7960ae68c5e2a31422e140c413ae7b1 +654ce32db587ac4a76a95d216672663a +5bff9cec94f5ab89567a1d0a24c1bfa9 +a184f4517f73ace5bd3bec0da1852a55 +0b5fe2bf13f5414b91af52ff0d10a79b +1a8647bafa562cc57aacb5c7c62b638f +828e9af0cb1dbcd622ca1d63e0e1bdc8 +cbe6f1d64cdea427ef66eb78b8855711 +235966e001353a4a671da45065525b1b +d803fabf3b3bd0a060b1eb7042eb7659 +5f4b6f1ca735f44296cb984c1801ab34 +371e5b91a7af79e1bffdfea8e5a62445 +5b346431022303cab5816981f8ec696f +621b70c222b0b3dffa693fb015efd519 +22b416a4835fa528e312e7a27522e970 +300f139554327e63b13b44a2e3040ce0 +d57b80dbf2d1164433900d8c6e753b5c +cd6f27e5bb4b648684dca7c2a5c5801f +6695bfad5b17c19efd236a560f93f620 +94b4d303549927a4912bd3c6cc5639a1 +e332565d743a4b7db9952210350d3c62 +f735ad5c7410f050691770818eaa3d1d +6a1356f3d456c337bfd561624154cc46 +22608871f31618ad6f8df0f9a1178998 +0c69004182d032b4cf92872c4d6a09f6 +8458bcc7abcb4e10eabee70fe4e8b44e +4704984a628b889b27b134ab58d97742 +9a115ebc25a0a303b3ffee1a7437146d +fe6ee789aa8fef72503c64b79c7cb5b7 +e58a4852ebb956f4056f7aeda25f9413 +7fdcd8ed6b8880e31310e8613254b8e6 +c0bc77f777b93d65a435e81421adcfe4 +7d21fe8ef3e29df1ec3017bc327a8371 +e86220c200f12c6ce3b15b86156680ab +0f92c08458d44aebc2cb419604be833b +a8dc201ba917885b6362ac200308b4a7 +ca1aedec008657bee2e6bbcc63e21053 +e3444859b200505e41a3e3352fea93da +14f426f50f4afa3a9a5f9bf5b879b744 +2ee9e32270acc80925f62113f94392dd +28deb57b1fbb74d22b4ae65204502993 +aa5c64e78c74f10ffe0a435a7d1d8ab3 +a2ead81566c3128009dc7ffeb6605494 +ac8545899003da9305956ee6dd18a471 +cfa9dcf111fd54c29fa6014dd779e497 +3fe4fc53ae0ded41d1b932caddc360c3 +cabad31261fdd6a5eb76834f049679ea +d4340b502fe9f5c16ed28bd799a17e71 +8a0d33b144eb30c117a3d456559d5cf4 +b6d7228bc818c5a4346eb99741563719 +86eacb6993cb51ed07f72f2f91526662 +da564d9ecf0fb407ee4a816a6012e5c2 +41f31b3f6da7ed8c03772f5ee36aa866 +119dad86ae1be26956470005db7afd24 +20e1b9b2d102850a752c098fc4614f40 +7e854ee55e83c13a6bb45cd55c4d49fe +4eb681f841198895a0fd0a4b1e2f8ac9 +415bce594eda2ee5221147183056d56d +581e5329b6d82504673c4d7c46ff3129 +86abb910b1840e895f695ed707f65433 +5da4353e89def83877aa4e8cf3310170 +2dd4f9fb69277367a096135d7d1bd439 +7254267461fa5b1df2c3e391064f4b75 +76e91ab53cdf8a08ce71add2aad7117a +715d1ac24d4b08e27ac7db3b4df844e4 +d1e1f6cfd986dfe64c009ef5aafcffa9 +7daf644c4999f3f82ad19ee6a118f2fe +d6e58050557bf4bef80fd837d594e8cb +2b87b1d305f07c5704717aa7e7324011 +004e6da6677e401eccb9d23e075aff71 +212cad0a751bc284038a98a525ff7e90 +69b64623f86def16ce17d454b8be41ae +370751da74d8145ea4153e218746f10f +016908e6a21e495a617bc24c0d050726 +40dd3550d8f10d93cba27deb289f620e +95e02f7a0499f69b5401438eb8352f55 +917bccdb12ef9f132bdf78ff1d39e174 +71699bca367512922bb0d9130bfb9d64 +3494a24e3892ed7e2fc3749c0e22a2f6 +9b141cbf65189b1661344a0c56b1def8 +c1f1cb2039432fb0174f3b99d393f601 +46d5439c68be91fa15201edf2a41456c +249eb42739c27b22511e1604ae5aa561 +855e5d12216d747f89e7443063458447 +7c897c2167f77748644493434066ae04 +88256c6e5f2f065962a80ec48ebba834 +33432a4d8bdc89d5e916779a63409b48 +144a5ea4f1fbce22708f459b4ddbc4c7 +813d307ff728acc84c791bbe6b001e12 +87e9c3597eb886dfac124d20459a4182 +4952278fb1ab93867c572bfac0082713 +9fa16c784b1b979eff483e4b203941b1 +a16fa9635abc982ebce37f97a82d7a58 +3e77e559b968a4c79fe2b885daa9052a +02df026f33e62dba2c10a1952caaca8e +7cc90a6f535be39935215f0cd1f28bf4 +279c116aa328b23168545060fa2086b1 +e0b1a605610f4d3196be32721050ae0d +759d05d9478213e50a48a3ca7545fdcd +2e56514cf9e03ffe2d10cbb8a01580dd +70bc5392fff93c24301acd8ace1097c2 +126b2b7a6935656fe296df8557f5bf51 +e25dde36879ed857d502e33ec8e642cc +0e99ef084328bcfefd4d0130a282c41b +a06aa11872ff4ee751f00a22810e6665 +fe92d0d6b68926940d3c06df288194e6 +adf281ab68fe7f2ecf11df0709aa0582 +8944fdcc8c392fd637aa8529a04acfd2 +0a51b6f97c7765a89da9bab51b70df60 +cf3f2a865fbea819dadd439586eaee31 +e47cd52500f9507a477072f6738f5b0b +b629cb84b39bdf20d7d68b245dde56ea +8ddf33b4f339d522b92984eafc17d932 +f9ee849c07c646b7a71d9cc8b8682506 +845a23bfbed9e43c4c866fa474be7ae5 +ac0e4f99992fdc2fd829c1e39d4a0f85 +d9f9d87d0950a11a870b763bbd6f3d2d +52b9c2acc49533fa9782651e481d125f +713154c3cd9d72825e5752ca9e6e221b +a7c84d6d5a617cccac374e629df30c32 +e29351ab419eadc32685e89b46d8df7f +0fa75170a54de978c565a8f3e87aaa6d +de26e24e835669d2777b5af0222cdecd +706ac4a6c7151728fbc6e01af9762551 +51548e9396084cc0f79cbb718b49602d +001f12cfde389280e2006fc5a5739896 +7fca975872ca9dc9090cd7fca82cdb94 +1a3434a24eba845273ee621dc551a484 +4bf833b33656abbc8ceb478f4b9b499f +0f0e9fe8f7fa4e1a770efcd895543509 +9424517f98623de227e504e4e1131f7d +5ad8ab470c30f477d7c6b5bffa42acd4 +37808c8c9488f99d089838d7d465274c +8e15e4a19102eafe4136acfb7d8f1502 +9b5b645255307c844e90f56a2bb2d0bf +e399e10eb96f14f58ae70853de498897 +5bec9e8af0acf4571dd506a851e304d9 +ccb43fe5f257c057814b7e7e253c6ca5 +81e69c59ce97b60da9f25d02d39af536 +257115c86f1b7261d6854ff84710967e +89bf13de0aa8c34c0e990af8cc056234 +bd8a89c726bdc3096aa0cdf99187f790 +ed38c5c24fa59c78d889f9b7e5c0e3eb +1a4d91a6e4828bba4e48641eb47c04cc +e533685511fdee8ed435ecd908d9ba19 +c4f349f655a96993ad0b0680862f731d +674f3def787399af6e8148d5c09ec115 +fd1fd0a1e254babbf559bf1dff17be3b +c1a860a59fbf1aa59cc4fd8358900f23 +7c1a5d12744dec24641ab8ca14fff597 +5783a5c8d63d076972f4661f9d8b9b79 +30acc1ac6de04d373afeb61039029ceb +e2533fddd0850da09e119368a106e0de +a7b0f3b699e20bcae5c880594006436a +0b59fd40b443549c917f88a348b3b9c9 +8ca8b980e7531e4d78d0a6b787c1110b +65c1026364078cdd1f4de310c12ab0dd +915a00868b4dce1238b6d5da8de37878 +d99fd76b7b60817974d0515934805961 +a6f919fc48a0c6dc5005c9188e3f7460 +980a68a6988c40a4ed77a9dc2c517485 +b51501d2735402b74db282396e5d2c04 +26028f3375621d8bb0971a89ada3c71f +cc6b164294747fda794af512bb5193d2 +bdb2ed86777c39a9daea5c50934435f1 +e8db92077ec6bf69aab2ffec184aa4db +8d189e7552327caece995598a5c10934 +f51e7387de4082c40a77a905ae3180e9 +5b996944fca5160289c5ad6e923bb0ba +3244309cff42fc2f7eb62385e536ce28 +ce012c16757c1328c5dae3e8c4d7861d +2a97020ded0229afb1a8879f4584cc3b +571130d5d32c4ff3a93af13e82d570e2 +6174ee50ba2632ccf006bd17e80c3d46 +0cb5b778715ccb6b300892e974e2f427 +3b2c0a4b9cb066507b320f87db65c938 +c9c80a13fdf9df2d910df2ac7fad39c0 +688333f9fa37f22efa526d59d20de9ee +9c9046eec60ffced1ad3dfa673c8ed07 +dc6edd64d7a13befd0d1ef7e1bb7d77f +69c84eed586829e6c7745c9e8d82082b +b116ec0f9d6cb50c7cbc85efa52b63f6 +3a6fd3ef9394efd432419b3104389683 +865814ea0f3bc666774a873400717c53 +2f8cd79ada7a2c8cfb1923c71cdb4dac +75b1df3e94fa84175e62a653be155b84 +14a06c67943a9c7d7b1cd66a6a7fbc2b +80463801fac263134be3da3d45cb4bef +1d1e63a3fcb12e33abc088af6f76020f +1417171afd3e17fcc7670c6d17ad3a3f +1e0242698333591c46dcec8c522a0310 +7c9f1a90bdefa3ccaea80f8a894c5cd7 +88d96aa87b5f1141266273ee8b2b509d +25dd7f71eec15a4d010f74201cf1ffe1 +41ff29bebd17ec9f08a252d97579dca9 +2e863c478429ef3ddca46ce7e471a029 +0b24cc97c2665656dcdab5ec6690d665 +0589d080909a1cc85e9f633892341025 +eaa80568e89172a4c67128a8d2fc11ee +fe4f298677172abf5220b5741f3f9eab +5791cec09a1eda6c8487089e5da557db +056e3decbf68ee87dc24ce544129159d +0c493ac924f9104e5fa4967b68388279 +63dadecd5323d789cafe09f01cda85fd +cfc6a61a0ae7fb18b1f52d68411c40b8 +6a4f591c239fb295a7d90a3ddad685f4 +281e398e53bf354f1ae378b7a0213d0c +41f58cb5c86a751e7e2065d7c021efe3 +2cdff93f5f3bba398c537620612d94df +90f235ead27d4349a4b108c963158025 +9acc63c25f0ba4043b7aa15f0afda8f0 +eb86dbe69b0e36eba607f7ebc47488c3 +4c993cdef3049c592b359e3a58109de1 +90af554c6d7e167767765f1371490ec1 +12ef5be68b9628aee6cbf6d3443477d5 +389c8b8f2c825ae4e1398b080059da56 +36d2de54d52b6158c2c9bedabdbd5bf1 +464cd9eb2f1cbfa3fb7c13a03cc063f1 +263d7b5c5b0d30f1a06001c38ad04cb6 +dcbb6c3364fd3a79f84ec725005a9f7e +458d5f1afc81ae7291a7aaad852dc12a +96922cda733ed8dfb320b2a5afca949e +bc4e70dac4a264e62a80b58427011b8d +6eefd37109ed544c7a5721f6e2b06817 +078f890f1b4ebfe426b4d33971c04e83 +3c880e8965dd86d4b71a56bb53e8ed0c +95fb7688b875d03d4003c904bc68faf8 +d2508118d0d39e198d1129d87d692d59 +f3508a3a70bbd8351716d9a895f085bb +0beee71d891a072d90dde496bd48f2f0 +8833bf75a3c54f38944e60fa31f80634 +d7eb0a6f0967c91a1d654b168ea024bf +055ae1f7fa3bc0700aa6cbdeb40fb5f4 +8e242ff2578f4be7958a1fdafba21a0d +c7ad1dea6ec57ffdb5b80a285c2efead +6b81811d392e183cac4c26755d137d00 +1264a9e3c0f79a201662bd0ae6900c38 +3a690fef098f767e15cb435a91bffc02 +2c8c9759d4bf4ac392bea195273eecd8 +fa3c19e8b89ca8067bacd7c9e669786f +f6e5c496f1fe799cf25c12e3fdd26d58 +ad2ac99c259a5e8c99b43807f7b80c2d +f3b9bacfcfead73e0ae49b341e8e3a52 +809da39b639cf58799713ebbcaa99b24 +817d0dc6b35d1471050751ab38d771db +64def923b770b04c08e592f599405bd2 +fdc8283977e50ff7064f6b2adbec9cf7 +bbd092550ca6dfda01c2d03be2ac1d86 +98aa63b2d247f7561e25cb602f8818a1 +83af423d2f2baa88b5962cac65c545da +2a725a2a3dfe4b80e07a19bbb3706c5b +0e583da44bbd30b8786a820afb91ccbd +5771344d06686d3b8b225b580e82b7c0 +43b8e7663ad3873c8076037e48f3c7a6 +86acf692e6a993bbf3428af13f540500 +390a08238214b6a629a613ead3fa9632 +c2b96183ded5287a5885758aec452ace +7511fd1dadc135b89ec42db38dd8a10b +09e45b294521429126daccfbde202b81 +66250e1b542cbb67dc8cea2ad8c60d4d +2cb14ba63de29b5b409e59a8c4757a7d +8eb563719298a20c2df97b2ea1a558fa +6c547efc37cfa9abb979ece1d00bfc2a +bae7c318c8f19c603f14a5f1eeff50ee +436e2671a1b5a98944375a19c9e2d377 +9883871fd19191f1fb488a6c259231e7 +0fc128694962b96d8a25edacfd0c1b9a +9105e8832e5b61272d27b6747808f07b +bebc1a873dbcc9e0305472fe6a61bd76 +9eaa769dfd92170e3963675cae828c5b +9e154c3ac3392eaab9147639f5719ce0 +4f457ae0d50c8369951276ecc17507a1 +61380324537ef499a4394f615ec002aa +1a43322efb962a456c0f1880b33cf88a +58681149558784a41d56b0cb6da9a064 +bc5bb7274d4a1bf2738be8a7bd1396a3 +4cf5f43c05428be428b8b1b5e5bb25c8 +a8def8c2faffc61b74bfe0a289e0d591 +9d90a0e7f65b744fd6ad5cd00cd1d8a8 +02d5bf51cef06b25a8db4e1a18adf685 +50b873ced18f6ca3052bbaaf06af8ab0 +4b9cc7e425e8ad58b271cef2e57b9a95 +89be0c50c9b29cdcd3cfde297fa95645 +240e99e9c7a67fc302e8bd47316543f5 +e15b29f7697fef7d6f585089dc0f13d5 +ed87b95ca4c93ceeefbaa30094d18d62 +3033e57514b616edffd5c42740dd45eb +0c287612152e4fd5c4360cd5189a4bb5 +a3466d6ea3a1fc2d89384239dde73ebe +125752622edb29484b3b6d6019e8556f +062259faf9d75798b9df36178cf68bed +eab802f6bc2639c454b09ef82cb3d10b +315d6e4931a5196c82d1372e05fd7394 +da719826457688a32fc355f954282139 +19dd8c4e6f05d3ef61bdabae204440ea +b27b7c6fa16c50eb942e0f3ebb8060a7 +813a4219d79396f889752fceb9ad78dc +c30b5d3533e64eba623e2a2ea0f0751a +73e3cf367946048515f46d96dcc61569 +5f06f985a510e4ed03268a4a9a671561 +2aa949c8ddfc40d8c992cefbfc16f9da +b9353bc00c519e1b6a01f0d980e27f66 +c407fa0f7489e46c205c8a6af3dc6bc8 +1c27f4bcdb6f72ad039c5fefedcd24a9 +22e104c8ec7bb7154350c2b4a9ec1c0d +d205abca4174fa4fbe729bf324125505 +fe13119fb084fe8bbf5fe3ab7cc89b3b +5e07141d73470853a4d31f05ff2ecf3e +e321471812e5c4b54c9c58319aec9f2b +ce1776d3f1362ea57c5039278f4f0049 +18697449d7c48cf32cdd4f14857e68ee +9804048db7e16d9c9692cc6f380a09bd +3015d77ef7e58fd770263639e33f3c73 +add54a687c6aef45e63eed9cc9b65408 +2d6361616dc5ef65bcea83ab716ffbb3 +763921f80799db92bf00dc74fcbfd8c4 +46b5bc835dc835af2f38abba6fe8e1e6 +8ce8bcb8588ba3bfa98d9d8c854d0c8a +8b68b155a433141fcf0aef81f70cf020 +8e7fce12d46b2706585fcbb258a76345 +65611f6c7dd655826667564aed1d8219 +074a22f21dd30f563e5256a4922fc814 +6ad2df3cfc4ea58a34975ea17422e63e +fe0d02610b3bbaa518d365edc8e2a40b +288df1b766b0cd3a9a72d95fa4194f2f +2da538aaec60bbebeee60e510ddaefa2 +4f501848e69f05a1ad307c29646b3884 +d1aef16003f1d085f1e233a4b8080a94 +82d965a52a8794cbd321c54f340d6655 +38310b9266a4602d4b61151f4aa86fe1 +88f7f811c5ce7a239ee20eeaf4264a5e +918be526d14eb9ac5713b6541c770299 +0d54ae7ad1db6495c1737d7246f51f53 +836fb3fc94326d0d7c1a105b9664463f +e4f39349ec32b57a0b6b8dcee03005ac +f1e319b8ece2f31a4affd9a911d53c57 +95ec9c3ed988959fe521e2392f25fe41 +624c050bdc9e7032c8385c69a3ae7c53 +9c6c4b03debd0d9810b2a1315fb9d6f9 +3d2fabfd501abd89f2996a97e1faf044 +c39bd0d012aceed4a07ab94f04d31688 +4c2dc668f05726cbfd2f5e89bccc22af +6983b4cd210aab338877de6d3b33c926 +7e541ed02c95050c2adc0578cec44fc3 +02df99f5fd027241b30413c96905812e +b1f4190918ef5aefc1c744f32dd0a4f7 +0f4036499be2e755d0fae2c749664b65 +dd34e94b95abf02e177b48f0366099d9 +1468849c7dacd87b19262bd0add7efec +9cd599a3523898e6a12e13ec787da50a +b3db44e0b62512e27505251390a09877 +aa5ea07b7635132ac4fb1772b90665ae +4d70e93c98a3a5ff1e7e5160d909a9b9 +2d7ea60e3afc65423c79ddea106e0075 +91bfc7a8ba770df0020d1d927ba7b171 +2b55ed7e47db414f2082bd373e4200a6 +b3a1f819b62b1538958129827d37023b +c99cdfb28579b1e36ddede800b88fb89 +48b031a573bfb741996e65dd69ea1486 +032e0c4adfbf1c197d56d9975498fd7c +dd71717420fb418121333ddd04f14570 +331a145dbe850529f6f2be94db621359 +875a168599fed50b049e061f24ad8fbe +f01339fc4abbc1a4cefe83c503d44b0c +e4ac654ba9b61686c2dc854a1128a323 +e14b420b7266f69a2b2b457f3bbec804 +19541a2746e08a6b8f5145bdbaa23e45 +06d0145b66fd46c81425bf9e38891272 +7e5eb6d825a7f37f0c7be4fdd95429ee +3fda81469016e997ce1c19d79a29605b +d5c8456987fdde69f283fd34802d0140 +a6a2ad65c7da0f0f28f4f908d9c9fd6c +ed967890f5e0f5dad4d6eb8c01a8cc9e +5bbe8678783011869d67ff0087cd8fc5 +7e5b152fcf63f8dab71a695d1dbe01fa +08e9de24ab150d083240557cec091d53 +82964817bb3687780b7c2e9016ccb2fc +7f813597ae935d5bfc30a7aa7b31aa35 +1bbe688a9b125b8e70f2037a51e6e80d +8a8ee9af697ef1f6fd5d2bd4dbd42f5a +992b85a92c01e462bde35f2f09edf986 +46af79067ccc9a409290afe55f678d91 +12812ee3a31fed982d1e33afc936864b +fc87ad40f8d502d70dbc1199c5cc45e9 +87e6b529685eb8d7765a925666fefc16 +14b16718a968f5a6eb0397fe1eed1db1 +2f3c3dd012fff07506bc8e641ab7ba13 +b3a7a04957b9155efe1bdfe1091e3591 +4373f82543616ee768a7e4e205872480 +61aa5b6c78fa4e3636069347ae39df10 +1d5019176434d4f4fd9eb347c5a6d983 +d55fa734c1fa905b7a4b7f40c535819b +5f6ca5e5842af98bdf9f267b26b14105 +6cb86681008e4c1d22673bae3fcab3c7 +4d1d0482ce8e27a7467874d69c44d9bb +3b09fe568a3f024d309cd0c64db92f09 +68613f71357a59c03935f2c9d9453000 +3fc9aef608a93d25517d8f99fd5691b4 +aa04282dc5edcd285d6f4bd3a9c293d8 +b46f2effab845cd1ac6dfaa8fecce4c4 +3618634fc7650e537697fd7f542002c0 +26a6911bb179e433be77eb3dfae00794 +e4c8860ad5fd9da4bfa1b158e1c76670 +6bc1ffdea33face9a3ede95169c14ccb +08792dfbb668cc9d280f1f37d8e3cd26 +b7f002b308f5770e67aae23cd9379301 +6a88c80e51afb6f0476c3b855b46afcd +df796f86501577e369d6a3054c77bd80 +674441960ca1ba2de08ad4e50c9fde98 +ca35c56c0c379f292f8fab68b3a19f61 +f3a2a427c0020a4af9259b4115eb8da3 +032e88c736faa115dd7d26273ef17cdc +6384d241aaa8b07343b88a6abd670742 +67fb6d381e8ba29ef0840ac8af406c7b +426f8401232ba50bc8537cc259e3c8ef +ea758d023ca0c5b511086bcc5916a02d +bcd2272fd102f76a65cf173261cd1221 +ff4cb78054ec27108bb9d9522001f511 +f405ef9870492261e2baf0c477ac3e96 +2dc2561452b90c7dfa2de4cb74008ebf +c99621b28b3d4f3d6f6f8d2c68a7f564 +93831623f24e09f627bec5de284b3f47 +1722a7c6a388fa783f7372c8c93bbd05 +e73af36376314c7c0022cb1d204f76b3 +d47336d969baca890ee24730a37b0435 +465f33eaf03e8239eceddb1571b8b2f1 +58e6c85a66031074c2efb66af1d64ceb +2224caffa98b46da55ed4131b01a9989 +49077cd8846964ce865c72e324be16a1 +b8bd40d7f6a822d5f0f191a7f8bdcd80 +521cd7b832cf88bc7bf0f85f4aff993b +65878c95b1d5055b0dce287fdb970ff0 +e710990eb64a10366f72e0528572344c +14bd6ae80ecfe2ff182ffcc9ec49358b +7ed1b87c709239339c1ff0863ce482cd +c79c87bd1ed892e1da65e3b2e5d26665 +0a7740e654623915245fa1f8e985f244 +b1e3598f3837cbf336a2488105b95522 +edec7973b20ab2b97b0425267e0ef412 +9b616b5bc92aac2a23cce334c7576aab +e6c7b6683fb0dfcc191793acd5bb08be +5a33df9ab940d7a95d4c4f7501f6c444 +c5875e887d4876cbbf887489312cf679 +a2b03f22efe39c68c049a26d46a5e2f3 +f027869eecce8914925fc7865a01609b +a1a740e5f7e4a21557f2fc05c502c552 +36244a2f27481ac112568ae8a40b6913 +e7b6e3fe91f8e4f9ce48f95c8f5e310a +a017f43d17bba6f32f90a4c86e8055c7 +3b8117f71a543345b1b317fc792feea7 +867240cb4a235673636a4eded5ed2d95 +073fb397954f0a9034a78122fd1d2fb6 +8a337f6360d312d0336b90f8805a681f +a69b49b975bb960b921d6675a83fcd02 +b087f94e1f3ad4756678ce80b32fe570 +66eb4ad35cfeceffa1ecb4aef34bea2b +59c084ab2e28a5118835b55e2c23b8c0 +acbc02782691b078435e1e4f296ce5db +84b7340a7136b7af7a76f8251e5cb0a0 +8d6363b62c3c1865e30be769dc4d44ab +de2c2d88d06254a74854462d94ee5e62 +a968667010d65112900f27a282204c15 +d36f8f9425c4a8000ad9c4a97185aca5 +814fa5ca98406a903e22b43d9b610105 +3c2018f200058a703a7aba9f941b2ddc +c192130986511d07aab2caf8b6417d3d +d65c0531bdc51a85658541c131b84e47 +6bbdf3a30d5304b536e0bbf464b22acc +1f681635c89df401ef18598ffe3a0694 +f6c68da8e9f60874fdb6262a59dfb8b9 +7d97dcf0a101baea5a5cabab7def80c6 +bc6c583385e5855fa96d5549f0f7210b +3246a85582036e262538c6bd3088e9df +6c9f3c47faec5ed035269c989e72cf47 +2fbabac8f811d96550201494332885d7 +5bbf5a52328e7439ae6e719dfe712200 +b602183573352abf933bc7ca85fd0629 +a2228660c82a860a7d13a5d0f1c7d455 +14bc4a711d82fd75b0b781bd678398d2 +0619c1b70dc21ff936694addd9fdb36e +d403433032d14fcb3e547c4c23c9426d +f076a3709a64330bd05266194a761bc6 +ec8c2bb4550b4c3b15593a06be652e15 +59bf3f6f08723b9cdce0904298526d14 +2fd160889c4e98b3eee09b1efc7397ee +ed4487512de30c5e054b229c7e4b047d +7f3e0ba1ee665c4c052e44525c5cf69a +2d90c6b20732e7210d654b0e7a9e3a80 +9df921c968e7074909651ccd613af0a6 +b26d4afedb4acc765d89290b8a83c5ae +2033ea3066c4fe12be571531f09ae94d +374570a06b9e5e9f0de41750b283c091 +0141029fa227c3ac4e429e5a6bd64e28 +11d9812a5f520429be28d90954943b48 +7c153925f73ae4379900c595d0d93bcb +b7cb7e90741d9f786e56070512b0ed00 +89dc4a518a3d5f078c5c554eaf025858 +acec79f265f963c0cea08e8cd13ad495 +e34142e877a26f0050b65a6b7962df46 +aa6680a0a2fd9a165f8938309e58d1c7 +f26d12047f7b9b9b3ba2eccc5a6ded1c +8001b595e2cd10e445f36a022d7c6e0b +55cc8de5e6642e060e76ba86d9ca767f +71dc632ce9fde8249540d99519942fab +67642efd498ac7024a68da47824ab5fe +a8b0cbbf3784b21eaeafbae4275bbd62 +13339b6fae864f0da2bcb5917dd872fd +4cbaf90d9dda68c6a0b21286ecc98590 +06b2b243c2b7073b32d7158e5513e56e +8a4caf77a77edd2beeb588161a1d8523 +4b62858447fcafe744304ac302844d5b +7e1fbd65d5d6a7a32cadebacc2c0013c +f3bbc05c5bcb4195c7a50f2f238a2e2d +023a186382a3cf06dee7a5434674423c +c3e1cf6b123cb0d5cfb04bb1acd38595 +d3e353a4e7798aef768776b10c29ecc7 +54895a7fc98dec00b0c60ee700098423 +50c44c85122f3bb80423a2f3e8f75e30 +e35104e0d2ba6b9a7c731b73226733cf +072c1a5cfd6b485725e0e2d9854f8409 +3b2992c503f32d3599b3179745dd1db4 +59013fc994496533ecedd0e68df2ae60 +6b0c72a08e3a2d33f247ae8c6f2bc0b1 +c34b0d70fe65ac4209c6a079fff99add +b10ddd0c218f8dd7f420b4e2dc12436c +aaa7b7e50c39dcfd648e975c6966d078 +522472e9e8cb391d2220d3a89125bd46 +36dc69bb796402759beade2c851a9281 +3cd639231c1221fd6e8905037bcea39c +c171af021717f6b8c83b5a5f66754ce9 +9587dd0d97c4d7d5173b5ff91129de7c +416d77a1288453e8663e6c30d214a991 +26ceb3e41f60c247ce12f264972f7c6c +7964b26d9277ce91dbef067def4ee38f +88fa9f694690e11239096536ccf2702b +91cfd35a6513bde5ef088568fb7a1e2f +466a09b4cc34cc9ec407fd8caf5723f0 +e65d2794fab03ae498c3aee136760b2e +1dbd3ad151ca7750720ee90f62295230 +68d16db1cfdc67ff29f488491d41ec68 +ba7790b1708b71cb2b61b1a30d824712 +ec6fbb422f684a89c81e9522e87db426 +b71bb12bb7a7e446bd96cf4ec428865a +814bf51258bb208d948c106dae3e610f +c56c7b392f303d53b3a3149994bd5a22 +54a6483f5130ecfa75a0c5628396bc0d +9e99c1a541127c391618c4cead906d77 +1ffe0427ae635aad3e2891cd6c69ab82 +5241d05abe3d56a0825e9a26af6f945f +fb7792b6596fd12502dd132c0aba0568 +036e1e1b4618a5d772fe06da7a9a7ee7 +d4c6d1957aab60656d244d958290f5d8 +40d4f24f1e9717cbd9f72fcf0f0f3191 +d4090c9aece7bd147df15ab2d6b43c9f +510b82f4399f3392224b2427611d362d +24237202692ef9941ced239161e446a6 +838337db0b65bfd3a542f0c5ca047ae2 +9761a7fbe884b0f99a798662c37cb817 +b9be14d4ec3a3374f3980cfcfd391453 +4c3203f26e43d8ae515b97c61d7c1dff +0fcf18ea3f8d261e7db16bee8598c036 +c20e4cadb22a9940811171c21f086ae2 +0dc7297dba75171203a4b0fadc21f4cf +d1f423e166ff81d90d32acc0f53549ef +e4675471e795dac44abbe4ee4b074327 +9bf545b357a9858da2315ea35dcb11ec +004eef552d21be12d566000b05a85722 +586452f5b1e6b9521a174f7317014b92 +34cd39b138b527de24d6576fba5f6ceb +1465ee5b6d264f6601daeb4e3d83105e +4d0f4ed3203b0803d2d07e6a4401f2bf +fe8c2cb17cf598ed340b86e09d8c7a61 +7ed85a60254d3e798fc6ae2a38c55068 +b0d84bc3440f8262bd006e56b4a61abe +9ef3a40d6c62a6aef6e1ca0da4f150de +60bdecd91d995b42f84e09c5accd34a5 +7139760026dd5bfbe735fdb193aca43d +45da8d03b558d27851b80e9a5d20bee5 +4ba1612034954e21ed1db46e3906b42a +76a2b24c7772fa4e4edd4fa7cbe73fba +13f8017dbea1ba8ad373f1957d79f5ad +670260cc6c817bcb41af52c4db301927 +adf6defb6314925a46a9747cfa21c740 +1ab1baedfaf89b4124723e8776ed65ba +63b652010c5bdcf9d2f7a2116d80b4ee +0673c13e87d61768ecbeb4a32aeffc0c +4a5ffb56c73e5265fc3823712f9f82b1 +a41a9b2bedb10fe9cd8973038ccaaa04 +858fddcbfaad945264f1f46c6872268e +fc9aa3dc9bb4699c577b3a9db0e441a1 +9d7bf075372908f55e2d945c39e0a613 +5c6d81c07f7c268ca6a5c4a9c829dd97 +8801045427ecb0431b1dde4b198fc059 +13904743ff50d8a4747f730b90a661f9 +aa0ac0bf65aecee154f9bab6296e3527 +6a9058c597a83f8da0f7f22cf3668129 +d95b2b2ddcc670a66330a508ca3af5a0 +2adf521149526dde524f030851c7f903 +819900cf628b5e5e3f6d32666edeada0 +242ec6f98523f85812ca700e54c29daa +a8a14835467bf45da93d858ffd3bf71f +6138a13d3d4c90c36ac1a9c13a70c348 +3dfbd5e9f8d46974d732afd482e91210 +a9f2082af1d8403bcb3953644d8c9d19 +54f67150ebe2d7d4cfa6d1d9348dcaa8 +a2dc902164ed35216482088f5c11a225 +29eff9c741d432819ad44d9628008609 +eeb336ddfa888cb3122b8ad5f1350e16 +7efc6e01f155c4ece892fbe9d540d28a +d8ae4cd335576d75ce6319b90cb34e52 +be0e77d1505b5fd31fd0eb69f02d3e35 +26599a2d5754ba0e42502773811ba539 +a9d2117e820674751ef6eb190df5c5c2 +b6492f8aa398e19ecf4295c9aaf0e72c +afd239c5451bfb86220cdabce4d8b30a +34493b077419b8bfdd94813ada011ee4 +c60c5b568d5916b5172bcc4de1249b32 +86711773d8cba579a5e85969051e74dc +eff7490b8ccbfbd4b6e72a412b5b383a +e8fdb230928e36e2939b09153ac91f3b +2bcccedd86035dc0161dc0101f58695e +45870402888b12dee460cc73114dee17 +71483a002eef416b98b6ee103a6ccc15 +21fdd5669673bcf883a6b8b3f3e2952b +83ad77ae50304b3f01d90e337e40f59b +6f0cb8ce082a1d25dcfe12801403f58b +1e82e6c5df875009c57b04c4ba25857a +84de5c660e48687189fa7ed15cdbb57d +be27028bcd71b41715043a865ce01b11 +0908fce9b1c4c54057ef8e69f22e02db +3fc4af350cb9d2984fab35d925c4f718 +e7c00af75dfc2e18f407b8a1ad4ebc50 +d0e7f6a94e23ca5b07eea3fafc7cd623 +3270bb98d8714ff9ee49388d728ff9d9 +4528e6a7bb9341c36c425faf40ef32c3 +239749e7fca41c215a24212eeb0171f3 +edf1b9bbb2e79dff0fa187fdc33dd0ac +46b4aa6e9493045fe0662c1f802f2bff +fd3adaf12d07eda50c944f014e96418a +e7fa32cb05ba9ddc8d5f75bdf1694790 +eed33f61bf2988ccb2e98450a2be1668 +f1adf7c2df0758fc149936ea34b9e8ec +921f416932d7f37aee4875d2832f43d8 +2633d841a94068e477eb42c3f04b4297 +bbbbb43af4416f485ea18bdb705228cb +8a6d8826b87b69ad56767e77232da79e +e35a43bb57ab57bf2da8764c7bad274c +6e75aa3d851d4c737ce56f13aeec3255 +7257a37c541b29c23ced7ec4a81de7d7 +fbae4e521c5167ea032ee739ee944afb +683e7c0dae508462e3c1766330b83eae +52ab65a20f7500311a77553f711bf530 +79532a4063a520a4f4aac67e687099c5 +3115645784e9e1b9d6a653382f45d5fe +611a2f126c291d5ae98e97876cb27014 +9ed0ee7d259f7d2807f843f3e0f95344 +7e2cf6b60c065ee95439bc007abdfa7e +ef17e107d8c685be4fbf4ace30abad69 +313f3ec249bac7a8d31d2139dc5faa46 +39e7dd9a5b84a5b6ec1936ddc88e4bf4 +39121550f853508dc3b50fb8323bf4c1 +1951db00d7621de45582166334979c55 +d80e4cc5ea645d79ce358dd1892b7960 +5c275e5aa628d8274287bc9a532f59c4 +52747e23869f0898b1f60144ffbf5e2e +9b1db7c4b5f517844f202bf7ffc3bc5a +e7dda9703abd72d41407244d94b0544e +e4c8f179f899ea1843d9c6daba4f18b6 +1ff1a34228b5db54a0957c18d08c4b4f +d066c53f5efebac9bf0f865583a14e17 +ff69597e924d807b3f7017d19df737a5 +83235cacc7e7b5fa7a4bc9fcb44cb5dd +51ceeeba96884b37e62ddcdc174ee6cc +986762321ea6c350eb0d726f80d96d76 +95632b99239050122001d2d53a95ef03 +a6a3ac1f2b95eeff6a4fef2d62f683b1 +74c4c12140b5f1096537e01c357a5653 +74fae5cae140fb8c992d72f7b7536413 +78214a1716aabfc7523a0f5cca684481 +d0fd15432e9574e6baf8d8c24c89f505 +b2d6ac43a43b6131099064e2bddae6e9 +e4ff5f01de3ffe7ab01878e2a0ce4a1c +300154ad5611568886a7a0382c5d43f0 +08286e0f0e36d5c4db8b554996cbe03b +4138c17c157d79500efc2a5271b45c35 +a8dee2928be5339615c8155234a64144 +3be6d8a1d24c146ed3f5d5fb5089952a +76189897b5d55c98aca6919a2b431783 +be66c77a2aa4491b927debb5078c3aba +e97adebf2447f501664a1867c538f724 +4443a9c7bd04697e4889f3c1f601ed4a +5e3c7b35a39e8abdb7f21584c7bb3364 +fbb9c819182c584fbdac18f87f531694 +208c76b438dccf89be43436a5b0dcf3a +7d5d87993bd73d6daa86ce68e5bf6937 +613a6ea73bfff02f0eb934be13cad4b7 +8364d6de758507b5e52cc23b55608b96 +bda13838e686a3e2b6986400cd26fd93 +67ed05d7e5a4212d2ee15bea7c44a241 +ea2d16040430d8a53ec38586edf6aac2 +81cc255e17b34bfbaca5de45376ca540 +f980791b4b1f8b89de50d46947050c8b +523bdc6b1a4148b2e5bb82a9702da250 +5fd6b41a8015a5a4fa5f6c66a8496704 +3835f12efaca3ab92297aacef68af2b2 +03a0bf48db85881c7f1928864158e67a +68d280e5f2fecdfd071939089ef56109 +45a47cb2f6c51c49277701bbcf084cf3 +21b75b7b6052047b8c45ed0597d9c258 +c9016643e4c4b35fe29f49ec33b7dc10 +0751ead5bf259e8e0c3ec02a59656242 +44c94fff6a5901f838ba165fa198965e +1169cfdd2251e558aaab374d91d34d1b +6ececcf2dd0a1579822037a917d13779 +089c80c0bce399e8625774eebeabd6d2 +dbaa1b2e2ca91e6f09a2a8d4041bf50c +c8c6b8bbad5930c15e4931be6db0b5e9 +b8a39d4a946a02133237231cbc8d8150 +d33a34d4ff178d410e2032801934c779 +a16dcb7549915546893a27a6d7927615 +9937c75b74879bbf448404a485f69cf6 +1061a3a173c24f17a718abc38e4de759 +05399877fb41f4fd90ca328b8c2344ab +7c189d486976a79a2d44eb6f238a5d35 +7343761eac8bd68c84bdedf06e3ccbc6 +f0c26fbb9c45239b3b49b4de88859f39 +88acf761b172aee8448602fcd7bc93fb +7d069ab854d57df34d43084f777b2813 +ae1745b3794b78a5b69ff30f77dc8749 +085f45fe61e58e8c203a633304fe44bc +e36f76529345bf590975aa0aac3fbff7 +10520f2bbf50e4f710925d3a94a933f2 +3da8068c4487068b34fbda555a2d3f18 +7f5a5e922835892301f43715deee13eb +fe9c72a03100e332544cf29b428ef8bf +65ef97cc0023d69935747340d386f9ab +3ba8823090714d94745db97188eac499 +9aba1c9be514810364eb729d71ab6370 +ae7c4122496b9a2ebeb39b72ed324199 +f1ff26eb1e44d41afba77800eb99b1a3 +1d42b7567c7945155ca173262c4d5782 +49bacefb8b056cc00a822bd0b5477805 +cf982747df48e674e432668c9a0d87a9 +1bc89212e3c29d807c1d7e6a3669c812 +eb127b015221538029b30cce12cb4f32 +e1633dfe99088bad221a7d7b057473df +a47d7d2b0837f5155770630fc3480e76 +4dad22f58a189b1d7cc91ccd8410020c +f5f79ba90d11fab4258abef2bc1f9836 +8d014a8b61c251bc6cf9fd8e33ec606c +afd550e3b24e03afd38a69939e2d257c +0e577c52070a783d34e388db7b821dd9 +d7b6c1bd8843b4197722c546652e34a8 +ae4ecda39965914e899ccb4bf4d9adb3 +087125eb8ddc4612e90d54b5607f74c7 +1694d8494a04094fecf14c70515ae23e +2cee2613cd24c9f02529fed43b26a614 +5106882e11196e68179492944812fba6 +bc26a697e977e9154acefd512e4dc94e +c1bd4c58bb82164265461cf5fb4e359d +36712aa280f041c683c2dcc3762574fe +0e6031baff82d2af576ccd3ed651367f +547761558a8317b1fd6c760e2362bab0 +cd81f07240bceabc47684665b724bef3 +001de480d5946e14ca9fd68a49d0edb2 +58a661ce71e3db8d253e92885399b7c5 +6a42367ef59dedd0a0c07d9b6f7db11a +1b29599f54c556effd5497c6a880d9e2 +ca0782163636d1a8a0ca6ff9288c39eb +1526e73b4d8f06d94409fd2600fb2b0c +2af39739cc4e3b5910c918468bb89828 +6f220f6ade7668bbb47ba4e3a005cd09 +845a26f9d5976fe9e3fd239ec381d9b3 +9eff008d4a374aefddbcbdc8cd1bc7bb +52802d907cf24c1d5b2336965d9e42c3 +6ef04723483f6570ba1aab3bcb5d2b28 +330d932caf2026b13731e594c6fe1859 +f5d3c590e0fa0cc1af8aea6d3ac4d1dc +8ace2fa7cfd03f215ea4966a4aa30c11 +caacaddcf6ed42a183b78c163977a4db +e0db08a61c51d911c9e4fe3f610c6175 +7f681d6483e05ff9f00646ba2bfc968f +c7203d6e0a09eb3fc9dfb67f2375443f +b0044fbe9323862727e0f42f9993eb7a +3dd2ea234e548a1b17e06adbd0bf5ce2 +091d2ed1c7f1e2a5035df4bd199485fe +f6b622771a108a8cbe1d8009727cac23 +dea3a36864c3f6c61c4ff12141d6c4b0 +3bbc96af0d8c2183a639ef9ad5488cf7 +893b3187aa442addb4bba10fb9af841d +2e36a7f5c9896f3fe766bba6f1c673e2 +c1cec96895a46af00c94b755c85610c7 +5c89e09d2558c18d9a25c0a0c0f7311d +82455346ef05fb3a0041f427979cb529 +b91c590abcef3c85139f7506aa900934 +f0ef9e5cb4e4eaeb04a57529a4c80057 +965295500ee864fc566a51fc0d4ee774 +c52129103313b36d120edde91516c6a3 +c6f8719bbbd823e8a9351a6ea866a9b7 +a0dcd6830c1636a967c7581c0d187e1c +08aea3b73a9498546c2d16b6be0516bc +4272f9624c9902f8adddce9abb7b2fec +7595f514a65d234ce9ee0db583335e15 +0b610845ef1a9a403524cb48cd876f7e +3287e491603eb4c58d07dcd8fc6fa1d1 +973a1f6cdbbfece82ded045ccf46a752 +2518ff1698f539f8410576e93a4c0f99 +4dac80836bd0164a1fb3339eeab8fb23 +5859a61a44923eb094563f7ea5dfde1b +023066c62bc9de504086c4d86123efa8 +2cf85821bb91bec1eba147be025dc040 +f97725ac5652bb139a385ba96cdf5af5 +553356d34af2668fd0cbd5796bc1ac0f +eff6097716868d8c0ebe1f6a26e55dcc +c5080896b14ba9ef3a123cf30b3ba372 +162c229d89b95de7638b03acf5308654 +cdda04f35a8c5b1e3c9c30ed4a541646 +ec92cd47959ff3b006a412469e15a70a +3ce1e1db8792d86d21210d89d85f4325 +1c82a8ddf9772d329439ac35db8a3e02 +1cca78bab327174725ff0c0e4ab91413 +b66364c943adbbe87f1efed6006d11a0 +ae8594dc3cc4f678eef304f98948ee5a +72f9a298354b323e943093486013bfc2 +f5ede2d3fa5f945f21d0d6ad05f462a8 +a080d82f592a56a396f62a1c539dd025 +3759bd943f81b276cd45da15a8c07685 +e0f3e51d555c38a95d0b65066f3278e5 +88a3f45c147c39dff133528d44412c8f +7408c7a5b6402f4a60a544cf29f7cb0f +07b5010e24c8a059286390b36b513e3c +145cf122c84a4d81d0968b000b7a30ae +b2c6e73515adf84c41ed5afe70bdea94 +12a1a1865e8e23f2716a1e32c7f6f980 +34115ae07978c6ae82e9d1aefafe5fe1 +a3b69e7eaf09a20696a0d40c180f4f3c +6f03617bce8a5d04fe97df572f273d05 +bf256b8fce880c9650557c33b53191d1 +527ac16399fbead1fa3d0102ae589d8c +014ad490257f1757f32f4c106284b1e1 +8c3863eaea37a877d8ad3b75e8319f23 +db86415fab273e8640eeef1068efca43 +cc2a2bff17a8f1a032c2f3c3b0f48731 +43c67dd35b18d9eddfa72b3e6b3fe3aa +bd89637201cfeb3796d88d326d341ac8 +322e4c5687ef90a028603a7583f54508 +620f291e4857477cafe5e528b75fcbfe +18609fe427452f8dfcf33b06e33437e1 +b4120c39e8f6c056bee6d074bbf17d4f +48eb089a98207025c9789ef138e9ec06 +eb1ca19417c16e854c0c6ab681472b42 +354bb46ead5ac2b1f84021cdc0653d8d +2263c3c06ef342c8e44a0c094149f6a6 +89914c6ed581ff46a4ad32c690cf57bc +1a5e1eff3978b5faea8304ac53fb7851 +2425300110ac22e03c67657eb468d202 +4f2029fb0cfa1403cdebe297557d81e5 +7f3608c07c4d1da5c5bd475ba793f7e7 +fb7077358390b03ff61cf4edb285d3dc +93aa9b0359990f11f33e5cc746ae02b3 +7b934213f4d4adba4e52ee15ea9f03c8 +48f546cf2d58f6331cd0a9e780cd12ba +96529bc42e557190f292a0f137f5d27f +49e232e684f5ae0f556e4e3c7437f785 +94888133b92b3469e9bceef63aed14c0 +d95445cfc7136ab4b0156db0125c706b +5ff81b0adcbeaa76a555d8e773bfb6a7 +57054334de979de8663aab8a3fd25f81 +cd01f3a9c66b52683ff002ef68516145 +4c28985f201442c45101365d3a8ead5c +60d9c3b404678a9d18615cdda343bf0e +27c6f7c6cf51181928fdf738656b82b1 +8f81ad81957e147dd01500d90885925e +1b15054def71c3ea96b107543c0e2c6e +208568ff599e7fa7f82f75ad6d5585bb +56b288c91ca0595c34d6ad43856a8de5 +eeccbb5f7c04f34f106372b467c2904f +e40a285715c49eaec3cb9c1b2a071836 +b6673efc46c2ccc2b9f797dd3f1a17c1 +af2e5bc4b793b0f413bb21d60c959e0c +33b70c76c087bacc0e4aa99f9373f96c +e049d7c90a298ba66b18556767ec8b3c +fe854c94464612d3681b7efb829b70e7 +f3ba6ede7e2388ea8528199307053ce3 +a15d8d5c7a841cd0893330801c72e0a6 +b6841c3288f6e553700d28dd5885d4e9 +7666f96663c9d5de4985e640ddeed4e2 +a099a436d138c3264c7edf8b5f378a66 +9f3c2ae52508146f86b3fc51a35add83 +c40ce5fe26aa23cc5f4355770ea57c48 +21a2c892d8e401ddb701bc0de8beeb27 +69ac36f1cc051017a566b9c199dc7b70 +b1f1435260e1361fc291704a3f5b307c +46db34578445af7accc03362408e4c2e +bfc083ec9f950b57092a8f0fae3ff6e4 +2d6d0ef0a53dd2ebf350c9c28f0711e8 +4ae19eeb3374928c641ce286c81d782e +542b93afabf20b3875e8db8c838ec8c9 +285ae2b6d74088e208ef46516b37e82b +d69da09b02dece52bc5a42e9dc17b6d7 +67ccdf27e1a7f61386543b22a4e4e5f9 +cc8f169ce9f1280d3bc4ee0ea78743a6 +083b2220be838108dc5d62f0ad40ef9a +efca0dde803f2bdfd77acc7f60e71018 +172b13dd04d3daba45957c88cfc53b34 +804f4c558d8af50f4930727290b66211 +7137c409c3b57b29020d66a9ab552dd9 +2b18434f0dbf7813e8c7cd577ee2abfe +46ce6ddc095ca29426c4af425b4f9b8e +6a2cb90df46c4e8bab4b0d6a2b3c0645 +3f70a811017c4fe4fb8d115edd50e3ee +50e3b632bf40cb665eb4c8c1a03d9bb1 +b2fc1742595463bc41bb117ed4a56d7a +bc7a340b831e1a4da392ab6eff3f147d +c30592cffab7f35fc9c3454193ecb037 +1bc79787a5363a6063cd1b5c203ca9a3 +ba645ed04bb4d8e8fda7b42de42a9f27 +c6ed4e91b578557b74c4e5f488bbe0d0 +7bf8ed15e57d9ab8deb80111180303a6 +4abd826fb6354646402e661b64f6dafb +f9fdace683eb2897408e108869956588 +448bb4369c12e2ff763644bdabe3e6ee +ec70c1ff8c5fd743bdb97ac0f0492e7c +e710650e54821dba5b73e1057503e02d +bdf588f43c318169050569c5783723ca +482b2d5c05d5b8cb9ae886cf8642fd5f +a0fa9b9ecb457221096e07f59b4b118a +7150df4767888ddc22f831809b81ce80 +72cfd272ace172fa35026445fbef9b03 +485bdbacefe22344f6e78ca58a669242 +26814ed17a01a176039a18c4c3acd81c +ed426bd4711aa51c8fc7f6be4e14b568 +450c64614ff4cb60c672f3c3ca690afa +a02e939e5ac33143cbbf7e7aae249881 +8d8bea89388715ee7c01183a0667e892 +5439e53ff10c983e27d09d7174efc0bc +3ac4062a046bc25922196f2b8f864ceb +4f368a48b4e9bc07be976e0dacea2266 +7404d44ec06f4be311d2228451aa2e93 +4168ff76e2a0c9398a5f838feb15fcb1 +f084bf9a25585ab9a6e7212188d58ea2 +ac2144ac2b4c1422be9aad30489d6186 +2306b4377429730ee03a806cff76e92b +10b6096d4437ac0b5696baf7d92f8d7a +fb5d0d429d56432ef83e50bf54c19b28 +eeec9624e5ff4e0ba983a898d964b3fd +d5424d89418c330de795902205b1d6ca +64dfb1b7003fab04f9480b7f637166df +ff1fbdb87634e4a5bb20eda35728ce4d +02f7c34269455731e3e97ee383bcb8a5 +d49132778e5edacc861d8cabfe55ab88 +0685e72cd7956ecb70270814c54b4289 +c0ecbb1cee3ce4dd411ca1ce0f237645 +ed384f58875d01e242293142eed75a7a +60e82485f77275f3ac69a6bab34a876d +8f49a85e4cf6056adba5da3a42fb5a68 +4706ed30058a9c1543177851d43fa093 +5f4d1fb3ca84b0e94d6bdac300a9f39e +0794334c7244830bd4514a9f17e46f64 +6daea91df5a78e67bb1c6e4843362e44 +ca1250db1d77ce4308657341015cfa3f +431315274d2edc9509d4246a8c395607 +28854bafa79a455c3ecdb40ef8b1149a +7dcda8e702f5f4471da65d9a96c1dd45 +4b3ff01d0f9a084fc50507d97de6b82e +89a5bc96d967419ec0d07c6c704a6f1e +6a7ce4655e696f9603913c4298bf5836 +999b30c12f8a363e1ed6f3d673e2000e +dba2feda26da30806b8ac672ed63a29c +173dd5249ff65d48535635e7d741fb9a +9b8c73966ef6d9e83cf689bb1a774d81 +2b72d44ef2598353228e175a72034f1e +602131bd90d6d9a9eb56f814b4a154c0 +a79a6b661553189a23eb1791e3cb06da +69708d03c4e8c8126a59594a1779c85b +cf377eee2bd1a76e7890f85f45fbcf9c +941500a2c79b1b74eb8faad93bc3d6ce +396b989748d10207ce3d7b5d599147b2 +259f893765959d7f2af062b8e4191139 +f35c1df4ee058e9fd7079f26225e4d1f +25b9c3fbd9a5e1ddfb5a1cf927f7a40f +ff4d9eb46f3e626cfa35861ad5cf2a6d +2ffbd5c60ba3464c061021df236dc9d0 +61d72c1cdcf9661e0365641c3760437a +7ba93ca58754d7c44e4a69fd18c46ce7 +914c719a704026b016e7c12a6ed37de8 +12b0bff46dd2cd587c42f0328ef4f874 +03aa3b1979e255fd53cc424e44f74f46 +295d2e68c65117e8a4b9956e75b35563 +0acee51f13c266e0239c3e6be36c359f +72e77ad72dcdcffbbb9cf882536bf82b +3a5f1b52344f42ccd459c8aa13487591 +bec09de8b4330289d62b6a3459ab6b7c +fcb2f10e988fe6707be9acea5fcd9c44 +461cc3d997a78797dbbec30730421001 +24ec9c5c126b90a85ce2c45ac5ba14c1 +5ecd51396ba784ebfa11ddef4ba12718 +882760bf05fc70d7709029e5a6b6449e +136b8f37fda14192621851578e12c410 +d21c8c6e2e0190c686f8fa61b3a1c5c9 +ce524718b7cbe6e5c02c3e33b5867209 +b18a0aa42ada5c8ca81ee2e72ac84893 +73b907dfbbab27737ab6e4dae478f0ec +b0edab5a6cfcc6dfecb71e1e5d9e3e04 +b0ff05e707a482d4b86a9ec8b507e998 +0984446f90922a5cfe1842c0f6140ec0 +3793ea6dfe8fc96906c7ebe937690315 +b4b8061b9d0ac9812995a11cc2941a51 +fb8fa9101feee280f854ace37b660f56 +1b48d5f39b06f24992488ad11b420d4e +622cd1f8ff4c4f3f7015bd2903afd213 +a6591f218a9759134703e7f0e07a284f +7a27249aff75a1efeb2c07e243bd61fd +efa227ba9097efde72ee1765e1a06bea +498ba5f7d43d657cae3e4625b32a43e3 +b409934c4e848b824825982fb990470b +9f6a424ce939fb1e3f70492f96a6b3fb +a768683096834fb8c619387e4ea386b0 +1e6a49bb28d3b69409ec4decc40c6ead +8db8db648747cc6edac5c1db443b178e +b3278df3f92a8448eac0837674944316 +4200f0916f146d2ac5448e91a3afe1b3 +4dd9f43f0043b0a3afb049d0d621b00a +fe5bce8a8473ee0bde400502c184436a +aa64b81e05217fc1e5f54003ba926ec5 +4040d6bdf7c2bf466a735e7ba11c6811 +a8b5a2617ebf4f00cddc2c49e9a4b1e3 +91d2a3cd2d79ad40574b4c2ec58584c1 +6ab1e0bf4364368bc48248ff6d9db00e +ed0e225800ca78499b3b3daa2c93a18c +34783fb7b702ad1f96866fc6419c307a +9a4ba0834a34176a2bfaa9c37e47c9e5 +bc67d93f5b038c7a264cf21cda28bef3 +fab65dd0e6ef1df394889b395d7abf30 +7742a19693cd0ae9d71596a86aca8cf0 +aef4c2aa4948b789a7d79037c5a30a82 +dab84a414e10aba21b9578a2ff7494a3 +90cbd57adb210a3a29834a356c44e58e +788a53553f0b8b182ca427a4227e4f61 +049893cc5c70c8b46152a5acea1da0e8 +bb33b73645098f025403dbcc0c5a1024 +f66d8a91abc64b793e7f31dc589e385e +e890fd0569b716ded61c07c056d85074 +3bdfbc988313b6d076daa8bda7f2b00d +3f60b281d6a64223b357278b57225579 +bff3e5177ae55665ffc7fb532d60fede +d49f47b58bead3c7525d411086ebf034 +ad9235abb88576f2f435d1507b1a2866 +06205467897cda16a2b4a9253af8517e +d0ab373a2c6cbfaabc5d6486d1ebd56b +5055c186a30bc3f1eefad8d0383872ed +468dcc757771371c28ece7dfd5265c76 +950671aaf9ab2f72e0890f58a6787f57 +ed1e7195d28b52bda0a793a5183d9fd1 +1581f8d2f73c1f3c8442928b68a6c9a3 +5da9947000661f4fe3651dfbce34f57b +87920fe14e6a67f5abba3fbbd47d935c +39e417bc9b1fda9b3108536a0b08d60c +9adf88ca8d98aad738aabf26a7cd24dd +928d88ccfe503ece8a0510f5a17c3c9b +437245d679d2aa568aef5c8142a1f94e +895780e77fa0cd82fb13dfa33973f838 +d2bbcc3de5cdba80d3bc90fed5f8cf56 +df24456bafd21115f1633f845223150f +36eeb2b6643960bf42d4d9bccf8a0e49 +2708041f54dc85ef2be064e0a9412845 +db847403be6ff06a21d88ea8f36a18af +ab6e5c702965a99d4ce13df381ce7f1b +b3a3ace9de7e4d7d4e652e99409f2a1e +0007c21b18645483cfb12f91da90f7b5 +8e5b2aafa321c8118cbf9623e8b09bb2 +911c34cbb2c5a82fef9ead1580cde36a +f07bb5f2470234eab51edb086443af3b +3cece9520487cb8395a6ba682bf03824 +096f78fa65d871578b45b1cdcc03e522 +c80dbd650e1b93dadb101a70b704fb41 +ef6bc0b5fc44f63db2e0210def9fd3c8 +962b9616edd2147cea6f21a8e1d8c7be +55fb79f803743609b8349c1e54503bd2 +28025c349670e3a3580744b42739190b +57fc0a0881fa9ec3d77c2373fa52f42b +305be74d09d593a34e302a3569bbb738 +b7195e06a678e175e82bf75b931f8571 +dd96085478c3e234c3ef72490aa2e3de +d908d26cac8092d475f40a5179ca6347 +8859a31ce60ac0798ecbe1b754b76ff3 +b20694acb68364c5b44d8447cc523b0b +8e9f3d8e00f72097762ce1d51b6bd607 +c87ad1b6fb388f88b07460ebb5d2e4c6 +a9346fbaf920e99acc512e8dcc57fa3c +44ed81da123e4dd3f862b8562e82df9b +53d10efcb2a40fdf652611bba780871e +ff5d9bc9e53ab8dd6df2233d60cccd24 +65cac660346ef0e94fa112bcdb8e7c78 +cd0d07f735c34b699f128706df5ca9bb +9c5796c4e30a6476d20bea319cc77caf +10d37f58cb44c26de21a08a6c119094c +4a11560a2a5774704fc347ddbfdb269c +66ce461bbc18f31b0cc709dfddff5ab6 +358eb6ab9e06f0a0aa6f38af4984dfb7 +24a2e888f0482d4ffc7877525711a0d4 +42a11af6227acda973cfd368bc8aa5c0 +9ab40a014cea1a3dea999143a66d735b +db9b8dd0865370b68d39042fd8132ab3 +81d36e029c78eca5574a4def8d336df1 +8d080a8501b3a15c9b97dda12cb8500c +43a9fcc86ed8b1aca2e483e2b1e74f3e +197b4deb87ffa3decd9f045926a86cd0 +bfac6eb8308e1153c1f1fab4294d34f7 +665cebec3ce1380ce4e3c90b1bedcbf5 +8913761f23880c40c49026849f13cb7b +6427ad6b4dab1ff1309636d6daaf42fb +3a14e4a0f527f7bad14830728358c396 +ab03520d547d26c54744031083a783e3 +29789ad93651e9f57262b803cbd81195 +acae486196d032990b9591c834c8242e +c02185aebb5d1cdd0015347dc31033b1 +4a2c70fc0f089474b23d85269eea8e71 +f2552d9066912d2cbcedc286db3ea336 +384748a252d780e94aea05cb2ee75563 +edd9490fc1a956d214e1a05d17430b17 +4315a6d93d3182f18ca74fc5999704ac +c422ec06693c82dc724301b88d91d48a +4318be73b75c1c95a8921288e4c47c82 +73b0a84c5b09ac014aafc9bd98cf9ce7 +89f4d0a4998385251c2cbfbf8a64bdd2 +cda7d772d861d401400109e900daacc2 +49d26d671e79524da6250206c639edaa +5192591abaa2e8aa365c32e737cb0fed +1cc4c59cedaa83ed1e944f95bfbcc05f +f2d4d6ad53cd97f282f3347364c700d6 +ff35868766d5214cc636e22bac9a12b9 +22e7e915e3a8d161e6d2904dc86d3772 +0844967db23304cb0d3e344760e61dee +6196f35e26c63205dec2ad561521509a +243c516c93ec8eb0c654505a521c967c +3039c53e50678532b821263d9217a56b +60e473933578055d5b8681f1dddb7f40 +9c3d0064431924eeba5be7dcdd681950 +5209fa2d5ea8c6c83a13876832c78c35 +80a473afdf871669b0ad6859854fbe89 +8981e3cff69d4c15b342b4025332f640 +7de035f7a527f25257d0ffb087757124 +af78b4c306cdb93d512a2786141d5225 +6723b215d9185a85276f5b912c4bb9ce +a5c14093eca1594f117a7772b592a418 +66f835b66af08f2620883e308eb336fd +59ec69fccca64cd638f1a7bf443b435c +30470e51c01847aa81bda27ff91a701b +ab043a2d5d70fcebaa16f7021f372d19 +83c2d7a5ea41a50add074fda596685f7 +61ab43a1e2a8f4fd3a4a83a95f597727 +bd61e08b4eb2ecd09bb2f3b5786f6d04 +690551171b4ff812702d2956dcc23958 +9f4f1593d390e5e390207e93bf5a28b9 +15a9ee740946da71d9cc420458843984 +ad3b9994c5910dd8207448ba742b5493 +a399379121bcd7ef15f33b5392482f8f +a5b1e83cd0273aefdf9cca2994b97c77 +a22aad1565104cea1367161c348e3433 +6b492d35ac957c9d2e7c16369597ec71 +980bffe1404d71ba492b4f8108879849 +9afbd5fc213d64e04bf72d3de9853395 +dae71d5bb903b5097f4d9f1a1f1ce474 +1f3c225c2f1a60c057a9f526b619310e +757399c2560a7d8a34436198108282da +20bc17c9ac3f68808b47d0b326b55e66 +c1168ff54af7251fba945464cd01b319 +538bd7f4eaf11c81e8213e2207c750c5 +88eeeaa575f99cbf043b8300693f57a2 +0401d799f87003f603a1c2aac85c3571 +ec9618b679e945e7c743ccca26c24e67 +f1f81126b40dcfc90ea0464294a87bd1 +bc705d2a2e9b9f1dbf4903f0563e64c9 +980e4a3a1d30c780d536f46bfe827b24 +64672a10de469fbe6988486f9582d37c +3b814241937b4a0d99727ca76b551a5d +1558b6291d803e34744016d5804a95f1 +8b2e4ef12d5a2d448f074cb6d1205d5c +e2c0c58cde7910e7d6e54e58d5c67b6e +3e25277b8f5e3340b9d0bda1e16d25b6 +b7c222116d83f3b32cfac14c28ee93e4 +cb2cb95f5201872b355e3b8e886b88b1 +addb367baa9d77f2d915eee00a201de1 +ce20f616ebb53f8b7ed6767f76863cb3 +be0e7b9eb4b49a49d9582546e43b8853 +47914c825a0c5238d1db74a5920148aa +fc102d75f7a6ed749cd1befe2ac4fd21 +e830791df12065d8212cc099635ab411 +13a655960d5b602f947d5be350bd49ad +8d0067d6794fd0c766f65cd9a857d975 +aa1fd6a0f7b485ddcb4b2b066acab6ed +a7ad0ebf3b90c99242b12608d1a73106 +cf59b028cdc20f280e26692246e4a6a4 +1ed9046059f4ba5f890bbeeda5ec06a1 +c2289f55788f2626b4c0a4c5d07856b3 +14d860572f28febf9f9559b754bf41e0 +5cd65de219f5572acf19f91993bacb1e +1a293be1097418c5250472b37f332c07 +a2a8503e3c69e7992863e97f45093a42 +4240ef459f32527c040abbb149aa969b +bdf6ee62a0d069b6476f005e56ee13e4 +790a02d1fd38d0d35af9da3878b772a9 +0bd5eed17191e28be8e121e3796e0615 +52175753820ae06dcdabae01a9257cf4 +b39408a7d96d4e0c8f1624080b421864 +5587adaaf248082337bc0abd5dbc57ca +f327c6e5721d2fa67234720aa9e5d85c +a81e1f271bc4a3dd4ac87827da4d0a78 +1c782e8ff37e1d2114b80fe0bb8d05ed +f5b9e636ddfcef037e6a5d5bdc479102 +8abf56dd542c2dc45b7efd4f5fda170e +691e412dd009758132b1569de00f6aaa +3e62c6277e1a7b7b3518af78df5bfdf6 +24af095fc12fbc4cd5deaf358911102e +002f08cf8cbfc31287de47e3a61c9d6e +8a2c5bfab98149c80791f3ecb146ae4b +34628092121ad47faa10a27b7d15bdfa +370d57e0c09c6b4d5471897733f85add +98e5fa6ea6e88e6f0fd66028c1624201 +ecfd6c61d671a9c94511a92024daa814 +f659e88ad9b9a1e7a29f69ef3a35b09f +fb66bb90028a8fe8179acd70a7ad3593 +fdefdd4014332806d53ee0944ce2623b +b6524895d6945ed5b6d1c61516dbe355 +4ac4ee1444c48423a5665841463331df +bd3c3d80fe71bc6ba03d2610b1f3c2df +ff00b53517b0bf3c7782123bb78dfb32 +b0f24e3d11bfe3d31529d1b9f2745cfd +47a87c6cac1a8b856c99bdea15bf4247 +f26dcfbe6386c21aac6c61d369d0c4f1 +e2a191c1213e03f69a58b21b69627f3a +ff522719161cfe5441a7b0b7772e7e8e +bc3f381953be1f16b956a9d394cf969f +1b1d5addd8d977b2d912c1ab2f705041 +e3ef737035c7afe5ed0f26b3401f86d2 +a7838a5aaece334541df6f4f0b7b3f6e +f4d5d0c0671be202bc241807c243e80b +65db27307aa0cdf0b3c0323431e08a15 +cf9989da61e12e358226d3f79186f356 +5339f5204de061a7d8269c9b84e123f0 +b529bc78ae166049c777f2b90e388d34 +c8927c1f953e44b55f327010c444a2d8 +d019a263fce94b0c6c135dc97c39768f +847676261680bff61c72961c8198abc0 +490f7cb1fa4b6f10ff51f35a306be9e6 +2b645b131bea1b0c322fb1ae4d1bde7d +5d2c5335a81a2b37086596bcf0609951 +80d3b7dc0b80674158b08ef77ab61180 +5cff428b66d667252a181f10f022e794 +9c814562c1d7a8537578492a1d959470 +166e2e545492631c311ee43362379d38 +1a9b8d7de566afb7584ff1a25e91a6f9 +6632109070097d9a73f93c156481c2d5 +efd21632159ea74ea9bc2c86896cbcff +588e209f698255999f059a7bfca72b37 +db30af3fcd5a64fa6ae858b1922692eb +2cbe250a19308f6400cc3ad4a6ec3ac0 +831421a27cffe58eb042e5e4f7ae7917 +89f2535d67e222d7a56e996c2e310e86 +78d5422da2d430a8096b0a760780c267 +b7fc60d69ef710d3fb045a0ccb4ceac7 +9181ca4e510cbe41777e5fe8af4f4f4d +72d2dab880a0d84462596fc17707645d +3b737fa9b592fcc30fcd9ec96d1704b6 +f9ed90681ebafb6f3d9addddf9c254ad +338b5f3468983deb1351b6ad6a376ca6 +94c17d926eadd4dace908872738a7d5e +5e9c8d6c357693521c42b0762a53b9c6 +e759c4a1e8b4fe99718eb664902d4d37 +78a9e6a037b9c867289fc93d7f0296d5 +c7af35dcd99d483d8242f12e77e69054 +85d563a0ece5f4e448bce6d83ac945e5 +ac0c704b79d91ed85180f7a288f000ad +570e544e33c3c36bec2d8abb0423ebb2 +143f95691ebd66bc2c7de072fdd7bcf7 +2ec28a25be7be9ea1665a81e2a921a58 +0732dcfad3544e41b61571ca60a78845 +05f10c925987038a33be7b25a15cbb81 +de153269104dd48ccde6a7f5d007e85d +5ad62ab33650888608a11d17a2ccf39a +d3edc9c5cb8bf98c779e809ab25f4b58 +a449428a47383acfd816603b55c3cfa7 +37f7c08aeb26d0e2b93e38c12c9f6365 +7b8e44d396f61ecd12b6b7b38d96d9dd +56ec95c9613f05ead3c197b24bf8374c +1b9be335d4ebbe7f9bf8507119549d98 +74188fc03e8f4afd03a39753b3c1bf19 +c1d4770507f608acacdefcafc5d3ee1f +a2eec100b59a280e50ee341cced5a6bd +db5572a20f49b44ec501bb67cd26aee9 +d17096621171cc4fdfcf69afb04c4d09 +b4a03011c2188ee6993dd9d0aaab1327 +9c4fc45b8e6ad4bf08f959548f52099e +59d0d19fc45ca69230d858f60a5557f8 +f317f81a4a41f492e041d1caf0eab219 +b847125e5aed8ec18a235d5e3251eb75 +1ca6939028cacc775aeea5f5e8595a8f +b4aef0e33c28557063958cd0883b21e9 +60ccde56a561811d3f7c19b9853f3c64 +07477e193d9fa110774342b29065e005 +d749b99237cf8fca85c08948723cd9d0 +764329b9bd80b588bc65a647ac09a3cf +055967acf4caa06c3867b03a337fe29c +f9344cf0b170677dc96d28cdf2a2a8c1 +3e60e983990b7ad2c4de8f4b504155f9 +997997d2b58e3c0be9498d8fd00ef08c +3aff70cb5f931a610bb56b0e57bfa8b0 +a982f2b687bbd30e13e70c87b41a7005 +38606eccf137b88763fed1bec119831e +38958f001cbd129116e2fbe4041d77a4 +ad824a0966167577e445683f4bc15376 +219f27585bb3bd9844dcc500c2a6e635 +37de7e389e2f61a080ffd2f1a3bb2ad0 +e95ceedfd38dcecf07600469bf58c55f +2e570c40b8714aaec907e2b63b9042bd +2a198faaa6b8e75d40c6179afe5dd32c +827cd2c07fca7aa3d83bc37f92ba3d09 +dbe93c4d55c91faab11daba48f314574 +3c9e0c65100e2f2a9228890843f8c1c3 +d71c4e31fba0e867992bc0adb8fc5453 +0b4f191f10bf73c29f0976bd42f67010 +1cf6949d9278c5c6ecbaac8e518ecb8d +3bab23e62b1aaabc610aed5d57d083d9 +302e4f4abea2b61f23a1846052014552 +992ef5ab29b716c45721b9e56167c5c7 +b394a2f7defb630c81ff8fa1daa07d30 +eb34fdc06d6c488617f7658f7fe33aac +337ceb2f3d395d55f5b65c5f2be6980f +9f5ed8222f50d9dba8887bc250ae0680 +35d4eba7bf0f97a7ffb45b992c163df5 +19b284236e896e5f12468d732ad0af10 +93a71ec9479f6156a606ad646794bfdb +ed76be33910d777506dad4215891b46f +b5200bbd53959f1d7ebb3507129d10a3 +189d70d74792dbc4b462721eb65ccd19 +b600b4cff8f57392dd2b6ff8b4a71b5c +81ab7b68da18d6145db34147b6bbe293 +cee15e4bc744d199ba6bb6fe15d45933 +801640c9e02763fba15ebeedbc6ed454 +d7975bad2ffe426353c669b85d80f758 +c21ace4f27329f8f60bb586e0a807496 +1498be5d5e53647b12fa23156c3d9902 +33824d6707146540d1b748f04adb7553 +cce91d2ec01c06685625a486cac116b9 +61cb137233dd09930156b333b8a2bb50 +c363ce3a51ffa060d461f30793f50bd9 +e483f8dec5ddc0447a801a738b9f9ab5 +67b098cf2ea57412c4cee6102eb3bb09 +9674cf21ca827b719419ee267d1f9e20 +349c7ff61388bc35b351f788f13d0ae7 +8b5100d929e0c7be8f6fbc2e0019876b +5c49a226a50aba2ec09dc6b60cec3e68 +a70c2cdde803dbeaca10cc3200a24e5f +2dc467b8a6325669fcb60bcad0341654 +e8a673d5d4d69a5fd11c880fd4c3c481 +a2caaca07d301455006408d052cc098a +eb7c10af1de47a9c087a3008e79cc0ea +ac3217052063464d2b909471f915ac11 +804e75256d494f5b3a7837d5efb8a562 +7cca79b6e8d1844a2d701ff07a2d6630 +395f7f443a26db8e3548149a880ee10f +a1beb9eadc23c00a7a2b70c0075572d7 +df326079a0934d35b91437c4b654eb9a +4ae3cf4252e2fb2bc5cbf2d878a08dfb +fd328e7dac414ef8cac94502a95ccb4e +96e8e302abccaed1db53ce29467159f8 +c7ae6462d0c5ec146b24decb30e35c08 +93aeed40007e310d00a96d96af082c82 +94fdca0b9c2c80ebda6a8f4295726234 +c9f22962adc3d6afa603553b5094efde +94d43bcb4e885796840bcd350556eb47 +d81c81138e7ac584d26b57b105b1f2be +d8756c6e1a827ea7a41b010733e0a4cd +2940cbb5dc8914dd0236b7fb9859e2f5 +a6a44b09c6731bb2d43d652d24efc963 +9554ef898e32d1dc3eb798b33ec3af53 +d4e5ae8a6b22b08f43e61d69c6c646e5 +ab9a4d30da0eb8b479f70e7a96240459 +dfcd51dd5086b01bc608c666697a762d +4f8880072e67b3c3b4cbee2563be3b71 +74536db8993d8beaca5e90bee0c5b488 +4ae4a79bcea6d70dfc666e8a51b64037 +063cdcb062f575f0497b9d4cbd8b582a +810cda1888d15927fefd1e8f8fcb32dd +097a792054b14cd07adf7cef6e26437f +8bf3bed35607d209a34508e73ba4fc99 +83504e2315c1e9dd1d10703f7e847863 +fcdc3ab9a8f1c346ba4dc0afd3efcd71 +2ec160502f1b8df4b65632c8491aa69f +2e90b299d03f4544aff17b3e7f4271dd +6c8971e7b681999e29cd8d0288f922b1 +b11245dd394f43465f580d7cacfe6786 +2e09a50311cdc3cace4b704bbcfe2f86 +1ff4cab93f5d28e86ff30730e0a56b02 +b8c080bb8fadd24ccc37ccecd2a78730 +fef12151fbdda6c2f9bec9e301da7a6b +53ee90c5ab8ee4df2abc5158e438785e +9a94428dd05a534f70bd5600b3340024 +aee0bad78aa8511e61d937907612e93d +c9a5a17c297b3b35ad01fafe95d16f50 +2c1d4f59f062ce424618f4d25961fb76 +6525f0afe74e7be04ea8310e725e93f7 +e78e7faf2c91332782285f057698f37f +d788d370c534cfdd1f67f5c5f1fe4836 +ab4aa87031bdb7506be3378c95433fcf +ac47fb58d5d2020127e970e56879e0fd +b8f9076acf713661e17a63b153e8c14a +9988bcb5543739b7734d277f8f8fbdfc +851db0af7eb098da15b8efd8fb9d474e +7af6da7e82ccdf7982a0f168ff186234 +0c2710c14e36d184252ea92fc65093f4 +66d27281f018f27b010487f5e5944eaa +06b3513ef848b1cf5ffa20e67ad18254 +4d247cd55e5185bd9eb6a4bad11ba431 +899015c45efbb95c469a61527498cf4f +941a82a3b8a9099a52ce16076a9ed20b +4c01bd2afb3c9aeacbe2adf14309b27d +f9328b1bc7af8a2fc6cd8db26efea1ec +85a6bad15b6ed05f60660ecba40cdedb +10a8101a02dd29a9c052c5988e90ddfc +030b691da24d60cd4e0fc5ce4c0808e2 +e9f32c63f576fe795dec2c012a32f9f4 +4aa247bc710fdbd2fd68ba4f6f21f822 +bd01056fc6a2851cead51a02381ded50 +e7d05df7a20ef007ee827401b1c272a1 +c474c37ee65c2dab25d75df2ecea6d2e +3f80c1ecaa9e8645448e737c86cde3ac +58cf96aae382ecefa61f86dbe6ae94c8 +522610f341f6e31bfd8817844f125194 +a5eba3ef0c4237bf93f65497a8978443 +bad6f1ca002d538211f2765e159c9c5f +bef6783162f22ecbec735fa885ac914d +ff3ad0c078e35fbccd4e8952291f73eb +24a852299dc6d49ed83aeff0a5a599be +16cf69effbe0c64b48e7c340cc5b57ff +e0c2579c6e0f00b4296530d4aeab6946 +8b6f3e9e17ba26f2a89ce0efd2f21d1d +14c2557a2735842341eff8060a21685d +c7b14b6fcadb255321210c7830864f97 +9703c415763b78405b05380f67e1054c +e911432f68ed99e8cf3454698453c720 +24ce8ce69601495d42360966957842c2 +6eb29ddbb44a0d7c4c949e24627fa0a0 +3c81c975001ddcf20bed5a8ec1df6d26 +ae2efeca48c807f05712bba44c2f0ef5 +8b362228bf565fbe486574e7a1580c32 +da04038981b5f554618b27e991590de7 +bc5ff613063333679a00e2e4e322ffe6 +dce4d358c964073707a72e5ff43e572f +4c4399203341142953a318e4a586623a +0cca6b229cf2da3a2f3424704f6f4c24 +91031ae2e4a8e50b68bc18754c6f888c +c5c7316a866499995563d79049a8e617 +f3a4e5590172a34bb8c1dd009c8547f0 +29f760a087281a3b8529a65d98185ab2 +cb5dcf686e0cf2ee3acccb384ed43ea1 +bf6a9ca12c1916b87a65f8743777e66f +e860b6ab0ccfb04456c5379e4fb7620d +3ea5b881aefb9097bb0b28a38d5218de +e474ac59a9f892b2b2bc4c5e73a45a8c +36376f854b5363a3643689627b190855 +2271bb08ae974546293b87a772a04980 +a39cce46f68858d14998c58f03aabdcf +c7a9c6f108d584a4295405b721e0f5fa +16c23d13fbce1806efef594fbe0d2475 +266219049307758ee02b864907418433 +95ab6fd831766fe5ae579dd725bb36b7 +7b7a4698dbda71efbb564e3db7dfcfb1 +6d182ef7ea0b9755331380590c9c20ac +7e90c093039493c8de83f657d91772f5 +1bcaac66e484326d4403731f45bc23b8 +64f0be93ec5c6ea4dd938a1f8f9a3056 +2230f2c0139dbceeaf48732f5ccb2a78 +1a19a120cc12fc93ae2186fa3e8cb248 +57e347932e481eff3837c1716a9964ab +516e24b9624880bebc5e9cf07b7f1e2d +75dc0f212ae0df47a2dc4b64e8338686 +704a6d060b5042d0728295db4a75d0b9 +df554a9e9bbc5a4189bbe04adcb0acee +1b26352878b4ebb7a0cdc8ef486faf5a +da3e4f45eaf9c8ef89d070d67e772377 +4ac1dcf49d8b721165c4057819f0862b +c344f591ccb00d20c5e9a0ccd1cb8b5c +3094909fcce9db3e514e21a46a2c7343 +5d2dfbea120f23e84e689374aa2ba84f +8dfbfd06496dd93b237f5e9a2aebda4a +d31dd22d27e7aa61f2e0535cc2c74def +645d0ac840c62f57c46e38cef1567426 +a27dbac4728f18bf3e38266fb4751853 +346b40254291f3ff4acf55d697699889 +24e3a18228b219bc264c745424b7660e +899b03fc2f59bea3e5577a9bf337c70b +b3a494301a33a7c5fe3192d479bc909f +ddd1f62423f2f658a815546c2f1e3f85 +e7db4ac94dbd428f442f531847bba597 +2e638c6ea9bb1b2231803572143bf5d9 +379c2d754e0801853173d57cd2afa264 +b1f08a92e90ba8514e9250622d5bb2b5 +d15dbfcb847653913855e21370d83af1 +869cf89a286ea8d0919039ba32aa87b1 +1bb8bc6c986036ff24fe4bcd232145b5 +a5048a3bada8b78ba6fb7aa79bdce7bf +11e0cac682b228e9150cd03a1e016fca +abadbf1166d71c4857f70054456cfbb8 +6f51c19375c5077a8a579ea3f0aaa850 +0410f861f6044703c7eb8a56d40702c9 +89428860b65242b7880ddbc6ee619c0c +bdeacbb9b177c2612f28cde6f97f1f56 +79288e64d690d77a5fdbe5f0a93d8584 +d8e7124a5142b544af071ef02bfa505c +cd213ac0c295354aec0ad5a9890fe260 +c6408e50c9ca50c28af86796bc7c954e +3e537287e752de6eba5ed8f6a7846155 +106ff44cd98abcd450c3eea5fc97ae5f +a2e5e988620bbe17ef14dfd37e4d86ca +c5f699aa9966a5c0ed693fbde76aaf91 +0beb64a76e622c38c26e658335f438eb +5d08d4bfd3f89865b6b293e6e37630aa +0a7d9e1947ac26b812a606781ce51392 +9d10e1857a3c3cad6850d619407798e2 +846573eae597fc4d0736847ba9001b1b +d6907fb104672b733a6b25a90798f614 +a50fbf9fe847b7dd34a032b206c1d45c +56adaadf5b1c4d8efd2f2137e1492778 +8daa03768f8fc05392758879042481a8 +65168ed7db0dc0786731ce74df2b0458 +673ca705dc55cc8f845ff91de9f4f938 +f945ece6b359adf187927f1b8063610f +12982fae78652a27df41eff6e2756281 +1ab436dc96a6a1e97c169f2e869eccb4 +c1f10cfd640618484a2a475c11410fd3 +8271dcd433a8e58371cdc3b0831113a3 +70d94f8411569e9355e6bd7d2244de38 +18ec3318fe135c6c3d47cbfcead6b251 +750710d4bea29ebd0239ffaf15a0aad0 +715659ded383fa0f89f8818b8f554a5c +95fb31277fcfdea7ec1f631d1b0f28d5 +0af08c912523fc1e036e77a65af3f129 +e5806adcb32a4c0b3ea085d6cebdcb95 +63268cd3c3f89789c620a31c4f3c9404 +5456a421c8bdba8d3ea8607beb3b473e +7c6f3c3bd22faae24ac12facfa4ce32b +2fc7c380ec44eebcbdb06df1fd2839f4 +03d4fa39aac5271c36a421639f62c416 +4c2a0bde5e3fd81e1fdb5f193c894101 +2b04ceeb5016f22d5693d75e2b2e5f90 +ea72fa1467bd4c9efd131ef4a84b829d +242ecef96f4d5c4da0ceb6f6780fe244 +4a7529591a57e6e5406528e4c965937d +b5bf1d4c35e99be0b52d0d9267734eb6 +d92326882226dea9aaab97af5cc000a4 +fc6faa496ec811226b5a8db061bdf038 +598a9ac4590350fbfc962fd589261d65 +6dbde58d57c4a89c6d925a5cd8dcb944 +89c7a2773c5f42e81c3d900a385dbe9f +9b8210d0784d2634689fda21f151487a +077a3a925c724878292600b83c9af884 +a96e8035b5d51fe20bca0f80f7daee20 +27d6ae93d30f8cb058a2815d3cff3407 +7704076bc8325ba0e9529a6549ee8cd0 +a543b9622f7bf1a340a8a6682d09ad17 +40725a07e08dace32c821417efa91efb +e06cd975d0d1b511f71de80ccc2c7de6 +7e53cfa7856eea35472b843c590e6c99 +e10c4c618f85521f69018c76b78f3ddb +a3a9489e57863b81d5c6248dddc8db11 +9c44ff01b7d92fdd438fada07d74cb22 +bf1039f4a4fcf71ab1fc7fa496bcc076 +8a730a6705f57926d80817186fcf337f +f806962d32ee3980d23814526f67eaf8 +5c6d10da5a3dda53f63ebd94ac1d1433 +889e0d7343405c079195e7b8903c8c9e +6e6a9b53231e0a312c542add87ab9720 +8ed1ff0681353bc517351f43580ef48d +89ebc5d832a158c2716564a33fe2a4e2 +f3a9bd5df1b9eaee6a35ff299ac444e6 +fe679966c85515105142b42e97e06667 +df972ebc50f626705061deec93ad70cc +6c2c4fb96e7c5805b4cdb0590292edfc +942260a5222e002bd106669ff7673f0f +7de215fbc6d24ffed2772b05d20b23fa +b8befea206310b60ab930dbafc546cc4 +5c4842a0c464e988c432bec9d4a1da0c +149b8992594b5d299f6938df3474e5f0 +da1c0644d71a64d1e1ef7d2cd152e311 +b9a90a8da80dfb1b17f330b9e0fa6ea8 +0cba061c25c86424187f08b0344c13d1 +da616d88e7c0c86328e1627fb027cd60 +bfdcd38749914b6a6f6b809d28f3b748 +b3288a1ccbedb57fbc099f8091c72f5b +ef291aac1fced903097c8c97c092cb5e +e0b7ab6cd3e2df496849e69c355045a7 +b16eb97fcad2058dc843e67c4231d612 +59ad0715af88b6ce0d40846ba2b911ef +a13c509bcb49e671860a1b6bcbacb192 +683eee9c5490841fa9340db2d4460af5 +d122b23cacade5bab9fc7e4ae01aa12b +5e4007784c6812c05949626b818d2f3e +2fa6c7db96bcbf0d221eb1756cc5d1e6 +b046737d4e8bad5e75c7255bd4565132 +30d9529ff51c6977fa9fa57bc73fdde3 +cdbc96e660fb1ec36bd2240d8a099e8c +007002d02a0e5243c2c2f05d49658fff +99d3d9299539358521750646b32b208d +86a06296bf6edd34aded6359968a2f91 +dd3d5ba946d1666686722c6841ed140f +ed1652b55d75ce122d819ad918855b68 +6747fe07fd795ea7a05ccac8684a16bb +c4affcecd39cef6aaeab30ea1b6e5d39 +73e18607485b92176854916f893853b8 +38b88927572ef1271e58f51973360740 +90bfede40f7589351813975552f0738f +a0e04bda23c0e577b0c1886c6b7654d5 +b35883144e0fc29c60bf917c854723b8 +e840b808b347dea2266e7c8aa6db9679 +b28bd0ec523051c497c3f5d30d438476 +b99bc5545c2eb2a6fa6e3fc98f0ef972 +fa4df337a7c7775468fe99e40a7db75f +c0f4ba36f371e0c64482f10e3fd9db9d +4392eabdec418400435caa224e63d5a8 +b4f080358944d93c278b168ffe7eab0f +84bd0e336749e2139d35a4e1035f4bb7 +b80fa55b1234f1935cea559d9efbc39a +550ad2dc9ce7c5cff074cccdbfb690db +71f48b3561c9e187a7f356729c929a69 +8cab5c3f5106aa48299dec51e77921ad +e5a76fba846cf9ae8094b4eec61a37b5 +d2c41bd3eca10077d3083451a97d7589 +41b0f6b48ac0a1ae5415e271c8a7d28b +a539ef1081d4db7907c282c5177942bd +fbc124edd79499c4be3d2c562f2f2086 +1195b8149924fc984d72028d2854d1c3 +c127d565b1d2d24c4f427371e2da2d35 +17633033415b3f5203b35ddf8d62f932 +8675e02958680d04d4a3b0841884985d +9eb84090956c484e32cb6c08455a667b +3feec316c195d244a5a5c9ce39996c37 +3a844f435fce71b6195b8e0e4c858373 +9c134b68bda2a13fdd45e305317a72f7 +8085e32668d6c092bd8db6e0f8d6b0d5 +172ab715ac322bb086c5f5779efc119c +fa4f924ec5fabe54c01454f5d0c226c7 +f57dbda547fc6e900a0f8a585ddd9b49 +3acc80fe16baaa7906b5d509bfcc9beb +ee756450501a87a3d32c9ad4f8601f8b +c0f29360f10cb91d6e4aa076d6683be6 +4406ab09708eb799608f42ad0808a0da +07e3a8e88aa6196ec679ee53bac208ed +94f4b86bfd588edcd2a1ad1b0c15e5f2 +1dadfab8c4b9ad144c0c7d67aa27de98 +3f270edf01290ae09757b8d0b48e9c69 +a1e7c35a6096236ac22f4552d1fd9f93 +48fc24a29e691cbef73a7cfebcba20f4 +a544f253a1ea5a0299a20c45cfdf5de5 +5da9bdb109db78e382506b3f191c1a6b +2feef6c63c6310d25c432e8395978f1b +22522d301e83920f34347994964c6a7c +e3227418df82f5f21c975e49ccc62a2b +5300ee158812c49ae76f8de7023b7439 +bb1af71a0b5df1b195d4450f17b94234 +39fb3684093f22431670b76ec39cae52 +02cefbcf8b365c43ce10f25d7268e2be +1a5169406e826a80fd6f4b90ae065952 +26a9c51120f830485bb5361013c66bfe +3a3d1c1aa974a4307357e8bcae7cdf04 +eaeedc10835c6fac7596b8fb50501071 +064b20c12758debaabc5b6bc9a5e5931 +9094577cf5e5d1b7eff82eeece831efa +0e68eb77bc44140efe97cc93cdc5d4da +04d38d87b3aa8b03542ecf27233f561e +bfab74763aacf3256e7ad5a89a2eeac7 +5ea9dd9cea51ba1ef910b1bbbd695635 +60adc6013a720e5b5b817752149a668b +e6177e9ebe0e44db1e92913ed7ff99f5 +77c84fc3d9f3dbe3e0829c619c85b5cd +012c96f98a453db38c9d690033c1cc20 +ad6d3cc73e852918f36e6011096669f2 +e7375833e499638505be5e2583eb317a +d5b238df9d63ec959c8730656faf3f12 +af0967225ab898d02c6f97c9a624b66f +5e05d9ae98d78c9a2b7c613aeffab988 +463893148111c989d75f0886226e1994 +9834672e612ef82a2a07ad406104cf04 +5d591db4475b1e78f147d51511815465 +825306bd68f26cbe3325d824c3b20cc1 +fa75871576052f8b15bfb9a3ef492242 +52e82ffdc207f2022f41d9d5fec5f3f3 +462d21090c7918fd1e157a08b327dd0f +e7d0906355ddb72f435f7f990a358370 +90583aabc2dcd7d36997303c01464171 +4334c7e4b358612d394c0471f69af171 +e37b623db6a9b45031b3cec4644b50db +b89272900240ee6e7bcf5ec7db6efca2 +7dc468a515d60b4c69930c50abe96276 +1a723d1ffd70f56ce1449a7349670850 +74e50b1e6797952d4fdcac808d9ededc +f52cfa44c9b0a11e69e788aee795ff76 +4aec7ca39d17bca10f2238c1e2ef1169 +81d3b6052df9ad3798dc4e9fa96e5052 +1cf105a07fa2fc158f21dcef44018325 +4c8ce59cdb4834e74f151bba4a57ba84 +99736faf3381d2051d01780706678f88 +7ee1cfd817ae55f51c9a396c297b520a +73f031bd44dac526edb4f5b193557697 +a39054cef5a96cfda8d792f8f3cd4737 +002980e7414c1fcfbf9320983a4c4d6b +81385cf7e83e4370a7e1581217ed751f +84ee95c4cbc823a158668d35c27efa27 +d05b2fea9741071988bfa2ba987d2cfe +cbd4ef67ac77c80dd91cad74e7960ad4 +05142e537fc83cc6f93b4682221bf85e +16518dce5771e4aeb31bfd16ed73bc4f +52d280ef3ebab81285cfc6866f2498f6 +bb2c7288c178cb1346418969e347a353 +8ced34b8bd1455f6b57b3cbd5ecd6a15 +4c6babbb0ee6ebc829a56ebc597f5bd3 +6eab4351c3351ea73819564cd665d43f +6d6f65477636e5838d26cecc435b3609 +08a4efdc4c95e018f4fd11cbfe8af422 +232e9e798028bcdcaa14b893abd226d8 +cfb776e72387bc6de0e092d516dc9588 +fe0c090e584d0a6aa3e7e001eaac0149 +2817291c4092f609d2ae366b554a7151 +de6c7e7c554c0254a4b07872c61460e8 +dd4534a4f803a68ce350b40e5234098f +277854115e1670c0ecb1e5ae2b5efef9 +7e9ca543c4c6314bd143adfc3a1c4d11 +7cb5cc3cde0c2269657e012c970b88c5 +b7173868f1aadd737a0fbda1281308a4 +956ea5fd237fbc4bf4663937749af0dd +774a8d45adefb0ec265a0835f2c5ecb6 +0378b130c9e2302dbdc1281a03a1c074 +0ffea914bfac201b60140a5925192bbf +b48c3588e6cf18b292cc7af30b5e8f69 +9e72465be50879757a8ec278663ecd42 +98c365db908cb42d8c417d69793606ce +ff935c55fd2946a85dee642014a453d1 +a492eef8abc81fa693ddd4f293d5a9a9 +b7269fa2508548e4032c455818f1e321 +8f898b22d33b4ae6b360ec4725a2d646 +8afb93df9265cd8ab1df1ecaac0d74e7 +cc866fc448709b673c82cb83a4be6f8c +f49d6dc10dc227fdf9b4c95955697573 +e41e31889a758e04bfda829a724fc075 +b9be181aa4624c8f5cc09edfce2d4196 +9fa48ebe8fb777e0d81a801eb61950ca +31375aebb8d31ea683bfa31eb04e1c38 +c49d1edce15ebd093bbbc7c4f506f274 +2ec48e00fe452aa0f1d95b8e0ac468b6 +a70b71e92566e81f59bca1e5967eb9c4 +63bb9ee368ed384a03b3beed479dc860 +93e5d1d0e8c4da0f12f5bae2c2fced78 +73802e597ab87a2a8f6ea6907f6a6ad6 +fa72ddad4d944251e16f0c65b02b6bc2 +57973818092c59ce168823efbb536956 +9993a5f6fada34ec9af99f5c6370c804 +80fb1dd0b20823f1d83e10d25840e2e4 +9c0ee35f44109c7f38478e4c7caf4cae +754b762e94697416eb89ea9e8cefc166 +196e4f23a22b3d2f8240708d94a8bf53 +5d391c476b5e10ba6a0a6fe4147f2b42 +d700e940c650241fd47e99fb4e3e2677 +88fa324bab322a2596641adc8ba99480 +758d7a134078bd1bcf04f82bb5e8d8aa +57e5c60e9d200cbcfa0867052778423f +6b69ce8b0eace6f1998240976ed4c985 +cf031cccbf0dd9c73388c22d51dcdaaf +929ddcb2e8619ca3716e1411e4503fee +c704128ac51a5f5a7171648aa4dc1312 +1bdc324d110fa64dec7b56ec831a30d6 +b42842a8200086e3f154b90a032ad044 +188a0ff1e830261d0253b185a1c0f94f +5c5ba1d3579e3cd3d73ddced303d694a +a4e1a801816ada60b8f7b1a2f654f3a1 +93254335c827dc880e530dcbf8925939 +867860f2dd82367754a54d6b139c96ca +26b23aac8b6ddb8f4a65a8c49efe70b4 +a022dc29515dbb4226014dfe38052ef5 +ef33de907fdcdd63ddf2e0ec4eb1c98b +7c626f5526751e0432ced5f86008d511 +5d143f4f47b62ab4a22f01b285d05a06 +2b57aaa1d9a9cbc86f8c282be9233d21 +ebaf19e3e578b52e0271eefd37157585 +87aaaf3c265e344d17860a0d4ba240d0 +0bfd48b1e8e7646128f83dae26f6b370 +854338ed991088e58d2bb754fb088280 +277922353fd59e2eb74c1f9db3450bb3 +5dcc29f36b73a4af554f5fad30ecfc2d +0ad893bfe4e2b15fda1444c1ff6cf593 +09a97e9f6c14ca5b8a71dde5933a89a2 +d8e8fca2dc0f896fd7cb4cb0031ba249 +2205e48de5f93c784733ffcca841d2b5 +2debfdcf79f03e4a65a667d21ef9de14 +a3a61ce0237840f62ae9dfc6d9a1424e +acc5c90d8a4b6a1e8bf8b74048fa9c6b +eb1a3227cdc3fedbaec2fe38bf6c044a +ec4d59b2732f2f153240a8ff746282a6 +9a0382fbb0742ab1a08014e3e9fc4ec9 +d4866cd84fa2e28c335a236195802ce6 +4322b73ddc93bd1101802ff640e5b46b +418aeefc75f38080fc12ce1e8fdd56a6 +67f61d9c1808c837284ccd67b69425dd +2faf048b14739ef68413b94fe3a088d2 +c7eab01b0d087513397725d80165a53f +bb34469a937a77ae77c2aeb67248c43c +b0cbbccc6ece36f9a7677632520f43d1 +a53794d214dc5dedbcecdf827bf683a2 +4cc79ff6318ecedb45a283b92c656f96 +c0eefed8d2ddd395fab8c03de9d9d8a1 +1984d628a17d7712693f60710d8020dd +36a09f728752f10fe5e46e02ce216991 +1d84409d0eaae64a76de9f4c390d4369 +d6f328f61d79e8131e6dc9ca0a4b4827 +5027b27565499ee648b3113c9a014f5c +ecfbccc0b7b059cd905f2716090efc74 +e2dc32c08f2b46c3ecd83e7b06e4d93b +5e2f97e53effb9c2dc7b8ab0617f8f85 +899181d8658f5dcf2c84e77650fd2481 +f468d9da133a7a0625b0fd3ad6a92147 +6c8885513306fa3b0bf5aa0042d64ea6 +67f3ea148367ee7502eca86f96c3f22b +c4ff45bb1fab99f9164b7fec14b2292a +f326bed0dd25ced6bc1799eaf74e7f8c +0d2370ce20f4689891a3a6a9cfb52834 +399f1dc306daacced93aa906fcc5b585 +1d9d1028a95c6dae6c20ae4676e69f5d +110cb0fc39697d49110b46ba9acb4521 +cc1f2c7cafa072da28e66791a4619402 +c5a90045f2c32b491d1a0fb8c2d1b18c +1e89c15ac25f7ebe164931d3e814d455 +15446c8061c2cc44758a55544a69bc90 +48cfe40c1334fa18cf39d961ed1c5dbd +ee3e2d2eb00491408a0ff79b4863f863 +aa62cba149c51923916eff46f80fe74c +d6108272b2bf80d8902a77d6d470a965 +9e7b964750cf0bb08ee960fce356b6d6 +a0311b12ed8180f815965a24044a3add +8f8f627ede15cd352a16a79d78e75a3b +2ce39a0a4d1cf193d9629ddf0c457a24 +7c5b5c2b4d2127ad1e2dbc53606b79ab +a491ab373f6f7aa1738089a7548165ff +f53e8d48da3fa60e04dda18ba1645ea1 +febe6995bad457991331348f7b9c85fa +38a460ffb4cfb15460b4b679ce534181 +bd0070ead20c5c45e202b4d4f2d5295d +df1effe92d4ea42426a40f4d0f90b772 +9b327405e4fe7297cfd1ef1af3bedd26 +25564d0c75d8d56b86d0e4d6c0799307 +6ca41843cf09f8c1296234bea87cc48c +8d3d6c9b6a91cb42882f598eb8f6ede8 +7fb16c8f37a37be280233794b1847f83 +a2f0e4d38570b827176904d9f75022d6 +6ff3bc94ae1d4b040cbd75243e8ac7e6 +c0b909bf1956c267dfcbd8cab2fdeac1 +4f135cc16357a7d55602ff28b4533af3 +14e5e74f6103e9afd76cd8528edacc79 +4821726c1947cdf3eebacade98173939 +490f60352181a3546fce422abdaeed64 +24864075bebb7a75861045ac093a0658 +b63b0f7e3297b20287196cdc7d1e0ea8 +aaf9ec25b4877670d23590aa8f2fb16c +f8212fc11b66cefcaca5dcf1b9474299 +898e528c7057174e403372d4df54fadf +03a92999986198530fb5bf891693d814 +12bb4bd8e6ee35d152c473de7849ed90 +2492535347e81b38cb7889b5f6ac76d4 +0e1c638eb33ea94bb774334c820ccaa6 +6e0a768eeb548233b34d669a534b7136 +7bec9acb4a8b60a1f297f6f719100a9d +7a6719ef744f7f32c85545d621d65e1f +701e476eee0691a18a3763787c042946 +6a31452a4e5b4499ce89d3d2cf862547 +8ca31376e26c97f12d16aaea685bd0e7 +facdca2fa68795a4937fd54f654c3f9d +0e83100aa553f07d83d201b8bed875f5 +e20523853d6733721071c2a4e95c9c60 +6f470c58e045630a6431ce230219e44b +edb0991a250879cf70eebad39e0d2f75 +c0ce2ea06c2c4922160495bb441055d3 +acae2d0ab946259abc554699cde9bdca +1aefd0716c03cfe5803598e6d27d918b +a61e6d2cd26bf56adf01c5a25ad3ffab +38cc5dfec756b5eb2603ad5afce96534 +4772db3c5549125227c4b2309fdaaaa7 +f956a62a2b7f9469318649f39387621d +c84f2b52af9b820f4073958e8360ea36 +1a3156195f49de0199fede82d3357acc +7ccf504529ac2e7fd6895acb3fc97ccf +36700c2f72721ee5886b8f7ac4c8e444 +697d6490afae7e89577eab3065b1c9bc +fce2d147f70cc4ed43bd07bf9b55df99 +62c1c57fe95dfc6832b04d6f2a10af00 +85fa285c1a1f5beb6fd295dc5ea1d826 +cf865c9a244f96e1ea1b1886f613fd7e +7514c0b6137b57735a2f276eb0c06a29 +f47320fb24803359f363a0430e6f7f9e +92dd26a8ae50838fa0b6ddece1006491 +d8e912ef0c335c08f64c9e276a78cb31 +b37aebe1e2a2ff606fc0cffeb5fa0f59 +f1cdc4ce132f796364f2067fe623fcca +f93f8928fb52458f9f651cded047244f +8ebf6644ea7e49c63508f74be6cbc9f3 +46545b999dc166a5036719d7c434c5f4 +75aa783cf373f05e4d0bbc3e2da457cb +c721c2844057c849fd9039049ba132cf +2691d423bec668b88524951114eb661f +7b8d801421fa7c19bbd7e5ed68a083af +101d04088bcdafb421b24bef4c2fbd68 +6eb67bac545741aecf3b6f1c5b83ff3b +95349d1fe2c28e6de0650aee15e115ad +06cf395adbd9cb66d755ba3a508209b6 +6cb212062c319a6ce3472704f878fc4c +962f67f394b92d60a5edf6d173532234 +cee8c022234e9e17ea9c11545201ffdf +45b7a0083d25e60c25a69a0a6441c836 +e37131f10e34780b6f663d18766a6a4d +c9d73b8ba717a53469579759435a68d2 +956155b55e401994dd5985616f69ada7 +6a62f84bec025ac467f5b881d5df1d80 +4146a7522065815381b70488b89a15bb +064ebe816ba8970e46e75147c0f2d000 +206a863d746e0daa3ba0031832cbe56c +b69d6b6b260c478889676fc07279b02c +d79a46321d578beac5947088a76d2d67 +6fc8ad2d58a14c64feca87d90df4bf71 +7ab1a2438f033cb96a69bbe646cb4590 +a49eee6c5494b1aa3f185693885f78b6 +24571084278bfd6468de4af277ecd038 +f294b0e353fb3c29084ba676457d9783 +74d9a83219cabaab06a69fd318873f33 +1159184937f1a52d70a06a50d63b5947 +e2c105228519b5a5433db375118e2332 +99239ba46e7dcffa0784a4f0d1c5ef64 +aa2014dd3b122914bf4f824b853af869 +317f692fe624155ec1947f50d331f271 +d53b211329e78af5e6463749bc6d0714 +9b070a21dc6e73061349c78d539bee5c +09e0a3de2d7dfcafa973715ddb760f89 +5841af25c604855409fc52cabe606f26 +13d1f781cc1bed9e667d8572d874222a +a03e77341a8b095c2d8f024383006f2c +64949674c4123e25e25f2c43b5deb362 +ad526cf8cb02ba4357c2ba5b0c57835c +cb157e9c24f6a40a02fc374035be62e1 +1fb5c31f942b57d951c1012ebaddf09f +2de789af4b14bd026268b6b6eb985d37 +e996ac15dc6dc9a2769ef5c5ae161a45 +c193497a1a06b2c72230e6146ff47080 +3b0ea049a78d4a349993eeeca0c7b508 +f35d7efe3efb3e67af82d59c734bf437 +9b74508bd80070fb3be9d5b0de67b225 +dd16a8073116b85e214695092e275668 +6d88d14412c9b641978dd78699106431 +42e9e20b1c07e46bacb8be1c2e4ca464 +3185bd622133f978233810eeabb26139 +98e3c03193aa7f4d98afeb99fc20a19a +686b9602ec609a6ee2a8036e163d3012 +e85dde330c34efb0e526ee3082e4353b +c03b74ce71730958d41ea3cf66bdd775 +e71ce4c522df214699c016e6a2462d05 +68b8c83772ba7fbde6ede4c028cadde5 +69964c85e7488e7f6bb90de35346939f +ab8515e66763916a2ca9ee64f75d65ce +ecb6e8fbe54f0cc1675ad53bcc00929e +50bdf511fbd5246aa0b501728157549f +e4cb2404c80f4ae6c3a6e6766428f31b +2cfe6d80c57e253df65e2fbf35281c8d +85ae5b04dd0a666efad8633d142a4635 +afa9e055a5eaeda84dbf5400e5279da9 +4666fbda06deea61fa7aa8b1105d322e +ce32ccc4d84a0618d3f1cd92264ee629 +20c6d5ffd97e51e743dac4e261780bb6 +002bcaa7be0e2aa3d666479c6a58cc91 +7938eb76df1eaf10e69f51b4596c0d4a +2fcc8acea8f04abf3cc89f988915fb1c +b12eb505c077a659ce9892086626dbc6 +78c30f15891078bd62509293901b0b9d +488177cd52f120d49db1c37cb6549d5e +fb4b8bf5689b30826d92cc6c5e60ed86 +7f2a7e8b8188d4561facde7646209e8d +41e2ddb3f605be9d6078c45bdacdf030 +758763b1dbcfc998ccbab81c4caf7ab6 +b3285394cfff6ed95a312df2a77904fd +973bf50a5b18d48c11bfc36ebb9b6597 +c574c049157e40cd633a729f785c2054 +c212f715e6479c580c698bff6e33f513 +07f044c4aa2aeef9f99063b5c683e883 +e00cf001dd1b9411808595a64fb36afb +e0f38923f92c2d291d58963d50c61af4 +0cf57d02e3d8f8bab9dcb840ccbbc29b +0209bbf95b332e2ed15315b1c3c04cfc +74758f3e77948f32762ac7a3185d3bbd +9cb460c967195a0c0b495b46a678a00c +b4baec8e06bc53c8c247d52257094c93 +5a94696761e458f1c659a666554848fd +db46819e9b11ba1d7b2755607f9df790 +d8d4956af6c16bef1e8bb607befb1df6 +a4265ae04f1d80a2234fdf681044250f +9ba4476d63f36e51797fc8fb55038b78 +2453eb7e7bffa21eaaa0eb8748e725bb +8c06943322f5851baa3b8f227ede6ca0 +8bdd12d543a6de810291990b7b75cf1d +2f4a44ddc6f9b12b746ff87acd87dce7 +d182dca4ec032d6ad8e502271db27987 +5c01f54a0e31c7c1d5ff326e9c0af66e +f9a2457174f30afce1bc036885028f27 +17642f323beb2ae893849864865ca1c3 +e6ea1d51e76e2cf4b854031c5299741c +a7439af1dd7f4d3b0b04d68c8340e60e +71459664d828b0ae9c6b0ac65010f7ff +bbfea47a95c7d46a8c316b4a0b163e98 +632ad53f324229fefb9c815e00cfa803 +bbf9479f272decc274925301b03c75e5 +62c449dae5b3d88fca3ed3a696c6d10e +bd6a883255a0fc9d9bf6836ebac2991e +78942cb2e9eeed33eea0d3ade9ef8091 +67839e1bba5029447aa47d2e4b280b37 +01eb2c11c2685e04a0e3b0556549b914 +c5e1670a76fa30eb5c8cb1969cb58536 +83d043db4fdfe6882fb7f01a09d92b11 +81f28522db473d9139d0d4fb8d614063 +a0c4b5e29773d26e23e002bc7b736786 +551e5380f5506bb4d719a7b45f9a1abe +c253705057a0524fa60402bd97885b33 +362b74a8afc92b057106c5fbc04a0d90 +81efbab6fee9ecfde6a2f776f786b2a4 +a1e28f4d48a02908698bfedc88c219f7 +094cd8a9f8fc80977346f2785e22ff2a +0aecde75489b576541e5d9f4be3d00ff +feb5d5e8c4cf0497a3c5ad306efb398e +eb82e525a12d649fb9510f07e9c83325 +e3fc5ca459fa4184986eab4c0231dfc6 +1626aa5c31e7884b064c687e410b2d00 +d10acba4acaca68b887d94b595e71ec6 +00289fbb5238b3130ebb557b51654b34 +b048fc430cc5b27394d380182f6c6092 +66732bda8c829a56b55ccdc2e1c5d471 +f5bcd92f1768a52d4e6051cef7d6cd52 +3fc55ec19cabe5c2d41512941734c90b +bc37cfb8a4ab960c684c7feb5cfa699e +f0379bf2126c75446b7564e136856783 +00b4288b12a81b04c5f2479addcec521 +8af8b52c137b5c51a46f3d0ad34af4bc +af8004eae894359af3216aa1c60d95a1 +17294a8c1602cf65f9c74356e5d74f97 +1011347732ff50bb963505c6c0b8ac0b +f81230e49142f7e24740eb27129d9ec4 +a81be4e9b20632860d20a64c054c4150 +4425322b4d3b21484e2719c278c0a459 +b908744b4652957ee5dfaee289eb2d3b +6711f799eb9198afaba01c3218d1f7fd +17e927e24398f2a8d664921f72a6db49 +af3a4c7a64503fd41fd2272d480de458 +ab1294b58a623d6286a85c0f7d412228 +fbfa2612d486c74e872cb4bd607cc4ae +e8260b6a05e5c2e81a386ded5c997c3d +0e2eb4b09f21fceb7b5599375e88d4fa +5466dc8e0f19c658db16ea420ad5fd98 +e46608d1e2a94002080841cd602cb37e +4d7103309dac636f38076156e12b1770 +ca87d201d4ea41b06e488ed98491dc87 +00cb3b67cdc727d0f4fcbd14fe881b61 +e734a88a1110fa3d657454b2dd348822 +425a3e9d228952d6bf6ae19e67d8ade4 +04958db9d5ea968f563c5c3602735692 +008ad728a0f71173de0a786b9906a494 +24faa4ff9c940cdc28d61bfd7c3249af +2afc18e93681279742d4db33766b4acf +62110a75095ebf61417a51fff9af9c7f +5c6d8547e8358ffb80b9528598d72784 +864fec29a0552d8775fa793ce861bd92 +ff082c7565fc3663a2515e87b522ca17 +2ab93cb59cd9062c9f06e4b349559dee +d64ffd4275f606aaef843121055ddcf3 +756c412732c9e787f483d35d939b8ef2 +3aeb223d7c502f5b3636a800390a4b94 +db1bde148504c1023b5d56c6942f7db4 +6495f524902879c01f8a5d9f9d9ef519 +26dd85b0dc5ae876930dcacaafcd5d6a +a5ca744578c7c5adaa6b5b40ae82264b +621aa3eecfb67224f195a703bc17b015 +841ad5a77be924b17e38dc1912e89561 +f08018680e2ad19006c5488f9a74917a +1a0369c838551f778e3ad7a7d994232b +50f6c8412200021cb20303bbc0a0243e +30fdd54916489507bb21c8c0d72e1cbe +f04e34bfeff17815d948c11dc1744ef9 +f75c79dc29b1674b4709631ec6dce111 +2355160526e73e68fa203cd3bf38f4c4 +6a90a572f66e44ca87d2c4ccd7201821 +ac2410819223130b133199326572628c +b35dab38131090d8c042dc6c88668d38 +78d2c1f50e67bc0e9a47beea1c71a8e4 +13370c426aaecd1affadfbb4ff8d762d +4021ddad6787cb9a6f9a3a20cd6644b4 +5f6608c9486199de2b4926f0de14ca28 +44bce04a1b8cc69c30c6f0f4db426b88 +0f4add675eb7a0f1ab60fad1d520d88c +a9f4c6999c22bdc3d2beb09ede41c303 +5c17bcd16bb3be2b37a891cc392ede76 +fb4c4bf8e31a6b199bfdb27d8a83ba10 +681353e1c604daa6e1ae76fcfac42f2a +a01ec276627545c93d5af1e967038d33 +66eb65ba78e264e73ac3f63e17fef4bd +4f3aef420aa0949b4f5008203e45d856 +4b4c453c615a7e02ee30cfe39f6453ce +6e6c2420ff71849263a56ddabc5a1731 +d1bf2f2bd3de831653bc0bacbb09b467 +a52d3a367cc210f15c9e069bbd9b7be8 +39d72474da39b9c3f1b7b5479516b2f9 +d705d440d550129f6a315bfc489bdac4 +73edaa53630092479f75833f31e8a5f8 +cf435b0c182b6a660be221d30a9ac740 +83e352593dcf03d993fd671c0e367875 +358a9643e1a3eaba14829bd18f20c114 +d5306b61d06a31eed60a5b43fcf2f0ef +8d6511088d84c292bfffb3129ec0febc +aed58a22fbb7e21e28800fc59cf734e3 +b7f5e804744db46230e9b9fc9e1c3b81 +441e3bcab93a36ceb4c698b95b85077b +0c583b2e313ae447b56fe6799917d64c +41bad005d542c027f208773d3f0f4a28 +c5b29130a66acd93dd6faffc6b26ffa8 +dbfae9271df847ee0997ce868ef7a4c2 +fcb81f10d3508a1776a7d66be7d76ca5 +e4b5d9bc903fc15e809d5168d4053aa8 +aff776838092862d398b58e380901753 +c31d417aa704daa7442ff04914ba2857 +125ac6c93baeb3cbe2cc2e609736e373 +d0e8e4d91ce92ddd5bd6459e0388a59c +b938b801a0bfbd5ca4825715039e7574 +f14e837db317a2bba9826144e7831b51 +e5509d515db158951ca12f8394421da9 +007fe7a50612722850c6d0d914111cb2 +2f0f58e1d3eecb6a059734397f4dcdaa +61884835943e3bee24d58a0fca7db8cc +52b1ad3c07418ba7ad6dd365bc1a3e8f +850877f11e3b738d45416a956917d918 +f8806e5e8dae9baf7489e69b39b8fc7a +8c1d89fffe96c9b579a0107da70a4d87 +00e0eed5ae9818676e0232661640f765 +8c247d847a49e597f8768befc4593aa6 +1af83dd9b1ef773614b21a6ad04b679d +019311d24fdfe9d30aa767f19673f08b +159e710993ef5f4bc56e6a663ec4d9f5 +c436479d58079d5e6abf7402040afff1 +34dac36fc280a4ebf0cd18737ab28489 +1b42a11f5f647e53d20da8c8f57a9f02 +84c41802423e95432b5d02d73c6f1b20 +0f19042b401e559884e6200d95f1732d +d8d77109f4a24efc3bd53d7cabb7ee35 +5d0863dec02079debb22c05afc933dd8 +13634f24a4eac7f899aba1a9dc59f989 +6aba28f98c745024e4dd93bc75414d08 +d559ed7168ad81e8f7949ac3335653c7 +cf735762346983d0079d942c83886005 +b3e1bfec468534ef3df6a064caf8d153 +93f578d6a0c2f2ef3bc516e3180ffcd0 +f788b5d932a7a7ca56ac03c42a9724ac +f4ff3b86b5bd67b194e1bd800ec35263 +5af0140cbb7473bcd747b524554801d8 +304d82c0867e556f1b5e676e0d11f520 +24f90815ef27c641dd13775f97d561d3 +05f08c093385d02c7037c83235df2c88 +0fbbec077755a1170055e60098ba5419 +f0499d65622d0e4e1c12e96c5edcd4c3 +5bc81eaaa1393ef052830ee3c8f92bff +28eed834a318435684627015056d81f8 +869936e8dfe38c70b651abab3b50ea14 +b147499b537481868fd466e59d2f2e9f +55695ada382339fd7c790dc774e71f8c +71e92394af11cb927a5740b34c6e5d35 +6736b737bf7184a2d8e96641efda2dbc +240c2b1789881a6e3a6e211b68abc979 +81ab62a717e411ce854fb278c7776989 +00cf4c1f92298ef931d0c219812bb3b3 +78b03bd32f8513e38612b2a33ef246d7 +ab08aabe2888fded5a84286e9dc92de9 +a6f23f62bff85ec6f08fbd0b177b439b +e1cf1ce02de3fe42c8666443f04a7ad8 +d6e4a2182f7914b8f82b8c73114ad24a +351333891b9653349fcd40204d44ee6a +a46ec67a0f2e7c387926ac5d783ea4b8 +fc1ceb9bc84bb7b35340fd852928b4ad +4fb7f3f4f1b4ceaa707e1429a0e81524 +82ebf1d8509d459d2771fc7f122371dc +993ed7d20d5f775dc558eb129f5a6c20 +0bab532090d2068e05637757784b9ceb +2940952dfabfbf5739edbfb236d85778 +17cabade1f6212fc0bec52e64e366add +fdacb7c20b9065fcc1d3c5ae350a31f7 +f10a990c00b231fd5b8e35099453f41d +9fbc73065780f5fa7700d8e5001f28cb +d9ffc45a69e7cf198eca9e905cf486a5 +adef66d348293d06e2991529f6882135 +68e82fd46cc9b9a4199594e5b28eb050 +b50075a4289e9847569ff09c0dd4393c +c4c04f969e1678750996b3f16cfd11ce +fa44d96b596c5eb05e68f14578e7a2c1 +cef8a3eb82d81b0a93a77e962042a26c +26dd41bd1005550477ef82a72db3de1d +0132a316c0945ba04b0c37c6cc229268 +cd61e69a6dbcabf44a61a2652324fd4f +d8f1c5dee9f2ab31b628607fcbc2a982 +0c170fe680f144851874a532f3e66dce +7108b7e24d06d2edf311719ff65725a1 +67d3ff178a2af39a853fc07ca32b67bd +513b2572a5582e37b88e0d9932d77abf +54342318b35fa81c742f4faf9f88aaab +9d365f59076828add0b000414583cb33 +81ebcae3d7d8e2f6bc985fa037cfdaa8 +ff907fe5198fd9e2c453aba0b3497473 +2f3e54cf1b329803bbf81b39fa6b46e7 +bc744907ca20678910242e565fc65ccf +0f7220a0df94ad88e497ae2fa6c56cdd +401b30e3b8b5d629635a5c613cdb7919 +253bcac7dd806bb7cf57dc19f71f2fa0 +44276bcb960eb2abae2d79defe367351 +a4b091c0b5db4740d4bb23c630efc121 +a47551710577014847f4dcdf9b2e26d4 +4f4fffafcedea0aca5a4d70e80e2238d +cf4bcfbb7b32695fc4556d9d818dcfc9 +571e7514c0dd9e66686493f790d5f44a +de6157099845708abfa016b514a56ac6 +4c1731dc135c831abc8835f1c33d049b +6581e073b5df62bc934e9c3bb63eb037 +099fc8a2760a04ae1e6874a343a1fdff +102f5037fe6474019fe947b4977bb2a5 +f8caf16cb8f98353e7c5c0875b146714 +531c55eb282fbac78466099ac4d56b69 +3ae2ea0c3867b219ef54d914437e76be +21da93069c74dfbc3c02999e8f27a712 +da75d143c87e8bf310df70dbcaf3a6a7 +e294e47d9b5eb55a3d0e7abd0e5056b9 +81c26d1dd57fd11842fc13e53540db80 +83d7aa8efee1b5e742d7686a6d16c9f1 +ecf2414ab13383a708b8bd37cd846688 +2a73131d35404d2308beaafebf1b236c +41ff0912a07fdc52799ff27b38e7f140 +ae33d6face3d0a8882059e2583725b78 +5753f5136b1e824a4ae16b8eac1f89ac +c4d9fa4ac16aec5cbf13aba643207372 +bbc6d2e38fc62e52cfdbb1d2b61f5ea0 +446ae41827a47ea591871493d8a804f7 +310db8d7617c0aeea032c3213a87c260 +6855adcbb183229d50471852801d2f93 +831df319d8597f5bc793d690f08b159b diff --git a/bench/data/pathological/random-huge.txt b/bench/data/pathological/random-huge.txt new file mode 100644 index 0000000..aa6d8be --- /dev/null +++ b/bench/data/pathological/random-huge.txt @@ -0,0 +1,10000 @@ +56be084d3f2715872569c01199344289983528891e88bb026f672d4e20c09c3c +8da6c3d42db76214c3518cccc6b23083a83c1d238f7f68dcd9ebc978f37b1555 +2fbf8080518b0f14a20354896b164ebc85322853912f5d85cb4315006819b1c0 +172f4f5f318b71ac77a57d3ae74217e6c4af81d890fff8390161590ec1432f8c +0e919cc3aac91cc2c17e864e43058556bcc8eab980140a40f20b88df0b255ed0 +93de9c3cdd42c07d1b379b9a7bd9fe3dcba2d73d8d98d368e042c999040e072d +e6f36399001e131292b539a6d31cf30740bb43bff9dab5445c5cd3a77c6c6cd4 +9f35047352218fcfbaa4bd7184fd9f9bab1b2280f1fb287f20a7b7768d34ec2c +d3c9944a994c537a65f3201d767865fb0ec376ca4464f88d254a0814e768c64a +a2700561cf29ad4b935da21801854d20498e330a05cf889652642638a26be7b6 +a8b94aec972b3eea23a33c2baddbf62c832123691d9aed9e50594599832fbed3 +bc63adfcbe66680e773edf681601945ff8efd114f789a890d5e3d083efc17ebc +3b2565599cff5c1a1df7f41a20e96c83f84a836b77874ec90ca37eb89528742a +7b7e188293f9c2da4241b7b4da29c80c2b0bc5c8542b9a8dc2ed35ef27702482 +d15a9db94cd23a7c96bd99c5ddbf47aa2e4c060a207aab6d2cb18eec5609734b +afcd0a88ab53f797329e10890f5c6fe662c6673f577fa43205900c39a300edc3 +d642312181b2cfccd407bca979cbf68a6f4848300323411d588936a8a8b2d8cf +26cdd63afe57d3e7ddee03f8eea28acbe2ec3cb867f381c41135ddd808d74576 +872a7220d44e54e4e736021713645ddd128e766359b5145460e0e2fab343f58a +446cab34d5a596c016d4d0776ff15330ba67ac50bdaaf763a5d8b29f91a57470 +a30f51b2e3f1b6969ba1607e01a0d43e948b10b82dcf2e4f61df38bd7228803e +4cbe70e6ae2a4609e435803b99ba6ab0d71ed3fe70f4fe212f58688d67a171eb +5f7fe2b057a336baafda048b01ae86cc49576b023a570f5c2bfd188815197c3e +a594a5a22b30e5537541f84e03e5dafc890031cb6c1b41aecc9dd872a8f62fef +3907501634feffc4be3bcd37b0f417bf614e6393a15cdaf2d77a77bf28501c07 +c561f1c15317f186a73bcb9a578c5b361b29f92a580febf1859f7d7494682d70 +e836b8fc425aaa8c1f90a7b8bd1ca2bf45ea0b85df53f6e5f469097e564f1b80 +04dfc6e4170e7c82f9801b50cd0e82e78e68c8399a6625a1b50271861b7fecb4 +6b4570524522c468b9de43631659bed793c140e70c5ba7ffd69a0d1856068dd6 +5fc868d380ceb7baf7d1f55d105c7040a9d0d9edd2b06c2233b95f157a8a3c34 +0f63474a5a7b7f357764e0206afafd52333a1b00c61fb68631eb541dc021c010 +66738ffc8abc2416ea4a9d7e41b633f8aaacc8f3bafc6b0d7aec15d5143d43eb +ee9ebd9a367b8e7a2e0a9c7b6cd03e22fa1f33001982ac35682d2778a6533c63 +5c49a43d8d73f0087d0aef4f34ca899141b76b256a15bead1729de9122bb13e0 +1218f02d488688b97551caa1520858b6d34d5cad20c9db5d7535e044e53a4556 +ab75110d9b4c3372e861544959787ed851e97710398d4e30c96955a9a506a1af +0ab7f810ed16350d6fdb00ccf1d3882e2e0e416c18ec15d89a6c668437fe383c +930fb139445a083c94960ef2d996b39c88a688f3a43a345656f36d63b98385aa +3fd20527459dcc5a552082521bbe5a59c6af51fdd822294d9f3835504c7a043c +ce65da6469ea11a1357befac8b80a148b3c37eb64b2df348ecbeb2a281751e42 +9d28538f4f1da2f91fb16d087f4ce7c502d2635ba8a4810bff34b16704b8c82b +e1599d31febdeb0be01847614efc0654c5b33292406343806371e818fffd8e07 +d44e70f2211275ae201a4897e956b81ad1e9cdeb87a994313c9af70b86967eca +08d88617d217457576c287e4a5a957d199f27da4ff09ef2e10be81e41ae446e7 +7ade1e3316210df092a15139177cb3063d9dfb332d42fa5ed33a2b704a133ebc +240b21a16478d48f0bde7c6c444ca2cb02321ddf74f5d76de98cf6028f1b3278 +29d56c620f0648df0bc5aa2167a0a062b9b49ddf9da63aaf11589506a509312e +54f960043fe51250f9ba892a3d7d2dd01d642c515ba9b7f6219c1b3b1c7823ca +cc275c210c6298bf0e305e0868709c00596f240c83d803ef4e72fbea148947b7 +8c93531f265c51c42d77f7e5014317b2327c1c4e36cde8e47ce505e9b0d5b851 +5543297326a9b5f3cb830bc0cf9a98002ad2cf50cbe1cb00ae24b1758cdad206 +5f2b6dbe9c480a61a463c4ca1883246176f4f001dddbb8719e879bc7dd35309f +9f06b8e3f179fe9cea6bea7e42bd2d1702e6a9c5c99f412840b422086db9227b +08120f13be3f8b80cd79f020ef357aac128917e8c0dedc46f2815ebd205070a5 +53e4d9170423af2bb74ab5b6a907adb52e65d2ddaa3eb6398b3a844814b2ce1b +8364c2231512a93cd3208f645ebc2f3669cb825f445dcb1e305c4e92015beacc +de9bbd2359c628eadb29ef5958ea9a1aeacdbf8eb37b79b7cd2044b08b4e34de +f92d35617d91481f3804e063be5550129986c240281b74fd3e07e9452de719f3 +06a004bca7d2535871887ff1acabc3f0e0d19c4c7a7c034eb486b832ab47bce9 +60c609cf35016a27d6e9847c3239d1bdc1888ee43f72a28eca5e268cd4041ed9 +ab325c5a7088d4689dc6d9f748de348b73f3ee437108d3b0a4f7a910045f7798 +5a533b2c6eef0e6d6b5de3afa619e110aedfa9fbd1f809bcd075ccce67c3dde0 +6392182c9c17b0b8cba683a31120d31777b30c39c708188f53ee1a177083cce6 +95b2005f4eab38f10d6b9bc49f8b3b92871c875083d4f7dfa47bb261ab48aaa9 +d4af3822b1ab4450ae7cac420bd2d7b49325b7855bdcd5961ba20d76634fdc46 +4d87576aa16337f78901b8f37059961c8d2eff472cc5a6d14e50251512145264 +3e7ed615f0485400a1072741b21dd58f8da00debf5ce253859f07fb6caa6c435 +f4df3cc96fc9dcee14c304be1ae0c2c9e6b48fdcfa3802c7b94083a5f9070f85 +baa6a6b96e8bfe9572fee98e3438e6ca78f1f149e450b46a5cd07bbae105933f +550a1edd2bf51fbe98871267529bc359cf3d3fa63da5181f6797188e455d1eb9 +73dbef11631369dd9baf64c79bf9a1a44c8e975d10f0cf7cdf6a8ecfa4f7a79d +f576cc40b74d7c0e119d9a44ebceb96584b99a9a74cac6ff68189d81600a4d2b +507c59fae3581ece2be999c147d0709bf8366ca83461edd431d126760ffe9345 +ac33341e6e3829c9cea3ab7efc03f2d286c6a20e5244286a54206a5122aa5a36 +39b49549f0e50a2ef1334a528a413d616ef0fbcc346ae0a6f44c506ec595aad6 +44cb278ccfe5fff8224611f21defc32a502c685b19281f70fa9c057ae3176ee1 +f1004ad2e62acdbfc3926d26cf6609237709b9daa6d6533c70a8eb6ae5de803f +ec9645754915aef6403e14a2ac86ad8cfb9177aa0f92680d6fdb69e827d7a258 +2ac4047e10c409c92e4a694a14fac2955b4af919b8a188afc82608959610114e +1777700d92b076b4d7c8f2cc5c098177bace8ec3193fadc944e58390843c0af4 +2f403d595fc399900bad7c80876b5aa155049b55c13d62634d842556519e72ca +099bb9c10c1f634b06d68a19f047899253e0a3fe13f9ddd6b863e4e4cdadb154 +f60c044df83e5d34e0d5c4039ce27b9e6af2f7a785f2827eda982724c7ea35d0 +3aea0d0aa5b23273cdec1641db0e9f4754a7e63f822d2d9b654084a43ba992ac +490a1a37a58a7e9690336215188fbaf8df411c84f41b2d660aee4ca712f3b662 +1d427cbc2cff960e4c7bbe6c3423381162e6aa9eda81b1a71b336eb5ca3cb99c +1438bce7c957873df9344ebb382032d4f3abce87c2d9b45ca0acad41a2fe134f +c9b57022aea6dba429883b478d568971dae8c4dd913c2c6cc3107b459d8d4439 +7bfee8dd65b6600b8aeb2f46b8ec8378e60a080c279b6609e52b813570d0a93d +6881d9076e4bc37502fd639326534923ecdb1d0418d6bb047522214089580090 +7d80a5b62bae0836ecaeb19332ba8697d73f0c18b81abf218f20ae22a4cb040a +bcfe749a587ee3c231ca49564be41227a7b024f4e12017e52525d3bc250ac02c +9021f7c8f192a0ca00dec05e5b2810d38c89e862f602bf0c2f790703f5a339bb +06106df04c3f088044e90400c7eaa8fede6e7fca62299d79c851d2197b97a681 +8ca2844fff7632e4c04033cdc7664a58cfa2654688f002e7ea6bdbf9b4cef02a +27e8054a50ade53ed96001797afa9fdaf96a880056ca2ec6f87e50d525e0965a +7e0f2244db2709e85b8c7f41cec210cf724fcace38d6b2a7518d2741bed0e94e +f800b685ed6b8d9ad8c27006529fb3c1438e670067f73ed03fa7100b25f5c944 +691e114422eb6a13374398b57468b5b82f3bf34f66392c22616d8ed156f9f07d +48225d19e558d9867cfc9c135d77af2575a3931d171c55f82745596de2cbea86 +f9bb8c6cdddda9c1dd22c71cb8747b432a84804b6f924ad1a30b413ace06ba70 +b5e846325dd6436743250726d1f5b55f9516285acd720f1f02f16246146880aa +549713f9bf3c6e25c1c9574858622d1aee1e886e94ad9d6e17f80730e0f58c5f +d516a7c523c3eed7965b5b3fc77c6705c44ac2453b9d540841cf92edd3ac1e27 +ed66ad49957602137131049b585fd4d6db4ed69322aee62d20445666851599cc +4c978fbb837169a8d62c09fd72772683d12074721eee9072155184386a69a895 +e2cd1fb99a61787726a5bcb6e8294da5bbf206d37d56fe7d0f42a7fa5413f0f8 +a405a371b19bec14ec1a06a6483db2d1585f307b32a9e3015f5ef0650601758a +cba47b0d2ab681287e83df6a5ea626ce3dbd128ac1078c270b19cfd9c7dfbf2d +73cd28fde8158b5ddb5c3c1b1ed19c3f69b33cea42bfec88e3c4999e55d1a22a +0ebb74f0f118a7bc551ca324c6d466ba4b1b39e55eca3a1960a20d6c742bb49f +9f2113da325623e68a44e695363e2dbc8448ca37692a36d3ac53b5badf7de798 +3873ea0fb819b9ddd6bcccf99f279110a7d57d363aacf9afe5b72313704dbb4e +db9e7f6b91c24604cbf909e6e9b8770a1972e1b79d539dea8b2857714f1bf135 +7f46997d1e24f9f9429f5fb464775bdc798fc69d181b2e2576bec38af916513c +f92a79aedbd4462f8dc12b0489e248d2cdf29def752f50faee8696ad0fb182a6 +acdb3171cc6e9686abb7594186a22f25d2549c899d37c252d78a61f3175685f9 +8edf116e082adf12384f0d5b2dd788e1d2fcf73356c2105f0448439888c3b85b +ee13b20f44feee131b66bd63556572767c39c727755e692ae84a854e33705455 +33f1fa4710e8c6cdcbda94fbdaf05f5df0e49247f75c122514a8892bddb546f1 +965e798275e6df6ccdbdcf8b9723cd7553b24d18f0d399f02f69534a070f5816 +d79f804631b4622edd4ef34ddf44caebac13eedcf4873e64d11cd9ece65e6c10 +5078bceae85225f7c6868ea66d22bf81a68eb0b70488c51072af538d9bbd86f9 +38307bc9bdbf89e34465cf26548dd049fb0a55279d73e52f66e6e385ad88eb56 +23ff7419fdf1e695ba2ad54fcc8fd642117630d84d5caab184684fee04d284f1 +b49d9f743f85ab96586ad9768569f55c0ad3b46f0f34daebe196dd2089cd34eb +aefcc2aa7922f8c95540fefd48ccffb1b3ec62b95dcf76343c545efdf7a9766b +9d0870d39b9d775728d05c01e686dc3cfcd3d037f3cf4d69e9b4bff4fab84d48 +360d8a4bb581b419da05d6702cc1752bd4460fa08501a509329fa6aba740d04f +28778f302be818dd1fad14ad6a766effd6c85f45658196401ff319410c88ef56 +e2758fbb33ef22e99b1a496b9f7f575158f4ab6f9de59f1eac4d3f09c0432f8e +6cff7335e2d6e038a781e9f3eadbedd39da3ff7edb2826f717cc8c911c47d2c2 +f8191f3802e678f1828dfd271b1e1859ee77126c4faefdda98aeb6873bd0c258 +2a09aee71d37b678af908e55de764981b0ce12b25f42510f24bbeed002602bdd +0484483a2145f2b46b5c5bc8421ab320e2da048ac13200695c104574580f47e6 +79551a8c8a809a91c1e53c763e929eadd2764feb8744ea2306562eca1b954f8f +7151fe6032e48008e179f55fc0a847e51dc092bbfda5db059b121234bf0c757e +12ac37908041a79e0052f5a8c7ead7936acb50b136dd67f14f5c8fa413706908 +8927d7c65a839794914488c03586fbf04aba75e9fa9889214ab9ddc557b77ebf +db1af8e12514386deb67488742d5ab469dce55b1628da772b0132807b5cc988e +67597a9ec842d006526da716b298271ab67d0cea67a7325ee544074a88975cde +3a89d8f6d6185157f558e4b9c593fc59e66ba3d8a6a0776d7ea1efc84503de73 +d53fbe640d69145d0247b476b384ba273dbee531f6659394af9caa275ecb4c40 +6bdcd05a729f6b8f1b243408407ed8c786bb058cd47aa3516c461760810660ef +b8a7ea71dbdb4945d194dd0166f13dbd65172899dc29e919260dec370ec59a15 +e9e48693be94a087a9207c06bb0287d9208204ab90b07bdaf543bcdecd7fcdb6 +e3a8881bf657856e86789798ba437a871cfe88ae714c142d49b4946a38821266 +f3e44ccb9cb363cd29fae137d565fa2559581d881a91fe0fb88712033aad5ef0 +a0016553e93f38b43c4d59665b068396a2b307cd76ab784340caf445c268070d +5a751cda3372ca50e01c36a9ba2221cdd2ec3c4a85edfa4e18c62d815e81e3b3 +5128ce879e500ca2642c97e590d4c36168faa66c5b9b2f39ea6f06b3450eab3b +bf21c352a764c26e3812e952db866f599a744dabb01e294750ce42839ed84742 +627c2c7685d84043129fe5ad42b8211ff01aa8eabde3c85aa3f2e686580b0ad1 +9e626acb3133db17804614116533d901d62546d9842db199e77b125673442801 +cac9b916c2dc482d622326f4a5ce27b409dcf73027ca8883b2df0b28d964cc64 +0fb2afc8dfb71e32d1cef508e45d02bd529f988b6a88c420b6bb83cfb356926b +ec1d0e4edf951553de537a665f886722cf1cfb456f9e342c866c2ec03071f032 +82d3f1bbd6ecf5a053ad2fd27b9662859f0336ae24e963712d894b4463fa4aa9 +768da67b0ddd8306f1ae56824eb1cb72cfad40cf584709e259a9819a87fa07a9 +31466828a73391d0e643182c44eb369ae7557c956ee0a2841df211b576e35d97 +b1c197bef13c11e8749adca6ea0229986a45198b3f4b2ff5807293c05e3cd47f +56bb2451d56906afc827cb0996263662fdae686fad51c4f1ff179172dc500d30 +3722e84da8c81d413c4a1ad997923db032408036fd13bbca46ce49e7c92fef15 +0945986709fdd244f5d127b88c36b611785243462ed8e117f64a0a5ae0496fc3 +6d8eddd8c1fb9dfdc985160a81c81f0b417e4a210abe85ca6ca994f244a00802 +11c90c1da70d3c684b2006270138c126e57ecbf2ff848c3112a13ff605d8ef2f +ee0bd9e4646ed35838950a226e4be9996514bf54f0b4e8f2feb58d427aaa5968 +a6ae62d03178d9720c5fba70b3fabd91534f2ee94925683e1ddbfe0c25c149c3 +1ad398255c295c149d6b541a90794ea258639edeb989c0b857138264654fcaff +286760e6e15b25777ae8ebc6717b4aeeb7e43cf52edacd183df54f1de78e3a3c +cc6a5466a9f7c7793f5d9bcfcf2358e42091e1c0cec04a8a2d9846bf6c2b9e67 +58d640bec2d874a1bba89b82454fcb20418a818a4928903dffeaca5625eb50dc +2d3dc911f14cd5796990fc6addb7a2803c314ad259bae426058495db02650a92 +41be67309f3c7dad949f91cd3e2498dd73b6c223d95c56cf52dda131e38f81b4 +3e9c3ac38905270a6350376814c450857f3efe2e9fc7bb44d0f5a5613b92fd88 +59a15f9d03c7f8b759c59e0e0bc44a440c7f694e44500f7f276580906a04f024 +d1e196ca27563f8f81bea33a60b4a1cc6932b31a80680122396e79a37d4b871d +55369ceae2009fdfab316bd949be53b2bcd732e3795f3da40b5e33af6c228463 +813c7b231651360aacd6f7864c0cf493397c19fd9ff0b85a8816b2900e2f117e +3aec395efa60e0702c02009b26293f9fa0da2722daeb9426dcffd99fa3569c54 +e4caf2491908eba35fcd46e5f7767ccda28538930fc625f1c8275a98d9c3793c +2654007cb2b248bd9dae665b980a7cfa0b7d68caed0ddbb3e88893167e8e2597 +7ac119a103fac36b1a4f202e5a5655d7f0cde8da0a644822143d306a073b9932 +ac18897807c46114d9d1c04fb2d94e18728d8eaa110c389633c4fe674bdee989 +f59d873e8fad88eb3ac8864e2f4b380f765d44fdbcb7321b0f254ee25b94ecef +c4e82a19c36769a79d74ac98a854b8c7683cc2458a11a74d765e6c311d359819 +a4d41c7c396f7462995654a06afac91a0a94f21ba860b984ddf8bd6cfa7d21cf +0a2a31f50dd3c59f066f4ff6fe6921e776f6a12846ebf8d2454dacc244bd5a72 +28b5df4e443eb7580e79273d983031754cc037102b7190c83732dba868ae385a +8181f2919d0c7d20d45304c3afe097223814527558658c7c8a8cde57f407cb3a +d5e2eda76937e4a2075fa47d40c7a34d566b8c683351e2e430e388e888be4ac5 +c1f6797ba7cdc4e8e8ceee60c334835027266a9fb69e20fa3277e42b0d95f0e6 +11b1786fe9edb1c2367365001c87ca011f911a9c7eabe707df108fd5319a8569 +5fed9f8d01ecc92603fb9f0b3ab8a73ff516e87651093825cda89a3176952e9a +3318cdb311c80fb73a24d81531da94b6cdafe30a2884acc5f8d58a78b9f1fd94 +13d44e90e79cbc36b409e9f43ae493bc0e62207f20cdc697d7617f2cf29c557a +c35f19a4e8693f7b0c01bf1484a664b4a7f77701835b64333723c8533e33ebe0 +8747ed309542508c8987e03c25d20bdad49dc1d3c180b17d32c3590cdbdc0153 +0e7b4bb6a687dcbee1a72ee0a0e4124afbc97a1002eb405afd3ca4d83837fc1b +4f43f655db89945e2469a093bd4c19f95b729a17b164520a92b3f63c1e22222d +5de7f2f4c0a8deace404b5d6429e599a77dfbfa1ad6e839566e024669a6b2e1d +6b218f0c4dd20a09127bb5eb96f9dd110e0870c256245f54f3c58664e02f881c +923f46b13306f5f02818a303adc15d14067faeb7a5079c7abf788204385e4e96 +71a3f9180ed8df6d82ac974d15c6e17daf626459d05861a9c06751fc99c72708 +8e105711b34a7b2529c9703ae7d9799560bdd4dc0c9d60006baa0258689f2256 +9871ed1b5a3da989a4761908ad57c74f1fca0f0944ecec2e241d580bfadc1f5d +762720673ae525dc337f7b23d3a2381574a9fa661b37cbcc1fc460ee79991bd3 +830707b616cbb2455a642b97843118196d32c40d5ad0d4696c7c64676a8075cf +fc97320eee798d5187d0e0426cc932a6100c4b657d018ccd914d34a7a634acd1 +8795a2aaa4a5553f043bd2adb8b5c4825303d5eed03fe85235ef2691b0d42cb2 +52f96912e37c9495f225d5d4357422448f25353a5041e2e4bccd3a04c88ad819 +654feca8436d8fa4e8016e435f22853ee59c64b6b367b43e58663d9ca97133f1 +139f9d7bb473e9c3c12995a18f005d484c7c10445a9526829002add60353cb29 +b9a3efcac530804a54afcb99c4704b7380d9719e4998ba55240b23ab8b9e067f +18093406c73296d012fc0a246a8fe01d2aa28c47289b7b50e9d54708104af041 +1a9879627aa3b3333c4c0c84dd34a48a9788adc0b5076f522a4e9ad053b3ca4a +95d9ba7c8d264227c01a43d1b435a2c12435405659ddf4855f833bfb3c3cd49e +fd85437a999878d187957ab56f9fe63f1b866b3bfdc8e4babd1e6df865dd69af +1ceac8f7c9982c4ac3309709c71b14a7820a5dd29f57d82009295c7a94700c46 +d097cfa878e29c66fa4b283e778afe3ac61f569d3cd65444d15a10bde5dd0964 +0c5e3fa84efafb9de1774d309476f0b2bf763e6b1c9516fd3c1b263deca484dc +5d2af501f0ba8377388ef909793f49522b810f64c2d515c4d34df762941d43a8 +2c7494402c2fea35e70e620b340ef29b9556dcad04354f94ae7fbffb193a5aab +06d8f87199345de8e247ede51efa10d2ab3d04f8565fa6ab24c79220a96b7b9d +8ef6869370cbe8caac368067ff30ca83dda5258de66dc6033f15ddc19fc7c4c2 +e8319331cde20c73d5caaf493a36f21aa1bce3d64d774157d33a135290f73540 +d858d9cfd7a5efa470f4429c6e8e95bc8843ebbc1a953fe774fde2cf5c6facd6 +8427006b0e9d1fc6b429786e3070d16d3c66f9eead10d063a0dbf9f3b74670cc +b0d60dba7f0038e360300d9b049861f2b4756214a5d43bd001894ba2ab44a08e +3c02a9d3cdc1a6ee423c612627e49dc9edaefc07000a575f3576556058d52083 +6df0757c8b1b28631c7c02c460c52ac1a49a2160051fb773240d99c541880953 +5dbe4287b122bd1f933e43818f05d37ea6da106f2f2427b94a5c71e5b0cce465 +ad89610b5414012f8faba638d06897fd202b49e5ee02d387418655f730120236 +345418516fd64cc42ae9fbf2adf69e949438fb56db3ad04d92244bf7b355cf90 +0a67cd331c1695fd208e092860bb48c9ff393c8fb997f4f285a7f648df7435ee +020b2469b728ca778d9a21db5cdc2b8786c6ea4a24a586e2686af78238ad6663 +39c2763aadecddaa7d336a6205d84c23ca3df72a30c4dc8eb30ffa0339360b2a +a38b33b16a0d25c87ef758d0a94b7d2d79df47c816bfe9c9c0d9bdbfe85a1541 +d5893d23de6560d4f037f2cbee49b8429b13e945ff2eb342ac4b9f7385e4f334 +c6555378fc5a0ad507a9d12765a1c77fc6bdc1f448454eb6340e426a7b920958 +d2a6665a2faf4d25b3252f8fd07f6d16ed718eae274977b7a33b2e365c94bfcf +ee15fce33ba6f96b0018bafa91336a8542156cff2effc1f396a786e229843bb9 +94650d68772cb48d17719076472b2f2e792be644c6dfe85d5dd225caae354b65 +4cd19bca06bcaa85d8cf4d1462019130810848f588452c9278d4c29659b65fd6 +b0bc77e182378647ec266ac507d29e7767104171096187bd6e96058c1630adc8 +0fdb184f24219574b236ae25a967667299dbd18e805f41d852d44b44a65b6151 +f8f8036ad29c08eaea109ea79905f1bf2e30aa9f76a2fadb9bf5cf0b4a34d03c +090950910f561089a1721cd4617f25d1e0885d9f0562385318dcaf58814265a0 +71197d8e4d111a1ca154d336758f8c7b47e521c2008785819f8ab92b67626afe +b411380ae356045122c71f1ec45ec64150b26df3527e4329e4817ac0dbebfb57 +090ab88ee917678a7a1d2338ded696259f65770fa382a95e5ff330a2c1e9c808 +94ecd3ca9f21fefb5566ff368feda55e8a2f8ee439ed00ca2efa25673be2131e +0fbfebb5d3ac6d09d1de828f548b0ef0ecdfdefa4bd5e0f3931a3ed58e36f7b8 +4dbef2005626ccb366ccb629a71254b80b8203e9ce79e172ae28678fe0b59929 +3c582f91f23cd5f0842c14e3e028e1da28fdb3772288929cb026f3dcd4cc055d +61eafeab2468e8ac4c7d163a6c59bfd5b66148be7f850e8ede4dc5db0ab00366 +8fddc8afd358a72c93719ab10a0be48fae714242efbf62eed1ad791df3d6eed1 +b158412a71d37ad577aea0714a8c98b45ae1336d2570c9f95f6009d2c6747fc8 +5b53d20b45172afaa509428906c5dd9b429459e6b550357a29f8dc23ab1f9823 +a5bbf397d615cd6bae9ec7e6c6384a8a0328ec2a43ae0f5653bcec315ba31fb8 +46b3727fad9a8ae7912fd7d8a1decb673802e44409a05e068d8b909f1fcbb39d +e1e853c4af2353971e469f6e7875594d135f830de1aed128cfbba3dfe8d502f1 +453dde0c8a34d27b0cbd1ecdf409e0e41824b86393c4db1d6dc7326a3cdbd520 +e6229470a49c2dab8b6bb706893a604b9e89d12ed504d5db0ba31d1ecf65ece1 +64fad4f9184f874dfc4d34c6feea11c56c7887c7826d471297a89c1fab529cdd +012b07723a9d33cc249bf69911ce4d3ea2790b3b6e8b0facfc03e7dd44c77b8f +2bdef94259cc87990bca400264667aaf1718f3c0a7cd6820fcec400e701505c9 +d4eccf33d9ccacfa45e4c3b9c1575ae74af727b179e8799077c081bb77651a76 +e87240fa76c4c769b81cc2be7a9c8ae3bee0d8fce587816ed67116b93a000005 +9df664d74a77b80d2bd56dac83339c24905c170379629b19c5c585599d421726 +e6f1d826329f242b600e8bb5dbbc35eed1b3e06c45d9a70dafd0c0c26d0112e0 +7c7539c9794e76b7a73efce6dc78a83bd53295ba37bc08abd5164c84a79d30c1 +67056f456e73b22b72d593a698ac62e0475abf6ca41488ba1738761926bae05b +d658963fb5261161c3d2694d86eca6b761eb21b2fd005687133efb186516f9a0 +509e196e88b6050654d67e0efb0f57a16cfa05c4ab9931fd1036612c00bee740 +05e70af6d26884987ceecd8c910ccc87466c8d53727144480b2f9714e07ec445 +783603f36ce2f49c52da4c2ca625111152845c168a9bf48cbe1fdf96005c48f7 +6d4d11081dc00b13a214b14c9e71ad457b823d3cf412924b811a26011d8bc9bf +317647d0203602fddd14eed20a9242e523bdde7509bd970c0f15a37850d21978 +6a8c60e8c4efac34a7e44ef849986944e8957e65d7618b7ad129172a4c7f7f54 +91d48ebaea1293a687c7a06c73bfb0a1dc28fee3fc3dbb84dbd205c4b725b6ab +058336e33a3f9d6c6fc1a86b69aa32c8b7b9296d3a9e10d1624ceee2c99b3a18 +3070da6c905b3f3d6a2174fb259b83b05688e6c107d0d560f892eda5b381bbfa +6ea0e2a9f4de9def9cd5e00643ee6ca71837757f98cbde7e2e25bd5abf6edfa2 +0620e56d949253359bd53499403339f827e58b3d782c4aadcf094dd2d1bec66f +22bc41eb8d8d1841e070b21c122063a21d898745eaf5c66bb024a8fa9442ec84 +92f69baeff37921a019ac06ae4cf01fc0bfbe6e2278e4ca0caede4da85cc998b +a7711ac83f957b828d935ee92b335053f10732570aefd980a4de62a2c23b28a1 +3c1cbd2acc27adf227c53c2d56c36b1b7f223eadeb2c306b015348cebe257605 +6f43953c33d89bad9225027db68564d11a9025d624372db2515740a98b72bbda +0e9c8e49c6b7b835d95d4c56af1d187d461ffdcf9c2a3b944c3b8b4d672643bf +5ffdcef2369ae5833ddfa3dbd6f0f3f690aab8899b2419da12be7c67d31555e6 +13dfd2c725ef044467dcee9fc98842f1b859c41b2d6fa0f97bbfe53863e03ac8 +1df91077ff15d34d6861042f358851d02471d03ec42b720d630d4981e2675f7c +a88c125004e7e5a87e9a86c5d6f357f27b8fd980bd2675c9ce637c1577f91efd +ce8e881cfebb8647d10d58d551ede30e76fa9e6afaf654d63820ecc309ed6e28 +a3feb32f1e66a7577ddfab7a5529817a37210c7c02797eeaa23e5aec6b16c7fe +5e825ab864c57eb8e4e276cce2e2bc9e119c9ca7e4bfcd4bb3b2b8fc7433784f +ec7e82826a5064f2b66a9ad5b13675fb2659a01582cb57394213d84860b27ba2 +b70d1757bb5ed787c87dab8a7283df9131783b8d87500a323e3e7af4fd002bc6 +2a02e94942fe995e4e833de1c89cc5e932b25b1279c03b0e0192d0197fcf166d +dfb13a39964bf4970aab9b85f265de9219dc5874153afb7f94ba455c01c13ff3 +9d88524c795b0ac19c20215de403e801e6395c1bb30f5ff20c64657a12956bee +90ad20c2840d264efd509d8a68fc4f28445b6e46821d6ea1fb966446fadd5ba2 +2cbab0237e98dea777ce00eec4e54b81a3283f78dba81cb25dae73397f130a8a +cebf7da472b6b09d4ef5619332f1ce7a2d84a1cc47d8067328901cdf016b022f +0cb22e399b0ce226fdf57d718b90eeed737398025853d6ff0e0748eed9498373 +beed705c268daa6c4bb9b3acb56bc5cfaf65011f1a6f8837e2d6cdb9be4be3cf +42ad0bac1ec6b99169c581975aefa58f9af4b92218e3b78af8dd76e4d57a3bff +2f14521d225de66a19de11d9d2d8c5455c50e44a69851b16c0ebf2f7a1fa11fd +11482e491ebc1cb0902f6e813d2c9fb1e581cf05743b300bfd67e778bece08df +7f9ebc7f7e65f43b9a813ffa7545642c9244723cad85c984eb4a5c5b2d5fa959 +eb0bd17f9f1fba38637255b9d96d1d1d4e6a747dc86ff18d4acb968d4beec634 +4445d0abd79df1a60d0660732b72aa6311e0312ac6d74e4396fad711d49d1a4a +a1fc22b21b17160782d466078502a3afc342108ae179fd861f8d58b030db47bb +632215db75250404aa398c7ed673f67a1935769951744434986b63b242a1744f +13b6fb2cf7d5c105bad1cbe8549eefe24e90bafbefcc970166d63a968df59cc5 +4a51fe11eb9246776f7cdf47ae633e54d16a079460dbcf33ba34842d6880e818 +98e879d5926d7acbe07fb95fd908c059b86c80db5695c5726fda97121fbf564c +def11b27bd8165297abde326b0fa1a90eebd3aa6a26b4ffbcb3f30336341c44f +7955a352f868f0c3482010f1c9da06136e55cbf197073036f8a8f8a872517973 +b20bcfb0a199cdbd8be2eca47890f9be5f5c65b1ee1501d30f459e3d91b2eb6d +ea02e49a2359e4945eca988b59a8f22f930b3d33c45124a7f12af6e9d442c9bd +88d5526102f11548e15d9ec6e3983f82aefbb8e773c1370bacd267d264e351a3 +a438703404d5379d52567754891b2d9195fe8173d8ee5e85255886833f219a3c +d7fc0d2a8eabbf6181d6ee5915fe917488ccf11071b8836aba341bcfb88b6d7d +1e8d0a6b12174cbd386c7a999a52deb991610af9038fd3a75871687235438dd3 +38fe28ad3b8ce61b5c1f13c833f0da3fcc1adb67f52559d908e8f844447f1643 +2cab6d5430e01fcd6e9107a9a91f91f4e7f08727fea8c9a245e518e49934cec6 +713af64914ecc2b1a70deb2dc301588a6df7e0ccbb4b1300c7951f8da3b71848 +1dafb56b8f91c178dfa5533f8498be75ddac5e2c79be59097e480ea22349b7e8 +5eaa8cdd4031f635beff0445bd763d959fc4a40e17658f045756f7fee6d19f5b +657fd1efbddbc113ab4d6f36c084d59979ddd0d704015dfc7b82a91c7f2181ac +c1da2f4465fd6f15642bb1a452888c1761199d626fb16d00d46425c833a56100 +f12db6d7c398e15ad7f68a3c5d5562aef94e052aa8bedb9a5d848e66dba45b8f +1fde4d82bfea165b1531f8646b106ede22f1915bd5b3030d2f4682d9095672fc +3e8a0ad3a5048a604cdd04dbad389564d77ffd21e611ca5f659848207aedf2e3 +921014f0b0e3900e0c6ed58972a40b8ffe1c4ae44e9812631645ffeb4d68a73e +ef6b8662e57538a67f52bff2c959d7a197c590367e281ee8af821a6023aa2aca +32183814ff2a3cebb028b3b4637219073fed1f98b02a72a2a58b32d29b6085b1 +eaf012300757173a2b92a8531b01ddbf21c1a86ddb8f1afa2dc1d67fa3143e3c +96888d07a61275ba0dd7242a7ec615bbbedde669160858cbbfc0a8f48dba2ba1 +311196a2826e14ab1b036ccea5b6f7b486c1d108a2926912c9fa2c8e7a6dccb8 +4aef2cf7db8c7fbfa1ec7a0c9ca9ed96d0114ff75bc56ae57f3248ea26d89860 +83e7b86b312b755c7fef8ec3076af4555ce7b0badd0a5a97a029d15a6e587166 +55de4ee449f9ebb35fa5fe4278aa2ce6111902b431e93d3bfaadd97b137249b7 +25ce63755d4aeec31febb9886db8231de854cab0849805d86cdcb6e5eefb167c +a75057cc4c3bff9cabe6d68fdfb1af5e130fd130391cd33efb740c4f10208c41 +edca0c91fcdae364e2394218df94610e2716f9caa2ef6cc6fd61b8ab8672deef +a436f912c5e40a5192ff11d39a2e8c1e276d1d7911fa6a600f522a834ae75f3b +f5c6afca3e8f2c8da9668b7e50b4ee0aed71c46789a69a3da60641f94aa01e22 +e3ece20fa36729a27a06f182dd18b9385aa8b704a28aaa23ccc2e6dba7111715 +b34aca7327193b834ed673989fb2981ac06dc60896cf2cc9b88ccb76026df374 +b0313d9c7f2cceea586f971d9ee9e2bbe998d604a871fdc739d23ce1c721ee08 +7156b9728975546eefce42b6e965395333c8b7402b4a512a223c5aba537eacaf +44ff01375ee3bddd0c7ca7b932c95df51042a6aef8e8a9247ae1cda3c297eac3 +fbb7f287f79eb86423348262c220f16a419f145cccb47347b526af1bf10380a1 +8d43c3764c00c6ea41bba8356c1cc95fc841c4aabcd4a1bc2d7be6cc373b75d8 +cc222bdefa67365166629d3314cc3bf7328799109b1e38ecca9d6b0e2e2ceeb3 +84c16ff9c4518d23d70244d7fed72a238895d63fe5eef0cb31bc849ad85a4b52 +6ba7be6e01e698010fe17f126d880276306c161079dd60281868bc2d28027a77 +9a338b1425795d4b64de3ca45b9e4d5203fc291d93c6ea1853c1c81bfec094c4 +4c35b41e18054d62386f10f3129df37aed81adeac5b428e094dff649641d48c9 +a080c4f509de8e4ffabec39e4805d90194b081ed196cf1a658d07afaaa11d100 +648000edc887024f9893f1074991c70bb56b779d7c9b78a12c61723e2b60be90 +7b0d8b78e345632e05e7bc44e8c09912a3d9ce1018fdb515c5c7efb44f7fa275 +2d3ec8b2b2b1e73277cab998e47b90f946fccb5bf7247ab0768d7e2e02ee03ea +c571f69b0b4fecf5a3859ee411c24bdc8ee00798e4df0ee3c2e5ae1ae8990acc +da53f2242b8679f8ebd85a081af700fb86d753fd68254bc7ba4c87cc389f53cb +deb0c97701f50e9659beea392bcf0cc0307a0b6608bebe586e928f07b0e64dc4 +ce4cf59adda693b5b4a7e873f3e5b36099e49ac5377f80386af862e39cf812b1 +bc52dde26058fa0faa714052e0ecacfbed090cc1286572f7dda507037fb33b62 +4d1bb37df4441801309f23cfc9e7be782bfedd7aedcd7afd51b685c4690dff48 +262879d3b516b97cfe2eceac8748893a693d895f4fc33408a42c46aee8b99dc9 +d41fd0f611416266296df33d76353e12d70234f932a1c71bdc096f528ba894e9 +886cf504332fe7b699c7a7fff2b9c41771149cd63843eb31b8e48bf79e0de23d +da8f9acd38916d7bf53a995881d63f785004267dc749c667e26a2d87f1c53198 +b36bb5cf72329e9a8e69f786d1d3f471065dff5f90b36f5ff615a27603acef4c +66c550fbfaef0aa02bf6fb2d327f01734c21cd13877156ee0c644beee632cfa5 +63effb6fcaa00e814b6ac29ef8656e18079fea3ebf8b5586a0d57b3fea8541fe +48eab443fe8ab71a003ac142b27fd6c9930fc77a2e934b4dad0b03b2f0e12a5f +4cf9c1b076380d49e044a679af6aebbffe38fa7f6ec6f526775e8a35cc793ca3 +16f595cb4e7471ba60926781251ff3e9f9a05ab329f9266bd8d0f220d742df6d +d35251a38455fd98cfad6dbfd3f93c8ad8f62b884b7690afbe73269a79b8b4db +5be6f1cc2bccfc1454782dd0f695f31ec0af05f8797bea1a3f39dc5d2284f694 +a829048a0f7ef58588c1db9d589eff648424546560ad4d628e419536b3843b6d +9e5d050ff984ae26d025989cd911a89e0282baafdbf20e0c98ce300263432b92 +716c4b4eeff442b8fedb8e46303a589764db094736715a876021bc5efc7d094e +0ffee62f1cc23f32e12a0ca83c229970b83f95c21b57e07e465d5b04fb8dfa62 +bd93cb24bbd7975d4fce0a1f2634e31bfa1abfa4a6a1326f024ddf30364352de +21f5cf2422739651d5adcceab8d4eebdccb08b5fcc064b3afb9a2989d1b9608d +2932f8e23054e1af8e626a41cfee6057d0b24450ea7a264b48cc1f33193ce4a6 +60c687d950bb1fb5cf6a965e5612b0f43d703714ad2e34c0626a048fad890ce0 +8d679f0d581966926a26233a0e22c2f78526cbe5fb4de7f2eccadb7efc9b8d56 +af23b397aa13142b53b756809583ca027ecf8f5b82ba604d8c9422f7106cf87f +4c734adc08eadb525e16044aa110b3f9a0363598495ca6a3f3ea36842b103d1f +4c72ed554b2ae58805c95f80db1dfb7f43c4f17e0ce989a07695024777a50343 +03d59f8d64cbde99c9d2e227bec4462bc3a7b5feb1d33a7ad09c069667da2d3f +6d86b1e93f1b72c63e4ac78add54810303cb062b871c4db49c4e782cbed25fc4 +2478256d612531d0e07affb40105fe6fbc362044423d08dca5aed166eb52019d +67c366d10ec6acf0acf08112421ecb2471e87bfcd4a0da360caead36c2b76d92 +868b5028964cb9ecfa7b24fe699e033af88f1d89eebecc822aa0845a7339a1d4 +623005b72ccf8c746b04b57a26025eac9425ec04a76c1452c325c000373ecac8 +1b1710919be6dddb912beba06dbf21e6fe5c46a35299635dcca05029d2668e8e +e86a801898c5b00821b0482ca3a055675b7a746fb9b4c718b4c8fe09d4a15922 +39828a698631c534b5f85533b629827cc4f4454fc6a4725febba4523b6fc380e +53e37a9c90c1c1479e3a56985126259c96d41ed07b98c5ef2fe7c180c27b66b5 +804a286133d3be0a3ef7114a18ff068efeffa319dd79fce340d1986f8188ba43 +88217d6a51e459aa763f0a600c16c6ba8ea0107b412c081ba77df47603163962 +e1f6ac376e7a30f83e74c8232a58d53d00c8666b2e4b5fb49a44a1431af7bf29 +39bbd572543ed07b9a201c81d8cf197054cf7e06610e5ffad5d14c814112e954 +962828fb7e82e1cf70872dd94c4198c0a8a4a103d92dd3afff89dc71f9d37ace +686382267e976a4820283bf82477123b8826ca69fd87594430a0dc0802e22e25 +25a58fbf5db80a693956a93220377ccd322657dcc4d0aa15b2b56a797a865ea9 +0701e8db50d2b19496967b52fc8c6e944bf7d935183801a913abc6c967028c4f +e7babb4d25a1d66b02f82ebc3e764c7cb46d33192ced7e9c3909a847ac7b3e96 +66ca0069a76a818e92127d86290ddc2cf78f97eba20aab2c800b5a4536f1cbb9 +5e500a91d5ce654aac5a1b7ea1be11e41dbfebb28215a59679b852254f8bbb75 +4dce54c58e327bef1c6a9fa0c1f45d285e6c4172a608748942840d5f74671311 +3567c57fb7ea67258c742ecc6039fc900b60d7dc73c1f6cdb8459528b4b257be +9115d782d7f866d25c740a7b4dffd48d2ec59015dbdaf03d053fca37aa9b3c4b +2df4dc405714654017d1ce0647c3669e6d79790ee3ce762d6480d63b330419ca +8b6c303582e29168a7f775a2416d33f25c514461da4d8fa27b032de70ae7b8dc +2e5866c67f8c6500d5a31fb561a7e0965bcf461257c966cd02ca3fb274c6b0fa +00abfabe6b9b1c04db9aba05ddb3395d0af9ca4687a8b1265ad822c500241a21 +841fb7816e9e9c1682e4d4afca38943c1c758ec68964c7d5c90f0ea48ec12260 +550b633e10ef8d25e9816ead14491ced1cd5c61daf85989bb54f53f991a4d239 +0566fdc2bc3a7811feb98b86901f749bfe22e8a160e222a2584c205186140f31 +e4087a9214182333a6b24f5107e0d2703808ea8e219836628381939679a8ad87 +33ffeda1aa730135c2143e3527a72010187465a5e6ebfb46b04e2f2d079a2950 +6efb81ad3f645629272c3f05730ee82da38e146d60bc9d59b5e97923ed2819bc +0d4dce843cebe6eb0adc240836ea7fc366e0ea4ffe11e0fa03c80681be0570f1 +ab7bb5cdc8308b6e14f2b19a4f8662efccb22b6e912a1d50a0469f5261a4be9a +d73e024f8516add8ada4f601a67ed18e896082bbef5d1d45a5d33892d8ca944d +08d63a3ca29baa418397b7017841e500fbe95d70f7f832937089a21bb4b1a3de +25775a21890dc657a63f1c26162dda0c9bd4266c5be91dd3028be4b394ff4679 +462c17d71da9a03f8bbaac19b7ffa5e132052c88d61a56e6827a86da4aa42580 +7bea1dfefc2e1dab7a1ec8fda443baf7d3eac67468669dc332c3f1462a572e94 +ca4ad16ca9e094374ecb0fd8c34fcd0be914a5310e6d2218706e67e832d68d11 +965833d779c8a08e5296cc8da171b999f549cba36af831a9dcd02ffc1e35d03c +8eafdba2d40ab02e2f2b8ee90bce734618758ed6353c7528e3da88f4ddb2fc51 +b6f60b11b95c3e05b46189ab369f453778f31251157dc509cb37ffadf582d1f8 +7e885ad2f62e591d9a4b91e088d2677c89680e29b54b8e98c0426fdaf26444b0 +7a8a4c4169e74c60cc6d6d026048bb155573d4e6be7e58d7e7542fac41347eb8 +f2dcf5d626b90194839d4a5dc5a6a60d0e66f8557bbaa1dc4802a400e0694be2 +e27ce3c3370f5bbda3ba441572ed105d229abe73b1c9beee68412b3923f22069 +5515000c14a111c5b1e714e7553ec871208b090a11aa3b8ab89b8983a8b4a431 +20078bce6b53b461f8228974cbd8cdec13127522a8e6cdfebb9af6919437b089 +34e5475e10fdac5b57e62c79e4ecc2fdefcd9444baa85880f0e240c118b9a92f +c66c1c1a1daf6ada80ba6e8683fc3bf621aa20042baa28661225eaed299d2232 +10794ee0c4d95f70f3525777c1de7b145b4dbc3ec3703b9ff51ca925a2bda4a0 +0e3e97a75fae2004f8403a24a56ed0b0c39203f55032d97b74346bae719b002c +a9bbd4d1e9cd6a0581fee7421d791b82b3df6584d04e19d0605fc3acf755583d +eb97984498edac736b5e1003b872eb4093eedf43dd1441eb690e6b2a583488c8 +9595e1b2eaad33e34b70d72f50f43801cbee18441460b1666278a69585b7075d +ac0a65d596bb6c6f5456e1a21a983863dc9c0e3e4783f32efec3446663d1e389 +7b2c80e339a362d99bf24b939844c5b9056773ca62944f2544d483cfbed0be63 +2a7e0a9b272e3e02eca6601ae90d2d995b6168e267816c7ffc5181e2b1ba6343 +74562575aa670ed4c7979be1b15bb48cdfc2f71c3a09a6c9a5898e2ac482d960 +79b355f01c253ea5abfee887cd59b908fa03530a48f1df35d5b16bb51a86db4d +2863ef6338b22e5d87dacf0674c6605bb58ee1457a1966e6ca6e3dcea08744a9 +04cb322603f0a84baa728c411b3bbb12e72a05e61592a7b0537ce93b00ff78b5 +d4279794a2b5fe7bd377b5f380b6ebbf88ab1ba2e77d00cc8cb47846487b2813 +67c3f879f59ebed9a22a330c79090183955414da0bab01b16f7e2b746374c21d +acb1f0139a9a3f41180c9ac7e563ae89444b65c0364f3868cd4c3a79422031f0 +65c5714bb0503ba02b161f3230b4de46fab7329a68025ae2f8c5d4d1ad6f0c21 +e2ce4e6ced25d0b5bc09b6c533ab1d50086d33f41ea5069b1601d9474f3f7adf +d515b902c880c541607e7d10f197a9d256610dfa70a515829d1dba895d40fec2 +19d9b785216e57a0753b92a5a0efde82266a222f55d2e7879a0abc9bd5c86918 +8631dd44a986aee508e8d5ed4c57aed65f440b1fd660854e98c2615a20e81e1a +8022b01eb50c13d8e63380624bfc7f8282922a6d0942f68b545be9c4993338d6 +6f469da6fbb23954163a4aea72c07f14cb2d16074c1657954e30b6526a26f40f +d285920aa5ebb03e9fa893a04b16922def3c21b78ef86e6e9cbaf35dd5918a48 +85b9061c8dc3441a01eb4774d4ecf5eeb941eba4f33417d093a9d36e80580be4 +f0e520f16e4a699c1ea542a46b645cd0a85953852935a0c84da2fa7b0fa53e3b +a3dfdb1f265695452d7b8ce4897da5cbd3385a0e5c9c8c261550a5d8de8ed3a7 +29bd8125af7adbdd498f6b5451c1379323ca769092bbcfb7ec1e036b90291c8f +15711728c8a6ea6a887c5caacca3580d9b4f76530da46852720c667586dcf40c +f4a75954209bc089eff7318c3473aea9ba766ab20bd4f8789ba6c3941d96ab84 +583a2ba36a893eb4e3a5d99a4e359d29dce1e32dd792b8f1a35677071b4b970b +4a3160070a7f98beb5c86339f6c4a9ba0b1fb2609b1c39f5ca19459da549b693 +a37ef6f7bc5e47e73acb8af340d6c0048fb581d1331b576d600295bbb139645b +837d74b10643c30545c199ddae0f58745f248ef6106f3c0bfc31701e52ec86c7 +09d35567106d6fd208c60b33671ce61d23d23fc53e1ad6f4d1749502c26c00a4 +ce079927e8b0cb92b3f7911dabddc95647bfa95c3568db00d89941ff83312050 +f0ef237b5ef3be5a0b6d8a922e84af2f2d559a706b50f40fbfb8afaddc834ce2 +229b194dbcf71eddd1d1c0f79c3b4560f025b75772129aa568be5a948b982a32 +d270a4c12e6afe7232a97395b7e4c638f2f01661792f839610c54c8d071a6700 +9a146d098f5ec75bb09c228256624d57dff5a8ede821dcef65243e57ccb71af0 +f8aea0f5451fe1945d9c22248d0e0f4fb27cbdbfc5b0e5926f66b4880085282e +5e52e12b083389c7adcc2e08cd4c40966604ce2582b51bbe557ce772d7f94f39 +29ed7140b760fb2dc1a2c5c2fab51b79a7391fc13490ecb78f4256b1293021bd +d06a5e14b44b4fb9c3775643d64fdf660133ef1da637c237e3557a55b12c8364 +6302eded01d3b0f65267af07e455476e3c1d68eff9b37307ce9e83cba6a4beeb +84950dce3f303574477188bea813ca6744d63c73c922a3afb5d34b58a81a817d +1040d1767738803000b207761bc9ab78257112594ff5ea54f97d72f89f242d39 +8ca6e35bb55b78ea6b9c8da0c53be94e71a4e9d65753212bef1a24424a41ac2a +f3d5f6f775f2593e4851e5ff3327f96010059bc620cd360f5a42f2d3cf41f614 +8b08c20065ea07474871d3aa9033c32ae55bfbe2262d93c83175833ad5d4f370 +e1b6c5cb6df7ed836b7e86badd1e62fd477de4a33c33fb54d7fb9c5b6dac57a6 +34118d5041d5f3e61d5d5f73d410c41ed953f941752f6548988136f1c469253a +0845ff0d4dc3392f2c6c4059736b74f3fe97eb71ea23ce6469d6f48af5440bba +d671be362b52c36c4f733d8547e7123012d3aa297ea203eb7e01f48451b803bd +723f3f34798bed11b510680c1ac6a76c4d390982cd4de72759b9a2ba3c6d1ef4 +15eb7a811306859f0fd0095b557a76bef28b813649b9ddb3a75967acbdb591ff +73b7731d67ffe7fc0e61b673127eb58fbf208427aff785758f225f7c7dbf0ac9 +80ee732a4559935e255d72cf4baf7bcf6fde9b64df061d300352e0029fae43ad +088fdf01aa71714a275052a1cf3d575506d84b1e66ce997e62674990cf354a77 +b0a9132c31daebd4efc2b06793b18925a3cdf832c5a92813287b69e99f86f621 +4a6fde3062b071633410cc8e305c0730aced2f037975856cd9e6dd5784381bb0 +9e4c430c39f39300315513245ab294bc87f894b1a1337fac73ee4e1102fae0db +c0137bad05d37c7ae77d714228ffd206d1a0a6c62ba88685c9cbd69571f143e4 +d7555ab7330fa2ad377eff3fc7e30182102fcbe634a04bd6df11d054877e75d4 +79222808103eab1fb07ba343f71c4364b7bab746f15516c8d8490d765eaa7477 +1407bf5ec9cff775d9f5bf839bd32cb44961b26b7bebe12489b8caf92fc83d1b +448b3d4b652994583f62c036cfa4e014cb9268e70defb2d291ef6a163940d5d3 +13b74d3aef6840e3428f6acb1e8e55e63ab174f92cd7c347a2a619b25ffeac83 +b6c5faa45ab8e4db89a0fb326ba54d6bdd3c27b374fafb88acf50a9b4ee63e47 +43dd1a88e58dd9ace25a1d38422ef8b2c4ddbf4f81a1c0b34586cc6ec51080c4 +a06218f5dc8ef6d28d7b3da805ba4dbc5897a8ac4212cdfea2ab5844da4adbca +6e2966140c764e191e1e7b5d9f05517e3d9bab70c3b6a033e88beb200254bff5 +13a4feef5f5181c30fbbe4aa32118e16017b59a7dfef7370afe675cb1a58fc19 +5b1c6f6f0ce5090cc325cf88077dca3c5b29c7925d23c7832ed9ed2e26f35a8a +dfe2211194ba66ee3b51916534518cf073e258fcd4c5201a8c7b08219b6db448 +e4a70a815deaa3d5f0b2a85d3fbd777a79b4ae881c21dc60d4e345af911ec541 +1d2fecd73e9038f5397db3df6b41d234adadac2a9c6f82754a59be3200e51bbb +bd1f8af3fecc54dae0137b28bfd86f511ec3556d3f509bdc97106f986f3f3921 +db670602548a11058a4c831a2dcbda5313772f4472a23d85ac23c00788c122de +0eb9a917da22106cb2133e8c86d70eec2468375d825c0a08e681cac20ed6970f +94a67898cfb97e79f294f1442516cd624f3731edad4d956d13c4b4a9a9a4434e +66604a82a73891f73f033d23e0e8038d481986df5d2be8f6c3ef12395bceaf29 +f6f94b7a2000a308f0044f64f8e73fbf3cc9de1b80c79792e397a9eb562fc3e2 +623cd06ff173f6b892586edcf6a9c61dadff8a94162baaae9b7d4414075962ab +f58fc1079198b6c09c74e9a9cf8f4fc9fddba8278fb04332781e188d24054ef9 +f57f19b904f7734c6aaabf677a183bcdf87c2c5147681080b88868fcf1ea5c78 +a56a0e2d5a5e60de54a993838789367a83cd83d32cad76c6c7cf1cba78299b71 +648a995deed5cd4d279ba3deb36ada92ec07c244f0a10b82c8383946d1dd35a4 +b4ee4b943dd5a95a80d6699ee4fa56f1b3c569e7037a3200d0e28f4775f9d0f3 +529d181788098111da3bb2aa70e0852fa204edec66a725b7ce99f92fe47871fc +3caf7f8660e639016ed082496ceb90423c42eb5c3787bc6782943824a7993757 +e4d44fa8a51699eb13f329a16106c316cefc686ea17063905202d9197d5f1c74 +bc10bab4c389d542ec322af7fca6858b877a6fd3ec292eb1c054366e751dfd46 +69f8cccdc66c99bde52e94c084813c6381a8a75b31f7d9706617e1f0e8039ea9 +3e1a7210501b4a240ac1535cc93ed8c17a93c8ad644feac59453f8ef2ea7a9a1 +af2e9b924e1c57c17cf3c3b3e0a8760e25567dcaf496962bac8d14375366a3f1 +56a8e1b8400ba34c8b8e7cf9b889fe5ce5d19b51fb9b0727f95ed06f8208e843 +22496a6dce041391fa3711c5a30fb429a374c158cb66b97c463cf8d7e96e72a8 +2305773245360025945274d6d1a4a0b0d18dc0325fb460e93bd7f1545f605358 +92efeaba80dc613cb14311a431f3eb61786645b37138c778988d31f8d87f4e30 +fe1b5248f3e67ae5c6668162ac7f3b497200849489129097730a0842f3b91f3f +f33e4cfc2c5ee93e29f737a060431ecb050c8700faf72a0006cb6de0f9480339 +db722c96aab3a7673aef5d9ffb15521900a1c11291d6d8ae5ced56bf31f88bd1 +0d98131dcc69d0f878f0589bf4db7a9d6ec07dd43252a8ebfbef27c95aede562 +bf536c32b976145bce5355fba377e9299565b04e52e794f54320fec6e5ce60ae +35f2fab9a61b84b2e30aba2e2c1107fc117bd8c8163981cf493b72f6cd1209f5 +931a506d536dd9710d8176857d840f5af830176bb67291c9525ddd8877a47353 +a85481749a0fd194961e69c72bceeeb7185351a07af683adae55e6ae01f5c76a +18f5796063bb3fb5ccf2a44e3121ddfb3d4fb8bf6970c2ecc93bf24ce546ec6f +0b24f1ce3a6392928554ff2a95441bb16a8596d2d7bf7a01354a45fc23ff572c +ccd43d012b0fa8eba0056bb6915fc8d249f740ac9d3654bb29abc83f2d9710c4 +b84bfe46950585053933ef55fb6839286bd1f5ae221be05c179d7951c308f80d +c7b7fad732f6510e47710c3f241d9f5780a01da59c240640a22a3588c3a9aae9 +0f5f77471fe2f5b8a49a604c0d369ae53253b1d1ca664332e4d07c09a36aba28 +e86e6c70fbb622528961fdb085a905f0bff4e9b82398684a9acd27f5d94d2e2f +026ab33c48ff168e7e23d531a9644dbf0c359398c0b35dd7e919495de1f6bae1 +4c3784dec041eaf8279f0bed38fd62ba691f9d8e95e9e3156425b6a5b1c402fa +ca9d72c720b1fc7a8b18d5756d01bead795843458e0d9faeec09a231e3756f3e +00eac719eb5a750f2095d1fa9406be862f403dc9f30491a6ff28fdce9ff7524a +9e76aaa3ce7cdd2967f6e7af3fa39c156cb658638b2be85b8ebf55ca4be36c82 +670c06289a6535f9eefa7d411a2771f32793c68d52f9f6098448d70fa4c12054 +859274678c4bb3d97e71d10ea90341f9fce4fffbbce6db3d45b030c352559562 +ec1be6b1e05b10ebc0e5c8d3e89dace7cca8005d9b0a7116cec46d86c388c28f +49c64a9d471b6f060b442c16104549e1e5dead208c97749a343b5bf21034412c +9b01d144d4ec744ba3f9c525e0b240f9e52e7a41809e4d33098ce8b326fd7b4b +b86fc67b16ddad6c7b088226f5034ee8dd1a6827a8c66b50054a41c4b6efade5 +a1ed967f1990b9cd5889682aa94b419806dd82a04818a4313a0716d83738629a +854beb75472a583c4ebc18b798d4bfd69ce8ec8092a23b719b45dee0e1789f9b +bd250d0a797bc6e1940d1d1616e6d8268d008c39f85295ea6a97f122c5f28243 +db55bc591c0e060eb322a065302db1aa9d85d9949163364cf6d28f2f274a9826 +ec7ab129199d643dc57ea3ef49353c8a9155eb217450be935dc1b256a80659c6 +268b7a23331011ce35b431df850f2c468bb51188cec737290bb23ac4fa9715ce +64f69b6119dc0f371a85b27aa010fcbde3e598f0a08596e475ff6645f2878c93 +0ad15e2afa16fd23031ccfbdfe01f77695b47a3432465f5164be8f30dd35a2ce +b26858a2b0b026e43a63975a33d2af0298aa78dc493d1b58d87151c2e138a3c6 +54ec5a57fb06f6eae0c2bb992040a33b8f92b83c7f0618b6053529b17f324d2d +baabafc074161a3e1629f271429d683451a8e2a07230e030ed72b95bde2b6d4a +5d0af0f265fdde648381c7f665828deeaf31ca545dafed3deb55277b27a4349c +46edb83634849cb2fa5dc096b22af7c03e6537070760801f2d671be9eddf692b +88476f5493cf417e5af4a2a53ff44584022b9e4aa0da618534850b78718b4d2d +ef3ef110fc3d02888b748bfdacd54a6d395ef5e33c8e806ba5c4c2ec0245692e +d8a0ba8988f9bfc1999840099107485192f72bbb2bf9d44500878b36aa398383 +1e9123da27662544b900c75c7fb7a4bc55465239f413e29394bdcb0029b0859f +0bdfe2dbc94d685ab9300335e8e5fa46b3bb9d8fd3ed0cee2e29c7f429700e28 +c01fbf3d80adf7513fd275bddc9faf101d79dba5e646196ddc90e5d790e670cc +feaaad9324aaa341846f6542e104dbd56e226b74d26736f496611b1d60a7eb41 +92cf91710786aeb99de998de89b114b29e6ac77c285ce0ba15e4b87c233f61f8 +507b83d6d814b6b6bfd1957d3677e3e3e300e8d695fcfff2d22b4fb749121233 +0be1af105a8cb2a505bca4f5266e7b5993f9f87a7f00034790de8e866873f95e +21c0925817fa9e29aeb18810c635931ad0ee7327226d1e8845227cc1e45e884d +e52b55dff9e4a79cedc8baf48726fcbab62fa010e5b4175fc78f27ddf87c35c8 +a944a7c761bb7367e193f3580dabd77e95211d7ffba8f5ccfa9966693bb7c243 +fe98318ad499a4bf3d7096566350340e168be8e791df2d7e208ec6fddac9358a +288cfd8f5520a1eea4596d1ff3f5bb81841a52be506fc3254833073450edc1d2 +56329750e74522f3cd04fb968296cc7765b5d9226e7a1adead409e13bc14a8d1 +50ff963fe9572392296f01a4faa2ca4e31d18657b902a0bb61c5bcd09ade309b +eb29326094b7eb0518e4cad11adde596021263f456d89ded04795baece347c98 +e30742af7b5a1f0908a2a05c2d6207b8f43ba6865d593d117f2437c316288415 +20542036da0483d1dde6f5ad936d7bcd9fc176f2737f492f6f2d4f505dca4578 +b3570337946895adf45494f776166a2bdf02778d3bfa33b0a50dedd172618ac1 +2780949e0439932954240e1806725e6bf180ed9ca778f4bca505750ad0b29aff +71579e2bc10fdd27297dc97a26e98b7e1623ad07aff4214bf51f8831168d1dd7 +142d0bc31cbe6e14a31a500454bd54ab518e674f0738ebf599a5c39381555b15 +f78cda3549d6cf0f686a287e6af3e9846ea7230af9b16acb5bdd05877943b61c +8a5f603067368014edcedda07e63419c5b9393b3f6c0887fdba1bd4e29cdf045 +954cdecd0dad15f1b6233f179bbcdcb865f363a5b0e663f9da7ce01e78aba1d1 +4d397ad1f13f460fa455bbaf414291ab30ff1e1ebc28cfb9c4e1d8a8092cf8ba +0b2b0c2549e3341825e016ac8625e5a24a765d0df71755a42c7e52e77248ccbc +f9f6e9a9e9281bf218b3c8889d565caeb91a6660d13085b785e11b5273feb505 +b8506ca32de2ae1ae14dde32ed1bfae80950a00ba225f7fda06acb605540e14d +32b478697ca9426207a9219560a70052c48cad4a41c6c690d140121d7b6c2cac +04b7abb38618febdf3148cddb6332c12e372a72119efd827cdb569fee77ac4b3 +f019f04e73edd6cfc6ae8ae443b5afed8d31a09ab0bef2c7c5a56d4abaa14f5c +f96b4e325179e20f91a6b2184a0945e21af297ba48bec84bb2fbfcfcec9a4c4d +54b8a849d02db3a4cf9081341801ffc09b54fcc15641f12eb6e552ea0f754f42 +21c812c6e356b9d89a9a1a89e0c98617c7a27a56a348da8723b973d10737e9f4 +1320218392be55acab9080ffb1ba598a23f45fb443fe1dd5ec6ebe4e92c683aa +42c4f49d43160a5258531d9d952907959538da4c3bdd6d2909dcef29bd26a7e4 +5ce311dfe82a5df26550d2dac8b4d72b8137d93138923295b1a37258b64de471 +3d68d3e3e20e66cb8a80ee87e266a2ee7a99d37d146d0b728e785f7aede6ad6f +01cada2bd11b82b5043f3339346976330612e9471b252f570f1b5c898109d7d0 +36335e3c88aff0e9801345ee302ecc2338b6e84497e0c329a8d126980452e06b +b60711c48c7c06528687c732069b5437277b4c9462477ad721f4921f5567d804 +10e7a5129924c182fecb7002db237891b270060d5a89c73aebdde7160db0b67d +ccb80e00bdc0cd8e07d384ec67f85b0afb67d3c8df6e7a51dc94ac494c60a65d +f8acadca8c84dc3597b03c9178f7341fc0e5873389fca9af05b7e0e899d19020 +373aab0c27cf2947e7ff760a9697fdca82ec9e11d0ac41c0cd67a81119ac73e3 +58cd8c80a0e3276a9096a965535687a28106e164e2d622dc85bd7b2f9b06f67d +d9c18c1df038a8302f0dfeea1619e465a2d1ca1139799933f670803b225efb4c +c9975b35392170e6a15c38170ac8c18344733c9c830af8a587e2974cc7914bd4 +10c5b4eb8027289a65f68b761083745892c56aca2517356d1b3481c13de9bc68 +8aeeb9c30432490b0c9015f7d4a75dcc357f5a4129617bc517f255fc35d2b182 +bc5b0b582a75c5586994a32ffb8a0f4bb0cbc9062dec5a6d62eaf9a2b71ae979 +d1372a1eaa61dbfcf390add0fb501566a3e124decedd705dc93c3b588ae87c66 +b329e2b51eb090824e5cd65723c1ec6b76f5386dff0be90a7d0d6ef9d7445f49 +b05875d7f7d9363a6c7a33017eb5efc73b543703dc17d9f400bf9dc53c9052fa +4e164e59a0bfa762049920960537342ea46faecbbf57f13748e9fc4ea129fd83 +ea7d9bb652ab16361f5f34c4e9616bb2a276328ce49927d86c591359ded9d7e4 +34856238945254ada7cfd255a55ce3e8d86b30e4a81c8b27371eeec4eb998aa0 +f43d2906f15ab122e99099e33b239db971ecf507474fce8b117313dccca5660c +125637fecb01ad1812e390b7a33f84975f7f501c735aa99603dc353ee8d1f73e +d85eb506fd30b47af9f9d60b88824b9781b685c02032675c7b5a3d7265a794b7 +0e9de3f8734138c6351ac5c54901f83245a247817d68090999c10ad83e794d64 +9cf32e12054761bcf8ae97d86f4069aaaab8138ad3994be4aed4f16cb4d25137 +620126eadfd6ad8282a965848e1d9ee624672864f01b87cedd40ee5b71001f58 +65535124cd4e359d6091ccf487e7c2282daaf3be14765a41ad3618b1e01febec +ab75d4bfd9b9a9d4c706912c92fa53cb5c1bf32b6aa437e214fd08882024c9a1 +04ab47eb0dac68d080e9e9ab4749b1a5a74064f30c75b464df90d4349017440e +f142ea4e9915afeaf32c532f24ad68d0636f40ca3ba544ab124cca2627800974 +b80a990c2e0e757d94e99770431e5afdd3166cfae6801f572aa2058d49d5e35b +b4a658ebd651559d9ce6e83eca2403713e4817840f17bf8cddeca2b7127c3e00 +affe2926eec9cf9ee3430da61485a6f3ac4a5290328d3883e290bddbebdc9f08 +6940b7d9bbada853b9afbc5dd7fb8cf03a74078da1bd9829349674aaecd70ee6 +d9eb566bf17914673d0e1a08de068e3d6959976a7a4045a1d113523d6d3de723 +9a74d081264ec2633fb28db345407788e0c33116a02e3907ba86613d15b6cd18 +cfe718347da5796306d4ac055ee0b09b3416ca6c4cd92aa121e001261b27de37 +08724f02125e4398340104a371efa0114d44e6bbd785895258c3a953e6193c5c +0d40ecc3db5278673ee61790d3baefd1d9464246d54b88c6c8a3afa7056fbd21 +2224d6115a673b11e31e7c94ebcd6e0bedc2acfea576044e9d4556625ed9e8f3 +0c8aacd52d937bb1a1c905eac5a917fb66cdae15d5f9bdbc16dcf09a68866583 +49f5244c53f805c6865df58fef03081277ab66722a487163a9560fb2a2580d4e +097c5f1191cd3dcda898d72efb7107004019ce50e7959e8df14de414d967f1ce +cc4e0dd86ec04bcbb98d8e6b84b3fd735bde57d5dc2dc27258ab5d1f8c0fb6be +a8808f19b8be0f7378e633a528cac17842b7fd2977364ceac61b99aa78193f31 +57d3b89608e48e68622ae9e87e821f5310c09f576c1797a6971c033e1bb17860 +e307be8531e04b4add8dfc9f87e366d17a82e3ff7d33993108e6ceb2f2517e44 +afe7e46aec7e86fb93df8a11c13aed6c169f30f0e72fd1cab8593f9bab1d01da +957f1114a1176ee9025c61b91946df39aed15cb952f4f78691b12766a71a3da8 +1c48bf76576e94b314b56a0f7cfbf9c07c527b110ff3bc6c5beb0c4a0f0aedc1 +7af467aa305ed2f6f44ffadb99b7e5bb1ecaf4417a7bfa2b7c415dc2f2b98117 +9124825b4c9929404d045ad776e7ad938b7476e3539d1933c898cefb7674f0cd +8cfb57d4f720ddd8415f7e78bf00b0e9c25f221c955595553eb0248ecdd1961d +dc2436db4a3e821f730a9a56b4a8d7498b07e5f4ba8f370cd74d020af7b7efcb +c29a1702a145c4c45ebd3dbc629b149813b41d8dc2146132845719d41c244c53 +6bc85b4e407e2a5e895661eedf5c6c0bcaa7a2a693d0d9e859cdad4c752b6696 +b4509726e2040397a93ee73386246216918f727b0208329e148f689a1551f88a +012530040375616a9ade43f842df48626d5895097d847f6528a500d4c775d9d7 +e4b337a4cff0bf64b47f23df83e189610c62d3355024e8f8206ff9fcf96913bd +3bbcda6f068c71095f8ac3c76a2a9c37ca6fe1dcb01db723729e4ac1f0f279a5 +e452412f9352318f80a780001873dbcae387ece0a5276db73e5f6b39aa8c9046 +1d380cc4f8fbad53e1e6e3dbdad7a5effe1611a1465edf8383ebbb156bf21fe0 +055d97fa1980d15b14a009413ffb8da4db4d8346f382497a19f6c1c2bef05bba +3d2d6ee04a3b7bafa1a4e66691e580eba6f8dbac8312c8152ccce85226a272fe +189f66c8cf431eae9ea3af795a70b1ecd73834a3208123860447497855b71359 +ce662ef8a2ef2e8bfab320de2f50bc3e632edccaaa91585cf53a41717f514f49 +38feae4265728d1865975f4a98ea642412839af40834a4c51c1760a31d490c83 +f29dc13af10b67fd69669038bc1a32b54e641b68beebe567cdfd2a7e91297f80 +ba13c99b64d29645a769b9672f24860510b3e43483e711053fb0aa79bc7d727a +b51fcab5bde991b71888e7ed9ce043da81fd29aabaf3d5d4376abb4fbf3c360a +2714f4b5522769f78b5ceb0554a749727bdcb583e3b0dd63e0a8806938c3be3e +fcf66b2052d0b41327587291caa5d85e65618186507d0df8610e8577d1828f76 +f969f060f6290be91130d49794c6ac31e2d62e891de4c04748f2374a205d06ff +2fd338d5f55175b0c0785779336ca30cd6d54ca9cab27490c1238cec17892f40 +4d5c7bfa43ccff0056dc5a5e2eaed0632e4824efc69321e11b9e2f73b0b819c0 +69a9a967e99d231ed29d400991c6f8eae096abfd966067f702e2aefa6c95c6d0 +95dc957629146b17c34c703ab264bdf15f08b1a4122bbac280a90de7ff1a9166 +1dd8eace2c50deaa0f727ff18a863ce76dbdbc88d3a01cde8ac047a91923014e +840d0af91b95f33decec2768649ee98d8fa4f323d6ebdce4d488c2b4706caf18 +6dc2c2b0311f2a253ee39cecbee25ab5f6e0df32b757a5328fd0918925266e9a +79d1e3dae3c4b9e211a0f68330d43bd6cde537b2b88c0ff6e5ba7714acd196de +ff206dbeb1d313be2b4f0a2f996e2342a902f12a4a19e767479b4de74438d3aa +70a779925034a8b00ae004803a13f6ff0465d07d18b34e9d578377b8d765d775 +b5dcf0f39a285e961e0390dd95c392d085089bc973c7b255b9b73ae162147683 +ec183bf55f592c77cb84a398243d0424c6709073b632864aeb96cfb2f295b2bf +4cc5b0e5102d130e3cdc4a047e046a9b0883c30e5c8e0f086942c43af477097a +b7bfe7f6224cb1ea917ceb928ef8395b41a546d5306ddf2565e513d4573b1fe8 +ba9daf3f2254b83208016f5895549bb2dec8c7694fcdf104efd3cdc00c42a7f7 +dc2bbf0914fb34d5c405cb97d6e5a8d3ab1a20f0e4c1c3bb9319e77bc5e38cac +dd1dbddc39a284e86f2e2cd05809cf59ac5e699d452129dfea3382c71ee85048 +fecf6bdd9302451aba74b621c42cce93396deb139ddc9ae3a75295a8bccf8c96 +691578cd3de5575826ffba1896817379723f1710dafea6e46ecb0ef0f23869bf +4020a9e81a4e763e06aa889d4bb42c9eb053c6bf5dc9d5b090d0419a3fbf1a3c +815d2cf5881ca98a747cbe3a31c67bca36e454f089ad395a62c9839af8f1f057 +0e6012beaf04f4f00a7ade236a108a9ae428a4c772816eae9d7c1abab322d05a +a9e2476380f524c1f608854bcccfe0f6eec631b02667582ccc3e236f470bd042 +e1199bd62db38b7358016a204d117137856e913ddd0e477d4910833321e71c2b +60ccd162cb0452c0992b3165cb0d7d41457591cd44b531d9a16756cfabf8cd3f +66d52f56d4c625e4b8395c1340ad937e0bad5d080b4d5c2a4fc40375bd73758f +41c160f11792f2195f79aa88839ff56a1f910f956c1cea1ef066ca1eced608ed +162c030ea290ed422af8f21ec8f984a30bca49f3f9e5ee165da33b506a8bcf28 +31df33356d267a018e1666b4f46789596426824349db59a162d7b6a54d8d74f1 +cff1d1b581fa13328d18e01e9f214d8f617c354ce1500218c7fcdaec7d8894a0 +4945284ed7fc30ac69910627f91c427b6395934ef0d60885842c3bed90ba5496 +2822314e6c99efb623be210cde5181550d722f2d8a7b697358cdc8677069f174 +abba298d6099a5bea8edda5c410f90ac0c8534a2621cb646923afde8cae980cf +46268b7c6d9541fd578a333b730ea29b87fe4b9da8911fddcaacac463d6ca320 +1e561d8ac75f89e0a14e1277ffac07527f9a3aeae0b8f54b5edcaf4bd06d1a99 +cde92c440782fe1ed9689e6fbf50e5483392cfbbeaa2658b39b4149b8c9fd892 +7e37718c2bf0bee8b6cc700b30038e35c94594b6bd061368e71595160d772ed9 +00291daae9dbb36b07ffd612990f94a0e3885d874aa3c72d83dd326ffd7508ec +0e5ec3e0f4d12a0230e84a6c43579b1733f184272ed78b85825e12a82e7a0640 +d8c0639bf87a5cf2ae8872fa37eb71a23a474b1265348856a8cd55fc7f69b944 +596bf05fd12b69c3cea1ff57371c5ebf08ee80fffd19b2913732d3ad0c0653a4 +39355776c3724c8c3e0eae2071692a01e992c0fa93fd3d7f636d14f100d33584 +ca0ae5349027cb2bc9e414d553e943c6e18164bca27146dec431e0b366ece204 +c46686b7eb3668ed6bac7b232bde2ac7f27374f63098bf32a468d6a74d41c690 +a589dde0d2c243aabc0f147749abaf3ef139104b7455d39414f9f5f120440b5d +2153bffbdb5a2e4fecef35604baf41e7f73faf603309e04a5e305418b33edbb3 +d05cf06d041f610555a4249c023b81a8272145872db8e81a11244b10212763f4 +1a92e9ebdef4581548252258e03da4204d91da7e4a1b4e48d95a2e393a2eca8a +252e5fcafe9966ea4c64408799830d4449d5838c944f20de40669eb0c4d430ac +a66e8a260c1369431fd90d88e996e3f3fc1911cda1b3366476d75f707cb5e89b +41773862a56f2066ec7153c07350d8e579326af5d3730faefeff93b742341ffb +c7c4c3e4225b3b27315ba72199cbc52b89186626df8c64b2e62c44b1e023f3c2 +f0c79a4a2680c56e1afda2336193b9550a1b8f8de7cf5fa8ba229a4b6db64d40 +7bd6e59f3b4a06b4f3166b2f8aecd1cf811ff8dc1888f003d48866326de34886 +59a9eb9f2fc3f3b34fdb156088845ae0f284a0baabcbfd83fdafa8bc5ee2a54c +25de8c98ef5712fa11d3e6dd9ea89e88565e137450e663ac02ad570e1fa16623 +a37b8aeaaa9cf754ba2140fdd8b00d5acd5bf10c9fa3af4f2f1f86f7410d17ec +608ff4f24dd152d476c6a2deef3854ce4853a6ad252601aef63c34430d37edd6 +37fe838fd70b6392815e4c4eb2489164ef45bfc00ed4810eeca455aa73f58da9 +63ea019674c0f63a996001cc9429c81dbd682e14bd5cdcfba7b00a94713e944b +13d4530117005f38ce34f785dda8a12519ba08cfb85010672ee7ffc6693f0975 +bb3c784be90aa02c6d2e42046d3d5266fb1af44f96e18156bc0f383eab102bda +b17e590cdfaeac3efe588b2320583def9448a9edb9966cc53e1eb81d2978e2e4 +07d443e66ad6bce411857f593045fdc59aa6bcb13eef0a726f69c63302527b79 +eb2ccf9f7869b42d3913f7e85ef793483f2b8a1fa457f5436dd52543ab01187b +ba0bd98a82b9bca00f6fcd7ea4b8c42fbb281fc9f5e45c85655bfa3389002d22 +08a351b81f53ba3a328007ceb51b42ab104a15ad389074518e9b2a24361d466e +0ceee8e66a2b7bdf1e0fcf1d67e3e06c76e3546c33e9b3d3266791a3c5d1c1bb +0ecb2eb0ff00b5c168e88eef521740508aa19373f1e64a99d2097c52888e820b +7665f808ed40e446164bbac844f2903ef6d550b48fb2ff1e69a65c0c0fe98034 +391d3edee4d5395e6d35906ef44793a79fa76e127d18e8093e3e7074c23ad7d8 +2ddba94b8a22003c3c8270e8f7c41ad8961be79d71842b839c51905cb466f653 +03949a4e063190ef2cf33b555034d815ae65d6a43563d3ceec6c199435d726f2 +80022e0df342bcb72bde7d08444b7f93559af65639687e6df61f2d3745804272 +e4384ef82bdf646c0a2d59773dcefeb06cfa957e3fcf9b962141bd30bdcd3883 +98c07c4c3496e2dc0e447fce1025aabc12542f0fd7aabfc7b5ccdbb96ee4000d +047c0ea9da3462ec7df9c5d6018e9b8863ad93236658fa01f6351d67ba093d6c +680607a9a23860355c0e827b86d8ec09d4b5f9c186f2e260952893b9fbfd1b70 +6b1e830bac2d50cd2fa8f5a35d95c25b8ee851e16c475e59caa186be451cfce2 +383045a870a3ea186d2c8035fd3d83ccfc82662bc590a7b64d200d75aedf6a75 +d9376a48b61aa327bfa53a72ee558d42fa5d4e43fb43dc8a5768358d57c1dece +01edc8bcb96f6d4455f40058e33801b2467c666bae34dc478c29e8c3f2937789 +2573199c9b01c8c62ba65e017b1ab3e49dd915bbfbe7ce979af5243979b62d40 +b762cd985a39a2ee6314537e15ea205a3593ed162209c7fed23c79b35476c885 +bc3bb3e9302bf4293a12eae9d12ca2446d84660aa6e733e22cb88ab24a269df3 +b8bb11c63e733f63c51f31398918554c875b5f3add9ac6e40b85a9837c6f2bde +8cc13ece6a688e8a602de0104093897bbec1cea77f7b7e0e3aba82e57cc54757 +58ed49d50cd7ea94d8c628c80c1a6025415bc83c730a56338421288a9aa2de59 +b96149d7ca409e2a4fcf262ace3addc52cda081712bd1754c281f5e007cd8745 +fc1e2c784734adf8e931923dbed3844cb44a3837917b3e1868a28765ca1fa61a +20d3d0c25bc303332979c82732c9f637133d8a9c178d81352b0342596cb7e99c +89fc012a392ba18a62b925524aad451b4a5c2b0b48b84eacb2e896daa8aa90b5 +fce6d47d574ae523e7bf269a74d47f9c1d38a9d121a3765ab70953ea39dc4114 +58f2e157d54fa551b598b7d2b14f8fe49c58fad988c1500cea4002f8f44e337d +8913d3486734437fa1a2dc947fa0a46fa904d5daf848c25ae65d80ece7b58e0f +cad4125470bdb4f9973ba7a1f750528efe9f1d47fa1c3fb1eaf6d58f0250aae3 +ebf2ed89d9eb027011260ba94726a74b86b66ec18ed5726a31265ad078d38b38 +6d95e85fc321bba9e0709b5b6228ba2da7aa56d2bad6532bae9d2fb584da5d64 +97575554668b2db7222b4df1396934b2939c45adabdd1f0fd4677b0b03299988 +56e3f1f55e2d0c6c9cba55df7b9dcbe3204e22039853290245abf937af9ba7ac +3fb8967d62477214488bc48b49bb2c2ba2f2763e38deb76db5fb45382d7b81cf +63a6e4fcd5266528a7007bd926ef61c7c2bcfea3cda6490e568f894a2da0fa3f +81b3be299c1753af2dbc05ebb37363d5e2e3aa2a8ef4149d74fc6a0a02783f97 +02acb454a92cbc24e90665ab11ee26d7c6b6cfa4da91733288e679cf77f786db +90423894c53f30302f0bcbdf276e153e3fdd647b183d07257a9d658c098f227e +c029a286b9c610e3a17347e4c2691d3ac63118732bf849ea12e0ebb751592067 +5a4ad429b21bb909dff80a32fb71547a06c2f5cda8c9f57648acc2079db01f90 +ab1f9c7f89abd2f4db5eb088999b34aee7d398cd301ca85bb2b57bd43bfa73f5 +9d0d7fd84932dd320a173808251be340de901bb5b97e513dcfd022a255acb57c +c4f2bce71f269c916328493e24c43268f97577fc3f31f768b2372376275a3fac +9b05b27663f1e9f6fe1617a137021a1ef6f7859213c6cb4da876a92d247939c2 +eb5caba308b4200b94295603842ac9c68adc845a8fd3590d2555ee4092b7238d +82865d973336c9fe4b59b43caffa93da7f400806c5caaa0a8636deed8bf36059 +f80c195626274b20051cf969966043554cf34608d4a4b6f73e6038766ab3f6bd +3eca4b172a12c5e59a1ec954ac7ea0e59643ee1b2b24c306dd053e3784f01a87 +bb964366bdc1ba9d674a64d6bd647aa887d72ed953ad458b32e3b2e0dbc4fcc4 +7c095766e0d6b06b247ed15c5279a27812bd1c94f0751ca406ab9c91f5cf9cfa +376cc760642b8f08ddbc9cabcf75b0187de8701dae1a3493232e4c71faf48476 +3fef879229d952f95c0d919db0d62f959f7385101dd01f5efdf6eff72e20a5fa +c900600871c73d4684361357846f5277392824f48e7cceaca93caed06ce24c16 +3f733c129afd405b1ef786a0682c82333c8b0dd477e0d0b223ee2bda19d576e0 +194c1e631d9dbf67bd9966d74e41884f42ba97d73b93e2825ebf22b2884f50c8 +921c2e4c6b9186a446b412ae0e1ff8035d145bec0b370b55537c964ea7531a12 +f0df2cb4541892bb39278dd9bde4fd241db9dbd70af58d11685203c9ab19e836 +9da185f88c5cbc5d4a03f53044ee0bc6d6b6f7766f98e70439f5f7fd896f4956 +12a8eee64eb978a9c384fdfda418007c71f498b0cee59e3376e4cdac6c2cbc79 +5d7951d9b09c60423e66f2c37be050f7ac9ba5257fb948e3549d07e956f36332 +02e990aa2271d2f28a77fd0f141df2cbcc4f64a4a2f5ccc99878b853282a47ba +690056d92e77d30525eeffbfd98f36008cec7db26fe978a6e251e6214a8bdd05 +104b0e7000d83a1068eb308847033a8de238eb43c496d15bdb6663ab3c4de5ed +c2a576fcaa66b92e696a31c7fdf1a322f1f6b9edc6239cffd59fee7bd20904f7 +646c814201da9561511124da9ab8de9efc9cf2a83ac73c742d3865ebfe976c2c +64f405c8e8ec6303b23f5c403ac13e70bb99a879a22fbf6e95a3941e7717d942 +f77474d496a18f9ddfd441e04cd7b3afcd5e1872ebd167558c6708c9ba3b0f7b +e4c522b873e9f6631756e2d44d1a3e731c84e841e890a25d2186052129bf0706 +cf57a821c81c3e7e860d4fd65d85b57e49b39ac863f52da5509c2faf29705b90 +c81e44d9bb7b704ce4f4ebd7eef10f657f879b100ea3916c2b23449cc029e2f7 +0a9aa98bb63236c5b0dda14eb6d6c979ac4c2c892b6643a8d2680b1f7b1a134d +7a9d555d5592853c39f846808c1bb1ecbb0b57e4f6e7e0a0943958bc293f723a +ddb2ee750ce6b49ed499d52f244feb0b0a696cc3fee8b50e2f7105bcdebf4066 +680194cc8c898d73149e745d86b5851e39f524ff3edcda297b4cd0756d8e5d45 +616c09335b3228f963a04f7cb28eaa2bb7632762891fc1fbb316948782a2aa54 +934f9120236ceac3738bd35e1b53d6ce9e1b4896b9d867ef0422d01707cd5da1 +dd21748e5c6ee359fd390e617bcf3832410ca1516691b39377ab52f9aec5706f +84f565298bb05d589ec61ff6529a72945a98d3c734a048d28e73e843c2b57da7 +c1fbfbe9896144c56c9bef8e731eba495304223daab2a1f2d1ac63afa0d4ce8e +448a5e4b74996896169081057583b159ebe6d532500ff72a4cbe387b1cd298c8 +e38934eebfb16e18a6a6997251bd0bf65e2e87a784e39ff47d1d56d128c27892 +95804979a0bae4e814d6fac8e6703637210e49198ae4dcf5d2ffef0b36465d86 +a74c41e15e059eafd88500729de54def349c2ece3eb49e1c38a790a212685449 +1aa624445a3eb7da8d2dd159aa31c38c86760810d7feb455f53cb99a3359a861 +4416c6023515e1567af64d2032105cff128f0358c5c76ca88a3aecf85be9594f +b07c333ae7f0fc811c82f41d81401a0e4bb8adaa66f9d7d346e209bf9b674b7e +6adc0efbde47bb27a4a105f32ca9ed41feb5452f573b117987513af082f7e586 +8a0600076c7c0bce493f8007ee14d864b0af615d265449f99ea064021c3718b7 +c54f8667804791b1db160632837e029bcf0d2a7f16ea2a19a9bc96139d1f3093 +e11872f76c67ae13c27d950f97929dd0e43db9ee71f287885c1684c2c66b2a72 +bc2050ed428a6e2c3e88e50a861294aae4207447d0d2f26c5a8e00f61506c18f +c8d5257fecf5a80180edb3601eeadc22f9c8187734e405e488283f853cc34c59 +9b3b66d4148c947dacf6918fc51809031a18d11291d149f60ef3b69f33c4642f +ab7b1785c1b58c7dba7a30d7fb7d74771d02674ae4746fd9d24356a3002dc4f8 +d4c21ab930dbf8d013211f71cd1909f3d946dc6afc29e20a2499081519e7b0d6 +868b23cf92eecd8f0227708cab0ef57c93e51d926aa5152bf99d3d5504acfd2a +555a0ed75cccbc02055bae95e23321a705dbff2bda4dd9a5f202dcaa77418c49 +987b4f390fa1f792b8b5f82324ecc32e8bb8ff8d8daa724d9a282ba14188988c +ca7807703f0237504f69e532c629f339a9a3bcd1233732787ddd8d3f9fdd5223 +d4fa965c6c61737dbb65dd64d0ce08e9341538a36ad6fdabbf427110ed4b265f +2df004c761775d7fab859fd654afd9d9f3949d9d2db89de013f6806cd72cdcf0 +4a914c052ffd6136bbdbfae56ef8e003e2a22173b22c6ee8455e1322f2f1f20d +b472d2d4565206e423ca348e8238df937cbd7d72be1fdaa657540989cd17ad6c +3dbcbe6f1134aef232f541ddba3f32470ce4fd14124b64f9de0a423cc7d3d196 +1f1df60bc67d40f89857497ae1bc0f7f8d8f9096f55102bd904e77b62ced8049 +3b83f70242887d18c511bb3485c458b40e0b424674036f2054565529a1ac75b1 +595f375f9af36c700a0c4239973818c14f1e0965681b0368a1d26d15d62fdf31 +f4fd9ff37ff2141b4addede8bf86ebe020d753da435674f740b68ec15ea8a331 +db959a0ac36470142f9e0541ccd3ff9bd8f1c5b6dc8cc0aab9e84bd0af7506e8 +af351f116c2727bdf45a39a2ca992b520627bed59bdf11f01dcefe6eeb93b20b +7ea5742ec8061eccdc7deb25d21d919e11dc33829ebf9aa6aac2021c466e244d +118f9f26c14989ddb5aa47a3f56be8f629f7ef4a7ed2452b6d932d5cc8118c12 +491836f81863f50352fd73022a88a230704e488345972a49c0c4c04f819da7a1 +23c66c16eb0f81f3dfacd154dbd751076d7e3c43d951a3a536e59ab9e281faa7 +830ff5eaf4849bde5d6366fbd79d1552b725dac4f5d7d2f8a2696edfc057cd1a +77a30bbea4931c629919fcb46255597c80bedad691d08c4536a812433415356b +10641f78bac2dd37a5612e5b80088388503b2f6d1407e702bbd3c47f73f712e9 +fa534207300c8be9bdb13bf293a611303221742dd687a799c74caa0ebbde839a +0641b244cbbf6d357902d4b035904d5a2f61e4e099070e8888b8fe45aae49952 +b836d867d9d3c0f81ebfa4603a3fb053572c957cbb30f12aa07e45eaf86bbf59 +f08ee99993ab54a3221361d07b85c19ee37523fc4c8f9233bf1c7b4d0f5dbc82 +35e64c99154275ef904d3aa13ca33c7d92a5e091ade464562f2610b19f803f94 +37022dcb7e952c8ef300925dc7af99859de3fbca0b27b4c06db902bdeab2e3e7 +a1f1b987d54a51749a3b362ccc267918c044e2c254a03581bab674cba4b88be5 +231bd8ea025ba46b79fb7ba769ce6ebf37cb27ff24659c485e84f0a29c037b47 +5e4bc5eb7686d709ed2ebbb4f608c0a25331bfac8283fe57daa3370ec23a0bac +7dcfeca8a14f7cf6a84a95ec58273d9cdad6e8a548d6ea7696cddaf2f02a2aba +a57ae310ca5191ecc14a567d35ff5c0f3213b2ce997606a59c70ede173a80935 +83a0742144819859233915c31f64f11e35e165f4c7179a8ee1ea79ec7736dd45 +d05cdfd3a2880e08a8ec81798bb38144534dad2fca07eac523d7c291c58842c8 +459ec9b1536fa6690e777dee467a23778dc575706924effe40269a5e38109594 +4676393c49d315851dfa2c0f445c0971f4101135c46d7d44d4c64f0f2242c5bd +61a070bf3105f0884e07dcb5000ac86b51c3eed287b2d9d0307b2aa3ec2f528b +59b9f0e02ed6ca32f7cfc76333d040a643fa71caf2a5dd52091c483f8e136abd +a46de8d058a81dea5bed08e17e3953cb75bfaa003e214b0c666bbde9c19fc81f +3405bafbab7f655b8a419baddbd6a22f06d9dab0d3c2454ea5e1b3c43ea0a3df +981fca7a92d23c3740cb046840febdf55264e4409a85bb2dc58942cfb9309019 +0c47485d938cfb86ade5feae41074f480480eb6782c322e7eda51ac0aaa81c7b +b70fc4451f36964b53728d67ee79b0115a372201228435419f9d67113dd548c4 +3e5479916516f075311c07c376ddf2fc920f42c35cac12cbaa6453a7065f781f +232f6796947b7b967bf5a8761679908721e8a8c15debc944b1f91f16de60a43b +4d7d8b0773bffd161e6ba68b6fab57740dc192cbca3e85ff5dad2a581fc44ca9 +2814b1877a58f06972d7b0579ea38c1b5e9c1e767fec1e07448c52cc62ce712e +a69e7769db41f5b80e03ffedd415d978db6ba09a9fc424b5d00e8146faa8fd80 +7455448400137916238301616d50a1aa6457aa5ceca2e2b1b5ed811122139d68 +85ade3e9da58f00e442058809307e6a4247804bb13f87a5b47332d08509a9dd9 +0f1a5508bf16a6e76af5ef15d215ea6ed2b17adcf76c2b005f48f83a5b78a64e +b2ff0ef81530707490b393715950d17835be5f6a5b5791ed76e8d84b1f8c57f3 +885814c5debf2708a00093197e105097ce61391874f121a5ca3d6f3bec647368 +04542ff4bb78c8a28cb211da00c70f91e60832625d01267aed217b69051f9163 +1c1fffde1891d6ee999aa7f5d625b23a082f4946ce2b8d0e619269ff5dd2e842 +ede7482334bf59506b9d8db9ccf775219a7a3ee9cf9ed4357deb5a05199d4ee7 +cb5d16b8e1349732d76ed5f292708481cb3c8bc3088ef01716627e1368dd6191 +f1fe834c2f29b711bdc8bb7d992085a61fc48ac7426f73c9588d28757871378e +f124a7373b458e71bb1f8deabc65eb25ec69dfa9c7589ae42844ade3bed6a6f0 +539fcb524fac13f988151e170db09b97354e48efbb4d75c3c501cc1dbc7f1247 +5c6bfff259ed7280e8ca3ed071f310696f1918f921fd2a4f541c8afd45c317a8 +53e439e13373750b2d969f67d6c72752cd9ab249f01b6336143f7d459a6ae648 +ab49942095e170584ac7c711240da3f3d43622c331165d3021219a6a88b9c6b7 +280a1a27bb2eb0daf2d5600f177ddbe533dc87a5690fae942d7d3ec7b197e868 +d4e33fdf8d938f089fe27673ceec8154f07e21057a150e5789ed902a572a58e7 +1fac5d0431055dbc8bf8e9ea033516568867613f75fbf0e4f970ca3e2b866a33 +10eb78219174a4852513d9912faafdb51019148b04779cff1cf009836fda0809 +0f80d57ebdc87f2e4dbbee5b953286cf545fe28ab123754fc811f6963e183366 +47d8fe237cfedd0cd4e16b3df3f62d121b3d1f2c823119c8d0d0bc645a03afc1 +ef43faf30b15d44ade6724ab412c144f996c38dfa9b13d75739d7c26072cca5c +092b88605e707e6e73345318aae8157b12030b21e794ff991ce4d6e31a49398f +80b087f66524b2a030069ac7fc57c17c639f04840c57151d12e9cbe612460951 +71f11959cf33f3256f0e2ed817ccc804c619f1bffbc93c4cd0b9c6c523edcc23 +added15d4a724d7090b5c0e16cd22b0606e9d2ff335be6ecccb7067d5b9a6fbb +9dd67ff08b2a855c195ae5ae841b55a70870ccf1d34ec15581b9d2549fee9f78 +f7517793947cb1418c3895b304aa6945cf80465488a760702b8e790cd02bbbef +eecc7ea3f876147825352de5b16c604feb1f743d6cc53e7e02d777e265cd087a +365c8ba9a367075348aac23c14f1e493bc8ea48044822207282adc0060f76d4f +01901e0d240db3b1480d937b0e41523f5e0b8241e3331ddf6c9996aaa998dd5e +0d04d00b98c7974adaf5322a8943fd32dd228780730755ca54b136de824c271f +747b6469950e2ca731fc19736af154951596b11fadcaba5fadb9feb62ac4bcc9 +baa5a366d6b30a44dd635ef57a30433adc6c2e089ae32150fc64dc4a085c970c +3af28d0075acbc0851382d44a7c4cefb2ef09273e140a79eef335cf48e7323a1 +6bc80586841f04c0ecd93ca1c57cc321788b866a8fbcbfcf2dd9d60c2711f78a +f72f418bf9d48ba1b2545521d86b2d34d2a2941c7ccc81380036076d1ccfe14e +02182406ba8d83611f1e6a38f9d027182926da8e42f615dadcfe181f2cba9247 +f6ea9d21bb94797d8c90d7c04acbb182bfb8e2af1d3a3311b67f521a13a5a8a1 +dc788ea3a3a6ee8a2f562b10d41fa91b731d1e454b1d27e23b1b7b2b5c1286c0 +fca52c1cc13f69d8789140604b1dbedf37a8d47f4d543bcd0fe2bc425c727424 +149b99202e7a30af2a88259f860d91d4d9041f2c2be22ceaf3f2dddc0c8ac498 +c3dbabc55cc3f559f0f7f3cae9438053d01cfc63277c79b9d2afcf228c368a0c +ae510a18f0c1a872f25dc287c70bb7ed5f544644fc6252ab79a653093b5b2f1d +94e96a67b473ce13dc18090f094299deb468afd14fff7be8f96d2e92899981ec +a70f0a84f29b97f7a08872413c891ac0ba4d35cf453781331ab7f819bfd303b2 +3c73185e14f2bebb526e55a152fb2d91eb4b2cffcd7fc52680b70d4edfd4daa1 +ebe3959c121110e598f832201426b3949b6149b92e4bf49bcfda3d73cddc3e02 +e245b55b8955bdc55594015a4a8b5a29f1313dd7e469e90e42ef7e2ebc566bbe +b571678760d8729df0a7d9d5bae270a433b57caa3fb817e64ed8000bcc01d985 +9a80460bf93703cba36ad8f5792b7550c0d9367670490464e20448d74abd5b26 +4a0f408344afc4dd9421b18e30cc55fac8549c451474e76956efaa1b1d7b210a +a84b46349138f053be0be0ed0e177b9cd3ee148b0d282f4198aabc1f6dea957d +5b59f50ee1873664d1a5472b2d45a9da0e225763b860c69c3333ea78b235538f +4c68e42e5dfd7f9d900c1122911b90786fde9b8ab63373751c45de6c5b2f614a +0bd867a639d4707458aa59d5891cf15fd501342c5939ffbddd994e36b3cf2218 +e371aa4266ef37e6de5253fab7792704f8644135dedca11e041161e0d2112a19 +be3db5f1b499a4f1855ba568650b57fd888782a6f1a120a01e16e9955b1d0be2 +5d345ff5dd2da520456fbc8c511ed690d48684197e1a057bbf5ec52a5425cafb +987e2b31672554ef7e53d06c069524ed33f5f516a0fd970fb797faff55420781 +4f948d4fb3da933f8d1c998c462f63413332c7e9eb3a43dc7ccb12507e43c7c3 +30311ac2594a6af050ce883da53850884b37517eba81ae07f332cc204f0b9c89 +942960340c3a9c51e0a60bed43f492d866a6206a930118bf6b9646945cd45430 +21949c7b0a365073bf8389f3724aa6be372aaee7826bd8d4b72a310f9127bf51 +aec07c86fe97da8d45431d88ec5c34c431af96167433afc7315737423d513ebf +d31892e017ba6c62f44980dd5b1267fcbf313848fd2fef6000470812c5f25b52 +26abe66114760cbf45fd163736a4ce450d521e60358b3460f594d38712db6a39 +41def38f42a02daa3246eac7c793ff5b8a8ca36131590763da4b5d6a4159f44f +db2e2cfc616e54f172a2660d807f5dfef515465333e9c5b7e6fbf0814972022d +da4fd512ea824ca9462a5b0c203253028b70db3db2501454cfc32b731b727ef1 +6ef419733de2289e2073eb820b935011afe0c277db58dd9769d035b90adf746d +dd95ce373ae09a2f7814eea0b28b32b6bf0479463debc2311557db80f75a1220 +2d41a75c8a7929a39137e0c0957c91992f040ed1ccd5554a0fd5c7586e8d1e3b +a90f6c0c7ddf9415f95ff36d3926795b10f30a3ff3c55e878f547d5d6f4a11a0 +f485dadddf6a411ebbf4f6fbf545c5c7a4717a04d4122d004c8c2f54738c99d4 +64796882e0d6a49ad4e10c4fdfcdeec39be8e90dd6e54664d1622c5713395793 +11c8f9b70c302cdd98658838714a9d3cb6765b2252af9405083ded61d9b88d3f +100b6beaeaeda8ecb9f2832446dd03270e007f2270458adebb0a55597ac5bab8 +3014c8e8f4455a36db7201756caf0b086ad93af5213b23776b4f39982e70c4ce +8678f7eb05f2d27d9c6d229dcb2086f535c1597ea315a7594f8d22f5c3c28fea +5f4b100776ad467b447913d708b418895bc0e46461ec7edac19ad6e29609cad5 +9493fd7b966677d3326d6bdea60c063a36b40baff0772ed66e7f5a494d21a03e +644926fa5976b8fc520aac97945987209b2d25de759eafd679b899aecd219a81 +fe9a72f59b5ed4af891d255d018db8dfc201898a7d9698ad535450bcdc001e2d +ff8ee7d78a25a4d7eec4aba0b528b58028753e224b759b84d6dfcc77a442cde2 +a4ee3e074f1c787eda7e340f1562853ab553fd911bfcc7596a230f423dbfde78 +679c997abfdbba02a260af430847a1b6b4bf779caf51ad481782a1e1c8d6d40a +27c07657f1e712f6619c6422b69b98b86b48aba79ab02fa79d27867c67bce6f3 +bd0fa82aa33ed5cd64c8f6c9d21759776c9c31f03657bcbdf3c02afadc32380c +b2c8ecfebbcd0db05416381cc140edd91fe6b58280f74b5949899be9fad9c733 +39ca20b5ab0ede6ec6dac9fc28f45041e8b66876b9246d5b83b0144795766eef +9cbf5e63d7dcd4100c05578abd4552e35d755bb76a7537e7ea239eb0c4d968af +ce017ee70d783a78997d55634f6b62d4713a1005b36efd4572e92ff74f1a2873 +b45afc621a34e2302ab694bf2d536028ee1e20c61779f57c9a0d31eb51bf9f15 +38b609f69b9dbd7df8800a043db7ad35f4ac9ad6617a8391c15af4c4164bf560 +e880502905d4d7445a364f3b628cda42e23b556ee923a16230d933709f3ea7af +5dd875a9c0751b06dd0b2e5a06407d43b029c9eec3f42077adc7f1fd09a403d5 +f1d97798f066b8185f7c31a9f2134e38e439165bfb6dd9f1270d8b226829e26d +6448228ec6dcb78732b2869f7eda0fa73a3a80416a93cce6bbff3e968099a1d3 +53bd84c074135976ee7f750d481451a850ff7719c464752fbeef86781c5d9bbf +2df7c8cfee893e4b539da6948480c4061ee64b6c823634d308d47722ad0af8fc +2982754852475d18dd4eb040802677bbafe7a86a746d8f83a5a9b80deeda84f7 +f147520d7e56850bcfd739f5a70a1081dda998867b8633b1c2795c8903304922 +9e95fdb11d9c01f5578a0f2fe4bd1b40d51e0dc545d278cd15545e2c12c11b77 +1255a75ec5dfcf0f16c0e00100bede9d706ca7fed3615c513c2fe5efb12ee2b5 +768c93277398d76803c93ba46644b44b9580fdeeda4c35a02b44ee59cc182e26 +a24d17b0059fcea9c19ee14d056cecd620db3df7a679cf5f04a1a09e7f501d81 +92e6910e36b113efe84d7e5417d3e747d469df9290cc5420fa48ca5d201476bb +ad476ebbfb4899055ac6ad3531fd8e0ca2ac86c182228abef4000bdaea1cb2d7 +5ff1ba4eb82d99364e4d35b65da89a126ee0f8b4d6f916db01649db7a86ba20a +07196d8a17da625305565b4b1627be291170e5f51ec9c24fe7b5a1570ee772e0 +68a2108f420ac9f9d14f5c5e8fcf3f3d80a99752073a582b81ab15e281519437 +0b0a2d8591caff39e8a58870018262b676df9a21a27e4508723e6aa7a5ffd287 +d55beff3527f8322bf0717f2e4fca1f43df8ecdb137bd4e84d034340e565b323 +f54a1cf4f80806f9f190a19c4c5a2a3cf4ddc3ed62a46d39d017ad85bc9fe64b +ae59012fa9a24f96b0b4ff883d28779c0e96289b9b6f99848d98f81798edcd21 +8997ac4876b99a1ce2253e5f60c8f28295326d97f9da65cb5e92d1ad4c77676c +03bd84d9dd7dcb03f84ecb042401f93ef7ea8fcfefc2148e73dcd868aa5f7cf1 +a377655a218cf35520d993e42595c9c0bf44da64397567d46b2eef3f8ad2b86b +62f3fabe414c6511ad191a5e4b1d75f1a8d132dc9a5f2907d731d548645eb13f +32ae08a63e1673fe282b803f3ea7e62e3ae031d66610225fc9c48ec2325f3682 +4bd852ec0350b3de317915339d4deddef3292dbaccbccf80323bbad05e9073e6 +bb726ed5f6382ae055b3b7c36f3945bf16df7e0b69b632e01d247a610e9905e8 +d3fe156d3170e66cbe452357ed9bb0c67f8fc16d2aa46d7c7bd4c2b7ae4221a2 +74e1b1f273f4325f58cbd3c4acee20531ffffb3faee6711f36e6e431586806b5 +93ac400be336898f55098396614eb5e7f9e0a2eb1fe50b939a0c9ba03dfa6eea +f5e97afad54c54cf65f991a7ac5af1486fdc8b1c2385ed93d2d96f8746eedabc +3ef56bece70e3d3a7e2ed0abec5cff9aba226cc4721ca10be199ea5beb9cbe93 +3391386152b0989784e0d826189c8076512520b2fc727a5b0c9b42fc8ba16902 +71628769d9e9b67a489beafab6245e32d3dbaf1d6432af5befd7c5479ac00ce6 +aedad2cf03d9f26947b259e959b2cbadc29ba4e0a8f4c47edec7e0d66a77a95b +6d80d6803f47d8d9da259a674e31427911e4b845293847566db28bda0fb41510 +36d710e26e6fda96d1696090365f39c8e20babf470b800949358869ee2c6a07f +803566ba9d96190169e4538538ee5b51718cf954b01677827a3763d234271582 +967c4acba9f043eb7b90940e61d4e6258465b33b1c6e73f4e308ef5f2fb4bf41 +55ff011fa211cede75d05aa7e0f663ddaa11b6b3cbd4aca564448f141d5aa0e7 +dc01d85123905ee7edaee15586729c78ba80cbf3d4cc29e7c4721768d91f74b0 +78dc40eedfc6665b80dabce5a294589d38efc0ad1c81d7b58fa5eb317fd597b8 +8e97724b4458ea93d74d7b79a7a5b1b2074b7d943501b10b8c3657627fa0b94b +be45c51414ad28114b9c6626887ad30adf05ea3df88e2905231b56e4a14775fd +6653efe98275478150d5a08d18625a6b291fc6f5116c63a8534bdc15a4d5e225 +8d55962d7a61e96c18cf89605e2379dfaef596f849d8ab7079a4deba7f22d602 +f2ef87e5a2a1d4b0b01690b7717909ce8b19a54ccf71ec7bdc911fb8c3f30788 +a610f04b33aefe91eb623888dca11cca6cba72dcc43321c2bbb6a5f658098a40 +b9d962c6854b8c78b9c06cd3294f9981096f1e526bb86cfa811bac9f890072cf +848ddd43c8ab9188c36b4fd5b6360b43399f7cad276071ab18455ba51b103075 +379b99b974e614686f214a5a55e04df670536b4d152e80604106ccbf468bcb4a +dfad33b6b841f85adba987f4fb6744aeffa09fb1a245757acc966ad80ef7776a +640c23a470ea23435aa9e830a77d17b3223631b2207cd6e358e55e4cd351e471 +cee561126d7bef360ddec03b6797783a8b0db2b8c6df75cd837bd52aa7858871 +f4882c9054aca746c1ff72f683831186cffbac1f5ea41eced0fdc444b75976cf +94e9f59ae0f266e1c2478f93b4de78b8ca9ff2570bef17758843ad75aaac6b5d +3a72cad592b3478a3bc696e5233e968688096284da4a3c209eb293508deb183f +6158ab36e65972be5ed1af2a1f871a1356de71c64f24ba5f67ca448adee4e42a +a7855644b0da9d3365a6dac57740c5cab4f1b75888c7548a315e7b22b70129cc +9148351106eab6dc3604ad1daa6a4bf211b0dd0849ada9aab62120e26b8483b5 +eb3dfc37556006f8fc7ff9122ad4507d028a99f5404245dfdacac72551eb2b68 +a29815975c68355d8a0caaffcba0acf36ddadef0f9d3ab37387ebc8d06369a65 +d448fffa24a1f74dfefd7b80597ee1745350f555d8b8eedf507f4e77521a2c12 +3482d60e05cae64ba2000236f754dc383e92a98f30e671d840fbf674b550ce2b +6c269dc99fe9abaa5bdc27db2d34e716eaadd6b891e428638fd2976830b54a52 +63ec0dbaeab2169b887cc81232fd5b58fd9289c0381eab53bd285fc8b094aac4 +da0058d9d02a3eef8d32057c98f72dbf2b90c9776fc2fcd3c3d6f007f6310fe1 +2d101c5fc54bde036db20c6b755e7f2365670468b6a27e0ff590fb6250a1c5c4 +832d3eac27b10518f136471ed0b5f4daa36f6915ab3ed214602e94ee500652a7 +7a978ff7bc2c4558e0d3a96377171341f22036e9a4799a18be7118871c0524b0 +933df9cb72cf1f75353a8e57e889bc9f29320b3b92bff35c5a93a4ccddff74ad +f2370ff6e619cc9f840c1411b7e76f47444e7e64ad41cf524ff6f1445e315792 +48469e81c8c35b4d1f584693bf82b12fe513fddcb234fc2803060d3ece5c6354 +422d71252fee69607ff39008e6d5b122d7917b1c170c093e829d885583d8dc0f +ab88319ad48d292e2ece68ea6a7d65417ef5c1fb409887a6782f914d20a18821 +197e2e508e5444b047b2f6e1047531322397e405b56b2d1944cfba7da9d26ef0 +2ec53d54bcaf4bf8720fbd4ec0c515068dce82d9466fa5493b2e9e7109a76cf6 +86a5e9c10562f3dc18f31a6957f90a905573aefe9a73ee9de3fa1dca21843093 +abc7cc13b03a32b50de4dc316473e8854ae99cf4fc3f0e410c5d7852d2805b1f +ec18541b04404bc4df261b8024a559209cfa834e228fa86c4724d28aad9882cd +01426d285e86118f7bf6e18bb42d3cb5c7b021500ba0f4fae5f53438bbc4a6ac +362db2f710963402cd272afc56a58233deff36009542ff8911c26b13ed3f0ca7 +6b389a7298f2f82944416fcb0c0c409b82469f44b3f805094be740964830abed +0373b216a1fb44582ea16320184f142efba5a22fa171744b047d20b3225887ff +7fcf7d533d9c129dcb06e2fc1e9b16d3f40f3ff5d5d5d672ffd99a77857eeee5 +acd3cb3383c37a81f6cbb0c18d3d775d6434220006c4a0ce9f7185a0314d43aa +d8952f7fbfde2837aa3bda75b9d6ebf7b2c18392d88e69d791375064eefe5a57 +34a515f8c20ac9cc513469aaa8f32960cf474ba5da1c127a1de7a67059e154f3 +8cadb18f4efc5859156d2cd959c9cd997eb4445b4009a28671e671721af615c4 +1483da6788042bae5cce2beea9ce304ca1a023398861c0b642da25b3c2c1d4e4 +05f9c6cb068db23ef88a0ea5065c7c87df2bb5c785d2ed2aad41b0ad1e4aa8ee +fff1cb5a2afb8e855d0150c7389084c7b249343e33983e5c60fefb6b4f7c1377 +9bdaa5b4c735a7bf4b7314cbb65bdf38f1770fd2c237f71157f105edfad16d2f +b981ab8c183853414be8fdfc6d932ad4099b982e0b5652fb512a5908c01b6e85 +a591eeb68f682588444bbbc1ea13c84eb6f33966055ed4cdc17ee77ba5fd5281 +5022b5184510b16f909b7269715a962ba392d458280dfdbebc7a73d2ff313d75 +48660d43329ef8557c31dcd9441ab38487d20575520916f2ef2792b6201c88db +cf324ee5a59df10ab1916059770a87ade4842a91ab854338452bde766cf6e7f3 +6eb369321e2e26dcfaf0c0a96248f3e7a944c2a42615e9e0396b1fd539006189 +8b65ca9c98a87b843b1de982a16d0d438cad157a39a1992d3d8eb264a6ea141a +b0ece0a6c553bff1b00e488522e72bfdc9aba97e4599743a6c2efdc78bf595c8 +825cd9d4026ebe5b9f4dabef79522c5b12b4854ce541f3f550c182e2c394528e +aa2db1bde91755a832b2044e3be9dfdf989ac410c23811237b2cde8b30892ea9 +e458d40bda4429f830d98cff2f08f55c371bdc3ddf7bc00114b4579fac1149de +5c43fb09e4a3282fb74d1b83da12f95450d6372c2073db78ec6ff53c17a1c133 +6a89954a4fc5439c6259c60333a42abc61b9a670666037789cc22a29f475f1d3 +7d3b4a819cc0642e5e72cf632e4f1c7b9f86cc7aba867cdddce6403c7c708f08 +b93f6bf262aed94b528a5e17dbe3de222dcc8d8c22dd94400579ff6ec6ad41aa +31d6fe3a30e800ea6046c8f0399ae5e99bec18dce83421caf72a87a29020318f +cbdd468621819ee91c8b9f362d851dc4aa9a82b4200d9bd8600b44aef715d1a5 +fe6aa73bb0096cc0c43d38dd04397a9372d4f7b50c5d16b9353caee7f4afcee2 +24476251d9f26799de5525b2692fc9c3165e30428c91b0ec3b24b0560f33fe83 +10d2087e074afb21d1e46a715c4965a7f331e847be37edec5eebbe7a403f5be5 +89db8169ff958d3ce7bebced6533376d0d58374358a3f38fe526b9c27ebfe02b +c7b00421d587c644ff8bfd7df30bdc8b6a0469abf3aa29eb5ef062d4b0a2f6b4 +d510303c022560dc77cb80230ff5930b7c735ee79a4c8f2b8bf7aecb9d3b228f +65eada42d01928ffcff4e3b26066cb82dd1f8a6df7d906e418cb25cd0b4501df +e2e1c53d96c7a21dad443a7b05895c4bb29c3093b23440c6b27f89e7b8414019 +743f36e5657c73a673a9581ecaf6572223408eb1e2214c4d0de023ca0c793d23 +0bc08688985927b6a3c41b866dda6f8d0a1698d3b134d7323d751820d1484843 +f601d980fa92b066419ad15d750812d9664c31ddd86db842ed67a6b6dfd6f1c6 +d7484719149da2545de302898c445a2dc42ceef0d8b61480b1a8f5542f41a9d5 +1f9e7b647781eac5e670edd7b074a737e13eceecd70fb81e1773d4b5cdba5ff5 +eb92b4313fa2b80fe222960a610b640af586a50b427f0845ce9b7136686bb702 +df4a7b180715bf50a9865ec2ffcf7bc00019d755d3d895a7a1df59e62c707351 +a04e583a2c151e1f975695dccbcb93103be938d1cc7c557314c9f038b2883404 +522fac9dd8783a168e4439581073b74217c25d9c669af9b2420e5690de5e4db4 +dd5467218e0a9d9406004c2c5afcce47a9a0d5bb50d5ffaabeb1d63062bcd7c1 +8a19f453b9eec6f07748edfeb3ec19dd00a086735b5e808c1c2277645d2f6009 +c3fbd95ba28bf33cee8703a6ae7696fe5e92288c60c2e9ebf486f616cb0a5ba7 +2ba42f902bcebc0024a1cb5a9e7f6459e4cfaac41309a7f13e31dece298231c8 +ad6ee5fb3af0eaad887aff78343087e8d66f1501f5387cd6bbf0389f8810ca93 +b72f9d6f160af7313c3f3ebb638d824d9c5b21669d5e875deda8c183bb2db7fe +f0781b3f3f8f8543f788780743e4acee084ca9c953e301a11282f8ac4a4b1987 +34c7b4a12b71c90a451e4f4fe4ab4415746b58a8eb5cbc71a4c36ac9aa5603d5 +c4674a650192d3d02fcb2cd9b550a41e6643315bc104bc83c5820e070d5df945 +9340435292a8d442f15bc10fb042807bec3ae61407ab6b1a3cbe886cc5a9ff1a +ecdf66ca409c6a30adf223adb3fc1fe69a79232c9a84f8f01861f29c1a9786b7 +fb53caf49ac30283cb89ded2ee4dfc6a3a1904858f0e96d0b2a98647c3cb2ba5 +6fcf0938c915aada786909cb2e7c3b99d46f35cb3b27e4423376528bccff5cda +04ffe6a81508044012cce2d4c02bda5e7b39d33f49d0e6f7cc7ae104ab6ae1c8 +27623d799e747c80a3fb7ec6abda7eb9b390eff99868e14661a726732c9b3fc8 +0aab129fc2d323bf277e77aac06325afb97e2fe9947b05c9b74ffc47f841decc +b8cae0eacacf7479db857155ff892ba6569ea3f0dc3976715d5d3aaf77c89894 +84281f1f60726acd09189ebc770bfb64abfcb3324a9ace1ada3347daa205cd5a +d156ef5ab9b602abf1656bd66e769cd6ea3dbfc0a167d59b223d31c9c4724892 +c46a73a6acf60a7f4d5067074605879f858af5f370e3f1b308ed2ec99636d8ac +26dc6e2f856b2e95d1dfbdbc00f52f27d3f084f619ad466acd67617ddb734633 +81969e0421cd4b124d41b860163f5a83b63453285af0709e6a9327780ada947d +a5a66b3cf21177a6c364eda796fed24363fe2750226c6229c267bf642231de00 +a8fca4f2c5ba8aadf2f4f68e80ce6ee2fd39b53463143e8c10a6bc16f1b3fad0 +e5d50612cd6ab2fb46ced027fa36285619ec6ae6b4956bdacb58e158f36fbcf1 +5afaa909e4835ea7caef56fed31cde6c3171244f336d2b9ad7bd07d8a36a09a7 +2fb1ea84f16f828393100b300bdd38329e2d66e5246a5e5d701e920e4f51608f +7d1f828b8ed7b1bbe1d1dc87f28d42b505f62439ef5c5a4a63011803e74cae57 +1cbd1e6a27b7972e25ae9fb9234df9dd084e8e7e0c2d81c0ce87c4eeb49b552c +76db7ba39eebb3c65ab93f311ca713e4860ced0f4a6e15394d9407d41a685fa8 +0cdf48492792e51eaa4effe570af2aa27dd431420b6437aa5ee12d75f6fdc0f4 +cd66a6629d2416eb6a4d3d2ceec1d26511fac54ad49d3f809ef36666be876907 +5ff22443bc4d55ba7ae4c2a5f290ad188f6b23de1fb8416cbc929e57c3dae7ae +28d14a1048b6385ced2f19fe4f465dda8fd1d2b2e0a4cff6d37ecbe8aeb19297 +c5268bb9164bdc03d46cf11dd310fb01b7c2f40a3517f055ec362b61ef9f0dd0 +544f9303aa997af6d21dfe2285c6eff48bdaa1424ead80198f41b294273df710 +eb9e8866a3c6fb02340d40bd90f535d23c43f29f3f8fb3c013bd69ac24f07386 +894d32aa34698a8c06828498d0d89812421ec61ed479bfb37930171368fc1af6 +7ef4abd9bdc9f67acbae8bb3591a62516377b9b00521683d6ff8adf41ec14aa1 +e122607c80d8d2a53156a386d75431161c12107edad2a037a7afdddbea746294 +db3004528109f0199355876227f8d23498a1c100444a2996e51f250ca33cb9e7 +edbf148ed569d58128256a5c1e0d62ba8e799c5e550b3b4358cdb22dc71107ad +37a841406ebe8a83ef73b866db04ebaee9cf0f539d6ac40875ecae23c5c84809 +f21006263fb455d2377e303d985d2649233f59b3b6549121babc14c516f3728f +76bbe906b6dfa50697cc4b29c8bf0957cfd4052fec114df59fc9caacebaafcf7 +8f4c5da6d156b406e973d1cb038132e6abb0400bd15bfe2e4ba58a54efdf6d06 +13feb1bba09de5b4a53b1acff47e78c3fd8016f250d2dd680f623a0b87efb2d7 +db210ea39847f399719c29294b0e5812e2046a7bbfe8f4e896c8bb5840e28f23 +b67c8f3ec4ae3d718a3807aa24b58fe96ea8858f9db00677e9425067bf4ae9b7 +0eec71acc2ca17ff77e79626b0f0a421b29e20872d6760e70c9688a93b8a625a +0d2d677e18ea7f72014bd01e5c35a9a676059c7f8ac5b2400c9fa15b4239147b +0e90028da2f97fbf809c2f653396d4ea3ae0df39032d7059b04ca99797635d40 +6c269c7b410bd691e6d31244afc9cfbb56a856768a23de6ae713cd424fb05b97 +f241bf91ad7ce093570d1cab605b81876aac4acdee766ae1b15881ca15a64422 +cdf79fa1548da2dbe428a0a44089f615f803d5d67668896a925e1dd642dc2178 +9ca88776e0be735661d6f18a30fd265f84350637822c552bd04bb42f94ab6f2e +56fe57cb07362528840198d974d899b68745ba45f6020c7db39be906309127b8 +38f55a1db974663cac6705638847792468d82653de9b753a400fbadb00672c47 +94f79b9c4542cb344977f3ecc7ae97419c8315553fe32e4970a581f85377b2a7 +c4a2588f828831c14892cdec389a30494c441114a3d2410e0f3b9d327954f42e +04241acc05530b9d39974661ae420d59346107774193f4f4eb5baa8746329010 +0a1310531b50ef9ce229f711673682557e068df7cbb23cdcec366f0ecec8e91c +f611434d56f5cabd80a453c8f458184a7e46cac66ff46e8b84db5c8315dcb575 +a951f66af979952017b7ddaea757944155adcf2dc4894b5342e51f6781ca8ec3 +0f03fc5f95df5260572f411c0086e1fee7752a7cf74141013695ee7e62ff1643 +9c0e607df19ef295964a1f75869424be8bde0a6d7b7d177a02a56b5385929317 +2157a55fef6dfdda3132d8e114013961ca65e071494b6e4aa42d6171978a98b4 +ee454bf44c60f04a867f4f7e18fd47623a377fe3e903516c2f1bb2f47f6284b3 +5f06eaf3ccc094fb448fae58ed65c40e3134353fc8f97ad65993b482f9c0302d +b5f657b1ed54c3b2bf33ae26e0dc6574de706c5390f896f1c33f96d945743ddb +9838d38c973ddb867f6b3743f63f61815615536c94a1819a9c9d0f0ff4338e35 +0afcf6c5677b14206e2a72033912850aa0a6a92c6059ca7b3a369bbf776adb67 +f21d9d637ab5e91ee6357d689f896489a99b1ebc1d69a2a743a901d521ff46fc +e67537da6d856f10f7ae3fae3960154552f69d0114abd421163956fa0579232a +5f4e9401b7ce116464136f02f4f8c21e085e677ff3d1c8703164d6de9e2c257a +00097824d684ac7039ae06b600b8bb77bc253c937a0d24186b811da960673cfa +1cf2f72ba4a590f4423ed7783590103c1a28d7ddfb8637901ab28249055d84d7 +37dcfabe237113fb8f4b9613a4a80e4d6fcd087885f6a748668c05c765478d65 +1201e5bb6dd32be5dccce28c45e28557dd567e19c806af41379951d0b61ac880 +4cff6a21b90018316e3e882ad762d30ec245ce0f9fb73f7da87bb2561edc787c +51a01665d3a3b72f07d93a50198e26a0276e639aa863c193708917ce0ab71367 +5ee73c936f191cabcde7292f8cd65644669126db403c1f7e6f823023b8ca806a +654acb48083ddad9e4703066c97241569be8284bb678dfb63c143bdf5f7cb262 +c71db77333595afba55aa27f4b0073d49552257521519385a9642501901d89e1 +09754b598158fb7005591cf718f41d75e374591b8b6ce6663dce1c4a73cf5b74 +f260851a02ba9353ae7940e4e8a8c7dbf6f64317aaeb0b21594b1c51bc17f12c +f56bebcc7b4b106cd807a192029b795731cd640b25e126961e83942150c07e20 +bf989ad7397d89ebdcb0642049984eac0354df9bb5c325489a2f996293a9d8d6 +6060de01693f32287765e3a8bbc7831e61aca2102ffc7a1155eaa9efe2ddd7a3 +7c559a090c110d73d7aad4ac17c8b8b8449d6d9a2ac0a6896f4a9279a7571756 +969cefae2cfa3f08f1c5ac8dd1106d3211600398c6da69854d020db9e58b2724 +74ac37e6079cb50c099058a5e83f0761d15cf673bd880359e32544eed514e11c +c841b65943a50bf9271d5697274354f10680a00313e1da9786363429a667f8d7 +632b7d7881fed5385b7506b58b9f48551c2496935e30feaf64ca14831e043e17 +457a65ecaf6a895f4906384953ae5591224a63b02fe8f496afad481593ad1fe7 +9df36a154ed7279efff538199784c56b01170e774e969daa170356d96722da1c +8c83a5428f9ee6ba36d02c98f7f782a1439c76e43ba456aa35caeaa05cba9036 +40f14b4021f3316c80dbea37f2f06c682a0cf8646815ca35dd80036983f73eab +bf4e70fe5667b837f80d63b55bf146b01e51737c7b32e320207fe54f8901b658 +1521620ce9c6c9c3001dff058cbc8dbcc351935427d55ecb8c4186b9f10aee96 +c0a6e0067dc47195041ea8182d00729345378116658c52d463930af6aa6e8860 +e907d5bfffd00f932bc08dfe19653f21bdfceb31d1e52e58d726436d188543da +76eccc820cebb2c4c57b5a56dd840a1a707a68f0007054ce99b62f1c8e33e7c6 +6d6769270dc4aa68375959465ecbec267b9083aab5ccfc04800f09c65e4fc7f9 +6f4f74130019671927846f8c6481dd00068a06c150b1c4f1473970f0bbea1e8d +ace07db3c7a015b9d6411045e1d9b32c4442a98f273b5c135010133320293d68 +cce3e0b09ca562dcaeed7ec63671245c135f3e654e8470536bec7752fdd69a2f +2f266cd2f2d3d8d148e7597d98cea4bee9e0bea9cd0205fa0beaf70c929bc7f9 +f1aae48d433cd33d8560d157e06852a2d2b84e97ebc97bc2b1b89ed3f0f4dbd4 +00744ff4f45fdbdff6f20a8cb4ebfffd1b528997a65ad6d3b2d3d36b7d8378d4 +79bc038ff11f10dcc400d558b908def2ae7a97d16a56adeffcbc2a8deb959cb7 +07b46299345f12fc8814ea03389106c44ad7174855e0b04c65937bc54bd327e2 +010dba393d15dd7ae57f6bd8409f825f3280573bde655dfdf8955836c8f95570 +e42cfb8f6188900b58611cad7281e9d6e3cbcc9be49df832b30915dc47b4504b +b4e84adf58258a663dd5113acbd9e869374495b9afed7cd273408147ca7678ec +ec0e56a445f10891989ea42a0d0cd4af5fb6f4b74702d40d1f761d31d06c317c +6d294627f949d6ac7174c567e350fd9ea42f27579e5caebae7de99b245189912 +0a658d4d85b5897532f42200ed99f706b0ec8e752c85209608e5bc9dbb85b1b0 +5d537d7e28da0f5a44e5f3c5429e81a73ad7f13d4e759bf90d72caac156d25a1 +e7d6c515ac84322a5f838b8f480cbac3696ca23369e7bbb42665c6a1838c4051 +f68a3339f224b701478f0813e44ae3ac48c0304cbc2381e19c34670c11c2a39d +8093fc127b43e051cbeffe4d63c8f1562bf859f50a35b68188b997d14466eb9f +5d9dd88f8433f56d335028f2702239991869e37faf56d99101ae98d8f62fa910 +39410345268534bdadab8dbfdbfdbdd51ae14feb4d0cc5bc500dd406d686fcf5 +f9ca023c35088ac4cf100b602c150004e6d2658eb596e9ecac008ce6638d4cf1 +32e5b80d2d90daa7d1f27ba6c944291ec385fffc9603b5226913d8fe4898ebce +c9d0b566efef3c2043797e36e0a4c0fbc82c06ed05471828e064e81c4b3b6836 +2c3d984552c7bf3a2aabf9fb1209470165e954b05d15bf408a08b8ddb00aa238 +779b1e8465423cd18a343c0fd9bc4fb15930e8cc0d7c2d87efcbd643c1cda935 +d4da58ee70d6de5b40d50dd8bc2ed1afa53ac21e54302db9b512563b1155dd14 +996216e3678fb993cd90c6c79dbcc49236a4429625571706362a82fcfe4e3d10 +4ec649919af52510cfa10667ea18983ff60e742fa456c2b27fb9c8d6af4b6cb2 +6ec4e668d631d60c246b393e367c8d384cfc9d469360719bc9fe0fd06bc3fac9 +94f6bca98cadf6ad4b9781a8fdc8d19b598269cc58ce04b6181b5b4a0ffd627b +904f55609a2574fb65ac84856daab3995eb4e956a75fae43f396786bf2935942 +366538e7db1651f3701ddad24266cb805b8c6cb20da1f61d8a694099aed73bb2 +4b464b098abcc036571b0681eebb40f1e5f613105126fbd129e3f69fceabcf51 +0e8870dbe76818e871f743262b06e4e8fc2415f2a4b873fc19e920d3740cb006 +66742ee99535ba94764eccedaf397d562cadb5a92f8509c9f3073948a5337dde +bca7643fed08e3c9fe7678b82ea70f98c43a0030f28b095e385929c8f7c795b6 +d43d4c811a4e006f5df52a69b2a155a0f40454bf6d2a01473bb3b33ee10a980d +04959fd4b90c70d71b317b5e753d3057404f51b192b96d3c28e6f5be7ecc2ddb +e05c957a822d4b76c7d86ff7c77dd5a2c22563cc0e0ef565db5aab296e15e037 +952251c2dde36d13c25ec536c084f3962068bb4d40e40bd201ab722b9586246d +2915e2ab7b523a5c4eadf47a0e11f6e83f31ed5037df2ced3947922e7e3d8faf +aeb14fe8a1b27210086d0b7fd36deaa11fe841f71032078e7e4fc25b44dac06b +3a623bac695c5d5a79b274d667dc906191328fd2e09306e2bea0647e2ffb4c2f +7640149924257a7df5b0740301fa4f85e0dfa195525637cfd07325dd8be081ec +60ce360afb9b688c9827592ca27a6c3cc2c9f415dfdab067fa12970a5e25d3ec +15f3cea6cdce1c8ba2a8a2b1fce6e4cb2ed598bfe44c2c052b9904d545951893 +27a1c1fba95ce41e168390fd02d8b559fffeda5186b7fe8d891954027799ba27 +7fa8092c5813d0e21833489f546278a5a9bf71c7af143390cc88c6d8b14493e6 +38a2e03d0ddf5f9cb0867c0e440573409ec67b365a62bc863a51216a2619a77a +91f205ad22f12130ebfab1d150e3b8ea97f0fc829c13f5e2d912d9b450430e3d +e74c121c7e7ad08a22020b33f97762e10e9f0925152a1b6545a843bee73f9ea3 +cffa6f978debc78395a6a8f7e3ef10e1cb3cab5df123b4b987d52514d9ca8fd0 +7b9f2b93401470975050cbb71a47653522268ee55855564a7c2335f3a0be45f4 +6108e326dde921ac0e8e680940b68b749a346caf656fc6cc768ec8e8ac1aa102 +285c4a78b304504a289c85a8b51ff4269b0f082beac3ef4c661cd559f7d4d7b8 +62f0db04db2c235cb2923162dd4215e6c5441c4d9a01dd149127ffdc8f3195d2 +155b7625d0b1dc74f506267852f4dad5a46e763998dd520f4cbd09ea72a33e37 +afda1fcf20778c7875fe6c5f0b8f57e15d564dd1d8a98a964909c85dfad1281c +d028053816b6d6036b34975c3c4df87f234f986e5d304465cfd8a8246ab5571e +f173f88e07acafb91c3b5696de510b0873b009f65a0dca7e2a27699af3f69f8a +3b50876038da3bba339f0d7f29f829c4d8b661d8a2aecd0463d1373fac89235a +32a5d2ba0df86cbb3dd83328b4cb5675b42cab2a81eb433c82ef2110a21e2899 +fca42f648390eb6ec78e4f9007165a3ebe26278953b1c9192fc18d00958496f3 +ee80722ba1ade5d06c137731278d7b444206fc3dea27304b9bba5bbd55e20014 +be933254922bc696875490ba0ba1be684696c882b17df50f91ce91b9fcca0750 +18eb19274ac1d09c7f785058c66046b5a19498a5b2e5e4c0e3e0a2ef0481924e +458ca80cc9dcb35365b3b3883e964bc3f54fddf81047bdf282045cc8da8b8007 +2dab1f91c984a845c8bd82f7dbe8025b73d7cb40b4abb46fb1eae583c465e396 +0ea5367f6775bdb872652641fdc54d7ffba2c948acb8b2d9dd77e496e75d9612 +315379b7ca6a3d5f769fbcfe39107fc4918cd09ee4d3bc25dafd8db133a0fc95 +f05223693ae11f6a021e0e79abe6d0db856c22d622be3d70688b027966091b92 +1d9b1a5c1d3be76642cf95975ed9263076dea2d81304447ff46ada0e0379dd71 +33af85299dcb2efd6dabf1414f978e61f21cd39a614808c1ebe6e729fa7ec7e4 +91447be7a4d6c36f90d6e21fd3fdd725041ca440211e2d6d3083de73ea2af310 +eee95912d33390d5b2f79c5033ffd56b0100cf6d034981141e94e306556a931e +399aef0c60c30a27d70ce8cf12859ad31c61632030a177beafc74d60c89e99c2 +ab1e21834d219a6df33f7bb34924042cba8b6d281567ef200236a5ed9d10c8ca +f6309789a4564a6ceb8e416c0c618f0f1050c1abd46c508e50f492dd9f701399 +8faf065384e7ed1bbbf7f36a60ade6779c7e0e9cb975416a35f4db5aeac80ed2 +8453ea6a4d5d9fb637970054be3bff0145569b4df59dfc90198b0031a98df35a +d9482abb2bc4f21b7d66e56f405644468a6ab11cf584cd51c99e2b45dcb93748 +5de0c7009143e7968fadcfc0a0c377c71d268d54f478a51a959486519ac533b7 +45cfd61a1cd78b7818f2aafde00b6916e71eaf4c16bc30c9bc827fbf2ebddaa1 +ab4ece7b615760893ef8e812420de0b4ad7ee7f4d071668e7ddf982022bf4b47 +33715cf49c38bebe62676b0cb5a6fe2f9c4f8085dc284d6cb2d5a6d8cce86df8 +94b54c597fa4b07b54fa8dd9b06ea932b6c4892536db3ee3ef7ab77253771354 +0d1059141a63cba7a142fca31a6469bcee37cde307d1386aa7ebf8cfd9759baa +971657cd8844a5775418c80e2345859af0f6f35c3aebe24984700e2152e048ba +651e141c5c842ee48cc52dac91bcdd7ad7a42d4eb0acad637b05b3812fc82ef4 +85b29834050d00621f15b93848a4ab7c72a280072719f5e2f6859f0d90d735f0 +973272e1afc18eb949fe512befbdf7bc8ccfe36b960a801ad04b0cb5796ee7aa +295ae2a199cefe0798cba8db2c8f899d699ea1db395da2eeca6cb8b6d1175807 +d505d30bfcd2945a2771f19b24646cc6770599d1eb36166a7e5ed2048cb7d85f +c3d6247ea0a5362597c70d068de4866bebc494eeadfd7a364abede29e4b1bebf +8d95cc577ef8b5ada814fb528c114a45ae9ffe3ef3582105733c55aad2e5aa61 +4f63c48fc143ac3c3b1ac6c650616cdbbab5d146b6018e1a1db578960acdf0cd +dc3ebfdc1394bff9692522951dcd7628c2dd53b0be6128282ae7e9cf09262271 +978f4b9caf91cfa3902c6de36495c9c0a9a297ac3f80a1f3b8cd60a3c23d3198 +14b4dba8b486afd722509824af735711c9ca5294fdfbba458b7ba1d211aac6ac +29019961e41868cac2693f0b06a791397410c245c9a1f43940ae75a03154642b +6daff9e14d69148d2cc19a48836a531b745c8d90d3e04f744bd633f51e2d5a2a +31bf683ad754011252321c0e174ce5ead609769f8562db00c875545cbe39c4e4 +613932677616448b942aeed37c80b1782e52cbc8bb3d9c0ea9257fd8909b6000 +667d82813fa287a7f3c7ab7fdf28302b4918b560195fa4d3a83faab8791ecfb1 +717ee75004a5b923574687fb7dcf5c954b9a48841e9dc5fe53cd0fa928b82b37 +7d322ce8156e6079923335fc62111a2be855279e6e6921dfd86264da7b202425 +9753df0f63b559e34063928e9eada2b75c460a4eb9e3cff6dab5635362ea3da5 +b246e49d838dc9d09554af673c5b6e891dbf0d86f8a7e7f2324e58a6f00f5479 +8a0b57c5e2b6d8c1a449ad54726a80129a6671992618f67c7e2a104dbc0aafee +a6141921c0b47cf70e09a3b15cb9d6c2e47eea8586413baf1feb1db654590c1a +7be44030223fd6049f3a57c89ecea20c0bcd410b068151db8ca4dd3bc63ad81f +cc5585eabb8af702b77246e7c83cc718ede988a1e6d9cec87c9313d997b6354d +aa94e0fe9a593f330e1c048ff88e64b65d887ef751b61d87626c4b4d198a85b2 +727feebe8f1fc278a9363c1efcc029d79f7e7fe6d7271fd369821f550e5f9910 +19394c90abe3ae60ee499465c6b74b478a2b9b53fae6d5789e6e02155f1c6977 +c313665911c8313c58cccb43142247f668ef559b683f0d63d5989366ef3bd4cb +50528ce1656ee3c7dbe5964bfe01c70647c313737d650c69f92e13a0707af3ef +c6ecbfe2cb53bc8146c06e1a2351cbdb53f33c97c200a320c38fa7e5cf3b259a +029b5fa36a3d2e233e9cfdd13f53f314e153371c3e798657d5177e68d5317831 +ec3dc11334e391054895bc10638feda8e99cf50152db0cc14594b63ebceca6f1 +1a557c1f003615b885e856c05b5af1cf069dfe4fc442b7854d9acb198186aac4 +123da915c1350874af50f565a6a91bedfff77d4b85d9c7d35de6c8198b1a8c76 +44c45d68a3081c695eccbc537893f00a9622f271f45f16c8294598ad66841cc1 +414c5323a698991b4bca480b94d2b4bc97b683fe4c16a48e72f33a3ac45ee479 +6c7371e87f3fbbd8b76ce121e6f532a4999ad057304f0aa07d04534b0ed1971d +e41f667017c4a3f305104eda5a720970e0473c98a3ea718fa0f8a699ad23ca70 +e900f6dd876968a08886211bb186896595743352cc2f818093d9ce2197c65a32 +c44ab74f9951d2aa32a5e7d7760def33043659a416feded2309c10eac41eaba0 +4c6715a7089cb441e26da41e96bd7b5c2afb1e17da4e73a53b28e2c70ad4c352 +c5b41aff3846a47232f01a04dd64f121503fb3234e17ca658a0502b7ceb6d321 +8d72c7637055a820504de49f299faa85af2969d5ecfebcb7086343419c2e2fc1 +83b528a6fe597ee8aec71f2a294848ac666b4f60604318a9359d696e2c3c94fe +a770252cbf2c18ed6e7831fbd276a6e450c55f48a9f757c9f6aaa0c8cf07f15b +4cff95fae33783885cd40e8442f622d21d294e92397cb249192c5407ecc895f0 +9d370ab7d09256aa6ea9cd8c65f65228c66f5c5e710e0460f9bda7913720ea6f +8e3a3fe8cf7cd88b1dd893ae1cbe4707228e830341bd7d607390b9d98b5561b1 +c76b574d7de022e0fc7b711b5cc0af47483ad66588ce0c7f113da8831e92c8b3 +0504eec87841218a963e68c87f3ac532d398d5a3f0d3e4844b76cd7f33bfa2b9 +7a70e3875bb447bff00f0ea05e3268325b2d338b51c38124f26d0baf5ed55104 +683c015c3867121a7f509848b76f337a3eeb151ea3bc05ef80a05a001bf98a0f +297c6a11bf681bcdd6fa2d0a7358fc1facf7efab8f5b75c6dccba66cd9152d51 +6617b03f5c83becedc2afc128d86dcd477fa238b7a0273ed33bff569a14ec0ee +77541970c0d461b9e10d802fcf76396020f56498f00bae13af9f8846282e7eba +ef87e4b34d4c5ad1077f01a885e15e3fd7536b81b51458554153650c156f45ee +0b4fa1b424349bf9fffe92fde83ba8d938aa1d7de4bcad2e0a4229cdfdc25a66 +10e3f67ac33b8c4f65ab3d629c25fc3878fcac0903b162089dc732a6db704e92 +68ec3bf58b9dd619176ae01b330bd183711096ca5992a78be562bdd4ed834e28 +de5e80f4bd5e5e3b41c6e277c63aa6fe2828fe2d0f378ddcd94491476be3845f +c781662ee1e2e842b00869ddfe1f1e843c4f65d467c589568e544ef8cbfb51f1 +abe48ea264671e21cda126d14974fa63defb4b71e0ffe394a12d43b36731bd3f +ba45c47ef6274b4444065d1325d9fcfff286447df740eeb699bf2899aa126068 +1d8b7377cd6127552c817e13302ed75be3f0558bc77f346a0393f44bc442fc1a +593a8b8e771e05cdbea7e5ae9094ac1c6248824b29c3bb703338a1654c4f3a0d +cbf0cd7a007f3c4dd34b7c2895d83e2a3ad0e6276b7e12b48b1682f67aacfdd2 +4db204a48b232f7cac395035c55eadd6d746ad11eb94d19a081c078ab68cd222 +66b64ddd33bc7d58dc9b66ffc408af85abf04d425ee0001af5fe3e674027531a +91b46d995ca27863482cfc14805e1a7ca2553c7553fc96fd1f216e2b997d8aba +f266ad06df327f3b41fb642178ebbadbf8b390f84ea53de59d5986aeae9c4921 +fda47166940d87e0574e6305f83c086918549f90450cf6512044a4368856febf +577037212a37193824eb1c06d1b8ba4436e14a6438be0bf8bc114cbc014dfe8b +c135e23b7aee07e8f190eeb6aabce271f2522309b50e11a68fd55738cabea025 +f0dd875c95e90cf764d092b8013c795a8aa0cdbcaf347883beebb8bc567ce652 +3b8c428e83b05d900a4f50a5cc9f0a624cddea2f3324f8be85feff5d2d703597 +e878cd39c11df0b788f3947a939d8f17ac230a41a597e93f7d9b9e10e69abe0c +3af2a637a03a2ecd926e13676c639d6016f9b5ef9a292f753cfebd57baace326 +0536fc20d1a604cb44facfe31d586130dbc2d909fbce1a1f953c319ca47c67af +8e350891f2dda914ae0e5d65a13614329fc03ca8bc80ca5ab04c6939847d93a2 +f103361944b6966d0527c9758271e59c9f5f62b6580e20ed5d801c3a92d0f398 +27b8496f3a42ad6cc504ff2d4a393f155c71c3be3e5f3c484a6532eabea19e8e +b07dda76251bc96bcafc3464d533bc8a1aa75fb2de17f9721a15c3994a3cef8f +2d3e06b40b5ebfadf8397a6beab47647a38dc77499599227c1ee4e463273b000 +dcbf1ac67d45952837e67f2dac0c4c58408e1e60840f72afccd815b5ba821ba1 +f8f569c87ce4187323d30999806fec666c6cea1708d7fb71b7879cd278cb2f8b +df0d5cc79c483d9d2d767dff1aa025cbb9f6136b01e7ffe177c05b0219d9b34b +93c611f1658624c01f3ccbf966e23bf1ef73ce21a20befc6c2543cf2bd1d873d +2ac117ea3ce7c2f6a7b5ecb2e6143768395f6006ad23307b33183bfa6f6527f5 +b76a908191cee08a03ab99d60605eb5804d9d9f5d4d8838901431bd361ca7561 +67eb509b1927377aace3d4496ef0dcc6fc804e396e0451b6ae384c3652f9bc5f +3b5d0f3b9fe9ce74fc0887e965fc7573734d6e877fcd5ed87710685dad834e21 +db5897ecad09ede8e09bb8e82a32d7279e86714e6f3a158942d463b86fe77d90 +9ff70c92d3e834500e3be8628efe168ab2bfecb7d0d0b31668220af50fe5268f +9f18a277e2434a6567f15a29999d741c0d8150edf67e8fd98d0c2eed5384a91a +28624fa84f65c29f3807afe1e0013170832c4d9f3c9faeee6c19c87ad7190f22 +56afe531cb6e2ffe4be283f3a9f8bacdd15defeca6952f73d2ab087322edb7cc +6e8c617f373f2901d5648c9f4ab5453458e4afda1f03e7f1e2001a317454b09b +bcc9c66b278c96d28d9bd487712afae7f98d4836fc49583bff8525d0f237ee10 +8115d1dcea1d23a30b3252b126dc152ba45746d64eefca4995afc70afc07e968 +e3b6e1ff0b1ecd5d17c5e91f17e71f35f63d67933734639ac69a21358ee67f9a +a02a016f8066b327a1496209158b24adf15496a8e6032789cb9efecd1f01ffab +0bccd97e1d49bcc767025f48b158cea609ab69a6915ac7a84fbf5714cd3ff87a +59410c3a575db59442e9bb0dd0a37600a5b72080a95953db037559dc937aba13 +73a2ffbfc2169b771569af80991501731d305a01918c3519f5b2c465fab12b3e +df490649b155bf33fc6fdee3e0e15a11cd7c44c89eecc11f1c63615777cd09e8 +b62aee5a083335ee663976ce38afda2d2003492cbd98841e91e9dd17800a47a6 +e2ad0c9d5373b8b7e5f8b6bf6a8baece928bd8431869a064068a117b0b38e216 +7924b18677bcbda065eb1fc623672ce410df8a0568fd458bd0852120e5853348 +dfbbd336f108a75fa9e4ad1a54f126a8adea3d84e2aec9674b2fbee722c5bc5a +8b0cb8ef7413e1797769493357e9a2877c82ffd1605255d9f05953d5457d36d6 +e7dbd0152e60c43fa4ca430159661205bdae357f2c3c75ae49b9210104e1badc +62703c20aa440027c87de84bfd62b9c130d42467cdedb25e5bbade8dec3bccac +3701a6493a6c0ac8b14686ce0cddd6c51d855642bdae93cb506fc8efbe9f9813 +ee78e27f8f8036c29262505bea6e9c1f630e2117726c41a09ade3509da5a10a8 +e63400b24d39e555b13720bff02a667a885a6eaed805a3f3802ac2a5a94883d0 +b2e85af538b011ed65b8e8071b9881b6a40a437fd0569764589367f446cf3593 +8c3151f57cceff0ad9d49927ba1bb01edf54d830bc2311b90e01cf2a5437ac00 +79adc587e08cb2e23647f759f78e8715ce49d09176f6059be055cff4a9e18ffe +973bcf3669cf962a488b53619ccfdcbf90669b7fb463194d9b40d76ba3a08b24 +1a3980f79a00c95a165c9233764057bec2f547677a9e684e94b27715b7d9b01d +9dd7d27c21e5e694347495727d0c2b1a8d8cb03884ff0d3601c84031bf066224 +6eca8e5b069c1d27a9cbd78f5bbf1868ea0784d010a517b011c8eeaaf085c25f +a2e9db8878b0c1f5a57da214e2fb0be0ba253e2855c12e3e4f2c501a77e00aef +96a415847bb8d637feec3e4a6dff18bde2cf7bd68ac25409cd2db51fc7c82f99 +e6e4beb7c2c911e54ad38a697b4a3c1bb0b3908d9cbd04c418fd01be783f36db +523ab9c936117ae838b84d01da11f3c3953fb9bcd2160f267c05e23d190dab5f +9195665caf100962fae8f5fa5d0254e6d2072f9ef126758fda77dc05b707ce1c +d4716a6ceee3509c81b0995c9b4116dd870c324007f1b210f9dc59738336881a +aed14e54cea71a2bef9372f283d6f02deaa53154037cff97ab2ac90c112bffe7 +fed02c45300faec179a1817b0573f2f0de281036ad408f652cdead7c07a6451d +6cf622482fd40b855c146344dd3ee36b8e070d2b4eec1840574d9f065888f380 +57803f2fc1a360356bc2cc0a0108bb8589d3a4a7f4f5851632c209504c169a50 +4b8595ede35a7425e54ba0b6d9848ba56fbe5282ff5078666465fd73081f245b +8b78b51a643ae01f1fe3be1a56c7f98e252343b525f630b23696cf234e467016 +9487b2882ad3677cee7a6668e33b92ff0e18eac6d94c3b9fa5049ce22592a97b +0bb0d9e23c27cbd9f52a3e12cefcfc6458485902380755c44f15007174fe2212 +6ac6d942943540e06623c7db8173df192a8a4d26bc67b5cc8bdf2d0fccdcbae2 +87ebd6b8f8eb0427dd0accaa734b87a00886b17866870bd83f4f3f60bfd887ac +99e6c27e81ac69017dee5e51233d3c80bc08d88bcdf9388115a253df204b44f5 +8e1f42a35c97a4cdd79e69184c7c41a226e0de81c379c61d261d2336a7bcbc72 +fdefb7345852ef3d03b3b487e08b5664685449bb52815ac45aece47ba221d83e +6715c0c36d09ce53ecca362acda51309bac376e2777d90a1e7706e5c62ce2745 +c3825af3184a784aaa0c8eede1b4d2556a98d58dfbf696a04a69e03fa39e0221 +6c3d8c2735f695e6855fba60d90df76c512f755131141574fe367df968cf6acd +a495c4a6277ebe98573c28df19c70579facd3f0c610212d3aa2ec110e1b20555 +a3790153afc9395b43b8b1fff9dc94ac0716994b675b93dbbb174b646fe5c4ad +0423cfa907082c8595b7e32fd83a6c5f2413c94499e8ff3717b3130a53edaccd +e664965f0fa5e4393832218ac9c29a82a40082e0cf00e37986eeb16bce3b77f6 +1f48db470a0e687dc7ca20ac3ee9d98bd467e60ecdbb2e932e89f739462b37e1 +fec2500f70e2e883e3700223afcba7b0d7ffb1ce48cdee1aa219bb4db47a2ea7 +780f89aa8e3389a0ced580def66c376ddff84b2e16dcbecc711af35e2c1bb346 +ba31a190ccbaa1e36361194bff210a673d9592371575289a5ef9ac0365529283 +62449227a300b7c721b2b56a5ddc1dc93f29623a019d1ac5b127c5bf4158cfb1 +f7d5c20469f123c1e703921bb177425437fc488c1a011c5f7f926641f98c7d51 +8e955e2e84aad48d1376cc6ff6d9e6815ba9f9e33b408fd2a15a0b0763765245 +e155ba93c003d301c454aff22b5ba0b10a5fbfbcd51529dd0895a5a4e2ad8d84 +2e5f2373823487d26009eb2717535824265900bf55c0fcfc37973a658ed14e47 +8daf93611e30fd2e5328203071cc4e264b7927b2002c79ddb5ed9332d8da0d94 +993005111c0f4e0a6e06d917a59be6649f96a1d16c6d5f6cede84a85a8be2e3a +94a77bfcb1ed95cb7ec98122e46c991688f48a6780109c9951fbdf7e52ad5cea +ca1d232c47457d0d08d00c205fd7a091cf36a8a761c65db7c24b0e68bd66b83e +184f4ff5ca6ea83d1fe3c2926097c119a48494818ce44909a66b1bdf427d1cb7 +673a556791810ad274b8b67168d806acee7922d362c52fb3b11939430b32b5ba +3d0be02fb1b7780e1aee35a314555756163951cf37b46ca822eecf4cbc6763d0 +69e00944bbec453a8937cce17a80704e9e6a691dbcdebd2448cdb5eb1b8aef4c +8e989f4ee7f6e66734d1a7a9ba837973c8c176f0d4234f5fae6b0ed6ba856c5a +67c45fa55bb67b87315c216c76398f039a83502ae00036bd82aab2fc692d8f0b +a6ca4a8021916f9aa3a383ff3acf383f53d885a49365ecf23ecd30f2bd204b7b +5f9d6a99759d8c9c60e10dd037717271423dcfbe97438248a812a1db00229d6b +14f80fd349988a842bfa248a27017a499a9d6518ca9b127ccbc8390ffad2d656 +3a84d1cd9c1f86432462df68ae1c307f041ee7166b7eaf3b9e51c7923e36a578 +00a505eff79dec34dc2826ccddfc2d103da3803973a832da107ae08517695ada +aa7731650a9d475d0ba725eb2f300f52134cfaf7f822c7f31adbdc28857c8b18 +eb9c52549a74068edc4e9ebb8e065fed61161c8a74670199fa4e325ba67148e7 +0a1e7ecb21d78afad30c6de81e29d1a7ea2d278b85db7900afee050d1aca5adc +219a30cdfc498f387bcfa2b610ed468c3420a8d6f4bc347891dd964fa44c360d +3bb6211995561a808540f25dd3ee310d7c92a0e9484738a1d1eedeeb55d302ac +85eb3ef0ab7418c702fdd9507fe6202e5c500ccb072d6be043df029e32c4f1fb +d203532a866bc66a73a52772627de1a1d3cb651014ce986593fc1807db6bd2ec +7f596917717624cdae2ecae3a1c6acab900b61d882d39ccc1a706b38d4165dcb +c70fe67c8275275c2f1bc872445e18a49d1925f5cb0bf75626b02b52f61dd7f8 +8b3163c86e0685b45fce8f2f0368d95466e7128348b5ed3e765539bb45a35934 +8b28ac5b26e53eb2d95ef60ac11ed77228004b41c6a91e26db63a97311d58bad +b8e4db3b32c4e4df898f2cf012da175397bab3e54a298bddc320dbf70e4a7199 +99f386b884962e7ff522a6f727aca0796641f2c6d6138ae0c4a534f80fd6a301 +ceff1e4a0b54cfa00ab4351f0b6b9484ede19a7db64e29baf2c3fc09e787ef8f +4bb075114cfb109f1f6b418b66b48da6a23e25f712ebfd3adda9ea656d6c5e6d +c41cbbd711acfd8a3792451078bd5d57e39eb4838e2c0abf5db1821fc041e93d +672dbe33aba9fd2248218e170c34c18ee980eb2753f75a87bda81e4f9839638e +defeb188f79fc18c737bb2d466349c242f768a2fd0ff7ffa3ebc6ec714a94aef +c4ab7a67072b39e3f1c28a9e4c7f04bc9b158c246f41e12a1759f5f9becdeca6 +7b23f141d9110cb81db5cea5610d18d142fe504c8abacd9b7e4287c5ccaa4fb6 +426f5bed9c810581efee9dec56e37540fe1667966767008580ae1c3e73ead685 +b95e856eead79711d798f81dc5168599b6080c0152258f2c898035be7239b1c9 +100d24a1557151d68c21884def1664883a04a70128c5c5462bf177c6a5e21463 +c8d80d198dd9a7c1fe76900fd341f8ca5294791bacc744b6330ed1ebe342eae0 +72d9716470bfadf889eadb80d5edf8f0a7796314a7ff8d47c831933f92ed4392 +f3e4d53d401c47faf4c560576f38184c82ba8ed45c70c549cf7d68ab54c2d03e +23430d70604bfcd8a8e27445f0aa13582768e75bbd23a358a51e225f972874d7 +f7181c605030ad4fc2cd91c1bc3f6e44449931448890d4f7e580e2c8ad6b7cd6 +14704ee04c75822c2bbc0ad031c4de10a2f4bd580a3c703c60bc5ade91c03b2f +d24857caa4e30dc4a11daa26045b7f984b8577daa4be487add11e48ec7eacdc0 +b8c41789f6bd6312914fce8787ca9b678a041731593ec5ca20e8b1b594f343f0 +eeda0a33b04dee41d2c3fd11771e9c409a4fb689208b73ee28e68d1ab3596e70 +84bb70f26ae9264497639181bcd9a3940bc019fe20361b61c1621ce35c407090 +2f288c62442ca2bdcd35385dd0b5e48af827f7de2d1e3199b22495e3fee9472c +2c6549de6ab19c6f996a29e0176d939c5a6ebc69a2e74cd43708cc317c50a79d +1fa21434a28e539de4d61a5bc87be9b078313f690b9130211d41941359c911d8 +58026dcd0ca91d09ba751dd9e7f4f82902fb02b42d3b091d1feff20835ea6b05 +bf0ddfca8d3ed1dac2a58ce91233117a1872cc6a5579106ebb8800f2ecf5018e +1be8254a60982e56b211af1541e5f64a18141c6fa68197900f59e801cb855eaf +66111e6c08a4486d15e70522d3bcd9bf27f30f7bde8bbdb272ce764e49d6c901 +bd75ccafda4dfa6449560ea2b38727ee00f7d98f104a57c6a8730b6556b27ff4 +5836ce4254b53ed91e877606199660ffb6b2df1a3f66c6884a00b817bc4cd366 +a6e6164e5c31f7fa1d0e3e7ff67baa68e0c96a9f4a738f75d3ce8b523e9ad89d +9ad5a45b0a1be6e28d0ef08a9315d2abfdd784285f95437e9cc3c4262a96e58f +e887987f2adec7791d66d7a743551cdb0ea0b4c704870b6d9e179d5f090f0d80 +de0963fb0cfaa0751f035114fef578e44e52f2f119ce5ba50f9d2a2d6fcd974f +dcd63342210837e4eca5750073a07f63235b00b4d7205e1d2f7f510d24ed9c1b +aaa6df5a5a4b0c90621e416785558d05c60ea50189dc727d7546e354a02a5e7e +f080015e3f47c9d38f43c652ac6f4d89db580cbbe6db8a5d328497e9094bdcbb +4c5e48ccf6a7ae30c0812bcfe1f5489be6051c62b5aa46d39acacf87acfee079 +44bc5301340f5c0f402d93e944f0fba1409b926d968cf893871e6e82e3a5cf66 +1fecdc28b8f49c68fec1eab5c1bc74e4c0cbf6a236afe3341da149c18db1ffe2 +801a5a4469df7936389c5dfd5cd6825585c6fd115322dedf3ad540c2b0306690 +83c2ed2e11f1edbd10d3dbb4d71d1397842c36994495ef95de6b366dae2322e0 +5e2dc08302af814364e9e880fbc1266c02429997f1013be347d911444ebfe03c +f3a409021cbb1e9b25ed96b87a9798487770a0c4a0dc032a1af5fff31496a68a +f0c83eec12c651eca6ffd40919b132abbca34f4cef8f2b9a8ae02c0b3004306b +336ef5cf8b8afabce1fec8052bb4d720828edfb402f6a5b5bc4c5ea1db080da8 +5fba9effc2f7f7b489106ee7527a789b3d9ebb68dfcb29c0f9fb22b0ee97cef1 +5d02ee15d752e2cacc1e137aec6ba284e739fb1dc5f0784914b0fb8a3a175e07 +c7a93d1a310d9ad826a83e34fd7598a435cd3e2187620f9680e73ba2a6409fc8 +44f0802c6114fccdf30d6c525977f0be0d091a60fda1ae8c046ec0b4ff7dd208 +6e0135a53c7511fa4b860c18d34f1f54392e32a963673fa69cb5a2311f55d26b +d38c3a5ddf434702110c9f959cebad4ac113b7c274a626742f0eaacf34acfeb9 +c7f1da5d961a103180cf3606b4b9f8f74c0db7ed691174f797cfa782f4443e45 +b9ebcdac8d19a150ee208265487c5587a30f26da7c7fe34f44103d30dd29c753 +8f333586134955c8a860337c716b9871a768a181a0fddf030d97cc70761b48e1 +c83c18235d3baea7592efc689ee393a0040377d0e08e043b08e03683f50b6523 +e04593713d69216e78fc6433f9890a01f7a61a4e73e826241da97a8385c4f995 +a55ba955d09428d86e27cb2009f652fdd5ba1971584891015e2a7ac3ca5e0f9b +eb0ce96707e16f2a71ce2a62b43ccc3cbd8cab1b37cf6209f08b33bca9d59e74 +1c763f7c37219d9b8aaa22be16a6fdf3880946c3cc8700e1b04bbf8510bc61a5 +d12938181aa9d2c409d460a322ea631264eb2e7bcb56e841b39197852f2bca62 +4fbe69b746d0f9c4afda14ba80d8460230cf7a6b08795819fbe208d3bb24aab6 +c103172c3de86a9b3d055d7df86afcaebf39a5748a960015f66acaee2fef90cc +5ad3a4d27dbd78d2bcbf03be5467a3be56be91d119ea1da489ba51ea2c46bed1 +98d58dad122f9ead1c8befb496e264bc1096cf3036f9634eade29c325b766767 +3fcd0f29b9ecc605d63cfb4b1fd91f6b8b521805624ddee9e96b51707a2aabab +84368aba1e61964a0c9de8082bbec9a52edbd5611a727306cc50a1e572531efd +86727988ea16d88b4d0795272ce92601b462b93f0426a3a8d154c1aa7054a503 +5d8c10f15ab9cfd1c66c04023ca9aa679da357fe42c526af58f662ebca062195 +3fd55d2451d17ae2e590e73c38ff14b8dda9e6ffd45b9ae32cd646691a953dfa +e64c8bf528730d41eaac3f24601538344e1b2ceac19b5fff891deaf0dafa43aa +b223d5f4d3a1221b816ed1256f3df539e83b9b51d96c72d6956ac27ecb3552e2 +bf18259676da5884232beadf4c50d3fed9b198005c4c88368b04acb9c0acd002 +3d36ebd2545590f3bb2cb390e0a3569860a2fe9683ad7c9cbbefbda91315b228 +3c11fe9c7972aa299eb7116e713bff50e51b44577589a7c198603a555369e5fa +31c8e5e636fea9bd68e0a66fac1943da5902ac61b26d02cf5c6bf54f4f63e827 +fd1e4e375bcf573eea23309a5e782031371bcf54224ee9344d7404d89092cca1 +35f052490c545a4c5ac9cfa2c5c6a8689da44dc600a3fa9ccad0e75589ed116c +28d28b3091c3eaa2c4c125450ac3c7b5e1320cb470fd46714de841c4df8e04cd +a459f5eb9da56c03aeace327a1b6073dece9b0b2cbd851c71250d2e632fbb10b +43a4c79afe241a26258d3f1b1df75579bc5381449f1a838084b7f86ab91dc3b8 +945d65b91400d51d187f0576345f75377470d2b92700495825f97119559ecc0f +0b7c76c099c158a3c04b4e1a694aa910f38e83f623bf7072ffc021a57c3e6d60 +11fa927c7bc0655e8264afdf7022aeb76023c9bf73affced771f4955c661247b +7aebb95960ed5d11fd787a18d696ec9c9f2f081b3039ed3a5976d887bbc62f1d +ad16c3ac173a7e3673ddc9c0968417d4d4b9cebb9ac8f7774a7724dfc2019de7 +2711faca94e80a21413e4b8f32f9ea99798bb5e7ea52e743fbe3c662fd376ee2 +5b8365e4f535a66e4a3167f63be99c12ef0dfa2c7e39172fe6371ed7ee0678df +c27c74b9b763662dffd19f62dea51ae2082047bf9b99b16657da00657b8eef90 +b7e758c19d056b709821c6f1cff1ce662356e045c2ad4173afc60bbd0f5f188b +cc8c005d1d79dbb98e3e1faf3c93b45167a6280075da491d6494cf7c399e19d9 +4fb50b00b2508e9282065ab1072b8e1ba0ab3078f6380a3e56e02d865e2a2e4c +b94c4d6734ebf4643022684a8ff1b630a876ba4c805b1f9da541f3cee9ee7c96 +7ad972f4501d4ff351ad0f5d8c22e500f9f70b5533419be30e0fc6bdc2b0093b +1b10dfcf6a798b51ff59f0cd51bd208e994ddaa73060eff0a49920236e7beaaa +e65d80ca88f36e5216b961f3d564691bd61f12f0bea3e3e3c26c5f86aec50f68 +ca75ac905ce5a3f822222fd63d32bdacbcf7d9acf123e354de553ff8002b9d82 +f98f5bda34be444fec1863318032d8639dc1261b16f833a0a2d989bd6afb7144 +97d06e2bd9257261593f8d75c86aa1ff342ba90a9a3cf89b066c482ac5744866 +3cf5fd45d9da8ba8364a569cb4c691a9c1c6d313f1d4d11cf8ee183a13de9f9d +10be0e803e0991376cadab693afabd9ca02d2a667efbfe19cca2cf2b09e9f3db +0440fef4993bccf141bd886afed9008e516a61e66c6d94dd5cbdd988a508f09e +90f0cc12ce5770b32e75d769d1cbb17d3490831c5be2765fd8a41eec64723420 +9316cabf2f7e00be9a8de673fd6a9aef84e6a7a593fe0395740be07e1a98217e +f388f14336777cab5079aa6ea885ef2c9e2444a37157431118d0983b81d152c1 +5d99f7c78aebbb79764cba527661b742cbbc2db8202774b968571fc4f76316f8 +4149c74215ab991b0104d97100fc7a9ca40606a8f6ac76722b0834467afdd90f +39a32ddd1740e23cefbe76a0b2ef556ede6d5bfd1fc388dbde783bf007713a79 +8db55ee829d431c7802bd747fa2867f3099b9b3ce174766ae91181cf30e64aeb +32278f14a6c697691f9b92810ef226bde8d88c46c7b09e38d40326b75adf8dde +4e5735a1785bb9758f20b4ca12e10d4e43253f557c66bea38e032f3296ef1b37 +4f1dac8357612c95a7857444fae85014e0b639a04a7840d5f659b2774950c811 +780ac2d4bec1f67e9d91e7122cb0f2ecf81f2155d797fdfabc49427249b069f8 +17a53f85bf109be40efc48b1a43678cb8fcc3e40dd2630527d970842c960b266 +1e68f08a2d4c2e78350edb18eb3398abed0d667ab411bb535335e22341ab27ad +7743bab55ec8f9084006190f6f631ba23d0e187bc89a21303ab567dfdebae465 +7b2f12e664753da85cedda08c25da1ba01d198a7bb4a913f97e80672aa62e460 +420a65bf4efec755caa59b8f200a934b972e4d2148341ada4df389c8e7e4e773 +18864075878be2270eb8c11a9926f81f41bde90aba6841e7e775cc9eb2f51bb9 +9d85d17230e6049b144fd6f28cacd0772dea813530a79c0f6db7cd9aad3065d2 +a751d157e8cfd3dbdaea4aa9f21f85045c4d13f47f801b5e500640262c1ba676 +9adfc4d001611785d1cce43227629fd3650395f784799a9d68cde0c25b0c3b59 +507cbefe3fd2b578bf26b9111ff5794fabfb3cab094840688058b41de0e84099 +6b717acd73aa9c47d93dcb9470c7560e6c95b9cdab10c6fef8d23ceca84234a7 +558569d828e0210b6de8167dccf041ab4c99a1d35ca9800624a8f8bc1e6c524d +02de68d91437fe00653cf2cf2cc77e433c226947f6c8da313a43ef44e77ec641 +c056ee89f475bebc46503875fffc99d4da774fdfd2ae215b44a5bf16b8c924e1 +7e714bbd8a4a73baa2cbc1e7fda7dd048e41058e315e26f4c4ee4e8c19c94cd9 +2520e27f8cb64db6fe95832abbfabf386c9b4c1360a02aad5a65498c22d37887 +1afe0e9d2b567944915d6b3bd304c00374739957ae49a3944d58ea45c0d4de3b +ac86aacfadbdd00238e809a648699a9337c9b6644c67afd7ea7c605ab52b346a +975942edca65974b5bbfc5798a96ba6edc98b8837f995e160fcff8ffee18fd9d +2c0faaa6d2674ead1bdb0b81ff0a96e8af3a3cbb12231f9f4865f9fd194aac63 +95bc0f33576ee89f93e7d30dc4c5ae6bdaba1cb3da9fe6e88d5a1b0d06c04e2d +995a054aa73607d885cb1e75b154872b94a461785a4c1f269e931a0dc31defaf +dba3901d75b3f28bcc546268b9b89174c22173f07f18b92011ad776fc0fa31d2 +7da125611aff13a7c4c10698b9cab5bdac1c03bfeccb20fe3068e366d77aa8aa +fe9cb63d57757dbc4bb91a92e27229d774074d13aa21a3fce50ea7cc969ecb1a +50e3f36a6a982a5971963fef8425473063549e272c5a2f7df1e2469640947807 +8f192fbd3713ec9ac7f3346791cf9ccd93accee3efcbd8da37c47c1f8cf069db +e19ba0a3c6490bc4380b063ac8395aa7602b985af5a6622aae239a8e02f2992c +da1c426f2a2974342e435dd4e2864f56553d6105645957e8ab12dcb7e8962196 +8eb1ab959872584b695977506472d14417522a6b14ddaa173f81c6d67aff2787 +e9860d1cc3d36a6685435105582d334a1ce6f35a44608a6c246059f7deb4afa4 +0e0e1e461a007aecab08a9d241536b85aaa35d595f734d3eea485d22bb653b14 +9dd5a9b632d2193c393e29feff2619f79fd805bceca4ad85877867d339de5ea8 +a48d95af3f91f3ddc38c21bc451ef7e38688f812c4cebb4bb69d9835faa5b0f7 +41bc8c7493ebc974d11218679fef9d2ae77e5e42200af7685b7ff5b8395e13a3 +e5542508275a47d9cf3c705f0f9a4bcaf29752e88dc6711312f012a5436477e3 +60acb5c9f116e279ebff4b1573c2a29caa7c875beef6e1f6d54c7a5c85691738 +d07d88b8d8ea616fc49372c591aaf50003934d2fb56702cdcf39d747fb4e230e +7b8929a345bfc0a56f06e14912cc567f23cf4fa8a9449d247f52915f47598c13 +8000c176bf1905d42ac72fb6428862f5b2825715e25d4adfbf47597a4e6bac5c +6ef7cd617630b1270152100ede1a995b41a122e0853a641b66579a818bd0dd33 +2282cce5c8179f5f8f52567c0f34117824f21208bc04fbc5d468b6a6cef8bc22 +631ed4724e74af727807395e35cb5a02b6d49288564e7ff2c6192ff104227dba +d9d09711d6be70f151216ad994bcf850c570e288a6d13b1be1d7057acc614034 +7ba4b1791a4e948cc68e6e3a1dc9398ff0df8bbfbb3ee8dfdef4b2227751b491 +814e6b81de0fd596c5f909d7eb70bc3294a7f14da98743c97cd35e8ca3611cd0 +d428fc80847fb3bc948432dcaa062c98fc0895839aef7059bad8d8001c33c8ee +4a376fb54d427e8e33e01b8b320d8c0e156de84b9993fa98934dbed5efa41293 +91fedb05b103c19b9b9cc887624621fee56b29d44d56b597013f7e19ded0df31 +cb48ea6e205eb79f02254ff9d1aee9ef8bbf7511f9a23ef4d53746c75c2367b2 +747a341d993055262ba15fe48f2f2e3cda2a7862b351ec881e00fa13c65a61e5 +ffe723fe2f6a5b9fdec9af450d2431675e1aee407f9b1db491e7134a6c8b759d +460f61ccb4c000a4a8285256549753d39e9e02d60b95f6fc42e69cf2258d8568 +f34220f437bfbd3dc0c44ab31dcf33a97672c3b8aa70d3a08eddcce381e5f11c +79066019efd2e7c3307091a0f0fa5b24594952a30369ae68ecd19cc07bda35bc +36639f8be539234f5a56d95acdae8338bc1eb20a9362391aa5b040c4502cf75c +6118519acdeb8f0726b2d7415ea25c36364b33840de805395def022570b34e89 +10d78f19fc86b9fb296f99325666593e0f3952aa2726f8ca260d06d0de226a43 +17f0641f874d32b1f0d6031d9ce13fa0cc5c956db520ca17926469f12f40b543 +12a8ba83d187f43804895d4cc51025afbec5c1ed156d09a64ce96c974a3f2a26 +69134a4e1317709e17c1d038bae8c161b71f0e704e416fd3e9bfc1a2592d51a3 +8ebe269743f7704d9a0de3fbe4a059df125651b709bdd0582f01506213c403cf +b8d1034a1a38a09d5b1405cfdca405b04ac6bb8ce3aab7dc9f1c27133eb16b42 +0aa9663cfd4eea285e422cd8abde6792b7ba7b3e90529629aea34f00e81b1dd8 +5345532c560082764e4a8a3a007adcb7892065461adf3dc78b300d60d56e636f +6481d6ef93a80f2bc7197996c07871c070be82eef1f650dd2413e5a87d54795d +35c11239bbfb4cb11ed0d3c60bbbc1794ea6499bcc1b511cf281f4e7b33d7bb4 +20c81133e62c62690dd98e8ee2e30aee10151725ac8211ccbe9ab59a22585233 +6ec52d04ab69d976cf22e0e8a9d16d7de139b9c510808a92bcab77199764fb76 +32817891e81e258ec49d389a6356a0f3c949d10e555ee8266601ed3873d6df46 +356cea99563fb7f540cdceee77abe73116f24713493ce7b79e14952fe597e87f +bfba53c290805c36542662bef833a7e0eaeb3bb1b98c3daf0565465c9372afc1 +32042339be21ecebbdd3aeeaf25f97fb15d155edd9ec8046b97568464c9a81a1 +050c3bd3c16796ff7237666d3a3d217f06af0ea62cb800151f59b213bcaf0bb8 +df93da4d9dfaa703fd4009dd53520eddf02eafe8b04b1aeda8de6dae8fe066ef +c732230661b97fe066c1fbb848a8739c182a29437b42334a9b93a45a787bc98b +71af89d4ca222282b98ab2764d5f4652c81c55d2a7f4b09f8f8f6afa1cb88abf +8bccb37d8e491d2dc3822b5d0b6e2ef1d95e77e3f8720ee2b22df9d4c6af96bf +831477789344f4cb4fa03d9da3ae6e7d00e8e3a9ac8503d5568be51dc044a9bb +40afb3d6ae8ae160fc9133e2fbabd2dc7391920bb44191eeb971c0dbb6f5787c +047f866571d1778035a60e27ad86ef1991518d377a70e1d54eaf35fed9cddc85 +b86dc1ac6e18b55dd07aa7d8ddd4904fc4529b131bfe3bf5ab67da671903e66d +65fe29382aff367766bc4133e64575a9d9ec4086fadfc1355fb42aa274a6af0f +6bff90eaaea51d399c346924982160a3347b6db3ae592d44bec2b8eeb1b22cda +c10cd883b71b6abd7150e10d41bf9368f19db447ced4c1e9b7ed8f0a955f1568 +2f84298f5452057a01bc69d663989660f8e70e460100a4353cd9a69b5ebb0037 +ffdd4aa9f63317f449a52880151046bfc883ea6d2d4147923dc0a9ec0109358c +e662ff496e4fdc81f711de1821271c688fafffd8717e586cff1147b4a3a0de93 +34dbb70ad80c72740506cfebd69946d657125abf630e1ce9379367ebf2155092 +b0cf80d5f0cf10866007ccefc64a2cd4b48d3e9ebc7294354b1bde82f419aebe +814322ce9086457e8029b304c8cada804b3942e6a8a5c7abe6dd8b7047df7f05 +82f31c230616e555c59b26625c29aead1eccaafbee08cfe6032bfebe1eb525f3 +a188a62b29e632964a99e3d4cff5b962bb28aabb355e3360edb4dde181d694a4 +01ef5a9c9b2a22ff8122cb5e42889a4ef299d2573673fa9f6ba9ecb73cf29ea6 +58c37ac9439e163fc552c48a1b60cd80928bb84d0f8b1cf2e39c6794c510a156 +06f242bcf2bd78cdd5a93bbf991f461adb81abce61e168d74379776f5df0fde0 +3f8225cba99b20b1564bea245ab2a2bdcb3956f9d1f02c2169a990aaf2bd57a2 +9eda00b8320189b0fc830867362d0295d0d54e485b100773a046c9d6f0318f73 +5e6b15d4e0c8c0cd4ed939546eeb5d0417e826758ff71210ebe712f8e95d26b4 +02cdaa715ebcb7f9239b57cf252b5e903a5145d1ca5c4fea3cc40fb619ac006f +b338dd8b83f81ba168206f67c3e76e1627e383c0342262add38d890f6f71f30b +3b4a4dbfab402067dc61ac1852f8048d2b821914269ff868e0888686fd11980e +d2519632935b6985080b0f5b76b13017dfa718acb6153d0b27799cee11571ac7 +c24c3e6b6b1e1b296238198421b99c508d6b76d7223ddd6b47421d1bd0c55784 +b2a11811c3195ba97c5d6ae215220f1acf5cb2469a5fa4c56d651ac42a970986 +261cffddbd8b9a139eb043cabe1a89f447b47c1d176db753ae17a6398ac738f0 +bef85dff033e4fcf1e7b2be8e135014ac82513ee7657b2094b773019af90f416 +e6d3136b1f1a0af8f55d84c688f0c2210f98e58c711312c3f5e1c45ba9405106 +5c885921e91621e7c5f5e5e3fa6d64039817aef7c6e5b728b504b2ec9bb32e24 +53d5c3bd4c8d70064018d9f8eb51dc6f82d92c205f6e155eb6d172779e6cfe7d +cec0f3997436c553c6bdcdb7083b9aaf8145d5c7df6462dac27f7fd1c26abb71 +7619b46b276ffff65d23439777df6e3d8495b22436101dc4168a543c26a2004f +c578768b1a43f6e9ddfa028623aed2c4ba6787bdd8a443fc33635d7ec461ad86 +baa4153847656579414083aabde833f354943504928e18798bcab85f41aa6440 +8328f4d3f2c7dc01b7b51d980ac22e982c8dae315a57fd855278a8a01f4e5b37 +504432813d565ec54bfd4d072cfe298f9c22c2e05e2fb9daa3d8a0cea9799c55 +0c32a773c0641a415570d514b51f660fdf559f54019df5e3f1b4c61f7de24d53 +6c0703b2c79804cebdf0116732bd499f850223df6d219109451c0bb448a874f8 +42a466277a22bfc481d384d7fd6505bb3ef3ee555b8e7dcfc5abd892c35db1a3 +4f5e56edc9ccce355d4bb752269a8c89dbc6a31b152817e74a3119eb0c07295c +e0d9cbaa71ac8bdaeaf76d2f912919d3321d8ffee9fe6481e4fccd79e80369ea +21c98af14f9ff50689a6699914b5c049e530ecbb666797fd760f66f3b2057cb9 +c93a1510c27386d08576d5d3f2ad0978dbec793fa6e082174b330735f9445fd6 +ecffdebeefdd5567e15bd3aa6393d61d1b371681a8f65f6651f54cc9fc59eecf +7670ff2b4ec0a2035815315f49db0c9e26eb0e7f6c0098f425e06876110f5128 +e1b9ed81ec3c37f9d6ef563ff28a8f711095f19a303ecaab97a253ab9e1b90ac +09f3d356618c257875c5e0cc575bf1b0b25d5020e9326a2787a58e315bbe2968 +c21d758c8c900f3feff4f93e44556468e84cd3a14528eb3f12295563c230ecff +4b10f0d3d1c294cc60b1c3db381c857aee13294131378187b4c3743e0b76b343 +a3a9b07c2e6b7eb35e99ceec94c3347c58034a84b99f0870b4c489f04c455ccb +7db54c9f9ef91c0b2fa594e4317ed0e6f0c6aa69c6ab3c983d1b1301aeef5329 +fb295adb6a103ae920407b4ba17e1a0cc586ccaa626e66e22ad2bf530ebaf2ca +1d1a80aaf58b8a3260b41c2d8832a987a8787ffaf22957d654a8f8d0cfaf5c79 +eab7ffe9495b02f8bc7813c50bb5b6bbf61ebc7e7565450be27d685152dfa213 +938c04ee5181fb0ae7ff3efad9c363177e22336df9043ec22f8271fefa19c69c +ae751e41e3c63a3289cca82cbea700c163e505a0a554aa7c027bab67eb5f28d5 +38acb8c41bdde3fc8e0276e63a2f4766bf0e353576009bd765db429ef4c68821 +328a041e8bfc92e8fcb6af6616db3075362fb4bfa0f71d46ccf16edd5a362356 +dcc4d7460b167802f6fc0e7bb6b83dbdbdab620b60d1e98a9cad17d73732567f +bdee1d217b02f5e6e2e3077d45c3a99f15e289f616350f876c1ecf60e1fefa2b +20af5edf9b00aaf2d1572f502ace33fcab04f28fa6fb7c8ddc41c4690227e2c8 +97bddc1a5a1c11babf547727100e5cc09e41d4ca39113d764da7d1723307d23e +ca113c636986f91ca61e2eab93aaec5155eeb8ea897aaf3ff343a20389ebe369 +500653eeddccf4ecf8e6e201d538b3308c469cae909158200ae5fc0813cca7c1 +949177656d93a2274f2cce6f74cfb61f39739ddb4ff4f719c46a3af60ef80b17 +79712ea4281e7fda32929987d4c906d2fed0f2c617cf3ed32dc4e2874f93dc6d +1e9420d944cb468210823a19677718bb26c29dbcc71bfe5cf23fc3be1bc46075 +8ef0cfcfe6598d4b953c670020da874a6ce1e5f641956ce57f57daf6195411a4 +fe39038a594c6621bfd14c272745d16b8432710f92a689cb782ee85f7145df71 +eeef33e6118cc9d9a2c7932cd498256fe21a4a3c2ce9bc079b6ac4ed3eb21f11 +471650bac51d69fd81f402d64e1506b55b1b5f914ad0dd2bbd95c58fb2f24dfe +4c9da08d834fa349d645e1189a8cdf5214610ed977861e42d6c47ac4026b8c56 +3a7a6eafe2c5b8668ff684a5a79b9879ffd7afe742f962b72908617adc681d7d +7245e36fc3836438c2b260406d1abe3c7c8ae83fd47e618c5dcab795644e5de5 +7787819f619a94d4de3525ac3000448767af7f117bc5f374483fd32e30d334ca +0be86d845decddc3668fbc869a31dd01821f5616bc2b12b910ac1b5e991207c6 +03b389fc28058d7fb6239d24b0de97eba5f9bf8f40726b83c0498f8df449c74c +483c284c6534c4ce72c891a23c539e215e942d9f2637c7e3eba4247d0dd01a80 +02d66e3c6b303d57eeadc17a99b19c13e4b4ba8bdd119bb7c274870dc3703b44 +5400490204e1f68c0669ae67ca95fe5c692c02899f7fd1c8308f854f7c88eb84 +ea00652456476662f069219a8f283c547ced588ecaaee0eccd3bc529ec1048ff +3c3c5e128baa654ae85d997dd938aca7825f130d6969991d553fcef5fb0a5991 +b89c0e2bbec984343a65d283d55e87999cc5657feaf7461cdb1e078a879f5bcb +366bbbac74e72d7d69c22ee06850e5f686bfe426aeb6651f13be9970e6c047a6 +cabd1cae184273a41853f0aad04e61a28f7251d8f21c96405dcbfb0a7b3cb943 +b02bcaeb73bd14c07a64cb4feb1dec416e5a50c8dc492a02f0b1b4dfac3e6e99 +559b665c3e2e612b71f33cfc63c86cd49ec3265df2eb1770af0a93b4aac2e787 +e5e452de0056e3eb4c9987f9619678acf1c96e1cf0ce0579c71ef56d8d6c5565 +ad46c8a56f261ee4cc4a1714ada2716815a7ceedea10ae0a131636e374b23695 +ec811cfe9a323263be26a1bb57e88d6fc25963b9d066ce956b7d65b8431e18f4 +d32e39a9ef4030bb3d534944e7d701d4c167095ee0a258156d594c21d7825775 +aa5c172253d3c60a1da8d3a6139bfebd2b0088661b15dc8d2413c43b402b7f80 +e80aa51ce42aeeb603cbc381ad54dcd4815e2580e7d595c3ed7ffa8ffb334353 +0d00c30aa25285bf5cb579da573b28d6715034ad18b948fb96b21ca3625901b7 +8ede76633325fa213f299e7a0de6756467f49e69a0fe012729498a9a11f08d64 +46b835a5e513214a0f028eaccb5dc8154d6abccd7c5ad06cb2bb7a561499c87f +b1cd74162cf30cd3e41c0a74763afb5899ad99fce59c5d9b4d657645d087fcc5 +b89ca2c6d73771bfb656cef19118f3c4169b90ffd11735b4cd02e45a2c10348f +2fc863bfe853326be2372b7e33316b6865c780bb8a3da5540973f6fbfafe99b7 +99743045960177981ada72a404c0af46bdf7b50855787ca50579a45962360ae8 +54ba2d628161a36e2f3a5519e6264408b279511a91d728445d4e2a1ce06a671c +01072e21eec13d5fb1e8319a576295d0e6327c2edb71ce1e6b3d4b718b416945 +f08705d7664f07368ebe4ec465c8012bb84bc492680110611b8665c66ff66582 +1ab59586fde88bdd9b242564eecf18da2af435c501bed7e81bb0fcbaf3aeb06b +2656f460a559808f842c7a90e6278c86b77a5f55aec96678b326791b9d1fcf91 +b201beb926e66a34c5a7d2140b135a0d5180e7229a734a5ce91b0de10ec1854c +cb3eb9f702f52f2c804680744f583d4f72270c1774bc382c1a1cb341070aa2a0 +b80310b153f0440a9b892dab5726dfa15b0b491a511ea3a233785e3570231e09 +d62ee2c65e5f31772bb95220261e1e15884585f1976443809ee3911fc691d4a1 +d67ab91c712c23ef849d153fdeffe898437f8b13ca3de282a1003e48d30dffcf +27f09fbd950ae6bac7977089c02c26e26ddd4f6ecf43dd5114d65eedfd6825fd +7dd7a46047fc2dc628cd95e5c3a518febb70ed20c4cef8fd8e66cf93bcaa1288 +92d398048075c0a539b04976d790a45def974ee863d7ca7725dbe47c0f54bbf1 +a62cae24c33d6860c89823e5101ed703477dd1c448dedbb9461c003d6d5af4ca +182d81f7e50e98254c3a8c43cdd723b3cc2940e3603d7ebb3b0bc64b33206294 +4ef2e8bfdbf08355d9fec7177857d7ba20c69a984484737b698517436ef4bea5 +b575487d074c6a808437ae4e3ea356bebcbaa0d257cb875dd316512a8cff0df7 +c98ccc1310c5bcbcacb220f0766fbf68cb4962e1537720ceef260525a393ace5 +4472824d89cebe1885d282f16f9d02a54ee9cdf3886d1d26bae70514e50dd73d +88ab735ab95eb3351014ba9a76c326ed3dd82276d3c8437aadfcf26f3d21128d +d591614383f1b87f4b6618384c34e046fb512df307de3707ea75f6eb136728c2 +4789561e749808fbffce8682f16a332e2739a879641a2b2e3e973dc507bce1cc +478a41f80da9ff08b1184d769f036cc7d90f27e8dd3fe39d38cdbae26e6d2db9 +497b367a9b19f59f8c2efe41e44ccb7f81a4d4a093c4799bcb4426eb12952246 +61b173f94d3d9704f5bb77fc5309bbc8eb87ea91a482c232c5bc1218c5ceee94 +05686beec2474bacee754f45d35e65d39df6d74d24ee839e7e6b876471acc121 +0fec304da8888beb0bcb2d251951cee4533f8bf9d48322d267d68d6965684532 +37f56d5cf4618fd58c658b377e2cccf8a6d89d3931facf3ef856140afb2dae47 +4c7fc51aebcc0b4b04ae3daf9fb23b60de50005d5dcd6cea88f5320f859030bb +6a77dd32507e32b1bb6999972de7beb5b369a0af34de934ae8e53e685da5fb39 +52b7b89be030dbec3d29742cb3044032b5f434104ff37640a59fa1529a7e978a +58613e40d10de97952f0a51c589a7b8532141841c973614be40db6d10b628d6b +acfaa0a04cda593718c097be1212b5188c4d34e987226967358c59dfb9a75036 +84f038713ba853ac2119527fff25abe68f92c620895b5e0441a811c8b2d46e49 +b87f73046a7146db4e42621c346b53f9976fe08f15ccc3f6c59c04ff4ec19d7f +bb8ed7feaf83e0317c24f72c72b5c44f927ccd2813d08bf29b771ff8bf087bb2 +e25bea342fc10aee84a95bf46f48c569c57b9fdee0716a23684485960d76ba2e +794534194043312a4d15c10e08921f9b6af5587f45f9e381b37677fccf80f87f +ab1bbcf0b38cb88c1bd6b964442492774d28c9da1841aaa9aa2af54dcb8b5dde +c2dc23271db0365471a4efdfb9716c8614aa47f5d6aa0101e03d65914a31735d +93511495b94ea7466d96e15743121675524f788d966d5614e58666a7dbad20ae +fcfb4231f018b554d565fb66ef291f8612a1edfcfa129e1b93c654980477f1fe +ad771f9c07575febdaf73a938c89f743be71315d8292e4aecfc8a42b37b1c6fe +3d73ebbd0caf8d491075c6b67aac3c0586cba2662b2396b17e767379aae4c5b7 +62ce752136a33c91585556ed20c9b64b1ad958215781ac8649d0e307957ce819 +799d8cd95271318966a8d81abaef7b15e0f8293110ac0847074e7679af123aea +e537300041c41307f8c2522e2fb868d6f94022ade8ed8df1f778fc65822d11a0 +fbecf2e39ed2d65b7be3fd9b7a671c68d7d34589d4ef505248fc27815ba03cc0 +886576189b95da544f162265188a05c7e9c9c66fb85a0b3bb800d930f50d7d02 +141088b2eb438b15489d81e1a5637fabc3bfb9c4e7c12a9531010361f337e1ce +9dccca85ebe9976b15e297bbf0223d08f5568f4f710b2fceba86048f20cb85ec +e54a7af9ce4fdafe9348fe8179182601a5b95eb4a06441fb37ea56d19d7eec62 +fd8a1eab7571ebc4b14f6add4cd6fcc0aff1aca98c7e3ed93ddb54f60a6bc55a +e0efa92354930094c82aa3de8ae12d41ffb4746197ee3132d7903544d4236099 +9e1a11baeabdd4a81b07eb6ba7214a201b01e5d4034751ec483927194208f933 +17e652f02fc4f1339ff006a3f0f94baff08b14b1b34ce801fecaa18cc121ee3b +7c3aab08987f41ffbb83b7d9270fc7f859cab01b0b137aac2d46526670042cf6 +21cefce2d72b33fb8f7c43cd54e515c6dac37ceb6e6ddd2d79009264b8e11998 +6dd96b2b383d5fdc6879267510ac3dc80ea31902e2b5bdd50b03ee22dd9e402a +ca45afd908c0de3f461e4217f2b41dadebb84d98064f284ecdb119a9607757f7 +ab84e69f17816bfabc2319c921d848f6c577bfc87a416eccdb83579f06c68836 +e879d22ce4b7d796bf99f547ed61e8d39f4b5a3d8056e750d5b326b849d93121 +93d685d42495365cd7d0a20334b901e6ef846068949f479a50a2f70c4c2e0080 +d5a1c3008c2fdca0733a995da1e0508300b3b0520e21b28f65bde4cc9a8fdbbb +bdce0e00a5de1e58cb5fcb4c70a1bc17700b0208c871a9282997320e71f32753 +357fe557910a2ffeaedc8e8592b5f8dcc92ef5c7e7665e8c0dad9e6180c5a32a +2d825def5f9a9a17004561f9ccb4643b427c070c0d14cf88965a43911cc6b9e4 +6efff56856692115b7fac574348157e8a23985a0fee20de5e26e14dc3e35c875 +945ea80731f78ef78f1e970d44d06d76f1871db67c20632575074376d339b33e +b53c3814cfa585a0ac09f78918be6f6ea48631da1b000584822dc8999d64cb26 +986c1c6bcc740e4253bbf451ab2d106968f1251abbebb6f90fff5f17c1df8ade +3a943933812574728719a141e0548abee17845f2ac2361df8e2620328e185fd2 +af8b87b55f64ebf7a11d7b7b8f79f24802060c84905e6c2f08a4cd5390ff28f2 +1c6845c608f51f9ffc7ad8d8c649cbf14e20b5227c5c4be9ed42c85c2a12da90 +417e54faab8292dcc0a1f1437497498088dbe07c027d222b6e2c65d3894ab9af +ce8b4d2823af6d436b67668861940ffe090c089cbb4e0170fc473d4a92eaea66 +76007f3c760ad22b9548e982046b102e91859184c40ea49b6b32e6a890863e08 +1b7ae8d6a48b339278520f2dc678b66ee3f8aedde368140a17bfc7ca167f1a85 +3cca08a323e923c37049425719d03363f0d5e51e7e0d5f44c880d2725bbb5aeb +ee7264cc5061fe6da1e03bdc8234c0fcec038151c4a697b51ae1dc38a9392b22 +5ed4675a5de20a349dbc91857da033f59c78916d4b8914e3ab628c7075cfc706 +99054467dff03bc464f80a3017847b938e217b04fd4f46241d48c7498d15a399 +c3c9ea217e527fc5561d0d885a6a63583b41f1d54a506278c572623250aa61e4 +ada6bee6fed3593e5cb9a42f997cc91a0affd7fcd84b77c4e7f0bff3ab1f9746 +ecbd4dffb89b4108ee9097dbf9f9d075aca8ac546ac0d0a0c050ad871f4a2a05 +9fd0c298403e6ead4c093a2afe548bff23e742a9d8eb1fa00ad976534eb5149e +336d2afd18ae235424fc6a06aba551c7e0dd26e92bbbd372c85aebfee8d48484 +b9419d515b81c4d5f3b086876b3e4ab635ba702d3f6b5b74eb25a9b123c4614c +a19a795f71a80c61b893e6ecb067209506931d38f584ae2d07207aa6adb29061 +0aabb496bb8cd38f14ffe001ce6023f683152ccf2a73b688b946e787e102c744 +0236587daa52df27d113b4dd4819de40b4efa54ba5e8b28f687b74a6333f5624 +69890331cda71177bf368d07c1b739892b1e0b0193f9befbf8d18bdbba23a727 +9795347d730e9c8f8dfbf356ee8142024190006e0e04dfcc4ed01a852189f3f3 +cb4e7073abed8aebee3a4dbc2dc10697100282778c9116b32c0392bd21017dbf +1bc5800e827034243d084524628e8ab2733446a53e4f6caa0208364afa44a7ac +8b1a242a248bdc223e025cad987ceda3001dec7fb40371c46bbea4bc80596408 +7fc5693e3293a55b5a3cf1295c5a79f955b7cd78f68ff6ddd7b8a0ae11930713 +f6521e4981207d7e427f3e1475f80631742e7c8f8403e79834ec540ff645d40d +4e4a32d263c98c39512a2e6e307a35d5770c93a02a717a3943009ba38ec48f9d +cab18ee6f266cfea9911feb778eb864dd58e8f4524b7c45b76503d992eabc505 +480443dd9145bd4e92382df65209f49e34ea080522eee9ca0dca2a023d613be5 +217b445e8592008c692066628e3e948eb9a5063e40f768b5de13fc75a98c5189 +7b1be013bd9021668f02e8d70f221be19421690f013f04560d1dc555aea003ff +faed9bb38c0602663ae07c7f5cbd14b217df7d5c3c2d252fc6a95e5fa28eb0fa +78b03beaeb1f571b8a1928bbc1010707291d171fa5d19f88835138c0ebcc9ad6 +f6f07ffe2d02c2134a705bb9662e66e1cb11f2831b3cb0edc22ac3fa266cb848 +c04dc03c99b247629b7e643b6e24dfa2c98fba7df987fa4e943d67bd2d061ca4 +56d21caf5fe2c31d311322c24dd751390ebf06189064dc79d86ba84eda87aada +8c141b902d544b42d82a5078f74b37bec60621c8df7e7e542b3b80254d6867b1 +1ad9d94c9630931aad8013b384fed9d9ca04968c832ac492d6a8a4e549b966fa +6a52120662f29406d11bed53965e6ec209abcf496514f4aa5a8c2f36f46b5536 +c27669ad51efaabba6bbda7ad49122c244b8c58c6b647e3bbf2dfb46be9eaa29 +ccad342ad5304c6c2d5a2d269d3758fc78440007eede89df8277fc8bfd1e1cda +f9f44e67ea4c1a6d4456a0cbdae35e7d6db4a19389addc5c0e23480d4d300cf4 +3bf952bdcbbac892667acd4e88680335ace79d917b71d2cc07182af0c6798c74 +c7605fd7f7c70808cb6a2fd9cecce47ca372f24b5f95f6bf962114771c2cc9b1 +b8c346c93fe984c2eacc657fe30e8ba4f808ea155b995401dd0ad7e738f1bb3f +7e2b89f8df057a09c64fc47d2b91dc72a8fc2d8fdb41a955fe92b580c0ed401a +1dca8851e7d45086dc7019e02fd3f335115268bcc3406d603d5a44d7fbe9099b +187ee5af078267036398d920755f5e8188fcc8cec47675590c60429951d0d63e +d7bc32ac52f72396d17cc80d7dcb62b19e35db98f5954d2cbef1385910c4a200 +0f4dc65bf780bc28d5ee28a00a728c6e50cc6eb12c9419ea6a3c77028615fe4a +8cdd61242cbf232bc1b0ff233194c6d5811fcead386294d14623a929bbe6febf +e198ac2a6ca2b69e1012d85d3a8fe78813574bc3629121a85d3c5f7e042f0ab2 +95ea855fe690cb4d392875144ebf2b7641e0f681803dc6463b8bc2dd9ce8018a +acc8621ddb03d463660e675bdd657d23e75619a70b41d754cec98d886c7679c3 +6c67173907f990d49a935d00fe3a4e139201b6699e4244eed2a7f8e137818f87 +7113af0f9cb12d26449e8379a44989613b1663cdf4362a4e8cd014bee740feb5 +0979467989de884f227b6133563184a5f8ff66ce3d612a9c473ac15d335c2bbc +b4d18c4488aae6ebcc5df539f7ab6a7a37b03376b38b21cd1e3146c17521548f +212a2426c9032649d844b8b831b3e8ee3e8dafedf87c38c6b0a3ffad3545abbb +de5275db46c97455dc4e9c6bf0243eb363011fe2fa32f4dc63e4c694ad61adcf +b56207af09bda5eacb5f086adc015979bc8f36d08e09d491b52f9b7f27fc96b6 +950fe2f68bed81895244a045ebae47b609e71ea12633cc71d9f6ab57e5ffa00f +2cca5c7bf3ed0b8d6afa7f1a985a2fee9da0f9d2f69ce9c5302a70c774a311e1 +1646a9a1c83656ba90e31dd2a5b66fbc255b4c3a5618b7c3d4eb6c467fbeccb7 +0dd8627e66581643a7af844c71cb207f4bca25b4a361780f7c4aa28feeb010bc +36c983ca8eeba18e165e611a6f075213263e2c619094f523083b8966679e686b +0fd350cdc3df5d2334d27a22e554561cfbe1142a87d9f370ab78ca1e94644b88 +a0bcf408eadea49734e2a1a4013b10c5eb997e215fb1d3821a23b32f27f2a3d7 +53b4a92170127528f266e66ee325ee53bb24a9714d36318c4c915225666039fc +9ea5a09e9284e230b4513c949dffd4a0c648cecc34725bc331a20cfce37e3dae +137aeb0bacda9ce22112eda1079df5e12537264f69053b945485e0d63f1a0bbc +e272c4009972b826f3bff37871c44fbb3d82354b8ef978106690fabba5ceab80 +f0f00f6713bad0fbc8a39cccf7394cc1c1806dbe9f9c3b9cc207f859314395b8 +b32f44a433e5223a341788fe1c660cb4368fed883a55c8a1e51ca5e3381ff16e +e01997d9d80108d9ef0bda07317bba6b81ab9c7abdb3a6c722b142354793576a +80eda04ab3ceb391a1f5d45ce5208338b1f90ebb9964bdf27190689b01a8c0c2 +c9fd69ad7eccea07128e03266acdb44826ecc463847ce547ba40b5d5be4ea76a +3a531e8df8bf4edeee186fac23ad28922d405b6d8f39dfba4e7b16b498556296 +dc85d39e4d2b3f97e58f576fbdf09c70426f2133f41dd106aff75a2122f808aa +29af16c4d1b40c22bba8d41270a9d446d73e83d8f591b85d94f51222672f14c6 +c465392bd556dfba53c41fa6962066f13f579ae18c9747e51e5b5e47616036d0 +36772d307138669d8951c6465007d63ced2bd506b232c12f2bc9245b9a23b35f +6dce7b06f412ad2a7d62fe3649c32e58a90c5ea14d4e7795821ad225b996edc8 +04ef7008fb5c78646162218a7d0e9894a7195ab7f1e1a217856f36315bc8b2b6 +bee875692a392ea264ba1780a9696a5445031b1609369a7f36343593d18c45c1 +74a2c1833aa41225002ac3a7235f2469361abe88a5907c082a287ea0183d0eea +e0cffadb1f0800bfe229958c312ef70b0f823b32d9ab348bdb4afbe8794a5494 +c983b24e62f67487c3e297d87ee4d15b8c447cf3afb26255944d387d358e8a06 +c318b4c65285a998e5535d2826953f5f35bbb2a60d713f5562e11137e4079053 +e495edba9fe0c3f517c3352e0c5afd3f4637202cc6c65c3fa79ab02c4b1ec6ba +e1d04ba8abf5bfe31b580d5439f3ec7344d827cd3b25ddcab517706216176981 +2b9addae429da8737a0ec96c5bc74f847c1a32f929e02030a12d3539c5ca5dff +2d45e1d494624ced544c32de79961a3d304f4fe97d2fa2e2a78af3db4d15fec0 +c5d5de0ddf13edf1085a9b6a05fb4fe0f9de2a5d8b147a8b12dc63fd616fb21a +72c38dd35fa2326192451564e0e358d6e098ec12621ea425294eac600a6dbedc +f4e390fbbd8b1d1e78f7c27bcefa57ef955ba3a680f56797018967dfde52998a +a9ea66fa6b7aab9ae0fc39bb456e2128a5af9a0f65603659c27fea8ed3bc8e57 +c0d9ca2d52e5b72a48107131658eb661d8535425c032fc6efd503ea5aaa6e174 +4fa26fc025e31734e4fffdeb515b69758f60a6bfb00b07d215a0fb7b22331276 +23d72f0cec6746edb21944d535463de6d43319c6891000b07ce276a39442a606 +69c8db6ff8861700f49dcbd65c1fa9548f471134bffe3d64cc878de513f57574 +42fd3205941881da4ffe6a4b1606d1e6b65374dd48ef6d8ebd4a915457b5e957 +677aff1efd417cfe2d51444b8feec5ada29860beb8b6642d023ef1318441d44c +e70b1bb65c1a9aa728dac9131d0758539e72b4cefdc958dface65744e77317f5 +358158ac418ad5b33dbc85fa857b44a7e4cb89bcc549a29df166be1a547e8bd0 +f9363659991d2e99d4de96cc82b0cb18dabef21aae8521b9fc203fb3547c415b +f41f308e429ebcca2fe64d05767ea83a4d5ae34dc789c9f24125ca60d1f27a4f +70d8e31d063605e18037def1fab152fbaac1be299b8db88405037ef005c3ad85 +3e731c68c76ef23a5fa2f2c07beb8aa5be3c29fb71d8bd0ffe8026f09cdf530d +dff38a0e21d552dad7a7ee5d4167d71081e92ce8ae16a202fe46a41cfbed9a58 +c898bc5d8fa3a844f8f93b98233e7e116513d120f005e68fe439e57ce130a013 +3fb27b935f5e2dd9aad2c2674d682561e690f1ad341a0b46879c782a08f6f381 +34970a52b0c07c13b86f46d1e8525d29171cdf7e3d29ba1e1389d06743660be0 +c3325200128755934ae34c18c479860039da9e1e9a1d0ff80c74ef248fed8775 +f834763956705dca7d64a5259f507ff4f074bce8f3332a6ebcaa220db6064eb8 +50fa3209c7513fb6dfcef6402e60e74bcc050efb164eff5b9a815db76adc9493 +c069288d3c80bb72259d4ec58632dfe29b4dd882445e5b70fc5de45e1bc3e735 +b82734f803e1c1063655229f1087c7da8046b5541f24c609e45165bb26f35271 +a2e7f262aaa4eee563120c746a574c51447817ce1e706abf28dc44a1dc9898c3 +b464f52684b005d153c3342fe7206fc5ce3defd950c66cf49520fb0366f34588 +017da09eb5011dc8f3d67db39f5f553956e665c724c54e5d00eba63157257943 +d2bec9a986e371c7adac385a4492e8b9345bd3cb9218ab4911c506d0af2d8371 +ce0ad05a892483d88be17a302864630d3ad774d8a2762ee00d432709026d953f +b7e45ae928a28bf16b09a910b180fa27df300268cdf31862c3be11ea2b96a64b +37175753331cf356999d5d5a83b6009d26076f6362ab4f2e6d3d63ad8865f2a1 +f4d9933c6ff6eb06339d30a201e7ea9c7d9574103761129cc5dcdabcb465aecb +b36a4014b65bb10f02b31412ca3700c916a7c527d95c61444db8931bb413defd +8c90c7e8ab1e02ebdf7b32ca597d58c5e146d6b5b8ecb77c608f7952db52f989 +b1aca39435ce8a427eeb69f740979f5dddd5d52266b331a0d6ad202e9a36f486 +4460b53425f691a08aff5a0521501d5b006d9a1450ef57315bc3f27f80d67778 +546e7b1c85ce707a2ede03459a934e7b3957fd28667cbe3e43543d0e37b7641d +73e22bfebf18b5a36965ac02ebecddc41b1acab99ccae5eb67dafb76b04f69e7 +d72729a4c3e9705f85f3000cbc4d2c4a2d90e049a781b92e01efb9e54ee19d17 +89b87a50049eb2d03026119568f751f1647eb621561488c29bbd35c5cffe2496 +8fde1ded7cb13ea360c52b2539e082ae10918c1780ac3051e65479e699fe1423 +f117b2b761d3dbdec70139c9749808d486092b30dd937b72cc13cc316c9adc54 +8badaf0fd807dc2a565fa83afeb904bc87644dd3c5adfff7b5bcb1ffb00d533c +2f40fd10e51f8d4f13b01cfb92662b56f41bc534d19fba86e4aefd849a1dc26b +2ddb16999e3fe03379045b0e42f8b724f3568dd3d301a2a36b7cfc80330c74a7 +3099f399be7578ef5eea2cae6559cfc1bf9f2935412ba8f489099d42e0d8bf4c +e2d8914fefefd2164da6e085ac162bd08cace2d5553150400794282dfb991aed +c86e2175c68e2150c965946d2ffd27f1b3b4c53fdf613379e3c043414cf9dad3 +ddfb9aeb7e088a3e8138f1808bbbe60f82593f16258d04ab408ffe04136830a5 +aad3e35165b396d9acb619eddd300aaab545ccc81cff612bceb75920cf6af3b2 +033f45cb6419c03460ce2016ce3269036d56425db1f07e3379771712cfdf3c95 +d09fcfcb80c1eb139b34e419e732723baf0f1e02d918cd2426027c51735413b2 +6ac40db12bd865aa800b694345a468a37b4527d736cf8ce2fc3f9f459f267616 +adf329dd7968499800dcbb92aa0e983b04fa9ebe4aa24555d4bcef07af1150c6 +327c7775e90e52ec73022d3eb23a2d2737bd5a879d2fac31e720e2563becf62d +9bec24ff8a0ee6e72cd8cbafb28a057364eecd104ddac119ef62e27cdfa0b353 +69f221cf5bd7ba9dfbbdf120f7ef92b84227a5ee36ffb9b2b69fa1263d0b962e +8b151758b9db7bc077ab927ebe6e91ad5f7576c91be5a3a6e0a0477613072bf7 +9a3564533d37ab8e3c09677532493c360a8019d1efca1f97979c47673558517f +bc2f7541037e460d57a25b9451a6b2a2a3be872a21750449990d7ed391753a2b +0898d507450dd771e39ac639eca79e9d48afa80cad88c14a18e17a1335041f10 +bb3fe58a8f837f1ab43224b130b16a9f0f47e8fd491d806114e18e99ae467b63 +2cdf0857ae32d9a8646a9c3b298599db84a11b6e69497c4a81d60621c3a66e67 +5d7f629c5b59be286b97987dc3460126a156f37400229491be2b420350a39368 +006d8383839eccac5f543e0758881a43c086b856a9414096db2046d8f626b7e0 +a35b74947cb9b83fb2101b551b17744036736b8e52ec164c31e59e51b63830d4 +ce1680fe3bd4ec934f16062e5ee5a492a5ab819af7255f27ccd4b75140387ac9 +03984726b0b720f90461b5f727ce08f6af87e8e6463e4b19003eb1b985749bf6 +2d434614e2c1466962594b5a06ffa39ab50426dabd31e604a4b9b8b7e9f95167 +e777819959e198a7c98adb330f6243876b63b3c7e4ec054443e5f7c49860e005 +d494c9392879fc826bf4fbf224addcc5189da09b483eb452d90215f8544dedfe +7aaf52f05c2541a7e6593ef9302cd93c72f3981d50886137236a5b3a3a4de4ee +4b61f7708080781de1bd8c2cb7aa5145aa5cb6b055ee2207e160a691c81916a7 +0c9406b07791808bfcc9cb75f016f0d1738a5a965e02bdca37ad958efab6faa6 +8102aa1158d7775ca2f47efd160781082af8a2dbf43f7b07fe03dc26748af59d +2a1d1611370d94a90bdd52ae4d9da489b9da4d0611b506e648ef81af101aceef +cfe5037163d914c0b6f0730dbd9a201eee80c96c8f1203c406ff0042f38bf8b9 +dd645571c1495c513018ec5bdf16a80f308c70048024a843d07eb71af6389d1b +519fa1bd1ec6d3b66ddba468f1a7af25f9efe775b2dda3ba0d50331ed2590736 +b856d7e57db58de7d63a97b3f1fb9543522c5fab87e140d76705e3ffe61f7c6f +483afbf06a6be50a1d179bbe80c45ea87b65b69ad5fa7f4a0b24f667836691cd +58a33553843c3b308fe2d1e3f609e467b6052e246d90e462ade9688913f3891f +9e5f97dabf3a6357a7e7e85491b3a30170c44dd23ea7e78b180854108be94f56 +e1ed7212fdb243ad2a0b65946a01c7d28fee75ce3ec99aafef6c91906957677b +994d2a98779eea644cc6ae7182d43ac11cb79294a7237cf6eddeaeba9ca29134 +4818144227f46664c586b786195292ed40eadc05a5082d53e37e2d5b8f7297d3 +11349b32a48368481e9808e99c48762130f53136168c1b8c1f6b2c5c3068e2eb +446f55acd64d62ebd132beef41a83e1b7726b8af4e33b1e151f65c68581adc4a +97a8f291c989e867aa3914230d078fc3fbf82894a0e4dbda9f7218f0e7b3a532 +a5d745d56abfebd4a6f3dd7405d519af233ea1ba59192c889189c2484c81a4fe +0b450be642481b3dc4d11c879df51aafb9c7199ba72e2091b463beba1b314dbe +f48f50fd0eca044337057d74a38c651fbe6950afaeb4c970706bb31952ccc0dc +fb58db5d6a4670659480856d671afcfd3a3ba1a9371d5f94656fbf99090bd52d +b617d2f4eda38de34d798bfa36af40ca596cebb556cdb2f745b07464b6b25fa9 +79a6d7b62ef10fc153548597d9aa3646dee92816b029c43d3b770a850dbde98f +777ddfd5c14df2ff52138283ea31aa35e4ab39449963169bda94e62cbe91e2bc +70df5c9558d8d7ecd8365cac56e9a0d34fd2a059dc21fac276351609dbbbae0d +b8bc3ea13919a9836be813b3118e374a1de719ac47a23a580c444961f13a4a0c +e9ae75af7637df639cb1c9b594a65199e8d1c9dcb7d357642cb1436e94775c66 +5ac11554c927be5b00275930b269c378a8328ec4f00327b824c2a4f108b82d7a +c51da07e5e81fce4817cc054c548887610c8facd01f3589ddfef21ebe6e807cf +dc6377b8b2bb9a56f761c99797b3d4b231a816fec9fe4f9b4838ff0da25d75b6 +cf033d02a2a9536478ba16c59aa2b10a7e87664d18a2389abf575e7ce2c7efc2 +b48e25aabd92db109af22ff9bbd8f081a1773756a17cb565989af961d833dfb0 +82d16d2f40380588efcf2497726b413c14fd13f5bdc0f88672c0744976980929 +8730f17eca21e714d468ee2b5389a560c2833e962a5f40329bdc1c61936a4ad6 +e8a38a01ae87c21d19a43047ab7be01e6b74a6c13bc6862753f3cecb9322b267 +7eb1205d7b859d471e0747f791a7e6b6fa78795e1883579d789e77561c0ccada +5c495a628fa071c9091c9199f20022e43a00910f9fd8a4f0c77bf14be09b635a +bac705291fdb40680ffeaced85cb61873a97dcd81d4dc3f90c2ee51d59668b43 +208a94efc5fa3143a2ce4c4943aadc595b3f66c4c0b985ea627eced9b5c707ac +6a48386a950f82eaa3abce78c86127a1173ad76908520cc48657d0a35493d734 +8edf53d2543b1532c98120ea82866bfbb1deae844ee33dde2a578a158cb2ae23 +47491febb4945e6d0fb31dd4892f5021c1fae11baddbd30f9dcc70ac33e6bcd5 +808792ba633132105f7457f80d408e254dd1be3c96eb80818ff56c54323733d9 +a7db26b65cdb0d667d8395905664602ccbea6fe31c275f890b9b60538e859afe +39053910521f9ad8345e0e97eb1e07d83d7661533b8dc5f810fa19f5d97a8e9e +b154d74835b39636dc35b07dd52e9d5d63f5ac77d4061e062d9c8be040988a0a +a200e23922ed12f9fb7c00b0fff42ee5ac1bc92c6997d75150ee007cf456bc59 +ab07946c8074101379ce5df4961c47d5f3e5977e20ad645badfa6281fa83d5c4 +8b0b41912cf19bc89af14eacc817c0e72ae868385a6f8a2fbe008b3ae500970e +ef79a7a13bc903481cdadfebf4d4c91919d3ab30927eafac5b0bfcd28d642661 +f2e47941bb79132f3dae1aa3e1abf3f7ecd67da07c35aaa2df1bb7d4af893d28 +abcd1201348a109eec956437ccda080359bef3ce7404bb9774982f987081ccfa +7fad92592528c9f19e37a9d1863c8688453f761295d4a53b721e9d86958300ca +8ca59244940bcf1256adf83d7f74a3bbc9deba0ba07843f3834b3337784ff01a +5ba65c715354aecf7b4918ae8c8f6d43bcf429f27c4c5959a80fa5c605dda44a +bd8427ecab0880be86354902b145fb205731b04280d91a9278d53cdd40da8d84 +cf24f5023132e812fefbef8cbbdb691f85fe9b3e8c8de15e38ccc1cd84cd308c +07f67e1c73449eb7ac09fa0b5027fac4edcf7d283de8408bab51c33033cb5d20 +7dad4f2d6a23517906fef5299921c5cad3fdf0378a4303503e2ce2fe68500c1c +c4ba0e1069c5c6aa052243ff9b139f34fc353c43f5ef3bd0b9ca2930b85cc33c +07d23c12438fe226d4428cf123d213a20def2ee05fd250c394ae4bed4f54e1ff +e64591437106007d96e21d23ee87c578f8afd7c59e7e2d73744472ce3af77a9d +2cdc258c1b73f8763f43ab5eebf4bd95fcf1e2c5f70dcc600319e476e8469b7d +ba2b31abab29f906448d764dca3371b9fdc76a7a893476f1b3c330e981af6e5e +9dd4b4b11cc0b969d22de20b536dcc1f16683a677768c36c8d2bc39c66b4f497 +875d82a9ec50fe1de0570d816578b93a515ec7665e70d12016b02220d3d3e7c6 +91231862d31bdadaa8a9533496579206b298564501992c8e31165768b04beb24 +04763409e1f8579436bf2908e87dc1117010e5d9e71836ee5d8873140eb35447 +217aa19e4cccb0ff2585efe8605470acc8dbabcb1c98344516f8cb2e644afc7c +a12af6ec57cc2e90f29a1670a1e22bf41869eff3d005cb4df1562efbdaad7511 +c8de3c73b67eb3b99486ebd496695267b3b105854219061aa4c82453a3313c02 +7da3fc264fe870ab2e1993eae5481cf409d11e9b299f18b926dc7d3e6e3a407d +8601753b850621af32fdc7ba783dd085e0da1f058407905fa881b45903e7dba4 +e2b12262e78fdd844bc37d3aa2dc36d49cdbd2dbb6c62bf8c9d41c042c661fdd +1cd324d3163ef4e750b1a4a9534b719cb54facfa8e71e3ba98249759a0ac760e +965387bdddc2c00d427cc9ab4ae5a082562c75182771b00d223a8bbd8661b197 +b7045cb49c53aba93baaf71af50484dcfde7a673ec7a2fe5a5db7c2622db0522 +f547ccd1d6ff5f097fc1378d72810b0543f3d52d21e4f9abbc483ca880ded6ce +b5b4bd291a44cc4cba004970c2ce4255a3d4b30437c0093385d1039ca6d908c9 +b98fdebe9f47456bb4c86594b25c8a9c92939809933f57a5d5d3eaf0d7d8f5a8 +d3110375c026380eda50fe043d5ec585208372b68142249da03137a02ba4d005 +d6828c34542da81825d0c0f892c218a93451095640717cb9fa3a5dd5879972a2 +173d2ac337d61eda9b8144757f2d3c102c38aaff521dcef1fde7ae46ccb20240 +fd6a649684b233bac304045dc0eafad82bf2079f8373913349b4c03cc6f7be71 +44b3e779172312b56df6b9f0bc85ac9f6d58c2f15d9bc3018f6ddf432a657af1 +75ba090ae3efd06d9c30781cf6e700fc2df3e7b86f512503c72d80db90f8c19a +ddd45843039787f5ad5e2ed2261ed0bac38a08de9e3810be6168fa3beefdd2ee +74a6cadba8def8b97e6f434f5251224940efe5689a53d0e06a7c74294f6fe659 +322e6333f57d19f033849d8f04001d5f4ef0689dd78b4dc50c33dcc2cf90945b +078853fcceb60f6e7eb7ac552c7d5c7cd338bbb4559adb24534162fa15e06b0c +a7f376a0f655a6b723e1529e0db1df9f59d4370a5fbfb02721fc822728f7a731 +12647a9638ef403a5fb0e7c05226810ffea0ca7b8ce77bffa788e7be8e15b0ef +6f58e7416caa6e995c04c97feefb5f95111cd75990fdbf0d1133f983da55ebe3 +5b1316a67b23422723437db08bc8c9cd9ed4beb4ba09d1831278a1effe4299c7 +9528b77e311632cfff0a596a4759d170f8b9af39a22d05d8ccf274c7a42d2f67 +66ade9f82c3f2edd44307d042287b6259a641e1a9622d9bd3b95d43c5e175adc +7865dde907b9c8f0be4bca943ee2a02dfc8488ea5a4af0dfd9f750a106575c30 +54607acca3c633dd29111e064caca8dde33efc13f121e1cdea6bdb8ffb39a25c +3f212063b802e1bf92a752b317f70561b0db3e86e3a544ebd7d3ac97a208cd3d +964e10f60f8ee5461e82fd38ad54b47490a64877e68583adab4b4ec17e974e1f +05e2bad2ae1d1eee95325eb79e3d5d1c8d26f5381539c49c09a7c042656f3d6a +3a3c5de842a60566af0b9fe80587311ab324ac24e525d544f2554a1f8a6af82b +124f910f5a957149672b6bd913e86b786d7fbc8fe42fccf3fae2300f9a548e78 +2bc54e022b107656eb27df3150c5b9cfe7bb86f87bf23fc3a1c09817c91ed9ba +45fe4629967085674ccb1d29e2e4de7e8f4c79f974fd3fbed19b0e4478a41a4d +7ce62be3933987cc2f4162ad5c28a3da3d7a4b2d9f09e82251605481e863276d +d4a71ddb5f1dbdc38a9e3bfc6678d7484ae60ed9a42e0ebdff8ee23996bd6a98 +535b377741321ae2c81703e5176b4e7c4b08bb14f7596157d35cbc149bdb7eb3 +3f56fe7077907d6558dc0da7184baf53dae403c2f332300d8eb5ff54046ed40d +62b45a3746e5946b9fcb5f4c498817ea79ccc65398f8c64b49adbd6bdb17c3cc +b1b817eef018d29124146f5b3b489e29141cc86c3150e08920a3ac7f75cc0885 +913050882808c591a5e05843b9748ea223469ce5962909c41efd425587fd3d9d +2ca69676f486c0ef3fd2ce4ed3b16ee8ea94e89acd9e4ab39a25832089c9600b +c88c48848232ff6f75381bb1954a241ce82b75634e765eecb30ee136cde63d7d +86ef56cddb231a24f824c9ae833ae8f4048145075869aa0aebd0756af96a751d +706aaae27091eaef2df6b6cd5ee90ce4f804f0c7890955ce59987b75ae82b186 +47439d847f90701ce27c39724b38d273712a9457db6cf4a414ca71526d72fb19 +0bf47b957efae5aeaed04b658aa909a07d00a66691365a7374253508220efc20 +89e8e687b28f41d8c94da212b2860806d47c8acf0832d8bae9b67a5d0b5d4caa +1a35689845a570cf5edb9998a2c555f327e849d8fc86173393662650b4e8e08d +19173b41f8fcf0304348b40fd15f50f9ccb44bed5bac13507d692edc57cfcb7d +7639cf2e3c15632d48968a6ed28e385e2a658e25570d074bb6897352933f1fc6 +bf004d26c57cdd66345b9c631922be83267e75a47a26914ceb7d4b1e44b72e8a +262333ca58afe8eed93d4077df3202ca08f28fbcd024f855b9c7ed61bd28122a +82eac6284d6c2abc0e18c73c6db2f89519e9c59c5cb0c222187ce1fe80e11c68 +f019e054f3b36cf2c49e504b7fbbdfd1c7bacf42583517cad5230fe5b1246c58 +e6e6bb0541ea55f673eabbeaef8544a14725995fcb2af559bd0868fbab516f6f +4e2754442dee1660524172d757050c8a8d0f92293344f50a4bd9df0eb148f47e +711ef8ce2678bfd19bf08d461c580aeb845abffb9c8c2b68eba458f09fca0155 +50e17637d5dbf141ff9cf4c50b61e0357357afcdce54b37df373150d0521b19e +2c614af5c15c5b24ade120cf9af5b83541874754fbfc7ff14fd6981a234f1a71 +1f1f4c8d486c399eef2dd02ebcbc9134ac437abcd5c783c33fc51fad2d316a70 +a001eb6ffc9a1d0483094300eb0352651bf0d84aa14a0e97db7008009a062988 +b1408f4b9baa574e1f22eb79bbf88bf2e1ab654dd5b0103412ea064918c3b7b3 +8b129db4d9ede0437ad2cc81aea18aff8c98eccf3ecc1fc7d6952c5f54370ead +6a0c69f727c9a825250895bb9bdab622aec5730be2f0933027c2cc2b45fe2819 +2c82124f6e10829a5b29eab310f457cb5c3b1145eabfff55435fd91c66749cea +f948cc14a17f8f1aee7440897199af7f4f5e4a722e3c6658ed9495128f792d06 +30712c9d777fbc9f0cdeede42752daa2618516e6c4d9e4d66d3bfadff5d5a5f8 +033c6cefe1736702eeb8499bd8adcf2e11661c0233056e8d0d3eae127ddd30fe +1177b693e2d6669afcfb3ae766c8b5f22c088b9ebece669e6461f0ce8ca572d0 +c38bc82325e221684cadea49e0f3d490cfb9a42d5da9d437299052ecab142ae9 +1f9eb1c9b635c8f51474428a8e46fa0ccd5c17f2b3dd3e302a2d39e779975f89 +ba80e5c3b01fb21730b02cb118377590382016a52ec5b248f6eec6276e50a60a +775eeb00ebb1290a50b65cb378fc222456d105571172c75e73ce8cfeee81bb20 +7ac1be3de25044909721fcaac900fb2c917ff6c8a1539ec6213993687612b415 +15390c340606603e1c53eaaaa56f6897e7ea5acc17b8fc3356512b75395f72e7 +dcfff3d808c9d2bccc2ec0918fa6447ea8ee13e1eaa5e63245bf2bdc3855213d +90685c2cb5e3f605325bc5ceacb723280cb147c8235bd71513ab96c9f0b2b103 +df5c1bdb1a62f98aafacfd652c6dbe1e026ae4859c8c349966112b73577d4719 +3fdbb9bef40025c437de4814e84e35426c2f7a3a722f3d050ba1612639b0d52a +c1eb705b4f23209fc06ed06292039199ea09046ff9b317f5f9b17b332e7138ab +12f4d343e593beee97bf42b5f733cfe207ab3f4ebd7b9891bc4116e32f9a39ea +cee2d5315c343392151e5bd618f4faf738fc81f8002ae948a5c45060f9e93921 +7a8ac5e65859a83d1f75eae3df52e5ac25ca27d1f592e43a80c600ebdc67e8a4 +4194358b344f425d4b9f6cda54bfbae1810a4c35593e2d08dde6aecbb88ad54f +0e0598c1e21086df6a0f532859d2ab924b9b93a08e16cdbc672689066ca8bae6 +2cd51a2c0aecdef0c7d9279275fe18c0a1f79ec29d6491d4907a43a77fec2190 +c309bcd039915f62900408587d5edb710003ec0482618f4fb9898fc9a81853bc +f8240a0132cf4c5c1528ecd438229a3ca73423c0056325c12d26f5dad707ed96 +549b9637efa8c1ed5ba979527258dc7ef35223f5e2f64ba6c701c90036203984 +761d1a178d23a5b0c7f297b4918e220f57d9cf9408f34748333d67527135cbfd +4cb0a085b239463099f8644e7a33257e2b511562d36412a00c4efe0ba1e2d3f5 +e90ee3ee3dc6ff0e36764ad1edfbbf42b97fb56faa9015a85a8fc263f4b72aa3 +aa6d359974137d99498e8e6f518cd36db21eb20491b2a556c6300874bc73e9fb +e0273b75cc23a0f4230735807fd2010c6b6418cf90083eed0543c163c852e76c +79790e6a33d914932b0594d418389a6ae50284f8ccdefc350c6b6bde6ebcf4d4 +da070d8e4bde01cca59f6d75dbb205228e3e2a447291a7da4315fe62c3c7ddd4 +ea00759f8d9407a32e6285a6669510f9fbf54414f693ebec0c71893a3344f33c +265a192edea51fa1bbf833b08b210f0efa8a5d418fb3ce97504c5dcc97059960 +22949d231b974b0c37638d8236c1cae58e112f35a719b4e54c41c021ba4859da +2a2c9397f412fc20c1b0c7429328c592b8da04548c97d83343c1723a4aaa9ac3 +835186d437bb9e24d514530fc898fb8e5f5157d22a1acd023ab3f88f62281820 +d958c695c4541cdf1c8fc8ad538dc80905784c52c4bb74c99b9cb5e06127c284 +4fb5b9c20e53c842a0640b6d5d67bbba04663e1339e1cff1b4ea918fa79e2c45 +84a978e648ebbea680e1ca73d9354536fcefe57b8f983d9a89eb8b68979aab44 +28310f85489fcbc3d51f9fda5a1c92c21e1244fd2b668a2a85b1d78cef5191ac +ff3a9e9ec4acde099e530ad052962bb67f1292f994d0b1e279d8e68a20cb40d2 +cecd59684241f224a5b14e55857714476e5cc88f8dc462a1b94c209bc482d4dd +4c7f185a0e1befdbccf52d9da58c4a27ff8ddc38d0651e82415728dc38ec1cfa +5871e2ef24e46e0c19f65fdae2a7cf642b8faff29de72e0485009138572b2a9f +7cadb3d918b58e8674e88358d125f5261de1b87ee4d1902ddda615a6dcba1921 +e9f856d98660e0014457914fcc759d33260f5f63324639b03b9a683ff928057b +015f470cbdb001ea956861ab908928b8978e22ad26d240059f775c7981b6d720 +304fba4729eca1e3bfe366a5192b05683c5d6e5c6509840acd59f097aa72f5b7 +78ccddfc41f75cc5d22514ad82b3ea08cdac0686c0bd396845a606e9830528e2 +c48fe36344f60a8530613503d383f38dbb36ad864ff0f3b8650b228002cf6cd9 +e29425c87fe8ce16f35fd23ab347c551e4ec4dcd69271651fd1e963ffa5bb354 +1dacfac97b9d30c6baaa643c04a4ecdbea8414a1da19d57504c7e3caec41a17c +b84d90cd15010f827bd1bdb95f8199169b35a26c8bbfac6835f386c74f5a9f88 +f4be408207eb6046e2ae92906f7904db76da0d23447733e6dbfb7f554d55001a +6c1b60e1c898f45ace7d62dd32689dab8145c07aa1eade386cf764a60bd611f9 +6acc3d13f332f5d0511f6176ead16144547551284b8c8d608830d1c2d60c8b18 +f3314ff1a6e3abd50ec45f7815a91fa0695a97e236aa61500a4d16f8e22dca0a +577f5d1826792d6cb8f375aeb30af65e5bd61dcaeec6fc4c8091719337b8d981 +3cdc0aa55eb4958530cfdd46d2dad6d24ec98cff49981e912efc6706d8d9074b +f6ce642e69cd4470b4b725fe629b4293efc48da27bc62a752a17eddd25532b50 +11c9cb3893faf02141b90d334ef6208132559846ad79eefe27281f772d1852ed +594d4be9cd09aeefad7f4a447f8991c985ef6d05d54b62a8a096769959c4772e +aa53971c31ea13ab37ffe84bedd794719617f9e888e82a58e0c9307e05d62ef2 +56756ead134996ec9d2bf6a5e62223a04d869f951c2ed18ab3948afbdcd156f6 +cb2b04a9c34e22e212410ace47a525fd5a12753220cb3a85648fec2482068745 +fd81e83375005cf81feeca19c54db64c82bb35cf0e7184b28fb66ee9baa7b326 +90a75e7d039a7c1ca9879f8c5c532577030a4ad54741991f93a7fd6e7ba24000 +c73e9d4076fcd336100a669a9b4c31d9034bcd51a09c6ddc5cddbb9996cc4eb8 +0456427134fabdf830460695e0a8c09d82a45459a4f5bce6c2f4c1e32bffa6ac +59bd32a20b27ad23b3930eea6fd17ec4f9dd6b9ac505a1f949d95ab1e73369c8 +d1313cbbe37ee9f1558131dcb51d7c29af8eabc956e546719d5edeffc4077257 +f75c8135e4644694c37d93e135e25b77ef0e95f7368d803c28d5cb61adbcfaaf +de062f9b248d8940232a8bb9b72bffb14b3966da3180e4b92988652381305c33 +ee36e932b4469fe1bc2bad393bf41ea7046715c31f08ddfef164143e021c3c7d +1721bdb0a217aa17a7df5a031ee95e82b166f74eb39314320edd5ac2a8668e32 +8a9576fdbb20dd62eceaf7dc6ea4f6b93727f3ae79521ca8c94e93ee7694e17c +9ecd11b568c2a63985c53c0ea135c4b260c033b96f9f3ce9c3867b4276776bf9 +33a4b20daafc7e8fd08b24a57d5f99aeb37198a4939e5934766c4fec640b9945 +eb90c7c2100e0e438d8c83dae543e4857cb9dd6891ded16bdf4ef4663cf56a73 +a8a5220e2e001e3a6dfd3b714765a305b982751bc3718847362bdfbfc454e766 +8ad4cd85a2cff316832aaaf9a89a70beea00ab3efaf1cd96c537c6d83e124f76 +13de5c7d906fbd65c0937a61059dc2e6d990f58b30c9e32a053f6b0d6697add4 +18296cd9f83f72740f04815725a8884517803403b95c772a56babf1ccc7625c2 +2cec4d32acbcd28ff9c7addfbe8291ec7555a01270519265114d8dda4e0183ee +4c8d6c7b9908d61e6611b7e32e36083dd1655c02a8a68672f8a2eec5c47e56a9 +2ddfa580743ff8ee428676d2103ae1cd77ae07b524b3d4bed1be33204b6f68b7 +15bad94d3552440a29f10e308560806859d7711da272af448fc3fe1a526844f4 +09a41fe24fdc387321d429558185c5ecf8f474b67d0829c03597fd877f86e0ed +d15780c8592ef4821df1ed1b772ca1a41d3171b8d46a45db3dd37d93645af4bf +6f53a5bc3e01b6306e7cc71c43cd856d8a972b4be3c84ff023fcc652b65d4645 +72d190a64966bd5930ede8b7fb12b5e89844685df2a364c02e3cccec5bf60e7c +c3ddc2c7b2bc7809e9bb58b3640c30a80bb8bc8b1596dc412712453ed63d7e14 +4a3efcfb55613fd1bf1b3b7fde6eef00dbf0949b0ff21e8f2119e040e09b0fc0 +1bad86d3ac48a86b8a542eb6913190169ba965c567f0bebeef588fc847557537 +be6708ba5389dadedeedebe0e6c21a65bfb1eca6e8169cc42417a1aedc604a70 +5b2396c8b1ff1f8fb5cbfe8c736a14a5fcf1d89d5ba6780384c5588e8eeae83a +1cb88bb879d4fc731e0770871a846ef1869591e0a477bf8cd8c3689791b9af49 +0ee82cda972000b710d08553fb4838ebfb833d62d54913989806d1c858ac05e5 +ea188c683126853ce9a2795923c10d37cf1bda22099acbfbd3e85a5b978719ff +337208d3d3288e84371bfb8037157a3684109f8145981868a1a7d14a7b1b12c4 +c8890acabd6b9e792fc55ecaba1528d0ef5147044f5f16403afe8fcd9cc1f794 +c98bfecd26b587bf281f813080118f4e96f2e238455f3887a94fa5f207367327 +442d322f4ad674dfb6766734314bf4259db11efbfda913d3266318f511667f96 +2143e3b464989935a51c206422ce2047bf6daf9f868dac2236e3fd91fda97865 +d06a7e5cf95f91f4e5466c8fdf59d972b4c6cca43b2eb935244397740d731d47 +dcbfb7102023325fc822919af4f0cff18234466d7211c4ecfebf3c5426e36571 +337fa99aeb27e6bde1b8c32e0ab2474e7d8ace2a7d488bd03ad6a9a4134c6403 +97af59d92bc713115d7cbabec7cc08f566f84971bfce7224303c7b3608879785 +9b1db4ed59b3bfdbd07c1fb994760bbad3f341a5a2504f830feb71bf35b79163 +3e86370c05b34e4665c18b18077b379e0aa52b939b943fa07be8447623b95cee +2ebe909525f3472eb82b8f37d8943fd458fcc11eb9ac4a46a78a9d00f1a48540 +dbe2ef48be21bdcd80a161c81451a54e77b787bb9fc9ed259f61b5e4ac6543c2 +b98e03d22cbc124403761bfbcc1519deb31b87f4cc906bf98f9280fb89bc98bc +88b3e415632e1c423ab515ac2c2631f36120dbfedcc2093e6c411fe740345bc1 +8b4fbfc8a3f7b674c551a2f0d7a0e02cd89d410ba497b88eff14b165d4b5f5d1 +99525bd0f3b86fb986ff1dc023a0dae4ae53c811e3670a1e4dab11c7b0f2279d +80e293600e13ec68b497a3c0c6a7fa49f12ffd805c4a8e7b88001f7eace756b0 +1add90bb4a35f6f9c405241364ab7e78efd5c5f06ed7dc295b976e56f8405678 +3385f08c77f9c05dcd4d03e07d0df829ef384d01ea4d3440eabb730feb0e5135 +fd2ea3ab3b613cbdf0a23e6de75a1c98378cf8f2fa5c2003a3eb83837be39f91 +0a0214c31f075b99d13197f98a04f5cf362cf4f06e627092cccb25e135730590 +20c157fc6cbd3d42b4b167bca99cb89ae0672bb04dfcdf315d8072d71d8db187 +e2a0776541bd6b9706a0801e0581c855673f4496d2a16e4181d70e354c7b4a10 +d916e367ff0f81faea2cdd5bc1d2f693e7159507be84cc941d5953879bd7e8d7 +d36c3ee4a5c72e40868eee3eac4dbed8cb814202307bf61fae8e89267d37e0fd +8d058cd9762d337893a88c6512033e414611009a854354ae43d6906fa7415050 +cdc4924c5bd46e0e881b76e48ab44e39d551cca084e102f4a75210c7b4ca37bd +82d5785165ca8114a03472f3b26379568a7459faa11fd186209801354d169f15 +f976f53588d5e12371931d1c39fa0419e565e7eba70e934894a6b776058c89c7 +5289c1674abd7a80b1c41731d93a7dbeac3e76671fa66ebf3454e83c920a13a3 +bf44b25f1d504828fc71a6bd8137c720339f1bb6abf25e592825eb27fca2daae +be86a0f2dae0412b59451878a70711870fe01008d20b5255e1a55bf6f17211b2 +fdf0270bb4009934abc06fbd80164633e048f67f80f6200d02c321eff17590bd +a5793346ae5c0b2dc1e47e41a264cd5cde63fc65004a2b788ffb46cafb81c041 +d8ccc2f8ddf7fb62be668e63c52f14d8cf61cb33a93212e136703c12995b92c1 +58f1221cd916883b57446a69a1213b7c0dddf430ab2909600b16beb9d133ee74 +37cbd80c2412f94ca15a7ae55e55e0c5238626b5dffbb6d3a11edee267657652 +51641cfdab64856db068dc3369c294ac50bb56d96d121f07fb44c16832ea6750 +1087b3f6f53d0ffe9483cd11124a12a63ac342b9d89b3d9d5523caeadb3067e7 +0127a5de460922ee3935ca2bbaf560143d6acbe649bf30c5d2ac114b0c4b27b7 +f3e81d6697306aeb746c08feff2f5a8a3b5f9c3eead0afa713c86ea09585ac55 +e6527f8f1f1cf8575e8344345d419fc5ed753df2cf98b8b7a0dc0f192ede34d6 +9b1a571a446fd911d78658a7b6596d7a8cfaa9e25a918ee361a96cf897d65d78 +f0a142094eae4d825d00fc1031928f958420cdfee57ab2fc3d38e36cda14790d +80d1c338cd77e9ea50e68d167cbdc1d3f37c7b37e1b610652abf5c3f2360d1fd +7074b10cd85742a2ec9ef908b7943da5f2491a143b9ff99f1cac2bf80117f85d +f2bc9e4cf7854f63c4b0eb103d868eded9cb365df9b5e329fecda80df3db5f0f +1a7e458865e54e5df0504f16da3e5f9879ab1c7a6b7eeb9fa5e59e56a3ce519f +7b950b8d99942d4a1fe670f90ab098439334659cea9156a8f3d8a03b2c3d4d50 +9ff613ab2720adada9e3055196b8c63639f03924eb45a95f76b7197ce70a8ad3 +a9337f5c2016a69211e1fe97be9652f851127fb5207cba990c03dc957c44c689 +6f0b8d29a3f52d0d7e5af968a779fefd473cb51365a48228d8441aca1fed29e5 +f7bf4be839dfc23f1d6d84a7151075b038aca5dc602c6381a94a90c8bbc1fa4f +e84601189d68e5198c224140c001712247336f490116634e760951e4a397ebe2 +40ea7794b6216ae53fe1ec030a1e51adc1c1a67b3c3893befbbf08e6f385c50c +c42c304b83c6a9853785f4ee6de79dd021f2695062645d106e9915d567417659 +99d028b0a20d64e23c216690963a1d6e7c414a7f97e4a719a89b7c6a5153c8ba +87670385bb30ba7c98a3f065ed26ef10b9245a2318cae4bfcf0aac90e742fea0 +18017cbc6c004d92af8ee4f43a372600be011c30a8bd7adbf54be3077483e1e7 +e2b5592ef1404b03b891f063a6e5437d1ae0033fb42e18ada9d2bb04b07c8a7d +b267636e9f246010890a37da432956aa67ae1d68a8c3e1dd00614c0d994ef53e +aee7a61625dff52bf8d7757e8bcc55cb49147cdc2e9e389a236d0b5ec48d3d2b +7daeabacd61b980d11b3513c4edc30096cdc44bdd1caf502cfa2d3f18ddd8e59 +b15a4d7fcf50899a27e7294268d3fbacff4c75ed4ee843a155ad8e6ebef8aee8 +52cdc94a466213cc13c0b421db8fc6894a4c6855a1b471ce1636681434581c3e +395dfecca77d1c944b66f99d20cddd3e36492bf5451662e0a5a42a344bfa0163 +c66f123a2c3876a15b521aab8ad81afa6178bfeb620fdd4ae74ccdb2edd9aaec +af3e813c82691d30a0dfe3a75a68caf2db3982e89b03cfe1737e5f5d9962a775 +e16c675d9e1820b0d85018ccf06492dedc1da29ecb4dbca68cdf5f8323fa0f94 +b72ccfffcb7e825e3b634990a4c6d2ca8301c6611265f6ca8dcd3b3eb6ec341b +8a11e9c0a33f2bebe1496270788cb336b254d443e8ab343fe38842955f810af9 +32f37257426234e99e0e79f3a4b87435547157781f7e74a9c0a3ce503c30f583 +0b414a79f81577f807c2577c1b057f8022c7ef5d78208c73b7495a493c954b10 +1980901b38a17769a9cda4bf2d883b04183f8f68330e0be3c4ad0d3857e8c10c +96c6fc29155351786a4c85432f5c838263908f462199eddd45918c97ee95055c +81741178642feb53e9039f58ee51ae93418317f74eb52b6467e6d1e5ff9a1ff4 +8ec9cc0551768330dfe41f17c8beced4deccd6837f1fc7da8e4c871316a36813 +77ba655ab28e4c09168b3fd08fc0b0c7d3577c28493db9f6ac405970175d95a6 +5c291eab6c217335ec9fd1dd24ea9c1a32660dd70f77c26ead967bae0ffae90d +359cb66b315c6a1ed57c1ab0fe1d5ac164bbb2e17753e94bdb24df991b60949b +bfd46bf2c4faaa818cfc3e94154e5b5d934136c66c0016fb1c1f82e8d0b487cb +b8f256f8886fcb121c8f3a11854cf398462f262f777eaf6301cd75b13f3142e2 +c39f01d9e001c6ed7226014e28e7d8bd2bd0baa1450c1577855d038f7362cbc2 +22c7210d407dc84ad568b18f757224900a678b7bf079d84af62adaf6b2d3b70e +7a30085792a0ecea4a02450bc1093f86ead4366a12c9aaa3ee019469770a7018 +4edf01435a4787e5836b115a3987652ee65d8d7d0ba5585861419b6d27899212 +0dbb2e6217dc20f2f6979267d56ded31253a120364abd8c1a58fcea35ee2500d +ba1dd8c7ab4ed9ea04bde76923ff725e6667423882df901082aed78ada64388f +ce44bc07b089e8b77db1fb1606c13a8c607c5dd459e6c5dd0d0e2569b2821a45 +5f70aa72ddab1b132ab0e7480ea931f0006e2d7690f29d1dc5de37c4fe892df6 +335e2c6b3368c8ab9d19a2e09288dbd513d95253dacc8c21aebc9f4e0a05a68f +6e94a7159cee3256e3e262ccc39f4fa18b69d55bf8a5c1fcf8383d078920b8f6 +702d3f8709ecd9b1809c97bb93a569a6d977d08a2573367ab34e3a96d2beed6b +1874ba217e03d16a42d54d665c54408e125ed5fc2aad300973e22c164983e987 +2aa87bb6f34d2c8ec698832f84c92c87fc7fb0c96119e32228845804e27e745e +e1577931badbca5635c2d56dbbe5fc1573e5da768219c4c3871d832755845f7c +0ccd258aa69ef90d81253d194067fa1a6dcaaf9818b5fbe953c0fc67be05b195 +c52ef29956630b137ab3f4f4eb45e1294ee94359e10048dd1da7a17156ae7cce +a8dba368fab9e2d5d3635528bfe1dd5a526764e6f2a5acfdde35360d208785c4 +b27b295c8f5c3ec608a380511f619c69e65f4683c9fa9b61a8b72b7b628d6e20 +60cbe640f7372def47181ab9fdae10c219ae28686e656d35c1bb064523756f9a +1b3137afd95f1deb4b2b4963ac4c8beefc00813d5b18cee7ad40c6e557ecb4a4 +94ae82a8a65ca6bb9df0b159df43712a4759ad2a1ba906974cf916a4a4b2a47c +95ad8110cf34808f7b1b0d605dd99e21146f7d296028f5dcd0827845a58e928f +7dbc3110a61a293c6b7b5cff97814648c7f323d761768888f351071eb8371eed +7677cae290e55932bcf4e38415b36078da12324fa110df1e9d1f4f1d9ebf467c +d412a9d8aa86a0243c5a63d292f74b5f0b90b796279c00d6983da697a1325950 +671064ac2d6a47178349347bf2368456c08d07ac32bb1466fa1be9ef1a293a58 +857532b9050211ae50858160f1c821733a3dcbde3fd69c5c0e224276954255f0 +af44171817b567950b25812cf5e8249b683c13f2f9536511d673eee3014b5011 +c08da82a104813d3ce04fa1a9a4bf53d0d6f23904633ac9b61ec90687a120c58 +e5d129cc46d9324796c7a617f7bb65370c98f461333e598714ad3dc5ba690f20 +e34115737d71986e24275f7c3895a5be744e34f01007d5ff4ebe7b40dd789f57 +146170d3cbcc0c8c84184002cef73ebb726e4df04a4431e5806dc3bee8ed626a +952a21b36d908f6f3f09d547d085f1526ba3bc31aa9c8af70ab6284cc8acc753 +e191d0ae237f9a2464388334dadde4c9fa54232fe75ea210caa2a0527d42f204 +5b4f49fbaba06cba116bed6c5de24578887d4564fd36c4dcf6861f4a5b4c2e2d +2f193e93a51aaa0218488c80a32e7e4e29a1e9fc93fd6bd7f38673b65dd4e35f +62cd153274a84c7f0175fbdeb0f1df4261bfcfd6f09e4cbb3902f648d40ff502 +0ad407b36652db41915d2e2c8f2c8f666a557c58b4e2fd5f58a6613f924d1165 +9327e8937430f9949639bbb55664b27f6a9fe723e83e44e64e6f64a81c781284 +3d9e7c55552404b156e87f41f1d42de2e9ef1348ee9bfa86bf38d311bf815c1e +915280383be90766c0f6b3e667811ae8149c1a78cd662adbc1660b8191cdc968 +563f4bbd53e57cb2e07d367892f42c74e643d075e58ddad3f58942e0d1fef622 +c1a0a8a2e1efea818d44ffe75df8abafe65f2eae1e0619533f5d4e522fc832da +a893499072192adadd59b67381c9b397ff740ebb3249022a7a5997df100d8dd0 +4274b0b92b5ccf5de7764bbfaf6ebafac3da8b6aa5a392fadda94d17628bfe5a +d0a2971ce05939d41616a68dc129c680447ad700e34ad245da5336e3bc1aa8da +e4e874d2beef9ddf3571759c70ee8194448eb9f2a313a74e2bdfbaecf51a6edf +66e60c95bb1a8d85047c1a9e682cd0b42d8e8d281ff87fdce0881d2c5f575545 +f3e148f0e7e3f22f3b1464754c32367a66dd4dd51b6ded1e69422cc9767356e8 +04632930adf233959f31e69ae7ee58d40cba7c7d26c272e8c96c8bd26db6063e +ca83773aa63d0ee66f0e9c70b85cca8fd4b454bfe3357293e43945590cacb503 +a15b1de9a846aec0acb168b1a30a7c38ed878a1d5e7eee93db62f4379b10c3ad +f71be7cd8d0b39d1eca9540b87ef54d234924158dcdd1d53266efc925969cdb3 +b86e3474ac0c48a4fff910a8292c70c621fedc72e282d0ed76c0a1147743be63 +f064b1f715a07c6baafba8feb558ef3374e47ff98857d18ce9783c789c99fb91 +953822a2d71f8db43e45fedea79fd49c33ed165424ed12f834bf57966963aa38 +c407a0db2dd259405874e3026dbb3fdd003e234ee24be1b56737447a8cef49e4 +315223afeb76626243822c00bad465687c7fd6187e546ab1361cdc49ee1eb3c7 +e6c372e6571b345bedfe853cf78ab7465e8538ff2d8a55f2fac016a4d1f914b6 +33c439f9f010c3f74878e61e60aa60354e0f0ed6dc52d5e1637a741d72ccd83e +add266e4a42a7b6a41618dd5adbd80de7c61c5e1e40445a5b7c889213fa91b92 +1a2a81f3271776024997cb8cfa342ade35ac2d0d98cf006f0861d7d0f16dadb2 +889033ae095d0f738ba00f35a1f63307fdc6625fe2452f3aeb0b70938df15786 +a77fb94b18897832ee6d7b91345ae28cb06c59fb10483c97c4d9bc93a042999c +6b34dba334b4eb658b43504a1f907b6d4eca56d7dd9a5b5794455784d1714fa5 +45cc09d1f7a412c3351794b6d976aa7812e25279390823dd9cc81bd8ccaa28b3 +0004df9174c5d6e28713f8266738823821de8da93505104e2c0643abd99740ba +729796727f0db12f7fb72c1f6b278c8467324e5b22a7d40be9b21e3f978dbbca +8bb15d0a3cef8a871bedcd3abf839ffedf95ae6617d6e07f8f22c7564868b8e6 +49e77adcba0c167b77c0bd5917096f2d51940af46ce23e2b2d9720c692d017d5 +8e1dfc57339a8e023c1e89576c40dc049e2785ab2fc3d15bd6192954b7e00d74 +71ff9155a89cc87e650364c52729c33971457cf61d7ebbf3f70603f9d10ffec5 +ace2c6755f88f4a37e4770a0dfeda2717de19d345a47fb660f9a4b3639c5381b +0a59754d61878bff36ba6566eee1257471e6e6e11bc98d92c91a3b1aa0727072 +18cbad39b156a771b784f879afb1f2f036aab78740c47309a81b7799fd74604b +ebe47d5879587d422914236335b9dc9e7c8b0811385ece4166a4d1e4cfc60b48 +80eb7eece4d8b49c638ff0f9d729de43dabdbd301d84de77326d44ae15ba84f3 +de9ae5b991fc377ff43c822646557576e6194d080f40a04ad0c0b0589b0248e6 +2e939fd907021398309a0ba4b2e381c326007d1f58648782b86f09d8a5399b7a +c489278f36d20e12d2beb471ab25e39bcfce8fcc9aa971562cbef7d0a4bb408d +e2e01340e2cd9ed090cb787ae0f2a1191745e34a68955417dcf131f86f763558 +2df98fe45042e71f4ffcd7c486370b014995e13719180b1c689e77c8e98cc64b +87f76995e5398847398b94423ac4c25b95822ddf597937b0d3f5d6dd7ba98f31 +d5419baaf4bb0e058e97f0c660abc490caa36e774a160afa9a1e53b8970e423d +0e8745fc237e1e15c226b1baa96e6a2a0692fab8034ca5a91625eb2672750e0b +f2017c864f2631d9d143b89942c2c9d6012f38417325963a037b229f7969a804 +15328087e656fb9f93e49cf3b3cf581218e8850df19e4eda639b13c9de484bc8 +2243a8a3f29a6be7651c31f90226b739b4e822ac1984b216663b0d86a1b88f14 +5cee96a185d5f408ec49889276bea3780a55679b4b2ec5b3a95f09af81c994a1 +f556d8254ee80277502939fa19479bdd6eae6f53435a1dacf214d75b9f113f40 +675db73d2b432e7c950dffc7890a27bba1d9063424aa17757eb9b2a73911658f +6031eaa55cf723be4e50a139040061e7110684151a7d8fd2df82ceae5e9d6be1 +d2d3570d32452ed44bb4bc7d42991387567f7c660e8348d4d9838f55d399e538 +9d225d45f7b10957f746dc9cbe32c846f191a6fe7412bf19f2de9f15ab51d74a +b4e8055fd410f83ef80ad66cc9146cd805a29dbe18cb4281b918186891ef6e82 +933335309fbd8ae874fd7280d4b88c924198df2f861353393f405c49f266b179 +8659578c6b5aa795c4b03763805db50caf43c29dff5175779d80b85d95153c21 +54873d9f5c33a862ac8feb8ca039a2e6d96303f15b4789c2a88d21b86fb92598 +0b9c0f0c087f0162644157326189a636445bf3527e85ea2b1fc535bc23dc3c18 +588a1bf9abfdcee18b82805777d938ecc1bd6123780f59b09e63d2d8bcd8f4ec +59664689c390c966c34e7f5378594f1ce250b799ae06ededefc9e900a228a5e5 +0aa1b99ca9b85ee273ba45a76719d61e13028fc7a55a3ec13a06e18d3cd606eb +3592e004556d8516e0d13ad4e8c85e823b873c9723191e5fec9740a750a407d0 +527a4ca3afcfe57fe6306469443ea34544f53127cba15d2c46a579973c94bf6b +9b249a404a0c95ec1fb25f2ce65c169221f71f0c30c8cb2b8da2e5da239c6c1b +49a7c3e7cc037d63233d341634734211b6a313753504db203a0c2f6b8ee39a16 +200b81c2a57eeaae47f977ba39de1ae8e9018474c3dd7f7deab452b4d35e9095 +56047df880e94650c4d9992adde2776044248d6da95b22aa3ac1e69e59b11111 +db559ca3b47989ca86e885da154b62bc5290c1f29cd0394b95a50a78774ff796 +6d8560a6da97a6b3fbc7c122fc36f095722859fff688b5aa6d5ec437cdcaf6c2 +3e47a8760385b1a504c4176dfa628e43fa7cf3a56fac4544a03198bea7867063 +389341704549feebbd905f7566bc000322a8b91bccb5a5f374cada255731bd97 +40d9de1f3feb7ba0846e46ea3e8d89e47e3ba77b1d952eb612e417eb81dbff5e +f8ca2742eef4101e50fd8a8cc9ff2353e61a0fa4662e2f2c16587b2e1fe29656 +0690f89ffa473e58693e8474ec369a2506912ebc380aea2d1707adc895a17238 +854ce757119da3ca09ed2e2c816a10c7ce4732b374148198fef61123d65fcb43 +a0360d58ed0705c66b538de0ae94ead29c7b226f4ef3ccb9d889f638cbcdbc7b +26478fa48aa812754826c665e07a226666f37bea5f635d035087d02ec08095fb +07e670aa1b77ecba7b44111410b9ddf922fed806f834cb5cb48a8c816f8eedb1 +307b41d498db52766ad0f843f58b9dc70107ce9bafb9f89624cef63e76293f64 +e249c9069fe04c191391860b30b43bccaf1daa16c5114e2f509fcf3181c737fa +d67782bc7eb1f6845bb30b0d53ee8e4db533d6b433bccb2f1df16e1abbfc99ba +d144d7bd4987288ceba32a93ef96dbd3fa77016230298767466e055533325263 +85eff7e2b79f639e5d7e006a0b11094308df2220f14da4bde9bee8a0d32d1ea9 +a91173b965093354e10ae3514cf4d30839b576203e58c47c3a600de0319ecc44 +26d49e67c8c5a36f924525dfff0ab505e112f8e52b5232369bae0daa2c02aa80 +64c6effbf9158fc26e4cb737b0765b2aa5f6c0d1df0b053fd8dea78719528837 +7e1f12cc08daffc8d09f80e68e4f29860fea18da7bb43e127da620f4a0bfa1dd +907ae2596f49aaa7655524c7591c2b4f97ecf6817ddea546e5bbc0613534f7a7 +9211bd9f2bec8a7dd3409b005112f8a48b77d67ce7c64761c6c52bd538e2c3e1 +1af960c4cd06b83bb52d5394e9579b11ae6b220a190b10ac605ba0fdcf519371 +cbb4e52b1488c68f1e76888dd8d9955896f9b9f827209cc714fd661a547f5ca5 +570adcb8238266784808354fd293277bcba4895eccdc62ba648d6acd612e568f +8a1b5a384d9dbfd5658a55824c88587cddfccec8cea25b4a03f8c7568d9f1e52 +cea809e80cabe10189c2f1643a086f20323344e3c7427a38900d8cad9acef2a4 +289cc98a33cf6acdd5eac7484aefd2280b4b7a0e21e2a30181f075e6cd21821a +3fb2fc3c5b01c36b627187151fafb113108bd6b7359e9468ae8eccf29e47fe75 +b4d621421b764c54a7c729e04c93af7bcf4a66fdc06cd1e01a080dc5de8e3940 +4117c8bd66daf42be4b5f788c9458832382832109e31a44b4996057f3be0211a +36829a5b62118c5e688ba49d1d6ad6ce370e78c46a01b31e1b41af9d256a5d88 +bb1dad8066a532aeac726108ae7c5dc46ed8b03d0aeb5013830723c815ab4aea +720a9301ab30028d2df192b6e364e3e2932d274e8c0167f8806b0622e079d451 +302be712a481474ab7836212a84e71c40ac7f09ec43d7d89eff46dc4c30a786a +633bf24c791f0c24d7bbb289ca5af28f576b1f82e2c888853495fec8693b193c +331b9eaef45b813f5f9e0cb1e418820c1ed230710337c21a84e6380a737a9f88 +5f68d7759a6a559b516295cc05ae396108e9c1e2e93574d40c1cc061fc8bd6dd +75248ff58ab9a17e90da5c9de7e063168f289e865ff82fd2f375d7a8153c0995 +13ad1b03ee5a3ba01cfcda6f095640a2f02c39e4c236fb06b04bd4c41633728d +d04919fc02929a12d1ca6d94c8f1c27f47a7663d035e0b0c86f203d6a18ce136 +4627bf3e9ae1ac5848de91a30a644be2d2fd9031260669a1e3d91a0561a3f128 +de0ce74b7d9c670e5df71c1c86b322e353771f6e1e6fab569cea1e4da3b95168 +a93c42a0947716eb4a00ce16d7d65a48a485afee1c911c7954d09eeacdef0f8e +f684c4e7de0d0546b365fce208643b11b46e51928e4fe729eac09a27a3c5f87f +3ec823345be0acfc0c86a8266cf576d353bd7db47493be9ce1ae26bfc22dc882 +a28c4c73a8845b7f751837d7ad65466d8a89e967d21b4f3d1f35e3101570ffa3 +a4f979df8707a0c79130d8fb2e1c9c8ed3a5127fac437a76d237a0bc1644dd93 +12cacd1a4152df315f886114f4ea7b275e961a445e2ef325c6491a1af8bb7d75 +c75008e1478bc88d3ec126f736472a5efcee134e672f55ccd1cc466597fed0af +b7094806c5bf1ae83279b383d3115da0e32bd72048161b0f7ddab6e2431bce37 +c0d4aedd6eab2b0936b24629100b74c7665d39e9f6f8d10ba96464d0a3f05017 +166314e115dcbad9418e31044f91bc5aaf18e1bfb90a29d94aa5e6c23486c250 +ff401d3c922863e46cec5dfb67f7a7dcb1224a0745faceeef349e801e363bc1e +5cd4d7ea4c15980e456c2a08b508e7d678ad412b212beef1d6b1c55291300562 +81634c293627090e0c61d88b3e36e6f087944825cf28717ddcfc067f6c5f6c2b +9f4282d32dce6b1e73a8c6f56675f20e122abe73144bdb859310a3029222a91d +60a4c5ed9892ec5b9ac93744c0454979a57f2669e0d46c04e85bd1d8bb1684c7 +89b9ed812824a6d414f1954dfa40bdd95d94d9baceb856c0caaff55fb89b3669 +067b3c8280405f6f9da5227ea5bec87af16524a93187346635e73c77f47e1dd3 +251a52deb521376b1c65df61a4583a8d940c85a52f97674f2be09b22dde3abff +04c119495a86f65e60b0b7f68d4ebef6eff903b92cfce68b6ca2074a468d3701 +cea1ab37040ed573900db369dc64ad434bcd1cc1a39970841816cdc2ed4106d4 +22182478c3ef96cc690e471fe81d9ad0ad8e7e5503c312ccfec23b308646153b +5b9c5707fcb863aa5dad5100ae7ecd4c02b23b6acd75cecc0128d714c5d84152 +2238f9ddb4ffc2cb215f1eaf8994e2af610f443c3c696749a3ffcf420cd2a5bf +92a5869e3c160975ca101950408eee0315b13be4082994f9465706cb87bd36dc +a10c84f5728f6cdbc6df897dd88156f3e0c18e554d17749b90df4da83e54ba1b +0922ed87908bf158764f5a7b647dbe4add493671ae0c338b6ea934830271c3fe +45a00138176aac9ac1224787c1b17adceefd4749f91eb75d3d5c51ed8d1bcd1b +26c593e444083fd82bb3960fab4ced4ae564ebb8424a8bcc95077cf5f3cb3374 +74bdbb35f00e616561143eecfbee6e5eece039645653ceddd53486998edae733 +1f8fb385364b9ada6282437abb99e2828d04fbaed605f1dfc71e532666ab7a4a +588516984b71ae57c980ba1e1260e8fda87110281b9d5ff68134b88a1d0262c0 +ec758d3b9dffff0f86857192e1776c0fde5fa2bd6db38626ff8624950c2bff11 +7714093944b1c6785c86d4e55dcfdf73d86ae6338edd333bc5ba84b582db5d8b +c64cb7b9977e7797bc590c4d893c559af4acb847e780f8780498b71683624d85 +76bcf01849b14d6690888ec198cb495cd933cf1e8b7b80b1662d33234b511bd8 +9ab4508f0f43eeff9bb2ba9b7a88fcf80d9a8372fa61ffdfc48b84c2a0706eeb +8b5f0ca77e7507b5365dffe81836f5a2d6cfe2ba77015edaef9944797beb6e3f +6c095a4f9048b9748f8b53db1eb3f6f1addf97faa4408b2427bb9136a2fd96a8 +55a55aa3b6b57dd6dcd1ecc5abc3bb226850811df975a8e773e199ce4fb0fdae +40e7194c2f7708aca6ec4bcb026bd2ff886e6be944155700b88be6011cda3274 +b903da62ef527a1dcfad82a6db26d677d6773fb53fc721c4a08e88d49a7583d7 +c6b80ad5d00db0cbf7721e264646e5e60800b007cca3374c3e8cd3caa52cf179 +f6845fbc7f5e4e135412483ef2dd18483c175c62cb1c36467b971ad98843e9ba +55e2a830462fa6e548575b3381d732aecfbe2e88ab2fffa0e6ab972b1e161f39 +f85f95be6f3d8e8208909f75a189dc1798ff27b41dc3374ae19c72364dcf20cc +c1bd2b56e6912331797a30252e5c598dc79a75e9adbae2554f808a6e00919e99 +eaad8871ec840c1a2cf51fe27568f24b30140bc5e8ac16be902b592484caa264 +44fc9a00c38aadd17640cb520fb00fc3ed5b8ef01e52ef44aa711bdfad34c774 +1fb44980da57ddae2f5a871850b94bac9fe2a60e273fb4aa13309809d07acf6c +2e4ae4527fe18423396364ab90dc7a9a8bcf85566c294648e0f73fe31f8cf150 +fbd92de67858e69ff3248a5efc049560154042076b8e2bf41fa36af2bb8be648 +35dbb541892cb66b3ea7ddb7672b6baa42a79a065579208677d1f11019196bf7 +b210421cbb45badd96159e92a294e7d81ee1b80a99269e60df4acb6a9a8291f2 +48324da99b767019c4ef8ae06dc2b71cc8b9521bb26f9ad3f58e53275e4f06b4 +36f12c38a9932f48ff9c99f30f14394c9e1a949030735dd41b4bd6eaa403b0ab +cd2fa093575635f36cd0e0fc01376cb9294d877789f10e1c6fa6dc7e749caab4 +79acdc12441ece89bc62bbd958789bbc5df4dd42c2d2e6e38f9637796d44e16f +e7d63c75c8922872ec4397837535a5955b2e728d8ae6316a2b6b2ffd07bf09a2 +be0518c1cdb5b5010b94c721bedd9aaffd26411caa1b085d505f3b0f4e09c46a +7a44622a06240fe897494f701614878aeb229d1803ad43c5cce6b7817b2fb27b +c351030f05399b558f0e1e02e69009c5dd8834b372ae3307abfb52fc8edd941d +d5b2ae81bcee24b16081834b5a51ecb586716a17ede7bdb20c1bd9856a8220a3 +9eab1e6bcba3654ddff33281729141cbad3d4f89017f1c2282bfd128755f8bfe +f570009e5d1b0b0e219ea29535d7a213a3978e09624cdd94007753133755c12e +150ac073895d1f36da02ded23b37176a8130304900e5fe0982eadd54c5b71eee +9640bb875a4bcd3b8ad6808cedf24b2c7a2aa2635bf2a7fb272b82356c971004 +6796de8a7ec4f6ac2b6b4ec2c998657c15b637db58fff97e8bb55c0846ad3cc7 +7bd4decd88bf7772269da22d4f1291c6eb5c9cc564280d0c7b5a7abca63f6888 +2138842bd5471a50d6e67ef534b6e1beaee4566a1aacbaa5c7ad99745bba9888 +948ee12fa432147783bf7fc0862f03aa0c3a9501abaf025e03e3f4aab7e5d0f1 +921b030e4aa122732352b6738574f9b48321161cee58a96eeb048e902b62be1a +c7c79c12d35fd40a62f839b0ddd2d14fd24b9e7b2dfa9f87ee2c077ee36ea836 +0001f801c853bcb8d2916e20136a9705c7266e51d157d24c323369f51d16e1e2 +259878d8629ced9ed0957d1c0f5a4d78b72def69c984b697f8d95bb311014ade +938d5b5df909af274466ad8abec2b422746348ff8422e233ea9b9681af3f451b +3d96e413c23a60a5386b865ed4ff33bdc3b363b70fe0adf16da0d286ec41506f +110eeec7b35f71e533ff348515a35d96c79e787391afed140fbe1cef9a1391d8 +7d09b5b7b7e83a5c525aecebc76b168cd728e2593ac5df6b950bf73bae36d4ea +ecb67d3f49a16e1a402383aa4affda0903b3fc60324c713c1e914c9a0e3cfb72 +1ec0081a81f09898782f925180dd59e1aabdbe9f24a8541fb6d50632c0034cdf +f104611465e8f12aa55137d03296965ae1c59d05b37a1d2c0ac6d3d87f6229bd +906bc39fca2021fd411db01cd75c8d69d1966ca83235ec776e71c94a0c59afd6 +9e57e2fc8ddc2ff748350338e65f96d35fc798b54bf2c1557c0b18c5d0557e32 +23038124b80db9cb7083f3e7e4397069a372b847f517162b182fd92e65dcec33 +727d919728241881f05d13b48e4ac07222d7e7b884faf3bc18590551885d2c62 +08db316bd4fd05969d98a7c5801f92e969235df0d628250c6cdf859d7031483c +6cf830db3fc7cba88ec9aa89017a73b2dd6b2e0770df1f97fecb59f12a8348a8 +e3fbef18e42c03ab4f3952f28259ac4d0e149bb034c47a4ce282c9fecebd2336 +001e56d9663daf977ba312b361503f1618937f6c70f6be85989f50a57d864c4d +40622490deca61503c73eb488fe7f9adedd6eda65722c8e853cb80f3acae9b19 +55a81d337bf979b5372dfeb60ea071d32c14b402a25890ab9817d329b3d12e01 +a1da362ee3b5f939ae9d6189f4937de601d3e081515f06619a3d2c3a0741c26b +37d06f8c23577f6828cfc9d98fb417501124bd7b51757e4336f6fb41919fff83 +676c1370311a2f22fb02628be4a250e8c9b0f953c9342e047e68bc93b3f76d21 +43e99c2e6426ab2c5828f587e88d62954c0bb319123c825e92afc061ce94350d +e9c95dfa112b66e3eac16e1008aec6b0759c821c0bce8cffd2c78846e2b5ee00 +f020dc34dcec8115699e910ff4b320e45f7b815a471e61883362c518685ddba3 +5bc9ce26000f3cf591a8c3fe692bf29d27a39315b76a3d1cf44a52cd5b7bfccc +332530c2590b35c9bd81ec3d74c1acb10a11463cb34f85c6648b619f74728f2b +962afff21bf646eb32a9cf0d0347d6ea7fd4f45d257b0adfc1007d0f48f18898 +8c74526cb46f4080dc13f721b7836f2fad5c7716cde4f1277f3568a4dca5ccb4 +c84e6ce66fb7ac77a24b42b969815780a5dc43c7aae4fd8753ea13ec26229d21 +53f88603e9df35f6ad8654e447ee865b0234de3f6d602b4461176d4e320213b7 +d62b95d67250bee9139ea13a7d4c1d93a3956bdc9f43eb9c2c7d215375a3a5b0 +6fe8ad173a15e3ada0df73a05eb17403c7fe16baaebd2056ae790a5d9eeb8a0a +e2672bdbcc22f87f63e37b8ddd8a6cdd104207075ff475f2c3d35fa5ede6c5d3 +476aa22ddafb081bd587f5677d4f9843a261fff8bf2825cc42552524effeff0f +e32735dad946f8fdaa5c0a7a9d365a6473709896fe6e292d07abf01a5fdde88e +fca569a298c50ea8193b7d6106827f694ebf14bb23d4fa6ef2b789414d0e9bdc +e045e388e48d0842824d8c88d247977f63c9ce5d3f7693be3abc10694ad29c61 +6d4ba1f49784d4c8b3dc5da51099e4ebd5e02f053072e57232cc4c91d240b0ca +b46b9502cfde1663c073d68357fb8c40c87dd7d90f447a42a67067ad55031e1c +652cdbecb22a8feb9f29e449a12792a17499d01a17db4794e829a267c98158a2 +3440e40bf226ce6e3fd211bb245c8988bb52d56ddba909775d7fcc6a481ba962 +7dab6d133a3f4a06037e76206c602a8813600c6ce1a190718de71ab9758a0441 +6955afddfdd6f6d70f987864f50f0f38c5a4cdb3bf8c713610d85a2a602a544e +f319fc45e00403015974daf877f7d132a0225b0e493747f110b7a955dab5dd8b +8e6f45a81ceb26154499d760e3b836309ddd3efe5d3e588eb39519213fffa8a9 +6b15c3fda976e7758343a5d81ff0981b27516d5c21088df1eeeeaecbfeb6b52d +ef6f0960cbadf9ec16f1f4b0e04d781de8bc8218cccac208ea8612a0c9f548aa +c92d58ad77ca2d624d8ddc0ce85433ae775f718a4be8ce855ac2bcfbf804414e +ee11039786488b67752407b911f413697ebff6c03371824f90e4289dce7eb991 +35d485477ce955cd32dfc4eea7a2257487d01953c3eca9bd294d7f85513217d6 +57d1beae921cd27bcb3d53b606c3ae09a389ad6a8ddd12825b8b98b275904725 +99078b8aa2498eb4e38317c3eceb94bf40a5c2dc84fc039cee45a76c5741722c +d025e137b502bccc7e83d1cfc442c99f83b0b54379f29c900a0c47639d4e0d98 +d1431fcea982764fd1b5ce3b7b219eb4bdd507d0ab40d691575ed42e98f7f0e0 +563a00283e85079c4b31d20fc09173192123c192a18c7cb9aa4a85e7c4e7d5bc +0291bccc5822d63e571a62b14c9ac57b05bedffcf4e7dcc56ee44a426911c1bb +b38d47557e24d4571ac1a676aa957883cc00c4d58ddc907218e95e88b08fa76d +c6c2352ce8e0857625e2470ab3bdce538fef2c79d89ce6947a772a023d666026 +ffb1611070607519ac93e465bb8ba008f5e625b273dc7d5d6fd572b6226aaf0a +24e919d942234826927d27eeb34854a91da6342370cc0fe9440633e46f976984 +bfaf2c6bc28f90270bcba941e59a9a1172760a6c6c9e2173c2ab21d5aac5197e +0cb546ecaf9d2d18f4bc6b3f47a086f123d2e3bc90e0e7338fb081189a4c1e25 +950ce85919783ee403ef31b1c09dcf423fd1d108f5f41df38923bffa2b395663 +3e041ff2616e0ec4616cb0091b354caad9c50070d0bbc28fde15d009a211c730 +d1ef2d98ce1364e6f2fd380eb23e2793b1aa756ec5d33f079a28f31cadcf4cfe +55a2386081f7b504bc05c31cc6222316ac86f792f7e43a2ecc1247fddbed6732 +5f51e23f4f2cceba360a2847ddb97131ed8c7f2505313274209d41970a1fddf5 +0c35b6e2b9fc6f8d0cc9f9673bea128f751f8ae44c57c012a64996227f1448d9 +11b9a3eae350bbb5aa34a2a2f0d90f94df1db1ec98e8c00d847dc186e9cc3c6e +48b98a8190e036508f9e539143287f6b6d0111f64231fe773e725b7ee530344f +1ed21b03768db094635a8989a384c78bc27994a94a629e5ee921e354842ea24b +0e09acff9651c510bc80308ee634a3872f065b2e6571de20b684b5222b98a34b +c29df4102821255d1a19d7aac64bcbd0453c0887e077c668060a38bf2ca0e99e +0e64769b170053f325be21ba945dd092358f05616c8ad18ec3440cf8db623b8c +440ccf8bd94e397e29b40e9fd3d9d172170301fb578a76eece2402cae743e62a +7d3dc49fda542617a8024814d4efc26dfa957a953297f13d20cc83dc89652d7e +b93d970f74195cb1b4750fbf2690ac320c0ef11a23f92ff73e9e1ba1e3f6ba84 +9fd80536ffa85e269607b2c0f8577787ef357f32d793923af2fd13290f938812 +f8fcf03ce176b108da6daaec993182a790db55f5a148fa214c8eea4db8531a9e +9af8d447731d84d28bbf756b9b801cce8b7370c637c847cd3d77f900e547a37e +c5ad5034cf4fee398cde62d3f5fc912a971de28146ec4454a040f2f3127b754e +4e71002e3485ca7148edd05c949037ffa1d17aee11d271dd8ee5f373250839f6 +0cb3c88e6db1524771ad6586add3079c62d7ac14b0f7ea8e96bfc9c43e074949 +0c0f885611d7c6d12d97a1e471a7c0c472219960d20bd4fd36ed1a73392d81fd +d187f7549336687bd3b65c2ab636a670a47d3ccd500af9253e318b38b9d4c618 +a67cb816274c25fa6f599063eeaa193b6f9cbab837791e84da80dae7bc17d750 +70c745a018b25d47e569fef64be22e2f98a0b89cda7f1530d13e8cadca2851bf +9301951b8dbd2b6ceeb9a634790005cb8649e3f2ee2004754592a3fa632c2fad +b53accdb283b48690c3e15f2e903c0cea747a7aa49137d1236d4bd945992a6e3 +6a1d4a4495db09332a12b4385d82b776f2816e061fba4b9c8ddd4fe38009dd47 +300da207abf5fae992294d1d737787f13328735f20ca14364d83def2ec119352 +96502da2637ea0cb703ee2032183699b46500065b98d9d4e325fa0638daceb86 +ae5c5ed1192e2379bc3a88980e35e814d3b3246b69ee7210b6ddb4b7e385e525 +3df7d8c6d393b3230106101a29f033d485a8f1b1a1352869905e5552fb4ff95f +47dbfa9300ba183b2c447a9f63fd7900bbed2c0ea64ffd51656b0eae1949eb36 +4f1f32e3780580d59285847ac1763cbc7cbdd916e4dab09bffd70d641200428c +308eaf3b0b2b1b32de5123b6c2a6c706b7f297c13bca055d95e249443c06cab2 +7a84ba144fc27efc5ca3c310f4673dbce99b6542749f5b186d8bde10b35a5f68 +c4a3808bb1ab5e1e4ac62140b1eb6bfc44b417ca51a715eb38f8294d3af65e24 +381f2573d778ac0c1ab7d446e3661179aa84d7100ef99e6002ac4dc0b317c04b +4636abd253f1545b8749827e136c93501206e173ab56385995941dd96f6233b8 +0de54bc431fd90b97ee9d593bf232aff4b59286d60b66814439e3c26d8b8493b +56894b452897a57c207058ed1fae7bc055e3ccfeffe514f481c1c98cb7ce4728 +e533eef900d92078d6c15e68d5c80a878abd4e12d5d8623a699a56f9077febab +419fc2d0e283f2d1d59db8aec11aec5d5ae9d8bfb9e96a87e8c79f926084887d +57b958f5e52be3b7134bb5ac508c79dc3b35d2110f5b9b217a1c764cca3d625f +4ce86c7eb8e75231ac5a647dc2da18c0e344317695f9ee2ae060faab2e501187 +dc64fb83550f74dea89e3a130b4f168912037ecc41b8c911348ac7d0a3703dbe +42c80573a05a6f714649a904d545b111eba385791b0e3a60197307a5144f06b8 +34bea09d6640bc5200a489bad38f4dee32590adb029d30fd5ae32d1c66356fa9 +042c47f9f4e7ea0c5a8c44547d73828a0ccbb3a4b50774bda6dbf0475668e2fa +d68162efba20042b834479d6eb4663822002dfa6a9f505d045190a8fdae41167 +72194e2f49b91e2f540365621c4b55a1c2108858453050d89dda0d4a4b833cef +e5ff8d04d0f8f658cf350a20158875ef33ce4cff5fb4cc2d760dcae9017e4420 +d5ae28f7e88b933d67f49b9517a9178c0c97e1cf8ba07b60486666761e71d929 +7049d371be77e40abf054db623de965bbc824696eab418c69e5e9775e4388cd3 +0e5a470174b0198232824e9cce5d0893eeeede516d374307bc2f3655db3735ac +d9f80a0932c15f8bbd8886f651ff39847857a250f99342ab7cb3e205ea7e1d44 +20c5449c7f0e56492cd84c2067af02ee4727577ca6dc95b285b5eb1053b4f922 +284278e07c80e15a2e149b416040052d1997ef06286222143cd3f365de2c72b7 +27c6e3352f5490a3b8aebb95e8766bc275dbb3bf6511c053d7dbb23bc344d502 +eba85608fcb47321568ca5ad4e56c79ea45f1aa0b423ffb596e38f5ef9980f0d +296bf0addff74d9ead927def331573037eb3097bee3ab4ffd47bfa8ac16afe40 +a8038c3a7a1c7a673be2ec8724888be72d0a7bb9d503d8a65f409b1e33141f36 +f68a1cabce6c12e9bb2b695149da4a206ca60d7f610126ec454affeff3f26b55 +3c8bc724976bbc73c9c3f3a3e183874a614e547a99cdbab2d9efc7c76dc20791 +69d42eb38ba3e0e865c0dbd8f7dd659a70e9de6a3b6c576073a9dce12e0764ad +e28ff03047e7a329a68d75618d064598048c6dc29b20a3182936b0799b02eba9 +0423e3ba4bb53b983bb510eec6c90bb282b9e419fee378f0f04d2bfd074ac9f9 +348d6cf92565b3428dc927c6c76748491ce5b007dae6fbf101c2291b70f1be33 +1898a19ea64d9109d0cf7d5831360649cae3b15a4cf80e83476cb52bdb634fa4 +e2920cf97a7262f712b7f94b645e1939bc9e5c9c4e6eb202f2bdc7a723c960ca +1c0aed7c509d2f84363eef8529abdebc5d086f3b8b3566d1d2db76234ffc00f0 +c1eb342953c0620ff729abb01292a8a040d4717c25f3cb254039c5e13deec58e +1d2f27d1e2402f176999d687b3081ae802eecb60e457c0f92b8bf65bcf289f90 +53b1c496f7aeca80472f6c79efce3f413f1406cf36b3d3c6023cb66c76eeda9c +36abe8c1e8b41567690bdf81eede1f0d19ffc0cef2f7522f7095c290eb856624 +6e3046a4508dd2ee593b7650bf7fbbefc9cd632e2dcda3f25269cad103b32b7c +d07dc1c52370136180a0d4c3b3cc8713444cf0d57471d1698d61a3676181dbce +dbbc4c76edb9cf2d3a8a45313cbf965dd9558acfdbd6ee1b2f8b20bf217afe92 +f3fdc9430027e6ad059850c7071c788430c4831397429e5f41840136bbf16c46 +8a20c3da4e510a6770412a88315b68662ac92584589d49bd045934307eea356c +39bb45b756bca6271e2a790c33ee8ee57c39a88c1d7104cc069ad6b9c934c8b8 +5a7e58e4cca4d22122f40ed50e7fccb746b4638a544fe344941d3677b8dcb181 +d7748e578995d94b95ec78389ca38d2fb89169446cf8ead7edf4f159980a819f +b091496526dba9c767dcb800f4a02304e34a540a214b48ce98224f1f0859ff06 +4271e1bcf4327c0bd899f8be48d8ef2d4ec21af76f58309358486701eac40aaa +f25fed34002eabec8d4998997de5f5266f8b9d405b050e80a70d4f24bcde2086 +ae662bd9fb804d94d6e1a070030faa7f1555ad435c3cdca6ab3359e080f046e5 +53efc6f8f3b92afb6c67677debfa40bdf106ab64d7a678b1250f9c671ce0285e +f2801dc5d1180f2a0cad5948134e64d0a3e042d8efa9213bd1e836496b586562 +04bbc6490e19c2b75ba8f79938b022c833db576fe9bdb5b966ae60438ebb0716 +00fda8db20627cb5ea9e85cee8454d2d33191e8522bff4474a618cbbf123e1c6 +74fb16f10e817d8ab15516d91bd30a2a8e9e8dd411843810c10d5aa8499e9ee2 +ba8dfae6dead6ea07df21e491dfdef5220baffcf3d1bdce96a22074375f7255e +0530babb7880101a1264ecef4007cad714970d74ec3f87c5041be48a3532af4c +b81af597557d6af050aceac7e3b39957089ba162f772b660669466fa20f2e145 +e48eb3416619515731511924e22b642229d0a727ac30a68e8d306978af8f03a0 +f0165750e7c6a38f4ece2f560c197de8b790a549dcc9e8f7be4fb91012b00998 +e2dcc2a1298e126619e150c91e58a7f4a1c37058e05c7b6475ef68dd36726a8d +5f62f3879aa5c5f629906c688a6a31baa6cb3ae9d395ca890b452e3e3573e436 +d429ccf54dd80ec67d789a55e4a838c4ad51b9580a1b9082c826ada36398005b +4005be39f88bf70c1828045e66272d425bb95faff8482602d1d24bff3b89fb85 +b621678a5ea228448a14e5a530a93e653b088121aa1bdef1044a76f4de2fb04e +4d74547ed262b0d5481c72e743685f76a867025b65848058d8289467853b7de9 +045cff1ac4358535d56df2867777940218ee2c79a0bc3af1217a3d30fcc39837 +56122d733846e569d1ca420628c8100d79acf99b036cf8d4186353ef87a7e4be +0a261878ccdaaf3afe4f0fee1b8253cfa5fb6d7192d969ab7f8e1c9362a4e9dc +7ed706ae2ab4f48eeb7dcde92a224ee834c78de08ee3e0e9673490a3ae2e59d1 +7a09bc969c391a190d0c7cdf8f30586bd20521a6219305b29943a67061312db5 +6a51aae121becfb217c15c51f36fd9fd0f137c835f6b2028300da5d3e27767bb +792a1c6d04f8a37185c5c1d27f99ab1378f33fae16269d2454000a70d69bc2f4 +9131f4c48cbc43af8eaa6a0601141b837faea3e87d6428db5ca70cc07a6509d4 +f68e62020f453441e436bf6fefb807b1fd27d93ff1c0a5d8e44134999ac1ca4a +f469a4f467cf380d3d59ecdafc12d486bb2349cc0b969e7547e554912cf59b71 +5db814d6e24fbb812a561291c9701774d290b542d6111ec0302d24eaa3f52652 +8874d42f138d756df4d941ed6120f1a7694e6a7c1185d324e75de8ff2613f492 +654d1e93611c399373c877f560f7594e3471455088128b734e2a64528c79a483 +d0e401be46ca99339f955bc6aa94fd92df93c65c7073d0cc013acdb9bf055859 +27c7846ad0f353f863e7fb8cb4739172eed00103611eb45ff3b64455c8474572 +b41418ae21bfe191643abcd27c84598a8dc705ac1d7675e9232a83f7a52468a4 +2dacefcbad08ee88527b02bf2714cff31bed930c798a740d1c21ceb6bed75fdf +097c9ead0f73144c800738affb87134286fb9619d16dc80d2090a50c854e28df +bbbdce58cbc441f22f9af5c5b04e8a0758d29e966270b45a237e8f357add6ee0 +c3aa9cc60e1cb48597bba41a7833082daa5d5f1111bf1cfe602d53d65e72a218 +088644a1fd43f03887ba4e222f88b9a0011eab97e72f6651ba9f6632fe3a1aa5 +d04d1cc1f4c4abcacaeec09eea2b14b12006234fd2127303803113a082bed58d +d64e21b55136e33560eb8e47b898121895df2da19e5acf71dd5493c1391a9b21 +2ab2b6c0d5072ab4dc57c2ab840f03eff0d5b7ae02695b345f2f2905b0992a52 +3ace32483f8db1513d7030d2089a6970fdcb60b07f96be54bd64c68ce5db2f91 +6a820efdbde2fca094a6b3431d90e0d9882e586a032a33d89e40c329670aec12 +9985ad7d5796ca1dbfe42ebe195a6003f73ed252928b591ffd22e460ed9bf96b +8d63e7c519371537544ff891fb3999d0d0ad3429e76afe112ccd450344c6d15e +3396e4d00dee53392100f34fb6286508aed328d3741adde92dba741d5ed9cd31 +8a356c33d26171baec08fd196837ec3c6714376b98e337355a84e32b55d89156 +1aca0614ee5855b627c669141be528ae57b747a67a438b7521337e6a446e6678 +9b88a3072d308df8ad4fb0aef83784eef7f3c48d762009355147ea6810921cb0 +5bec03caa582d2e0dd86e1043db0108cb75491ad87544f9c4c9e31a3efdb8452 +e016183b888d677b6841ff09e1147cbdb42f5e1f5549ca52f670d120de28888b +9f68a91e84321e39f879fbe6044b59c958f9a51ce5c153deaa5932dc6e72a284 +3acdf98fb02aebddf8ccc2f33cd10671fd9f9c0e84e71d881c4f420439c22023 +9c4f222af3457b3e97380d4f0aa1748749a899575a9c087ce38fc709ebf20e4e +0c8f8353e5358a3ceb3c7aefcfa11934029b4b285256b40e432ed98a8c0768d6 +9ea0c885f200ffd3719af1d526e6eec185f77f3cc04091953d3774e47eeb90e9 +9572faa488cd9fa2cfe8c319a77caecfaf6d720448a85547238afc726a1a4aa3 +c1b9f0fb6cc3e72d14c032ce4aab590f86a52d1fa0bb143ae1188026056bea13 +f1b3523ce7d8dca9336df949ad23e2953dc5a102b49da8850672679c6737a176 +4a03e7a09b01b6e31928edcf528ec7d093f5316305b3c5cc21fbc8a59e41d464 +db34e1113ac3b78be72103795d2495dd389af694df33661742e3c2510a852d24 +7165a2b628433711c030e6999af517ca7e6ac8cdea4b3a7d99ece764d53d7b3b +d8b19f769a580266bf9e06b38d9973a5ad13e13567b64e482fb11c0eeeb908af +318bf37f9a65975523df27033d409384a43eca74bfeaec64ec1f2e9861ac718f +b1ee902ae8800de884dcd33aa65dcf5a34a0d502af47ce8d0cd6ddb487ea4d09 +cd998d92f1bcdddcd6725f174757fcca01de2172ca364870fcf9e7e4da8ef78e +12400da4c1d7b4755732d85b027eb922f47cc385c9352ec0b05538b429d8afd4 +3e2805a91b7a02a13b602d91775bcfbfe76c7afb4706d71cf548128b6c296a8d +a386d684e11bb2327c1253dd3de27c768a1ee5dae100935b38ea746e17b02b6e +4318bd2f22bccca295899ff9e28a2ad30c24be10bb6d2234478faa56270d0c5e +b372cad7414b875bbaa2f088f8f8fdfb4cb66682056c73d47502f24b9a52b0d2 +ac05e71360b3dc8185efdf6154207f9e653a12fe4111881ce11f98a234065baa +e8da3237c176bdcd5681ae1856eb5d6005f15665a95ddf48caefcb3515de0bbc +0e5b06ab83a1cb271fbe46a5abda688419b15ceff2726cbe7d7931eb3619c32e +4dcdf873dd0522b7d7b84a3e84ee3323be5352835774d5a0c171de84d428d6b7 +389f2b18ea67f2f212d8d3607a567fea20d0fcf6c049a78a443ed910c9d93e8d +77df8a62f9eef53be11492da3271b81ae431e714f701e4629ac45e6b09439f45 +f9e6949df2eee317391dcb0ae0aae489a2727c9180071ce0afb5fa03e90bacbc +5a75711739f227d18a5daf1cab97c52be42a074313558297aeaa2c78e4e0bf97 +7423dee419dc11665012d7b04a0fae36e3b48a448492a19874665b247a766bb4 +a5dde12307ed82444d92162024e1e954e8bf5ce379fb46933a129f717abd91e7 +1b18192c9c85be627d0d799eb591a8617f28b94d448fc6ddc41f9b49f2f61006 +501de3f70448aa83e7c71591fe9191a7fa3d4889f38e7006ff94cba4f6ae4cf9 +471c247c77baa11083c2a758f21bc2f21ab79eedce906e5e624dc5f80395fa3e +9a1ae2ef4bd856f34b04a4628e7d5f5f4318f5dc2a8c5a836a75f2b570bef432 +c4cc28f0858df3701169f5b67c940a7e13c24a0199ad4a9d1ca8e97417197d51 +d0f26541c251559c92cd47d75956480a435457c8f6ffbce3392000cd068afd42 +644db28d71ea5ea6f7b5b836abb90a3cfdc7c79adc8f4962d7b788a181afb8a4 +ea87388fec7b1a508cdce1adbaf6e7c0e4727619e836058469c6103d032cbbdc +6b8883ea4486c4864a0921997d6e06a794b5daa277473ab5b7beb796a3187942 +c3f9e65206ab31e7565a941df6830003c9135bf4f62187e968aee87ab09672f1 +5945ec9c7eebf3051714371499f446e10ad9ae6ca575a0265b920a3f95828a76 +a3ed49e71bdef5b9d914dbecd31635c8057e4fc424c7889a19328c22d8253885 +5b10df69a49920236446ebda69ee5e211002cee1aa293a2d09b6f5911037afc4 +0ef9115dfdd3cca09040e7d37ffdc7864ee839c41ee34b843406e72c24a3f73e +5304de6914f6b2bee9d5b0f0ec99afc8b2c32af6630dcc71bf469b65c2c3e209 +422e64fcb017927c3d60d1079bcc82f66452c2890a959ee7ac4d0d84ea5c80b8 +1b769d9857b154e2828d3b0577904a4e0bbf6ffb57a4b526fc481bae903b2c5e +c34097fd6347d297a35e0e80bd097c9e402d4404dc72be253f92d14f59dcc360 +662f8b7020a893396e8e7b37f0b218fe30536654a9d056b69fa94208d0623d74 +2a01c6ffb2d1b06f29b9f9bc0a2bf96b20a641e7aaa6deacc517d4bd25616b27 +673a143ab51927516dc55a8fd032d05562410bf84ca8c78ddd35903ea93acb16 +94a331d5a60cab9c0c4120954f7abc552e7d95824d7ed9376fcaf19f37099414 +d8b10b4bdfb3fafeedefdb8e9e494f216aa2eb7468327ddc77e8e694f6f6995f +873488ef8b62d99fefa9803a16a560e99ff7f8641f9babe54ed9fe1997c89558 +b84efd32b51b39ea86e7bae1f06947750319a4d6a06f94d4d560bd1cfb2cc8c2 +74be6d08d4910af563633aa115ed604e6a6718b2850d954fd6dfdcb86efc30dc +dec816974f004142ca9867de81805e1fb94a858ad3bbc3a99de56e49b4657d04 +0ed399de5895706d7cbe11a5bef85c2dea883d1ce49e61a161fdbeb6a85c9e0f +d028d9ccfe8f17a92b498ededfc0d5c981435960090116a675404f27c1bcee8b +53d611a4521928ea8664bbc5365ad245831adbc4d53aebc20a89667b215c9f34 +f9dd1598a508f8281f0e08f8bd56cb3a7ff37f12a2bca4f390a542b3ccd2d700 +34df7d40755ac79d837f0f54be2f8b64cd3af8cf76e3291781dad8546d8f5040 +3e6c5fca14cc1efad27344d982a4dee4d53a3e1ca318c7c7de4bbe348297212c +3888abe94c9197b5e34b0656b4ff22c8d65860b2f208309ec615f2f1cf3162b2 +bebd51f4bf9c1c0f1bab40e6bdd8b30280ff79087451188585c09775359c1eb4 +9bc1325ee476b383522b264d3af8561801bd108a23b44ddfae2ce4f6f635c059 +db046dae4806fe31863aa8446b9d0dc0375eb50b561706c6d7d72eb9924b21d7 +22c8dfd97802066ec8b9bbdf373bff5b37976cff3f496dc62d5b7b00c98f2c77 +7a4df62ab56efa331fb93891c80f6a058ec8c89eb0faa8a383a28be577f24872 +b379e5465915093c3321be9d925592ed2400d7c2d3c71843ad132f07123d498c +a41c0a41cf981ec825552fd62482913596d484eab4b6eed8177197db6d85049a +ed04d17bcae9142e9f3db73c7c96498accd2e34e299d30f7f5a46fe3feafef4b +2d0ba8ecb36c91774c2f2c4aeaa9557250efab06568875f0bd57e39758736d16 +4bec5df41509f69d2954c12fcc4884d73c63847ae1e70a791e6e0a6bd8497e9e +e096a432c237bf659b8c1021495c261ffb6f8753f757a8156a634c6d3faf81f6 +00ce518581dfacdff00e90b78f730adae456a70d547d1dafe541c56273efa04b +fb0c882f13da2f495bf00452519d522e1d07b6bf5e93630e39408a5e011c0940 +8344cb26ec7f0bc859a99d367c03c22566b3e747172f5f7df04cd9d385337ad3 +893690ca430f9fca756691b13da295b437add5bf13b4cb46480fefca2801546b +b47a1c62e8c6971e9a25fefd44f0e22e5b6c313320daf02319c28ce850649edf +2d2514e82f1b9374598b4ac96fcefda4514799a2a78144458f2778f6f5350cff +5646f2a136dcf74df23ae08a4982fe0b2685dbb1b013ec4c0f1c1546de39b3ca +abfc326ffa9639a4d4314b8a316571289244376f2871cb599dc50c1380caf038 +64c1504d48b345d253a81c3121570fa4dfaab60747c03df592550eda1d097fc6 +826d14c1502cf0c5e506063ffffab005cdeacba9e645b1667e2a51b53594be1d +8763f864d511372ad578a7cd9bf821e6c54fcd954d91da8705c498c340e5c820 +3763b164cc89553ab25ffc43c111919b4907131e2b57237ca4f5578297c273ff +d9f6a869b4b7a757bb72cfcb3dfc78cb1f30c6d6a90720938d1e72f65b2be525 +c0de2e5d2a8cc4611a3341a321ddfbee824c287040186add08340ff54aa2508d +4902b08116e0dcf98b1c3c55259384a6ebf7fbbcef27b2fc5c6c46cbe8e5f602 +c18746f2dcecd2f6e114aac27068c8d396f2d1b6e99341c88cc8836a9d9fcbc2 +f150c01474ba8b690cfa9bdce9bdfe9d0edf1e6e7f34e8e49df0bb16e1da65c6 +f4412fc707300c09e124ff58ce1effce49e4cec56921a2addeabb70422eca207 +1264dfe7c05a8b0c343905a96dca8b103d924d83afd8425fc72297c3fbb5c055 +138c35fe80159a61be2f4d907c690f5e9aafa1eedd2a8b95e00967acc11a0e0f +9e306043acb4972c7807e306cd4a103a70d803fab4fa0130902e729cb2f98bde +d18f703660952191a77109972cde502c1505d7c1eb2a1b28dc498fa52d866154 +a3d89c396d533555ec5d0d2cfb52defaf65121426f1e14b40c76e48db6d8ed5d +fd75a9e2209a817577c526065cd8a4f3eea95b613af799748923106f3fc75e3f +726e196f8daf792d0f8e14e6cacfed4b28458744895d3ef10361baab574ece88 +cf753b2d1d4fce42a7441d52012150ad81cde35bcf9a2e871e07dd2da9b6eb44 +a5ab34254bd4367641a046ead88b3d10b95c7f4adc84492918ba9fb00fe3ca8c +945f332799588a3a4212d11f17633939e3330056b927b6f74ca837b3917b4f21 +9b7343df75dc111071f2b4eb6b77869fde790cf84bf997cb5a646ada25f73319 +6d6d077219cda760c6c4882007627e094f85a3302d0676b292d87df19e478f7c +f75ee1e7d3b9fbdd51049b1e6b3751e92bdb2d7a89994d03d0588cb5a769a02f +6bfa55611902a035f22c05bfdb126ec9af38e7e62d739ffde3dbe5bb4556c90e +a42d229789753e1be6f779919f8bb54bfd4ff319b081f2017951297823c6a28e +4d2f426540f8cca55d733aad531b9fd2cc8f50b53360a890763822cda4252f09 +a0be806d609edeb9af6ae04b3dfdf8f706d99e9e93c815c014d03243fcaf01e2 +75f538926084d2975446fb0504cdb59dcf70ac78f263edf4cd8b3bac7ae0d6b3 +4f7fcec7e79d47783f93f8f7a33b0047004ed9baa1cc09b6477de878d52d08f1 +5953e4dd6ff1bef0862bacca7087703b440971006ebbcbc954d045056a5f8caf +00863b50b307f732d1f74c98b7b838a1a162ee1301fcabdc810aff4d97c51b54 +789d5fcb73ab199ee339877de2740ab703f707ef0729e938b9488ef1d92ec434 +343983946388dd286051f46033cfee5ee2356f1682c6c2a4367a40bfdafe2086 +63e25826c66a9ee1cd51de10b58fbdbf67927ec0c2fd2ff2f70c204e8fb28195 +281129bcc9501e0a2a1b8cebbe1fed06778eeeeef3adc0389e5b5bd2cc6ec35a +34d154efed2e23b6e92d55d5e9380353e3996c8a98e8af5a144e865800aceaf9 +d2e7dafd4704a90a5a0ca249b3a5562711ec25a2c8110b05580a08cb443ef3a9 +10d1c45ab2f0e750c8607a13381a2c59ec96389c91f547af23ea347e773b1459 +6723b9a4e495f91b6274f1e556b02cb24f72192b558aceb1d780fcba5e56bfdd +f594053cae29e5c04482660900cd04f67771075955709e3ccad4e8f21f66150a +bc55fc604c4747b2ee6882f9b58adf66f9f0ad5f78072252d2088257ada35fa7 +780d3c14894ed60ec428d3c45b607dc435cf6645deb587183d6af6fb0c2ea65b +7478b9e698ada5b4089cb24e081826af96bf3b4d08fb3a4a73cbe17d0232f299 +bd0bd00e2df84c3f687628e126dcc665a2b399cab3cf3c717d4999e783633c31 +d4a31b3f2663c35e87812aa3789e39df118bd62286346bf8ab1c6576512a51ed +eae3a9713792726039605e4bc48b082775e3f6967204adf341f2e71d3be37b11 +489fe410be55b86ca3ba08d56a3dcabf543358ffc7238dee54352fccd4c67316 +14a38751e220134b867724c416cafb43405ca178be8d99558443f3d65c43eb4f +543547131913c1bf184a3ec570ec7747f040f028d6ddbf7a604c80614ed3f13b +03669d43e91d36dbddac8eb98c992344f8d0814dbb60623bd52e3a2d83598d80 +32aea6cb7f16333be3ed28a9c352fb3839ccf4d496a2022002718a28f17d45eb +3a983b469892472d738f9e17441b164fd64ae80e0796aeefb10ee2d2249bd12b +56402c4711057313ab380fb0c925cbd189054559a76eede4164f1649633ffcaa +74946b09e748ce88c5d91960d672841dfcd2a209ca65076328317b42f538436c +21856322bbf15c233bb348e46ef6e55a191fffd8c27689de9e3fce9cbc26541b +e8a44891da54891fc41ea63434292bcd16d15cd71f9f694a4e2e1af180c80585 +39dbcf1dd75dca4531726aec0ac671d3a49c37812c5a24077300dbdd2d505b6e +3492df405d7c08acd4ead50ee0fb36536220893904f0c0b195783d2145d2d3da +b4964495df6fb184071e3bc55366d93bc00dfcf8f27cbf12e25fe6922ae7469b +dd75222b8a76810ca5a05dd3f1b4be4059202ffb1e741eaf25d2bfae51a2991f +0a7502d93c14c9ec7df13ae0e1e2190b750551d4c8040b6c2bc94352ed6730ab +5eec8a7bfbc415ee0bb11f244d32a14043db9e5f9ba610877f88b7bf76786e77 +f1c0db2ccb58e86d511decb102e59f0b458dfaa11dec4901209275074e734c4b +68b4e0f523984f789f6fb9455c98bf8332378a9bdafaa73e41e17b55de7cab7b +e89bfd4ff0737ffd762b448a1a184b00f2f6422d818cf9f1171d16872dcfb9c1 +d5d4dd2bf4a41675ceb9fd5aa182948fa485ae4a1dee1ef69f63b510685ad37b +01ab4f5ab745c0017fde08662ad50265c3d18f0e974a6c5b23cce23f47154889 +4c9ecccde4f2215ef675d57f18eb1508b2dcfc442520b1a9956bcb5a41e6c9be +871b6eed9a48aa0ee247e41329e90db9dbb77249e8b242b6d8cb58ccbb88e3fd +cdb9abe8677091ab657b60ce0280d21aa46c00647c4e17b05a55729d265b3e29 +b0a64043386d82d0bdf5d1a89b4fefe9a4b960585ab64ca89bbd7ba9c5bc719f +45ea0e13ed94a690a6cfac157f1ec9f0640bef0eb56141383d60097d08f521eb +bdd81e580a2b6cd5355b3a7b39e28d156bcd0458d338dab3aaa2efa7473d3851 +5a4cd8967d9a841bbb02adc454e621ab4bf1b24c6c45c0d4b1d6eaf1f726a21f +8663c0e6db0816d79dd6c4c1eea0484483629567598fbada7f556c08caa61479 +00d0c1ef9d9f7d4245fb639493c20577ac1806689ed1505186dfb4af6689646e +4c968e20de4b4690f7f69af780ae2e570393d6f2171779b484020e5519bb8fef +2bfe908988d4166e73e49206b35e23f153f83ebdc4abe68a7c5fc79b200bccff +7a6728c3185c23b2a357c4831e0ba7e7e92f115c140da639bb714f3680320dfd +765f36be88d4a02dd0fcea29515addd32f5f79909787784c0be084bef16cbffa +7dc5482a712740c8f47a39a388dd2bd7f0ce98542cb624951c610d015497d58f +43563f6fe4f86ce9a493e3f183b881048b37b0488e7ad86dc6c16d2031ec367e +2a706c19025fe18f4236f50b94a69cff0f09f09a66c6c5cb7e9c342bfdef4a9b +2115fa05c641247759946333e4e16afefa343c2ec752f16fff351d19b6fa4af5 +512720883733bf99286bd3344d7760d685f624a36d418951f1f0efbbd4172ba3 +1e8bd690c80a8505d317f4957f4181a369e3e848e519562b768c6ba36a907ebc +b8c5f3685f795e2d475e46cbbcf410368387b36736ebee3e9bb20e709c34ea5a +6cc46ebf06dda7d078f50e99178dfb0239af54ef5643bfa82ec99017235d562a +69b24660e3381d97635ac99cfb8059ab8428de65e74d17cf63a6e7ca8f02342e +041c51529a672c07712f30deca2e5d0b2a047b05ffdfbeb0fd06db763f6c3129 +8191da2d9080119c5f3246fee285b8f865627aaec46f50ae40a4e01751a5e039 +2b6ed5365f8bd496251e5cc988224ed34b11265a3456623d561d6b527eb64ba6 +602acee1b66eed4aeff8e546154f061159d17b3f604659e0cdc5a6a019b360d4 +cf8ccbf9bff2c03c5f832e6d2bc921b9406a23cc99cff5d9d2fa19ec12c71e4a +7f36e22e84e0b3df83bbd1eefa3aafc540d89cfca30bb0031c9d72aadff0606a +4fc8adc99037e372d6da03c60ea8a718bdd2fdcda477e121271c1a6a50fb8205 +193384a66c3b2106726a7d713aefb8889d02399a56249b42f09fe7dd6feb5e49 +afe929d39bdc63c16f7680044a58ffebdb1a86c534c3be9859041bbae3bc35be +ef73fc6aaf63f7c682e8d06b38f3f0756140f5bb786878c39b69afa0fb4d0056 +a87e8f5ebccfc6dfe5cf43f0bd559a2b2b892e9bd498ce26fad8fbbe6c6fa434 +8f129e293b9fdba495d88b92b08c424024bd434094e7dac8bc3b775744927cc4 +5c7218aff4a105634b1138214f82abcead701431d0b882c980e7fc49bc303ec7 +33fb529dda8824f6892d861aab637fb6eb6029230b05f3e7612018eb9c438424 +0746be95808eb29b71b468d41ffbc1bd54a4ec1d976274bbdfe09bd0463b5129 +04ce74b7483d917e98b4c54858c73107caef5cc959c7bcb89dd508648548a863 +fc597d5b9ec199e77d69912c33a33cd8852cffdc81d88389afbfa672da8d08ec +0bb9c4506c7113ffc1fbb032abb04dc61dbdf2fcc7f3e7438382da34cf6e795a +8a798bae5d197642175095b99ea18075214b959616688d82fd3e8bcad4f6d230 +e67e7125a88e3cc7fc5b7248933dae009568fed65c9a7c69be843ee97b50e674 +d8e7f1376d4cb67198ee182d14dea56d13d3fba8fa1b1e40a3d5ef9186537a06 +bda06147406a1dd9edbc49341eaa03e35ad88fb54047ec80aad7a126edf58c51 +dfcac3e2c45c122ed78108d479da88ad159ce220f96575d86c682e18adb46331 +c4141848d1175617a0bb1df857a6f57cfc7b25f7e4731197e2114d41f25efb47 +9fef56be4fc19bc8c17d890e681678f704ffd718d8d4594b670fe9da36c75e4b +5d7d4a7f194eb63e4bfbf16e3d963b7e2edc72ff17d5f17834d04c09fda71a5b +a82114c2a3dff0b865fbed06ad1859aa2d8b3146c248b2a97e8dd058cfc9bf3d +570bd62e0d6e73800a2ae8cb770e2cbd29ea05a92202c12853b55f9dfdec5144 +4bad959eec0071334966531b768544bb92dfe0e3f15ac7731a8af84af803aa4a +0f072ca3ad8dcfa63c9612d2850e879c519d7e628534c84082bf6062a5c336ce +c26156af635c2fb61d45eb28f52c853c2c41f5f0157c6de6342a5ed20a2627f6 +a5aef4a6661991f7addf771e31bcefda32f64573f58a67d7fa0083cffc27c1fb +6a72d8f2a0f19731e5c41b12402ea44d029a0c0823a97f75a0b04d51474107f9 +41d841dd5bebff85afb7ac67a5c817e3cef443b8136bbdff5a112b93be5c4ec5 +08c5cd0412eb2ca0a7fed49e416e7a5c899a9118a0a2c590b6c1a482479ff7ec +f361c6a276a5a2956cff8fca308015789540b33f2991c466b8050ef0e328f36b +07b638527ca6da278aa615e1ccd8afdafd3005e88799ede1799b0960edc8ee16 +bd0de4cddeae5b4c09b646409d7ca97398d35f915fffc9ef28c3f6311a38d8ba +b79d924cf77a3ffeeea709624344556d0bd444ce3285b9cc2dd47fe10c9bb9a8 +84f200db79faf147fc7b7ae65058021a3c281f6e77a038aab5142fa333bc4127 +a9a83911fb9f2aee6fd86788cf8067fa4a4630994e5a644ddfec7b982f2379e2 +224406d54ea57a51e48dc39a8562a710998f494bee0f31321698273626f83a76 +e1cc6e22ae5994ffab9eb643b2ce3151fb199d593ba51ea4e31dc06a51918ae6 +d1b7009ca6b52adf396b2aeffadcddd29a2dc156e1278c1cedfaa83e6ca1e1db +b21ca2f099f52060a562b4da822aceb2ada7bbbd56287809b9e0e6d377dac168 +92b935f9d8b0c06f441d31d98c7b36745ba7ae6b94edd368ae2e711c4e89f36e +8a2e3a40121fdac29bc8d0ef2e67147cc9ef495b93f512a2f74f7518b8d8b2ec +fe90fcf73c47a40e0801ee70153426a80476f7a5287cf6a24ae4a082c5697ff3 +bd2b1d5bc2ad73db3452a49f4d83d792d1e2ba4eec06fd4d3d9b42c8897ddd28 +7aaf1707ee10b794c9f7e1be564a3dbfc44fb88e84dd6bf253b73575db658801 +2355aa59dc652627430a83a93e386d6dec364b93d113a27ba37539300559f66c +014be7fccdc2f6df84deb7dbd36de72e2911f94056cfbe2703f2eabeaf5fcef9 +5cfb4bd33adc4aba14cb8d021e84abe3c5c07d58195339da38d321101ffab18b +6baebfd40b896631137aa7f44f6581d26345cc4d08e00ec80cefb364523b5d62 +6932e79a3c662820d2d2d7120e8159d141fa3d6a39e5c0cfadbaeabe56cc58da +d2bb07aa899109176de21e9238f723dcf01bbf5a9bcf65b48c084265a6292553 +e79672d92e01ca02883809a2d8ed8c3b1c3624bffec507d7098b93fda16e68fb +28cd427159472ee414bbdf61611f506cc17f261ae7f62729883e157be0b6f369 +7a27ddd6298f8387214c0f7a972c88f247c702261db573c6cf943c88faf23e5e +ad410ec4891db790ba2f3e9b01275da23a1dc085a5a88f515eb636c2f9b37a84 +42ccdb48fd68d9dba9f36d27103748d3e65d141112a48bc0a538eca907a2543d +e38d0034708af79851ad622feb8f114ce23cf68ea5af94ece5de102ad396ca60 +908aad2d41382e489de5a21f29bf236c8661e75f10e8fb698f8d1b891471550c +cb0b7ff9124a88df59718fede4de2f7a48cab77047a433a53b4493719698d271 +957b2c052ec053a07895b432ab070b0ee3b7ba3254a30bc3e7d25031b54f8e6e +6f83e029f96ec78d7d2aa7a86697e14850c0027106d0870e9176b411511fb526 +f3d407bc1aac74c84c9b6ee0c0652bd735431ed464235de8d1a04fa154ea4315 +3045cad50be4fb45fa5f96f2a21199e4c10616d0ce7aa7d464d19e96d1e70712 +c45726b5a433bb53d0a7f8942401280fe10f84f772c36d522847f5017c345501 +55d75c9e209e6e509c15a5e7e35d1a0d0407ae1a0894be8c3cbb49685b853b43 +24d4e9c6001d40a4b995c09380364e33720cbf7bc3f6aaa7ee38f7c11ca2602e +c0bf5cc74b790c2f2b3525b7f36ed6c6f28a2d0bb42354ddc143bcfbbbe8c815 +cf033b1195e2df6f32a34c5c7a516987cc30f85ddc3767a41273c396cb74594d +2e3a02dcda51a8c6813cbb668477a88d6dbf49e092949dfc0054f8b6e37298f8 +2e16a5f626e6662849b37e6dedec725aaec082c75ed13090500e515093fea09e +eb7dac674bb5da04117df2fa23b0dabdea710c537d4de590c6f552525adb539e +4354ef03ab7156158672f24268daafc0cb7e1cfce8dc440d26021a82a519c244 +82fa5e4d5c060999b7eeb3fd23646abebd4e23c1b248c952366ae78bb7b02fd7 +0ff0ebb551cbf206e34d1d11f1101624cd9ce90a4a0c77f0034805280315d0ac +b5edd96312f2deca7005d9a110578a7f36d5f42eb243bbd5afabeca1109f4345 +610c2fa3cd78a0df2be97200681c408b9cc7cf6c0f91bf244c2c6f550e42e138 +75e9ee9841c3115fdb06bff4e69e7e8820313eca46d817f9b9da77156e059f7d +0da916a3d79c98b6b6aaf5627f65d87537437d09e758a6b4e75743a2572052b9 +f9570763ebef559489fc2cecc0da39239d7ce95bc0932a081d72d1627e20c1b3 +faef633e5f30cbe3f2efd188da2486ddfc7c46fa4b79d23f4cc74fbb9125a3f8 +3e7e01b60e27857a74fa928ef4cc745284f34312d8976901e792128071532489 +4dd44a4a52d2249193ee2c6640854b11c867dece18f17e367525007559f01696 +6e0b79962444a74e16d6cde9a99c2e73ee70502ea18f86ab048f57170fa6d88b +69a9eeabb8411e9c8699da9f458a9a0febdfb913788e0f1feaa99efdd14148b7 +3f8aec4a032b1fea73c7751baf2214aa74c013eb1573639c8d5684b97dd3c102 +424e28b25ff9a54ca7d74d9c7bd89b8384b0e6c7b08dbbcc2cd00dcab22165d4 +e5f60981bc76ebbc6668507f18d3df632cfeb15fe34b6663d216c19e281087c1 +4d17efd2e8e3249efaf7c40596ca1cc8ee466a2d34ec9da57d956b574f941a29 +01a345953543872dfa2abc6c268d025497ffa2dd0cf3d79b00fcd96202b57c54 +994d405e63b6bff30202e2b18dc3203109605149c30deb46f58decfa28e793f6 +b5e721bb78cc77d2503dabe7912db5ab1598a6f4f92265d069c19b5ea6a87eca +24b621a051a16264f680a253d803dc927fd043e4e428c518caf703208d6709bd +9a44258bc00c2733b04c835211bd3935d154c1ce0f69a86674b39fadf719e16f +2a9bf8eb3e47a7755b2669d77e48814e35531db83e00c4bae0dce0f04da7a054 +836e1bfec5d78d89ded973ce2c3f884a66dc9fdcaa326eaea5734f4fdf9227a0 +447bd7aad507403d5b3eec16bf9c7d93865307a1955e4f8aa7ec9a89f62c1d0f +8f2edc864568614450e85dbfddf4b496580a020d2dfd541f0f9919a877d5623e +1b98e8d40c1b446c60d34f0cb96cc2e44173c9b49d08c881fef0a6634701dae5 +da244b2d17063db74be090eb511181cf7d2916ae9bbd37c5472b60f1dd726858 +b91cf086ea7ef7a3f718c0dd406d8f469d28dbf8861271ff6854bfbbba1cbab6 +f4a714336112e5864841f9295c294e45cc848cb76bd8555d7f66c23499f4639a +6b1eeab8490b68d906a16b5ad32b4546f88940aec78b011ca6e8f3cd33cfb9eb +f3c5db69a448585da094ebb2ed6eaa283ba55274cdb30111a259c775f79d3a3a +7c41c6da1c6cc97e4bdec11681dbb5967840f388c8dcca858682c7563d648424 +316a87bb2e970191acaa143079406edc0969c514f388890bb060ae8b5d3746fb +57ed3e509380525003a43d61e756d0c7f9e9108fa4dea269db8e0dbf79f3864c +1ff753922c523241c1547f707b707694e89bcfb31c112dc3ef08fda30e0d273f +5df88210828ccc95c116be29cb55ebc86bf38100ede685287eca53a637a7f58f +ae1a6dfc144b1ba48456eea650128134bfaddde3e604afc293493a7e910eec77 +b99d8429a209b7728427869ea42fc7892077cd168f28359260a5864814b9ec78 +75a18e9556b33d0edd47612721d8f0a44f285b58441444feb1c71904c54ae2c4 +96dd2229daf695a1543b3ac16cf53916e2396ba0c3927231bf8e64e56d5ef49e +66bd6640d36aea19f446e26234d2dd22b1df911dbc4143b8cea59e84461bf0b9 +e16d3f4361465c81367a6b1eb810f9271d56dc7cf8a4ef514be1bbbd921de31f +adf2fc63e6e86984598fe942f5fa759dea60f55ae4ef011c4cf2ecf2f32438eb +b7e99c04a5944068ffe9a9ff9810a903cf2419bc5bf33a079b1cd3f862426f63 +fe283710fd2da0149146d6515e2713ba828274a20211d350364c05c1767033ca +2c4108abbd924112290bc5226bb666b2bcf8103192f6ff86d6db449427d1d6e9 +d93a5fc559ccd546482b8c8b2460ca70df5b3793695e2ac690ab772927a5d578 +5e5b090573a6ae831542a63da23ccc6d2bb1d45fdffbcb029591943a34442718 +42126ffa773af9527733e4f4d8c10457b743d1e6c3caf34f29bdb53a73f6dc84 +cf3cec5c41a226bd5a1dc4c3409f63b4546ca326d9b637d323e8c44e55cb0fef +8f8c807e2893f07f75aba52ceabf8eaa9922e6d08500e133982653b87c236520 +c79e40168f5b83c66f857111b8b4d38190e25e9f41a41fb64a5dde7af8f2dfb4 +daf80eaebfc48717b90a3ca26de249c7c68fda8820a21546998c47357283e816 +eaec04a50a12aa4f7815c42a1ff5647cc4326cfdc354bdeb351a62e511333130 +c2dc4dbeb26ada4ad2c04d2c9a3841d13e9a3910431bfbe5acf2d0107e2a8433 +f4c2664eb161ab237ba38360aef60c04fb2a1be7695cd42e7cbd3a645f9a8348 +ffe933668bdf286b7a9c394677c3f316ff725ec4fbf56776a3ec46e8b81629a0 +18c62bf6bfac2f9aa1e444570ee0af4a72d68498d05ab1920931a1b1d29ec01b +70aeb0667f252fabb8741f18f1d2b3b6d19f24e6b36e4266e8fe1e6efb04d27a +dc2be6802fd7e7fffe88ef550a88c31c9dde4580a3370f6a8194dab7335036dd +72ee7a491ed43f4a69ef98483523d1331cd9223d202d5bb33b18941602d1b717 +00ae62ee6477ea39bcd399451b537fdc4ef0c593485b3118b9e36fcc0db68396 +9d4682edfa645980d4126701df51890655bd73bf85767a234b7a718cb672979f +2791e95613f48b3b93abba0ac356bbee5e8b701b986cebcdda9b87c8cc135b4b +6586a3fd160b4e3acf13a88fbd7704e17b1a6d73ce4db474f73a29cf562fa1f7 +306a40b1909129becb291d2c4986de647996bbff881c6622f7374470132a1c64 +631e9c402021286c52674d774ffeb9e9e844dcbdd2a809a1ae24c015578b6f62 +8fab2cdb318b03b5c3d77f3a3a87c46989bd3dd5fa09dc5375c0fc51fba832e9 +b6621697a90acbc66dcc6ea0d890ba2129eb41bf22906d01f82cecaad87f7496 +9dc37ae417b0ba79de5aa66d8a12cbee50f4f038206ffada5f92496fffc05a1c +5655659fa25ed472659e1b7651c90786e8a33edb004f205986795a4fba089fea +d47fd7c14af633dcbfb26572c2ded8a65b9e2d51b0ee83abff13a2a25544ca71 +cc00913d46253ccfd215d760a458a22f7fac1ec5ceeb39026ff3658525c53185 +6e119cb22e4d2497555a2ff4d51c323545e6e464891e9d6e384d7c65fdb819a6 +9f2af990675045049d225c8575309f982ccc94f0c4908a6d14c3e4318c38677c +9bc7186ba5f69eebc5e5410586d388a0253fe25fd319f890dcf20d98be7182d5 +7d177469cf6cd9d51f728effa27e41d953275a73c1f44c2c8c7103ba2a1ae893 +63f429b96183a160e636a4e51e7dc281732b480dc24793a26de59cf401fa7bc6 +a6a8634935c4656e8eeddffc3805e6b69b1dac63715bc0da3da5e331dd67d1b6 +927fb2a7b652d1b74785344d9f64ea4d64d86f2473d2f43800d2f3068179cd3a +34392eaeafc9bfde8de3eadcb20faaedf9640ca49e9f25e5a43fabecbb521c6b +b79d02483da1ceda4cbc38041f5506afb9088ba352952f2be867b9f10e9968cf +529b537fedfcef63457d3620ac25a9ef6cd30aee9a43a43fa1fee197de64e966 +641e653eff07d2cd151879751bc354dcb69a71d98096c3a3a9dfe94c308378e0 +47cabcb3d8994c929face095fd1a1b2acb51ece0870e0d635cdde62e29ddac9b +929db95c08d0a19f16bf7b45af8f12d9e67459db154b9dd7888aceaaf51645ec +a1826052ff43175977f583f4eda06a6c5d26d0bc30238e96aef89b96cf8260d5 +7e701089625539aa8f2d7a5cd6559bbc7fd74c237e51b38643706f004187ed2f +c49becf19ca45457c64c0df43dd51979b735631d5729f160c4522246df1a9380 +07382b56a45ab96b76910fb9d329f7bb42e4732c3dca16856f5db5d0a4fb4cd6 +066ee1f14936d68016ba41e8cf4e37dc01a215c906b51d26d5755c715407fe7c +f05116ff7a2ad5f715f04f116294cc60c48c8fdc1ff144079415f1377707fdff +37aa7518390b34ffa7a92e5c61e8bdb5c8c901263b863c12fcbb286ac5cc3e85 +b552d3e3c77c66f7f7a7286fbf511e682ab7d6522cb0cd60e5bbd41c254e6de7 +99d7788e2042c0f4307a6b9df0557bd9ded3fb4485c849ae8f4f1a02f31ae4b8 +351c876581bd88185bd73d0804b23edd386a39d1dc676e97bfeee2ade915ee97 +343f43c7e78000a6efcf17ebc986097ff4fedd38414cf6d8992c09491e49a260 +8124d00eec2cac95ff05df23e4d24540d0789722f365a0b1d6198d35d75ecd5f +33f85d0e817b5e4eb435a60362edf8d424c61bd3c6b4474badeee3dae2af4db4 +feb9d20b773aa6bfe4dfd5042c03005040557014bb9daa1e0958e4ff1e1f2da2 +a2e3d0b7a58752bf5910e9d9372d13ca3f0786d7b55420bc1a8f9fe13130e579 +678313fb7f6fc7623938b5a44476bb0ec785584f5dbd05c03e09b892803bd514 +4b4b4a5044c528d64e76e1aef14fe63f16ec3bd6e3fabe8631b5d5b424abf28a +8abc621a4b79e50ef09bc5fc60a1769de2478903519738afc50d645f537cb4ca +9dfd667e69fb3df22195d61d86b7b3346722d73c01cb1a939b89e070efddc3f0 +777ce207a9fac77e784d7880471f0419a36a1ad8c866be1df3cc764b71e69ddb +5af7f39b3b8a27e829c2db591e51029f5a18bcce64cd7ad6de8e4b1341374e38 +3dbaaaea01af0592cfabf086b56be55bb4bd5a23fe9d670fe2f9969c8f5a2e2d +0ff138deefda719f6b59b93a6bae0effe4f530561c2b5a61a82783222d1156f7 +8f70396cf382c4ff780f5fe200968242a3a0fe6f3580fdf9306cb816d3691a90 +c78c6a309b858301b254e6a4bba28cb2037b7f1373a3c657b1b66916deb6dfed +a8044a45cf25587120f1c0bbb3debad55eea5c0ecafb817a901efc72cef1c85a +4dfcc017a1279648b91a7b756c3b2dd689aced540d1d19948575675dad1dce70 +9ab2fcbd4ad6a016265669962316c8ee5b5314e7707f979772aff5ab074f09b1 +b078627f3ddb648933e1cdf8d6a3957a8dc37d1a21aa378bcf217115107d2cbc +0e7ee912ebf02282147bdcf240655114a793fe8aafab8e953664b0312f6b355e +c3b28204a191e125ddc8973d0391cfec829c7aaf75228f0c3bfa265b49d426c9 +f0fb8a357daf3a0b8c5ba5ac0cc3a80f67c158442928d129c87c82bef16e0133 +3a84a9f97844cc900671e3bf515b079aa1ba921e1861a9f7e49166f70cc0c994 +9f26e3038330ec90f92f2dbf4edd4e34bff875af72021e7bf969188d2cc4a994 +858bf93723c375d96c1f4b75fbaef14a69e7e25101d847b45ac0f89fac718f04 +888e3ddb1efd8ea6a46fbf401afac4bd70ed48957335794defbd095de9a347fa +d28d04aca1acc0004201df1e852d9792d5ff18c1627f89917eb5d94983cbd6c2 +645307eec9cbc222707e0b868854b7237a25c64cc65ad9baee4fe5dd3c77978c +f91e0d529126026a0c2634ca181e9a8d02dbe71b368b5e565e2edf1d5856fc6b +03d58d18879ec92c94c552491db94f1a4178929a23e76d4d52f95408b63ebee2 +b1bd3d7997f558062cb96e55e4a1894d5e0a4a35868e870d2447884331e106aa +f7bd08c7b62ba767ee609c87d4a15814385248493991c07652d764afe95a174c +bb5751c32eb447ba50155961a4a892c2d8a70971d20d9b6fa94a8d80d9671ba5 +9f6cbcd32fd6cff32a2cb877cd60675afd995802ecb37bde513846f530a60c7d +9d432ee768a9c4b742bb62337221b0981bec2271214013ae23f1762fe7565168 +2f9effa5b993227c02ffaf7d3b37ec6ebe101c0ec2d8e8a3c13c0a56ac9231de +48a0e39d7f25997954861ba8826b52d8852f189b4e2bb7593ff75df173c596f7 +ebd980f276b3574e1327660f62835d56f32bdb3a658c2da90ffead81fd03c7f9 +d5c5db03edbd8f9bfa8230601a3a15226c429b6a36bb86d6fd139a315a71932f +144c046f135067d5767ccf94cc21ccfaff4f446e442c497c280e0cbc53ebe6cb +e65367afbf04087b8257e10cdba89b4d2c1482d154c863e6ff252bbb85e50b68 +ea500dee2d18c22740844efcaa533d7b628b5bb1227d2a72e6fe9e73c46e3419 +811fe74ad28310cb6106aace75a26bab659af471870d03a3493ab13fb97b92d4 +b71c91461196ce842e5d6d06679e032ba5032f6cc209978525efe1be59c52149 +e226f073772f1b697b49c53ddb1311e142e67df158953e48910f568411161604 +3c8c9d20812d1277372071bcfb6ac73ce4813ebadd05886376d38d7b811d5070 +8f23bdc8b3fb24acf061bcd55fa93ae0d169466754d478b06ab91d46f3086a25 +cee56f257e18aa302805e063cc88bada0b3bb2fa731db39e961e7a077286bf03 +b977c1a59f5ef33e40e0b40072fde7062d534452dabcd864fb25b8304434810f +25038ea5a47f312ca71477cd738fc948ef1eeab724824568734effde2e39afe4 +26555c67ef2ecd78e328c4ac784e3be334f867cecab5e5e45bf756c88d8d1803 +75dfb81e6c943f2b298fff75ecb9299e1692af63e00b3e6ed6a45895abaae85a +d9830e8deb8fd05e1bee1d7d1f57a4b53b0556457370a69f52d05675979b4986 +d3bbb2e800673963decb713d612a42c27a51db1c0137ddf068a33531cbdaf4d9 +9f9156d5b3d7c3d708171d985976705f7025dad8e781309e4ab983b8d7d825e2 +8bc9c7f8d8d4f6b7c531ae29e8ec30f5eccb2fd2c172e74ff0a5e2a90f88ba3f +6f9e6545edd2b7ce3b0ccde0ddce75bd2547a027c6bfecf05f18b1ec4cc5d162 +f149b3a0cbcbf1f2a95a66a04930e37ec137630fa381a3b5e3685a5b1d1be905 +3d618870e5832f2f1d2c2d10255ff681142df338c9e7485707ea9a77726defe6 +f0778be7b9d6d5c722a1898b623ab11bad7b885c136fba7a56020cdb4c020e18 +21ece0b76f763e7559aad7b361398503b5751e785fb10039a01d77f54bdae229 +337add36f182ff16e035d24e4f54592fee1061aafca1f4d6b6993fb040141f5d +44653d1355ea6c77f1d57d35945f786ad90c63887d39e5186d006eb6f8b9da8a +443b2abd36b268b134b453188a00f61a7936a2936f30d6a7775b6891b7351084 +d8cb4322bb0a39440639542991ecb9a1563ea1f7d22aec9ce5424194758c6c55 +b986bc88f918243160de4443a496b585a8ced5df964fd3981bcd25e65ab1992f +9bccd071eb766ef099280a7879aeafe5af75af95e89948d5200c42ffd8a356f8 +6d17a388be3c6678dfc35d5606f67b6f92b4a17b30408ac8deef1dd26a9ffa3e +cf959522995401e29bfe9d06af57db27487a24db5060565881be3e918a1d547c +85b7e979a078118111767371ba2075e792af13d5c48e60cbb32a154856807119 +43ff8c16a48e2c629804f5abef3a0e0d5228463c7708f0baa3f8a644c2c9ee64 +a9945f6b2e72b6f5cb41c7455f11c4677e7adee3f5e720e623a69b98ba7f9759 +828ff89a30f0218e4f7d07922b420dac3ee811d7fe9782fb7a72c8b25fcc4b3f +5a976495c047da2594303745ecd748932514e249686c716419792addb993a534 +b8b6e5c2570cb73736789d6cfeba3981389217226ee3108b08375a177290f6a5 +d98b740d9545199eab421ef818a18f837927e5c0cd9a8bb048a3a106b279512e +7776d882fcc14382c022a483d01290adaa4556f9df43b0211843b45d443eba3a +64144491a6fe1f0ffeca69162bd1c394f9070d010a5d661d59dfab0c40b7d964 +74f1f6d157cb43e1a066e8d7ef77f438d82d680ede607af96ffbebc8a0e950f5 +de67372651380863e39a67608259232cba21e941183dd8692f54dfa0efe9c4a1 +10e77dd8072bf57a08134fce7bd5fb34c3af3271febc16b4de891d1d00988022 +7b710fd222051e1b9da5f95af123e38e1e34911c57da17b37278e3f776a23680 +5f909072c94d9b4c123d9eba1b98c0bb46ba4ea8711946c5addd30b7aa439e38 +b6a357a952b7fbc812d864cfa983ba33c26b6a8bd79fa9cdb371fdfc437a36f6 +e00c1f75086de6b1796c3fd01b60d48b3d563eb5c6e826b6658c4c4168ea8c0f +ff8903bfe9ba441e48e9a970c05a5ff66ee31203fd762ddfcb7cf024905c6186 +5dd35273069008bf9ec95310365aceb69da815c513b4575a863c861ad4553033 +4a1a8430aebb65b9123540c3d1095aef2709862183b6483284267e4e54a88ca9 +e1549cfb6a0a67ec65bc50aece1d80c99fb39e5dcd5a011681fdbfeabe703341 +38849b9f2794853d58107d086a888c42427a7ec0a98094f2b1294dc8b37fdf69 +5da95d4ced2990c683ae106aa1f8a156dda7bf2fe6ac5f0cb2c9595a13161290 +1f9d0456a6f1b018f53c3815afee7af05e4f732aeaa045b7fce5b2fa5e2dba2f +9dbb4e8cd6674665914462cc2fdac31bc58d6307f06edb988a23a3713595f56b +4ad3e287f1806514414fd10cd0249bbeb7dec9f77f025b505db686c7358be24c +7f75f5457a18fc784ea0ecd1df1922c1670932db36fc6b5a3e51b947183eb07d +7851786f4d102a3decdf8d030ae6ee465ab75a832383a14d5dcad421e1fe0f3c +6746eaef4f17098fa85d208975f58628fa214145cdc1c84052bd77a1e8c99521 +cf3060c0b0a9f745816315f8d93491b6481fc1662fc4900a7c2b1800c1dde8ce +ebdcf8ac88d248adcec59f4697acc61e732a28bb4384dbf4db6b103b12e08e04 +03829f1fd503e21fb6726cd213d801e31a00b82c39b36ee436961f9eab20f293 +06052ce2ab621af2c4e7ae1e90797b0b3705829272797764883e8ff3aaf39d6e +db48ba8c329eeccf19fcc9cba567722a27c5d849073ea473d97191d40ac3e134 +8f64d66df9e960f01bf9772c851e58d27f9589edb445eab6dac705cb048f4c43 +437775ef8acd9a55f0d0a4548bed6e24a284976028b8b5d5ffb9f009d6648f75 +3cd704f2fd6bda7ff9a2295f2eb2ba9cfa919d6ab3aa11e2cc6457dd05af0102 +3d487a6b0108f28377352aaf85761c72fb9ed115057d610580946469e2af00de +723895de453a2d5ecb9a564ef46b5de3e98e90848f42411d9239baa896e454e3 +a19d3abfd97a5293c9afd01b2acbc1ac9149c73bbe31c125072cc19d6c27889c +93635fd5bacb84b6a43a16e35ab11fdda94f14c1b92eb912b770f2a7743813ae +57dbbac535844711a30a321346606890711dbb9cc0c2ad4bbfd1a37ec1e77554 +81d89c0e679aa473a6ca59932b533c91392d44e48238fba1d95c1879cf65282d +f5540b97abcf74d326c5367daf60fcd7a7b032daa1732e94dc8b13dc6f1ed1a2 +4c3d716a196ecae2028270e984d7c3af146f8f4aafa47242c540a007cdcebb3e +049120d8352417ec61071e4099f164adb0a3485360990b5cb056a1f5ef92f033 +f265461880c9b0e7c2431a3d35bac0e98ae33bec8ca14bb091d9bdc04020a907 +60f075d56a0443528dccce2237ee418d15cfefd23ba0e7a3d64003c4cfc48635 +e212a9da1fd93cb5bb4bf84e945f33dc13f480ed8f8fa353004ab4bee27961eb +ea77c54f3c2cc5fd41c99e1f00288b48163a91d3700a6a7333228ebbe74edef7 +462e2d36f86d55d130a4a06ee66485810baed16caab397026765d05fde388d62 +3d0b5bc50891e71bd2694f90eb786c2b5faa0778574e03a702a150a36f70c1dd +47ab1f37997b3a5ce5014a53ff6ae87cd158872f81ad96c52d3a16d6cd828e9c +e67661dd4d4309a2901c4dd4b8e3ca5be050b2815f1f3b07f96c9008be79e132 +99a2bbabfe3ab2deb282251f98e02f07c59954b39982d05dcef9d93a00c33add +b3afe36f5a07f1a4dbfb44904c04d6a261f11dbb71ec71700deb5fea74bb15f9 +7c7866ff4d4feeb7f6e2cad8984f781b9286436592d578562245212d4af80554 +a16ca28f7a1145f70a0266200c0e8947dabdc48c382c5bbe4595695c7b63c52d +548252aa2c618fde22700bac288b2bb3958a32c2d848c8c72810f4e394bb8736 +93aa57120d97de877cde80786d76967f415146c83bf3ce17076880354009ae94 +782f4a4114cb97030e41be0a82431c1d8c946c99ca86f1c649cbc0722ea36aa9 +ae552074e0b1e67c4f458508c33afaed1aa33cbf6ec863dab2f96ba35a661025 +8ccaaf5076c726637f577e479204a95d8c2196ba4ff25886b954b11031d53426 +b824b68346ae5a880102de8e6e8e6e9706395589aed9be28f81d74712893dd7c +fecb232511066da78a975c06b6108ec13687cd3f3e7779e64507cb878aad6c87 +8bcd01d78f7f4be45214245d6ad59430f02e96151224e57cedee4b00c33ba5cd +88b8ae206cca3740db31f96b37e84277ea2ca3cd6818edce75288aaf01d1c7a6 +302f1ca5d1b31d50bdcb4e2f9eddd5525a540c6dd23213bae7d5899c9b9423e1 +48d967cf7e887747be5da2df939cb4c8bdec7ef2f7f7b902100acc638d48bce1 +2c35d6fbb827276806d65765d2902d9276a04da74ab37ae9ad746dcfa6721502 +767db51cdfb4f659477de1d234fd95da077be793329940dbe505a37dd9e0ac26 +dedd7912ae2d74c801844b6beca88f3aa4c6e424ba1062f8b8ff0c8fa5fce657 +62e893f1742f19fc728cc1d24cc11c049d94da4aa2e8071c67dc3ceb8ec148b5 +85265b34e9ba65a928d3126c103476e75b0c7fb1b6417fa9cc8b2404cb4b6d7f +087174936c128b73aaf9a02d0740d30c516053c8cd895326ba1e0ed08f69f88f +01ee793771266f1ae0bdd891dddfc8dee1d5729a4f1d56e5cd0e9bc370c0c4fd +2f456796d707afae69ab2821442ea8d1f458b3d77412029d24e704f4d30cdecc +4fe2d35deafbcaa202694105e54ba32d025aa85964aae9050652ac84dbe38031 +0b04dd0592d28e527aa4f0cd3372d205b761e59c6da575307d85d4a64e754c15 +1a0750c97524a6b384b875196c2e78656ef4e97e34f376dbfe37a968ef3d0f2b +3d0d92e8cd6fbee9ca364900fcf1d262cc07b79bd4b4abf9e43390d7f32c859e +f522f9dbb8391cd3da9743bcdd3786f0c43a5afb14c18096790ed2b3ef547e10 +cd04df6737b421d0adfa956d8bd86c3276e8b1fc979a16dcf54d20f60e57cd97 +6b48f6bde4cadf626595d25c63d64d35a19985fe167610da47e34121c8fc35d8 +007dcdde7d5eb887d4a15f26480129b1095f19665751ff2367d09e73bd2d4afd +0ff73a12ca7727588a2e99e2491fb2e129c058c3ba5bea9c9faa26da9987f3c4 +2e1c1a4f3beb58f2c4423b06fec89128aa87deb3c58d1dec34f65f431913bad0 +859d735ea762c00edc6bdb491b641eb04f6d739fb9f5c81a5ae0f21082a97377 +57819325d6dac4640fd10d94eeb6ae17ad4748c41d6de01de580cd46822aa77e +db8e89cf09744744bcd49c884e843cae4d273bee5c3b7677fb6d61f3bf828e06 +3cc3767253577e7c1a5fd45eb846e9b02ee00b8db07532ffc1daed2d134d0726 +e9a594c278a128696382ccb48fb680432a57033b26bd661c2c7f5bfb9fa1b238 +1b0d19da4f0b66d2782fd47958690b6c8a7d515ed74db08199f569327008be7d +4745d5b014bc7356ffa2dfd4a29f127da7c8c6a224e2991f2768214ceb9ae7cd +e4cad5ece1a5f646dc6a62c9a71e27cac04eeaafda04c52016a2e80f53b89b2c +d0547923ae39ea12b726aae931d85aade7e84b7f18a34eb93e384de3e34022ab +b39995cda75fbdef0b207dac38c19a2fff96ba53c78ab98a94ca33314c8a136f +60bc2e0656e032f4740c6ab26b64d82c3335d4e50a4ca0b49373d55902a74238 +28fba34cef0642462cad4a1b281b2443eb350660966b7a6262cdba724eae79af +2f33060c3989b3131a63150f35c90b876b84be5806811e621061393178942ed5 +7bffce2b343dfeeea42d81e4afca4013f0e12b502b0b945e456128b6aad85b28 +11afcd492358f3dadad631e52545da996dfa6635b5f000af2d27c7249688daae +e542eff938f675416c11f4a1e619e0651fcb89ad9e9c959c65ef3d1b259cad02 +c46d11e1dfe7cf0f6a01c9755e6b1b0788464adc0f24a2a61b2553fd1f360b73 +268e2d8b605d9b8987693eb3ae797afde0d95dbae52133063b97f4705ed4b52f +c3a4ae78b3b95a2e96fa82f13c7a9be2e736a5b625c685b5ea5ad35f56ccec3b +7d78b20ee313787d732ed49d3a9b75c1bf0405cced5b0e4127ca051c2e23f154 +494592f7ad266c8e9d2b5ab441a28c8eaa00ac2ec41374b179cbfd27584293e3 +0a8eba0ffe463f4e8a2864ff3a08a6b1d96117f53dea762a16e8ad8e823814b0 +237f62d1b448d93963811ffd2df9540572291ed29cc5482a9699ac490848d480 +c1c3eddf8cf277a144ac5f41a8519585719a0ec0ac1bb933a6fe47f18d5a607b +1e526e0d0296e8fd4ae6220d411e0e0aaa712b164e6cb6a1678d26b81a857b9a +84e43403ca23f11e7f10d5b5ec02236c22ba82a6ae9b77487f1466708142676b +049ad89453a7074499f82b6af372493ee58cfa6cba41f0b94a73d3797a499e18 +ca013ed02875df97e32ce0cdcb7a4971dc2acd7aaf0bf4a0517d76dedea0c04b +df7463d6be65d4f2cce195d6a2b100ab7d9db9a41e802cc59d7d5440eb58fbf1 +02dce85191d672b009e750dfc77620652ff4e80042961cae4e984017781eff9c +43224eb387d79cc005e8e0646716078b7a1534b2cb0957a827fa27156a137968 +35ba0178cd71cc64556c7be17dfd03e4f07f7451133345d186f666d68fd33a7e +fe49977274fe833df777a6c1e49b728f7ac3c472fd720084e7b004770c02cf2b +38213c5df6da2c96e16292563f0ffda791af99708a71e08c0a1fd8696267df72 +a9cf2fc5838e38784014f8d717a1e327ec5c9975fe0e44659e069624a73f3a41 +9b86b0b744f9dc624606011b810071e48af4f66edffcf80298969eae693efa40 +650f81c709b20f68fefc9e50b84202c111cc2282501b92ec27e4bbdfb2abf028 +fb5ff79a07194c4f0c7e7d682df84fb8437ea69a00166d267df774413c25ae96 +5f253c7ad38bf53d25e92de24e776f4b2ec39883e8c312faad560112f70932ce +a863a7f462e48e292c178ba2261773d5fdea85f8b57bb606e85f2c73e14c0006 +d9de6bf96a4e55778c2e1e4ed241183dd1986d8ef5d7f802031fde4d54624f27 +701459ce2f8816f2241c462d00bd031cf5dbb1db93776c585d41cd884e628ab4 +a637996b54da1326e06c3f8eec9abb82fb21f63f8a7451a498775ca78fa77840 +accd876953c86cb37a2499956ca138807c2935151e198704971bceb36a630eb2 +d7415feca5088ef238f0b9304c9d635450ccd346ab3a2b9d283452a8da0e1039 +45108e29ec07459b6a4c2eafd47b74ff14861c5c7fb820cb14b90fced5650716 +d449d6a5d4de391ff952f6a6b62c13df6cfc905e90dcdeec87a9b55d650cd245 +2a5778974390e6e49e23b3fff7886c03405a9b8f4eff4ec9e12039df454b5c9d +e8d316a1070162d8328b9fc7737bf8e36ed41faabe819ce5acd5dacb3ea61fc5 +0f74a3bd5353f45049ef6dab7e9ccdee891673a82beee26a918244289937f578 +4624b2fbb8d9e6576031dd565549d238bb7f5b0032141e6fad99bcb71eadec0b +771f74a4f403f2ba460ac19bb155ead5ca5ee911d5858814802a58cfa02e5b88 +108b0858b7460baa6451cfc6597dd2a5334542f54849f7d143d138d99c303c5d +e0f534abd6b7bae22969f179c2e531304b90f7f7929001ce3f13533d62b5c060 +8f1c191fb504915d42c94098b03b85046ea208da33c2a4ca55bcb4fbeb7fc292 +6bbd2e030cb7aa7c0f66205db385657aecbaf41105939e5ba3105b7a28aa07f5 +e483127364acc7f663cbb38c3625510cb1c3e993432db7136291b2cd10383443 +daec0887e297c4e1ad98b4b599c86c9d23f9cf991f49c416e62986a40c93b70b +c445561ecb83399b2b09a79e531dc69e5e128b7ded72f6c1582ff8dd118216f3 +d50759c3cc309244b7115df32dd94de19b70b79ce133636e4d9af9e5ef90bfa6 +306a51f7de1fe92232cc8e601c4092d24e6f07c5c3ef3bbbf65ebd38c776a065 +3b249ff82d28bc485bca0694a625813a5aedcf50c73644f80cd66d2aab337d3a +e44828ce1e282955e07052183b86ccfa0d7bfbc399579ab518ef365276118060 +c16f5e64561d5bc860d17d77a7e1054ff3f9226ebe73b4723b4a86d4ff55cab0 +c275d602554f03e6f1eb3ac6abbd10efd4c7e4d0a9b3cc86468fb855afc313f6 +60f65a98a33ec89a7c85b666ca271a5e9b55e69e82d447dc1cfd8a510de3317a +46488223efc136a7e934517d2a57ed104c3c8e9232f572824e39cfe54552bbf1 +1fc5454470da20ca46cebb0240d4d4a3de2557ff8bf39fba0f9b8651c0a8ac8a +26d532931f4e1c9e9a7eadabcb91b2490a4f8c24d34abca7d59c2f9eceee6d28 +a12bd77195c2643bb7ef31bd7d38bbcc94a9fa901a4fc08f75f5e705cd4af4fc +823bbafaf76eba4f3f414f5e02a900f57a72345c2457fa923805396a0a76c1c7 +0e3fe87dd617279648dbb85a3115cc93cc3875d834f76c14ba3763d893e1ef31 +85109c0963da880fc44ff9088ac00034a147fd3e38897fc84e8d6a64765e8ff9 +cb9579ae75e19f405be3aa6050498de7a7c4f2777df613b80a1bc19f8e7970a6 +6aa1515817088a5c2c1028519354baf856ac95ffed41f05c8a880cdfd5ba40b4 +071a5a9296a01e3675a665ddcd351bbafaa26868189dd507f252425ee8a15744 +7995d4ff79e35d23d36eccb953a7d3c9ab677cd10718b36bef17e67d5c31d049 +6523ced555b31b1aa1a322c8121061ea70afe4baa6b48a84d6c705ee19eae98f +b8b178ab53b8049e0b44db097ce9a09e5f4984405adcd3b786d1b56d8fc3eb68 +4a0ad48618009c60831f2596a7532f20b8747fb12f42d3f57264a09b2cd90d7d +644f1d0b00b74a9e99a540f96531d33224fa87caca9a79f300a94407947c980e +b84a11d0a84ff95ed219df934b1aff1e21e6ae0af3549ba0a392a9df4dbfd1d7 +80008837efb84fd143bea8ad15012ab0a8464ad3debb63ccead5f3c53dd00fc0 +4a8bb8321f76c0e9f9682fe37f92537caf6222c19a91cc78619fd52aa569a271 +1f9309c2fb97aeae5087f7411f832a9d025794f7ea7e0c5c4e51a6319fd57cd1 +2b15fa67192b92cd2928038385385f9b316badc630c37405dbc76ec96da8667d +773e4d7299fbaefafeed2e154d72e61b18403adbc27e6a7d2fc40c224a74e415 +d2cff37962463e52d54323de5bf8f28a8b868a353f974a6ba0d948d3d80edc49 +efdb3d5f8dfd7b70931a09bcf689dfa25dff8f359d6ef1c77c7023153344b837 +d27d346e3e01b4c563bf3650f0ee7121e5e6bce7eef34bada5416dd2d1638d45 +72f313f6e0d2707f4d39a35e89c24d3837bcbe6c6e1e7abf410053db8c2f4d06 +98d8b57901bc0d065140c8b255a2ed6cb2f4f2d5490908790672888a7f730043 +37478eaf0b2671d9d8dd3731cdf2171bcdeaeae52bfc938452667b5cbcf94136 +9895921bc270465a91f2d4a4a1fc9b7bf8e6de083fc0f42b06989c84b7d277a2 +f6e5efbe029d57ef50f3c203bebd446d757e2ae683ddaa1f43b1ea4b572c03df +71b36a5e597819f6a93abcf9761f9e3b3d472b3c5b9848cd47ece407782878e8 +a9dfd2b9ca3cc0bf1926eb2d9ad4c1b17da35f8fc53b9717ef7cd1bf12b39ebd +dc709a6be92ca760f74d83a84c7ac7a91e49fa974f0d59ded061b245083eca5c +f7510d4b150c959a64bb5045ea658015702f0d5e6ee802b84fb02203ea84efe7 +b5af45e90e3ef8d31ed750f33e6fbb697bd33f9ccb53df74c866c97679487caa +da18499e2747b045e502c3def8465d9232a483927057541e0617aeb2be94e800 +bc98628dbe74514d17cb9fe22347d1f14a9d039266732a3b6552f0bc52c3e08e +67b45478b7f381a4e44dece47e9a8508039a4cf41f7397590019c78bacf175e2 +656857717870088f49a6b46872a56e68192d597a0cd95d78c31df0eaeddb0889 +e4fdb32183d92fbb008bfea78de40dd00339165383fed6dd3abe8eb777230b52 +c0bd6d2abc5e7e43b948b95d4432d2cde72e3846b11e5ac47dc239e6f6a9563f +d49489dc96ee1ef7e8c09fb2852649597014318527ba7e2d7faf57708f2f6047 +38f48bff3ed379f1240f7ab02968918fbd72ead95554287407db3fca569b0e40 +1c95bb73e14b99167c1fbac7d728e258a73c2aef3195adcff2ec1215134ff3e1 +ab872b387d01e34c2540afd8dfba0b524029a13c0a3dc6d4a645d77d6e8872c9 +6da71d6efa0c268e8b8f9fe15e3a412717aacfff75024b3d3d87b59de69df6fb +1db4eef7233876e2225ed403eb0f15db64da545ed89bff3504cd3effd8c22752 +9e45c55c1bbb2306ecdf004e07957aea29fcd5c68cc45e99750707aff8ee0c69 +fab10569ce90254e92420df10e2c6a6700c97be2dace8a52744f06ca6207fd26 +42fae02b93cc5949480f8152dd6c76c3907f09595d84b236f9e74c413b7819fb +2abf6b400fe3462b5b5d76e23c46997f93a3b79d8501a783638404d696f54d92 +d54c12dc172b7d80818760d2301777c097f43d82bd6033cbe360bd96d2dceddd +d174125da69f49f3fc88996ac478491df66d8db3f338a9f4bec6f49f47d560cd +867d214fec710ef3198a397acb022ce73b4f9ff28b8a4c4c048e781fe5dd9b81 +1d29e4175ecb6285bd950d4e74b1fd83f4a1afe405bd0ff26de0bbdeb18c1a3a +06b1c6061830bbb7c0712899fbdd7d9e7272a16b769eef601a0ed6357c4a5635 +90432966ffdcc5e62de2741eaa10a13ebbdd4a50a97f1774bdc09ede8d7f23b4 +5e38b810c6675e9cd7eef69ddb4fcb914d3c7855d748d265d96ae4e03d8134b1 +50784fd107583be549ea82d13b83a97c0df1c9880dea6520d707d111bc0ab9bc +caec0d601a69c9d5cfc8fc27ceaa5f472a31d5952967930b7f0a162a0a6c4d97 +8d4656617e61569000454befc89f2a43723c63b03d6e7088648a673f279c673b +9785c916dafa2e7c5023b9fe5f33caeb8e6d62dad3617c6892c9e84fd5d66844 +7a79845a62b5b90d62bc902a58711a8fc70a5e8124b1ac688c11dcaafb4c5c49 +f74244f22806dcb9f9dd77c3b7f5cef01208ac69d0e1d34476c2d3f9c9109cc7 +e9acda7805bcc1c77e42c3d51a8b3111246918270342e1f8fd950f87de0a7de5 +68c4454e215962fb89c26fd4c6c0f76cf56405b1f5278b9a53d1c71a30ba5bf7 +5eda303e75ebffc92117c3f58b5313a225e50ed1191d47babb7c2e0e797d892a +9db18b914d6c5ecf98a35a56b577f2d3bea488d812fb3aba9dd799e18413a176 +5bbe044f2b855511b53f9c3f71e6b78386b83c21a680c0393e3629905068e17e +b3f2fda638b4de63106f39274b8ad93f7f82eb79bcea8ddb19d5594052712f73 +d9478015b008c62fb824924bd09850519357d07ab34143dbbcfda218e5b37071 +bd778a09302936cd0ad62d9ba4dd5fb7fb61fcf239f04fc3a6f897ca42800eb2 +e8de582c8d788a62b1dbc0e9275be5f905b520b74565a1251e83e7be2fe0933f +556c118dcd40af7c9108e33b1302b7653c2057d3a2a99cedf27f7185477b8953 +40b201e4ef7eddf6b81bb6692ef90a4bf8cd66462236d61ee4bc9d23419e588a +60a2cb0ac902b31fad5f324f7e78846a77747a1b16df617f168bf009a9ab27d1 +9239c6c9c14a85c073a5836369170920b8e076f58d31365849fe73b3fcc47cd2 +5021363f6155ad007b1740a66f17cdf12a2016173b1049043321a1b8eb1ab278 +223af3606ad0e0c1788e83b2a9fcbfe1640fc3dd69f604f1e05d9c24d70b1c88 +cbe6f26953696285b833c99b777b361350c81e51a816f7ead7f399846877faac +8f1a04ac053b288432f6c223de41c0a07924e27edac39fc9c74ecb664be7bd59 +2b1b7c77a7e79bef8ea256dacd5c84269a96a719690a496e08dfc8afeb11b22d +c27db5261a458077180dc8a941e9692573d1ce78777c4997116229050afda9ae +6a081a1dd4c01f233a73427cbe82ab6627c6cd63a6f1a55cbda1d7da7219330e +d4fa62b9e24c5e9c7a226657e3a214ac2b6754232869a187a2a5cc68864f689b +657ee0b7a87829d702cd05d9c825665ce2a6eaf4711c0bceaedd4a6766dd00e8 +bcd00e580d82bb60d4b6af8ff74e193af5f9720aaa971475b5c132aab080c694 +463a4900f4751fb33f6764175c2aabe3fdcec21285c1c8ddefb8cf427767ea71 +cda4df4ab6ad8c542176d41fb307a8dfe6024b36e8ddfeed487a0ad4adc2c9bb +d11f05865274c478537417271f4c835b2067e911596f9085711c4b595359c9f1 +842ca391171c819a15d3d51117d2c2568f4c26b7bf25450044efdad8e3148849 +03abd0c39f61a26f5803cf2dcc411db7f3a8d0961dc180cdf71fead6e53054db +45f2ae80b1f27327231a5d1b50c6b5187c7b21c194208edcad3ba0c17f86a14c +ed87914d2920b56b44f77319b5a2bb318711191c29a9c77675db208f9bd2cab4 +fb35676eae529fc3c5d340b2885cfa66ca73a09eac38b0353090f02c60f420d7 +11494b800b0a83c6ed05faea46edb0dca0bf066190f53ab98e5ef8a9bb45794d +ad4ed2e03cfd079f218bcff2cdb18019dfecd30b2a91382fc6ed4b80178b3bf8 +c4141c5e1b895a31cbf9b1a89ce0834351d7dd67c997a001f88d14366a46c640 +fbbe88a4af7c1a2ed9fab22a57838121de18233240e8e0c3db4bdbe8f8a26a5d +b53b830afaac97135a89603626a3b145a0317c1e25124510829236e295934a80 +f5c47bb7de54b70af222c14ce762d68595a74df8bbc1f7a3df87a0c4ec1087e3 +95db170092e4c1f3a28d863c4f4b9ffd970bfbd98ca8dc77b970775ec5d0587b +d4fd4f670c0830d60e59d1a01d95a930f8e6e767d156518d978cad77e49c80e2 +cdfb53ac8e6e9d2e98585892d5905e587459f1f84bb989bcaa4bb507fbbfed40 +f977903a6a6cdcb1140cf27b8774dc327468e0dddb1f08ad498052a942bf49b3 +f54710becdb8a6cbd6654831ebd5e82e560a57defe28c2f2ea5add62718f0aa0 +79f4b700bf8e09dd31539e643a78eb10908ed04708b1607df45c3813412e3465 +e0c73f806c700f863d7d3275fc3c710e7e6ea5426e9295dd7748be5a5a76ea4f +76ca59e2aa5d8d99e7f1627429b13fc4fb21add8ed22deb368b30650b7fc0179 +930ea203a9cbf4a550b923ac8a6615c66e5f35b6a75ac677bc5b3c35c3ea7265 +18752b9f3e3ba37c8077a7f9dc1af45718348a1877d95f0fc33055b95ca21f33 +29a80082c176b60f09fba90b2b73f6285cd2045e7e70d7d1f85a816c38192a42 +ea0017a4a6a6e6e1f0d5194574dd7a90464219dedbe213d77154ee9e83ceac5a +4791804de2ad25889589178d4a672a2d006bfed0f1148f8feb60a12534f519c5 +19d5c889d908115a80b8fae4cd2f941d320730d5cbddd41b4aaa2664bf1fab95 +6f0f5162e27baf85c5f5cc2be8103ba0ac124344dcc4a5c25775818ba301003b +f7f8e5a39e133c3b073ef21cc0af5d8ad6e73c9e32e2266d27a2efa6150414f5 +519fa27e0d4f924cb23f2a9d1d340e2f4fe4cdd1b0289c49993655f9a1567582 +3d4d5b7e4d647c66f3f52e3be416750b302c988f06d125d36c1510c06a6096d6 +48535b79e228bbac646152f191ef7b919635b7426f581cf324bc47ab78ce1c51 +9f6571e7e120923616f5e326fc64af2f878181d7a723f9f857b26587df537eab +3e7203d79297cd61881ca737dab209415448024aacb8f740204937f961a89f68 +3a56fdac364c6994fe3a9e4712544262a0976339e4423ffac22812c619322015 +421b15c21455315fc68b738a76f375416864944939f86ba79e332f60ae0ed6cc +9da23821ed2335d1e2a6874b848261b2aadb30cc4ff029b234df6fe3f35fa4fd +7f25085696335d841286536b0119643dcae8bbe83345a66cc6a8fc875f613971 +9281c1d6a6d6ae2e36a74c8cecf9fa2ad4267ff78636be147e5133ae79814d30 +114b3a417a370926cad7db75e4cada32addad6e08b525a546e3398c48e0f3f53 +0ce7a9df593caa7bd1c73ea5d23513c290996269611f6f8352223102cac73e65 +7f9db567bf0e8547736aa5202369d9bc3e9ad14930ff3dd0021fa13f4cf086f1 +d925f1158cfa6fa85e767467920ee70a51af666217d37e949c250da1e420c278 +684a87b612a2765afe6a8e05d83469b5337f30111a6bce01b82b5c4f7e4a8e75 +8f4c3a8653fa818792bb0ba3c3cf86d680c1cb931e61f2dfad8a27474abc855a +00c00981798df1cda4cd9c4e1b285448f5007103877d0f365242333a2119c22f +ca537b070720a85bb9d4ff3db1eb8cc4cff1fb721063694e050e6c82866ca62d +0d9e576588e48b7cd83ab4090b3b1fb482e8a2a0541b36b7e1633a758711f140 +f76d471343ed5baa28e4ffe22727c71c5e1bcbfdcbc95cf61bbffd50af60a3c8 +2a64480ab2b0f78fdbfef93bab4be7f6c8dcc7e5ddf76f943fd09162af81ad7f +d9c4612b10839c9f0e99fe1e6c632504ec2ca896e937d45a1a4d72b1bc500ad8 +c99e816e4f3132ad0bd68f1976680e54b0b2ad35c6328aed3b4d997ff1f22ccd +f257c75d07f031db658b6ab3b6d917664fb9f684e1b4ab61e0b94764815632e7 +5ed9e6b6029034fe279e54cf76ac7f732595b985a81f37a82ad34770f3dac351 +a2fb0db97de985ff573ab29ba189547273d82a0bf21eb2afa32f8771b74d57c8 +4e5359855cfc8dbf1f8dda6ddee564f0d5e4a4466dd167376bce055869e62b83 +ad7fca77b39119347e6565963a8ec106cc264372359a26e14ed7740c2f1da5a6 +5ef178bcd24d041a2d58c52eee2b74b1458dd0f0c7b563882e1882b743ca1cfd +7e0ab6be2aff9a85081936002ec9f55396e6612e1484a1d2172888fe56360177 +6ba92638a4cf518a9e409ed13f13198247fba3cc0db502952bbd94da89a34437 +ca5b8e6ffe02e64a55477c1b3580306622c4d09620c141f1698859c747128693 +9a73315169a5c0724cb400cc27e2c8a947049f0c2d74bfb0030276422ca8448b +8fa131ace5da1e6ffdbb14feb34c358ec756ddcec4b8a9bfe8bd547c5621fe62 +ebfc3518fc75c6b67854dda994fa8e53321a574eaba504523d83f361fcea15b6 +b86543ffc82d0705906c9fe76dded500a2759445a15d9618d34c014893794a0e +687389a7b364d84feaa066df3398c6493933fb12cc2d45d2a96d2f1e87d5e72a +494737bb808c49833593428a5c0b72a752ab1afeda4dbb3dcb560984b0214d0b +f839a671b4628118cd271e68c04cb109a376750ae7b835ae125c18009063cea7 +eac016a6f74ceb7ec1a8f9d18656610ad549282da9c2d4d7a04dc89ccafa7ecd +a5883d9e080345a75e8bb431550521ef89d39ddcc76296cdb38b5441bd505831 +5f29c0274a7acef85573a41614e02d4f35668aa5ed5f6dceac920728ff72d874 +953a914cd6e5faf084e208ae2e6f1e5a54608b5dc3bcb514ef24be021c60dfec +b40d908a767db7a6ca3b35e3f282a667935f7f19ec4187ef8baf85b93db85869 +53bb31faf4c31a76ea4d6c06aa4ce4510b89a7bf13524fb026ee1a6d76a35424 +563d6217b54359d7a3b83e0460e22be6c9e959b21a205755f756a4cb0f4150c0 +8c110236f2e46f78d61f1ed95b7c00f2591aacc51a57d624ef3ff9cfe9735c3d +607722fefaed453988aeffa520c7dc99108125cce2e89b0b485b7b9dca7d4bcb +00b7a2a1ed7ede3b8a611c651b6e85821b70f71b1dc59df2c77a281a639015ef +02d7c25f65e07b00a4cabf47d07110bb2e7681073255705908ed0494e42f68c1 +a6adcba5a7337e572fa9a4dc795cd3bc6018b56edb2d5b809d59d07ab1b01114 +b038d8d0c3d265817b5b6ad0d2c0c859aab2116dd18cace3bd1753bcf1f11c2b +21a1a5a745b42c58be1f858a03fa9189e7103d16709c7235258c0f321b0171bf +0a9b4d91aef7343f60d1cf80104db0023f25147126190d93193de9642abf2347 +697618535b49ca49f6dc1fc0f9c27cd050b6f1a749188ba527dcc0f79daf3abf +3941f30a31d014435d99af16004836bd31353d4dc409d44b0cd95ec42db500c9 +f82f9ab6f07f7532376a9bfceabaf2d3295ef409c5b520a0dde07ea9f09c74a4 +8d2abd80b98ba29e644f2ba5d4cabf74962d76f3449009a786930816162275d4 +36efb7e820af49277cac5daa30ccddbffd1f0d028e58b389d31841fb49a0ef2d +8bf42817c13a24b258c04fe4b17ab31b959b41f74632b2d1847fc222aacf935e +2db93b1a77261a00bf1112ea62ccd57d76299330c4209a0a4572d20bda04cbdf +b85e5a4b19e32b05c2615e71a8083228dac6430167899198262d3dfdd4d089d6 +318eebffb60a1f2d4f3b4b71d7c0f49b1ed3d1a1351859d675630d617661cdc7 +78069ec3d936bf8f3ac4ade3b35f848b29e0fb26b8ce7fe0229b43eb268974ef +59aba9a6cf3a379299e8b3297b9c9df1dd089f565ebfb0c38a4e9f679224c944 +9c6fda5e5f573f390de4bd37b764348a5c2c6997411eb2498bab06c52af2587a +912f8c77156986476f786efef0fa17994bc37ceeb90aabdef33c727ad87ba2b4 +f5c313a1d10fd5f220b514b7f51b97f521b7bb316629f752494d3e0fb5f6b748 +b41e7661d3c71ef5180e6457ddef8e5359bb590e34ec2291db6ece5a0b29248c +e63df126c6ef09c5060f310d9dad6edb1da5aec3c7b8c26d5fa3b28e3b432dc6 +cf5609eb082447b0694f9ce0e6392d7116d30048162f566f70368ee80770186f +01bb8f4960e0ea3df5d0315227189de770e620d681547729f92d7c474a58bdd9 +5ef2dff081f54d0be338a664a674d3b6f666a25189b1c104a56ad1cae207da06 +0aec7850848f1da0cbf9bafe5bef824bc391f0427567c6ede423ce54c2b49533 +8f6da4d6836acc2d84a729d8acea8184ead3920970cab92ef4b18da18228e07c +b7ac4505f0643f0b9a13364a15ad89fa560dfba19c105f4b164cfb744a58e661 +cf208474ba7ccc1abef268c0ff906397b01706f49e6bc7883602848a6ecd9195 +c78abcade622f92b96076a99759f79baf7d846eb1696a26bd7355aac9b86cb45 +972dae5d951b98ff74fcf5c1427f071b074c5fe4927784c6ead4d88f1d4cd367 +86ed776db08abea68cbe145663c9345ada875f3bac904f2b995a2e29fd473592 +117faf946f5dfc8645ab792d1c3fab132d9edbe7524d7e4ef4829d3899f6c2c5 +4c9135050176f8730f2f612b5805a25cba6d191e229e4a6dcb99736bde1b2630 +64c641ee7ad134d2f0119388bea082dbb61cde8734ef4ebef4f7e830890ec19d +4041c9df01810d31471beb73667dbc90117d80785ecbde02db0dcbd6468c8b02 +35ce080c7fd68e24963e3773a9b5250f9de2b5e84095c0f16dbfb1129cadc586 +5bd8445439a672c8058555670f2c8fb02012c2a5c2334a0828f1855f8d3693d1 +f55ac39d1057658a1cceb4adf073ccf5c5e06ae3e0f2d50aa5e771dc5289aad1 +563633706ea884cdaae49c4e48665763fd58ae0e7c130a8c917a8f575bf0454d +d2412c3a0d79eca718bc2871a45049b388645e13b53c8b021e843cb7ca2c6735 +c4aad33308e850da39d7df29cf466f1691ad6abce6eabe5f48eb7161a2210956 +f3166611bfd858b6e82cecab053a16436457f72bddb3e9f2c8bf49ba6a829a34 +157d1b609fcd796f34ae1648c7ee506f155ca1a381294b3010f96faec1bbfc04 +68cf3830dd202c4b85dec8590a24380fbf7998617b5024562895c88eae8ddc21 +80a3b1d2aca606900f20643fa1336f27e1803888a0d202f8c3dc0e17742e40a8 +4a2daa2764fa28700be873a43dae964d380b468898f1794aa86d9169bc078188 +1c63a2c0143983becf796b020f4f74bd55afb2e9a96571c3db8da7e353b80f61 +ebb33bb2e63cf0cbfdc531c2d0eee4a1fa2223c6bb5989b1c5021e1d78fa7863 +8f207b3406310260e8fa71eb6c37b0f5dfb0046f0fa5dd20f58853fffb6c384b +b6fc254159cf9d47426e043cc63858b2d16084ee699f3c7c52252c6ee3cc6a91 +48ae94d6aef1040f24538f829200a69fa642d3db89a91550127ae1952618e1bb +550ee63281620855a6f4f07e45e747451dc068df05c7aa6f9a15641aee97a863 +902128b956dd4b424c0a645bf6db468aa081dde5972d055572aac44697eb0d0d +448b1f42bb954d5478a9781cd155f56fb8cfef43bc0566cd1f7a80ba528169e9 +135e6f614a632eb56dcee9f110e40e98be3fba5972e4673009326c99105998dd +6fa6e6bd8e0f62e0feab6a02559cc074ba5a4aea3ad94c15ff967a93b3be0c36 +a9789befa25bd4cc365ca26751b4a452a6092ac8fd5cb71f833823ee7f9cc7b4 +87511813d09fa5cbe7c68208b3aff0d103acfcfbda4497a177a81f53f6c2e84f +76caa79def04cd77e03a34e85823c26b4c9664e3a3ad1861b7ac1d29ea407cc7 +cee87730b32d03aef0997df3242ca5cf24173b15933e6a7d9ebc2e00082cc9a6 +4578199694f851985a929714fbf961a8434c04eacdfe29dd83a3905d94fea050 +3ec012785084c2326c3180374df13e66ec7aa9400de0051fc9101d764fd828c4 +8d321c6a2a506aa31a80701bbf0b9a5a6941e4e77d2d37f1cb60482807df2f77 +a896d545de7eb859ce90732412ffbc7f108bd51740bea2af08eb48ca8a96045b +fcb6e4b6c03175d439406d0ab5d3dd6be364959ffe2dbc4dcfe8828c512625c1 +863ed69568af5896578d2955b86b6b1189a7fa1d2c1cea93bb59d970d7a5947d +0e0185b36ff1cd6b1b783d7b5b2920d599c00dfc35c3a1f443512528bac05716 +c8b36bd964302168c253491410aa127faf165c57f595900bba2e8dfe0b4f50e7 +af1d23198a9a3c385ace40ff8ccc43fb9a8a64a13bf273089557ec31e1389c55 +1fdf812630edb9c3027eef4c7226b5915054fc1f7a4553a83f1510f8cd63b9d4 +e3de0ed6feb732c3c9658188324e8c4bc44e83dff331f62eacff1625d1450a93 +77252a8b862ba626d688a016b1b7a766f3510cd83d047b7e4fc0e1ef0fbeaf31 +948775bef5ce100447d7bb8a5eb3d39d1b17353ee611444d341af17070e67b04 +38b830a54b86f19808e24f618e0686445c271dda7e9ee1aad2f216fdd08b024e +5f6a30ca4c30b90a483e81285936b47c78577c15054f7b4ff05612e55dd43e3c +59b808d35843a27c83e82984fd4ab18d880ed19a67d199442fb46932469a16e2 +7c853ec5b2a3bd0465a65f0ba3fb10d853ee1d5041de10f461de326f505e3148 +4c90ff76dd5f6745aa6f2962d78f54139b2ed7cc470484dbd1d92f38577a9a99 +35c13061ff350ccdd724abdba06a297faa8100cf052c590ddf93439ccc4d8ad7 +c6dd21d739c6e1dda03f577723ce425ae9c534107b51155947510ba8c3a6c90c +1ae9b223ddc025d847dfd6676a0d730851f72df4bbc954eb65134dbfadd3956f +f1e955f5e4dd82c923a57725074ef099d9445b9eda8f07d686a326beb33cc40e +8fa628e743c46c23ada0c906a7680d9e3915420129f8c2833327d62314df57be +dec9bec9a7b348649d6e32ba7ba8dc3d4e5d567b69e4a157a538af5f9ed426c6 +84d24c64931161efa48c908fce398eca888c88c0716fb19235e7d50c14dfb2eb +e37d309e685d49006924b1453438bad74d4e8f5e50195aeeb5ef743ccb761465 +fafa81435392c00e12094f2c4152a3314b11992caf8fcd1342de8a0b3edc9a4a +de57f5732b9256e81bb1c017c08964dc43ce13cd13a9c2bebca0439a4ff5146e +fec0cf9358de65a4ada4ff46666d8289639a74df657ab03d0dd5e34dbe15cef4 +2b1b672699e131d7cfbb5f75310e115ca822e3ba5bc7673946afa462238d16bf +5f1da9ae95469a9cd32c82155455d3c8e5dab4ea1cbd834b02a2a07a2b8a17c4 +09bab72c7dc17f4244be28173ce05e4a7a2cf0689a82793f36597540575404d0 +edcc461017cc8ed9ec002f500eb60db674b29195320054f7242b4b96f0cb8631 +1ef1fea2e672fd3bd38d29ae5d71310aa2a10f89867a9138c1a0a987a991c573 +e4fc1af6c4428108d7522f076adfd5600afa502b30d7885369652b53bf066f76 +ef65814b87343925e38d4cf0a4bb481c314aa73516d1cd9c3d2d46097a8ac663 +622a74f6665515b1def6ee7c71aedefa03db38241398e3645ee8b44320452f15 +8765869f92423bb3cf329115745dc2380937436f8a100027cafd2af2c755f04d +ea02a723a3a344037025a1bd85fce024251451333cae97c57f09438902648011 +6adc0d99e8a7b8a30b8679c494be0a0cac5aa365fa519a1172abda81a7a75890 +535dac01381fd4133f0b093f7d7b5e5080bfa48fc652cb6673d9826979c11c57 +82c57faadbf9a75da7af55ff6efeab340dd6d9f8840359d4296b3aac85c383f6 +58116e0eea078528a6aeb697ef977a2fb28ae2b306b80802404dadce26938fea +5eda09061e832be667f567bb2621ac6ce40cfe794f0e24b2cb937c62cf32c9a8 +277b4f492024c317418a32f60e325915f733befc64d0c3815bafebc3429eac92 +7f24740f98f625893ae753084eed9f3eed17bb77cd88d6a974dbf1799690b87b +8a7201ab39fe37f602a64ff1a263f06e9e1964ddf4eccdae450fc8761edd0334 +4252ef79f118312a576e2d66b4140905a0a2e464fcbda39b6f53857248d52a6e +b00f2da5a5d9b7a1611156e6d2f0bf39d6ae1e931f959ef4d0ff86d80e27acdd +ac59dc2cd2e5e8a2a9b5a26ac885b6db10a6376837cbffa46f20209c182bf1e7 +c84576edc484c19c13c4dc6072e1bb94beef26963444b8da24c977ed2c950c62 +46491b7587b5ac684c78498cf564ac10860cbb1f6dccf6562b16043bd1f25b0b +bb1d5991982c87bf541bbf9deeda682cc1c986a4b1af8dce8a3f28b9570cca1e +f609c45e6b333dba964f076eaa4e8dff311a83f55722cd5b73c026ac6a53abf3 +c33fcebe6829218090e425cf1281a1098240cb3a8007b84e09866d17def4c827 +ed60e3ffb8ac5b1fc70acba1a577f1c388ec52269910a72ee85f435f73de3ad7 +1625126ff8ec0b54a324a733bef4d702397270ea42bed7b06307074a356e3b99 +d3f130d622ad8c7c4477a3e0091810c4f38bdbfd3480ce59db0bb92559a1a84d +ee9a0706811114bb3edc999211da0dbf26cc8946024b9b4de9b7d0404c1b5bb0 +fb6caef2ba7a8c9c1a31486c03eae6d98eea5962a9277c7cf1c54f7553f1cab1 +481ebad43e9d6ffb3511c55b39a375f2157f56ea31a74c70a59b52a723475825 +296f726f9e86151120a954c294d39ec26089edbce9a7bb75a0955ad3e5b2ad6a +b4260a25e5080bd4520b6e5f2d22e88f858549259739a83d573cee0addfaa79a +2dfe02e7c1e93198ec10d464f90ab70e3dc75180d9aa2c3d0bd6b6014c5ce075 +fa015e5108b7e08c899ecb1c99cd72e17f6b31c8147f486eab546b0839cf2e7c +d3e3b4c23ae1721203ab6ee6f43e55878307a746b262a5ff64bea6ce12e1e350 +e9516b95b7edb95576d30bebb42661556ecaa0336925ed15b91d77090207c58b +349b8177aba733fedb1f94020dbaecb824785b2e66cc5a12c94f1ba5cd3726b0 +f3c1eab0afb075f03abb31eeb7c166af21c1a74c2ee75aa3a7e4a5ffbb4939a5 +f2019f53ecf527d6488cb0c3446bee4bc6364de10af7f939e5c04eadde61d9e1 +14c686a830b222f85b17a99377ded182ec37365ace8b7028f460b770f88f9a3e +883558d55d2174eecbdf48a27c4398d75e5995f13b68d8ba1fa9115dbafcbf91 +a7645c38825ddebda44e96615f654d0a39789bbda8c076b8c7e76153330806ee +a89ad133190c2e5d154155f83b2ceff890c549307ca20f587873ba14d59dbdeb +d6cbf9bd5d799f1d58d3018d9e4b65d5722ad38234ca54ccd83e10fdb33b8b2a +479db24f31cf06fb035c9d0977f524a79c7aab7e81e63f874495adc346c73cd3 +a83e8f8a17116cb25a01cf229d453756ce021a6992e839630b06126ccfcbcc6d +691e6d409872a2eba49d10cce7da3d0b3a9b8c633162b6c87a4f8949f6e9fb0a +396d8a1a95ac753aa963948faa6fc8b80335f6a3e229b85dc58b05401ecb4129 +1de6690a0913f4dc678b41e07099fa68a069d2fad54c882f241c634a9fee7392 +e8a94f81e934ad134843f0d120f6ce7b7f8fa20a17965302d45c4d76a8a1c509 +246ab3c77b02b8401d813034e0cc6c6b11e7a45137fb5091ca5c07d170b90149 +4362d957354b644a7a4ac3920b40c3702e76072cd89f3e79f53cfcd0f24b1ef0 +a84d7471a23824e4f4a6f1d6dc7ebee46047a95e5b254579da1bf2199b2fe334 +030dee09f9450f8ee20a36356e5cfe6c187da88eb9d98fbca5a3bac575adbf68 +f7deaa3f308c0a4dd5c235d4fce9c75221a5a8d2b85650c1319e996f0e446153 +e2d53a85f47e8db41b703b41aed5b5ffdd7e67a2b633b052851b6382485431b2 +78a9a635ba4a57d1f46b9a751531dfed7710c429f4c6f6bd772a0ca9d87c2071 +cd0c3a99b0fcd93195f722b1d6ff45edd1150e2bf34922c83048c0becb62dcd5 +e9c7ee879701d354d165a5612d52b33a6eafb8f397b3fc5160d2c56aea5a43cd +1549275fcf3a484ec085cc6adc3c03cd44a5946536d84cc756e6926cdd8cb13e +902af575d72530d2d19148b08a1481b88bcd81ede06afa03a5193cb2ae2e4a04 +b500b9e7239b6b8f1f880729cbcc783f4f7a3fb38f09aabf39cfd1206b5be385 +79ac7a4b2123e51c7bfe243527227a779b3d91fdebce4d5394849540c2fd99ed +98ff068c3fc5e0d81b3bff8729f66ed3fcb83a666320a128926f5bde21463f25 +3d819ab6b0366cb104ffa8a088fc1abc72ccca0b176a955909709742996dd166 +c6d76a28b9ca9f2920d440a945f363453029033fe6575c8aa848c3c63bb0dbb3 +802a67e100c820d08c8078064d97da977224721884ccd78bbb13ba739f3a73c8 +1d62edbca9247eb902005b0822e0bce20ef55b9adc1bcc1ebbd9a6a41bc97a0b +380b5549ae58270bba5d48e816aaad13b8a8abcc6a601a28f643081946af02c5 +6ca95136d704321a08ac09be9e6e44edfc735d99d05d22bb9cf817075f404873 +d7ba5b9ae721cf0bae250dca9849af75f67442982b10a809985c8f07b621081c +d537864be2bd4294af130b1151b5fbfcb109bd036e2c9463476c9004ed4de3a9 +64a1758c271646186999411f03fb8f90b0cf8fba0c57d61990d9e1ddab8357c0 +182e69323818ae63a9165619620bf88a6ffa98f300a5840e25382aac7e76fa49 +4fb7b5c4dc04123445f679e475037307b4db5866e8e88789f9fa723ebada6cf2 +19541d474bb9c49cb4a6197a6a4f054d7afdc627eec359f716a4419ce35c04f2 +e2c5e0af8ef0b546566d2f44b035d9d0dea87ae6ed093779af0727efc97d5287 +77a60922b319039de3c31bbeef033ac366a4616d7e7ac8558f4717c66ecc950c +096f04f2568956eca50588a8935b98fe440a71aea4b35697b2c5d26ec89a948f +887465cc870c093e6d604ed2025b99e502874ea32a9fc2f8f560e508d74eedc7 +cf140a6886fc51fa77c8e373e14078396d5a6b2f75f63e88923dc593dbe7cce6 +b1d29834e0d6215aebea3633c7b0d221792eb91b7bdda979aefd56eabeaa7278 +fa302257f8f1464416ddf56bff037cbe0a63c55fbe09d62c739fc271b78cb2d7 +65492e3dab5bd772c105a93a321c35cd3e1ad88b95c7643253a07afe5ba9bfca +3d7872f06e27fd22999cb7f33f03e7c60f2a4e03bac4a145b483a80150096b79 +d91f0097a62e920e6664614c85b486dcd56bbd503bc4fc182dc13ec0276190a9 +b384342bd37c9e0d8d3513d634c77797f74ff945f59d659789fad05e79eeff7d +5f9bd77d4c2dc9c71c484e15f12a177e3d196f50a2b8467d6500e638c299b1ae +967a4d9e9162d0ee0b040c511e50eafacb688f426b7a0e3a18670821db36375e +88c4234bd20a700c8e428bdad943eb8246961c8b0d666832f828afe6a8d3456c +53591d9024e63bcab6bfd714c799628beb84f376f971446af59b95d933dad3e9 +09cd00ec3f66b72b81bebf37e6d12cf60fa5838501a9833afffe09ec63c81dbc +ab0102543bc9d2dfb424cef24052b15952f08f77f419c1e381e748b43fb2dc71 +f0ff0ff424a350f22ef005528b58e477f3931b754564bce31cef2f9343245906 +bc7ac8dec19ed3b7577bf42defdb70243e27652684cf2b9d5515e82cd958c9d6 +d4320486e471d0f68db80847a5172b89803822c6ee7f9a775815b87e634001f2 +64f66891eef2fffd3930d5c7f6913d74875f35f6cdb47aa9e79690b7297514b5 +680958bd9af04a64ea6657694e82af8640273591f79b8ad4799beb9abd32f80a +4726526372b4e9b8fdfae0db062d19202c6796ed98cefaa897c2666292e25ccb +1792e42f9397f58c7b9d5adc228d6b97678723480b1db418e88dd7e6a297a675 +137ee4eef3b0a20c1458562aa1e8d1f7ca15738344bb9c35b653246ccd47d564 +7dac25ebc965092b09906782940995ccd9c2842e3409f215ba1d4815ba254862 +021f333b3c46eb0118c45c4821eb6c81bb2a19b1c6e2d916148765c0e1f33d34 +4a5e833b67c81f620a41b0e647a298e125532fc8fb0f4202a87fc31e6f8be0c4 +92f8b91311d887915e5326c8fbd2a6bcffae0bd45f21c60746cda46c9b4390da +e9a82911abbb7320a479f790a88420baf34994c6865e3eccb6a0b3304d12dd76 +585d29071473ca8c726633035b5c7be49212f377408a4658e7dcb45a2ab55dd6 +76cbb59112c585bf9c4dde0441badcda6ff9e0e6d00ac818b3c98fb782649b5c +8f0e65ec26e7133b2db3258a6971392b21eacf1ef5fc73077b1bab87d599954c +eeaa2ec60a3021035c222caf916de01e09695425fcb9c651552e318fbf64e8ec +ea288f68682d502c8676c3062889ae5c89bddfc18008079750168591e1b83d29 +65c7e628c1952a9c4d8cbf9a9b3fffe470c69df2bb152855724513051791dc59 +8bf4c9026c65cf942007085e853f30dd66790701c073855f1aaecaff7f3e9e99 +7ff584319d5d75ae8816e04e4f5c150e08a1cc68e87f8bd9c6f1824b04fe9499 +a61676ec46dbd448c1b694eed6973c7ccb1a9a56a1aad011d02921dc0a3c1b5c +123f3271d4f519754fe8d85dffb23bf551a54b73f7855452fd515c71bc61ec4d +bceee9e5aced96e6309182463289781abd4421dd250d970b0650c7491a3df14e +8e70e9ececf4182ccb1b56fd93fad614a29a50cf651c74da437ed5149b0b2b3c +c66296039cad03792b7d0fa75b40053b31a0c7de8f63d8e5cc91293ef393bba5 +38a23c1105031bfcddd026b9aaea9b59506b763fac59be63421c37d58c0a51ee +56e22d8464dbce432ae8f773a0a90c5ca0f49585b82ef8b665ef2bfc7f171dd0 +b11d2d28f9c5ac1806ffafcf990f60c0dbafb2e747ad845606acdbdac8b6c8d4 +61b8fd58a87dcceb95de6f99054fb98bd996255e27c4bfa610a9fe6362b6f5ee +d140ccca12f2ae113a55cb814a7bc17c408c620f67b80bb7a6e38b8f0e1ecfc7 +42f473e9452d1aeaf91a49faff60bbac17c6c3371fda2b27d48287c26b0abbe7 +01f4860c25137e611fd7b29b4b2da4ac2d552e928d2a4bf058b11498fee19430 +b0fc778d1213f083fb083d24f99c17bd6cf6071a12ee184c53143d3e17321697 +2e9f99ad14f066e010c410858c186fd564e3beacf55c7cae12237e12ae4c7705 +aa8b88a3c04ab555c6fef17d294d5f6f32ef360ad5e5a76a87be5b2beb4b892a +246113cccfc7974667f2f4b666afe19e574bb9ea9625776c8eb746ca3d3b50e0 +8a0dbe29f1e169de31ca00ec092511fe30ca6c04011fda19d2abbf9f8bbcdfcf +4954b3e330cc6c1f629fab049eddc7bf2edbfab83c2d9918332e3dbf0cd93d92 +0231c3a85b5d44fd1aefd272256b697972aab105d7f58929afb20faca2481bfd +695a920b8b980181da9317c76d47464cc23bb4ed3e404d4c6d9073710167dcab +f0edd64db7261473cf8cc655323a4ae8500fdf9d2dcec5e7afdea808199848ec +62f5a115421e41073899b2bc4f8637d0e5fa1e91cea94ac4285a7095f675c440 +421bad69e58b1fc0dcaf4bd02f65dc4204339d11333ac1a1dae46a95ad8a2427 +df48b2a05750714b0adc7c812014a7861889cc820665f57550aad037724b87bd +9d6153e439f4e89af6413eceb869d1b7fc9bc66bfc0a33134c344af83b7d504f +28eb0b0a99bcaeeabbe0a7fde5130d6ea92bdf55776e440a394de22b1964ae28 +1ad2cfc8922dd5d952885c1a6d0c704d99f999f31c23b24f5812b3d131c03374 +646a251f1c2cd28255e444f871d759f23b3874cb32c0bded36b6baf6480a806f +d17a6c782444d42e7d79cd98e9ff2b35c7c567e05c2dcff0617aa332a4dbd768 +bfffdc891febe75b40b816e03539bde90ce221b336d134d141328e7a5f62bbd2 +660734e8d801dcd4f68be785e5b03c1258c2e3e6e935be0cc55525a43c9b0eac +5c4a5529531c83ab5192c03846e2391f6bcdd2fd3c554a471089416a49dd8b7b +58b9e8c6ab833667e8c415dfb509671f3c800c665c377394b54fd35c873de735 +e053cccbffcd6694de73f7b7d92c9b4558a9af6fbe4db94c27d7b25ddc291106 +0d14d0560434a3989e219721e8bf7c41ca8ad9559b8e946f87a6b65a4f372d25 +0a6c36069f76ecb170b0f376f287acd86f0a95d1f1fa37635e4b0ef47489f4ec +bc6f6f63ed1ec5e7a64cc59cef0304f05832d4d75b23fe895cb3cc0624bd7fe1 +e495da2503398e62bf7073ec19aee7fb11b3809b8dd130bbc14530c8c13b6a73 +2e8a8ea8a67f2581a0d501d7e5f8432e63020a7761de4df08f409ece7274f070 +651905088d0c12e950baa2147f95459e209464b46dc98f86f9d6fe83f21270ab +b24b8d7ce8d6932e4f5064fc26cafb92bc18ec63148b71f84c3808b05d7797f6 +8a2c2c7d77993b2ee4eb14ddeb13b634c5af7bb15fb93c061c6c735866438327 +2422e457351a7d15dc3365ea38655c6735e26539bfb141ee520a14da7c0c1998 +4214743dcb56868df139f5edab3ebf16c9215b79a9ed548e53d00c888a8b5178 +d8af4ee8f4010e664b90bd72f84f051517bfa1698f9c8e870be40bc600725e58 +6810a5a856d049d0d85953fb18c6ef9c163c4445a64a79ad87f4aeaa43429cd0 +412817eeb0aa034f1cf19673914121526bde5574c1531c0b753ca9d520997a3a +8298151fddb9e4977b3e6983e56846a92ddbd95dd693abd5121f00c035eda2e6 +b2ec1d0b77551a276a675eb1d757f30938419f687bceed74f1dcac5e4414e5de +73fdee712c1728f4c94a91bac38d54039d0a0e4c26d8e5f70fb4b76eaeb3f286 +12d399d0c9cd65bd2d2a663ad8bae773f207c538b6a39e65108e5a5585ad1233 +78954f8478a15c6da23db4a3715ededf1ed40d35021ad7e478c8bb6490dab278 +806fe9e23e2c99c9d4233176135a969dc6c74b34d144d6f9d65b54edf57252ca +d365d0bb2683df7d105b6669145ddb25608f2956005668896864057ed4c089fe +49adf24b51c8b8432edbe63ebbadbe9e7cd2663c37de30b7ca8531b30a0e2ed4 +18087fe61192b3dceb209038ad440e0ae058c9d77889d72037ac683ab87e3a22 +4989bfdd6fd099106c2a7dc9dc4543a250806500b9b0272acc38b48e595a72b4 +b89c05e5d1615072c62d9ce8547acbd85ef853c696313c58bb89751b509472c7 +24fd5b6a64426f03a0d6404a23d19224740355e3a7cad701bd7619863c3d3b0c +05cf01410f013a3cf7718bad01ade679637ce0770254839db1290f2eaedf7353 +6454d68e5fe34446abbab4c294266bc0c248a063763c974797fe78b17d0250dc +7c25893a2c598534fd0a0a84c7c519eef24816048015c621d8e2d715914e27b3 +738fd34add53b3034f7c267ea7c566e82f259425812eed5f5e19c74ae859b44f +11677f04fd177dc3b56e3c37df5226c13eeb361531f347f980920663b2a31ce0 +2a69875d895280737798b2e34aa90bd4c2c914f075b68829635a9436d95afb09 +f4c18ccc87077fa1eb9eb6512ea0ff0c365bd470be78c0f39b47fe2e9e9eca7a +2352a31d9dc7d7ada3dbc1b841677b24b5ffb647c9fe83f00acbb1c0220d5330 +31af740809ebb7c3df9d894cc0a97b9bb5e2a8eb6d16b5875da5dc4517c09195 +524e860e5f5bda35bfb1a9e8e24c3bb8f84869d8f6577c1eb8fbf38e667f2c85 +e1a8561c766289beecb229a470c63f74d49230724c037fad4e51a0992603dabd +f1fe20adb4995df3154e5829aca9d2af59a06a063ceef580628ab18ca450c2fd +16b3cde6e911c06583c7c55e7e74190d760a3792e6e848bd9bff6852a41a932b +4e8949935133b6acfeab815439d4f8b1619258eec4c802d9d7214681acd269e6 +ff3e07f29e53800831df42ba776a83afd9b8c139dc4d0d1430ce0c95f77734c1 +fb8af40687e8060399c1efb7ea2cbc86f74cc7fdb7e952b0dabdd4d1fc7c589f +38e2e693bd34541e8d9e1338a3fef82bb9ed41ee69e4e9ee46c0daa3330ffb34 +0d406c20c7bd8a8177e9b206f066db9fc48bdc27c8d5d245e718fdd3248b26c1 +0c9fabc3365ccc3389d422207cd8fe815fc8f60b1d436590a5b57a60c075a953 +7300a096c905b8a43d2b4dce99b4413efe51195d76fb1622433a60f6480dc7a1 +6835a5491c28aa0afb49893cf0350ead65d68c17f9aff599d5f8b43391904175 +6fb368e0e8be0991a245011006adf7bbaf7fa00a46431bc1a37c2dde3fa61c0c +8175282ec68c9f8b9698d204ca4665cf85f28d41f728d8613f05d20b2b228bcc +bc453bb9e294f0ce352b59365535efc50187e0f6bc044a42739c9ea7ddb02300 +9201aaaffde1b4b4169acb5ce731276ae7fac57e35fd57e249f64b2c0ee28cd6 +33afc7351c42ef0a5631273459d5234a03256c9bd74a77f8142c6afe1a1b766b +d6d100aa589e76980fc0ecae323abc9adc7a69d257a7c9fa08a043ee27dcb7e5 +721a5d20fbd1b5cdae1ae9cd323bc155c118373521cba2af1af55655a134826b +4c8e13607360d88d927e971934d8622e7ff8d46bcc91ef6dbced5666af5116f4 +606942560cf49360b490ca6ffe6a210c9be50e3cd0c016ed623ad7de42d334c9 +64685c1388bab75319e7ec3b374f455746ff38f9963b085a307e6bd6c9e310a8 +8bb74a86e128effed21fd046b4999e473d296bad69ece297dd911729061a46c6 +e57de988783f8519609ff80e10e71bc3dd8efa15df736a8d7bf5d8886f283850 +9dac12ec060cb9cedf9bd08375d0ccfcdaf12cb9a695f3b6fa8f39763fadbd1d +3ddd253f5a62c36c85f70fa334c204cef99bd0d528c62ba20ed315ffa14e0927 +b3499b70e6b2bbe1a0e2ed3740758516c2c379611acb6eb67bdf721ff4ec1fb9 +01f5dcb20b9c83107c57ff2c3fe9539fd0139437324e485068c58e33d20bc091 +81989b0faa54bbc9f1504a009a5d9baa4661df863b69803bbe1d24d5a5ff2bfa +725a3e1e3a0dceab2f641248a5b49d6db84d32e6af058a5cae68f40c9052e2e6 +87c0bbcd5e2451795ca1c37869125c8eb2fb59db8aca4b24c7d520bfce6ed01f +f4efbd6bc3a9e397e89abce93e00c3cb0425405f59a0b75561823e355d7c718d +09c2f6f40303b98c575a17158d7cd3cf7bcf544e264085f1ce58320a3f222eb5 +ec468e97cb9be869eab7c1039babb5b811c25b00943207e7c7df0e09cab7ecd5 +c4e4e6f17b9edbb4ce5071f00c57290e1538c45ebd540f8629e45c3ccfa79a54 +91e23e4a3baaa366a119456dee726240cfa7cdf6d52f754111ece87bfe3790da +6c8de4ed0ae13be32b600311f6d8e718d99b9c8ef282d24ac767e0aa99ef431b +32f6c30d6fcd3adda5d09068cd6320ae052e704702af30303064e22b18fa07ee +27e8da9ee58659320e0d51d21d3f8dc2938f05f6568533d3373f560f50aa801c +ea8d2abf80d746aba726d9f688456efde22522556e05636f391f345992027f7f +51fb8467d972f893d22cf36a94b42c1a7383682686987028ebb5d3bdcb2c776a +ad24e87058fa2608fc8f2ce042c06c13879e9598a9e041ee4e65d523f0ce6513 +2aa90b98bcebb464b0d44837af74457fd11a68e9739744e990b32968ba767892 +75060d7d07d84224b29a9beae2ac6a6494fa9d6f8a9ac52d3c48eb3f860571eb +b056f4a11955b66cbe1a6f5ec2bc6ad92049c6464fdc1e4f46ef3ea2ccef7a0b +4d836bdb1b63adf417ccd1dc9f8cfdf86c2b8da53e107c0bd79261b30b0e325e +f56a6bee589b4de951d96e51592c8ad0094d7f825057b387a07317ac832ac661 +b9d28b154662a1a3a83f347d3b4d087156545f6270f79aea77b580edd12bae8c +15c27ca20fa54172893a923839055cffc0014ab01d9107f6a2416b9df9ecc2af +7a0a68dfae8df3bfc0b8add67d425800039dfa7e3e534a36d863b243141b3542 +6c16ced8392b58afd4b1e185550258b97c4982661a66890c0b20be04bcac423f +17c1f490af78b9dc1b1ed398b168717ca58f5d43f88e00f9db301404bd210daf +658ead7a915ccb0e28452b18490751dbbd453add5ccbb9c71a27a9a79a30ba93 +104183be3622c590b5a2ca5bd92ee65b1666e3412cd169d385bcd3ecb7121f25 +35c3014678273fa41c7890983141361093ca4b62350446afd179ce8e1147a87d +012e8958bf39f323a4e9e9a1b51539b38b743f6f0e1aa0117cb3d5027c5d0a91 +8008d9138ca7f781ba27eaa72e2e7fd7d218063de98e50830af619c607efdbea +4e20b13d603f28d12497e73e3eaf4ce1f5851aa343606adb377940ab631f25fd +a65bdbada3c2214935cb8ba70030e734d99f190914b3cc6ee403a848d47f7b8f +5063f1b967b1859bcd18211ba241b61aa9167609276623a0d8ccacc464f375d6 +480f72877105c53f2f3f1e7b56d52d00435f98815d85355dee6d39f6a6a04a64 +a67d306db80952d995eb1055d9300292ec432cb54a9d8a71c898970bc57e1a42 +da7b608974eb08378110c74a71f6e40afbca88f838db1a011d551e37d05109ef +a138a0c7d3cf0ad428e7c012fd41eea9cc4c30be73ec636326bd9eea1620bd9e +6547c92b8d44e9668034b8f1baeb12d621bdb4f0f5c78f3e2da778b995ecc09a +6fffa46207515e56215ef88616d41fdfa97a7d9e88f7aad28a0de2dd26283d17 +4c95e7cf0b172e0569cf3e1fa71041ad8605befd82c1192bc4863f017ba6211e +4984c94bfbfa7fa43d53865b781677ab06c8623d1fc812dc789b3ee550a1365e +124a214333bd7f4769cbe78047574dbea8e7681ab7d8d8bc582ec6b8c6eec36e +65fdca8ca2397f60031fb37fb502ec1647fcbf4f5bb48e3e16adb3d06aad6a3c +c9491ad499fa3bd3f980c3c174b8a2b9b59bea09a3f7e134d796521c7d8d5293 +804f94b6b9f18b9a2dcf0d5d728669906799b3ec681b48c7d207cbf80f3182da +3a99ce2499e5ba6299bfa019bbfa14c764604da291492b733a883413ebe8616e +cb9706e98849d99588e0aab1bce3831d7beb19cb4ba5dda76774649e51a610c3 +f6138f2a742be7617978ac8e438ecf2a3e4bc484a4d5d0b4e92c7fcea8354c46 +826f11947dbe237c8ce9eaeaaeb6ee77291ecec2cea5861e024791bd012e4624 +5d49ea5a9525941954e596cc89def50b0fdaed94d99b88e01bc964ddaeaa839d +bfed7f110c0ee55c7caf4bcb3b59990bd86b05e068f5ef93efee0c291647378a +eb12d0f47166cab4b0985bfb6de6e80330b390987d19fa40a09366dc3231b751 +208cd5173f09aabc24002c5c5e777c4880d8c0a35453afdbd6bfca37db6f91e2 +362dda0019691fcb814695cd7461558ee3e6d875a1c95569108edf436f2c9541 +a5afaaa0562b0d59cdf112252512dde062abb61f6d7e1bd8d368e04e362c2ae6 +84f44408e257c052de0e2ac3024c7775b8e5e5fc4c452b0a313925b58d73ebc0 +7d234fb91f5c7496141e43c5983f084b7e351100c3b8988740bbd2cfa94a73bf +71febaba001abd0ffe9b7a349f096128abf057ca59d70bb952e8c0f390c87a81 +80563252307984f4d7831cf74b15cf39bd442bbbb3a1b4cee1022dedec6e0c6c +be9999b21782523b4a090935c00ded80f814e0b0029b768ec533c36638a7fa54 +893539a5d9b6167f5f3d10a0cda51d3b702f741dbdb5590ff527c4bea45d48e0 +47080b5c32768115fb3208910abf6cd7bc02c12a5698c7ca193e6eb879ecc701 +48bde12aa3832a46029a726a0879ec50f916084ac6a412032a574437a808a593 +c8023e26a0c2392a21c591490917647d9fe2bcdf31484dc37358018a636694a0 +7bb6d91cbec52fb725bcad7432346b12ef1b75fbba96d7542bc7f5c2b25c15e4 +d7ff0ad3fd11d1076f4b16520fde36ff086f7d5b72f784fcf2826ff0f1365797 +2ee415d80520beaf869b1f4ed2a14f69b5bb0a432e577d3beaac07839f410755 +bd6c0f60918914ceb0ec606e7fc400348e9e0fa0dadb6a515a1274655c3c4b53 +c28a75de2fadf99afe389a776e649a600b153923c07e0fbfbfa0a10fd14ac5d8 +52975f21b77af8427b2853853701acfd624610f4eaf83f0e4ac46efeab274406 +c28d0a80cce460ad30050ff664a6b321484ed80c51168df12d6d152c1ef6e756 +9ca7c0b37cd56312dfb1e047622c297ea31ab43dfe10a7ea611debad30656fb7 +7106f499c72ebeac773f43cd9d3b7eb76946352ccfcd6c0b1e4aaf6ea32af4e8 +04556819f5dc267a06de88a8706138cef601ee2a1053b8cf1656fb3fb8771fd2 +05d0c027263ff54bb194ab06f2f9c948f1f6123665014f8cb05c44666c55b07f +b57d33f9f3dc939846c2dfee063759021c3903bf813fd21fd71229ab10878a0b +0efaa1efd9552b37b8a8e8e1b5df85494ae3618cfaccaffd80094ed7850e85ea +485c9904a0c6c93ad2d03f0f927da0d23c55b1086c44a450198fa26608d6b4fb +04e9f388eb8f1862450f320a283065d7de10f46f6d5630c8d3ae1fb5fad45c5e +dd903e25c762c4ad1abb09a627df4ebe0b79accc5a205a44092a7f1b6c7cc92c +0b17602371847da1dd23e3e915814b8453b694f21639db69b4b213fa67593d13 +932ad5dcb732fb3c52dff150b8f0ceb487506b5c4a817573375f621ee00c7201 +1fc86600383ff364abf402363cbf9c6bc6a8887e2109b22bdcaa5324d3bbbb6c +bf883e465b90f9b44681d24bc03f72adf4a6b8ac9aa33b2d5ec6f7cb38b339a9 +43d72ae5ad87990aa2bb6fa2d87102bff4018f2ca650408e63562bc43084a143 +0c64df2f0d2988f927a4e33abe8859823366f63124d47fa2dcb01513bbbebde1 +ccd484bdf8cc0703d14f33c2bfa3d8bc6b68c35047332b02a719b7f39897c260 +f4a5ec853e92fe97ea9d9cd601bc53e3a53410f3524feb2d785174a0c6c3a837 +0afe09ddbda12b8fdfdd4e89f032a59f4419a70d7050fb00d14a672ac120dfcf +23888200e1f4fca7fbad8cbfc3b70e5448c0f14643c9ff3517606b3746a99963 +b6adc59206316e9f808d1f8f308ce2e0bd42ae6247c469d5567342b6c079d63d +3661734cc17e6d0cbc698013ce7268eae7068622e4c297f5ed415327345c0295 +cff24aa30fa2072e389069f5ebe42ed82dd56ef9396f11537de086be59305947 +1f39309402a3a0e71da896861c057cda08b24628f32d479dbff2717fc9a1f93f +77b57d6b5c5306f2615740cbc35ed67115532a4da296ed70e6e1be1d007a4631 +136481d860cbddd442db2aed32c3f584f7a1a904c276c3ad121b6902b3e8014e +1048829e7bf222ea38f678023cb96ab3f4aa0f0d1647ef53986b88785d22c406 +05481a658d618d7e8e360b1f409988521c549df8cc4bc0502f38bc2fd2084e6c +43bd0daba204091534daa7e611f589ef78e181660fe3820883d5eee35108703e +e79eb1acef8e8c11c63e03770b23f63c2021830f25afad20c3c2175caddf34c2 +4e53f9871854e77998fe7a03a1331e50582e3b4ff52b679b8534c3b718e82390 +7d05175046a5ba898ce55526a4c85b9a3bf45bae3c66a3a03d470c0b3048c947 +3c5c31369b5f37b778fd4482842978540590e341150eeab3a090cfa8d23acd0a +5d1eb9456dfdf19562864ff40494b506e3d2d32dc991de637c21c5ebf3318e70 +cbb09c4cb82f52c65de4ecd2531a15e3e41a836240e4579c442d4d7a823bb5a8 +123ac039bc668e9fa62a38510674f3125289b94795608a16c504aae33de2a358 +b689f4416ea0032f869e24e2e79c603096382ca5afd27574f108887fa7bc1315 +39a1575599586bff2f0e2325216d0b7c9d0d21c5c90b40f023b2ac2c05afd63d +f32c01149d3aea9380cb5d9cc0feb0c91aedebbb5e76c08b1046c387495b0fa4 +91d8d1cde73f726f7ce63756004d44bdd77a14e24ced99a51b0505d7e9c1c04f +fc19052a162b4adeb22778e0bf441cc649564cdd4f6085548adc8d12fd8b3f92 +1475f4485b9453d7c4aef9230d42497f4a46bdbbdf2d4c3b98b317efe4a6675c +cf703f7737c42902c397d2ed03028ca5e241a5959b431daa27281bfe41478216 +60e22b4b9291acce9846886720f610630e7f3cc78ac4bf62734f79349515d386 +cba6f5d3c1e326bfede2544dd78722f450504ecd87ebcf6adfd5ed27f92b2fb4 +aa82592f1edefac2a2c49e2403475e3559cf385a99e8e33e29e9332a6a9dd047 +d2759aa2f044401175a1636495fe87986c33a9d75a567ca4f16c86d1c72798b6 +ab290ad23d1cab9ba6db5b11927e76298e8c905910ee05ba7fe37580d950f007 +f2e422e30815f4acbabc0b6e61da645d942d32785efc646c0fa673a332db4d2e +e1091a8f55ea44c36e20245b551a297a0d3d497f609d5da88c7e4c95345ff0d3 +a8089a39877d7557a40ea1283c78dc589a5aa12918f633abb11fc14cb6897c8d +9b61f5ed7c7439ab74b722c2c655834e9bce9d6953c0efb93f3f966f6f7b0867 +9e25102b795e6e196e639da785ae1d65ec8e380ec79895446fb1e78aa86755ad +ac648d33c2b396e67c9b934ee6c16ac5c8b31490f6e507ee92c68f52c5d85b80 +63a23769386c324b8b5e2f38157dd693d3e1f0c5ba13eab00d6ab7053e4003db +942f700e249f183f1ac3477d7186dfc3dd54ce0bbc82b1f76e1eaf9077bf0d48 +28eee89046f9426a52c9e896e4bef7266235d28f9173c7dd6f04e221a4c664fd +69ad44c9af1c286b597fabdb5e16f9ef2b90bb07e53688cdb2c5d247adbf7d08 +2224d5893873547fc06cc75bc37aeb6c976210942f9b3a01f70e8a2455506943 +1adac8a34e0076eb7545905d64afffe3e72790aca77e39e90b88f18c44c57129 +70a32b47e1edc7ca337008999402d19fe6e19f00f0e087a09f86b748a86cf32b +0731d4dc042af5a02e5d127eb7c5d8e148094d1dbd9cbb60ea32f3713a6f57a0 +2082d1a8b34d756b2b02ffba234b2a54212c0ba70056c4af7633b453f1def81d +cb94a82ce48c9f97f2273bf4b59939f9d369c4f9d8ae9c527d7dba97bf81a549 +123c1252dbb371d5f5a7ce9858abfc53897945d95fe22049eda73ead25265374 +7fb79264f1cb075dff3eb08f85a3af9b0d7a9026ada0887e0f91cdab99ab72cc +5c0b55d9c84cd054016f8d3626ba0efdf864f1b80e9ed5d01f3ffb6fc78fbddb +9aa8a28f7524da27968cad9851bd3e568976236116a03d812672592cbc245f22 +603d061626a861ad0953260939e75a6a3cd0fa201287f3c11f03c3029b4628c6 +a94c6afb2dcd9fa1f80df3e4a2016281658e1ef929fa6657ebeafd25c446d44f +7b4e1af7be59ca4b4fdaf8a53b926ca0563e895fab0cb3add0cebf0b5bc99bfa +f1c2bd81ceaf0bc13bdef9e31b733ed6784e3fcd5d1cf8ad32d622f2832021cb +da97fce78e7456b92102556ff00dfd5fc3155f9244014870ec9a712e974b7931 +dfbf759bc98cf3bf7984af4a8fa5cee0e145974e2e2b27b129d993de1464eced +8f914a598332c57a0e2e2d67f481a1f87f8801e1c8da16c0ac421073621d8ef6 +296b6dd1aa05c3af79e5563c075a61059871128ab22183cf7736989e2b2d3c07 +5720c1a74fa6856ee4d15d31d55cfb438804d9ff866689b08f5b80f2575d670d +fdc15aefbd7aef85b146d445086a867a6b76108e0159b2f8fd0ba436f987c64b +69a74954601d83b4e00e29ecc2b1204fce6a0084b23c8e5b11ed32501c4e5b81 +48ea3163b0b778614002e081ce1e9f0f298cf0c13f3bed7e199b61fbb08ab162 +34a85d14e811d6d221f5485f23e7bc19765496a32d505eaa6461934638146410 +cafb403d11825e6cb4f532ba170fae2d521ea3105db2163aa0401fbba4fc8955 +a9beb53e64a04679dfa3c9aec5d82bea640f0cba5a82bf7794411bae377a0ede +83da52d851c820859edd906909c9f3021ac0aafe4fedb16361fba42b0843006c +7445c1ccc85675d7a50a9b2eaf80a4869b60b6b993249b657bb8e0dfe536dcd0 +86a78abd77688896c4c29e8b7c5d1af3007a36fdc1cd3b70c113bf7660772ca0 +fa00c682e2567d377df1ef6db30154f5da3892bb4b512a0d053bf4548e52e437 +858fc88cfebd47dbda6cb35986156a5edff8cd0ead579603dda8513d1e27fbb2 +990c20e7f0e2337d583c74d21316ebace4074bcb154954508c5c25e0730d928d +5c65799b83d508c23175cf090bc4520627c768d861d522dd2176cbf7fbae41e9 +4b0623c1263c960dff1868d057296675b44dcc7a5f02dd3d8f559fb8e5b65a8f +f9607bac681c649ae74229b7bdacfb5e1b9b11df965cb66a5991178266917c35 +a5f969ce489bea89576bd58dd342c232f7f2b08cd03ec2b35758f18aa4b73801 +8109ce5bbc8ad235c7b5e0f447510eacf9eb9daeb5a2ad489487c8e7b0ef3ac7 +67908a80ad793ac6543db4bab4f1dc6121d4b16d31aac0cc074d945117a6f1fb +e5dbad2222cbf3a4f355ce2f8f1a570d0919679aa3996c5ac783c242857720cf +f052ce3ce78c2080617b9be5c9a5cca1f959a0ba3b594aefca48fb1f439e06a9 +063b58deec0e7ca5a3a40221768dbe5c35bcd5f7e175c7403666d2065233b711 +7f86510648e6e448de1f099c926d2d9b9bf1ae8c4ae7ef828cb3df1e75e63c62 +8a62fe27f01b538cb63e965becc0c3aa84eb3c529019859477045a52c3dd5c8c +31803f1016b8bbf26fcf063f607f7d6c19d851558d6b3c812f608875d341d18b +8c39c82af2a495210542efbd37a69c15fd9c03a8952f05c2f346abbcdfd03f53 +6a56d6130e5af9fb7b3830d4a6068912e3f4079fcf693c5a9cfa16e248d14d8c +e116a637ec47b4c26b6e6376bf8d7afccf31ffef28b7a9e9b20380eaf6a5fc91 +54edf8b1880825b782c81379f84f4085515c47c5d20760f5a27a0cae1ff65c84 +c810adf1a7f2ce9a1c6c76fb71c1607da884916ce987a5a4128acded8abec535 +aacf05af347e8ad8e4bf35348a0aa50b628c2242ed2d30643791ceb98bd86ea1 +fe997ffdb68b92748efadc0284aeb3fa557a885801c9c863a0850279e48e65c6 +05ed85a3f98a11d3268643556b4913808bdd4a2011c6511ed19b3f94f10c508f +7dd1ec9d37ce86dc8ad8efc914d0e46816f16fb60db48f85c31e34884fa9168e +1098abe4d62d2c1abf4efa4f0a84f202250d438d8a19e9e6b1391fa54c49ec0f +fc8476187cb857bfbd2aad76087bb74fc1f45b015447a90e8431e55dd4c882c7 +1d4b605ec13d01e884c7940f82e62d76933a7a88cc2f4e5eb485ddabe118ebc9 +86dfdaf86cc12ca2ae55b9ad7b7821cc3c6a64c112ca56f5926a32b06612027d +c0bc2caafae6c2dd74e1b88219d7515b506393919cbfa7891b92bcf08f4ba9bb +88cedceb4e89d3872e912256413299b3130666f288d1c5d504605de11b1fa999 +b4a6f117c5f86d03d7aeb41b0fc65cd5fd7a39383a1fcd629a15b9d7d8423bcb +c8ac1327ca65115ace1911f922ba70a9fa061e2824a80e664dc4c7307cefbee1 +c80bf093276f45e1e0c9c0d22202602c561797261079b35454a29d6d596e93b0 +2efb624fa2c75fc5e400c8475aed2e94402f0e2858a1626d9880e540d199f70b +34e1f8fcb5b3317c0a0cb1272898fe8d9d2f8e99b774887e459a4a6bb4cb34b7 +9aef6b5424ddde2982d1193fd2d891dc3de4cb61afe7197da3841087d02ed87c +8d73155b72036560b8aa4d5d0a3f1f828872307dd8b7e6e0b95a3a6acf57f490 +f1c86e459d8e3046487c457d5025b3f9817697613bf63f2c2e314cbe19acc65f +93a25039eb015919d3315990a644fa6aa523fef2e77eda125a970e4bbf28ca25 +4cdbd03a3d23202a2b8d6c12410570f23d0cf4464392058e495bde9352abff49 +4ea60a43b8a233060de9a13512d6411b113593b2f7e3abfbbc379dbec0e25060 +8d7277a0d0f0ae4a389e94006a60c7d298d5ef59240ba40039c893ad71d61d36 +b2633d2783671afd7cbb2d5cb33e06bd45da0346451fa238d942493fd87c6703 +0309828bc808dd519137596ca934397e6307db1e92cf48dc7ee20c3530288a06 +48ec45fd748f9394b942de71c006897986fc6e5daab53b01057ed961fa180f27 +fc3004af7b436b9aacd83ba39ba03914c50ee00ee2781db73973077da008d4c4 +fab5bbbe02d763db2f63418efbf96dbe94baad2df6a97b8b41465b9f86bfdb02 +c6a63949936ac92c7a1215e9b2c8fe01b3e97a0b2fda8ae44e3c67a79d5534b4 +b67502e6e35cc7ff491ce664bb9550d5dbaae96e10174c45e56a1f449f5730a0 +fb805a689b368a2dfb6ca2cb690242eae2f3efd00b02eb116642acbe10c0f3ee +32ff26370bcdb5e9334074219c6c77ce0831e60ad88cd8c4f1ab12049d065982 +07542ba230483566bb97ec9dc9116024e8846e459ff6243e439e1cf8c1477b3a +5a3e9cebb504668693429e367ef4a3fac6eae9db83f2dc0aa641f09ee8ab14ef +961b6ddc2927a490fca62f15bd8b891ad459c77d26eb48c4a099ce3df24c3300 +94189b1c8e76644411670721a72919fe7460e0c6ad2712dfdeb5646358e29b34 +ee63433f3358d8122be5494dc8532cc44226943cb7e22a37c87c1def3dd8eb4b +0714dc44d5385ab5c86a3708dac1884eea3e26298a4ada86544847cc92f7efc9 +f028fc10a9267b7e6063eca9267520ce8690a07ef3866f3ba71cc0d7d2ed9795 +65531f14fc7e7e75b6d241b5b5f35b9422b3fcd1fc6d7de1a85e26048a6614da +6c689cd384564565992249959359f56631a973853299146a342d29e6a256ea28 +9d3d4b711e15e713951bfe1ead076014e78eada7fce65e2ce3d2929179b97e27 +90f2b9c0ba086b71338f14174e9d85e6773436c2d08ec335c40ddb4191d9f929 +4d8dca6da12efd75fd39145fa330cfc7926676d7e3c002519549ac9a20170a3f +d1b8cc3a45291e7c07c9b53d2d4e6bb86a707fd6a1c766dd46997e7518446a55 +8a2a6459152d5faa207dd61f326c863e1885bae88b141f670d07e6c2db905a53 +2d5ecd51027fac9e6386de38043be4272a7f24be3c3e26e0da5597298489f1a8 +629c23b4608891a5622da8cab64d5c51591b098cde326aa75713e3f858fc0292 +46f7d2dbcbc1b16807eada2d46e4889c3637467ea8ad9bb1ff8c21f0eee0559e +a346558476fafe7270d1da6e66f487b4e01e610d639fafb46ddb80b4f9d57057 +aafe5b475b884b175bc619867f4c2fc28053bab73d0c32b85d731a1bad5e7827 +6415e8b7f972d5c5fd108658216ae9e4f14c63dee83c30f0009a41709724ea96 +191b9c5e46b3f7dff5de00c35e5db5b279011bababcfc136670d1d35b62b08eb +a97555d19ddfba6e22a444dcbb8e351585771568f112cb6c7d8334a8ab1730ad +12f4304b5ffa6165b483de459b205c0197d1dad828a6c13e11af650689d70d40 +fefda05127d993f93b6aa9936dafb52f1ec5a73bd8e900036683193f3af30af6 +edf08a30a3e782ea9c5dc139d3501a9383a5c20b96e1a067e49b60cc964b8067 +94eb2f14057803c4d4f606d0e6f4ec908406138f8bb691c7ff10fb30bb042c52 +f53658418356bdda66eb1437256d00b94489efafa50959d798a69effce9391eb +5caab5598305e136106a5a3fbfae6d9a3625fecab8f062714db5b5741985424c +44fb5bc3f3832cfc5dbd25448deb821a83116289307e025efbe46932aa442407 +91f32e5cf3fb73f4d7bd035bb9b2a605a9f9a5fdf34a4396225b25a2806258a1 +5597bee13a9a3fad79694d57cde0284a2de9cc3fd1f172986507eaebcfcbcbf7 +2f43b4a586ea02e9c58592e7b65033028e19ca2bfd4eef1f25fb25e6fad42aa3 +b5d6f68ad839cbb4a342285ca7cecaefb0a479ef4f424d4e35242c3be2d490a8 +f85671257c2fd3e6cb51f491b711badc1207d70edfbe5b30769573eb313ee7fb +50c01d2d795d43e640e8c853221eb4e24ae9bdd9feeb1948c3e5650f7d4eab2c +0a2005cb73972c8b361279733ef420208cce4855ce6cdc07992bab3a518b199a +c05e2c9a71dd9638ee19cef161d03653fff0c68bc7c31856a7e3eb0ddc95a4ee +44c3f42637f133581140cfc8763efc2e38356e15734fce489bf330987e13989d +001504d3b6a768c1aea311dba4206e3ea50e48d1913cae5a6e9314d2cd27a0d9 +90bab0d0a4d7eb0ec54793aa3a2548b26361563c6bdc0569614e35c22cb0545c +cb89a0f84a949a11079ffcc3dc52ae51dc842f39dc102f7aad9485c0951f63da +5bb43ef4e4c6e796ffba2dfbdae20ae017c3b2d53f6eb0a96c2737375f15e208 +aaa0bde5f64336db344f18e7fbf55d8a21a08373b6c0c392805ac87d3bd721e7 +e48604af8a3dd85db44b373d19388f5f755f619968ec7c349b421e8a05573758 +2563606a06bd2b4d6d8bba85a8fad06769acd6e412a51c4f53f0e5b76fbcb1c2 +6d1f59c08bdd45388c3b12f6d511b544ba033219b445165a0512572afef4246b +54cec7715f904a6feeaec858daef686fcd16df4b420f2250d7ddf2b0736c3984 +197376836630c269514a483fdf18eb28083c05d9d03a4f3f72b5fd193cffebca +72d95ed6dc403588f73bb2ad2b6f5c9ce9848303368c1c136f46a8d6f83ecdc8 +fadd4f9e90c5c1104e5b37efb374e03c1640b137474dbefb433f779ebd1896ee +63ed2b57b2ab5ebf30d91e16099066c39653c5a8fde39c4c28d76d6f5cbccb55 +640fb246bc7604f4f5fc50fb621da401989a5a038c6e23e2472f82153c877253 +82b71d4b2fddd156adc3e7039b9a865f92420212bd5236ee51e65e7b0d625127 +8ab3875d23234794b47f29bb65bb0251d263ce94226eee28e0d2f38f5b997537 +d3ffc7b57b243966841afe869bf9020bf81b1f835a5b53f4cd255861bf0f7c05 +fd8675254085c098414fd3c8379f1d2cbdeddc257f72f28f982a10d9ccf3ea80 +a32b8518a62cf64af73c5d187e2c5408289dda2ec1ad98adff51e572f2fd43d8 +6dc2131c082a78d597b55666a2bf4b960579bca80c04583c078061ee8ba4feba +2aae48c96198c86a779068f310cd87069f9e7b61a532a74d8b0dddcb1ab70f5a +8be7bf1105c7d25198cc73b02e33ca1db8517d3cc448248f643d0bf4a952116e +f5bd30039a6f1f6a4c5c671e6c2c08ad439be8a9fecba17a598efaf0945c38fe +5d96c1fe7d4dcfb636e95e462dbab6c29dde452fa0e6ce48965c6355df209a6b +b79bf0d4a9eaf444989ceff136c14636775496145adb44897761e753a2efd870 +55e423a70ccc743dd4012f0d8f070060bebab52d84d6a0f6c5d95bf3ad44cbaa +ceafd50033e5b94a70d8cda11e20fce69da0eaf091a1aa1edadb67afe133f9df +d49aa9bb4952fc1ec2a440c41d6b26258f81e4ad62fcede6ffe44bed65e9ae61 +d05115f43c39cd2484b5e69cd157482085a54dc286334c0632b0441f201f7cb2 +263adb5007dca00fb99b052a2416c3b9881982c901dc8de717fd083ab61ae55c +9ba834f6c9a80b2f6efc41093d5de5a68bc4525a457d10b75ea6f3f6497cb7ec +bfb60aa9ea0f2c90b85440cdc1a72087fb8b3fc98f67dff161cc15824e0f764c +f44beca127f584b096d6d864b05f26a2526b7abbbf0102eca2b66b397d5f09e2 +2b5c6f9a9dce12538e345698966ca746863977341537adfeef016e119275a14f +01fe161f7680d6ea9107695f6fe48220a9f39ca6f8ef5b8552eca3c57b5566bd +58f86cb70257fbef7469009b7fa652c5c9d8b6c53f337d87c40f0ae7d5a3bb10 +3d86130dc0e6cff74a48c38297eb8fab72ee72b77ad22c87e5e5df473b46ea7e +3e6a32d97e8f354290a33779fa4de37e1c5b9628c6943b2c64b04ba05ac08737 +e129bc248f7bcd5e6341bd8a6459df78e8e6b9b7dad1cff12c0594618e578910 +8286db522cb837e33134c03c519e86ad5cb4f47808fd8c987bfb190206920a67 +ff26d100c740339c16b52aa51b10d5467ef6b7888a6c5124b2561197abd2d7af +f9c903f356197ddc026cb8eb0072b58a5fadd75e08ba6a20099e38afdf8eefe4 +6c10d78567e7cf9cb444fccd18bc365cb6f3dea1e0fcb11160b8b7c005cb543a +f50789eb7a531b5ee3040494d4836491545425c6605cc17a851b36228e12e76e +fb628ed03448b5430dd6284859f01fcf9691e4f9a147c17186482d6e89b5413a +ed377eac296c6c06fdbfbf8b419bcb6c6c0cdc636e8ae985afffdd92a409192f +fad7446b107f96744dfdcfcd5e3e93615ff5934787089c97c8d7a93b3195c60c +a722d63f8ebf5bad16ea890ad8665d8e3c4cf9af7141ca9cd9e77bf7d2cb1a9e +392cde11a08e2a2386c33268479f1ba60860e63b88f0774087ab6aedc10259fa +3371565686908ac74daf5daf59a4629cb31418da9d5a7826b883572d86fb70fd +00cb8834e7006e9dc1b91cc5f50095bcca09706f0b5d9c589c63dea6997046ee +f0e9bec1d53a0b9f6f207742d4609d67e38c6e37a1c5610efdcbfc5dfc2bc796 +6e92dbe5d0a9f4b9bc161458c3e3f2264da5abe0907895e0195fe4678d4174cf +2512b8071287ab4c27af9234d966897f3ecbb9d174a4ea08f026a2fcc19b0c58 +97034358333f3bf000a5d6e5194d0878b2ac02e82b3f293f535f6e1ab625c242 +b90c9f13ec07eea9e403e84ea18f1221270a9c55374a439edfc0d9f0a7206438 +fe6ff0da60b669c8e05e33ab76a9dfd78f530937f6afaa52bbfe0501ada9d51a +506b02274fa92c9c0b8e899930179c5b200e8909840e7d3ddf80c1823a175371 +faf2875991821be2b38c7568feed405c53e5eaffd187f293bda4a609669ddb9f +537393e5395895261eb472e5f402b0ec3bc208aa1061bb6b78ca1f95f1501d47 +f36a31d481ab47fea23c6bbf096471815cb6786f95858d903464b1be9c323258 +86a8b593e1b63773b5a0344a99febf865320c0dab654a2ba96e89d7b42ec7b88 +5583b2102d9c983dc0bbcbadbb23c1ca8986e4491229dfec6dcc07329070b34a +ff25d610df1522f50a7b66c7a7672793932a41f304fa2303e0ca73b198bae567 +3391d21cf2c7bbecbf3282e4fd802229051deec56017af46573523c36a6c7a2f +5e51074cc1d058956eaf6687953af2bab19b0d381e140f45768f7ba3cdb7c351 +2230a4f772ef22cc2e260138b183a9d33b64584fa5b671454d132064b27d1e8d +9d9a11b9d7bd5cb2778ea68f2271b8d1011658aa4130cb9189b61f71bae0c39b +5842bff1aad5543c43ee7108c1a211c9ab78a5eeb31f7b461df58572d1957437 +b1d1337b178c07d3dd267df44b0a81073282ea18a8f546f41d401a8066753eb2 +ea5930e41eae35a9d6e8d1ead8e044ff0e9d0995c933db14c363243a77e38644 +4689aee3a6947042b1bac0a1f2b6d540ec9632c8217181ec7f0152d0db166c59 +2c82eb39e307ba6c2a19d88d9d157c2ef925c8e2a51ef5c1e7ef9046313de1d9 +c98214a15a568332d6f44bcce3b5ef7b09d7c7b04a4389010586e549c0d98adf +a321335447a1f78e82719e5ee0780197a5ff726d92c55cce5226552d7843b8e4 +c6d5a80b9ee877e2be5d76d07af9be45c8355c14059f603aa85ee784e7a6d803 +e5a35e453961b3554a6cd945bb130ae83f01d0163145ff618c89de3bcf105294 +3d7e9369fbc3b8f11f880f76cac0664ba1ecd49de09fd29e13de60b02031fc8e +5958fb4413772f5b88f56b7fb9964562ac0f86be18dfec748ebdab3030ec0eae +b4780596ef2817bd2c5e24a6d502177e011f60ae0a8a0e8f2ec4df2c66583489 +22730f9fed1ec5ccd56e1fee3faea783996dd0b1277a3f50a5fc2cab7c837a31 +d3f6058172f1e6b8faf15908c253a2084c89c1db2a462582b8b15f363c112c10 +bf530a3a05782f424eb62f30130e2dbfb57ddafff84640e22357b3efdc38333c +4cf1c28b71e785be7f47c59c3bb7056473ea3bed8f296c9ec17d9c781f52fd04 +798ae8de014cabc0285530a8e72a1313d5c17ddc93f421491f935eab8edde78f +2637174e97f1e46c83896fed45bc00bc27616b87f9ad627a6e0be0423fbfe6b8 +e02d5a8dcd661f700a31e817ea22304d9582f3c5653df62a0ec49f8658b5ea46 +e67c64e563aa7783591127864f7a8935ec7d983e6b1d1784384324284818580c +a9da0c8666cb26b520cbaad90e398af8c0775967774977348fe0a1ae2ed358c0 +6e953f684a67efa4e3b37342e10150ac41421cd04213ec807e212e717005c6df +d7eccc639f4699308603e25abb0cf8ad288fa94fcd18fe973c50824fc2bda939 +1cb0475ff36e2cba914f8bc9ad62e9254c5883b111ad75df9a1fb13c1007a9ba +e51a924ae1f4cce7b03a9c22e4c5f882cf39d08b50675d50bf9c89a09056be6f +1d5fde54f49780d4386a9a5fa111f4e496e55be9781a80deab8feac8e90c11ea +ead90829a0e27684ee4e237bc5dbc8b0f21a91ee5266ad072d9bf7e48e227218 +e4ddfc1e7687b2d71841cab471bcb3a3e1808bb24904de8c426069a58200741a +06f12d910f2aade1baeba427b2788f66b0f9567d8bfe588cd026ae7d4169c169 +cae8e52df06f42e961097338c5855c8c084dbe6387beb16ed9d757d0d880d18a +0892957721ccbac487807fdb42a12261418c772e359a7257477491558212dbf9 +fff55b8a81dbc1f95d17a3a82946bf8077983529f2a5094f1c9b157b537d0279 +aa0f81e3cff9b9adb1fa0ee70d8295e823d50275c073b0ab87a4c917821ad416 +30336e3cd54cd6b1aa0d7b1a36406439ef5baa75ac3be7af2a19eba2f22a27de +42857da3c47561a9c63f9534fc855ba8daa3de0c145dc2e60cf7a4665f392c2d +ef0fa737df7938886939368f7cb0042f71a18a8aaebcf7b7101f124f15702e78 +2b8ff75d4ed43b085395f59082775adf6e133764000f81e91f7f23eed6f265b3 +a69e5225a6d1f1152c447e26c7b7d795e96258b62c04ad1587f1663628ecec6e +21e6ab23d99ffec79e6e46d55e758879f58dac96966e3b9ae9f780b7a109c70b +aa6d5543183b3bf621d7b707d9259615b5b8be65f59d9b84b41802fa0a8611c5 +8a551d69dd2a6c2f33b6bd8023d9ffba08de0dd4150b8434a533ac94e5222efa +42ea9cb3aebdb9913193615fc2e87588b419be0abac644d9414f5e7f7305bc36 +18af6fb1dc0f383f867c99b1ea0f24ac1a609eb6cafc653711701148462296a5 +364947053cf5029b18cf588a2d2bab0f51845f711075f23d890476c95db4fc8a +2a6622aa1f652e1b7c014f9fb90f81ed6a527d885af6b60891254eb914178a6d +e297353498bdc35cc30e679293a8af970b3ed41f439564c7e260fe0b67543a1c +ac29939e2054372018ac0390a1e5970fde0b36bfc097ec871504756e47153b13 +7491533934d4382e82166faf59212ffa38963dc1fdc1b49793bcca23c1c37e5b +c6cf2c4dc084937b71db039057064604c310bd431262e9793f3af6c3edd9b878 +ba7d5c62793ff0486b4cc89313103ff214062ec98b682a177da36d8cde6d41da +27637ba6bdb9078949ddb13f8b140b1fe3c9559f74e2c87681d2acaeff9e5ec4 +3013c81bf79a4e89a7a517a7d45729b9b99056c7230395586cc7adafbfd5268e +f4933fded81074162947d422bcf5c06d85ca3f3e01a30aab2bab23bf703eae58 +8b992c6f25300092bfb6bdd50e8cae5747f44b95187f1b4836c72bc8fd702573 +330007e1fbe2289ed7538ca7a8a048d1f4ede36b0882a476caa8d40211594fed +e9c607469259d559bbf9b655effd2f12c8f43f2a2644d9c1e081032424b259fd +45c2aff20382e95c83220904b2ca9a6c1ffc92bc8a1d8696360bfc6fb83e5a7f +f949cb63cfea82318d95fb74494ea9de45506d670c56d869f6d0cc8b8e09aaa6 +1f287bf3701f1e25eeb761effe1aa764ee9e8c1f697015a07c3ef89fdfad712e +81d4c94801f799098e0008617f10a4c5d0f941ded6d44a59d0e915d6c4eee7df +99eca076caa0c0b76ff7ddec183c0173c99e83e42cc5563d4dfdc895ea5ba284 +a21cdd39c748b61ca607f5a36a6322a59dda113ae168de6e7ff7c35a31d2edae +2a9e8860dd4b7e969bdba7e8a7f3bb8a646ebeda176c4b5eb4783faf6245034b +472ca9f8870717b11494219a36ac4a7ce0673c083347b10030722e9019647a96 +d909f037b875af1e798394c98d8b0e96d2a7afa9374c6602b4923099181a31de +6c1b67c3df05c57e54bd1913f2060ab21e84080036912c5569380561502ea577 +064fe99c97e45d02df1c659ea96fa11d8ebdae89a899c0d414ad25a77607c6a7 +336d610bad8fdd7e5e2364fbeb06f6ff8d90cae94dcdc24a4162003fea3883d4 +1864cc782d9bfc98cb3c3c95ee7407e04881107380ee3aa92b2d9a253b1ac08e +98ea18887a8504ebd390ab66bd4a54edd2dd79c2c949dd6040aabbf81cbb9f7d +a1615e5946875a5a3bfb49bbc6d3aaff3d6e43734e5e9692a39155407a20871a +8c087babb87de124831e46e336bb987ec8190bb2c47d18566d3a9a7f3c79c2bd +e257c5519671b078f3dff5373d4358cc49bf3956edc39e77cf03c2437c1e9d07 +75ecdd0800106c535527e3073baae45a92a68456149dd21b01e3cfc51d521fee +4c1312821d3ca3feb3050d0e0f8056d93cc279eabecadfbed9f47c7e8fc028b6 +16613dd386e89371acbb2db7850d242f887046da135e7791e8a284963a56764a +b839065a6a9a0089def7aa7fadddcc5dcc8530ffc2760c9f0942fb5491cdd434 +010ceb1d945761253587a42d274acff3605ca4aa48fd001c9a2bdb57cbfd946b +257c2530f83a0f9883c9420a6c020d6440d56f33e9346374dfa096932ac289a3 +bbd9ca598e1208472a99c3905972541a0f24278f1bf8fa39c8c67fc6a438e13c +ca9556c6b24444a07dbe1d0adac16460e8db1ee085b3b2a0056428fb4cdcc49f +0b82dfccb5c3db9460714bca093ad5829903cf7a4fb47b3ff515b7517263ef63 +de1ebb20c781f35f83dfe2c1347daec0ef80e7555fb26ba6cd28361c473fb97c +60bc5bb92db418245b610a37a11471352382e323ef711573bd174f42a5504290 +9c8c4ba58f21cbf56e7e02148df641de08a1be2ede3e773f7f2cd9fc56c517ef +cc5c1538200f06b57cd0b6933d0ca2b9d13827084a88a7c45ffb0c91f1570107 +7ecfbd1b817bcd45dec55fd5784d112dce70fdce59bc48ac4b678e87fee3dbe2 +bd1ed6da2533c36bc14f18ff5444edf4bc4824e1681aec147b861f1dbba518ed +01c3e7a43107bd01bdc7acf186bbaea8bf405a6cab7bf6abb23593aeaab99395 +f06c9724ee9e9c9cb096c0960444e50425a3af2e55c035b7d754263333ca3079 +1950d85e72d5b9295ab083bc1d357e64afdd00265d17558bba86e670d256e9e2 +fd34d38ad27cb761e4f60bdf7f5c6d4c68f28b49626f7ff8e4248ec6402a04c1 +0f136e9dc93d75d30458563bf1c87692e54a93612a006fae7bdc250445b9ca38 +10ecbe96e1644a5833a9876948c090c88f6272023a64dad34f139551b2f472ca +59370e410c961a609d5b39fb99f2d4eb57595602fb04ba6ca4ab61ccfe26818f +1c8a5628f44d83a51be82136e685e93d206f5ceb377e9d70e5a866113180d4b5 +697d803ea39d8ae8f6737e57853da0d3baeeb0c7df7b679996f2164ed773f661 +a36e1582ff77682dbe467e5e9638718560f8cf57844190c6b7838dd325344ba8 +731a5424a8ecca297f0a5e92cf8c11837862e9e0384ede1a7d46b8b43aebc1c1 +671d682514606c4b4d6b055d5caf71c09f35622a5181758d081c082833e23ac4 +c059c0681c988151778087cc54875be084e8b2ec434917fd8cd919b19dc55774 +836ce92e98216033a20538656445c9ea61c07ef70721cd0df2b8417a45da0276 +9acbf88965dc193b5f6915594d14ee7f0f70e94a8780db5617f9a9d60cb66955 +ccee986700630a9b0dc484598f26b483ec6a8ba3d5fa7a29085d37e322762759 +7e50001cadc3f3f96e85946a17909b8f7a0423969d611bb4cb6d8c3d2ac74df2 +fb50d278da856923995a1c37aeaf4f35d66c597d39b3908b416af40fe364a366 +a6498db24f7bd494e72c4505b2d00df83fd181c2cb9aa19401be3586a7e1470e +d75a78ccbe317613c07226e445e3e6389cd4282518f7cf6955a06f4eac010cbb +a4a76e4b60197fa000851625a8c54c73f4d2b9f9cd039f7649f841a8fe6964bf +64337af790c11bd481c7079aa50a972de75ac8e59acdf213331fe1dc2f152780 +deb5bdbb4046d50cd56f37c88a9cf092e99f7b47b2d035ca924d81d0d54dfa20 +0a8b796ba5606f7ca6a373f80c7b15bca08094258dce183cd51547ef63606bb3 +39fee2b8745340bf06198e5cb53a51e2000e8771ab78851a7c5283d48dd7f9f6 +8f208cdaa8aadba546cdfec09b3f8765facbff9c110bd3f277df50b03eb01739 +49c457631b366fea5419053fda0a0c8bf5e6d2d85d1436607b4cf7afc6346d0d +5258c755263b32de7d0fd6d302aeb77179ba2728990d9f6904335ed6cb5dc40e +ec2d4b9242cd5c94935444e8f4b208c8c8af47a9ef7c1aa0e6b26b89a299a709 +e13ab1235ab10eb212c608fc6a5d12e930ecdf029a8164d0dd4a07249f965d2f +e55f41d44d5e66e8ae2b99ccce2f14e0c8b91db22bd9405e2d3de8bab6b7d7a2 +542cc2f25555f9a3aeb711ae16037f5ddf36c3ddb77963691d7c10f88690f900 +a67f69e1e7a7c54924051917540de8b955e8d33523fb2cc1999f4023d09b2e18 +a525dfe307352e899a47c8c21a92d52521e00587fb9a97fa64e510f084d813fb +aa7ba56e3278aadf6b3c7c8734ecd971661917e4a7f95e145b51806ad3ab44ac +06dc80508f5a4428c65e2c01e219aeedaa9eb37f208d6870110812575b419c53 +81f40fae821974d8c517832ddac04515cb82418cee049303b3305ae4e73a938a +a8752295c892b6d596ed70daf62955613aaddedf62586d421632a03f06f80afa +52093b208c7dbaa942a5f045e07e1f213378ff4b72cfe6153df87170da52e3a3 +99908356c282d6e08ab521c820b784263255eb2f36deef47d24c8fe80d80d29c +d102aecffce86b6650cc0243872473f4faf727c23b47e96378b1c73da70837ea +3e3ac6e2b0ba84cea31f69bddf4e25c9000687f92e437ca3134ef0f06f3cbda1 +c32d37847e020c1cd138979932ed537c49c0ed1ffda02eb27434de66f28bdbf5 +b050c84ecb3b41ae947fd9efd44899a2ac747c45823809d56bd8659214043280 +b9ebf7be2a342a2d22676506ee60c24604f34085f7b4d0daa12424459d674494 +a26962cb6485dd0956548be96f0fa8a904b225bdf2e355ccef003345e43fd884 +cdb5467a1aa9a340363585ce7bf95ee254777ac009bd73137406ea9f92731f1b +c31f87122e4a4592850d5ae0abb6b520c6d7d8f90e0efe027a403b4fce76ffb9 +1d19fe4a0dbaf0f105ecc25fbc814030ec4eddf431500015d74450d88c6f5675 +3e4c9d6512ee3576f29f62b24b3fc046faa686ae8a6a8054728c34651ca92594 +9340d56ec0b2263d668c94133cfd5cf2be34281a06ee3a8c976e99ee525bd86d +32ba92e4233880f10ea5975b83f79ea6870ca11bc733332f6008c22bca116a90 +efd63f1ec35f606a6a2943e3b6bfb99e3b3aa1dd188d3dc259d01b939fa9cb45 +326673e0eaa704756ace85fea56ddd6c81b92d4efc083a835696ab29a5d529d7 +00cbec9cf891e5db32434331148b0456570954e9e16d3b10646e7d7b993466ee +e025c8ef83aeb971380074eaf283397b28e0b42289d2eaf0b52ff54821785d81 +db269089bad1c5033ea931d12f5a7f806e6ecb28828825a94f5c8a6111e32897 +a454eff81d42f2bfea0fc6442c8b1b5754e0baab05e9987b0528909f14678a66 +64dca042b3d3ac7fe603a5862181f30d9bc70c4c28bb078f7da0f37613322c00 +f7db455ba719520dd8c473f84db210ebc5c3cd359335b13a7fc5c72f163a136d +daa029ba30b301b822e998107c81c77e20fb088b3e49cc220c426b54aeb8e4b4 +6c8074802e671285039da2623bccc4a17d6897e3e7eec5353f90ad5522ce80c6 +3fb64f1b7384fa728f5b8ec68cba7328a225714b957d903127fa07fc188c1225 +2a8465429b149781d41e55734387fd2b7cb2f013556ffcb9210c26918e0291f7 +44bb36ac936ef778c0ce8a4a4431b58d1a4e857fd58c77551299d9b312bb473f +91f99d2bdb062dc21368e73a4f09374ce5d89915c1f6d11a071dc2efa01f6bbb +a30811fc7209251e9714c5d8e0a3278416e0efe38863b0c488707fc3a3b7708d +09dcc1f7a19fc376d9a53e567c982030cc8be908ae853e367dd51ec2f955bf49 +421e1febef84220b0a6ffb73b0c82d5f056b29e85359b4daba59b25ea61d5bf6 +e1c5c0773e1dffe196af0669ad9f0ab2b8c10eb28442133bf3805d5bbc7ca56c +3618076beaaeb2863bed8f016159b685bc4c328e3073e6145977be19cac32fb5 +e1c252d657873371593db6e4844da17e5669139495b900b5aa4a7b6e3b81409e +0a95a178d0d7fba7cb878a2cf5ba1aee108842a72009af953600923e852cb2aa +6e0f035a87b161d89b64a473fb4f0ffaf1aa16ec5789fda3b9c0b11497f525e4 +4be74896bb4cff59ac095088d975ff43a136d92b056330f812a1fd369675205b +1deb6f4f390de5169bc5985162f38af6694500852e14ea26ac774e7dbcb451c0 +c4dd8c5718652a7537e7a94f14208e57a3a72b90808c3760bb1837e269d5b5f1 +ba33ec5cab8eb4e379da6bbb26e56700c0ef7662f0e92739d89478dac1a00a61 +d95a2768a229e15fc51aa6a86f3f4315023bf6fc9d6e05b5a8e313403f17efe1 +cc7e26ff1fb5a7d26dc1e3e44b878958b3b48db1e0ad26a515d03c0c0931ff6a +50733493825f59c80236feaf467bb66c4f2f17b025335359848f083a8008681e +ce2479807720a55f5e6565ff2abda7f209e20d0e92359ecb6c803cccde11dd43 +00002d6ec434d0f0469b80c95f66adb9c8189dd764fd8fb031b050d65dde2ae6 +a86a596bf7e2f1e2da604c49df345e08cd3cba7c4b4f80a3fcaa6ee560ef3eb3 +ac46256d883c4c8022400acbe6cf56b0b9170e4cdd649b11fe5aed602518ec03 +422c74c8eb5891a07b335a765b04a1f11601130ecb00dc392257fabc8fb82dda +b23c40a29aac3a1fd8b86e0b0f4600abdbdea1481ab8652ffa29374f0c25936e +ea60d9834522299735c1a56cfc897223ea34bb09a1f48b32e232ec8316823aaf +dfe428b7fb6c6f44538404839f29da33ce8ccd94c78af279e183bbd48d5d7243 +b5512679b457a1c04f5d178c5dcd2b2a5e400852ea7a14da6de2ba6ceab654cd +d270a789436b3c3e912e2579d629542d87d9c03b6fd8fc68c3acb2b821fc2d9f +1d998838b376847d254606cf3dce0dea455f67eb94d85e2ac8835c9ede2ce08d +ea94552a389620acdcd11caac81a498c4580ad4715695502a3aaf2d993cd3d66 +2777de78494242266b02a25312a860968e62d4e4b2a2e3c8d6fec42e54a80b06 +daa91fa8542a3ed66de591f2d3281f42c484d58e4e40b49a7cd661874c6c0abd +88f84eeb22bac4f1c39cf5aa69b7e4d816361fa35a9668b2114f83c32a560af0 +fbec2b8b31554a70e8aced3e887af7c297715efda696489d29d8bbd9b65c58c6 +dfb1470f29f7d94b9a837d828498a70bdcf0f5b5d51c25e05aeefa0833490788 +d18bc48ebbb7636698fb57ea64df6b17c5c50bf39844f3ea0dc97a9c198abbc8 +b6f6116835902ea3fe4efa957fc6effdb0876794f3aca4deb998efe80d94f73d +fd3bfb89e429215009c9a2d559ed7b5360541f8aef09f82edc4b257b4357b4d6 +b2d78028f579b155af9cb395ec678e8d63784df5c5a197fa85e961ed18f5f863 +bad90252999f909ed42be8a6347f7d03472b1ff776e80bae87f023ec92f8224c +a2d347600ac6c5bcf20242fce55ebb143a626c602fb4065fb720c83b42805915 +e5ba098ad8924df6d45bb99ef8001786ebcf7fb52893c7f1f42d00c549ef7e83 +7a4b4eda517049c7cdff6b3a4935cb9fe3ade448ad1b0f8307e4d18f513f4a80 +dddc93629981beff5207c55dfac2579a3d227994b6c1e788d4084e1ff152535a +a58d609fe9f7b6456f51acffb15f1d4329ed5f95fe66add22e385442ae61d7c1 +fadbc0b8b358cc6956df7980bffc15c67efa13a639ddf98823ed2852a20d8740 +519db6482f1a1b3ccd1ccd8c53d798898329c459579eb96f759978d232b9c913 +683b9f44a5cc027534b43985add3ef248b0ea9b8a861d6e3ba12bfa3d4c3f0b0 +d30a44f8e0eee84eea1baba91e1c5ce13548cc11ac720b50b4a6ddffc0d4a706 +8af5872d999c1432723da84d529ed54fb4c3de8e1ed98cd0f10e6fbcf27da0ea +05bf4494019d97b84ecaa445d817d8c79c97e5983c2ecbb40b7e22f5a27879d4 +9a6cb69df5e0165bf2a3a6fb5d5198691f4ecf7ad778959cd008cdf4dc2f11ca +02caf1a8c0161799aeefeb7bc393bb9ae59f0362de55c5b2503e9ef2d47b3ebc +c65a4a58e19623fa923299d17ce3d64593602699b4b0342669c63ec924cef85f +0ee64df7092d5fc8b3404f363e3fa5dca6f814594ddc3f74fcda0cc7ed18489e +112243ee5bee9c282fa4b1fabc7dfa8e3c112501e76fac905584cc4bac177e88 +0784a3f513ea064dc8afe188bd0a4a6177adcc6485041177af351dd94b7313c2 +2eac0a1972c4065513ca26a95b01d37f801b331eb642d3ec39e178743b79a94e +1d690c0e048b8dff5fc5fb7a594c790465a6ac819fc0d728bd07103e68aae78f +1b013e7f8bbf0d595ad91d2c22179693518fb9e38f70b10d3617f0558a499157 +9da81bce9f67f33e98fa026146374a83042a43e1ece9ab51e23ed7224b09d7dd +54ab79b3891e1e8c32eddaf1272bfff6b62502b520738d0d3a81d4bd5ff92712 +70130ff041eddb608a98926b8cfe655a5897469dfb7b7a9edac1a8da1f280224 +c1324adae3a9fed3f93babeabe802029c196c5258bf852780ad2286bf020ba5c +6135b39a2b7f5769bbc5f78b6300e96644537435b72d21cac9cf04d797851b23 +9dfecaa0f7052f3e319d23b63204907bdc42b84621165b55a635dde4438c72c0 +17bcc98ff25fcd612c254c41769564f4e4d7c81aa2b85c96225ff7aa6988142d +95897d4ccfde315c7e8c078f8f53a5a2fdaffadb4a6ea734a431a7b5f9f8a7d6 +abf75156bf4d31674f2fdd98692aab772c2b17d71f08b584b0e56f3c670b5cc1 +8af6cbde831498077839a59b59996dabc1b2c7efc4fd9dff0a16cdd33c720fee +f82dbd587c2e29b51282f7909aa5ce4b0fce63028ccb4e92158e77cc5e0661e7 +1a8e619b362eebf31e56eb350c25ed503b00bade176c52068c8b43251932e974 +f0f30f4875f9bda936de956c973585f16e09a24d8ce0540cfba47f0f970b5159 +4d5782c4b1a172e76a09a99442b1b24360d26e4ca0127c51401322ff32680079 +9f8319a4fb82aad8bdd2aa312397b6b04704d4aca0bc7e438f7839b72b02ab8d +f775ca3125f1873af8eaf10a7dd92089f1b3b3d6f61d7a02bd1307e99ab63efd +4b54716b6204f3268bfdb7d4bcf8c4c6fd630276a7aabb23007ba1929f0c959e +befbc36cb56bab5fcacd1ddf1700f3980646774e24a45a7fb5b37427a0dde532 +b6c1d2d6bc67825ecfc674b9a3339f89aa399e6cb0efa2f452c7f37713f7906d +4c8bda7b8053dd2ed43bee01aa0f5f67a2d5394d55eb7b8a8aea50a44c046475 +531614d9001ffce90f24217a99e10f07e5ba404afb180b7deef3ebdd055964b0 +abd3e68c1cc67cf07989bd1dc06282272462c2754bdf1a244e6cea7d8ecd77d2 +f5a03ecd04eaff1d64fda247293c033aaf042710ccb50a4cf1c16ae730b833ac +0443ebdbc2f9fd6e514b57d10e3a25cc60bb6c1518bc299ab3e499dbe17035e1 +514a029173d5c3dcb9c70681871ac70d620971f334cef0356bbacd271bb44ecb +468186c12c74db5dbe37357b5996e0f38fb94af7efdf90d1f1c05f2ab893c0e1 +2ea1dbe5a05e6bcbb4c3689263aba65821c89a6798fbe66bc04fe5f8d44fd458 +2fbebd1cbc563f4bd536a58a136e25b50daae849956154c0889d279ba913e40a +03a01d16aba68e84ea94a44e664f7bdd46b9f547685e28e1fe8a8d803f5390c1 +70fa927609ca453553e2903e9daefac8c9bd5c1acde9652ca52824b1be7b5b43 +4a5555876db1e0b3c340aedfcc41119fb92653ddb0f3b61d5ab6615fcda3e258 +62561e0429d503ba0992aac7d5f39702b46d5969177c31f9c6a8c57616190d4b +64348f6b66f15ce9e8239729d62483ccd040b7eeacbf93236411a10c21712d97 +d456c848e0b0c21c2245215e6e071a7473c23b5a69530f40e223973ae24a44ad +7ace0e9493782d7a4da33f227bbf6e0a378aefe47cb08af18a2df146029be1e9 +ed455709394c4ea21dd36425673f09816563eb6effae29e999d5e9d61997a833 +9edb1ca3d217fc991a246dbe061d4f0de8f4dc66a2d9c708045db737a80acc4a +f5d075199e38867782095663750b26dfb8222eeb9b1fcec6452c8fef89de7839 +e7e1bdd9c546dbb15bf3e36e4cf9fff5b38c0f65e2e0a419354338cf25f49522 +4f497edbf74c11581239671acd0648e40900e58fd609b234082792f48d83ad1b +8b0e5ef1a675ba8344f3aff0d64cf00e34cff3cbbf8170533d1ed0c65fca4906 +c2ce5ef1e68f9b99c47cf94d7950e485b43bc0032dabb2bd398527962124fd1b +7108aede8db6a43ad6685309ff8387cd5b55cb6a6c09472a2e1db82786e626f7 +c32d87c2066bc79f037786df08cc344434af721507b799f48b771f0c3c82dd69 +9cc56d082dfb9bf31f3af2f13155f276f6b0257d326bf50a63e2f332a456b503 +254229536bb34eff299fb886d1c2192e5781d33a846b8a0c5a33a0aae00bb2e8 +ec6b2cf9ceeda9e14859890c3bf06d6c3ab156eb1821baab15198589c487cd90 +bbed036c716fd876d57c6ee5e518ab1f36f6d446b844234683390e8f4e1a05b0 +2756b1eb9b82b7afdcec323ccec6e6d823f6138d0e15c0a5725ca0e42a1ef934 +5380656abd59348c9a071a9b4e6f70cdedcbf8d2c773bb8548ba1de4429a9ee4 +7ae8cccff4ad0ec81c9d458630d8e1e938fa8c567ff75e50ba8e9c6c39fe4775 +319b7acae470c2e160113be66d34de1d631a317f6af5a35062df88f094ef2032 +698419fecb803ee9bae42579fda2e2aa9701531b7db29f702243582a3e9a6982 +504eda3bcf255732b66745f9402ca50f6bd5643b6dd0f20379ac93e992844f7e +dbb4da38cf872a4a19f1037c505243337f9e6647777752c81ddb9ae20b20ee3f +c128c35f8d63187a5684a78ee257ed479b6d3c205ec545024cf4e9d2f1a811ed +efd3395207d27366945d5822720b9657f0da05141c437c98fdb3516590faf723 +4b460e3ac4610bf23fbd27acb53c9370e0a5a20bccd0a1f657d3c4bd89427c62 +93f44a33e09c8bcdfc8c177a92f815c0119ff18ddce5c53905a3bf1eb111aa24 +d365d5999b781f2e0cc443c883e5c9277662a28b12346d95add63fa229282e3a +23a3e9f1ca800cf79b858dd86e5e8500ab56a5d04e3081d96d632f10df64e56f +c0b967276866a2d31e8a250cb80995b205642d70d6b81c5ae8576ade657c741a +a7624892474b558148ad632ef18d68af73ec4b978dc703b4a95ad30c7512b77d +6a38b0c8dcec1ebf57af5e0c8b29b89f0ba0af78152be2b1fe2ec744d0d71834 +3364f85c1b6c6a4d6607905f0fbd91f5cbc59d78e5fe5913b4af0bf6a18b4648 +e370b03e53e9666ccccb44c39eb520b3a393e32f5896353392715c566de206ec +65643daa0942bd64d175aa9b13ab442be8ebe3de19aee44bf9cc7e40fd54659d +d3ee90ec5e77f3d673fdea96fdeaba96f3ce15775b1033ebbc29402c2a8c3ca7 +0334d73b401b575299214168b3a478ae560ba4c3218d239278df200d2f6f5efd +baae6eeb627b4bf95339b0f2e004473153018a5030dc91269ae60de8e5dcdb87 +d7408d89fceb3f1067add34e2ffa4903aeab3154f38e614e520ab7e27720762e +56c441dc0bf7d271d4bc35f82fa472c99241f2dbdea6f42efa2965074eb438b9 +9c8c0002b34391eabaf0fa0f48b0d1da69296feaf28ec1891a0b13e1227a038d +d61f884250bf41af7ecf5d687977f321d8ecd7d9803e9396c1f4c67d6453d578 +ca16781367e1ad396e3faf6205b7c3cd1cd6d49179ec9c39f88298ed7051c59d +fc11fe71ab0b3e071bfc132f0e9d392198fc09f0bf2f9dc10211298691199a1c +e07c5385dd3a5671617bc3847134af0f9c499abf1543c48b051228b66b325a12 +29cf91e5747cbbd67388b0588f1d46c5b2ac4c4bc70f591516b13caa783ec5e6 +ef25edaf9d7392fb630e51fdd353c6dbbcd37a0e89d07b50db52722714f82902 +e9171dcea8825d15901ec32cfb1d62c67ed6d0d08d7f5c821dc8539d06dacb9b +76fbe55939f5b6eb74677cd7641c623ea47a6d7bb8761563a04838375e1757b7 +e827c23b02c243e49c7e7fd805b6c844480f299527848939eb998a03bafbc0f3 +88549c9f07289b26c2d37be0dbdd3b7fabde86645790468c44d931ea2e0a6bca +3879e2dd2b90bd67e10fe5ce55d9fa286352a1bc165420c9f4c974331e28b2e4 +81599529152453818ba4b78f3172aa7c8e53d805a7d9273ce8e15209d03e2560 +5921dab1f3048ac28d24846b0fdfbad7734888b5c00fb7db59678eb48a73620b +191d62bb11b74cca3f41b56f73307b43549771a01ae497067ebb45b077b6b1f7 +79ae8c5b9df4c2a562e6192c20bf51d0e17731738c526b847fe5e8f1a260f963 +baca74b4dc11aefdde4e916e7f2c298094aa0e657f61807e5bc3e09576e182c6 +4f861cc3c48157ea7d276a6092cd4e1861c208141245da61bab3f10544398176 +78bfb0c6bbf10e818649ba1c735be3337d27c7440d8e2e67fe5b9577b5240b45 +e31ae394549a419abea548130cad3d978a6959ac4c921acb321d2cbd71076d84 +91fa113f6bccc3a68ff3f01a9d3b901a8dea1d9d3bf464bd9d6afe82efd9a61c +1bbc83fe71ff0169147ee8bce5720ef34c87b9ddd0919a32660c0a895cb78e25 +5ab066550e18e080da24286d74e549d463b36226891589bcf820e37f641e36d8 +990b2b3047db62b8275144651da91f77422fad6e20fc64dd9ec20d76d2bb5d63 +8bbf6561ddf5bc5da5f9e3b95bcbc298f1ce3482f4f5caf9e7b69019e932d062 +b574892c8956c04e27154232e8de101bbcb5e1dc95107d50c87a54d8c08f7080 +a344936fde36fb7c6d2c78d8b0c508ac9d12ae0432463d990e1d2ed99fb109ea +b2689b76377735af4f7692c65c70adab547c451f36632172e6132b1c439d5130 +0dc22f872aadec5620a4ccbd39cea9189e52ee7679ba2c34275e80acb7fca1bc +d587441e8fcadc9daa5d5760155134a71bdd5f46cdf1d170eb267d0c4c24a0fc +a25053b8ee96f3ce18947f7545095a8e433f87de2749f5819afe661ccbad593d +a1a64273ebf4ac8f0ce768ea5a5860503d60ff8854e254f9e8734e8f5237a681 +b00e11783098dda2dd845e8ccb8e83447a42ada67f1373702f54875b988557af +5828be45e9241a313053258609ecb3ed4213faef26c5fc806ae24406e5a26329 +63ee3a58428ea2ea140f2a164b268b02f54b2824f402eafed5050fed71744253 +3699c1bfb1e69c4a873839b4c02d6223a9d143eaeed0d3bb8d0ff90b3d4eab3c +72e58287584e6802eee8ca3408a6c80e43b94302ad59286eab768facb19823e8 +dac4580194b97ecdb9d5b9f693276b01dea7eb1b2834070618998a15193e0af4 +5a310ce8d8c59a453ab64a9e470d4c0bd2dae51f753e407b49e50df65039a9bc +966e641bae1c535f0345d4bb533e1079cf9e513ea72522d168124187d55d7f01 +fdef1a53fe1e4aad16bd2cbb42c961c1a61070a6da932311129af9cc5e5cb5ac +bf69abb472fc144a76c44002dc437884e2270b21c1a650d2b70955dbc2b62c78 +e0c3ad81cdf119e76fe5540eac22da4417b9ff2cb876886e85e2848773fedb68 +739165ae4111bd7b58c3adb86f6a6f00e960f96109a5983b8ed433da8507b440 +2adabfccd145ac74b9485c7ec9e5212e7c4d37db59a90a68e7577a8a825a0e4b +615c281a218f43180466ea3c25b164747f36b203c3a80b6eb26129a16735b00a +049f2b543f85b6b6ff54352355647e76cde28eccd09a55221ad9b57eafe5aa20 +30122f630a712ef443babcac57f142b0dce30df2ede17351494e9ae8d0143dfc +16f70fa7c11c7af558ac7de807f25d157ae5337be8d725aac876310e7b3bdd4b +f86fc1b504c71a94653d66cb05c533fe665b4a551495b4fd6b0cb23a909189bc +bb85f5f5d6980e0bb50abc54067d9b1cf08d38618aeaf7c7ebae7d16f99fc397 +71c190207fa19b457789498ce47e4930a755ced4083f21f61fb10aaafc0a9f55 +3b92036687a1515cf59c7a0b77e29c6963909824a2469889c55afaa184075740 +deb99f0e9497ede395a90b611a753f9e6f370503ba419c02e40d34fedd443bfd +51b6e66b73e4f84b670666738ae8a6c19bae685c9482f697baa994446335c405 +7963c86a991077462c3b92c8a019a642fa034dcb01282b31037a615a53f5ab03 +095021bb796a9415367cf972e9e26fe339aee6fcbbe03099c5425715fefc55d7 +93a92f5339e84182241e9c43a6c0d0c5437216a180ee0d0141d1d86d5cee3c4b +e64360144cd4ed78a88fa504aadebbdf7a5fadc4883a080caa3e07967f3aedbf +e1c74b080d77999e57e6b8dd15f9e2a0a9b7e71c0f8269808470be73f75ea80a +a942d2f85a5a9696e2ae026823eef06abc4e0b2a2eaf6fb4f8089d178b8cd451 +f6b4418f979bda95cb05ba04ad93af56161f4abc6c2cab85113b610faad49c09 +264c6224b5b7e67f7ea32722ae612bf65bc9ffc968408359f7d6cd6c336111f8 +bb9b5ad9da24110dcec5f53d5f7da64af247cc734924ebd6656e6ba6c729bc2f +2fa1946e18c2f3a72de7fb6be038d89dd4e2a7d49c5a1a20705a9b75de20cbbd +ae5fb5197fc51e087c1697ef49add6f6cb3f0ee32a0a3706699d61f7a6f590fc +f07d10d799e420f97b256802be061b3df4ae10207b9af189edd53839a16d1536 +dd80db57ba1747959e5e43e03bce5a095346af5d8793c4ac498b51ca74665549 +8a668ad5190ebeca1945cc459e6cccb4de74a6a5060de3180b3314ce64e24fc5 +84f7bbc090d2092dc52e1bad04359a06552e3fe2bcb84ad343019b5d2ec92218 +f35705bbf651388a3f1acd43bf99e3772345bf8cc5e4277fe280ae74cdf2858e +d8c1e8c2a6b367eec2d4c729169503fa33a0c02696e94f1db57031475f039c9d +4988eb6a0615a6e4c367d680fedffd5a88f27640f15562eef0b474dc8439a107 +2ac151a86c8f88f6a8cddb2f66e771cb28ef4fc5f3f887318709afe060e30b35 +ff818ada4939f0106e58b5026e9740a32ebf5b430a1bd035a7d720fa474e17dd +a0d48723c722b11fc87069fbb6389080fdef2f0789411bcf4717e911c6091899 +998af6d3374850930b49ef5302a5712fa655a0c530ec885aa823c53522fea326 +747f5964b35c642df805c054e84fe8e3cec0ee3aa7b55cae1664a00afc75071a +3b965416a81eedab12a70f8454bd2ba7e641eb02d33e3efa56a2866be4670514 +464f4e7945e651efe8b484297451c166b550ab5419a7ba71bf2079f35969d620 +ef974a7911458c4d6025101d31e830ff9091a349dd2b7e57b364988dba66d85f +e7438bad5830d2eaab8dd2fe65bf1d2e7899a912a251f78fd435d1e96daf8379 +595ee7590402385dcbbe5b1e1dbdd70954b615d17f33656358823102b5c44e59 +61a233e3148f069938d077398cdddd5648341848158367b9b5fa418af1f4ea9a +73226d662b395327baff3213feb7cf8fe9e8fa81beb3b9568c07ea243cc028da +e678f99bdb138f46671fec959519def6d49b55280dd098af3d92d15c78b35ebc +5b3b8076886fa2f2f33fbb4e3c59cd1d88dd5e033f8d6e1e8dcfb88422dd84f9 +1c14f4493ab16ce2b2c274baedeb6640fa980e15568db8348760dd5225918ad2 +a82c5bac1a191990cdbb53a7692d5fe2ee97753ff305a1495f7565f9e112e948 +aeffeb0f3d141397f7faa4d435f9d2a6d39cb870c935a73c418a49884e9cf95b +ae30ae0a8788161e6634a9a1c933549f171629db2e5803ebf37469736d0d455c +515713f83d5fc6a4961110b0e730055e84b2cccf12f3b70bc9132527241d62b4 +1f4e351af1782c55845a2e8625ea2f3522c74bd2ae224e81fbebddb66248e7e1 +b0eb8fe498531d5c57f7c89c680b9ec01e1b17b91e586e09d39008d85659dc7f +df10c7f88eb18dc415182a0ebc093f2aa7c61b6275fb117d53ec839ae09f3238 +be93beb08aa103cb6ac517923d146cba418342e6d2b0126df99042055285522f +681ca59e31aef9003f984c938a0eee0485bd052c96297cde1d0c2956911a5e4b +eb5e7391177af34d2f013ea6246823240b0285c0100f997796ade58f393aaf32 +d7535416d8e2bd6128a625adac422d980935614b31c4f4283a056ddd18fbf92f +4b95200f71461476817b3019f736c5e2499652f368df95d84d6c12ae63248a45 +5d751c239283dc6e41848818e0132a21dd356a1a82c5adad78780575ecd79a6d +e3863a2faa359da6ad4b24404a85c3f3d4b44bbec4815e6cc312f15e3431fbcc +72688c0d0609fa5562112ab19fa6d0d33db861ebdc2e10d6740fb37e0cf0b19f +0594c7c21f471a309709c673368614b08b43fe774eb9b3ace8e36a1c84b2b14f +97db3e955d0b699c73f19f9be0e3134fb93f48d33a13dddf54ad32bcb57137a2 +c88429e319b32876d1c1f731fdcb3bbe66e710b0029ebf11f709363386db9ceb +51a04209c1df5d72af2af52e8e210f3e61e6b7244de2fa16f5727f5bda340b3f +d170b7e6d209fcab286ade512e7bd871cc7ef906108ef5354eeeaf15510ca21a +b49ae21590f1979a8047e27d6fb36f27b54711768d731d9a1088889dd7e807db +7bef88c2b025f9b102d495f9e648fdf323710e48b3078d454b60facba9d6bb2f +bfb67bc9113bc8b3e3517e23651826ae49ea58106a6832cb4bf0e2d1e76fbba0 +5a831c03c57b7a08a4e68e489f5cacea1a5cf1b6f7ca803276b8b3e9d4c3f1b0 +ba8514790b9a6cb817ec519da6fd008cc5e218a4c1efb070128fd86413967a61 +6da594e4e51d53df267660b88114d834406d4c6421ced9019bafd1363e250719 +e25bb47114a347144e9e5eceee02547086409f0b2a7770a2e7583234c5126a14 +f48ccc2a2c93ca07a61acafb14171473c210194a7fa23d1ba79e58e5caf3f907 +19e8ca3bd878d6733e6d1fc9c81c790f6c40df4f60c7bb3358e6a8529435176a +c111b9e8b942866bf072093d9245dc74f153835cc0b944e24bc4bfc9b097c1a0 +3337a61c255fa78b88f2cb21d9390663bcda7e4630fde2af54f869e0923312fb +6754efad81defa6dbeda821f606d7a3d6394a214389fb9c0c6444b95ada21660 +a3fccc3e3bc7aafa87aeb5efed1e0dcfff45e7fcb050f773bf757870ade8b058 +b29ef7b416bb6cbb58551e094f6df43dd5be9c297a328f7f45b97c0fa08e9ce3 +3d8010f4fb0d93aa698bb117839e51003616c63b7b722ae3e610cc10e3f750cd +a82ac7bde07a6e40ad6f5e85992f7b4f2aef98ca130adbdba0e4a35cdbcb5dd8 +2425c4e326e1a8ff4afa85ed6f6bb72dfc693b8a2f660afd8dbc430234f675a9 +83d2602c4b7555adfda22180ea596710cbeec7d0870a3f51c8dfff4b670a4370 +bee51ea340d7c9558a6beccf5dc0d96469fbc6e7484b0e71ec6754f00561fc23 +9ccbf9a2fa7499f891656c0b5c79136743973bfaf83473baab00f070c4b401d3 +d756e0cf99eb5adce5da8f7fa61b0b5b9b96c1f56ee7c5b349ff71fb4a689042 +a92a524bb164bc6b7c2e3e8c7e5c55f90cf636db11edef43044afa0ee88c3057 +0301fa4384ac552182a2188543b8c9c61bb246ee40a98a186f5ccfeb51509826 +c9a6bc1d0428360491be30698d67532446abf86620af529097601459187321c0 +905f2128dd06bb0beb2455e58a920d49a50d91e2f3c5cde339d497fc864ed85f +4c7cff48795c44966ec236bb7067d3e639b4e988df397b3da60979c4872142f8 +da61a08f104f9a7970decec9f5dca99b56755615f091039d09ec9e5e419c3b6f +87551de0751f550489190b8e2679b8d6170a7a58ab017b5f671dd0610863453c +086d3c7b085a7d7a84d6bee4ffe9b923b638396c2e76bbf621b667d6c728089c +40379af1f0658c7b0d1904534f244a9de6feab40ee214487754083d08ab28e7e +c9fc8b30d5503e72cd763b703079ff00d7d1d6d47b122b8b7d51c5e5e70ab529 +56c02c44df0c227861f6548b736dad55055f5a45993418edf78b255780e40959 +f5b6cf76b34be9518738788e2169d2f9a6cf4494b3d3088bc453fe36d03d615f +88f21a333424ca8a8be607a0cc9f605e29a38b2e272f6475e96fa4414dc4bfc1 +098a1114939e7cfa127311df21cf8c1f0205cbda9c6d7eaa6c8ae2124f75bc0c +1ceac501126f03694b235d0bb992ccb28c6d8ac62653370b1b2e05e2b959f6b6 +2b91bac6e4cced6a3010630b32fd10a461eec219cddbb6bd4e59829b2a5e8729 +33799a41e25cc0461151421fc1b9cc710aafabd299a540a13b79a0b26a2607ae +cb385914dea5ce340a8f5ec1d0d48d567fd0e9bb418f199e0b48d3b98ace00e8 +e5a18f0628a5ea1943a7a1d25a12c06e9295d149028f06c1cffef016549228a1 +a7f6a277745fe5833162d11f25518b7c90f7c3ed8f48e9e4c03f4317272193e8 +f29d3e1b29143b6c81ab73689efd5ca0ceb588bbe8b4dc37c1b0511d56f3e94e +839fb09514300bbb360839fe1a9d7fc42a7120015fbd5e649886ce079565e087 +2209ef88bc23220c94ea8dd4faeeb1f8ebd2b445a9b385f1195cd5350292f4f8 +49c2c5e51869a9ba79a8be224decad84615cf5a57b5341e9165c772fa1f6e6bc +7b43e0d677e3da80dcac64a99662cad2d814d306516cf6198282e8b29f10b2ca +4eca2ce598c3f5d278b522b1afd31531277e9738f59d65fadb73afeec3f503d1 +10ff4d0fb56d41e1f19806512b4fa763c82d0776381e73356df6016f77a6d420 +a3f9d20cc636fd05d18618608c04a42cbea8c427fe949618678014513ffaf692 +ec1f0ad07a18c22bfec4cecee3fb03d5c769221d8b81dd0eac9c358b60a12b8e +956594fbf42eff07765766b0699a6b0809cc5698b0d8f5e84e572c67971d780f +bf8f6c47671cb8e6237fc97809679460db5f56029aec8a9cb8e1687e396e21b8 +f4be922a6dff8c304c88f874471f141a6d2f1f4433e7215e9b9b9d9e69bfdbd2 +669bb7c4cc74c57a18dc4684a0bde8a533d5fb362d5829bec471bf3c5e4e501e +ca0ba7e59fca48afb22f7c5e032a85c310e067a304dbf8b907a4b6ffbae41343 +13c222bc8e3f06cccd637534e9a2d7111fcbeb93cb409bd5153df47d55501f09 +4cb68921e9b0c3e5b896b711cd63805f14396b01ceb0c4f44b1c3b91032a743c +169fb76dd413022a3cede0b76459c80fc0cbbc92e93295d710e0434d1dd5a11e +fa141bdc49ff0437a043e80ac0f8b97f8b42a30f034ca4c4981de2af5d37b945 +483f424f670cd538e39467cbb0bd2c017c91a79df4e75a4decc69aa2cea81a80 +a4d60816ff3db12f131e4ec1c5f6758ea43bdf51e627542e48c7822de7201596 +f88f85ed853538986b02051308c4d15db9d439ed9dfc8b57d320b512c4e19719 +23ec398ece1ac4d67fa08d723072365fee15693f552a6022147e64854c80ee6e +2bca2879e42cdd7103e83af3b815f31c622f0e959ed9f6e9653690db01dd1944 +c50c65902655c2158a74b7bbcb856924bb47056d06e6c6d3ccac847bdd2daa9e +a080e6bced3f45129b258d0103fcc61c8671d3f4297a942d5889738fc0c5b9e9 +770e01e66a90d20043207dd9d1d32d59933accd1b92f36f1401a8efeeaab08e1 +e0a1c1652ef46fb45c78a331673a5ffa2215357ff31493e896a6fabafbfde68c +2fa968080b6ce48b8768f8abf9e9e0311a8725dc91fa78c9255e6469de9f71b8 +b88254d0099466575b797b6b0ca3545dfaec1a4737fff5b10384b426b9dd2a1c +0c7bdcc13c5d3d33335b8e175f5a5ee4a9545f9842a1b202eddbc4d370d03385 +00a3a68d775eed0f0734aaf625f8ff8aad07cf06587a0da8bc372a1d74b6fe6d +4da74de83428f0f921d1df958c0d9678651a3fd9fa2b01cd4213dff86d6e1087 +56ee8c5f6ce36ef570c886a8ecf12906184a6ec01942d1441706cc2e0f2b3b04 +663cf26eefb02d7135b6bf08b45af4c739a518bfd5936fa3be24d5f925ffe033 +1c1423c238fac9dc9d109b6c0c552e69c2cbcb63676b6719a53bb1eee69f6c50 +eb0a4af9f72a78593a980a509893a7466f88786c75adb5dd58202b9f4d84c2c5 +6ef4f7b51d3e80f5f523913cfab5cb1d66969843d977ed8dbd985777ecd6627c +5965b92b66a29078f604cb4e2f8aa35c7c6d3e74a7136fdd60f1edad2095dcf8 +66cf8027bbee7a0a7e1b481be27186ff55e06e925613069cd042a7a054364194 +dedc335b28764371159ebc0e692631aaa6d2cd5c2056ed4b635d1ce0ad07dbbf +c7ea953d680e2edc4b8574ef6b564505e6bab472187f074d8af30277e4c7607e +358add560d692e16540e1a82793212ef5665ee181d9de6fb9827ab6e6433f6ca +fb5a3d61fc7235d77fda86699465b6f48ca04aa9d4a6312af64538c666bdae2f +ed90552e0f29c4f92538680f0cc83baee4d2ba3db1e7bbc25d9ee1fc1245c383 +1251c5c590a5e9a5b163d6f32b39a085a1db1331914022635369237a0873cec8 +be1a1ae8b586a79a914b526c39568063abe512a953842f73e026fc495fb54022 +e992ad981d6cbbab15d7c3a0217567eb1ce3ea2fab493545779dfd28ebe447ed +4bb9282134a71bd8b9b544a0556713dcd53ff30680d4189424769a38f50199c9 +40963243aaf3968b8a847047eedd2b4561b0992bbba2357a60e8ec791d69e3dd +45c2d42bd71710b3bfd0a237c056c0e9131c83cdb4641585e993f0d5bf31c638 +571fb036134dcbdb76cb75a47bef8737896e98182a0248dfbb1fa277d91bcad1 +81f84c195a5333be5f1b487c9aaab979b2137d92ae6c154927b98c58074ef0b3 +a05134271fb5e5b64069428bdfbc978d27348362fbd7f59b2808d39854c8a428 +afecf18e57e41d0a560376addf2dda48e5baacadb22db19c05c4242e5861ec66 +95c7986bd6eb50107a932126b0bbc0947756bc4e9c6eba65748b49372a2d314a +dae054a75fe08472e6c52143aea3ed5c8ecde25a04a3ae67b44d2075563e3571 +a135a85e2476c7e247d3d88599db975732808e6290cb9abdc8603c00ac9b3fd2 +c301074b1fe24d1eea871b53df0ec6b7a35235892572069ad74014849e3ce2a8 +65be37d16bc8f40568e210c6ae17488a7c3407e9d51a2f6b47b588df46f7fee9 +f5bacec5097b3b510012de233e188c8e7881cc588f9e5a0fc393af258106ce22 +4e0a5b64994e138cdfb80f5eed656ce0a6396ca7c34a0b20c3a363811c9288af +f5cfe49e3e609a100bef4517e4db29bdc6d2760a2d53664db7d69625ece02abb +7ea7cdde7bb4a06a8ce4ac80845db5bc47bcfab212a5047a4af6fa720d19559b +60a4f0cd777f4abc0f6c82f58722418729b9fbfb3a7deb2d71501448370e4c52 +a8760b15f4ba02151462880cc71a4815647347cfe964d906e7736cafc95c19aa +e4423091ee39af6822bc9d5a25ffc21ec5351598a9bb79a9877c4dfa18bf47ab +c45d3900fb09767c00daccf4acb15e0ca920d8f1c33d2197d29e3b2d663fe40f +e504610a1c109a6c803faa220d7efd983bc59e32cb063b5ba2d81050a03213f6 +9899171ca3c2f03f841fccc328d247d9e081f300b65522d75e18c07c6d55ee35 +be7d1d93580a8a5776a607d7b682c088ecd3b22e4b11feca0f8dd32eacbd1937 +984bcb06bd906139dd19132ef0be0fc8d6d63cefe29cf8466ad4bddab6451fac +b87a956c0cb0864aac4df8b378a2b1bcc07e8092c84d97e27ca5fc1f4aec5a7c +331086227f2723971a6725c22034e194c6547f97608dd2fe532723b1ea90276d +3cd538de9b07166b8367dffea73b7be63a649404d1f088d2f3092f73b61dd9e6 +0ed470a69dcadcd5731d7f829f0923b9ed0932cfd508b4abac5946b1430c081d +e520822cbd5c06769bfaecd4c758316dd00769c4cf685b783b929910304ad037 +e407627e76a23c54faa03900f3fe3b8be4a276a1d2e89b9a5b0a23f5b88697b8 +ea5042bead89d5f0f9ca9ad5853d8be2f81fa92591a82834d07342b634b8c61e +eb75200651104220a9bb67486ded0e525b7f8650207e4252d0bd202ff114a5ec +2f9ddcefb11bcfa83958c6ab7d96d6297de1715c0222753472c681fb10473574 +42d4ca82fc491c43480e98ba5cfaa04eff24aaecea5e61c0b957f5a51cccc0ef +7add55c709059bebd124c784ee739652d57ae8214c310923be62ef00cb1aa16b +c45516af16f39bd91b5e750f3f2c5bcc226bd394b97eba2ef9579863e4a198c9 +fc2c7bbbd53b0fbf498e3d6b2f88c8375c30737ba7de7b95a101774490710c89 +a72599515a552aed7488bf31cedd7408afdcf4bcfa4ee8a29380c1869badca78 +e7433f74a9eb522e253b4432f0248f0a944d28999a694c3880f72acf16196c32 +beb5501174266d559a0258847a088edf3483fe5b7087ca78bd73a018d162fb4b +236220f50c94797b15571f7e15a83b681c02fdb733e7fe3d1c301a1b4b28b6ec +75702ea2f3f90fd33b6fff5bbf30cb1a3039b8a869a82d33d8a6a83324f942ce +5822485b5f059a795521d17daef0f2294da3a48943eeddd9e22e5712f77a0043 +a9e0d3e29f10b19f5f29ff7471e02cf788cbef07539729822f3cd37dfd9febe8 +8310031b1528e0dd1185ead7b1a10c3a69f54ca2272af2d86c332572590a2c82 +deb80bbf41e089bfa6006f2e2c16b2c38f264b0e4e197f235713a69274fe7e9a +c36e5ba7d8d00a709b2b02075e88413ff2f742e18c0178794545bfd111de1f14 +a5367c393e9499a948d8153f9dd219dea51d6d11e31727bc74026b91f62880d7 +ecb652519ab09cc44d5ccfcc825b9e0b408a45961fa9e2f562ae07f626fca598 +634b6f6362694144643ce8de08543d7fbc3288642bfb77b6f11d7b36e36835cd +11a0e946ccb6afaf0829a6838447fdda1cc1aad7f7a17cffe6863e4228cff4bb +a821483c181658d5e2de37f339517b674320d5f3d1e1d9f9101d92330ae7642c +5ffccce22ecf4eae5a726f166d63e507ff4df128b483d793024cdd3369154932 +3f9dfaa841ef566043baa8e42cfb6c4282ad4851c410bc212c66bd3fa7b82cc9 +13407c5b7923404e1f5a6730e4a89f4a3ccb2f325136eeb974f7979ef4537923 +1d38a1ac0f7afd731058e26be517bf115420537dd9687d023bc3b06fa75c5360 +483af15f248351e9c7cc0d0b00be1ab7d794f75bb257e42740aba38aa7c6b9e5 +331a0f84980917c22ce7ddf588937237771b8ba4eda5fe92d59b5718086e6d29 +0482f9f0135758b74305a64b6fd020578e1b4e67398f735d3b9604e1c6d75b8b +f2c5c01b83d0845b7fde820766898aa22bd5fa2a17172c2f72ed416fbe93096a +af54a432e675b1731ad23885d81ecc5ac94369a96af12c54e95e01a1b876b8cb +1938979ef8eb4100da5c2e522e93ca0bd471f74c8267eb3682273f2f2044f323 +e59c4b7df9d75f769d6d998225eea3eb1331acd1691af7060ed0add8b7277eaa +adb47c982491fec33655c7ca377d545bd24c02afe547c85c3ada798c9637a64d +00db51d5719c73b5c919d0e8b33c64cb3ecf9d25c01fc6f09c842577d19eda47 +739ae84cee865ddc412abac6d234ea50075fdcb59219a703dfe084bf8c7d5c05 +a73c0d1c9a59a59891b5111cd78ec163fded47ac9152f8eed59dde5ac069eb13 +fdacdf7bbe3496be8de28c649b0b4fbae0355f4e50d7737b1ff07f27a29505a0 +fcee561f475fe6ec40b1210fe107326bdc385417ee5208ddbd3c2af8aa96bb46 +52d585a9f3b032680f158d0b73e380912ec64d3c155f78e5f5112a86f4d1b7bd +37df5eb4fb309a4d5fbff180e691f86cdc643af34e7b1f572b66a5c98513dbc2 +bde47fd000698f48c6b58330be688e375eda117106318f651fc203e260511262 +b36fddf9289d23c31dfcb94e0216bfc978394851eb0eb2be29839397e6d722f0 +3b7965e63090ca190812db054eb42cdb71de31e1d34ba12af9df9a2635bf5e6c +9f6c3789a4795c39ea94b96cbd0b3a2550cfba4a4321f26e0bcf41a889cc905d +54759f5041bd62b9361e618213ce8d003a182c47987c1c7bc0fcef8afe0689a4 +9df8df3d0d2bf78a947c645d8e3035162ed2e888eb24d17574221348fc4ac4bc +c8cf123a374aa63caa422b4f09a918b3e1679ed9478dffdd23a24731dc86507e +4d1252f53a99c54d0accb9f9c2973c3157de81fc5676444a97f32d84e0060b40 +f1cbb0aaa97acdcacae0d2bc3e7584c54e1ea8e0af04ce1d0253639267918ca8 +a25d90449cc36a4a0fbee9be49ac75ca4ed54d211329568703f5eea3a5efd08f +0e5a1dec3ce9b355e874786f0db3af929b40cc7e667b96124afd6ac6acb9caef +cc9965b21e85bef1f56b46328fdd40a273866cee81d49c8ac7e44f5cda6db9c6 +c7b9f2b2548719baa620f3c7c28f1e866afa2d29f7e9a47ad6e0946fbcb32229 +cedb3531ad30d7b6d893c78ca52e6c849aed87eb6f76e1fe81dd7223844bd7ba +140ac8d8698615c8f10da9c33dbad445fb6da3f9d6eccb3889b82fdd8e191e7e +1a5a3b21ccedafcffc0bedab572bf0cd3b328d661b289103fa523dc83d89c2e4 +55b6b0065db2c07bdf17a1d252872fd12df1d772e2db444d90acb755c9e05a2f +e87aeb0fb2565e4eaffa0ec4f684b45ef6070ec34c4b6fac5889de6a2c477153 +52a28455fdf77693064f628eb91cb9cc8b1e548c9f5ad14b32d686ba0b53e50b +520c982b59057809eb0bbff570435f18e02ff2b2055c48459786dc07709731b8 +f336a128fd42ce2bfca20a35ae08b2f32a9177a3138167e24c753ba197c25f02 +73f6deaa077f58a457e9aa2f02616dbb1c5b4230906be1a031c2d15250aef6a5 +be03c52a2a97c45db68d8e88a1bd04542d0f3859ce59ef5ef5e817181b1dbf28 +a1534ed5903b89a1f9fd1e61dfb406c4e04325c4fd26812f8a3daeff3ba1a473 +287b69d6746ecf06a6429775fdc01f1dd9b05030df9fac25484dc90561cb09b0 +e4f5e44d12e23412bbb4abcd409af48277d52771b94d47835ed9c3522fd1ceff +9dd869fad76eac27e9883c968a274a8aa8f9c82987b7df6b14fb8686092c6ed0 +db02e4c3798fd1038c8ea0dd57d87bb57a98f01e06fcf02cc080ae614b345395 +e9b6134db5b227ede1241f0418b5285e7367f6159d79d1e33e5c614affc4cb03 +98e52f8a6e1fb5be3648a0c15eb8ad5b9b113cf9cb139cd232a56445ecee98f8 +9c57ef7f4d46a8f43100e53573a63c58dd9b7ad6b1cbaf87858cd1784391f326 +983bb8edc83944478fda9a0618cdf26db2ff464544c8ab7cf67bf8cb0b734f84 +a67d6d988d011b2a96f2828656d49ad7b69958ae65a8cbdaec32d0fa24401fea +521f627cbbbd741ccbf96f1423270b1e7a45a3d54cc209aa93ed95b5fab1d6c9 +92fa46521439989a9be2e907a3f5aff15bf8d6bab0976370c428bc169263f150 +4e0077be024f738bbe3e3b29fc2ec6ece6c0f074d0534b4df7c959f133b257a7 +69a2c3b5a55b20db9f16ea04710378edecf42b2cb62745a7eaab3635f7056198 +7cd38cd0481f2b4c05340f00296dd9c76b6a769b540c3a3f9dc9aef14697a424 +c865a1dfd24f72edfce5570b9422862fff8e0b0c2f28067ee56143a0fa5771ca +5623b594a9cdc4c30176381d850916c09bad5df8a1f06cc4a126d4251e3f10f9 +71f7acd0f5d69d85f2c72159b2876603f8e12b4ea8dbc33b83c6853f0660c5cf +f17b131b71e0aaa276544b7cb9fb4e68142a788ec4d635875584798250ff6c41 +92cf1bca3ecf4e61c3bd3ca4f538d35d2dde5c96358ec7b8e7422e3937c23f6e +1ece53ae3e46dea01a9771354362cd79b0c38cf01a96aa39090d50fd4267c551 +ac8eda79ee3b48ecbd96edcbe51e62972170c023056a98fd22a47bb6d47adefa +0155030406b1bed8c86f21d14ce87177cc9a409059b71b1ec628560438fa4de5 +395b07111bdd2ebb7819311eae89043011bfbe0e6099bea7b2dd41fb72fdc444 +928713aaa20909beb343c0e4a9b4f50625c045f727c2f0f80b51072d05c0e50d +ce7f1d5db47c5e1b34aa7a294b622f02c656c6a588580e3f3ad8489fdad9d533 +7de5084be37a053b6b689134ec6e3048edff621ead02c477bad059faedde1c24 +524617d2f2f63beb163b9c3d5c6d30516dd439df499280e536ea3b7dc3cea458 +a15538426d97f7c73727680815380fa09bdc10ea08ba417399ee336b14a78d6f +e5bd5e143382bb654b7ba7cad38a5d6228cde2e032ad0ce589a3d5ff6ea40125 +a2cac3457cb289f0cd8a509521adbb5ab8bec1b547ac56b8c748c95d1f2ffa99 +8da7a4a73b75e2a61451b2ff161cacc0a86e332e82e008122944ee311ebe9d6c +be69cee97ced7a468e1cde07406153f8057261f79a9abc72dba2b98f260bdbf8 +916505e3980ea47c0562522743c778c5d0144d3712fefb3f00f2614e05439e7a +144a5c987efe49cc1cffd32ba11af0be78cb46e9cad5457f7ae5ac2d3f014d78 +99532b927212fb7447d3d7c00ee076d11dc6e85fdd5272c1b57ca7607ee01322 +8e6a3e3f7e355ea6ede5a29afbba8e8ef6d164cab77f031ac10704d9de3d801d +1b6f46e86f19b3a2638bf8580336365dcfe729c5c50cbfa2caffde768f3457d9 +43c39aab3d72d3e9a1eb578e5ab84795fa066704fadc69f4a2f5d520e953a323 +d039a4221fd130a20fd99adc6a5d85fbd04887367747ec0e706a57a4e661802b +981f8a9ec42655fc147ffd853632b1d543c95ad8accae230dd6ed879695e540d +bdc5ca4007ee887de1e222a2cd2468d131af76e5b65bc1b3b8129fdb34a223c0 +e3bd3e36b8987c53bbe13721a84123b45010bc2fae3428dabdc7027722fcac6a +9f5c404e484e4e138aeab42f6c3f14f484b0e0b7b71ab35b16167dcd4fc1c16c +f43fedf12be8d55076188db43b9d51118c9dce37f1a5a646517f835cc345412a +a50b9fe6e9abafb9293af40e5c7026a1885b3b9f8c1781cd5e7d5b78ab080c22 +d90f4b63ec26f080d181c6f78734ffa3841d1c49589542aa237548c36e447d49 +d3bf16b154b60a2be5b109c1c0d93937447a855fa815005dedfd4b974dae0702 +6386dbef992ba10ef2b2257b5d4cac6bc3240255c22ac621e51499865489771d +ee81713decc232d28d140cad1b7451d2c67922935651995023eb218bd1b04368 +731e750cfe38a6e95d0a6b9990f0c384075ba7d0c0377168aa59f26d078865e9 +7e4b0ec2a46a5f910ae06ffc4150fb56b2b12ef2deb837b599c8ab5435f2ef2c +a8a4b73cc3563308ed507ef7d97c094efb3ad015f8f72a60ece2817fa28ad871 +62eb5679ddc98c48aa4424a11004e325863f5aead4dc83d4d486e5c3164250fd +53f7ccf74fc079b38c0e2d8a1f50b691d128496f44c8f3158d21aa084529de4c +d79c0b517bfbe8297110cf79818dc53ecad72be6121d975add64210fbefb21fc +95a751fbdb4e353a8d8b0cb4aa0d744a907a8fba1672d3e0f121568e1db30f50 +9170a2c5b2d87514374dd4f87692ae93d2cc42670c6fc1b64cacd5b15161d3cc +e14531b6f6b60ad195ec96290839fb3160e6ba6a30460c77dbd9aa873fc993c9 +b3347dad1e6a400c2d5cb952350d6b37cfdd94547a70005b31ef2b5c390245a8 +916fa1c2ab3afe6c9ad9f8ca46b626c2fe78fefb100d1e96ffd896a72092cf00 +012659112651822ec9888b21478f898f3e85ec9c748d8fe396b786a7f145dd6a +53304121fb6fee88877147d78e5b3f0548820cd7e838ae0ab64a4b401eb47c75 +1a4a40a58c076df2d26cdceedf7c87871f2166f575f23acb231224a13b271c54 +e8171e71545229492dcb9abe0a7fa5c4f033b43327a057c62bbdbc7026963815 +9e33cbe7e7e83f26d07eacd9c02bed7d82d45022e5c1a30844a87214771616e1 +655cbf98b4602f352267c340ebe156ed77474ccc4ed8400b7858f60555eddf12 +63bbbeae47c2b0ba526f9f9ff5231f2ab79aac8035e6107f4ddd98e7dffc0222 +69734772e73ce5d190020595dd04d263b792569f06e0b3262ccfcc0b1f51cd68 +16005ef3aa9799ce762cd95995d929ef834b0adf7c5500f39dd823567610e710 +8bc381a572b77fcedffb45faba957262949836edb2e998ebffaf1966f8036667 +4ac02d09eeda5cac59c019017a327f3f3e5a0880b16f3a1a3384d09b23adbb5c +850a420085da3ff503d74ab9d5399671124830d7cb4dbf2a1212fdb66bca0f7e +06a96205639193396aeff36045e910b119d9d0e69836063b88f67c9da2188142 +8731f406a1939569bc96cfa1498f3fe51315bc01b529cd2808b9893f62ac637d +e09931efb564dc0c8061b4c93679b49efda6eb21cf82fd030d1cb4645b16ea77 +ed213ee98d0d011b6d67b510db7d9509cdb33bdd725fe216c527ab73947e7137 +ab627c4e6bf22127d196a9654997c7b1195510d92f0d25ec599d16836afe744a +d926d40735e6e7a8a151331c8709be8ee5005cb2b2dd8d647e8e02c3b315f331 +1942264d7e04f458090bbf233406a13ce7c150651789dca683bf4d9b5bb848e6 +a6b2b6c19e185e21b3d60227b049f2fc7e793f711b253872322de690e515609b +a2e163fd44dbd7fa68271ebca17b70402f9c62c3f31ac5d7e6304cd5ac3ca032 +ab4641b942b5923af234b1c5be70ad9ba89c9d70ce0fab2265561d47fd4387de +7cd096bcde91bfe3d62144368cead36a1445c641099ec68c90e82d992a3a2b3d +8443b1e0953cece57b9e070468e85a1367673087fb39aa260a0717863d5f898a +705d50c196b81b5292ed966d44fb414df7083ada1169ac5dd9c18a89ffe37c2b +903b8586add36bb456ac0323db888ac258bcce04dbaf6b7d1ca3c8292cb7cc48 +4832b698d630ae5a55b8f6d5bad1bac5c5dffa667c21932edc5e222ce2e0f9f0 +adcc482f1ad9d61dfa3f8a651d50f6d0d4b444ef46cc4fb2e781aa72b13a9431 +941084e99e0d9f0124d8b236a54da0ee51dd8421970d5a25156b620b08c0ebe6 +a752eea6b4b02581bc602ceb93ecc3e7f67319de90e6add657f25e10336c7966 +e7534a0b70f2f72e721619d48d744e3ce9fe6c8bb0cdc061f45c7a3d60d2f268 +7b245741dc56595764df816de17f42eea084fa22c1fd794275866f3de3f80bc8 +b20cb6b81dbd2ed362c492309aa82d3346e69ba39721a74c2bd2052d694eb6fa +1a6fb067ff873d95457342c5c957850840a6934f0aced82cb5933eb85347c43f +1d0db6713c7a1005a157bbbfe10956adadbb5fbdb7751655928e9e31ce953de8 +f8ac377e2e84f494ca2928fa5a1edb438ed464999c49881e60b8acb9e09f3b68 +cc06a3e9a63603be7f3e7a8383fee59a4922518dd1520a4c276f1009b4079d5f +37c1cbed317f37fb1910b6eda695e7edcbd6c0df9308c943486b68c6755e8a70 +4a54c75cddeb6cd99031be4090c229272febc9b12ec098429925321153c858c8 +455595607dab9d8a833f196685c9ea34aaf16bffe9502b79be2fcdabbd6b604d +942e3203e2aa9731a13a2e9e13df408d24d4a5463b2f12771b55c0264b8c3b69 +cfa68ef306e21cf9b891c9c85044174ba48708dbab91448e8afe777e63b8be7c +8ed1c79ee20edf2eb1506aa4edf7bf380e2f38d70d9668bd0ac88d0826985591 +049a6ce668611f5b8b3d42f5ede43cf523171f6e07b78e13ce0567d9345c01b9 +0c6da55db6816f094ebe2f825ce02dcbec31ba9477932e4ea07dccd65ee0e362 +9cb0722776845368c425d3808002e0106014bf9441ab68a574666ca0bf72fcd9 +11d83fb9f5d76112a62a3318139357c2b2ae970689d0edebd317bd9e5c090491 +c06e19450c10d62adca51882d5e36660f36c033dcc6cb21de066bd5c7c1829ef +8f411c25de4a204ac0d8739fdb017c6a32d583f0e5e8c18e754288b180bb882d +cd899be46c0305e0cad550d2a21e4acbce7c894db55a378835efe58869681489 +e8bc0eb09dbf2b6cbba9cded925ee0f275d5dfbd58e74028124d7f0d2f436ac1 +c17c37c2ee56ddac8d02aaef9f28b64d9227f76c64fe0a6a9f7997648b73822a +7b87c827da2a9e4c5ff97ca0790751c3626e91e0391a3894e4231e0355bb65f7 +fb217735eb3abe32f7bbdd503fda9cae0d98e778e5c984b58fadb53d612bdbf9 +20065a02113d039e8e74dad0d80e70df8892dad2dc0c80be5a11c81bc58d4c7c +0aaa74bd1c2406167b632d2f5a1c71307ac632055bca86d1ef5ea68af236b777 +db378b7dfa7e6b8e778d1008d8ceda07966c9357463214dddd2d8356dc8616cd +bb32e7f502c104095a8c9723f087172e31761e3f0aabd40a2dbdafccadc9b60d +48da520ead359e0f4ba9677e4ddd8399483ee5ef0b1e98049cc83982360007bf +3ade7e49079c8cf14a33e63d7887ee7dce4f0686b73fbf107debda634c6394e7 +938e97fb624e74a73304fb8b40df9482a5c81ba2ba1bd78370a46f1c897775e0 +8a3522d88e56d136a8edaa69bafe99426e27e913c87d792c1acfd1f79ee44035 +4326dbe7ce6027db3615058608fd5bb71425bf78fa9f46b9e7d35a484390ed7f +22f85d77a2e612e3c33d18087a437b2565fe15ada3921547c17b16ed3ce8c8cb +68b292bed78242bd17cc9eec27bdccf8107ae6089630660832a121912862e3c8 +8fe2d8390e57acec29caff3fa8b0ca73a90bc00be646f68384617666e2dbb108 +f2c28db3b42e2b66748f6731fb137b4e4735c4836e048e1c36b1eb5a76c21718 +3ddac5d9a88413db7843b840d4f6c0ff6e10c6b5b2742f1f1e00f0e8a472b916 +a111416b218ce9677ab2edba61fbeded37f4d009eccc3fbbd5f48221f373a01a +2f833e6745fb42114b8e449d09ab449886b6afb314c86d43b756d42da291e3ad +6d1298a83035333b698ce0d3cc36c77d43f07c30134df21aef5cb7024cd6e452 +00bc9c2e30e66c89228c5e7d75ebc947bf275f7cf58f8a9c0e081c83c57e4faf +ed055817b3386287f3f55c72c2c17bae66b65d2dc5678c58e515320ed5dc779f +c397797479af0cf73b85689e86bbf917768c722a767558a4c5fbfab268be7cda +872d5d2156287f4f31eb62d86eb4611f2ff227c51d512b57cf0ba46592f0bf0a +10864b60058b134e99760539733c1871b126664309d89d382d131301739e1f95 +ebd91970cb83933406038d2e3af823a769c4f8c975252e48f1b3b2c024906fbe +88850af2af86a055794fa056baeb92a2bacd28420d8bb66e557bf77390ee5b33 +d37ac189cde46af1d7007b25eb23c2f119b814542bb0442fc1245775c7547646 +d2f154abc44351e238b0e5f8a45bd338a06d11a98aa5d63d43310057df9b945e +4fe8e4dda55aed79aaf5f40029ecb046b2aab0f3fd36785c77ccfd8c844a265a +c000a6a6b6499be3dab5012dca48caceba5c78442ca44ff88b422af7176b1d30 +5d187175b8c6081450df333f048c10783582c8173409d09d4931cb84f69b8ae3 +ddfa648e1c7daeb288280de69be37de65f1d99ed6c61551a3cb382144855d7ee +ff39ff890551b0a8ff2966a2bdc0cc6c4932050ceb2461cb97ce67f419faacee +ac1ddd3b9d76267b06d68b72010801919e3fab0e1ab487e67584cddfdbbf5fe9 +8015c0c3bb9495d31db6272ff80d3cddd64b7ac9f3d7ceae6f26d93410da428e +48add0c427b7054fac4d8d4f0236212e7c021192c4d3971f834487914c4507db +5c7dd612d2359ebc1d43d41be072c58c171d2442f6ce4edce0f66908b4ec6aa4 +d47564d23dfb34acddbdd038ca8b966815959a8795bd9a354d06c115783a6ae0 +eed059bf679b5bcaefbfb2eb61c970219d36976803c3ef4475b9e18976fe8d61 +af8837f9ba6cc5c3f775c8c575208ce364bbb4ac4e3154f73ef43ad1c64ca644 +e9244990f513877484acc230a266c4fad98899d36d5de1d88cfab985afe95282 +9a0f2109280cc038f23f19dc1a5a55b1be536a87e6f7e7b52e9f7d3c0610f236 +352b67d6b94d9cadcd112bed83aee29678d66a44a6a2905298915fbdeb318f4f +d7c31ca21ae36225c897c012ad6be19634949a537177e67673ea7a5e8069dcef +7a7de0153848f775a5570ab535b28cf2b469d801247a6f5cc34f4992febd499b +ffa47c06e625b27b5ad47aceaea892b1def2f8607e514644a1dee18f6e033179 +230624406ee58bad2eb1c9acb9e44a2afd57c1134dfa75c27da726a48da243e2 +cae2ff7c7058fadb8f3ff1795e0db17af69d6ecf40eb9dc683a7548a4cb87dc9 +9437c80d59ea0f9f4fdc448f1d70ded8c501eca673f25efe55aca6876a1569a8 +f5fabe666f01f21af82e451bdf6e9a9b37d80c0f3c9184a8bdba645f12fa66fd +e5e5a7d6acf7c96a9ad0b720c926e16ca7dbca1bbdd6cc39239eedfdc0f13bcd +c1df99b5dfa43125747458a6f1374ea2cda5aed20627d655b1bdd36536994ba7 +8dffef0fda855b6cc50120b8930534814734286376f6c8c80f7c75d4500d6cfb +ab4391de4f4887a1b976de5087ee77ed005bc1b3f99216a65cb5c08b05d69f0e +c7c9e41a9b1de7aa3e8087104657b01a6b8a1f562f478c973d195e247c7097aa +20a3395eae9be3c7bcd0a9aba8d3a8bdb59ac58f45a770b333ae80ab4b963af7 +decc7c79af4a3cce10e05eb9721e676d9e1cedbb97fc46e082a3a7b459652438 +105638852b6d436565545983698e97056d9bfbff2a74c4f7f08542f57582e4d4 +b3e216d02b3f44faf09d9bb3fc29d29ea06aa4281696e16e76727e549e35248d +fad3f1ba6a73431b336c9fd18003688e73130014a63a49355dfca4c71379e041 +39be38d6933c6ce2b78573ad78c8427bc4618e78911d9fa7890d29b5f0d5e99a +8dbe6f40c55b7a7f6b0d86e1054badb9868fb54c6db977e941fd4a55e0a49280 +aaa8e594268edfc4bb9628039ead564071d247ca5508a4f318594e3dbd0d6a27 +9b6a7416fc210d8800cb4a2406fb31989e98219417de3a4654fc3132d559cbcf +e0f14d1863dc28c392731a8d8e9fde524faa51df82bf0c61b473dc087ca9ad00 +804ad655e3f27473e20515e79cb7c520c1b2a1ac21779ac6b31ff2a77f7bf95b +3a6b16815634cc59f2f818d50dea4331ed48e96979b2523cdf3cf46b90d85fc0 +c2ceb4ef868a40287152155ffc8571325089132a7a54b6c25760d8db89724c3f +5c97ecff16cd4507f6157cb52d4f454300173f49341fe047010ad3bbbf0d35a2 +d82498a69ac3712ecb297495ce2c6131aac363ed663907787ea21011b78c2d91 +fc0ee6cd273ef5e658b0b5a8d1d27c780edd019e8d9e11dd86a44c67ebee6b01 +0e27cdb08c4a54655d2004f161f6364f0f96c5bb9300d24d1c347937eb3b8147 +86b12b11e47a1ec0f6fdb6b06f98c08a9f7bf1a533efa2fa8037d373f768cca0 +2e53c937b9508b64f283c1a645777153b7125b2a7929926bdb33c1adcee7cb69 +3feba5bf8524d148e8484b4a623c18575dea5e8ea207cbd96d2bf2e33d2a638c +873a0431a11cf0d135dd30c5963ba944bb998fb09301c31c7bbb3ac4676807b3 +0e8e422b0ab663a8b3f4c0d7e2639ddf58fdbd9d360c287b857940cfd64ebb47 +bdccf1faa4b5709ba9734534612bf9a09c4e5ee7480d5c8f03fa6dde63c0b0d8 +520ba5c877bbe83761cf3096d1ad417bb6672dd30ce25c594110cfebfa36d7ed +68b748e4b761ce4f792d940ad5d9bd5095c5aab0ace678f0c758497c61b5c247 +f87559afc15f4b021ff3632f1712f271d1d4b8c32459044f1401a41261d49176 +be8ecebe860a35279372d8c1ddd3d9e76e51a1e7bd7a53859de95d7f9910450a +c1129aa64f1490f31ead41fee51e1b10d1cdb25fdd061efe9504e288c7c93cc5 +50b53a2a887ab74159a4c94b525e265744ecbce3710f9febea3ab8fe47097fda +91398068ae4290dc9941e31615536662bfee4c88bfb0b1999496bd964ff7e119 +493e901627822ddd8e0b9d8d9f1fa341d2eeb23293d5d527621c5453e21d48f5 +f2b0f3121a06365e8efbc32e2457671441c77ebadf4fa73d469f8b065ddda03f +c892f3dfce8ea24adf431e422665477fe7172d7b5dd4316a22055a1ba753b6f0 +a294b95316c62879bef16e81b679f6cf238d200e38ef89d7af2e519b66e96252 +9b84609b57736141f0b183afd8fd31c394b01af80b44aac4637ac11dd93751ec +8768d38f77ef32f6b2401cc350c626737afc8381a96d48118db3434297207f8e +5ddc7a8450d70d0d1a51f51bc9189c1407abf92d0c3ec5c42b836dd954afee30 +fea10544f02635727ccd806fc9b292c42ce439a4976a53e28b826675ef102c86 +edc22d366a38e20977d45419e533e299a087775b296bb6284b775546b15b5dc1 +0a1489629b8bd45c46ca87545bbe0539332ece33cc0c72606b2a460df4e79e23 +6f2eed77eb62563c7c64610a17d72f5861e7a235ecc85fdca33ea8d7ea75ffb5 +ad1418e9b62eb7b938848015639d3836401518d80c54713bb689762e028830e6 +eaf196ac69bdaeef85e1ac91b21d5910cba0de3b357a296cfd798553ff1bb13b +a6f01fa241ee7de8d450059b32180af5d71087e2d2b16ca9c5f42991206e4734 +0537b3d56153282ff59c675320e3e596b13a04fb3b9d6a5eac12ed50866aaaf8 +8a79a4d1209b58bc416b9a273d7f47295942aec7547b1f1feed4496d27a61d1c +bb5fa817acf9bafbd2d3111cc337b709b1273e1ab4bf9ae2bbb51716e3abfe0d +9609a4a0b49c16824da191affb038a8af7f7ea5de1acfb3983c122914af4c138 +8d5c2d8731d0b73b0f4ca8f699a882534e343c3501e21f0d5331052964810d24 +e4da7e5dd579271b942f8ada2c0b3ef7c3cceab9e9b310bee35f05d2727dccfd +25434fc295ffa9287cc8d4e1c743c9d5d5ed32c146e665e4f1f6fc95b5244678 +cb99c834b3ae88b5352475749547f8829170552c6f1042a5f513d04f9b251a39 +c0b64e8eee609e041fc2727ce28213a6feb3e4a59b0d9dcfdc6bb3ab2ef4ea4b +8757cbdee04803fd1188d25be64efd069ebbb26a7aa52c496efaf587b92fbad1 +66acad9643557dc761fbcf7f44e343393dbf4dd57b529af5003d34046f31c14e +b40a68d58521919dd4e588c7c55bed22acc5db8e86aa00cb6a2aac9ed6008d5d +f8e35cb62d6e6ab015d09ea79a9fde04d4b99cbbc32e80f7b08323b519e85103 +7378b65975d2f879ad9024a19677a3fa91998e9a0084cf1b0dcc538b8b2e1e3e +25a84159de16d55c8d455bb8598bef36920b599e09ef99f85eff74dca169c344 +7e611fc0757fde7c4042e557518d431d67d309d7fcd1b94d5c062725cc65d353 +bce84a1f13e186056aa41d9fc420e3c16fb911fdcf3d28452bb74ff47294b81f +e0d67ed34442dcaf29bece98369e0c2af8515780809a5cd692ec8790ff4b4bd9 +ed20b19b65a3fabf62c28749efab8072322c53a3d8e1e726f2eda8c531aa9b40 +4c81f64a0f4c02f3325c97b98d8bd768f1feaf6b66fd2fddd9322a00c6f9ae06 +a8e53cdb4426650273837c96011dfab505117eef54007bbf2ac524dc8ec4c862 +8a67713c2e1eb35dbd3bf55479cf70efaba2351ae1414b7e2376504b953b2523 +8babd80d511b572d8ff30bc656f1e0e2ba49f44cc5640cabcc86ac87fbbf26a8 +40ece37c51d300b55458b4ffc7e2dce7cb1d8f743377e1cfdf2c1f107e90ce98 +bbb57d2bae0fd9c471a50a446414423c55bf7845da511514e200a66a6272aa88 +94e958fa35ea079ffd2590898a7ec57ff8f3698ef2b0ce0ad9df3b34f1c982b0 +b1c527f31062ddbb890daab89955ad2d2743f537588aeb6612f8a04fe111938d +da10606562f96d12ffe5da878a18461278d179e0e2c9cffc3d2bcf287d93b008 +dc05cbb656db5ddb76cc213874c9f86923269eb0874705801a98a64bc057b6e1 +da07a2b35bdf4261d79a6c9015d1a240e451127ad08b765f681c22e87a25da7c +9b64ec0a71222c8ec10c162f4a973f50ba91a2ac29bae6ca812358ef1905c88f +77aa02642c339fd90f3cb943dd89f0d163918990473a58975986c467a0e4eedc +04e975762a4589e862be9f3c0452e5f4c79b29bedb4e6f9e07097fa99361fc9c +9949b5b708e43973409dce0a34bc696b444136b23c2e537f7b63a39bdeae3406 +42bb55e0bb082926ba5638d830ebfb04850e6931d7e9e7732f59523062813336 +99069e0d2010da264a4356a21e783d1e087dba44e8a7d6b2f33f73568d0c1c29 +9b2ee9fcb0d15e0db198d6612242c52567c3da1b8453f07b359de455864e24f0 +64736abe3f9a61ebbecbfc297318aa5b439e97408e2d5cbc7f34fc1743e21a15 +e32c1c935564aa13f7c4870afc6966b765e3767458ab60ab86cafd0874957dc6 +dbbc2aa9df3787b91f8b45180d00beeb34d65237d1c87fcbd819c7f3a5964029 +5c516e61dfcc54b88e7ac546e8b516b2e19b6ab31112e4e6a7e6bca7e35d7e8e +0a42f284c3c9b4fbbd01903d809896ff4450b68b40494890430cdd8117ce469c +5c20bb3d6e448f5b9c794c4787a55a7d34576c942bad4b3801a1e304e0a58b35 +0796a0d9fd6fe03e3bab47f7fef49a2a32dc199b1f7745e107653b2fa3f48b0e +b68c47fe0364ef6e00435a4cbffe21ba10bc3e9f042259672961edfac0fca2d3 +18ff0cc302035a258a1d483a4e5be1de8996a9af430fa67036c387d6ced09b57 +f49ac0de065fe68899f5c93fa6de81110d0b0c8ec81ee3ca9ac74440ab6dcfd2 +5edf82b70f8f2b896ed09a0716271b6f88b9bfb3c997da394849f4eba20c23fb +9f76e4a0dbd8ab7fa09cb02720d6a15b395d28ce75eff6e7237fd170a1236357 +7f238299a60660b3ab74fff140e1c7c110c23e15c2ceff04b49a0b0a51844204 +051d4a670af2ce2cc40995201014a3a31eb4233a575bc7f89782329d65e9e429 +6a7ebf6d7335868fe26aa0c9205a56cd872d01bcc81b78cd08fab64ce4c297c7 +b17a04d161b11bd32a4a36d2353e68fb74c6fee0a4feb0869e014888ec8a0cc1 +6900f2ddabd4efbe23014e4a68c2c046d6dd5f0bff28a77f943c3e0c2fa6fc7d +283402931b15564329abb7fc8219801bcd4ad0e94b5496c6e5ed434215f5b9d5 +4240fa289f520237b10bf7e0c5938006bfb4625a041e8f88d8f0f51bf05415c2 +3518b6eaa4f3951af7f555141ba3b2368bf658ae234bdf75d2d47521be75f87d +c6401c807eb9027f562795b9a38f1b8e8d70f8f3fef7cbeec675001a228e5bd8 +783929ce690c7459b5128eff37f59cc7c67110e351047a5dcfc8f6a0b0348cf7 +c4c7db235f1184f1ef6cdf5b0cb0fc4f3e5a2a5409aff2d63bb27c5e89d1d0ae +f289804511c01ecb81e9f8eb6c1cda53284cc17574cbc8c622c2acc837181c4c +ac1a500a688d6751648adb5fd803034cbf4cdd0265577664307d51c52a2fa27c +099a7bfdd2308330bdac3c73722dac62e33bd85f2f73e99fed06b4c5b89adbca +0f690b28d3c48f643c7885a68cae60d557521cfda5ec918839f3934bf12d2d5f +15b024946ed029bf3597ff21168d1ebcc5007a692f3f0b6ad60ec1d240c34aaf +800095b275513e392d7734f2c2bfbad833be106eb13ffd107a2b4fa90ba84442 +dd7e8e2adc0b208fcbf90d60cbbbdcf2e135075e5f40f619a56d729419015fc8 +30e77795125f33abc9b5d13f36bd6111469237d27932c2dd17cc029650239dea +0d531e13e05194e02f216e16040e6492705850798f9fe26d395ff897be1ea6af +540aa07f85720ed73b459ca81afcfe8162147c4daaa1f0ef51d16ba61c6cbfdd +c12c25bd0dfd75ac6159468de018063acfebd25e46892cabc58ec5da56994a6d +44a9a2c0f0becd895f860819acb9786339dc5f58d4570bc1fe6c44c7744e45fa +ec718db4f175064f274f5d7bb88bee7e7f9e83ae7d87ec6ee2ed71634f0ec2aa +99f1be7ae64713d79e189be45461204340d11a7b6163f237086fe711a1d4f122 +b27fd75b3013eac386818ff12ec9f024d262db2f3ca7abb701d68a3ae16185ca +7ce4a28ac1a376eb5ef7d3aa9a22a2da4f01957fd9d9220404aaeeb93e88022b +59e2e0fb69b7751c7198bef2d7d289960a8e4ed7750cf021361b61581acfdf46 +0b2db402803fde39cacdb8541db36099fbbaf1079cee60a07cd6f78003119e50 +7c5d631af09108c810d1f3b5defc86bc8223b562186e218f5d58dbd7c25c25b5 +6d8b984287d72129d27073e743a949520297ef70b6069d9a78d816e760862803 +fbf8382f6ffebbb86db4944e6bcf5012c8c65bd864b3b4f882b5e8d370cbab7d +d05751773e58b9621e3fb87006cd9b461881f798cf959cb98e8ad6cae41e9ced +20b52a339b5bedd61bc2414e8c1d5bce530803f6280080c834892805ce237595 +bedfe533f3e8338dc4d33292fe47aa831f9fd380314e150b3cdf5497cb57ff87 +8316454bd851de2112dfd5a412690d440a873feac4ef062f9c50ac46185d854e +cd994457db4a2d8f03368f079f5c37a07e742c03f4bf706b88cfdc007742cb47 +7846bea275e3479458947d7af061b0a3a20cce8b118cdbbadf962dc8429d5b1f +30f4d805a0b39f2e0f489465ebacb2d66559b85e887a6ed4f02a1f1726392423 +b5492e71f1748ac7692d7e5cbf8a5c4dada15ce0e84d40a394974e7c3a7e27c7 +0696dcfb4d4368f8f6fd650268f379ef47dee0de45d9655f39bd42599bc2e701 +28c81630470751d15d5958cb7c3b29103d637f59bc222f3413d7fd85da32376c +e16244fcf46fa24cbc95f5b10990a1c42cc87b4855d5e321ac43594550049293 +3b769610f5bbdc9e15577c54123676dedb1e221dfe6c1f41b8bc4e5cee02cb32 +5b14ac2078e356cf7ef1d2b1bab573e642c6a5cef4e02d3fe0df089d3100403e +b5f0dc55bb1fa1896f304b2524d6b8bc6762d352b70f9d4ffdaacdba2a68f80c +286e64cc8810aa4e0dba214abc5a107a60900dfb7674056102e6dc37104773aa +12ed7dcdcde7ada542c5e308f665f3797c968e703ccc4dca38c44d4d9c22a96f +82c6789d3610f1da97a393ce2ec7a807ca0a42c3674e92c2fbd058a719b13533 +cfad95bc18597de0aff36582e7aa83ab20e2bad951e32119e374bd795a3f6ada +d83d3a2c5c19cf2ba48b70f845b381939022c792b03a2fc804ee0efc5a3d814e +4aa337b328d62d43fdf90a77a6a09d0a6387f12ce22a843d0f1c7c12e297e47c +e314a240629b4271f1149dea68fdbfdd4e83d659757adafd999d6e1e141707a8 +54a95a45f22d46192825863561a4f36c3361ddc5128bd7b764217a0728d1293d +4aaeadf258b45e93db3cb7098af521333f0261ec3290c05c3dda2bd70623e107 +2a4bf28840372a7f3b317ec93190944ae38cb6bc6508696be68f09436d4f112f +ea845ac845bf1ad0de0965e9b4dd4b7341a267e81cff96d7ea9244865f74c5ab +e4374d32d0c0daa8c43f4147fec64d2d15b7d608be6d1af18bba69a1d9c26e10 +3f1dbd45aa3268a5b028874c004d456017b3c9750b16b50901c1d28ce3e53a90 +da5c624644aa1d244dcc31334b8614d82cb6529dd59865f0ad1f636f584ebcad +d405eab7c506c513a1b567365fb13aa8559281a1e859cc83ee0ca69debb25966 +dc78d122bc779071cc9aa69a64e05fe9af03c834d21bfa37160515851f3ed877 +c7c4bafc9707f381c97d780d833faf5c7fd964182383f9c3380fd4c2ca594fe6 +998b594004204141a0c0065e347ec6c3207ef01b38a5bd178b3bc312d756dd10 +b879f41239107e37139191682213d4c3ccd156970b8dfaa9f365365fb5fb994f +9cb5be971a29c256006d65447fa691fe39039218f54a94405ea1e403b1a5ce9a +58a51d101caae283fbc933391ead3be3a670425f6743c5713e7c8ae1c3afe6a2 +14e183d1793b3c2f5e3feaa09281cdae191981bc343d6a35c91dc4961052674d +950e11a9410360d467632d0b9ba1cc42beababe36e97df88e19df6d52a038a51 +975de34a8d359de64fa4453c3bb7e05e4d697a9f0147981490e4e7bbfa74f759 +a990d4268338812b3d76080d6f7577d7578d971bb128868492f968385bc912ef +9f703becdd9d004c204ee297cdb99cd3c68fc105c37c6d3bb5736644516f2bd1 +428c3b8cf98361ca836db5bd883f84f62c7682f37fce8713ff7e610c684dcbc3 +fa04795c513062c0ddb524464033cc36aef65e5ba2207384c3235003b561f540 +d11a77c455b1859834243d982541cbd78fe5c33c18542eb9cde303c69eb0f022 +c5cea61a6032dae43d7ef0446bbcb13e80ad007e8b4c6a0506787b4ae6f1a43d +093ae35e7a01e08a0a1cb350bb51702bf7f93bfd80a3530f38cfdf063c3bd085 +4e4ecffb7521ea7320efebb8fa01052f447b1a5d9cce9b1113b3cdfb1671d1d3 +ed8751d4231ff6fd3364d0944940fc64ed1ded6996b960ec1ad5b68a998a0ea8 +51ca9e64b59cb1b13d0c905f23269ac6beb16600446a0a92df88bd4e634a2837 +f2181f924dd82dd467e87e97d0626e26c4b9df0e5c7b578f30592eb0fafbfbe2 +627d95a518a69ea5409db9a66b825ddf6297460a48ff7aedfe11d35db98ad46b +49ae42acc57e0f9dddb00b629c2299476bc2892c173e21a10b968d092671c32e +a97acba094a9527aea17ad3c06b0644488f3e10ffd0700313c3e645e132a2b63 +afb66675455d9dfcb5c165559ac28351040a8a15ed8e383770fb253d5cace7f4 +f77d24a46e4bfbdbeb1ac96d07b7b6db8140921134fd74275429a5db4cebe5c7 +195dbe5fa1b0ecceb13baaac0ace55794b3435e757c6f72dd6b6bf1a34ceafa9 +c66f436d08d55faeb0d125ad47a17cd8338cd2a75417b09aaea8c3faaa53e80b +3f44181b9e261b8353866f82b6f0053ea24abf092ff06167c9902aefe27ad169 +71bdb71a9cfc7f3ea2d279ab38b4b04acf541d4382fa21e8215b952f52841657 +5a0834e997f9e2be93fdbf93378cc22188c6c982e6ff88ae80f351d9e369fefa +cc49f6985664f420f0671ee692094548470b90d80de790ccfc6f6b6a9d56bb53 +da9e74bff3585d23ab355bc8cd9157b6029fc119f1254cda7135cb85f58803ee +c18df0cdc8d48ce6680d72fea15f4a97903c93e45a5a617091a2ab02c5c5fad3 +88fb3ef25f9edcc2b218bb420e9bcbf9d012978d9c311d75ae7c57995a470696 +6c8dde4322f4f68f790ff1ae911c32ee4a462f5ae194e2b9e9c2a42efed4723a +1fef5318cc92d6931c4219abf239c5f74fdc426229c30bf0d72e34488046d9e5 +4366d8a0d342c785d9d1f4f4c5c8701fc82e02952550371e7fc6c892de8d844c +d0cfba17183b6ef86d9f2e499aabc789bec2913bae66642b02243a2e00f16880 +0b607885c5326f3f74045a956c87adb01a855a4545cdd74ed7e4bcad2fb9614c +493997474d0e5d45595658c8f4788dd522cc7e635aa7c2cb3d9df06e840a9fcd +bf3f44168086502b6bf47ebdc5d5b3bd477a686fb90efa256e8df00cba0ba7d4 +68a0f5071ee8f4837c3a4650500672ab24655306ee431b21a21dd9e652381a04 +2d93ee0862828308c633b6b1730e57c40c38e4662a07ceb0416ef8ca355d329d +a0096c577e0a503fb71b63a00ba730f9f4a30c1c7c308eaccb0176a8d8392967 +61839bda2aa083e18c1ba3f7fe023f06e2a397023190f93acd7960cfa5edd8d0 +8d6ee96939a4b1e8e9000250a7cfaf0b5ffa65822f1a9d738bdf7cd1dbcb42ca +c9af214489bb10425b879a1562b8666882794c1e23a78b33b64a563c58eb40d1 +cae1872b548867245983a153aab777e4ae80b32c26098de07c99b690c9e63444 +c553e25f3ca70b621bfdcc6dada94199f3b02f88e68d5961074009141bd302e6 +9234cc16d71491a66ad65af2fad3b6f4270832ca02468c53c9232734e6a3bd02 +11432089ca6027618d45784e346de518921673d9a2487fd6f204ff9799fd5359 +76e6d825f2e6520623a3af13843aed22811e6c5016520c0e25b0459fac1b7845 +4cb83750c29f6f2d2ee50b1e35c391974f20510fe0755e57027541d3742ba5b0 +c03826461f4c91f768d3d92a8bb7329b54900258eab85e26572631e301d74e50 +4aa32fc466da8d2a9859f92d57e47b97e124f2b9bf0a5138a50295cbc8d0556d +3e2b562f1e02a75510dc160daf5ff6ec14cd9c74a167e64d23b0ddf31dec6f19 +828bab59b21c06f61a1d1cb0e72afdf88712b20bfa27fd7e7ad052e0812f9c40 +782c4e253acae1202e3e63d7b300df5f74acd73fb645b2adf55290c7655a2faf +efce8766f89cd8f5eaf4493bdf8cd1b74a75cc8fade60881d8ef66c44b34005f +e4a96f37636be9373f401d7e8e9ae9d87e53e2cd781f7e9acfeb4f8c86b879c9 +a37a518feb45240d2c3617fd9bb25920cfe75d9637e1dedc097fcb9741ac3882 +2ce23d556d68b4c5f3de1b347524a603b21a5116eeb9da0656a55f2259a095f8 +98a412d6c7132306932dddfd1e8f0dd26c65b8f7ad65ea756c62c9ef0a12daf3 +f656bbcba96e25bea161ec36eb92eedd99dbfac878a66ccd72182ee9c8b97ed9 +dcaf8fdd1df0a593557fbb2d4dd639850e82604a08ff1e564c31037bc96fbf50 +3136fb31fae78dd120f19f32e2f2f5f628337e22518101eaf7bab15de32a821a +ae162727b1ecc6705e47daec06f63ae9d1e29fde811c29863fd54e47f91091f7 +89d8cb29d4c781f24992ac08c64ce92c717912a7b5156ab6f3df804bfbdfa1a1 +15be13b2c892440d00ddf831fe211a65fd7541f7555d6eb35ea4eaf7a87f1017 +8ba1fac972a4a074a3ee0ab1b040d7ca0851c98cb11b699d24a7d73ec9bf0408 +e5caa7ecebb70b5efc09d70759388bcfbb5b5cb58b283ef74641abcfdf509708 +0f6c5cc5da55f801868b23fc501e6eace0102dd5b0fd99fa90924869ebf80ea7 +8df3d701eabc5c4dc366210409179fad692ac4a552fa138364b5b7b661f9ed4f +d5cd2047e18a66a64d61a6ec8d2bcf65af57d80d7127db6686366f8c2a7c9636 +9cf4dee4f788237c39aa9eb3e4ffaf677442a305108a13b889cafd55fef7d036 +c6aaffd6ee0199605b512c6a78f5a9e32ae8058bf6fb8c8c66658e9067a8acfa +1094b30985eae047624ac24aafec120a26d89bc03f2f7a4ab1fe695899c42f7f +69beed958671e821ccd09b050766b1094e4f1f9ed43a6872241cc6eacb412d37 +4aa0241d3bebf2cd687287728cd6066159f1fd7d5ddd1628753ee98da39d4919 +46d9583cda4a1ef832bc2c66d170a45aef91b49ddd19e3300324332b8ea7e989 +08606c0065e8ec72fa621c075e1dbd86a6e83773412d36634165ead28ffb4e57 +412f39de3b8529f688b6a628184a15b1c0eca5d86b72e85960d1b282780d0723 +1df62c95545f83ac6f106fe67d5cae48c862af6ab53d0f36c86125e64adf9ed1 +77bdc1f0a0044a465d6c2d36e589d206eae1a6b0a4613f94df9bcc8473ba9b8c +7827bc1ac99da87356083811bf6338e447769ab190dc10b56c1890003be7fa5c +98a69f1945b5999ae5b41cb1ed818765ce9b481605107e620f60504d63f49738 +254eee7fecb9534f97d3a4b9b7dc4442bed6c65a8847a7d8673c002811762c60 +5cf4548424ab55aac287831f781bf787978318f0be359d75fa354b7ee9e8503a +0edfe6c78c5d1151dfae6db7321661035622710e5a11a449588711b53465182f +4232f19d6e655a81b6925d61e9eb7cea6633c6efb16537ec3ecfb40c54d68918 +e97085cae818a5f61e3c4df6069f683a8430e386ac9e6e937f75bb6f57b4add8 +df4070997a0b9f3ac424244557f38cc5f71abfb64304d1016c67f27ba88d03ef +4571917a0b40b9228c3f718295c288a29648bece970b214556f28c396858a086 +8974c0cb489bf6d624eab0b767251e40a4abedfa8bfc29417325939aac30fe65 +a9a93f7f343c6fdc5b67113dcefd381449349435c95776313343a9c7afd07791 +866d4105863f0cc027af32533be71538a0d8536f5de2f7f6f942147380228da3 +a58176954c64257c15925689b71b3cc2042fba43a7b2d52d1854c3d38976cc41 +a5a791ac9fcc3be9ce972d30ecb4be043d4f7083fb9269c88bf8c9fb6fc40038 +59f7b259f6be1f5fb6b7cdf14a7de9c583690b8267e9217c8cb335fc060493f0 +8269cecbc919503ed46d887166f8b78c4001185dc8dcaad0b75d84da91ff29e5 +fcaab6d3b6b76c090d1889613a2b7635139c6d0640b84f8edd8b95f6a1a5fd04 +c6ab2e407e9eca62088695646e309ddb7f06491c33a119b68a0789fe52666023 +04f86aa14a03831c9e743c16c84d7ef33e534393c058110dfcdaf6d3ba790567 +7691e8b304076237303d712afc4c0e6cd7b77f12b610af89c67018b13e694e6b +aaf89cf0b0feaa22a88057189a5d182f8eb27160a4ff2e7c156748cd8c7ead4a +812a85d4a207bcea3ca0147079ea66e479b0acd670556a4c254897839110e561 +8c53fb0e548cb052463cc92e79ab75d4ea0b8ec43fa6588419d2d9dc607f90f2 +ca9a1c7021a6dd78dc12c2442baf7b42d2801005bcc72d80f9c5476345b8e85a +c9b44e51ce5a2143b5c3804b7e434a7b803c90f761b5baa562c70f210b4f4d37 +85711a305306b2382b8c15b147d8f86b334cac4c6d7d84b5ff8d7784f8de22a0 +0c46ffb0f28a444241a69ac670c58a5a1a49f7d2335f84be4e18a3d78dbc827b +ac6f98ebde89872750c3e28f34ebd1a2aac24f8f573284094031369f2e4b4790 +fc8098a0af2b8065d4671a079125c77afc4de97dcc2106bce382b3446e5dcc94 +8ef730e56ebe6b04710c2f5f2e920571d83f5f18b867b7a4e981bfab0ce0ffa8 +b42072468e0d8f5b19f6f633dff65c08e262aa0700362b52232d9ef00c6a0531 +63e2a3192336144667350c010214b325d0113a465497902729aeaea217a7774f +d532579f5d9f38fc19af106ad41a6a20e01bc9df8d90a2ba79a557bef48f0611 +4512343c02d8628066610a544e54b7f8fbecea64046664444dd77fd13459cda0 +a383bf55295f37ce722f6e5cb6b6cc5dab3943bf9d9205b94c7874b92e145e26 +7d2700c1c3217a4eb25c65afa3b629003f02e73f48091995f838111afac9dc2d +dd693d58077e04fc33e2e6953a85f535c00d1a8f69cfab04ff24991af63314f6 +c17f7b33c55cdb28fcd1f0a362023471dad13ffc372508be9f199c73393e991b +2c63b129381a5ab0ea4772bc81a2fe3854297975b7aa8fb7064708952ed04487 +0bdbc1874e86c4c57c7190c52dcba232430f08b6491872bba6ce2a1c50956ee5 +759073ef1610284f7f1f6a60f2bcb7d962b7ed9ace9dd39234b446d1651e67d0 +d2c1b17912561082a42778fe31278794a9972f31f77c95b058e3c51573ab6de9 +a28a86c3d65faeab4df0790d2dad4dbae05b301d8514c3714bdd2533be030b5d +236084fbb303356530030787a85b78578885c503354e17d076bd99d622fc4883 +04e565aa60452cfb5bac54998f2e06290cc3e8fcc1d6b85d5d978cc49e811771 +ce1656bfbfd301335a1bcd56d6a11f4d4bf9526baf930a6d617a054d4201d79b +770c19108850ce0d89e412e1db6e231051c3002bc6d832429ff09e35a4082a8b +e8156a6d89c803933b092eae7bc27fefe0c06d5bf90a43eebc86c8a69ccd7740 +5bd4160de266a982ba73c94b6ecd092d78245abd4bb93e1d5d594b0835b7c06d +06d1a6a1af50b9d75869a8550d4e73853b141600c57bea93010f2c04573ee4a3 +fbd0f2c179d18991f6284ac87ef599054b890d7e0ea817c3a42db49cb7401efb +82a00d6ef69c17c3cf15295440da405c2ede71ff80844c229d835362bee56e43 +83c1b2d2e9c1edc3849d9158e26a626fc1bdf7444b24dae505abd45f789bcc43 +f917baab7a54de05cdd84ff917e689b8130ec2d989bc95b99d5c405ab4926654 +f258d2dccc4d01eeeefc00ac39224678101115d4ec8ac55d495bff2e7680107d +92bbf19334278f28e919811adb01e32f06ed44705b614bb6deda7927ae4bd0b6 +c96a953f67c3b09d5f117922575c1b9adddd19214ce0165d9e90ffda37d64d46 +cfd27b697254c28cb41787d7a5d01a1c4e3191bd26b7bfb3d32f1d169fc92e9e +856e4327a297a750d29251c4611259475a43a3c8f453b5fd8f29663918e84bd9 +590755dc3b1b5cbe3f790abec801755c69aacef4d6c9e36926fa0a70eb0ce8bd +858429755006d2d38ae6806fcc9f1856597626481678be712e81b9ac43e595f2 +02d774eea4dbe92fcd712ae9bd1cbf78c2bd98530969f2ec0ecbd3a44539ccad +922cb135a902d5d1be3516b4ffa2d0debf03838933f262fd449dbe77b9bd3db9 +1880a99fc7badafe8da5aa1d37846ef358f102efeb22b4fcbb19fdc7eda7b273 +864522b47fbdc5bbe818679ab78645526d532089996759134a8f5e9bb104e8cc +c264cff6ac0818c89228c78d81c2a223cf0b722f0bda2901eab365c2160d20c6 +a50de71a8086716b82ca56dc0384f243c757e5570591ebc815e4e7e426feab8b +135c09ea1e1df754201da6598dda6967aed4135336e7528e064d2541ea750044 +db40324504ecd722bb391d63d289af7dc0dbb95596c9f7e0937740e3d20874c0 +d079285f42e11a43d281983d174e766f9a18ab5d4fd7fc8a559edb4ce0eeebb3 +69ce353f30c58dc5e8f80e6d921a29d354258e1c9237a683edb9b03391336d4a +8f09215c9801b86d706bed8723c24856fdee91be3437e223fab5a38bd1a6b5df +55786afcad18591e18cbf7d0e4a171fb68d007ba3fdeeec7139a2a15a0044f05 +ba47135abf90c1f467c20a7850e6043e2c1c89f9ccce86242afe54df1cbc5600 +4e2d0a825550b640c03dac094fb52e21d2fb2a85fb7b49e339e30bedc4686850 +bc4c913da0cdb9f8f3b97780c35e76b8677b282a0af96a88dd59af76af6bf891 +3a64ea2f21b643f3863a54205c070fe0e9ae2470064e60d84ab85f6f20acc8f9 +56bfc2d291c2dc701fc36fe70578bc777389953c45203d203b399a35f46ee3b3 +eeb9e156c4ccb44d5f7654a36384d5bcb8986b8c0d68c0b8491bab8ef27f168f +cb53c3d3f99a48451b9f644e1d44db1c2c40f6b5e11cca22b3db2ccc67365513 +ca5c4cb66828e6b3abe351ba4fddefcd5973ee8f7652f81fa18505fbfeaa6e79 +1323c41c939cd888449c051e3dad8231415b59f42fffc37a265fc866b76bc2d1 +115f9bafdeb7814df3aea38aef93b1f1e576bd7e9e0a1c936d51e2e2e7e218b4 +8057174b6f866dc4b24ac54b63974aa17b1dc71370cf3ecf3c155dbf3c85bf34 +231495cf23879be707f8629460a470da2448343157dd54ee4eb3871f2cfb475b +e0177ae71effe2aefcafffa608e53a48e82ab41c7f289aca8536d782ac600851 +bc023f7a84795a35038e38f5f3cc32d819d8c9699b9052c777e2161d996e9195 +fd5c1ea0dec3221ed1c91c5ebd3074dd7841f5b3fb8e13c4880059ee6814bafc +b4b3060c15a341fa4630e6135085a2360e2ce0fb70b563ae8244d1f89b967b04 +36b5e7871a050fcade45de8f2948e7b75c28ad9a084ed6090ed6a833b5fc5f6e +6cdfe026dc44f3fe42cabce96b5b7b6c482d441af0fa0d9ffa5136ef35c79100 +48bf7fbc877aa6a835d916b23866f3a869238db42d491cf2ca65ffb9ea148eec +a01fa16b2e7a5ea4d7f3ca5225e3746f92fd1b1aa662565e9785ef3e1190140b +002e71447b975e043d8b7325c6fbdd1ef937891ef64b66046ab167aa09f6ff48 +6583a3d81b1927fe24b81c00017b3bd2b525ef59200bd0425bc4fe7fb94d5c1d +75e570bfa6b7d62e0a71cdab967b819229249a74032c37f6f10648fb89e23ac3 +75329752eabbe1d292d02b6c47886944fccaf67c11f6754d11a1f388c7e52b17 +745f876fead905dbb245922fcf3ca5bc1a8fdc3ef33c2b1157148d71e3c93820 +8490172c85441f1c5ad7650fdf7112c2f9b2b293719707d46c61cef4f588c095 +41ccb8117efbc6b2d7b01ff14b0514ea358e7d34a69f67d75307ac7cad3eff79 +09b1270e972feb0f713a16dd32e331a69ad65ae02a8966079787f359f91052e7 +37a6da9fcd9c64410bab7e3225984c914b970accf6208de9756fc1f54b879e92 +ab9de5f136d12879a290cdd4d6574e6b4bcd0c395c7c17052caa3a1190ed2c30 +a6ba1eaa4d01770e265b09d99ca65938bf872e0763bb8dc07958cfb185ac7334 +b2d4337c635e82be11dd6cc8def460e5e9715395389282974b3f586fb1f482df +9bc2e76431fee4bdd6a4af8187bd79d624425db52575072f84441475de602499 +ec61b0b86a7049a70b9c074bf140a11ae4fe8a6511f8b2fa427a1acdd19bc28c +edd8614b34e3e86c025025c7209b905f8c8a647f7c5d8309bdf781e657c72785 +cc1e21b389142908e92b722ab642a7bde1745c8a505d1b92d4e214a6598f7d8d +75bab28ec2c248d8cad9beb013a86122027e329018d07a354a7290672afa723f +04f817a591ec3ac6a4b7597593d78a4a699d5948d6648e847d5cee0afa23c465 +ff45f45ebf5991bf05be8963552e6f471e3fabbbce62a5f8d65eb186592cc4ec +5b175656ebd8d5251207ac307f7950301a397e4d6e976e8f8ddc49e2326e4f94 +60a70433d21e08580b570fdb3c0ac4b9c97c1c90d36ef92736f0855545a53c4b +99432a9f10c0f5279af798da76e373bdd618fa8f712b907383e880aece8e5531 +e9806a2e711bd69cbf7bba237b9474026dfb9ed146c1a49fecb4a1059ce8a658 +4f93a6f890701ba764fb2772a90ffbc744c704d15b93e42fba4300933cf0e34a +a5be79811e6f86ec7a723cd650dd6c9bd939155dff9b33f1bb11c716e0d7d6a8 +c728ecded8d0cbecf6371d7fc7babf84d0c3391b224ccf0c2f89d5f10698e7e7 +e9ab0857908db18da2801df5de2c729ec5deb8c84fe082d1b80f6673931493d0 +e2d5cbac700cf3cf9673482e800458c972e05c01adec15879971ef7cf1153862 +d445a993a400c8abc02ccda91a372456af17ece850fd86a6e8ad7738c6d46e0d +5d8b88b23f7de7341fbc53c498994679982bf8b521315143d743782e08c4aaac +511f1820528e97a4fc8acb882b48ad057e958660042c7c7bfb634bb86cbc38ad +c206667eb140b3b49f1c69b92ebf5288907ebea7952c140c3283d2f822e30043 +2ad81e9bb0aa06a0b238164a4d2b2f20e651bcaf643c3bfad8ccbc6b92db2a31 +a384b6d9db4e5099b8a1d772c65f67047c107e75b61d1c1c86a9140d9e565abf +c3476dbcd6995138a0bce19e4432c8fe99ba1e39ac58ea314d029d0d2f241553 +e0a0af0c91b26901332e1514d0728c5b0bc5f2bba79d3b40dd0852a88abaa396 +768692582798c23521394d0e379f0d298c23566fbc5696c052cdf32f071f1a44 +d3d14cf70a939b946873ae07d2a8ffa060fb707a775b81de109cf086cb4b992c +a29c2e1562cf83141947e3dd578a19a536cbbca1f1e59f5fbfde703aaad0a837 +8621f32ab0fce72f2818d8e4cc1e1e7d9888604f5d6d9442cd3353da5b7e5a5f +e4aa832a22938e76446134b0f098bacc4b1d57cb3d6759f36c4d3145582ffec4 +ae75e51c555cd5e88961a386a4386cfa203266a3715c1179bcc91c1f11f94811 +3f5dda5d72d30bc52622eedcbb5ad4f7efcecc4d55e678412b89524e62437ca0 +3f42e50050e5ee07093e16452fd9bc2c912d202614b890f665bcc3f38f334f72 +6a956e7189143973303006d9b6319bf65ebd916fa86869d92e78192561753f39 +6ebe8d4c826ba7bebd1ec8ce609911b2fcfa3f0f441fd29c6d48919be0c2463f +1c2697461b3008e121026447e97775555f13645f4dc4f3f3c0c9524fadd9082b +81052ccc102d67c6408279fbe2eeb08a4ec32310e62cfbe1af030016b332fc59 +933c657614b009c196b5fe81c5642eb6b3f233354c3452167d146c19ce739f2b +82d49b7e162c707e335f22783575f409396c138f70aae0efed0541cc05248bfb +69de77190bbb48dbdca583f75f8541e2c306601cdbbbc9f8998a33e504c9c04c +dfa7f5eea3744d82f7ad4eeedc3459aca7463052a582827fbbbc37d21f01d7b2 +fb06010f8cfcde87c94d8d2267800d01375d94be7667356895fff6fab76dc5f3 +f867a464c2ed83b8195459e2e56168be3c10b646cab7c8f36da16f85b0833442 +b6c2403de62fe02158fe4e1789297443fed232c020cb3ce47af775b60e8f01c6 +d0262d7e872db796c94952204afac3501acd193771a18eb0cabb07b444f89fc5 +c3585a3b674fa49ec98c1bd4e8815f018e4e15c3ea21ae88efc0bccfb4a38e00 +a77c1466b12589aeb9d8f1a8e5533157b59f4011410f0e2980de87d9b3e1dc25 +5edd76bf0d839abee8c5e08c4a12c3c9a5cac552f64500f9aacc8cf6e35cc758 +7aa756277f26865236426a633857879a59be32305d3776eb77361c9b3996aced +38b628d726f33e5cb0ddb79a988e149b2400a2deecddc16110758a0b740aad44 +afbc2067e29b72849c8ca097965223220d5a835e22d9d23856bd1d247a04eef6 +e7a274eb779a737347b2a8ef65ba48eacf013446c86d1a425703eb40436d4d7b +d70cfd9a6ca6b20586e55dcc3bb8a329828a9defaccc3ac7c35d5d3bbd9863f8 +aa6f24cb9113b255b26263c25c3812d4d29342a794cd39b6fd5dcec7956d7a9b +89bd97d9641407a0a734bc86dc16c104f0ea602d0f9244109c3f272e48687efb +3cac0122c024a8399041ac7ae1f4cec169eaa2d0d0ce9385f744415e75e3d3c2 +abc6f187011f5afb757057a1524f644302206c6b606f6895aa94f5cf484d5c4c +359be18bb21faee6f7e4e8ee085208ccd11bda9c11a48604567748c38788e45a +dcc4c7f6f43844f772b075d526951712cb8917f998aba43f5ec6cc163ded4a56 +90ac883bfd6f8715b32f63125de395f92c14ee715cc9b2cd1895e527194ad814 +03e5b4cf9bb383e5f9604f9c7d3a457fde8b23009346b16b604d6e82c3989b4d +058d24d83fab0b7973eb389ce36d1eff88c6d8451b0fab9e1d280884e05752c3 +ccdca5f3af0b2be37620a4efced4af20e1bd7f6d6fec604af297e1e2d970ae99 +77f1574426fd959a8f16283574c32b6874c2869fd3212c04cfe17b368863a1aa +43c8d230deaa4c013075ffdbd49b18c2db51124c77886beea6a6d83f31dc850e +74eb0ce09f9ede433f4acc52ffa82a86857b89698d8e7274436b486a095c9f7d +506f1e517198062a738d9a96b2b299ce2491ac249316aa845566d139c24e5977 +9fa5c3b476472b14948af88efd863cdcb36ddfdd35589d01b6ec5eb7cba77aa0 +772bbd1369c480640bb55e04b856b1d0bddf8e744f1558e6b436194d8498bb0f +dd54d7cc7b1cd3e1888c5ad1a55364a4dbe2f73fc90138e6d6c2d79f7c3029a8 +4b3bb17e68628a4d623354c1f7b33f76328f179a0087139cd37aa3404501bca2 +a432fa989bdcd3ce29938bb36ba63356f37ceedf5e8c22c1ace2f467589583d4 +ea8a02c37a86957d978e11de32be15c74158f439a088863fd22ec27db31dfa73 +adf640c938949b94fd034b1e2142aec4935fd383e6255ae768bac5e070332987 +ab937a023299a82b8110251f2bc15d768de22d72042936ac1c5c1cf9d5260664 +59a7c3046f23cda3381356f428465c29ec71addd04335f996e873a64cc4ea32e +727c7f562698e61a826678ff1e81a044c5d0629442315eb726f82307b11a653b +0f314e18ee0e344feb6d4c950d92a34a2499edc9256f93adf67ab4e448f13147 +871250f2ee69418ea6cae8f887d67af6aa702082562a825a94fa6f1e3e920c04 +36f36e4b95a8b4e0fb63841b0b4810797070e9bc45cf3ef8b4806085db5e835f +780cbf37721b05927976b370cccff996a2431e11e2aab479834ae1774322751d +5927469f585f6901288c5bc87a5cce712dff28515af55b123e15e9c6ddb7ab75 +74d6e77c2f8498b3e21ec0ddd270c465cb372d481831535852481cd8835ade83 +b9754a2d34d7be6c443d43316f83c8d9ded197c1afc8ff8ea4fd1c62495e56fe +3e06fa9eda1c6b87556a4b8d8170026a22cb53bfce07b51d49dabd4e2756bd31 +cd3c653b89e848fe7ab6b88c5aa64daefa7c0679b02a803ca4ecbd76a5ff3419 +f3ffb6ec183d43dcb9224942fb8dc35826a423576723856a4a048407aaea2849 +e4cf741162a21931a232816ecb969c769daba4e7326c233684ba5b8551659ccb +9b0e4b77983ab14cf50d0057ae18af7e93919ae31a49d8f2987f364bb83610c7 +eb1d2cf8f6bf9a1bf2ede3235e46a219e45b14b274fcf45bd058a95c0fbb15d7 +9b099190baebf4cde84820c3cbe160d906b73cdc44150ec2777a7d66a936fd46 +a343eb36d512b3de95ee9140b1a5c731619df3c8c2c9e1f15bce59c88f396fc8 +076ea2b729b6a8bd1e49b40c2737afd3de50482ffbb936359ec9eca6f29ef284 +1cab994319f85771b72a435b8df6ee798b77727efdc60b50045dd5f12f7bfe2f +fa18954e547a856223d9eb5acd07c5e86143edd2123ca6d5ff6c11349ff7fd4e +abb0157781215dec89483f88abc2173546935e4095eebe5e0bed6a27e7e8670a +c08afd5d91ee567f5d9d3ce44ce0c3becd8e62a13c8bb5248c3684b3ba86d7fc +eef73ccee3bae0e6792420579e87e3d99b0656d9772be85985d37ab787bec49f +9f22f7fe7c2e3b2cfed6967f3b2a32b27a087a3ec043200845393683cc6ff67d +01d743b407df690146764310aea9afe2b7ed6cb38751d1025ea0645b69eb424b +5da8331c0c7725389a62675407ee17a45223dcf0fa49833be05b0250aa396c4f +306717f1d8232b4cde4b811724e9d70fcd39d6befb06847eae300770d041893c +58a84a5e6259946668229cf23923d3f0a9babb0709ec3e380cac763ce3701398 +ec1758649701c9719fc309b975ff88b58e49559f994778b0a9550e848bf9bf19 +265c035cbb7299bd25f5b9d8c3ba658f552e7ff2e58f015e2abc7d3c6676417b +51e5e657647d40f73ded17eb2c582fe9444782e7fe390fedf742e604bfb8ed2c +6d0dfc9c56c6e18f4b6296cc17a655445cae411162018623b1146dcf678994d9 +6a046a7b4ff93bc44cff26febdf4c3226d2b8c95fd6cd80ae7fce619e1a43f27 +fb9bdeb636f147de98204ef4c4616a3bb9ce2e29f2f653caaf002c0c9a3dff09 +09816a441a09beaeff396337aa85d41dfd6d6597a165b0d5815231805dd6ba40 +cf9796f7eb1357fce305abe0651abe50ea93e3a7478bf97634b8d6d0d6f2a12e +8dbfe8f93396409d9f9a7178f974cd79b57e413f7f749ded1b0e4c8b8907731f +7b523da6a6755b7ad3ecbf899beadf7395e66b76cbbb2ee694a467c3b26862f6 +8c99c2b97405ece42178fed4f5b06b6bb85db670cbb65e081329f4a87e4955df +24d9e1d2c5a2a8929c284549b0e2fd4251b2066e373a8d555f1bc2b62a395ed6 +9d5cc81f828461f6cc654da5882d92841cf53be470370271edaf857e71c1fb28 +c0fe9233107cb167b671939cf8bebad7d2148a01f3c365a78f7dffc19655e0dc +51c75ba6950ee64acd75a1ad8e8e3ff17881b8034f3ee46dc3fe3cd7b17a5ea8 +3d86e23d916bc586b709b77d938f2db80c2edaac3c77963696a70290c67efdfb +49eb41fd2ac0e2fa5d2fc5d0965303969050c64dbe220c2ef2b0ea7cac2ff4b6 +abddd9dd014855a3f14e9c0c649bc21637ed21666df76ff7c74adcba53a803ab +1b5fbec88bf51674349b965977584fdbc24410315c6cc0b68facb2bc09622b8b +e47a7ce9b166e54f0b61e2cb466a60782eb46a96c0130d82716389d12c41ace1 +7fa3b8404c9963d386975ad30b6eafeb248e4fb251b9fad694ee2e1f29bfc09a +80060c5ceae0698c5c2e18309ce85ffc7c1208d0ea1253517aa559b79662455d +568ce916e90fddbe80b47fc01e6df0677fd9e77e274f75761926686c9894cf00 +0b95dbe12705a549417759e369bfe7e9b418062a4514ffb27b1c39f574686a23 +4d458d1ddd05de060cc88f73b0d717468e313c2dba6ce711949634416e8c9be3 +bfe7685ab9dd06b8aab65d8219d4475e1351be5a55dc09924969dfbb448f083c +666b897bfb65cb930919947b18534ab1a4c15b8ad853e856810877815e8d02b6 +f9498c028a53032f67d895cf234e324ee84111831ca0441f36694d50f3870093 +175a1c2cf16753ff80ae4d9eaf823c2927a5b4d40a6c2bf2cd2ddd743e181970 +c83ed21fabc5867ed9dc9fb05f91489a70aa2a2be479a90436510c8180701eb6 +465656fce77c3d4eaaee745afc54caa54a33f92092358dbbe3d1cca7ec6df012 +63abb27d028eb944d0f782da79acbe19510c6e39929cb863b0407a6eb9b2fcc0 +ebbe26b2db6104c6fd55886f1db4c6f6243912146c1f38bd0b26aa6079ac51d3 +bb8db15d3655a4729fd6aabc5980459977c3a3d18d7c0f95e55d9e8e563f1655 +e80f313c0e29eb03a4a68f8fee1ab7c0c27b9945e484a39a084b454bb82dd0e7 +532d696dcbfc8ac2dbfa90472fdda2805759fa08b027dd7a49ce42fc476416cc +20f52ff394da2a1a279233c70464429966c33b5fce083a637f1c0686937071a6 +3e128565dd7d89b832c98b7ad50000065fbd565273e9308f59b7537f53738d38 +2afc10a824e9791e5af49d593ba350f3390df5463bdf63af61bda3e4594cd477 +bf5fefc1031cbd1eee6e372999070eb17001dfc35d837edf5c811ade89366b5f +bf9ac083965c9cefb95c31c5c05eeadbf6b3cd0bfc0e4fd9f6d7d35930fb39f7 +cb87abf5a0435dd8111a68ad9837c8db66ae12e3074e04b6d46852cd4097b54a +29b186cdd19769639dc6514eeaca24be9529d072857d006172d1b7dcd5f26ba8 +0caf024ffe23d0a6ae5f7051aaff68ac414e5d94371e46381eb4358aeb05dcef +695fd30a2bfeaa32a1f39e701a0b22da16ca221077ba39b795bff2b10b173525 +544a9f10a34979d631ea4ca5128322ba28b25bfaccfe0f7493cad333f970dc2c +1873b546440f449a38ff7865409330c8505c61d0d6b7baabac8735cbc4b69eed +a4e8c35d2d8e289bb95175cc204696d37a6940e3f3b54fee522e113c22a93764 +278e3d526b98a3e6d37ec3b3ed6e574a1c54d1fd754c4b9df33fb3b2364334f3 +5099b103a89b522b7ede51066fb3f5a72683390f656ea9654f3ccf7c16101e65 +950ffb9fea569f8e67ccc65ddc6053fefc8e69ec5dfcbe42b67c76a5a1611cc8 +76c720fe967ce946e03dd404c830067e26de9dc5bb7979d0f95c57c537301f5c +7fcf97935f8fa3bd0b9a7dca87b678710553d653c34acd354b9d002d97dd9f7b +a5f966d3df220445bb7c065879aa2b05c3bde254f64516d7c147d21b05cbb83c +c805a03e0be0b86b58ce1c14d139978a643d746aa6ff33af0aef1440263ae3bd +79017fc9025e59c415e89dac3fd5ecd5bfd857217dcdcc649f258255822c279e +6ac65750beca018f716f7422085e6b95dbc4d11b2b4e4a266ee59b1446dbfc14 +bb49c5e4f5cea87d1c766981c456e2fac57a15181cb0b24c443c8cc9c8649a69 +0f822ec4a397c0b9b043074de1bb46a035aa4b25d0e4219f2138138a7e29c44c +ac0b5388afd7d76cf4c52f99e309717187335c237f146aee096c16beac3a4efd +201c1d21bd984ac6b905921f1c71c022afadd6746420e5867005ddbb164bed6d +54d969a17b7dc7aae6269b2218735597ceb1fc593015ae08a39f18c19d3f70e7 +8ab9d6aa9ee769311da7b52743cf147447c13f5c90b6016f84fc9052e597090f +16046715bed89c215ce0ed38a064a63d69b99b3b909f0353fd143c5751fcd391 +2b126d8edbe0fab3ea4ae11083bf5d0a2efe6b290319fe27bbc5aadd59138995 +951b0e2c1e209555e97f838c0f908d3bfd060682c824af8962038df2b73fcbb7 +c0a2775df2332611ef5b690af173f6c344a29cf0f4ce986d42e2bad55d8ce590 +bc0afe71777837fb5131eed96c676c1e6bc656b67be64c00371dc8b56cd549b1 +73b3a876d355fdd8bc63a84eb22cb4eb65888d8e24342b1f68a614ded19056b7 +33312536c75897e40ad0c091294a6eec96d8e51c7c59ba7e797022dd7bb9c45f +33bf02d1550e44aee52720c3ae5fd3c2f1095b6683570c73d19c990bd4852a2e +41abaab3e30d1922508c594dc2bd99fb1cef86eec37371ec51ef76f97977ac11 +32e003fbf538ff534f7e1d229c770772414234ad64e5b4ae8fdb77baa0e8ec1c +b5780cdd622c6a15a068d954224ff7e314a9a79cf2be4850506fa932eb21a451 +f1787561775f9d95840bb5a02e1acd527b275633fbf2c17e999cd4cb7890826d +c46efec9817eed931a2757d3fa352bfebdcf5c62e4e043fe4ec130beabb7bc38 +fb2e6d75119eadebe290e6e9e79c0a2fbed78cfc02e1baf2afbf03877bdfcfb8 +183632d0f793007ba63ac477221536af3621d45cefac5679fcbcdf2b06d4a7b2 +9dc8ae77c05ab4d3aa1de559ccf70b5aa5ea026807ecfb17969bb999d06db9b9 +59220fe6558066551d200fedb18d0873c353f0139af9f34626ce86970e9a092a +1779cdd8bed176c3534bee31e8556913275d27fc40f2c8ad18d3d059f5137974 +4f0f35481007d22a4bd0ceb368c74a7433d6b3eb62d923b02cfa69298254dab3 +b135e32db45ea916527b32f8ebc29a19ad6cdd817ddb0f671bb45dcf6b394dd0 +007ed31580f4ccf57bc8fd04aba04bce0e6728b95db3e8e104a870ab98aa224f +07bb53f7be9eef0176ae6b08985453a536dcd69a87b4ab3089e5287824ff433b +5510cc46a4292ea87d64c508171ca883259b4b41308d6a30710ffc945d1625c8 +7f8e8fec4e2a857365e729b788d9e213071a2646a5687e30a649de3dcb40cd31 +492b285595e3361f0823389e572ad01c7167b1293a1ee84beab407ef1fa8e69d +27d96ae859abeb36e39b3e1e38671ac57fcca2e64af7f1182e23d8d34263360e +f39103e0a9ad9b723f5f1e2ad9aad685c4406a0a3b1cbd102203ad2722a6f88b +639649c3503e0e27b871482b8e84e0178581b02913fa935ea249a24abfcdd03f +cdb93d27f286e98362e6d50ff7bbfe1b72d5a655c16f9a4297c7b70372a36f44 +07db13b4a8b953166d771480a322fb98d73a63872d8d197f25e4a10e99345960 +98f975fde431be82d1580f13b7ec36fc7ea075d9361543a3d46765bc55dc7767 +3fd130e21368f2bf23c9153991cc1ce30d7f0a822e15921139a8db076f10da0a +0dd2598a3f979ed9e8209f257c60048b12d9473dce8cfdf5b7eedcfff9d056d5 +228eabe5851c2e4bc4babd884feb18e59125b4ec9ed31e7f16f93ac01a4e9d0c +206bf3a83589ecb0b3805e85a6978e984706017f57cd656a1feffa1d581c54a5 +98b45f1d1008f61c44bd3dad76d196f3e0576a9faaa232107a2cb65101e02f3b +643f4fbd8d846fbd4bf8c586cfc48d3daf921d5deb0add55d62136ba93d37bc5 +42debd8eb5687eedcc003eff6726d827d57c08e015ad2c882cdd5d56e12b1a03 +274cad07221b343cd8667e8a36638742c9f118df07e979c3a947d40a4423a35e +32192198a5825818b526fb009f6600125b1022ae1842c556d4ff4b72ccda1930 +c8ebb8c4552523983e6fffe464093f5eb33ec64dd39cf4cf1e7d618e109acb0a +5a41e878200837b124cd71872fd8f974be9f2ad317bb1fc3781e312f49f81b28 +9fbcf673799ab15d57e07e955f4afb8970595899ef22e15e2738fcbb64cc4d92 +588fe3f7b50e0a449d8407e8dd92e162ed09af955755859ab70b10d80abcc583 +1ecb1c972863d19e547d2cc2db0113cfd410bbad499b90a0d9def3eff77b5da8 +9f927c6f29cb035b8eea907d9e16927f095fd79b74a76d02965e3813530c9fe1 +225d8bb2a5ffd638cacee041ef9a4aafef99311effeb35b50de563714e891253 +57ad4950782ebc10d91c522585ebcb02da3f6e0f8077a8abffbe4025b18de4f9 +ea8eeab044e9ebee67120aa5c07a8b2480f0376a129062cb29dc071d8f43d3b9 +1b5c13ea52bb60c6b997b92314159096ba1d545e49d221dfc4c2aaa9d4b4a7c2 +87eabfbcb25a6048cd81b38de5e4bc1e6d8334136b74dd74ee5dc18fd8ebf813 +8b25ecffdbf848c413b45c0d6b436bb0ebabe44f938fd8ba4e31ef5ef991350a +46498384802a8166d0684da5b2848c55bfa48a5211c8817669afcc8faf44004d +cf8181b01cff4593bebedbb769a1bece2fa67ef316bca4d6a2ab654979f9d454 +4426ee3ec0d21d8759355a14ed92fd0e44ee0a3e78b284cf9c9993a4e8c13058 +8a319f3c00e13a49e26787f1d7e3a0df05442aedd515fa76ec10e08fc01bd28c +b3f8a87f80d47a6caa3160521a27de06028745fcc6a40c7378d08a1f2c97d409 +fd717d285651800f597ed098b63725a15ca42f5ee70162fd475766d871fd7980 +3653b586733e04157f0256b17a78c6393ac4300e999bd8f4cf6480dde1549f5f +4ff19162b9f7f3632fb2bde2be698a54bb4ab2e724a4796d1c9b4994747ebd26 +84a4e55bf3701d1f73d0b6c316bd30f1164fdefb48b2cde56cc3260e7d8a74df +e65aefc9aaa258df9e9fda144bd46a3254b2fe8bc7ce2b04440a830c3bc26ce7 +7d1e539a059f8a2404d0782249ea95f297ab2131b00d955c2a6f14900185f022 +739cd218a64428f36285ec36314d112be95335d9f3515aca0b3f4684a4601e61 +f23a67f8808cbeecd39522de70bc3ed744a4dfee9aa9181c9b8627f4688743f0 +c51d9ab986485ac4642918a784293aa9d1149ee7d1a6f02f2d49721fc71281dc +fef68de968790feeb0a9b94cf9732ce1fee45ae151425bd7ba4f37adb98135c8 +c88ad0281a65962ba6c4e316a919ff01d40df99de78fd4786da490cd10676748 +4009bf971a874f46b14e1442bc202b85f4f7da944152f703e0a487fe01c74d18 +f5d68780bffd0bd69aab0133c33dfe2cbdbb5a8edaa421f99e5fbe81f2c9b0bc +a6b8f2a2f5c9bca06991b641184dc75c2ca6112887b2c901a0b0fb7b9296bd26 +bea985de732a62b5e0574d0107f9c1704bdedf8e3435a0e76fc58671a68af9c7 +0b0624b7d7f9950cc2dfbee24ea224e59739deb70f03bd15f56b9816cc602c99 +d85d83d411ecfdd1ff87773c475273f2a82c264ac363de19238ec0c405c7fcda +6987fb8142213823dec4f8d1f5fc0f9b30f35d49f42565bf31f33d94286cd068 +82accdc429c094d6ad65fa2eabd50c73d79a37fb46a3e425aa38879c0ee5225a +982c2948ff615cfaf0ca47ab479db8f336bd52efb4f0a063a293b82b1a3f94dc +8c1f2404aeb6f24abf71f6062efa97071b408927d0dc6b2d373fb20b87129b32 +2c0d40e4e81b585042825b5b362edfdda8bf372fbc4ef6e08b2cbddfcbfead1a +ec875980f7dfc1b465aacc6bb4176fbcb07b4dc9e91aada9dc229283bddcb296 +c631ca4c7661ce436d9ec24c3f4b2183d2337a455929f5bf74f3d5b16b3850a2 +6a99ef6183c2ee516e7346eb77cd899814e9792bcf794bbceaa4bd58375006af +b12dfddc9b82685d50e82f3cc29a591b5f4724dcaff43f2a3bd5c0e6bb4fcdb7 +3a896fdd097be8817481a6c4e955c7e4a16ac3fc16349559c47bea185f74c8d6 +9b847f44774d8d54c3ed0c62517ccc1058c69c14fab412923f7367af406109b0 +cab296c6bfc48f6a29b5641738e78fff2f5cd35c2dbac10644a665b6c952ded9 +095b1278648045c66b4218e0c9aa9255ea65facd6cd090e6c24d75707b956cb8 +e10b6654abc00d93eef80d665259a69a70e1c8dba67fa674d36965a33e0a8223 +e6e4065011bf50bdb68ba8bdb1fa12dfbc2571a0167492ae886954b047e3aae5 +1133fc02675000425cf640dd2431b4136a4fb829d6554e16b139a3edc404cc26 +e48a0b7a08c4a1b051607fbca99895bc50f15718e84b9e0f0a751eccff26bb42 +6636395589e670a158e3d1c18aa4e5da877d7dc40c2dd480686c413c82569955 +bc811cdd76e93023090e20ce479fc6ece05bc3057cf379715d00ccf6a91f2490 +567fa0d893dbf3a4cc118e895b5a1364bcae1f0c27104ad33d907767429e6cb5 +960437205e19b86155a94c68c17c3f1fdd48571f9025c9ba5d1d4d8d03112363 +92ba4368a9a29d3c2f8fe8660e5f3c31ce4a4d7d4444d54cdab05e0105b55d68 +3477fc1c50aa93c72e4313eefd3060ebe5a1aff02f1588002c55d2b8d5276423 +1c2c7cfbdd0bf6fea877bd5c30419e92fa642cdda2dfdee37bb5fc937456fe1f +0dabb9f058afbc011b2fca9edc3fec0b614786d133d14e2f8e30b34bc35e2143 +ca0ad732fb0c65c7bf7c1853f382eb4491a2da12e0193d84f90dfdfceb985159 +ebca2675b60dc6da402b99b23a9d612295eec4810e6a472cccc2b5e6bbb4a6da +11f93f84c7650daf556452fe85ef98b2e3f6933487a499dc3b638e4ea100d3e0 +57f787ca5faad40f23aa8c603f9388c799e996261c83ad4f632ecee8c0335019 +0a9544b2e66c58292e9257ac694885ef8ee4c4a9fce9ab392c630dbd0226e23b +66c9170d1932c87a93e52b776ed27c2a885f84c95a21a13af803ed9f4c9bd5b9 +04601b3324870f2dadf6966e8507f4265e1c2da5981c07c140a42579d7610b5c +7ab77de645c80b821397f37e8761402845ee8a3608d7b5161d7c96fb723d65f5 +d0e7a5a9c4ae2005831b51997f987f3e9c58a0fd2fd03f2ffa5990b2576cd54b +8ceacaa715096209cda6c271245fdbc5296299154fd9d5d64de4854fd59a665c +2c7553d4797632a43a60fb9c82ecfc617e6f30b558c4b225328dbb7b846852d2 +3924785be3d5d382c04a948bc48da496f05a125da3d112f964b8628456d50283 +8fecbb7289756619d2f39658d55ae2c314d7e3d1207aeab773f6df0b60c192d6 +7cb20c1b0facfde9ae50ee04a96d724385c4b60b4b23890a2445283e6822cd25 +a3afe1dfdd88a89569f050a1fb492ca13c4ab4214e3c2d2fcecb246bf935cde6 +4dc7229f69d9c7eebee89aae710a02a8ecd9fd43c1c33d581eba8c4055aa40a9 +89b95ef917e9d9c27da019df07e522192d03f02737daf056a6a90829af2336b4 +11bfb9f8f6834188432cff829c1a97796dc4074a1c6b50f7d6e83ef566822cd2 +ebadfc9da5ade3837fabb432be6f7b0f897c8b12a493a99fd0c4038da194f187 +5bb945af4ffbd8fa8a78d06f013e650a510c14817724d6cf20359e184a8df5af +31c79ef2a597967f755fd7e4e9b039568e7ba8e147c20ffd91837f9c20cd6806 +dbe4f5f3a88106328da179b7e259b5e63441ac532aa3b8d5740b1e3f6b380319 +48558d424ee75d360d1a7cf2142215519486215c35d8d8ae82830ec7a82583c1 +0996b934019ed1f37a5748ba06ab9414e852865982f78e6a83ec35c5925a2374 +cde823ac5447cda34a6cfca4dcfac955e3045802a349af109d40b86553787b6b +f0f116068a75aeed5c2f720897bfd636ed9b4f239e23a2786672d7fb3ddceed6 +dc98c3f27c68791566da54343b3b4217a010c9011d07493c309e2acf26b4b023 +da82d1d89ba5cee59bcb678f317e7583be2b7a28a0906a828c8feaee6c47d10b +dbad86332822e689c9744670ef4e2787a196c8a7b84b7c513b68c0e10aa8c923 +07d8b41868b6cc3fcbf2bd3611395df88f252f85f73067c1fa210d8278165f16 +9a849b23a36b49520f3e87a90d2df11368b7126e00aea49f3254d108aab0baa8 +519ed0f0f7fab5cd528fea728fe623074ca01addc6996026aba7e9398fca6bfd +3f7e73928c14bb58fd5f0b8efe88f3f03be36ff90fcc84d37a08c1cc0126828e +f2b59d870a73be9ff346f101f2c82379987a1c68c50b7b9e8eef9e112ff26914 +f5241f60ca6b4e32a3a43f32a9c8f94d8ea3aff3dbec72a5df9de63ed4080c29 +9dc68c52c9da2688960cceff55d5b57573c84c062df01b56521ef0ae5f8ded0e +da4d1c596a5b061af56329794539db71201d0bc78e6f41314b386a3d2f683bb8 +852f192b82c5f1fecb892fbfc1a9e2fa3852e16082da9986951f141bd4df6bb1 +1f45c4dfc8429f851582005c673a992e220dcfbb8f661cb08057856c28961154 +b4694edb6dbe58af90265722d10ae694f8fec785bbdcbb0e7202f06770cc6222 +4d157f89ebbec48dd1c4450dd3f814ee8ecaff5357ae9e4290c317bddcb5ab8b +0cb32904119894202a9facae03521fc32a5b68d9828be8a2de3a67880bf52605 +89ee5571b038f32f0e410d3b84a30a264adc0c90e04fbd04c25dcc8146b3277f +ca781d200bf3be8984d4b8fcb677e8a92868cd8492778ca4e391db41163df000 +c534b87b54a9a678eb9dfc206a9061bec2c220ce9d3c3451b84bcf4fbfa21919 +ea018fbc064ef31d31b3ce72f3d832c3ada238dfe9807b234f86e1b32dd03054 +bfd9737cf99e3f555b6615e570479d93c1706f050d0095c9f1681f3e140c384d +4aba0a0b16b0986cd839580ff1cc8dc4c084739eca39b68d0669b35ea1e9ee95 +6c10db54abad1f1a1dde32e5d95a0e11097ae2b74336d029f27f6f48acfb371e +c1632341c8a05163cc16acd1a94d1d9a591e167839d519c2d967f0c62e52647b +d6a0ed66679606d2663f29ec042d33ceea2d7a31d89234d70b9147845fbcb427 +d15b56e445ce1c499c665261cbebe93dd9fb8a3f54d66990a863aae745e37cff +51aa6c642ed17ac7cfa3d246a538d238cc121a3554bca2850d653f0b53bca7a9 +a9bf161ed9eb25e31b84c90083bbb95022b4d17bd695799abc1f24e83fb8c84f +5ee46c4e7f0ce0d43e1299d99ff017f4f7a81f1692797133e876550e93888ad4 +2f69bbda038befa42c51ef654a82db11a76886c26ff69db8677d3ac4175cdf66 +47b6ecb85a9c8975aa377670cbb9da357e1b4080389360508acd77f66cd11078 +5f71456b54ccc11aff3f52603a02c6b621dee1407c6430dbdf44da587294e62e +508eb8c074e079a655a5f8da46cfae233dd8e8d4add4d104610947263e72e7f1 +d5c4c69d256f41ee6858dc6694f99da81cf63e4e74b5374004618137a2e936d7 +9fa44701cc0739d9abcc835af08e300a57591fac544695e5c5f6ca3fbd3f77bd +01b8ded4c324cfbfeaad94567f7c0cf12764830a208edc53049365effadca1fd +4b3385b99f07f8a10b825389bea7116777f532aa96979cc7eb48fc5850f6080e +d4ff9b98368053b0ea90d9449697bf9347d791a18c396c360db9e48f9b13f7c8 +cf12bcfbce0be43e2b52e36baa650cdc163c3ea930c1ecb2436a1e433e37b450 +69fe65ce7d27a4c29bf4c789baa8ff4c09613c040f09c961611212d96ad05bd5 +d016daceeac47c5374f7d6cee93d9af9cecc139f306c373b9c0e32e9229fd6fb +b2813a3d1b419d209abc8f0f77d499d6d8e3907e94c62cff0545f5e416ff4b3a +8adbbd817ebfcb669a1b2c08f6213842f0005e288834e6045abe1df17d556664 +271d5f6e4724d44928ebbc5665ae24b047826d426dce3333f10cb007a9064820 +8764985688354e04b1065d02fe6e76cd2de4dc59db8bbc76599f52ee07fb73c7 +3e81d7598c6427361dbbaa099447dc5b4290e74fbeb3700c6e97513efb46bcc0 +dca4781fb88f1b4b82fd90a399e7c93298f6ffc4192706e297bb0ee074b52472 +0e170e66caacc8dc052cc80af85ffa278274a8f6213e930f12421bdf98ce565c +199177f4c3b179b79e7d6903756ffc79994b75a4f1b959636b5afaa9466a16ad +72f5c6d00f52907d599e4d74630fddc99b44a79aeaf75f2fb8da9e2f8531695a +62cd6b2ad58549db45c1b5b214489f57e0c0b1b2393ff26663b6e890c8483edb +dd672b22eb541c8feaf7bfee15c3111654e22f0a83380ecfe154c635d242cb12 +668edf31d90c6166d066ed228f6c76413149e5c848102008f14cd5560037a177 +23c22311d647a2f952461acc2075bda665090ce22480936236f013a4c914ff92 +b650574e9584831d68e4a399d02bee84a37f465d724b7091834b0aec0c255c7d +cec44abf3d6dabc8440ef5eee5a0656ac71b86422136806411506c6bfc7ee7fa +eff2ebdd9b383e2e468c29c1fb6c6fcef3a19a72010bdd2329a4cd3ed81b5ddb +7b4ec9d4bc22f05a0635775662795276bb0645b354bf0d88e65b1ef0fac98a2b +b3df8004b6dbf62ffc4b6a5d5b60ac44ec928f426db153b737d89556c4eaff85 +ceafc7e456d5620cff0bdfc6376cf83ebe9f1f6261b8c494c238383cf3d4d4dc +99b67c1af41edce69c756cde34d60cdd83bb5c2a799f56eea962cb18995d1b57 +cb1c9ecbd6845dadaf8f884fc963c0c873196e091ee977569d6b1555d0e8e1e2 +d56b8fd993471767b7a4e6803b5a42b0c11f438f3582a11566af97d5e3642fc1 +0685f0c7e7e6b9ae0d3099ba6fd3302c44fa6f4d04d5f42dcfd6d30139b9ce2f +655e2f47f680b69802e969e7f4d285cd8cddd4e96a31c08379c86534cb74b2bb +d03dc8ff3a027c4514c8019fce1514993457819a6dddfeb9b4fbf06f74c4b9be +013933bcc0100919e7337b9c728c52dc36c74feeef6f35121727af91774be2c5 +16620265a04e48ff2d6c58258417afcffcef9d8003b2f61d73114d267e0dc4c8 +b25194071e4e4367930df1411c27852f03e8727359bfec157cc1e530c8f28d21 +3490b5c2b6c12eda25baeca866ba5e6e14d0e57d428abc8857f3ccc24b2eb245 +5a93ba68ed1578b43922bd2085a904c106bb62e79e296e8e64732de57a7522d2 +1b35a5ad7f0c55939aa948644957479323e025aacb86fc71969d66ddf514ba0b +950f82e6d7125a6e10e2d0330062c8a015208ef08eea3e4ad6ee7142ba103214 +6a1eac1f5e1129be057cc83c9c75e7202be27e0e3904b1d47cd3d98b118ec78d +c3b3e2d087827a902287b12f91be7e8103efc2b0c85df09f24e5b43d028a1722 +5cfc9341d1acd12507b0bc091722e2477c1b827ad6d46ce605a7e510397b0269 +3ae212e093c1cf5d6a35170a9d9b893108c7f757f587c8614cd73ca0d6df841a +712bb119a8813db7e7fb7288a826a288e45654aff9a51b3371ea8c2b593211ab +fd72526d9c1845693af5192bae0aa640e8440e9ef8158c6069bb31becfa9238a +32990ef62fccf9e1909e8f07de2291281e2a1f118e40679be8fa676d85d10c10 +9ff9700c2dfc5a38899805008f75a472fd7a5938fde0eae335492028af9306eb +475b0b02bc469a7e45d8326d7424b8f33f70d22aea963b31be57947abbe06654 +8f1f0021776e4e9de5a36eb44c65a1701ea18c9820e7a5b835deb5ad75ba5c40 +3735d9bd2a174c6bf95831c9424e70f925a3946858bce621b42cb1ad71c76833 +49a3a7cf85a1f1c8411d8d2d3b82779a4aaa632ae96dbb33e37a7228d70e0c7e +c5f2575678ff83e8c1941ee5dfd9b49d410bf8fbacf5279e1f50aedafe113281 +0cba64e9db430ca26ed08e1bae0fcdab7b6feb52daee9368f70b1b7f0c69dd23 +3f4cc2edf3b166e3b895f3285c69ffd13bc2523467ac15cb40d91515fad53c6f +dc6377e3035e4d9e014e212205a492dc710e01a925320c4ac193cb59a4a916b5 +fad91ff8da91b31eb72e8ef788f880952a087d526b1bd7eb1e762fa5838acce8 +182de2fd6818520bd993c0d2f5ca4532a18c077578b49687ac2a637e03e3f3a5 +ea2481db65dd8fead1a547fed4b0020c0e4326d59acb524c65fd2332276abda2 +b3e238604776fe32228d0c43960791075144dfdd94d2389252d2d8bb0aebf9ea +63f3bec0e793ceece73ab3dc7fb750d2c91d0b442c54f38b8db64709ec566f75 +317aadc25e6b562b9070eec69c0f483f63a8fa8195faa765389c21f85a78b2f7 +f262e9bee5152abb4022818d238f4cc73fabcd291764cd89b13565c93f2dfb03 +be940f078df23c87ea8dc42653e5542c8fe2813ac95652ad001d57dd11b90a96 +88d4e0b4ac08caae2d74feb6dd9115de259a358d83f1dabf7c127ba346d007de +b7dfdfc4fd7c68eb12b7089fd15435ceb18a72747af68632b2debcddc21e8216 +453f7d28512760b0c3c25a8076d8dccbc6b98a1d6100fb7c1dcf93eb30a1981d +afa539047794912141927741237e96be9891ff264cd399c4aa159f83e4eb6aa3 +180beb47e31f3768703a21b8753cd92ebd81a49992f05c0f1eeb3c4683b494bd +461e2efa8a68967eebdf169ee03e972255d868e036e4ecd56a0f83cdcc67d907 +6c29eb141e4778ed0f01311db8f1c869be9ff4108afdd9e2a7407a209fa4217a +afcaf4571c2ba9649635de546a8667a6825762ea42e00ea923abb4e2560f6536 +4db50dac39d9be24d036cef1726a4fe9ac59bb38e23b19512ca772a053415776 +a40dd0f148f1e2e7aa99809c81659d5a60eb784a7a2deb5b46a3f8197f96e212 +98884580a08199516b78fbd18b6634632f01865f4387e8e1c8a940272db79604 +1a4fea79ef970c32fea41b0db0dcf8d0ce4ba940b9a50b7493589737845fe212 +019d54bba34737911e24268cf2a36362ff3ca6ceebd29712d6df0cf1a747fdd0 +2b50d3fa6aff26f3e635eabba2b9e57ac890b20833fce797bcf92f807c46e41d +afd6598c154ed167df29af4877dd8b42f1913a9860706b72cb6503ac1f5ebd03 +b81b9f6853e338aa0076b846e310c894d5733674d3545bcb205544b1bdf2e737 +f2425cc4fa6602c05aef2dc8266c3a490fb57edb6eee725f5c7b26bd58a337d5 +52695c2b84e35d0758e2011a455c346f063f5244ba4646f0d2ca793e8da03de1 +566094adfe10546f1b50a290a15af7725d660476d711216ebabc83635c47342b +676720e460515ac4fbdaa749ab8dc5ae1fa565d3003099ea80b6a9b458058728 +4f9063f9a6bd78c1102ded4522c8214988fbee271c6555641032d2affedd1d98 +2c970a7345cf7f20191265a07d0aa0c6a3ba25af1124eb477a5715a5d2c17af2 +8c76a7c633fe50be2979eb214c51f98eb1370ce197b1f876a7bb6faac9b56203 +e6fbc0374ea811478e8c594bb8ca5d0929721d9ceaf4d4d1591581061bb30364 +79366078e8bfca55aa51f636b67ee46a0e8d0566ef36a1581502c3960c5085ee +19f208aa5e5cd0e7fd5d974e95dfbe2046a3c7990b8612254c169b579690256c +001da431e8538d5b49457663e75be3df1f2d09ddce45e286d1a2433bf545423b +0c7311ebdb4a6422ff1133b145a426b22daa72a6f65e02907302247195785513 +6057b8ba2d8b57ca654f85af022c76aef4a790eb19bd3e7687a307ed1f84544f +8f8a933b5271684681119de23a97024edcc3fad98a2f8646586a7c4ba5dc2181 +f00e409838b552ff1ded863886203117e11afc0b0e18171981c3fa5f1fa748a1 +0e171be6e6cf1a6bf8fa161c8b2b7ccdb980231e34c86582bdbc5f65364174c0 +d087421358ae5353ae0d000836165c4a8d3f7029e047641282e44780d2bd800c +83c591611c58b8e33b778e397bdc79cfd1107d34dcfcb356681d1091ffe21424 +0ac2cc22d510792878587ac5cfade34595de42d90f4b92b9dcb59518e72fb74c +c6fa18b3ddec37918a907c9aa7d504b95f99c214afddc479e8eec920cf022f73 +7bf09c99b60ebb9eb85f901c374da0995a4a1ec7ddd5a63cbc5c122d9ead04dd +02adb7c3ee04348644fd5b3559115baaaa65a5b6d07bd130ac9259d786443d72 +d6f6986d3c7bbdf76cddebf1dd124f23096729443edd36eac8896023cc5c03de +9de01f56d34a09f0b8d012c47ced4ff569d4f5d452e1fe6bd5267b8dd6038ca7 +77de84acf8f8a9f4f7b1b832d8932f3088dcf2c7d540a5a5e9b9a5827f1a3966 +b2dd65a1c1fbcbb7c7f2cf87c299544d539238bf5b811cf7294479f681cbb9ed +a51aeb63ac706da7550d71cee5654c995738d280e111f458010cf98d7352cf43 +c4ec5c4b716667140c572d5903daa78b16e112f5352daa644c3ee65e7e6dc03d +83ee292abc9e0adaa7cccf32602ed2e6217878ff29b7bff261b31e93e11c98bb +9c1ebd925cd8840599ddf0585f7a02ba5f6e15120c07bb11870d56fc92079ea7 +2db4864a51cfb428624a0af32aeda94595ca60c32d501bb4850d3cce5387b3d9 +f8948b71a11a9b9863fe351eca149f0fa9f6465a49b9a67bca804682c27358c4 +d551234d3914009459f55719c4c74e5b358c556ca9d9fcda2a8438b57f6edfc6 +5f0b295afa8b3d93906bc594690412677e81230eb8800d1b3b9ae41b97d3971d +1894ac085dc100f94b9d67beb45742ff524d5e18dc9b0a4ea62e57f9f650da4e +09c70b41ad94560d336d480b9894768931bfeb0731a2c912cee5daddce4899c6 +59ae6d53ce01a4d32128015dde5f1ec558b0c266ab1378a3e21992462318df80 +fc1d25f84f3f00269e573096098b4918b7f48a44a35e285d57b29f220f679569 +f950c72d6990144a12f224020c6edac83c7edfe325ddd64c5dd2eb9da0ba0a7b +f5cdd4aa88bd226f9dd0714f40b045133c84a5cc8a447b3ed265464515c86e6c +3c14d0a2888800d2daad9c541c15f43e40baabc58d5060916407bbb3ad6fbe6a +c88e4b4f7090118ff995e245037108fb155c72d6b098ce0f7a051bc80f2278eb +04b64468c7c241e308f286e0e82b54f66855aca2e1fae3a405505df79a0c6cba +4bb3600507be0f0cc1206fdf01bc6afadcb6fed179901c43519a35dbe0112fe2 +d4d3314f86972e1fd201f5f21d479a3e980f3eb4912ab42bf7d1a8aa5ded4632 +b6390b875f4ab665f5b9d4eea9f355564a3392bde2026462c93a03d86a787db6 +97d3da00d99f583acef733b036122a18186c149e05ac8ebcad8b3caa7cd16340 +3404bbc9f501eed3d9c32887a27c395a25cdd6f3b2e35ac2a56b07f707259cf0 +2aa12a5d5986379ffb8851bb3f0850bfd7993c2878bc689ac0472b40dd1ccdfe +569f0b607a2b054b3bfd947eccada6a97344ddd6e3bb34cd043b04755691e88c +17772e19722b28046720a2bfab1b831f4aae3cc9a2e8227cfd46ff56caa6ea0e +20d5b7cc258fd05a2d7c97f820b6f3cd754a4f608b2da05363561e98b83b8708 +8ba9365525bdc2afba88484ebc203db6377f21f2e77db8646d956943d4b03388 +545a881796d4e9b18a59f5de7b593c057f0f39341ef93cf833afbea0b3466b4e +87a4ce13fb456512f056ee81492271010f9d0b7c87a85e46d3372c80666fe3f1 +f14bd0030afd372d3dcff914844d15d9cc9ce0aebab1e7bb31f350896f04eee3 +2936e348a47424ce7d8731a1a9af0838ec171d6b282f7d27c1d023ceccb33555 +5b25a319b1d924082866e4f0af23acd80b7f44b7b2d01976f2620b34dc02e899 +81cbefdc5be54bb4341aaa4d08e8b9e59f18033c4a9e81345c5af6dc0f020508 +8a5a50cd2214c9e771d96ea714b1770bbbf8bf677e4a7ecabacf8d9477f59d19 +32d5333f995f259ba32652b9304d4c835526cf8dab74ab4a1318842dc9b48fb8 +838397f4efa5a2ab639967761b4474376cd028600003f2d534f24e326206c4b2 +4863e38f8c4e4ff3a1a444c97dbafcd68bd4f3287f080112d7bc42e9bc4872c2 +1b3569aeaa6292068b5a57491f76ee6d1a24689f0bf829929f8d36e55cfec0d9 +1a17b30d13ca0f5a22d1c8818ac65595c60f6ec92c29b68ef970b2bdfa118e33 +b576e77cee9e65835a175e7bcbc383b01d85f59fc84b6ab3a03ccd194ec4a79f +220cc0dc1351005d01ef54e4404178ffd17686735c7568fcf20a1b471e0a6da3 +e7ff425eb593f919fc664a5633df8e3f57062fda10befb9adbe59d3f21d12a7c +8df9b78034c6d72dfa281eebfa03d7fde94b12ce1ad639ea67301baa458fadba +07a66add59015cf5122c027be7016238900ee14c2b5317f7adadfacd55b4c493 +fb5faf5571a53d6e7e7a01549cf395cabf60bc0d4fffa0448ace9c1123a768fd +0e35393afdd608b3128115bd681333ec9a864edd3dd729709896c188621a49a4 +e5b1853e5514b2fc845dbd6c575b65b4fdaf9687be91566cf47a22997fe3a301 +9a5bc8a911b1f5d187c3242696ea2c31aa1781a6f95028755298ff221e4c243f +41bc5bf210bc1a3e6874bf4307ef2b911289330464485704e8a50e0144272c81 +75d906413752754c8fa16eb301a531021379fe7a847acf53a48d63df447eee98 +d7f551f8c97199afca0471fb46ede464fc2b91f405b6f1250a0b41847ae4dc1a +9a2b7bff52614d395eb97ad86944db27f470470704ad615f8baf1926bb77050a +2434a20103661013fd653513c247249315309ef31f4246e3447e5a807b32f9de +ab6ccf16e72800daf3a89c34277bde75a6d02599fcfad66cb3f010f77eeb3081 +a06a5640285490ba0755ac091af0166bd81e38bc71a62df9ae3d2e8e17cbc62e +ff4f882f19647d88c6947132ce559de0730f32ebaf5253af098df70770320afc +3047c52de82df92a1d087a4fec2e76e4adf00d5cc617f95ea7e1905c84ca7970 +c0857f2384bcb4d502447dc58f2099c0c626c3263e61cb3b3e7e8f74dd4d75a3 +adf2a1e8fa5a98e206496c85304c1f25e377d5ca34d4b9f4edc45f0bc710cd07 +0c72044a3764bd2196ef2c436d77333f78951f46518f8544fd2dcc0d2931bd48 +55ac4e645956a4ef0b24ed9f3d8b4b32bac43f9d91549110fbd49f72faf4130e +3c329d65029f9606fb4e37f15ad99639c23940f4226e313c3c4d3ab9cdfe6199 +873bdd76cc59bc360a87c37cf739adafe315f34f482f25964447dec8d4d1afaf +071b8695aa4f9d0c56a32b4d9b664688cfd60873515ef90875790fc9bc140d40 +bb4e7139c280428dde762d22e574f9416ae712e8df98710596a8dd3b47eeb9f6 +6a39b9d37e64077b5d056b8f866d5ac6a0cbb8ba7e962a991339dc93537bc22e +6c6a34d6c30db1ed07e8b87de2cf6950f208096c9f6c9ff29325b5600a126453 +82d8eaf146186b2d87530b1838762c2ec6716f94659b6b935a63158300392a50 +da1f2a4ccda82fc3846c9aa88f282067bb1bf377a07d28a79330640d1fbe142c +e86b91946ad51911a8d46e116012034550182f4df6a1342ed942819e0c36fd90 +304c93110653a1e6fa0e1b3f335bf737244dd3554b89a8e068c4cadb4ea7526f +ec091a61eb8845b5acc3ecee137820a68389e71ec21cde0114574925a5718359 +f543c08d50accd751f2637f8699e2b58ae7ef3d69b4ef1dbe347065a86819cdc +492e6d46fd5bf58a63e078df6678f71b189c56fdd15f1e202dfb909019e25ffa +31f62c0dc832133f5074da7077e1deff287eb6c67ac8e90e89429ca4a197b244 +e493e3a5be89984a8b2f48d6ac51ae118d31f5750c8416199d1543c88c712478 +6e9b613b0c8601381916755d9d2638206886012c8a94e3a509fd97d04b8fc30b +b8c34048d12d4f2c21c930e9346fbb4e9cdfdf66dfe7f56234f8db18f63cfac2 +8c8374dba0fab6a3100df67f6b71f1613f3088ac91a7d0d3d1447969f1a807d2 +3149aae0706a166b1b22e1b3e7c4fcf8855edf32d8cbff5b8cea92c4eba3572a +7a769a4e57feb825bc0be7cb3f4422c763646847544787b0cf0fa483d94c40a7 +5b5f794fe37c6b37eac85f2015c46a1c74916f4eaa8302d9d04520668dfb59c9 +529f9809385877e87d082e4791801a6ed73f22fd01f302749684064d9d5bf7c2 +760ff7f219375fd94d8891c717e77fdb3f4e13f782be03f34e5eed715540c881 +89df93ff94a0f3f32b3901c0061391846aeae723a64469f0ca220bd124fbd624 +d11dc9dde6fc58d94625f47771bc2ee4137f27ad1abaf12799e354127a9ee70a +8c76d4642eff7f521a606b4e40911a7e020a8c23565cf67fbc5ed1392b8ae501 +a86d878fbdaeba333cff3572670961176de205cd50d5e987f6d0df91f2b228c3 +396cff3794e0fd1a855aa9be5508516c0233ecff77dc0bdf81a7cc8bfde40a75 +4a051b0b7fa618fdcfcf1cb93769f5849304c4bf0d48b814274d2f4a4d5fc4af +7bc4658b38addfd124f9357b077c0dc732b9d73e59ea40f0f1f3e761d4efdeab +d7a96cd6da40f844fb4eb70e00d85cccba060dc0d3cd0d3ceec12be94dc54e3e +811c2c4d9076d601181b6892c5c1d8765b2bba6900bb9ac215a1858ad78acfa0 +eada7ef2a9e0aa3515f7d0849f6c421bbaa630410b6aaed2883de6e5d3d5c7c7 +ac2a71f3377b7c650b3f78e15f3a9ce435c2f371d09dde7ffffde6069d98d0a8 +617e714abe16a9e442f0b3eb22cd0261ee02938df0cd79c17fb2965b1b98ac62 +dc89df1dbb1bc8320b5c50d88bf258fec36d768e3d4cceae535a87bc6243ee5c +943485cff5a83fbb6016c74365bb734c080493f6d9ddd8f13796cfdd3aad671d +3708ddfc796c2640833c61301671fb8fef2b88371746e1bbe62b597c9373fa9e +c7a7ebbe8abf6e9e406bea97cefd91b019da85c9e54cf71e9f52b114b547777a +47567454ee0c9d5380deba96a0c0e2c329d412b3e1eeef7eddd90f814b160777 +85cdf15d2d1ee4b81babeba0872b5451d66dd72a38a38e4263e63ada9603e9d6 +7d4cf799aed0dca2d5357ec7e386fd5042e554b1340203329b62eb19acd8d68d +3207611c282dd84876eef2190f01fde7059aba370753eb4626de6f80b0a6b7ea +503b2d4c5bdca9e9e7dc84da4b3202b5b1ab19f60d179b7ff78f9a97e22a6ce4 +a93b730c1dfb7855c341112bb4c6681702bbaef7e547d7177be9c02377e5a23b +3064c45f5f6b03084cf8b15ef1afd8e58a2c538426841f36bf5e99006a6185ea +8e85b3a06ba5f35ed59068ee1a55db79ad815d2501c36e716e11ac1f2d99a75f +85243990d1d91a1d9916a4dd3fa98476b38bea752ee4aa63770d7654145008cd +f8e47668e0b384b900ecf41b4aab9eb69e152f3ebfc224dc8387c6b997afbc3b +b8f02bfd03c7995e8fcd57af2ac2f312f9b88a2041467ee6314aec3bb5ecb25f +8937a9122119169469d06033a6aaa472360ba3846d3be7686bf5e4c7ebbe9ede +55f9d40574dfc8c0b90cf37ed5f3e8adda9818c95c3f6fabab866c0a04dc22cf +134c22cdfc2c5f934f4b995899ec1851cacbbf486cefdc83b463ce1ff62b4f04 +04d905ed55e2fc161ca22340cb2835a0f2aef111e7af5117a2393c9077f3f8e6 +66e4c7fc339d65d14e65354809003bd4223c456a9dd64b21202890a336f8977c +1130000238482fbaffd3bdf1c0edcfb68fac24e02b9fe1e4b1fcff96f3c7555a +5bd53ec00c427b844eab272bb938305a05f3643b637c14ce1b075a3ebc8e0d4b +d491b2c5b90c083766271044eac63ee468226d952e8442449c3fef2518ee49b3 +3d2a532f13347c9e11e3e53baf9088fc9b0b86c426f303d45e0a09e43952485a +b1fcd6353bdcccf30a2b953f6be60f52a47e4951df38a13a12e8e465137b87b3 +6953e9babf2009fb6f91e2bc8cc160e81fabba5a912857a0fa8eb7b5fac5d529 +3836639c845a5f44b86b3aaf5a34e8e65cd1fc125dc3856e4f3a88485b75622c +d434a967ac360d5ac61689e3efd76c05c0ab1bd6644d7e505508ae0fcba4b55b +767fcf2e5603861cb9beae686355918c7159db7fdd096a9f8e018bc545da07ee +d3419f5e64db442cf8375909d9347ccaba4b5a781be9bdbb7aad2c046a0953b5 +acc889215cf0e11a7822a6bc009d579ae0ca50aec158395fc2640baad2a902c3 +0bc4f885666db91983b6bee46b9ef86e511560350f17253d822bcf7d50199551 +7c323c70312ed0de4a6aa4c2422370f471554d80cbfaca99ac0bd010b2f2b718 +4dd8384a4606a8cbfb3aaa94eddca975f465ff43864d6f39b235d47d371938ea +11dafbd0bcd309360134fcaac1bc88b5d149d3b1ba6188f66d69695642f0d100 +5bbd636c17e1ee1766e3b65d15583e9e59bef57047dd180202ef4c3993010738 +c1c6f85e545d38a8ed60f24795c1cb5e5b314476f76a0688f24c6a14036a25d5 +3a9cacdda825c58ff6c537ef03cf78bc08628a2c8ebc698d1637b18a134be31f +847845f5e928127809f00ec51133c0d6238234a8c33ca1c2d0045cef8ee1eebc +924f70a7a99a6c66a7de28275d4ce98d9aa2839bda58fa88db0d2c357018276b +870d6aa199794cc440bcbc57d1712eae621c3590ce5c674199ce218f4842c77e +e2c5d024003c1e0481e0c4963809dec27d236e13938b977b286c903b1e3014d5 +b21eca7ffc25fd1ead9f16dcd0cf7086c960812b4a6689405581ae9e34c72902 +7928ca9bcb8342a9c5b3d4eb87702359166a4eb5f286c5bc49f0bd1d7f6286cf +6698930b4e00d35b6b2ae46c904cf2a6c21ec3318c4734f3047aa8267bf1ec37 +136fa00f0cc745e585298e48619b4c4a20cf4f40572d268d822e43cf58be57ba +488471a6f3c1d6efff41b49974102d10c7ef18c6d101296dd0df5f308745d1db +221784176596c168302f546e60b27257cd17a79133a9fc97600ec5e3d7aa49d9 +6ee18f505411329412af3fd9715c2ab867584b716bafe9c83b5d283e3dcfd127 +2d79e4891f431d77fc40fd33e2eb4a0764314c585da46a9d4f97a09be6eff786 +04d54ba789e362a22588203b21b0a6ffb5110ad7f8806f45160e456add5a2b9f +068b2e54ccff0c2f42a2204ab0902111f34210a0e4a9b7bf95a18dace87f1f35 +7a34a02afffe4e15d412c86575577fd011a5b5176883f7e3c60f1d3833748297 +6179032b642ef3f4cf3270e1b42df1cd9e88b401b1fff85be269815300c18f5b +fe02460b1ee2e8a9b1c8ec956fda009d07e4b12d82567646c72cf2d6c29256d1 +bebe6418ddc33d13c8316b9e4f102e2d4c7c2c14774bea25c5a5323832742e36 +67e646df288b864ef6dcfb26ca389b8c2652e6b4a9aee9b20a089204f94e89b6 +353415fdccf618891ab6694c816ec49da9d51835f190e5e3d8534e8c85311ace +bf21d3677e6f66cca2e8c7a6386b63624880e3b2e650a659a9aaa63fdc48d557 +07f2dce64c77c3acc383509ee98b2b9392d44e7caeb70621ba808dc714f127a2 +b34998265a263d199924b89f007a6c0556dd0db43f7de06473fbc7b7cb42fabe +e4a4ff32f873daff2137c98fe1b9fb7122142616b4390bd0078e81d21b2c4a1d +bb562abc0ade97283d880f9618292552d8f8b62b377d90216f983f12549b3d89 +19347cd92c9525bf2ea1e46bb075363347e732e92508285438d508f5b200f674 +d614fe53796520e09a2c3372c58ad840e62cd6c2d925356aac3f7bf1b7738ea7 +0ecff7bf5dce5a7d7e193bd7cf174cdd1f8151f21baf98a995ef46a572802462 +b5dc3225927803486eb8ee9c6c90c15ad431e77887f5b34fc467ad3fafcb5fde +bcf6af81b6eab9bbb0a3a17fb430f9c790f519dfed867fec0944d82965f34156 +262934d1e4e650e90a37ebe57d2c61d377d05436b1969c059c8b6a0317ae9b8a +0414a5fcc72aa6caeb2877a9522fc772c53b8378fb8b8e0e235712a373187b83 +d72d8bb055d347ec03cf8071fb7c20c9602f2f639c71e64ed479f2df5868a0ab +b9c4d2fef497ace71bf01585621000f86de2b6bbb8c1a5ed831fd394a91ed848 +ef38d5bebc8661a97420746937c22786fceee15229eeadedd50ec9883351b650 +0199c94470a0571904621296e804fd023545234ebb26dcf8e68cbb7f7143c366 +2a20287bfe7450abaa8e784abbb3da5f2e02304e2bf107e31c1c4741fa6d3398 +42f2134a2d4db29be19486e032922f541021a3863bb69ccb41a103bcf13516e5 +49a1b899e11f07d146cfbd095cfb832c6cea1ba2931a227deb580273e6f5a0d7 +4cd70e6e31e37c631fe7bdab83dbab86bb3347274cc2301c23d55693058ebfb8 +da9586ec91d681d6356aa6c37b0d0727ee2e6dffa230004cd1d7a69e240621f9 +71f3d8372455954506f4066b2c6bfb9984c9c5ed99680600cd5565c194746ebf +59bce825de6223426c7738de852d34c93f606ee962ef9b2f84ed0b862480d4e9 +5eb29744c0d070ba6ad130f5730c5e48786125dd374c029fc4ce9ed6ac6dfa1c +c2577e2b9999e249291ed429336876a96117ae680e08ac9e5054f3c04acdfb02 +717c1694d145c02d0bf4384ce80db160de54e2ec926302feddf9c39de436d610 +205c3249f4db2b0858d93552014d451e2ced9663c7685ff83c141a8a013bf315 +8c3b7d1729dc9f699f077a57012f68d15cc259bfdfc0ec8b9010355525c6f6a0 +5fe38d70b88c57a2f2315685a2780e6aedace2b650981b99f1a755e170016775 +0cac25d007720c63497ce5cd72701220511c1607fb197f2bead3f6b1ce687e0a +f2948d545d53524b6a2447176cd1e74e0875ac0c65fb0db5b80b5cd08f6f7e2f +cc4494f4fe2c9a3b28dfc399db10bed25c68006b3fe825a3833878238c6c9b8f +09cfdc05c7b4bd7da70264e8a362dad85407bbaf61d4fef1307bea381a51efb8 +bdc5f58ae5b0fe4f57a4b7b2aa9d3ae4a77e3afb1ea7aa15f90e193fd6c71f7e +576cf77778d1974bf82689655fe724644d5c99f8b677cb274f408fb3e735883a +7032ea2296d285fceb0ea61f0e5faca3d0d6d872e678a08668100a922c660227 +26359b9c697710aa2da2b248a1ec340ed7d9d14a00e89f191afa7cea81a4994c +6b9a0d92edec77060da50559a0406a62c0689edf9c120357d8501845eef12825 +b99f131d80629b31e4647ba5863aa7c275298efa02d03a97b83f9fa41a17ca54 +314dcc0ed7c476a32eba2f9d7a66d9f796423e906d15bf20076733f114021b0f +2d1582ade5aa69bd80616c7ff7ea5532c888ff0ed081542440c0195c5c198670 +c9b27898f8caa2cd72fab731c147681281cf17097bdaad36561724f1a61155e1 +f2553340c53f457c43f69e0b9f480b9bd458a0419ee037a03d84b2f999cb81b2 +72a739f7d0ad827f1b38c2ac4bfbcdc14e400465f17ed01cb4f047c1f0512b1d +c89a94c2d8d165b5f290de471df3d15fa7d5c182873ae58556ade6e86b28c9b1 +3d07622ae8aeed896b14f9cd3b04068da3837075a84d5037e7afc303565600e6 +69850ecc0c7eb301e2bf271aeaf84eb09dc61229c028fc10e7fd270724ecef5a +0d2e2c85be75bd11bc33bde504a1a8873a512b7c7312783bee6e9307f933fd6e +a5d90721e07922c99eedd5fc9900f85a66b356c56f32cdce3c7a6e994fb47263 +c318d82035e2b9a5f05b34d9c05ed5e95a6cee2d0904837aed3bedf1e9a3cb01 +0d1a2357386dba87bfd9c27783cd5578da2b0f5ea5560063c36dba917622aece +c6393da617b08845abe45b6b3db1e9ea99e54bab9544c3173dae5e94b1078a79 +1b97f7dee35e902f75c1179f8dc828d12d94996e26e01678f4aaebe5aa43d37f +de2d02d50ed080ef513ce3bc53e870b7c453fdf46ebb12d24fce859a8bab685d +37db811493951e84de8694c18fe465ddb0a2adcba5184b34c62e6ab4e71bded3 +701c709e4820894f39ff3a5409ca27493c88c298970dacb90256c77af9efd88f +69ea0408d3fdbd555b3ab988beaa62451fd7052d9b341f5f95813d88123754a3 +47b0887cb97f339db3a7d6478e4a7e4d714648dafb6656f8bad04e297bd8b256 +609c84ced1b423bd4423cbecdc6a6a4a07f42fce3f4094cefc66c84ec5a11df8 +ab5e9c72a440e1be48b906fe7e70250271676479fd3261d3a1230962f3fa0c3a +18db1b98b652776918541526b974ed694ee1a127c4997078b06d724d145094b0 +9487b765bd4ecf9f13368d85f192b450fcf35f031defbcc3f304abb68c780fc8 +d4e329beee6b32b8d302cd94aebadb4761c8d1e55e317ba21a8245a3a7b6524a +cd3321c6e353bf4965c39739357f0442488edeef1da940474e76a64d83a2efe5 +5cfdaa37e21ad27785f6ffc572d750ea16f2e27d2dd2b08f5704456817288892 +07a209e6fe357d503382e387e57c00073959b8c1a267da6276feffcd9e7b0a67 +726fa7bbbf88e7d39a519bcea130364c4d00473f1f6f8c5a6f0848700166200e +bc7f567fbe49115733de41d7d5a5e2efae42c4a6d655d7793395948d884aede9 +8b2e41e05a43a32ac425c370315f86ac015bcfd48ce58e36f306f4bfec554fb7 +dadcde4f3dff3cf0210f658d44c2ca26a8480f81a45afe339af208c618a5c6d8 +b3c837958e226f197a6ed44f01221ec9a138906a3b574f39f0fe3ead400f6ba5 +f558b9e370c3416c972d5e0133369b9a8214d29e18c050862aaee801394ef456 +b42cc3fb3c1c1664ae32b14c78d7db4830b6abb93e88542fd17bbe717d737ead +ca855e181f6fecfb8d3fac4872a0cce9d65752e54bda81834eddcdf349e2a4d6 +efdef8ba00948f8e3515ea1cc88b17fa46581298ac76c308c811db98644d10d0 +8130a4e7852050b58972110f8770213e663b20b82dc7c6964ff94fb4db0cf7f9 +b032ea1519005d98bde056e1121762e0526632479769857a840b3bc864db5c4e +529c7ce95b3f3e7a8e479801a3ec6af7be6b770668743b6e37189d2c3f618209 +d83e9d1dd5a8f17e46e85a61569dc1309ca0f5fdac5da8493ff4aa0cea5afb9d +57b70ee73dfd9af43d82a9b8fca9c0a63f2d709b11f0542e8b925d33ae2af35f +2eb76135e935e821892db40d1d8b56fc8b94805287cea43426dd85710e91704a +72136a2cba8dc2cc7e82df59c04d3e98cb4997c20cf513d26925ea9388e75558 +d91fb8640dc81f67dcf7e2aea1cf6bfc4f900fa8beabf81ebab51d5116299ca6 +448b98d431032d846c2dc960cb23c09cb8181e3f0734a63a735bb5b587d63a49 +6fb8016f8c51670fd6afa55a1fa00101ae972a881426ced46f9bec3343ff5f75 +6d301496fab359726365d6fa7a69ed4bfdca99728c29de4ab0d04b565f4ed2cb +af190b9fe5d58fb6141443da95f6e652c529f38d336fce0d8d171763e1dc6392 +17849300b3b46388d90e4eeda8ad2bb428752ce2c9a8f54f10725df7b6c57a32 +a9f39e8ab60c4d02981a2b194c01b7e23fd070173ba20ab8b5d02d0969b7cf5a +eae74ebae49467137f76627ba8263f258ce5a92ae7ccbbbf844a87d7700a4d0b +d1ea13a79d202e1370ac3fbcad57cb8cde150351072a8addc01e66438ef58b9b +ed57912d50544f490b3f4315cdc250674f3fd5ef29c71b174a73202ec145df68 +75d26349462d14a82f0ef02f58ed81ca92f8f921628617379011fbbca58eb1fc +12c67e10cf696fa0a76a5696637339afbfc89635010d92aae016415e67d02488 +49a7eb01f7dd0223275111a417d85249fbbe3866c0608bfa3e1b95987a363231 +f52540b45c8a4160f90ebf192178cf52435c664e07ac620618330a92a86ab918 +855265f3675ca5d7d400f12ee41a718b476443ac4642db447b3eba3643a58418 +c0d87e719469873efc0443d8f3545a6685202e032e04b356e2f9a581fe9f2ab7 +3e7fdfc3b9bbb342c3b87d87c5060d0cd515754ef964327b346982b0e8e4ed35 +a7da95eef77c1f44509636a41544d6bf8c75c4134ba5a84035c0ff9d7d31b974 +3473e190c3f054041e203d33e7a8d873c843079b7ce4282f62817c269a9d1e74 +67159e9931fe444dda75e61e26d554b8a1b4a8b347b2dc3abd701d470093ffd3 +2749d7d274f3d294999b0c80368b0508498829bb49867cf0f096e7a53f2b0bbf +89e25408f93c304bad3175d0717f77f3ff0426937a513f162adeaab8046a467b +e4b46a2b28f2b710c4c3e1299aa62d4d37ff5fcdb9312d83ea7f67e61c6f381e +08a4cd65c71008809fd2339f4e7c03de4c4b697bd6b706e1cda8b583c0088725 +6921d2f07936c633b2e18b1cc5960486cf9a43b49be59f721e0206a95c71e81f +f917d25acea663912b4518b018778923811a5b28f4a0a9796478ab20dbc67e59 +8a122182cfda63957e4a26d08e5a1c510c723259058352c1f4424d0305cf4dcb +c2175d452e47e7b4056a75141fac32db357a0686eda9e9fd7d51f17ae2a3f48b +111079ce7582877aa2001f7e7d1548b6d701c5028704e0c71c40cb9d7677ecad +c9ca2b0417e0846a4b747744df4d08a1aed6fc8702b58eec5d260b870046cba0 +24819da12ef67f0f073d20d5de79c5e9fcda8cf6e59b9c61c8742c8e43538c3e +afd100544bb031a47a2e5154abfa3a8379879749d2c1f9ffb090d55f7da18aa2 +3ea6a89fde11b84190a54e29f607496b5fccbcc3fa1da762d52ecf7b1979d2e9 +c5be884fc398ec87c23f572785a4cf83582da3d03cee2571ffb245257a1181dc +9ea45376b2cf389ce47145d77f414b9c1528b10b66ade161c8e76f5f01db0052 +9b8bc8bef375b8721c80076ae2e020bfe3df5c84b151a6df4322a095d1b56a4c +b19baf565ccebd08f06e25739c743a1ef4aafc44ada66492c87aa7b6fb8935bf +8460a0488eb6867152e55250e073e988073a2a49e261f2b66dde7e521d683ff4 +5d2d2c9421e5780ed85b9b7f85502f3c5e62a2e0c458e7430ceaf0eafa02aa98 +f4cf886a88f3743bc0f9fd74db933b5ce3373b4ccc66188679dddd147873e026 +ac180086b92954a9a2705d7f2f20b20284829af4f9ee037fdc134062febe4d53 +6fadb4c294c0ff4bae91af784624aac3c4e9bfd727bf0a57633c34e96bfb2bb8 +f3d7ce00fbd810877976587606cfea18ae626242f88a845d5b9516b346490c39 +023c7f7c0a9e8293c67e2f72579180d17f298fe7eac14e3c5364122b2050a6a5 +a30cd414f66e3032385dd173e19d161fc996e77bb81eb94eda73e4b26efdab72 +d2be0a2a0d381c7cf3ff655a55eb75e26ace8513ccd4cb8ba46256c5a334df2d +663c3da0b1395eb89b067778fb98e0ecccd98b73cbf6f2fe070c5dd6a4538cdf +a8cf8c4393046a4847d422715499ddba705058080728e742babbf17e84fde53a +8032a59def1591bd6dbcb3b47c2597a9a60c797384d0278b772043a1448f3520 +23acda8876456a3b94c82bf6822609739a06e6c1a8de416ddde8d16c7bf01155 +46ea6d6d6e9f165f05fc063edb571cacd4bf65d74c9fb903771a34fa9a99bb94 +d72052bc9aeb1aaf93b7e2a17a08a55af3cbcca8503d552c7bbd9659fce2617e +88eb49754abd4897390768e4bfc3a9b6588f3800b9440f338cbc0c79ed287f82 +dfc6de330f8988cf6a2cb290fca612a1b8c4f1e9578578e2c3f9b102874724c8 +8a1a0af2288962beb2700cd79a9f66dc348981b798bf30ea82157edf08b6e876 +9773656980064c702d78d3c6ad5537d722a3fca572637bb98898c948ac8c7a80 +2e9b8899927c5be96c412708f1c988033e09634f84ecc6ee2fe2aa0e80c9180e +f72abf3c8833d6337ec4c679d9e186eea69f454db4dd4a98e968fa556a2f822e +24343b79daae420a0c990467c988c33cc3583a806c34ae5e8815bd29cd535cbb +623c01ad938372b98db31058f32b8c8303a4675edbea04dbc742b5f6f858c9ea +225d41d387429a1674b4179de9fa0758465abdedc439c5188e981be7d0240adf +7eff1fc847e968547af03366df2840c1d0bfe602820c16aa7482a9393e437067 +5ea47070c87c9385abe1bede352f107d6c1f8bfea36212d56ea915fa39f69551 +38b92eac8132991714559a28fa18c3dbdada6d48d9dfea512cf591ecbfaa0319 +bdc06aba2d52c8022156324cbd718b6ab3d7623f45438890e3e6448c184d3576 +2ea831c947e30aa163372a2c22e52d573a37f132d137065a405fbafb1322647e +d2b4b69ea975c8e9c87bd0ac2af84c835f6bd05338fb3c067f1211d0309dd67c +2b07e66ae6d5a3b62e4bcd9a3961ed667a01ef9d3bcf1d2b504e5a72801c0fe2 +13f6ee6f0a8656451df8e6b3c675127ec86bf74d265135f2bcad9eab496039b7 +c9e012eb6f7032c97cbb4f589f0c6483356a7d0d6a0d5926315b3c5c9362ecdc +eff3547796fc7ecf5b6c9e0c2445d88288cf0ae84eb1b0b074da2d3960e27082 +3a94534b0517cf7943e007b65945856ca4ecef56c94cf33cf0564f9ea6a686fb +75b14cff7ac5d96a9e3b8f2806abf77035021e2fc9a6ca6ed32941460ebcb6bb +abba0850204e3b99cadec260e447f6bfe3fb0de512f9efb73c0b76f3661779cb +1b5fc401b7ce7c5680941632a4734d883c85fed2c0445b65f826793d9237adfb +1026f608831b4a1d51bb6dbffaefb425aacd72d15e250e7c4c1f2b8b4f80eba0 +9a2ebca61f0e0ce6e1e8553c244e2cdd4ae1ec2a86981a70d0acd08b99e557c9 +e78e6c955ea3151b6386def808fab512ead3df4f5429972348b39060657f0531 +ab21a0d078256d2e5c0999b2b9b81a7ef0aa7d3741abee1c2f606d0c70fa8a08 +2cb12c3936801296f334e0c11465178918f628bc94d164d0277c999fc3581180 +26cc7aa0cec66f7954c7c889418ca8e995f15a78f5161b78d67a12d85b1028c3 +13f569c083826b7d4e83d1030050f4986a0b0345e7b6b118aa3cdf17572f279d +8798688209980a297ed5763ec39defae97927782825cccc65eeab80944b3e4cf +691d0cffe774f395ef9f9571b0a0cab031b42f5829631e97ce5a438086dc8740 +bab48ca59bf9401747f4a36c9d03916ae1df6a5f48ecc67fa5c4cbb67dc93127 +4845caac7c664a3cdaa68d9cc658e44d1d430b33dc451c60607de1da0fba69dd +ce1c082d2ea007e5be7a723da8e1752c56a96973be728731911947229fecfa54 +a4a193eb8b603a61a4fab26470cb0cf734d123451b5209f9205dbb684677c93a +a306a354c694831dc1469ad07642d7eee7b09f7daede2e83c23945cb7d4e95e1 +dd9b1d7ee556b212562969126a743763318bd75cfd3bd900227dc31063c3cbe0 +4297ea043588fc1ae4eeb88184745b771153885b455c43f9a856081afa605bfe +13ed4ed6661e5dcb69b98757aa95d96da5d8260f0e7bbcaab6d072b9509abca8 +85b3c2fe3028b5a5e43e8510b31fd241d8c457e892e7e0d8fd316b1ee7456a44 +a3909f20951e950548ff41571c206c72d9f597a1dcafad19ea0e29859ed7774a +477741e0230f054d0f815471fba86b8bd00ded7d05d80cf39497b3bb434c5869 +68e6c343c562d39af8a34bf9816289dbab30f37301fe19cfcc5ff9660d8bca8a +9cfd02e55483aa417440c5101ede59e997a50494ca2e20895194566c8b78d7b2 +54bf338cd3833e687c98e1b1214bed4926802d88322de87b89fe8a83eb96cd92 +e9f9b7d39c322d7be1932da95528ffbc4ae740c367053c9511618d11364dbd7c +0b5ec204cbcb88affc5172dca52db35465df886b71d1f9f836f376017fe69967 +877747f6dde7c1af478c028ccaf25978fcea2e84df9e14af67b4c71750e38d46 +d93fde0728da18663b04d843a55af2437098eea59fc4fa0cd562e5f3a2660fc3 +8064037a133fd2a38247818bdbc7e8c4b5f44c1f6caba612bcf922cb0b709522 +d8bafaefb8c0dde1a5dc1be97b7eaf6bfb27674c74c1a46829cded17973f22e3 +1be37fca7a71cfb258ea74a148a0fcd88367d475ac7f1516b27c969f179c3d17 +e2869e778fc329cf706167633887f2ed719946579fe926933a5cf1e29d5a4451 +00131292d5e355ec978069fdfd0312e47b451a717470ca9678e343499bc6e190 +18a56f4523bbc5ac87619948f5353941cfecd232ea0812041edaa7f190bb9dd1 +2f9dde13cc1a867b5bcf75772d361ebce978e9f38d524e9f60019a95a9366edc +a8a7b527372479a27790ec8e05e897773ec63f290ad0796953208e40a0c2ae44 +178a4cd2c5fccea95c552d4b5b1a9f329aca6e73343ff28262ae0a0eb9001337 +f9bba144a90c2eb435c0b1156e4df1f364280870291ea0ac0198f069785e54b7 +05a3c19c6a93c6cc9eec1ca7c83005c891290e589a69a6c850bf79977902bd28 +767460bab54cd0e9ee9cdd97f932f9ccc92732da1c243fd17e268fe0fd4cdf92 +f23d4d148a87644ff2ecb94cb3674e34c834fc03292ad2515f20313319f55155 +d5159a86478bc9b51e228fd4c5c75e9fa27cbf457be922b7f0800d53f53a1f62 +bdada98287a608df2c3f022a87f131974de0f8dd2b1920123f5d1948806780e2 +7ba7ce4d6fc0a3a283aaf17c9fc7a7e7bcc73b200f405eecfe81cb3ecd96f9ce +2d0ed53ac424b6cdbfc6ae9e15fb8958acc7f234302ad092e3b2ddebb288827c +bdc2cba43be6eba791e242478491c5a15788b5a7c8fe25418a447a428bef9d50 +73b586adacfbe10a701c6ba204aff1e6ce0375f195754a48db2ae23cff5daec7 +9c93c40c6b52b197e311e591a9a1c231de90cdeb495b40bc4cfb4716646fb7f7 +017e8a8f8f23cccca6405090ddd34d43d373fc0a678b6ebed8ba66f9271b2f46 +6b09fe96f0c234f57312f1d84cec1e43af4c771d41e735fac026958b638d18e4 +3fd7033e0cd5a39fe55c9a6fdfbf774d9717a13e6575efaaab15e3ee791855e9 +44c4e8f418beef608507927a88b2d8a758c5341fb00765bd7f6d9500d910c71e +6469f507c9bac634d36b304afcf94304a9d01f64d1d2b42fce73fcde97fd5081 +b2345232834a0bd9fc48082b652b5b9e5ad2cf67b848de86ad8b0c2fd34cf45b +98ced4eb9f3063bdcd785b02897eb3c80705da1aa5f7ac92d776c67e630bf7a4 +5bfc6babba0695c4908dfe8b88c4cc7ad000d414981c097668bb0efbf470c592 +40f2853dcf71a59460bdf0f7036c5766b16386ee2e0f8eff5ac6e8de130c690c +a0fb2df2ffe2d63ee456a145fb016ab5ce8a1c04851f486f352c9d2c38df2722 +dd93a3ccd58e31c7a1c80b551d19144ecd3b102134f7eb78566142ce7e0c7441 +7ea337ff7ba0f952270159751c80f3e83385c91c5622d8b8eda5e465684cd1d6 +16bbf130d097454068b68c5360075575fdd8c887dd33e8dc31dd676ae29cbdee +07150ac59782bcb82187dcf7633310334a164ff03ed83e74f11f04bfbf630d64 +659c66bd6cc229cf46a9bc91d055df43e68bef190d2ee7133550a7f554274c06 +b0920f60877fc44b90e1f314f1f631d8362bb6f4730f8b1bc205ae851ce17296 +1893bd1b179dbccdbbef71e1ac372979540f9ac7d248775288d2bdadf0213a7a +a2d1b81939a0af7ffe6572098446528fbea73f5191a77383faed70c82b769395 +9fe8bfce8402afead09b56b3ff97a2e9b5e0f03c8db3c0953d9d8a227a261b7d +1445a6598cbbcfaab5779ae3e40b73a354ac9c7f72979571ba8754362e5113b5 +8d9d5cdf3ba778df2ca766a6b9e6599c135b179fd77657a99d95231d111c60c0 +29ff0e31a12b778edbf3ca370eff83399784a9cc8d37cedf5285a21863da7ca5 +912d6f0263305c1f57ddabf21f41b85875406212dded7926dea0b70a805ab390 +3710c8b851cc91a93eb401b51b157319ee42c9c2ac0775fbce9edf66ff4bc50f +eefd104f9e7da6d55978e1a37c06767fc118a883cde158e92138ef4d17f39228 +3380194abbde4741470bf848c68197576b3aab5ee4b1776f7a16b6e6b42e463b +1cf3d31eec4370dba36e34bc59dda7bc1df5dd438993091831d210c48cdd6d46 +48e2845f0e8f8e29b1e219798ad0ee40b81202c1ce093653627c8d363aceefc2 +7b89c5c24355e8a7479550807c7ac0b6641b62df669748738231a7e7a5c8fde0 +5b5189852033c70a08edc32c5e090df36ec8c88e01389f808b3950e8561d4732 +81cc40b96972d9a2e1c3382e6bc2a40e347a4d6c6cadb5feb3cb0819989d3e88 +1481c61dbe357e6c99cf74e2304b146fa3366e58533a1ad1385f72654354d7a3 +23e26f9cb5bdcf68b1763a5ba53df352865120029dfa28cbed6e95f72c41ad9e +3e6d0d732b39347579f2b031972d0034d6cd2b52830c6d6f511d04d6ce983111 +b2b6f233baa3d072f3fffb663f663c89f335cf413a53ce2c9aec4d06fd878421 +87902e75f72577586a457f2edbb388339cb9511d273e2141582443f3fc6e4102 +8f32f946b7740ec0d71053810b8c82da58e70c3fbeb5f303ec8edd57f1c74db0 +3356bce2aa7c51845d46ea95da66cce57a4da66d424d49f316394ec3fcf77ca0 +7c35757737dea575b38c8138e4427e33f0b6282f017e853aab9a829906da292e +16ec3f97512e3b8eb0b1761b382002d6dc9348c70a449a2a2c8bdea987b15445 +1339eb99b8022a619942941dd8f714855b4ce35dd20ad593ef2cc9d07057239a +790607cfb4c47d44df1921778ddac0645fb3f014ade20d9c2feb02c078cf5428 +4a9497cc1f7c329bff723404d28d9e419f77b817df268de004df45d0ea95846e +54c2d650f475896c12e99182a9ba4cb7066d32ae03895a1a3c8cc8aebad3fe16 +7c3354c4e39f4e3df1d8760605fcda5c832a7f41e166354dca43171311e158a0 +324047dddf2f53f66667860b1f35fe9ae218a45472352ca8809d4abd0313508d +de240ce8991b493899d0bcf25a9b8cee1577a2e0524cc2cd83a6a5a2aa528ab8 +79740e0a8a72e907c4daad35c20df2cb07299dd50717fa6bd2ed7fcebdb1e0c1 +e13e0d95e7132446b1a47adbdb8182905e495cce1631dcbdb37ca1dca6d92a42 +6e95fd17cc0d6ddfce8ddb5bdb157b90de0f6a401f7632eceaadfde2ded4d299 +168e712c2e9982a8c1ab93fcf11dc2e235ea08e01db00b070aff4e8b59a9a248 +b520556a22a3c91a1c6a29d8c39dd658d0d853c4fd973a1d176fc6c1ce35e2c7 +9316b32b96c3b05a42b1d377b8e4d980c34c196e02e41a87676f52e15018067f +d72f9a6131a9e0a3cd7b1124ce353ccd34116c1cf0591bbea938821ee1bd3caf +3ccd05d65e2c74a315faa3d2ae7fe66e6a64080dc362afe5c3ef572b8466a67b +502f80db51f2291dcc81108cf38869f52ab76e04ea944052c8ea5b73e29f2840 +672c7b5055452325a0b2277efc2034501ee291c67e1b7df80c92f8ef53e97573 +ba44ccf99d57e18d29b1f9f39ca38a199b371f4032be5d78337f3fb5ae355208 +1a46c040706f787f65cbb281c416565aaaafec0a84dcc009b7f3eb57275f1b1a +56a3438891b0a33777ae4b90d71cd2aeb2f683533ce4af0c0a17b07b88f136f3 +dfed76c2b28756667a03229c52e1e3460514847bd4866467b1d4ff9e7b2ba9be +75edb0d9d8bc351226c557ec62323a7d42890239b2e6015198a8e630351cd71e +9ab24de29cfe511fa0379733eb0966d62b1d6555d3c03ace31529aac7dc1f8cf +da5e5b3c475fa84c18e9eb83b8590eedc660ab161143241c4913e10860f63a0b +174b9d12b05b7bbe4481e1866f03ce2d112142d470cc2ae0d6c9d0046e157eb5 +2d40c9215517a70f9a42f18d7edadc5ec2840f126dd26f0c9a1d4860eb8c9e6e +5ccf91b7524be3090c613334b3f5e52eaaeb2b13bf62a3050ea967fe21e98551 +21b3ff49a68e39c661dcfe0e97840052e91f16428ac50ee0ae842c89ea361512 +8194009a9e0bb10b5c63c886f9deceb458db7d845343afa2dde4ca1de2f80958 +70ac84efedfc7641f51b7c43786994f41b19be397cee3510424dc68126fec6a7 +87398ec63f957deafe11a0f7ada8c89159fad8e3ff44a4290fbb0efe8a52af27 +29e74f02f69b2acb2ec141ee2521db80890e10cf78456bf86fe675b87f76ca6f +563b6b774e06b5fefad57ee5180c48d9f40d5696fa92fb2e1d30081e9a8a3165 +e39421a6e3561d36c739275211e97675e5397586b8caab5be84fc8079fa2ea96 +e4b2eacbdb8ebf731a167c8576e6a3440b2a163d5f5e4afb05645e19991154d5 +bb9ae8dcd148285bbaf4dec8d9ee5c4cab2784ff6301e0a98a68546c8bd30f43 +193633b0d203f99cf4de8a45a7f7897491d5662121b214aff50c5515427a613a +436d007f5010a56f7c43903fc413438ff94e9c2f9f6bbfe8245a8d9d6e503832 +15c65550331f0e5a6ae10e7e4b5b52a4573d39edf4bbaa0c6ad1201b8f5bbf42 +fa371368126c5ffd6723b2c04123cefcb89f8fb2444b03a47701ce7cc5b8ccfa +81f5ec72a4fdb51fc802236205abb475a0eb2fdfe069cedc10e2221f8a243efb +446e95884170f56643a4b4dfed3ec4acca3e45dab31f6e6a5a4347dfd6117c2f +212103d7fd8f0fdfc9d8083d8462aff80b6385a96f694ee006ebe7144488e6b4 +8b3764aea976c5178a2f035f24b5ed92091c2fdffae29982e8f352d49f224870 +503a471ea2fc96416b2fe4b4b8ac813f505d2bf18e6dcdd64bf2f167933948c8 +197b8acd36c4d6b6c0d95e720d7497e8592a07715099b5a7f69b5a36f0a385ff +8fc0ac9c4d1b0584a0789ccb18535e9dcb835a6bbe79879f42182bd88e8e3e18 +02114d403aeb338596111430f806f553f9519f4e589d6aadd0c5f7020fa38e2f +122111d4b2e0c869d0e57bf35098063336d7f968c5005b690a1a3a821227bf5b +655499e126c87d3ada24b5728bdf279b711ece03f9c2ecc7b7a79b25d83bf246 +fa39e3500831ce106c8008072ef14a657847935c91ebbc6bb7dda9cd0cc7c65e +687ff2248c2bf42740aed73b831955bcfc414e7a0eb1f228f707d58986377f57 +262fdfe335592c6a45800b46fb223d2592336840bbf53b72219f0287b402407f +583d661d369598adf3e8b4407cbfec4b2b7cd8e5feb290bcfa6a34a4938e238d +fb0b5ccfb74d6fef68f17aa6185aa97738e9de05f96cb7cfe1cf09644c8acfcd +c90a8e5d730965fec38eab286b98e1073cf086f852347772cc6cbfcf15a70409 +87a1c26563d7101dd0fd7b74c04ffb5885435cc9ed52e5e2417601d224ee99cd +0bd2a8efffa03e75ef6bee027ed6c98a1c52e4a04ab667510c0d66c3b6eb4017 +950543f0a1b6ad0d34c789a82d93d48221dc28678a25f88add97b197efc8d033 +2c38226613dc8304848878ad7f1f76dd7d50a0afd6022ae5952dedc2b89a2589 +85e7a2877875be37f775080de606cb39b90601ca584b66f173a2611f9ffc0c7f +26ba45788e53a0d29aade81d31f7fba90763b1a6384c68cfc8617d830afa9141 +4a8f75c87f37e487c0aaed4cbe6d9c0293aa7213841142d6603ddd830e6af3ae +3c509e714583369de0b36e70fa29c5fc916b9a1abdcbd85ac52361284c404c5d +8a64fac57d94d61969e8824fa0df2586a113e70e0cbfae1ef29cc3f28d73eae1 +98ebe4ebd8469331aea82fe4554ea07662dc8ed4a26ac829f1707172d3461edf +9b786213cffc696c276cbfda0b869d49bd627efbc7cee1e79f80be893bbed428 +b7cf5d9d29f926f4a06e947a049f3ec2f935b194379ffdf8cd10297c20839883 +cd0ac5b0d6a77a5e3b44f783dbc5e1fe83f91bc256a9c0bd163a5d5d42360c20 +d2048c3a6ca7e684f10fbbc8ae87aa1d60df6f8f50077b36e83aee39479ac291 +4f5515add4a2e46b8c6c853663e3b4081e57bd9ad1c477d185503c8c47f916d6 +6b21c7762c134b13614ca91e7067b41c30ae8c5129bca83e0c99bb02c7065eed +ea731e29c5ffae15ae65881794342fac5308545bd37a4a18450424b02e8ba5c4 +4015fe5f05f628767472a96433c4f5b7d3c8835d7a13fc62042423c4b3bae505 +da978d2982b2e9944e656a1de71b19d3182a290d1f8da7762dbd0088d182694d +894d32531c712ae8a53239eafaab1654b8e8484c464026537e2fcb8c9ada9d6e +070188242693fad0443fa03cb7c309716694b4412123115a42c86ac3b734c421 +b3e96e876134efdbaed532918225098f47c6249db4470dbf4381838c809574db +87792599e977a5fa97858b6d4173a2b8bab0e56dcbe04f13bee6b50d90ac2d7a +d8a3bd0b657bca23cea67d993abc4c342148bc2132459cf928e9c1882f81b3db +97bdd3678fca7023dbd79e1ba9281c30617527220f6a9d01d9b7d91447184294 +5271bb3449de1441a20250efc99df772817104ca84be7824368a0a1beb7fcbaa +5b8dbd37dd8c11a1f826fe974ba0a26a69d0832d67f3efaa80de3d7c1ee14716 +f264cd875011669a695d108287b1aed0e814aa266f88f0adad6ad59bc380dbdd +7daed2b962ad79bc4f2820de44c62047f564a1ab2d21930dd9ccd1a19bc089cb +9d7183a3a8a23862218ac46c368c5f8d4fa82ec594d8fa254e1930bc3c98acf4 +60c5fd4418439e16ba0ec15ea3c5a4e8741671e39fb84c2922e8d4a2304d19d6 +6201f828660028c5497c69b11b278f24d7bf6cd2bcd6efc690785d52f00dcbe3 +26451c875de811692f133bf162ea63603632732d818cd09197648123fa431ba1 +dda782805998c6eec82b3a85fe6851768a1919b308bf7a78cb34e715c7ec9fdd +81e8376caba7ee44813275d97a75ebee6aa78c2ae7ff9d83848d4112b6b7afac +b57f0e9b84b854561d2b1ca368fe2ea8a01027e38694948f4b84d205c2e545cd +7c12cdd7d85a80d5d692a34bd28ec1d8e62ecb8476e56c4799de59d7ca02a768 +0c3c70d4394a6feba21caafbb0bf93257ffd10884037a42cb278cd4a0706b8dc +872b153bfd9ae3642985fb1691f975988683bcaffbd95adb10ca39c8235f2e01 +fa9a0ba1666e71d62aaf44ec5d02db12df6df7f9e99a47038e038cc2e60b857f +29c2753692e8b711ac6993c6bb3e39b61c066125922277bc94c5b6f375c21b7a +69ce8e30b04afcca1a89d9bfdeda32fa2371536a8fbddb4cac691c35b3209527 +1df7327724872678a0bc18c28109244c4e388ecc34019e702c5336fcfe482a0a +4a292d1673e1fb5f669b1e9d1a8edec87f60cff527168421f791668989d71f68 +903e0ccb750209c7a192fa98dcdbbe86f2b409bdefe251f513b35e5b4dcb4439 +d4c4ba7187e34ae32d9e5cebdcbe76cd7fd3805491db0a22caa715e99f31d597 +84bfb10b84fbeaa42b859996a075b2e2f5f920454da25667cadb79f2086ce296 +dc18148839988ab60cc0da451f51841dfda9eec6f741c8a8a3b392a6bcd6d8f3 +f2df5f3f0c1d7bee73133e578ab9ea64764e6ed3a863e2cfdbdf438ae72861a0 +6f0adee82c62ed345e7625a78b89a2a8068d110167ed0e542c4f5c9658478c54 +372cc7ab1706616e67379b61ff1acabedce7e0e9f4a45ea657c43d313f7bc7c6 +a77bb90faf1befcf8c6026ba53deb8af9bbf9e76eb7c7810031d3a62a3047fef +4baaf9604eca731c9aab066e50f5e26c4deb7abe5834b73a8c15aabdf2bc67ad +df3d8c42061d443742ae79a312fb9aaa8da92269bb25260f0f758d0020a64701 +6adaed256d16a0938322a001c3b7b4df06f029093e088e2ebf84e9f9b7f03ec9 +de031f9254992d862c23f2a9054b02493ea9e8ce38a955720c9abb84e906cb6f +f52605a7b4eb530322183496b1fd6f091b076f84253a43e5f56965a97627ffc2 +f884d75f8728f272c3d47d306150a6eee7c1405379d331d2adbbc11c82ce9226 +6795bf88a75023ae35fdfe634f3ad2d7359a102d329d210107aff1ec633432b5 +bbf3feff0b2499f5ad93261c25ce2dddb3ea20b26e79aec8bb107b0788fe5d1a +7ab9169f923effcc1a1b7b8a81b7fed5cf61a922bbaad4e354c0c8e016dbea1d +5dd1d24146326d82911993e2cf72170e17ec4310867f17a116c75f337afea954 +45ae7e16fd43a004b05f6c13878a10bb0a5f785017842569f2fa4e76d96c83f0 +1f79c3cbcd79ac6d95643cbaa555366a36dcf3941f90f667bf737b646369ea9a +08bdcf273b76dccca6ffb3775b25e96b13838c02a375ba801f67bafffc9715a5 +65b07848791bb67dfeff7a0a1d9ebd84a17fec62781e68b9866062af8fb95b48 +5be7e3bdd38535370ccff33ac6a9f479d77e908c306a45ee253bb9acabbb338d +ceca5400f06ddf3c1114d472118bcd9a9a5d873795968b6ce7ba55b42f0caf95 +2e1bb3188f23273784683b86631cba00641fed68290ce1bf48f3f6d91310630a +add043fecc95fd2779b616caa3d6f899aabc030015f799c9956e0ce71aeb69da +920db0bf43417005839e7c5ebe08ffa5cfb0c6f25c91c728289982aae002bd6d +17401c42f7ec7cb680fb8c2fe614368a2599afff865ebee6a5508af4ad27b8a0 +7fac1f2b2e99c22677b9ba346d4bb846c0f06b883a08bd36de605289fc4216b6 +8f33e57692fc6fe6d1392d8aa8bd0aca82016259466aa3b5c550816db4d752a5 +7ab55c4ec2e592ae006b54135e87a1477cf30971aef579452337eb981610012e +4cad5999d58b183363a3fe36fcbca3da7538eb3699db08cb411a0d369e3046cb +56a7fcf333d08fca0cfd4dfb5e268dd42b8162013032ca37a46ce0858e72a212 +2cfa1c3ee9315be5fcf796e34f4c95a0b13906ac90275ab04879f32648276eb0 +d205bbca608aa2a6e95cf202c7e1eca9c33d851fc67eee832fe414f78dc1be04 +00f1340e91fe39bdb5b87bad3b19cf67c9b8d6b1b0707b40eb8871aeb3447377 +fb17aae00f0f983bac00b72cd32e426415827f130e9480fad4bf3f54831967d6 +3c777d15fc50de9e2dee1e9292db38e2e2fe24afb9348835e6e624365e3be321 +747418adf15fd2296f9615263f4977f4e49d7cf3ef9dfa1b010d233e1c0c7652 +3af52b374be7ae6c80e19f40d4a4f8fcb28def0828d8ab8b9300cea69d320fe9 +0d5bd99ecfc5ffd5fed305ef3cf5a6ae6d04bb769520ff14f5253465883abbf6 +14680096fd21794bf6166abe90af531d7c9126d2e9d119f633050031dfa840bf +0da39b66290e6f95ec31af178d365aa1647c75701b5451748b4720803505e265 +c25e013b05ebfcb0d53a3bf2d733dd614813ce3475b5091196ab2f62ab394456 +cef225574aa6368cf5d84b58fedd899c0bb9aba90d8a94b28725adbf9bbd0df0 +7a41e6173506c96398d583b611545e17438d6790f54c27029dc1b563b41f1184 +aa151b2dd3ccafeb4a4454312df18bd8fbae30e9a8c1ad5e642bcb60732d505f +ca75640b3fa7e29883090c1504d2ceff0327f8822fd4de5a6880a579ea715c18 +ecfbcfdac6abadc51cae4e121febe80a5fe0321fbcdea27417f742f1f266848a +929a435e3d032535db6db7345fec4287742a1dadec33c8ea6a7cfffdb354d4e9 +1e9bb807e5b723ee8e067d9216c17de15de218617596d103b23cdc0f1e34019e +f36d272708b04a1c08aa931889df97f3067c597c5cb1495ccacc0ef5ec486939 +9b9106bad96d248eea7021aab7c39c16f405ebd12e2ef469b7ea78d406027b2b +365f098fe0572152ea5a6ed0c0d8c28ff19b86c8c9e9843d7ecb5825ccac3071 +17bbe152f70185b3d308fa9b36ac56817246a1d776c393c664b6ea7674ef8999 +fd30c0b5735072fa8ef23ab277adc000eb693dd410f886dea81456e2742a6f85 +e675c8a331f59e544aaae9dffcb1f5497bfb8e073a21b4688cf317a38451fa07 +d68431a63607656a833c107c37753cc661ae9d55cdb8bbc6ac116c0b8a21fe4f +6273035ae5647561ec1064610cc4572b3a052adea890854e441dff6fd154675c +2c4be401c9068efd6de4524fa08e09453f4ee81072114978a3096969d67861a4 +e6f32d0475c79aae6495a35372910b080029569abad6fca781acd7ab36185826 +2f4cb76a17e65b4a92425f7e36bea7a4303c8f5be566a7b59f87dff6a5d9ad71 +5c361d4eab657308199b40af2c68d42fb9312e15d74dc5f922cab3bc361dd549 +7c2355ea6c757bfa1815244d835bd8b580d3e7a9a90b137bcb807632b48780ad +561064b38f4be9b770e0a17442cb34525c62439bb656154e42c7912a91da3901 +d7cbeb8c5202a33156b683c884abb4c3d43374b8540a5365b9d111876f9dee20 +e70ec8b3c3b79b53ea032d18b50eb1e42cbd9000c284fbd242fd6f0dd2ea6d58 +42e1c308a81ae4abf36cd07eddb928d157191c88f388cd200eec5cf6279f79ca +38e44b58be534f0e8afa0fd00acc7ea6489fafb078081e46d7def7311d49ac03 +7ecce1201a37db29fbc80482fb96bff236768b7036566b2ad69a9357fa1a0de9 +df75f8828dfa4bf3d26d697cb9f40282fc800c3c7ed4990ea6bbcaecc42c3dcb +f4638dee2a4fb5ae2320bbc289c677012dbc64c5549cdba90bc2972de7bdba7b +62c1a76cf6bf7b93c418acda894069a55967bb3ff987d593ba330a08cee65437 +8f370e81494188262128b21708bfefe6838b586058f7a08f35fff9dfd490e489 +a9cf609a2542f10bf7cde0dcf598c360b65b7fcdc078e6622ab2206c7217f63e +ba51d569de2072b95752243eda81e12ffee48dd95c0f189937d6266ac340ca62 +992dbda5b977fc983ced3d440c159f3c5dd1994347ae6fc543a7109ed911ad1e +098ddafa2e6ea8ea8e8e81897fd4917e59b52e78981c1587196c66698af8e87d +6c21edd578a52d5dddacdb3b7bea104a2af449fa9aa1e3f5deec08a79a962f2e +a5e2a9ec2d75620a04b9de916e795e920222ba81fa91edaceae8ebfbf3da186a +8f3dad674dd476f0178a5f30cc49fd5001174377910619a65ddf09db0a4b4b71 +d54453c5b33e3ba01d658da034ab66d4e4048654d3fb36718fa95235f486abc5 +fd11091f68176d3051afebb133224713b3d5c8746fcfd5d45a78ba1b9a97a46d +990d39a2218f93b2119cf4a17543bbdbbe58835290546ca8b877de55c241549a +9bda906a4ed45a512fe0c46957f366bba57826a3bdd138f78be5a90552cbfae2 +ce0740f06060f2cb8fa5340701848077130857962f54d11cd4710625438da7a1 +66575e043bf3ab5755406d28fd510937bb85c478170d85c0a3d2f61efdb1a08b +e826a35e3346eceeb0f428b733de60f12d694f770e0ff3a06c1be2c97874a992 +89eacdb3fb21fdaac91c9e98636c2d7c3acf397294ef0ce01237d0ec970e3f13 +bfcd7493be64ce675330ad002608e65e0d4f9f9661066a86d43b198dfad71f36 +fd51e4170e61343d5eeb35f4f27edf764d4beb7c209dcc61f7b942e932e391aa +e3335a31dede03d507a7ae500a9b5e1689193a3cf46f1176cc11d1569b188560 +e2082883d78b097c289af062c2d288230c908f6a8371813325e3459c91e88836 +7b0ef9d7cbcc764c0785fb5d2fc4e494b499fe4a34b5d4259fe73a67720407ff +d4a27597912a076a8808436370dbdcc362c79682577092e2f6449a26d1507491 +b62e55449a070e8ac36cb412f43cadfc7d1eb32c3d3a17875fe493db349d19c4 +548e6ae8d297c34cf13837819b984f3ea1ffebf02bc9dff7425eb3b015517ff5 +1082893c9b81c83a6b0692687076b8a19f4eccfc1b2d1d81be2b68f149a57d77 +6b11c07588c30e0b6a5b9000fb1b02174d38a1c161bf749da33b8f802b98a377 +c33583f544368cbf3db0612a7f059a8f37ba44f441620995397efe39a6621a52 +713bf6fd26f8db69bbb374129933ec97742e27ec82db164eebad8ff091ccac3c +4f6c58363c111480b1c01caec12a7c1d65f0ab7650b286ea692d4782e3ca2143 +daec5c675d82bc21bdf9067e1b56773f900d385413908326ac36feafa7620d90 +9b0f1db4771586bc553cea5c262f006415c1e6d203cb3da2cdf3954f6ccf1366 +4b1d396071ed925e681a42a6f2f475ef453da85167c395c658acf6d1cbb33b5e +c266bf355fec8550178eff9d12d30eef71367f2fe5cdfce9c07c02065af58420 +176691121d826c3b9a06b509465274e4d9bf0663de2cc77602ef6e768ca4d87c +2b5d133f615d29ca0327e712d90c9a0266f3e8969b18608c364ea30bfa84cd78 +d0d806a2b9f80191d8d4c0cfcc975dcb8a5b5a5fba531d824cfd2ed1bb27423c +b60fe841f88fb69fd97dc181eeb31e18ca51592ad8b30db23a711104d0a15846 +60ab609baa330e31494692bdd9b56d809720a0880b97ceb95f24f61dbc406a70 +dd497e160ed976a4460d5c4e042fbdbdea66106bb5974ee65bf33fde3793f7c9 +2ee75b3f9ed07239682ddd8336be0233ef27afe3c437b7751dd875b9e5b47eed +5332c70fbfc4e900ca61f08e5ffeb00daf84b55f3e0234d3ca433cf731e49eb7 +8b6d83c9f8a18afbd0d8deaee804c10a67477a2b2161d800aa222e245683a159 +a0ed79814c89ffa440966e22c31b0aceaa3cec0309d5063f3dc777b399e39cab +643a3097cc3869df0c34ff57819a97fee889842db4bc54ae95d4311555ec821a +b43ffc065784977104186159b229ef1e9286470a9a28255f230e41b7cb0fe4f8 +1a6128ac872a9be7ae548172a869fbe2320517d502b2a59f2efb7b8de0946cb7 +1a7c15bc1dedbaee69fdaeaaf495be6fb45e4e8f3dc62c42e533aea29f0e6cb2 +43a86af020c6195b16229ec6447541236541816d031e879678b7ccd93bfef4bd +3df834b8cccba222189ac48db305772634f77f953e4d44d1364a6bd580827064 +e5fd0b4a11ad994096fc0765ab8027d3b1140addd437db719198877f82163116 +6e691f3568cd8d686a2718e8bf60292c6abc1bd373958de0d81025e0e29519e7 +5a91e0ae190de1d442abadc8b3584c356b5f88c81494f4872db918136b5c9ff9 +029d384cb3f42e10519224c2b9180b00a192b4daaf52c6957d44627930acabc1 +3c17bd1a7a4a4079a87da4bfa98aeec42e738b095934cb0ae198b96170698a7b +df01f4504eae106ca797aafe50ff28b7f801b0ab253dbd0922b65803fe4401dc +431cc41684a347d8f925355ce2000f2be13e55b21abae5288193040f2c35bea2 +861c8d9e6ba76296638ef808bffd1103212c37ba8fb6e9ff974ea263d220ab14 +bf69092632b5efe964f00b358be4145b0ac0a335e6bfb036afd2998dd8ac1388 +8dbd159aad1014a4ba1da9d55ff8f807b4652c4e3fcb52ebc6d9e93aa33e76c4 +e441521aba48d87065a44298e283a9cc85fc18b267f8a7b4c889722f440c4810 +3e5c9e0dfcfc55199a8406bf46f5af06dd3a454ae0312c8e244451a35dbda3a3 +a42df83d82656d9900c969e109cee325d7a20b3572a2e5269745cc0108cdb969 +bb7ee593da8a7c0e0aa5ef789b8b8b00c193954564cef6e16598a370dfbdb7a5 +8015124cca87e72265a95f378507608f308cad87614465ad607f8e218ff7bc27 +2c253f362f2996be81479004ba6305c6b3a9eef2dfa91981065d113dd70722fa +a9fe7981422bfd8833a56f4bf2466dfeb42ae65900b71c9b1c2079b03f2d051e +a29c216548b79e991c33beb7dfd98adaecb011dcf57dc607cb26c6da794f68ee +6468b0585d20976af1ca199f1b8e7e0ce1afc1b6e3792059340908c3c8077135 +4ceed71e676c4d1330bab06338dad20c460f22bc4feb277762cc9937bc20450d +374dea0f1e0b8eaa10ac338bd87923d9b44fd1e9c0069c57c1bea34e06e95c16 +1ed93428b2ca0eee2f3625fb771c28944398af7959f99b37e028a3289555ebe4 +af93471e6fb8fe599888edab9ef397dba2195764a1ebf9fca215b2f992877cf6 +17f426e81e2e2cd3184edce42596f1bc8e74d8470b70faffc6d0facf03134198 +0b292b23f2ff28229df9a987490c5d8cb1a37511c47db854a556e086d5ed83c2 +c2780c8e3da3a9b07cec09428e7eb0b27cc172ffbe470a966ec523ba5a545373 +85b718c372834d0aa0f68136298f31acc5b64643e41c6f7130ebd84831a7500d +338d341f639204c95c35b405864e874b117eddc28a665af708a517c5ab0e2f93 +c0d2ee58bf7360ce9d4e4f637c62644cac432ea1e0c6ae80bf0fc044ea4ea47f +222dc0df4f2e426f9913d6ee0d3bfc0432f8228899231b2e9aa50e6a4fe2dff2 +52891a9dab40d5d3696fa90aa3bacbce1b198d13d4bc78b6c21493d6f222d92c +a250b37612fee9447733ba053c8f39dcea939bcfbee053af9de1ca5fcb30aa24 +c5bf3ddc309318384db538f3532ee919934c563253e4d4e776e06ba016aa4c71 +5a6b80555793a13f9910cee83832aaf5de98d78fc4b5ca58597fdd8169e52727 +b3ce3cef81a8a281596472f86e698ff2e8b6e8e01c5a0e063a86e3d112195525 +f1f5814b3ce29311f0da378b21ca667417d6a7129ac5a5a7d6e3b459e1f9f01b +9bcbcd172dbbcf1ad3c8cd35a435c599ba26ad5306e51477849d6b72349b29bc +45069e53189a9107ec0cc07e839908f53bf72662922d1ac6f8d40db7b412411f +e13ec13167fdc92590fdc3cb947f36924e5b20eb5383081f4af7c98a331b99e9 +50222b0a55f39a235f12b3bc3c48fe77b1718fbd9fcc3ab51a2bbf2c875802d6 +e5d23dbffbcb7dd26cd5f2bf63f5812f42f7e5d0c44f4e4aae9b0fc52917c1d9 +67c66471add8979f4947d686a7e257114449e771e99b4811d86228fdcd22fafb +3e1702243a9808aaa281f775b83c2ccbaaff1d53f88862c849ba606d35168594 +0d489f4957e80727e3a5cc2b5871e3ac4e42f3b6e5ec505945ce13a572876d85 +3a71ed9fe8dede2766f408fc0a56c97d69ea961f3d4f6845716ef35c19bd7f70 +e25eeaa3c352ee7c076f872f0344cc0927f10559b9865f127f6e3e4381662fc5 +a1f485ff300992af1fedc1216f1fe96212d2ab094a1e3e2f151f845fc79058f1 +fec085688d1205f9dd0b6c4fa5f39f795a53c495d8859009bb1674764ca4c3d4 +f131b9a33dbde51fcb0f240350af46dcac953b9cb5c5038a3c5089ad10641ff2 +b2187a3ab446fc5da2ac27003b922246f50154705e39c2a965f72a81f45a4bc1 +798aa06f1c6aaaaa98c531a4e3e69d243a69a0b35ca5e3948507685ea6a9a4ec +e367d2d5fba7ecb44386640f7a0230583d90999a66905ea574506639cfb450c9 +9ccf660c755fcb161e868b37b1817be93fee086f986b7c94c5131e49a5741245 +229f2530020e37d94755808adfb16a57d84b945b1ca05cc0cab1a1a64c0ed43a +88291dbd489eac602560cec7a74f6e9b20f7848fb6a8c6b327f36b7e01d7f4f4 +d8b49906e02c56dc10302f175c5dee1a50948924032e56710e1ba13f18035db6 +374d4b3ba2454e821adbdfdf4e8e37b0b6cbd3b0a893b7c8941fbac6ec116231 +f2f8d5fb992f9126a5f42ac7bbdd7fe64a3dbc058fecd9099aa1fd5840579803 +d6f2817ce28933faeacf317e958b5abcd96b5459d4b34dcbb9d74877287a8f8e +c19998cc6e7fc4030e57db867889bf5b9c36ad6c5f5cc77a631b8eb4d383d0be +e92ce3ceede1e32b5aadb8a3fee08c0ca04a6b0fe4f955910bd2c70ae66e1d06 +075e49eb8864ca277d6a9ca6d3809b0e7a7d90032943eb6a6e75673d85e28a71 +905810088c462f12ebe161553a16bc02110930448aaa8d856a906f5322405b7d +2ed7346bd37d57a22e3882b18d0cc94ed6d4ae4748acdae9fb05cc8676cbaa0a +8da587e33c17e63fe3117c326bc855e5b38079a8c4db9f0c995e38cc7d186fd1 +3a8d2f6fd38c711dd30a3f6f6ef658a9632b0c610e37b9e1005e42fd240d769d +cd3f63262e6626161d9e399853f45ac6a21028a8b07319fdaeafbae79b50158f +38f8596ec689bbef1e1de5b75de1df0677034660bad6daf05393c1b52e98cb8d +7eb0569424f516fb566015a4d96929f21ef78f82da98da0960f7d82e9c077f43 +9cca030f6ad66d47c63e462965e0623979245e1393130d736f220360d2a5db97 +d953c6181763d8a679f02838d0b3961be8dade8faa4f84a11a82345b43b4ed87 +c17c9fc3b24074714d52d82fc255061609937b130ea024c29f78df3ad79b83a4 +52a129ac42b1cc46ee590ece007dffe6335f8efb2e8bb06d350048b3f19d6dec +5a7291a029be5265df766d7fe9e728e11d414d75d8f1b22a6f5a9da0f34d6dd8 +f844257e9a268c65cfa43032c72b751bbc6181f4625e985a4baa17e9c14f4e43 +3763a6c0dfc76d0614ded599b5a3e5a3e5d52263615e9a618f68f6e26bd12afc +1afd5f7efd302cba26a3a84afb156889be16bac9c597f1de9a11a71472cb2454 +628f160e959b82cdb0769dd9f6fdaf25f72e57f12a597c34c46538680bfbd41b +61a116433e257989009eee8084413729e87254842ac8b0b2e4700f825f26531b +41644687d70c9d890179a7cf304f6ce4b8214d87ec4e6ab789dda8cc1b700355 +5416aef4c2a7bdbbfe256c6a2a76b2237939a840dc592360b762ad4031573325 +5e901dfad2315d9fabc6325a5d62dd165323b53e33b082a480030537f9be4d8e +885f04f4b9978349577273953fe39268013b12214cf6d45d69a0772455d950e1 +b3e49e04b86feb035706c6e15fdbaa4a97d765bf86b5b53a83f81582a6dbcf14 +09e407c95a39cca328c408013f785ac593637ae8551b46d27ba28b1653ff2469 +746456431fe8105b6bc7e93c1afc11a4a7281bd853d356ddb2a560baf564aa61 +f0e9ce9f5b7a5dde5a4bf35627f8466a5b18f81817876188b213c8b148aad2e8 +b1eae12af87ca3c9fadc9f3e2141eb5f14ef6a503eab022676cf1e3ec595136f +526251d4661c4e7d1cb1074db787dc80d43448102636a2a3e80e785ab605f21c +f5dc743d1aca4b5872b4bb75d3255844e79a8e499a0c750dedc8f5dfcf164e48 +1b866631bb4855ba48b50ae2ed852839e8942f34fe9dcbbb391cfefdf397d00c +9e78a41633ee39a0caf687195b763882e3149e13252188b4af494a1cfd772599 +842e9189d59defbc3b907c6c542c2dd957a09077190fd2d70c3c98326cc2fc5a +dd3446eecfe3b7a572a0eb3f068c894c20ddcdf588e89f35c9914e8c1e8a9447 +0461452ce988e1dcc299207adbf987c2e8188adac46d05e190baa88295aa0702 +8c4d460d5926e93f2daa65380c500f55b568ebc904361614b06bed34947db93d +4cc749575ae96cd01435c2b0b5420e9e9dba65335745953432281471aa23efdd +515811d331f48484777cd486b6416c78157928a802f51a7be977af214497c2cd +1f1a1fb5095d55f0ba80bf0760080dae608f7f7cd7847c25ce73a0133db1a697 +9ab7c7c734aa11c115430e923d7cca19a82cf9856e16548f861b3d91b9810bc7 +68e5fd59ff0476cb583c48af0c49edc1f3101d14629ab3703e177dfd59995640 +2684e9c8f2fcae09586dce858e56c6624875110cceda619855f84e74b9df0948 +df3f422632cfb7051e22f8f8818ed7c87db593cef4149b3fc6c9b9ef563dcc0f +c0ba86ceb346b05dfb4b3e58ee74133dc7f7b7c164dd5b2c8c66ad41ca0f366e +d67957c0fc63544c65e9acb700e642b8a1d593592203489daaf6f52c7e705fc1 +3cb89cee4465154d6f6e96fd9cdd6b53840bf0cd14773d4ebd48cd03707bb3b3 +3a5504e6678c9676ed925a6eceb9bb9a76e3a0930c98821609800342e9c895ba +4f60d14f3c07f3ef318eb6e096d8274cfd53dd54be0f4f55aefefa0707b3cef8 +6efd90e897bac6b76fdfebc9947121c6d5397e0be97255dfe0fef054abdd07ce +93ef68e1d33b30e581dbac1afab27e308716041336f78f8cf5678d1b5912e0f3 +5a569765657cf9b49304e52b12bae3a42ced94789c348de6f8ba2a38e013294e +cc1d816d497346a86db3111cff801ed7f9ad614641ca97acb8ff6fa97fb9f275 +83b74c8b104ef3523ca159a3ee996918ab60fed393fae47ce098325a8d670b66 +57f63f68f71468e9155ab5119c32daa7cb78e118b86cc4110f5a9c42e1d485e0 +b197c8ec7affffbd3fcc8cb8b438a62518caea8b6484d015df808342fa70f939 +b57e54f823921d31dba8e6a1f479ad4c1f85a8d063331df1b245f6ca82a1d1f8 +caa96f9cc635a9c2d7df2ac0140f489b52597ba2a940e412f57752fe6f022ff3 +075a9b07a637dd69fedd515402b5ec7943c249d632f71beb82e84a16b3b31e9f +396b55468ddd51fa82a7430e975488781749121aec60622a24ec2adbcd884f08 +a975562dcadaf69217b638570bb4e03712689b9b42df696189eb3124daab11e6 +fd1ac9d31d81556144bb406f404141b8c6ae1746a4dec10cce07b73c7e1a8ec6 +ad570c2543d60c2d3ab48a94b261c7111d1c44f915f85e8177a2fd3ed5de2abf +21d7ec35ea1529cbea7997f68b294d7b1ef030c41362a43eb0aff900b8dee49a +146450c66ff262dd852cde536225ed5fdb408ffd348c083dc6cb26b13082b089 +5666a181fcc5d887f511361435692304727cbaa9fbab82ea7316cf5157084d01 +f78c4cfec26eeea90b7c5a7717efa0965f295c1a43d6ff56ab89a812064053e6 +2e3a19a8f08ddb345b3aed9c825fe10d8942bef773d46633d1a6043bfd87e1e9 +504ff50d30312fa67d79e3bf7a8fbfd1ab225a863cfe20b07e80f712e8914f54 +4886ea10f7fa96b76c8e82cb24cccfb53caa6c99f06383f94395af1778e172be +59d75d50c8d2cfb27fd40703ead3efa25bc4d6c55ff3f555434d4a184976c02f +17c06c965199b321e0ea08bfdcd9ad086752baf29c155403ee548c7835f835f8 +6e6324eb8c1ec101c3d37c1a678c656f09060a562e645b3e6f45c8343c9f3d78 +dba13bcf1aa51d21e4f7251bd0382f7dfd1d18be3af373f1ad974a0d05c6789d +8ac6d032c83d00f517507f80821a9fb90a6d95ff5ddf2f2cf12464bd147b87ee +cb4242e2b2c18e85abea2dfd9ed3abdfeb0fa3d81646dd1102c8aeade41a9a11 +5b2bef211876f745e0d91e5ddda56fc8582b21fcceb3ab8283aa2203f875da22 +1bb8e648c4563e6d2842b3ce36525cf1ac68d7cd371a347587d86f9bf3a6c192 +7ae3abaa4fe15352336a44e57e68ce3ce7801029696df94208ef7cf4419b0e5d +370400d1aadc70232ea3080811c0c9b6e3fca94cc6b0daafede34fc7f5b6fe21 +a9ee255f4c432e349ab56c3566a2121a1463fb295efe9600be1b55ea231c5c67 +eb802d35d1c9bc2fc4a436d610e3578090d20aada7620824447782b4b98561e3 +f437855bdf58d9817887908084e612e5aae90fad7c22a40402c2ebc8cabf0a1f +806e90bbca95abee19ca8cf93c995eaece3653103c28929b2526e777c7a47fdc +2a3eb21774582ad740193ff9a903b7573d3a8d26df0255738ad859285c3abc8d +cbf7ad09e57c2d6502e6cbf3051a87344c8cfd8a003f13dbfeb5a1844bc877ff +f42970ce76019b89166b528fd0ec3875958d802016c0ab77fbfb6b12274ee243 +0c22f0af2065d8b16f57b2f04138b56b8cec19b34b4c9d2de2b603e6efce5bbc +495a757413404fa188b5c006228a2d50bb7b6185d87569b50bc7a44d3a7895f1 +336bb902d73a33d9359255252e30f63a486da3de445b38d5c49ec34755b1df4c +b585057338280549877e994d7306be4b8e5e99fcae66f2042d9a2e63cc978f5f +1ff1382b32b3a211dcc16f8fb83fa7aababb3e3dde596045e5a88b518fb8a721 +ca96c097e0731a46eddfde3c82ba5a89b04345ff49fff0dbbe2990f6e020c5a0 +f0c70c1d3e793248e996182bf31cd24aacfb33c7b2c44bed02f5c7e4888fb71e +b5a55dfa9be9eb0c9a42a02ea413720512b112aa86cfc4e95e3b7591b5d5ceaf +08be7e6cff5ae306f8e03e87f9392377980c54a11d42c38475e20bfcdf627aec +6d9c807fc0616f3b5465c84c6d1f431442c0f1696dfa90e654e80151a7a7fc85 +77e65470f5b55a7e306dd6b42ce4d68a2ca39b64fe94395ad405240c8884bf28 +45e04aff559bbd1e45e7ee58dc8a9b42b74622bb097522177de01a8552d22e9c +fb7ee3424fbf2ea83ba8c90327cd38cb10cc1283f894656d128fdf243e5fbb8b +269fda31695c224a9ad6c7c559cd19be34a49c7c92d924207ecb40cec8a944a2 +b15c76f21bfd783bfdcd645766009e61bc60194ad6b39abd39993f9b553bc6fe +3acaee88504a4861a45cd29f6623ca202500d4ea24b5e0758611fbf6411c8b4c +3a963f16576dd0af0b03f453a4ab01e8006dadf9e8f749d4754c073be3bb532d +8c15067dd4656907b24ead8631c283adbfa1ab99453de1c9e1381d4f7aacd50e +32423a1302a6501943f8b41d216159e0b8821995586a7622f8d0557e6023d4d6 +0ab3c3852376c83a0346ca01886a1fcc4b300da8eae8149357021158fc33fa29 +604d40eabef8de09b9d55b24ee7f752743eef2119783d7135d38b32e5d8d5c72 +a4a9f251e78777ecaea2d585ef6cccb16a9d6446b6b8d45509e273e74fc9a285 +2ad7b78b75179bf1134c39e663f980e03916e8816707ba0adb9685d9879d5c71 +c3099f5c7eb36f7d68f6702dbb0ff6f1986e02d12c3dd58348dec391f56c589f +44f2c9bb32ce0fbdcfc0731fcb3429410fec345a77bc1b3af582d8ec1c8bbf0c +3307707e6d46b1ec4a2beae476bd25e6a2e94526c75cf51c7d11143c856d614f +7fbc33cbe533793690eea5f76b53dbd4a87468c7f02d802dc581fbf1cb3db546 +333b17f256464998eb7bf793039ba46e4a89088afd48d3fba59b66c8d37d7f03 +83b08ab2170f4b755f93506e00d9f0fd436cf19f18834529fba92fc49bcbfa21 +3e9356dd236c661d9b0dab928eef8b121b14acdd50b181999b12f8640e582e19 +351bf762081ff21470a3a8d36002e7023f8a116d13bc03b450e2a107e2f243d3 +fd57e4b96893b5bc713503f761eac00a9d7eccc1c130d377ff0c6998af527720 +d0bf23f85811712ca2015cb8bc729a8f9f53d4a7ef10d861db6ab1c570d40165 +d79a39605c25003f291718283ce262cfce9f985780540a1145b194170113d653 +d5094319322e1ffc9896c4e08dc919b34be77e084823721142e198b6571306b3 +3d2439ac6b044e0f58838a6d2b7d6e5540c868d2979ef5e443b4adf7e419ca12 +ebc02ccf5a3081023c111bdf9deaf8697db123f660ca1d2e649756e696e90383 +12566522eba1733d440d9dbcb80491e7e650f7da0bb2f30a6fdcb3330f8c66a5 +c4075a1b2d1a1083058f08063657de58dd8384ba40cfa6b15911fa27b3b93e7b +13c1b109971c8e6c1862d06e86722df5a9f83f81569f6d8073a898db2cf8d1f3 +a2b4346a9e798804c5f7b321d0169c7789b4f097d0d0fa85cbbfcc7c617c03a9 +a67f5497ea2e9980e329be6526c19f085e14a8346977ba15cb8497dcd3be1fc7 +c7c23498ce9058e51b4c81e8e59677fb397c750c265018b992ed450543cb4d8a +fcfac6cc5fcd6e6a150c78def5c3bacc35d59214cfcc396acaed7c2109f4542b +b3e449129a74431d663dac6baf344f4fe5882dfda6a15972216cd05534e46ed1 +2dd12374f0e2dd3245a401d5432690a6b36f2ff3a83197cf812114a2db541773 +539ffd5adafb7fce4bdd4852f8c3a2653cccc7780add61c5540ccd8b64891907 +d9b9b79cfaf2bf8ea442ffa0537795ec29b40435c6c9af9f83760a346ebbc0cb +b1a0e403e9c4db8db45ccc1d202a5140ee96aa1319b5ac25fa06c76f38c7924d +c9a5d2b2d69307709b4dba2183b3c317509c4cb06629b8829ca745c2fec7d733 +2974c911a49d9836839d5a71362dcaea4ea2ffd09836cc0325afce2fc1e17d04 +7e9229ff4edd4c6468841ae46f918d2962170b51e3552d9f6d2d6a984fc935df +9e6f161f5d7f8921a9ae79f61563d1a44ec9728766396b8e0cb738098d6dfb06 +7cc8b9c760d5ddf98b8f9369b504a6ecbce28d7539a3093ae7aa758451d5fb11 +00f95a38941aef86d4142fcaf74f5ea184b3d4020ec21472dff04c7a188008da +d0282f7a7d8f4831722060a0a086666b82aa901e27840f23d2300975aea74d9b +8ebd5b5941efb313339bcfb864a354308635b89d698617b72e5786649b4426c4 +fd1a8adcd7479a63e284eddd0fab789e536a35b4956ebcf9295aca13e701c199 +0fa9d97ec7605f5e1e93979742e99c0c540e31ec27470ae5ee889d2cecb5805b +d28063f58414bda33d434fc23b35a582be6e2d092f81f577c19ce5f4851aaba1 +f00d23770ba1ee9e6d63298f7616a16bd66ac120f440f6ff33f1c083a04e4bd9 +d381faadb35b5db94e9a445ee0c062b6c5fbe39092256be23d43f02b259f0728 +119ef69eb5fa0c3019ef8355c6b664b2d4519fba557ce0955cf5cd9a29eb8051 +b118af87e90c255b831979dc4a6f3989c1ee61460cc038ca1f2702a2500ec30d +c101866f16f6662e6480216683e20240657c5988e9177c6275f610a0ce095627 +5d35e0bd236dd263a7c6c13e46ecdb7e9c1a28d861b6440530d4d4ef214c25a6 +e8a19594de8210cd8f6530009e29ef41d76d0173e4983e7ce766d4460f3cfb9d +74a65d0397bc4a198300488fdf3dc8d393f01b0ddc6bf6d0dd6c281a61dcfe41 +7d9f18764aac1f660fa691668c4178b6b5c970ac1d9fd87ab89ca8749bc8293f +2f4aa559a80f1bb980760eef53529a50bdd4c980e3bc8e91713ad348839a0916 +eae38950670aea8130b39b3ca807517ca53ecb35b3202a5318615ece4cee8196 +57106a0909c614e4d5069452b044c61959a61d4c52144df8ffdb03611fc11e15 +7a75d6e0157e2afc56a7e6489dbc78937b16b08bebb99df7931604e93d525938 +472a3f85acc6d6e199c5fa4f23be9c9df09e4055fc56bca5232df7506a310590 +78eb3396369a120c15c86c0a3348a927566effeec482d35b65f37d466cb52d91 +f2273ec77a324d246d6e00796bad78031c463d22d9cdec5fdffb0016ef2c1204 +1904c2c11401aa27a752c734f60a494de5f0d8746e3ea183a08abada72dd3db8 +304eacabb467cce3cbef0965ce62ff8c9843b80304f3664da9311d6c6fbedf0b +b76aa9df76c8032b3617b6d1169f03f00355fb6e33c81d2083b2385a73ac9763 +e2a02bf475587c1adb1711108da9e2ca1dc657be75d184e4b5e811c869227ebf +cc48be27488287ea07de0ed94b15c0f6338e6214cfc3c6422c8a88e70e9fdeb2 +750da9b19aaee8bb4f4dcf11c94389ae24cd7932dcd4785964137f1dcee0ee40 +34eab74a37077d54ec81fc74b6852109918c3b5e054513768e61b2f3e9577c19 +fcf6d787cb0f91b95aa79d4a07a16648bcfc93bcce70e1b694cca7bd4ed441d9 +d7f4ab44d7e212441fe2fb58f95de157939752408c85ded66063215811683700 +0b149ac257696b5a756f63bf067c2cb5d95a0e8c624b6fb70823edc3b1c76d65 +dc4d5c45efbc4a15f9535f1d2510bf192dc50360dfd346183b270add124afd9a +a1fc9ada3d9601d8deae5343296e79137cac2b14f5bef1412f106c80ddd16f31 +0afc318312f115a2caa7d18d68bae43698401211c627318012eb0ae7f3670b9e +64d283869954bdcc36e9a9e6f31dc629b1b5b4220b092e37c154de14d06cf0b3 +968365c495b6cb83aa0d6874ecc2ca9c0567a8714763a866168f4feede37476e +7e03bebdb3ff0377c8c14bbb83e171b895ed8127af11a831d90e018522ffba89 +6ffee5af03cdf0fe4d6d2f2bbc1f36df363e1ec8ade78da829e10bfc81d95185 +e0b3f52997e9829d4f55eed1abeb79988a703371effb55c4d355b14ec885022c +57b877da3c99b91085465afa3c0aaa40c267657fe9dcaea7e1d9286e78cec507 +7edf640bb17e9c72e9e348564d2585daa1a8401cdbc2f405d012ea652ececbb6 +f51a91b5c2e1c43a653404cd5c7438bbe81c2442354d8bccdd28db1461b17c67 +ce69ddeff50e1b01bfd8903ae5b8855e46591d0f4e74ad3a5b94ea32d084b503 +6f5529145287bf0f7a36b289999c02e749903595e4c0c9964a12868c61038add +360de51ca4e37523bce21590ec894e5d769f0c8c0d84d766bb3eefd99456c6bd +e4b626c4990f7dfb481b8919e5df29b350d9911ac166b812312ef0bb4054ce4f +b9d04853dc437d840fcf2d099fa6819978be454682f7c49857b3ea3b51105e4f +0ffbcb18d4b5c4a8adf72b7a43046fcd7ca5f7677802ab2ce24f536243fbb4ad +9fa48dfa43008410d2c37cde9d55af3935776e067cf31a5f9c4e64f8001383dd +e4a246cd9fc7de74fba2a4987851dd7fb5c704e0fe91be14eb3ff92faf5b1c24 +57537179422c11e095260f85f96e58523d508b213d512cefce5901cdd96d77e8 +83928b21360d687a33fc0050e462beccbf67c313344ba04dc996453efc00d417 +0a63ca01d112cc7bf96459ed7504cf59d36a10e80e5d925368ad3e8c49d60372 +e104cd0339519b7e881c8e1ac0a3b6fa084b4c22eaa94d7764036b54244ca9f3 +3e6f504100914bf93d9b83aee55f5963b18c9fcbb0779852db948718b0e19510 +7965dca4eed64689efc01531a02b88c058b4166553d014f5e431ed771f89f903 +598f79ee0deec8e220fdec61e645b07287922f842981c09f4175a6a31cf67188 +87cd674915986c371429c77d041a154f544dffcecb068350f4dc33663b4cdbcd +19fa1a3d76185b50829fa3196a79b938bfe1810f2f45d0c70f267ea7d20c5bd0 +b5df06976ea605e1fbf65572a7a45d49a3c63c153c8377dc3376da2b170ffcf4 +4e9aaa66e6db4598813f5cdc91fe5950e0815bc0f6844a556d3ae5b77853cef1 +5e14022c8911a21ed0661681b8f497ce79e79c306fbd5050efe799fcc9294bec +62c3390836da0e4cba741dc9ade2e641cb4803b6d828da11e1df765c72d5a46f +019a348d7f799fedff037cd188e0f87d38a1be7ff3d169c49b71bb20e67814f6 +0864eddf1d7219c38cdbc5f47982bce7f3e151ad15cb4575b931c71cf16bc130 +bed1b90f11a3f2abca9c67871c31393e188d9dcee785a4dd55163f88c21b1240 +0dd522f6ca3d8a7cd56320bb0379c12b32f42a08fa9f78cfc4a54e4f3ed54799 +dafa79d84e648039a7397b2c3756f5173991f714262ac25a5be355664fdc1943 +199384c11deb6cbc0d9e84d12cb72c5a8235651a13a496c6bc771dd5a51a12c7 +371c2451292a86a4980e840c9c704243b79d69daa569192d6c17cfc9c0283c7e +11af40a05922bc32dfbcf28982041667266a3213b105ff2fb0d3a2e5e033dd3d +695831a09f80d9a0bb2c1a557c4ab957be63c1ba9a732c7271f639d77806066e +5cb05fb9298e1acda5b4816ef2e9540f78ac482630fa48df127f886c6a6f0f2a +57e8674e2df70ee3a48f90e8936f41548470a8bf112da247203c3c6e436451d8 +19556aebf66225db3b5d085226a20a87e81ad38595d5aaed4e3c6f2848f6ad05 +089ec513a70ca4c426a7d5bc799f7831d916656ea0b4cd95fade84ff399dc059 +6a2d5e9d6a4f2782b4dba14b6eaee969f917011bc0cd4748da7c0496501277ac +8b31bd926a12006dd9923f28a832c2472ccaeeb0563a76751f32be27b94edb94 +b940c8c69c38ac0a4dfa127d876b9ecbc80f19445cb1f6ad76df9b9b27b7409a +5b8fbb605df42049e82b85589e7448048fa43483390b3a0a16809308bffd7e92 +1a1c2cac9242fd16191a32ea7bafb56970146457233fb64136a646edc8d68010 +fc58b0d9c9a03acdf9be13700c3e1012a98912e0ea3fab3ba9ef3f96bf1b9477 +bff0a109b1b7b58ef6c1ec22a9be6bd5873831d3108f2090c9b269fc69dae417 +bbda89b1ee6d89aee6ac79a4f324d4341d6178c8280625ed8138c259f58494dd +2999fe85897c24e220df1e038a7a365fd6f4c7d70d5637d65aa525dbd4199ac6 +c1f7771f977b7c45ce1cad206f710532a7cca4581e1bb35bee1836f0a7dffea5 +14c1772a81c1b0e0116329446c4cff527cfd644a8495142ffc5c9971e56ce47c +ba3e666a8a2d4bf7328129751deb16314fea953a99123fc9f80b002a8596238e +ca4fcb457cd92c50f8716b17aaf344cbed3a90187392d166693edf2d0479e83f +e61c87a3e4831f864fe98346e07a8a1c2a9b5506403ede022825798a7b862bd3 +de66e460c0d6b096b0a6872a0b84612ea75b6f07328c5830de51c774cd47ed46 +0eacfac027dab8ae57827c06fef218ba062298bcc85f3b597364419ab626ca3b +135969afce0d27d8cd3858c3e6f55b47bcf8f10b98b4cf02cec1d5226005f88d +dd957882cd38a96ce959a7bb3be01ca3a0555b06e43442c2a4d30e58c0132b09 +3ab36159a7f3de69979a5f5c355cccaaf34e6f8982ddea19eda6ad06ce65042c +79c846f5cf4deefb890ecf9975f62faaed21712f886791a3a7cf4a6fec89f808 +acbaa13291f660ddf1d6b5971906c2ea7362ab18c7ce36fd74e328a6c1dbc2a9 +da8e56d1277b3a7a791cf1e637718177922df51eef5bac177d35be1ed96e91f7 +ba04ed43b3779885b4b596a3832a546089ed292714552ced6a7b4200a8e56bcf +4cbce7b6e5ae0b0265044ea68106a6ad47b6548c2fabc6fcfbc4bb99b59a3288 +1a01f4a7b80448ffb07ad5651aadb41fe5ae0097de7504e09ced6c87b03fc53a +1af214aa0d8a7763e3ac120243be6e020e336b9799855bb909bed8ee6bfdc1dd +4f4dc2bf9756ae5c71671c211c9140e8a3ffb4efc6d90157207d97502194f827 +f3ab6b522cd1fb2c6b50577b2dc0a132aa7e404db93fd4159d5be35907136eb4 +f883d372f4f0d79c1c1bb92088c3435f0e9bde7233bc2c2c2c3a8b0ce77cd5e0 +80edf88cdbdceecbd12de998cfd0c39bbbc70b3ddca706a00f7260a2756e58e8 +6e9f3f1b2f630dabbbb5babafc322c6e96d224b66a0e1f3b00ed36056ad2b7ad +9ed4ab851f10c873ff7c107aa30ebf6b3a64492aa9ffa867bdcb646cf2723041 +ce5729083ec44686d9d2e36f8a4b83e6ccc7a1c7fb908b6fc18fa89c87207a83 +5cedb44d57c59a133fb1bd0bf2afe363ace3a04ae4e1050ccd7f097a7437feba +40bcd8350ea03b3b23fffd4c8f72fd10d631468fa6bce1bd229485d63e105784 +78276dbca3c8919c308aa7eac84eceda1f7643ed62f0e9b8243612849271cbbd +0b7f62a7ba7d12b5d94bd3de720b94d8f7fdfe02a86c9c0d5a01b1dace70cb30 +d5cc9ecd33fd67b8a9f1a8978d087c52d76fde279e5d347f927e405a75cd2e06 +6715e3105e489dbadc7661f1b3e13c16fbb1d55b9a8e6a3234e5face956901bb +a0e6b543123c509cc20940b8502f8f793a157d9c502d77560e1ccbde5a34ae55 +27b549b89371954c674df04396267ff94a56348ff9cff71d5d4c437b6ea3cba7 +57833fe11098f0686bd337f97196ef909df61ca761acf99538d9ddc5b2791187 +853016273dd47a5ca482c06f1155c0a3eba895d36a0b4e1e82b7048addb4a1b3 +8d3f3a2378ea46e22dcf35464d7824290844815b542513f54f53c0dd6355bdc2 +e7918ee8382f469c9912c1f746ed07521cf9c861d7092d1ab8b59b56117dfd74 +ab6ccf2fa1db5f5aa822d2f39bc8e353452680899d07f6d81a19e2434972b4d0 +18313201d817e9e372e3cc7034007040b162c64209922b9a3f7736adc2e0f112 +6f333c48b86c60cf6cff1886e979a00278a6d74a09a692b2f5c0d658444bc021 +0b4f13d25426f164346b13d9ca826609e87b8cb8fb0cfc9a9cf46095abadbad8 +deed4a34e5f09d5621277327c87109a85f5cc885c918bf6ebf8ab9c7d1df27ca +a7a045e6f509de6cddd1fca3b9840a263251b83767c8efc8ad1c36d1ca6bf20f +6f9fd132f4c7588cb7db085db67b4501c3243423ee3f405331732879def541c2 +0b60e49bdc01e726c2793b3099baac333ea27472d8d27060fc16d6e5fc55bc80 +e7f6eb4d32ca5838a7bbf6a63f4075dfcc41ae0345c57da2f37000a1043e0286 +7272dcb010651e246b42eb4a4ce3f9b00f0ae08f0e2169a65437f6e4fe6ac566 +2360316d7748ba6dd40500eb1ade97eb333af2fe4ef8e7c9d3635dbec7e41941 +98e73685514969998a5ff66aab14652764ffeb4b4a47980e8fba34c2bdfe8c6e +88fe245e88e84de953a93a8582013028ccb178c521e9f7e0ba542e44b7778d67 +d42c6bcf869e3d2be1cd35d58889bfe83d942cd902ef824641d29fdf55bb4926 +3c9fb086055f66af555f6cb2e6a1c7bd6a18cb23bef93e1832698886e30a6415 +8f7453508fa1b566f0be0f9cab67c54669b92e92668f4dbc017412bcbc43b6f2 +45e757f6799060cc7559f2abb6a02517a457a0cd033e0b0b6d98c8068b5b6ff1 +987e150088572b89d62d888934b7d6f46db500b2de858b3cfe05cc45b889d428 +b196f5646bec1032b18472621d0fdc8449aac8bb1191d1e0d3a6b70fc08afcec +a2707fa329e30b773cda1edda980d33f557f2e78cb2f3185f4f5af0abcaad93e +edc81b417b746c6a9353bc3ce85a36960c2c70f9e74f49e9f4ebcc84fe79c559 +6363f61df068a4965f81f03b5683618403f105c5fb02b8f8f235a2ab00f3b9e7 +bdfb42e252d2978b27d769672016b11563d57019e350cc5d4375d50dfa83877f +456167fd1d4bbbfeca9fd39a3d11539555eb5665e6da58af00295b875ee95032 +4f9d9af5c36c4e38bb25baac27bb1eba8072d131b86aa641abfd50f06bb7a6c9 +afe9d34b2f9c985eef6b8b976e2028e93c7d6b73d01b6150715c30929946d682 +6115ca12df24304306a3a8d38da3547542c9f7724232653d318eae76ccf16fb8 +e26c0ea994aff716c026d1ed40975f3f319a4806e179ea03381ae5f1c337768b +628915142f7f652acd6e9d7a962709c9c251cae5b8392916657e21faf7cb756b +50ed7118e7ffc7305238ff241f86b7f34ee71ea772c5e7108093dc02af4691bd +c53fd49c4584996961fab51d909a6e3befae0b8e0bb998ea9f97dad1f6f1baf1 +56e54113ffc6b824c249cf1e3be63c426b3e3a291e40dcc1948b073565f087e4 +96afd45cb8cb02add9aeefd59748c088f0994557e37946c7a8245a5f70fe014d +dbc5c6b331180b3c5ac3d2a3b4c790fa6ddbe054809645c57bc35d559d522871 +adaa77188f1847c2efd822cf040d0c9bd4500193d032507c6e316d14687b274d +a65c14a8f13a591fdbcc3eab99f290e020cb02ee606c90f7b980c5f57cbb37cc +b49332ee05a59a5006c8d6d3d7092aba7a7aeeb4ea322f70d9ad8a0735e42924 +8c944181ae86daf86a392329162032c9e4f94e2054b2d46b5f5bb5d3646816ea +7b08fa9de3389395163f7d082b0fa3b6442b0c546f16ae7f315940c3e77fcbb7 +ffae573308462cbd8b99292295929de8771401ad1bcb17761453c0f039234498 +535db2eb82b47994986053e3c3322bc3c92e57a54b6e6e1a08ef4c9951fb4ca5 +120935eb7fa42f52910eda183f2fe35c6b2a381d319bed8189bdeeace1ed433e +30c45ace8dea5b5c80895c75499b48e92dcf3f38bc11e7bddb8f59fb5ea09b44 +d6215d7f891696e83d1c16cba3a420fc4d305b1ef1897ba478031589628a410d +a93d84082813e220ef4d90cc93ecb0bcfd855b636e7a2c536fe7bd0fc2dda3a5 +9aa75ab8b95f70bb73acbcb780d37a21eee4f75efe6107ef3a79e4b4e0619b6a +69ec5834322500fa634000740e21559e6bc73d327a73776fc472f05af6d6b2cc +a827733f0a735382b3cb1460dbbf6a53cbdc37374fb52f26f12f475184aa9029 +522ed393427f987f89557dc161a6d50af7cd91277fc1b65a2c9d4668824ea108 +089d428dfd1e953fdae3fc510b436f3c874063be031c2b342a3e59fcbd0e3dc5 +b082d4026fb097e6806871d108dd0205d3328c957a364dd7736f58f1c646957c +ca7808129bb1b3b93f4e1fc94ee81a79dc147f86bbe4c51364bd6e582c105b5f +38340b4d56ff9d5a349bfe705261a79d1e0f62d392662daf89a31902636e374d +1a0c6050842ce6d4dc3ca0cac5f05bd3948115dad8b32398ce1b9e37dd6a4672 +11f6054a097555ca5c73428b88a994fa62fa8bbd19f5b2822d5f4c6acda086a9 +2fea6a346b0679212e7a6d72e5def724d9830b7ffd05d3a54181a75a35bc9632 +fcfb406860d41a2fc02c250d00f6b74693fb6f7b5abda4e19d67fa2d4e8ead50 +2c39b723a91dae878e6891ee9f3c1432155c1259fd639c8beac55774da563ff3 +402b7a551583176633c3275b40378e65de70a6d6dfb54ce657b1db8f195fdecc +9e825996f7b6cd3d75cd694c390a60042929253a1915920bcb3b9db9038d402b +9186237e5b84202ba9c769c0a0abe77ba4da5fef2ae04679456d89fefa424ab1 +2d344d40ebc4edf9b49a1d83ad245753935617b491bf9d44f91fedc87000e2f5 +b3f38ccb1b0c604fd79595841d5c757d3e7f7a54ed78ddc7491e526bf7304de7 +fd889898bbc7439c1a7304201dc26d1c2ebbb3a5fa0f11280a896876902aa501 +9fdad2d3062e24c53858702909ee549eab46ba7387b1c502876e439ddd81707a +85a7fd5a1deb80cca09d8d2bbd728172f0427e2b53482bb017d3c8bd38504d1f +5576a2995272ba439b7cddf233ba7160652d53630ab0f946f21fd7d35d9c388c +6a65b52075103f2eb98818eaaa86aac02bdbf285b19f499dcc3ac2c26a630347 +21ed15d93ad79200647c077e0a5196304bf9b85e755106f2d38c4e76c1515f73 +16b65d32fc00cdeb4d2b577f50b90b24ced8d2ce98834a86ef5994f22fafffae +c6ae3914d2628171516063df8eea1ecdaa393d510bb6fb51d3ad98e0bbf30196 +d1fa3e73f0819e5c2a979444dee2dc649c34a1a64c5f9d9695bdddcaa1b35c3f +423f9664b9ea1cce833a9450a7208f3ee1434de658bdc9b656232da6652229d7 +25b37b68ea025dff577159e671397f0cb635fb0ce77c5905d8714dcbdcaa8edb +ce1e3c3af35a0eabb89ca7be1afe03a6f2bc72af4f8256d131ce0055f53e6508 +ec0415778cd6d4afe3c86f3121ac1885aef7d4fdc8972aa576332746991c9529 +b76bef109b6096f5ab93c8916e3857aa874bb89437485a91778796d4f7fde6bf +23eca0acabd15f314d4ba909e07dd62397d603be308bf3fb1356d1d7e985b69c +8c97fe2fd68cab182ea2e51e4efbb996bdee5b8891caec566844142da9e95e3f +5523ac269b6a806fb5e8694621af032c962107072d1e502f5bb476f8a823a254 +fe32f22b495f694e8efc0c76dec23d9847ec77b49b950ba661cf6f7a40d2e270 +1eac6ad81e675526443954aaa8ba0959b5fc703fbbfaa24779b13a4f1c284988 +30524bee139a96e511d63c85f4f723db6aeb31aa40b22948426cccf580ab681f +0a5717580aebd054587bb8178f52c1524ae34143148cbf5b2101177ade49ff8c +dc69c848054a9a310fe04aa7f61abc21f66332886e7f9bf070b0ee5015b62b75 +8027c533c06758db6c02721e1db63307771d66a33814ae3d7f5f483a5a4d51f5 +2bbe8534e3512329fe42445f339a61a412620ad88e878ac6158fc21770821077 +ee98b2ee8766ec5bfd63bb4d56f7218455b27ce008f4eb0bcfdb20a2d16dfb74 +3739d19073d9870fd3446fd1f0a2d66b30514b148f3ff462f80c0b73f0d95055 +1d0d37b0852aa69b148d76a1b2a5275c1fbb4fca70cce06c73c441e49e19f30f +312ffe75f1ffc8c16070634a1576ff29433d34177900f72539df823e2d40bafa +103555953bf2d332120c5adc806f0f7ff951a95dbef3eabfad23a6914fcdaf3c +15ab9957d2336f22d163c41a860121aa3387d2891a7e15ae8fe947e8f4dce180 +55f4e46166a47441c02cb496773152edabb793408351dc1ab38ddb6eab87b51d +abd61a66195207d0eeca93f32a453621e1a523dc601c8a69799cdb0fd13f4c9d +49713cc203a65cee224c8735bdbf78774fe80652278d4e1026e56855b2f2d465 +ec02371e6b5ad0b9efa14c801620d9286704d64e74b1be29c2004bc0724db0f8 +b7a2f01f2e44fad8bd056e99256f0ecaea9aa5edf9d5769f8288bb2b74e8630a +32ae755a4530fab4e94e9ce8e66e433f9cb294ddb578d25b3990c34c5154992b +f8319d28c5906c2ff5a84b85f2c417a5622cee15e0b2a1d7378779fde78a140e +5f278e98c4397f30fb718dd758e224874510d0565f323d9d0d559b7b5d4c9e7d +3b2080be35e140cc98c7d8cf7448fced97456620501b1ab9f4838d7903157b43 +40177c4ad92aa14ddfb2d2e9474a1295fc6c7ea14ba871a6a4e70033d61291ce +a2bd689d0b0a2d31b261ffbbfe1ec2ec87add1f76214ecf841690187dd127a49 +5563cb02c2664025b522190cf5c804c543f5c08102ae2292d7685c9dcfe06a1f +8166b0fcce655aa0af26b555f4db94e3eee7aa284914120ec18ebbbd3ccdef1b +01bef75e2552b1bade4bf72c2f13c26bedc502d2d573886d14457ac1320f4beb +21883c198052e091991fc9dfc7f638e5492aedfca78c0789dd2b21410ca4e956 +04af1d34d2d98c16adc03e4a52384d318e424aba717275740d49810f4e45406a +65da979fa5cccf10656c32ebe957d9bec6f7f9fbab9945910f43559230f6df1c +fe867778fd3967298c79ee0272f6802f42da557304e0e9283a3aeda368873205 +d221cd78612c8a6d4559536fca946bc37a9489b3823b1b72bea4fc84ba485fdc +fd9250042e68468297e35f8df6c660975293b5ad53e30ea2393eeb9c34c0a721 +fe884d3f3ce96d83df89434d2b40bd163e9c81da5978ffd0507cabd1480ead9d +2986294fba9539c8484d3e12e2f208b7b8690caae0d89b520748e4cf0d4a8311 +8438435ae116aaafb743967f30a0867aa9ea23125380bc01bc6a443f9a2f3b2d +4e8103c281737832eb5cbc826f1eea3476b94685c0bff9914658871bbc5ec91c +6cb3df628e10592c0ac1e60b207deb1f5431e8b2450c5e72bbf93baf56df4559 +9a093ac1934c8f0c82d015ee40b69dce5658f1c9aab46b68de64c5089c929aed +8ec525257a780c5a02cf48e8e795b7795255c39aa08703dcb619adde9aa45776 +09afb244203679bd6b06a47517dc37b69139b4442e3b150ed11e3076a064a469 +c048627a7119893902c23adc6a35374ae4347279175d7fc0288adcbde31b02dc +5bf474a2af040ba30cc07a7b9010ce80d1ea20f48748c6b7df7745511a9ba00e +3afed904361bf3ed70e37854d49d28653443efe29ba070a2e1323dcfedc216e3 +850607249d6da6d792566014686e0a480b4e0e92d086d08bfa16379d8a716ad4 +ecf8cdeb7bd1b70bbe2da48962dfe8a3f2d17bf6cd0fb871a405ead6bb15991e +bedf12cb136263e0fb2b1fdacb86d5b963eccf6a3e43c3f9574a4b3b589fe23e +8afb96c2e44fedb8f914a27af31fe6b2c306a1ede486ca7f5868fd2e93ce9026 +25ed201e1d804b47f98765fb5f9e885804b382fac75b2669dffdc0bb62524b59 +f7dfa427a9b825bd6cdb31d47badd42f2edb50af768763a2a119e70d7f9b4fae +d8f3bddf6d99b848689d2c66d32ecfbb51848671d5411725e11ab704bff0c13e +aca83dc079b7eac168a25f3884f1fcbff08b36a4279101ebd1ace341559a0fde +923cd6ab532e667a1bbd5441357f408c593ed7b90d79ff8f173065320c8928f3 +8f56b99e7d1ec6ee6af5c42b3b88333151ea12e91ba00887bcb47c91416c7607 +2c615748b24e4127ea194f42fc09d9f9ae76da3a7079971d7cffa56efccdb0ee +259e5ad824758630a347c6d8a5d55b34303122f532d0cbd148e1a27c16ed82f9 +f5a50f36b74bef14e321c47706d119207cfa9ed48167b8f2c3a364c0cec895b9 +359b12b03e7e6b7f9d6ad99379841acd78c4e6035e4293286e6f25382961eda3 +83f9e4bf8416e3527e24d3545bf14039dfbbd056d243838f2baf846e361cf99f +1297bbc113076d2fdda278bacaf8bffef964b31e6eaa8fe72a2aad5b0a401f7e +52084225e2fae495e621fff749378ce1778dbe0cb0a801bf016326b90473e019 +471390ae69c9624cb0549bdcc3ba465d95be6a2acdeff59f8e36091e017682bb +2b421fea645e4e185c132bf13a1190e9ed069e6d064ae496bc3792dce5fa0a3d +b6e90cad810c708c666741ddf558f7dfcbcf7e67a2a1835c5ff235f4bd362233 +31f368d56024848a5c7afbca41cd86316330ae44549a0f386659b84be61345c4 +6330243856e232ea3d4fab164acb9f363d5a90ab82b96f80713caee3a8122ce9 +2ee2a809d66a55e4fe7a0f9e80a0e3ea3cc26982ad3d0581c700dbad09def872 +6ae6d5adb52aebe2896ed9679034bfcb370005084bf61bc9a636aa64b4ffb797 +783fffdd8856883a9f01acbc436f3c20af757db2d5706cddc16b730f7f5f1bcf +8ff4ad417afddbe3a3219d7f81bfd1f23e86aa90544fef981c51d1f894dee934 +9f83adfaa58762757777033ae9e247af05d3e898fbe055c6cd73dcc8259ee4d3 +3fefe6cc94745f10c8b730db055023147896fc721987c418eb62b7e805fde6a8 +7791e4a660afc06a032716601a83e1a2d0e5cc7ccdd9be98c775c9af030c9ef3 +de41f0012cf6ebc780ad972c076550e05e264692f0cf32c34aa65a2caa26f192 +12e7589e8cb05e6088f653daab5726629ceb2aa2771a1d6fc0358d0201b3e768 +f0164f8d5ea44178da7568c9243cb40d95f91664da4049afbb447def62648214 +ac3e3f6e2881c7e9df7b0181e13f047ae3b5e5fa90af3c84351c98fe04b91bc5 +719d357834c2fc98a42591b55aa24bf5f490ebddc1fa545b91191e342c9bcabf +8653360afb102cf85778f01821aa578924ded8195d1eadc8762eeb32e321f654 +37be34ca242ff06d5865347bec5c82abd7940cc32b5006a67605c0e0d6316b68 +dbdba0f96f9b5fc5c8262779b593b8db2775cceefe7a48b5f316a4f31698bac3 +a5ff84645c79829775952dd3cc0c417544f784ecf9d10ae8bbe2532e08609ca1 +afa10975cdd1b934df11862b8fcda2edfbe9ed95d63d4f36a9ce6105bff37954 +6fe72c56c682168be923884b5dd4450f9e389fa76b95ea79f3fe1df64f7f662d +c8a586d75519e10dd0d90ebbf9666ccecf73bfa05b1aeff9e85f5c618c675f74 +bdcab0a3f41478b03bf53ec27e2e99c1146c9127a1593cd244abe930a8a8a4ab +a7f5ddcc932009d415a11dc6883c6af0cf4399f691c1a5b5397eda6025794ea4 +4f1efe05fd4936f1f7654e9159c4d0ecf71c858228578c33a475761fbb30fbed +f83d5174cc8c999b33e27b774c78781b59de133ef6f4c5b784041927cc0da839 +b5960dcea98808afa536f7d56ecf6ba84ae05191e94c4ec4e15e66f3733d6496 +e8a97243c0d8607b7c762d6cf1b73d7fde323ab1169b4d4b047530bb1f7d63cb +48de4680496579099a340644c4fdc510246b8c5791790f97c96ff10ef65bf01d +85f297cfbf856f2bef9e2955c0fee6a0f577502723e7bee25f0ec9144a9f2be2 +b24edbacde402e9058c42a6860fa28b93c668434a9fa52989384ba1a6efd9df7 +4edac86c57c903f0538df34caca11e21dee02e09e83d3174c94314cc77030e6e +436e7afe04e363cb0899da3e04b3356f37ba3a063bdcbc931e6b5bc67f4646cf +b8d270a718b86d36a8bf71cfe37c8b406e66b6dd2570711309ffbdd171673e9b +55b8ca879b59eace860c1389778b357c03f657d909d7a070278f3acc4596937e +ca71cef11fb4e07f7961d98bf4aa12021a75db2f9bb648add01a8ed2714dd3e7 +9240afcd1c4ed4645fb4dca172c3e44a2a40a05f4d89596dabbec24c4c815f5f +352783e7f793966af602685453b8f05bbf52a4f79d1e4bea5fe588e556d66ad5 +e0c0a6b48e8464800520aa5027228c6aff5753c8ac00dc469ad07952a8af8fa6 +7ecb5c245335e6e86c8cc5c81189e9326084d45e6c72ac8c58f1778fa7ccfd5d +4c3c69ccc99d6f0f1429ea3739829377c3dcde2505d56d872d1e7fbcc5a334c3 +9de1af692018b0aa10ee06f2c5656f914e70b7abe70282a8b722185f001ca4e8 +b9e224031d674ba17b2d9690a4974b11ed8e6341dea79eac4958244512fa3a62 +d8429d2f0d2a32aad6f1e52280dd739d012ec6cb456d909621121209daad0765 +862e024ae2f65144796c60d12d3ce00c0d1af7dc4a4cab72e543df51ac9eddab +35fc9dfaf1e25d537a5f026489065a78071e55ddb03976df8773adcc2a90e59a +44d95f68ec096de828f70c35b16a2a75fc04ccee27ad1ddc30b81d91cbe73022 +7b25422f95b4972e0d0b1489f9f8148ba9cbae8f923207a39ebbf1cf4a1c9983 +414a7f19e6863f688edd21ea5c3a6854b2ab8504c823d05a0ea90172991cdfd0 +2ce488448fede5a046f7a8049c5a41bc324b03675842341c4105a088572abdba +b894a2ba251dd0e47bcfc1e7b7863e5c554d7174406a3e4ba884fe84c8a4e62d +dd4a0e330a3310bf626808012f9500c8bd74340a3c842c28201e49f9f83a7003 +fd9fde13b05dd88319817b9276a30d101cef4f0102ff616a1b91e42d31413fd3 +740f60fdc8fb87dbdf7bd0748b228476fa55d89c5d2b7fda2bfcd44756b65106 +0e91900e774fedfbd2a858109c777c3456a2c929e28c211ca1d28841b5466032 +98ce3ce53ce31899d0cc6a741b44cb8c1308ba983ec621b93ba0490d6b5080ef +53fdfb287db9e07b7044c0f64bc548c2044cd67308fac1593bdb701d6b3053b6 +becb0dbec807744898ee1efd3ddb57e4bdbc9ac308b31ae4a028dae4ff15e1ef +5116c7a6c133cc29ae3e2d505cfee7f7a396e9cd2d7e33e538923d69e6ffd765 +2e78436ce9a25c2ed8179c67e571dc890df7f88dcb29e08bca5ef7485171c396 +a77cf997429644ef557b273a4b03d1f05303d18c1635defe672db610ebfa9f52 +0487328a99e4a4db3419894c8f21289bf056c6426e86e897ebcfa1b3e4a1bc1a +2f93e99966d3224f5ad6de20efc7f3a6e9404f06f6abe0fe7319ddbe30c89321 +454804f55f46b6138889dcb05d5608d4f55f7f46f803d94252559b7dfa19c173 +667f3ee87fab52cf3bafb2a6090719016541278fa4b56422e7fc53f9d7e66438 +54d39408dbef48ea95af31ffed44d5390ef4c18149fd0a7d8e8a001551e26ce3 +837930a7d957e97c83eab239f0be76c0ce6d61fbcb657b2a6adae3841418a7c2 +da3e20a16d07f3e9752220bff072433444a675b5611e40e02d2f2470e5f0afb5 +3e3e7c55f2ced72826e1e30247abc1461c655eac5ea9a6a6d6e4ebd01befa5c3 +9c5a9b3e0851a08dfad338f5bb16bca6d2b8556dcb1b882633838830433260e4 +315d6166ae11d5b71d5c522695849ae7baff2a06ea1156220e0bdbb7ca18a000 +0bfebd199a922241008946061f06d6f51b3d6568e19a8e8ed69296cffea6a575 +7aaeb86026e15cb2ba7f152863f8a5abc40307c6645798d73339d00cc5c92a2f +3da3bc763b4de25d77540ef12bc5b226ee156058bf7bf558e090dbeaaf39f535 +29154eb0410907b44735702bdb2bf5e7383656f10064a202bd37bd277c731e59 +42826b293f74abbd674ebdc8b405f73cded0b8a257a0367f5fcc093df445f7bf +831b3019bcc1636e1c47279a9b1e930054f1b45199cc42bfc2d5fd2887a20cf0 +f6d017336a6b24b0dc355e5abc204e2d6dd28b16427ed27492a58cf285fb8fb7 +2c53da51e8c9582695fc9e378e91e3648597c0f4936fc43ded814e6f6ffc00cb +9980f27a0dfc81dfbd0118c872d054ab50d417b528dddcfde8ab02cf1c49eff9 +917085013c5f4ae08711b5e6454a44a8ff5cb43af88c506846afefeaf97dedf5 +42d7df4d6233b04dded5a3ac873f0959eae931e8dd80c716d00ef7e4809a3aee +1fb830706a69b1f3bce192c2ccc0bf0cbdc5d567f71e68a7906c0067c2d20b6d +079576ccae6e3eca892aaa0547e526c31b7972b75d3050411f8fdccb9541a9f2 +9c16a8c027cf0584f4c80fa71d208fe3cd393ef2ed3971f9e1c981b4b134aae9 +07e09862601e91011ff4b20495fdf7158e6c37d77efc2b4fddda8cd506cd8065 +eb2fe9e63052d128e4b0b61391170cba97cdaefe24b8332379e05d724dec2d2a +a7efb8e4bd9ace9e57d0c156b6def69c91e6c40b3dfdce56e3382e440ffdf8dd +9892110499f9bfc8c5bb34c980c3677fbb4322cfff989040abd16faa5b1b41af +7add784f950b601acd78016747c7e75ca596ff36f17cc5513c55557250632e9b +48d93a6324385ef9cbabbfbf892120f72c2c3264f72fb2cbaa5e8cb7092aa1db +b47600f988d41347fc29edbd930350a9515227324e1069d65bbecedbfe30c322 +518d3f4e8d03e852ca889a804268de2bc3e32e7e3276dfe95e9b909fa8d1cac9 +de44f3113e84e7390c00101ae9735b679ba962700994b46c1f32b123888e6c66 +1e2c0818e29fa44762092a49d3526e3dd0ca3aec9bc73b0090d9e328dcc503ea +6767a35106c231d18154bdd971570f27b74a2c6baaf1354ef8e54cc3f0142ff0 +10bf7d5815715d64995607543f60cd47cf1eded92694cdc49634a4bd96fbfc5b +5afe077e1939bb4ba5cc81b202b502fda23e552f4ffd0df0a97db3c1b965e4d4 +7941091dc0d09f50fa9358ba1916009d970d7aeacf926f870cf4e925c58c9524 +3401a64331f960d464f5ce7bdd01b324c32c47371c55bcae0714db3c50d5d2cd +b22974f81feae7084bcd792b13f6872ffc69b953b13dec4a49ed337bcd537690 +967f380d93385254a9c8844d12d8c5912492e5600c12d73a28a758dd08fca2e5 +160fe8849277767c4cc2dca9895b2152cab6547f8c2578311abd111b372c5f3c +fe65ae9ef1812c5dd18cc16f291b91f42c3c33583b2683ababfa6da3d1012d11 +a01c9659593cb99375e449ef54147c6e8c7f2c7cd02851ddbdc23a223d6fa75c +2922b78ac0365868dcbe38242fed4e598d46456d9a6b5db4aeb6916602f42210 +2927dc778232be64679f464a66a1b8ea70209c801d7c951e166ae532381ea65e +bb49bb665f9ecb7d793e65fcf279983ab9eb95469954b031be5c135ff7882bad +a36060388027f824e0b00ab50289f11e483e872fe90895b3ab88ea5f30511843 +dd3e3c75ed15a3e587a4610807fb3208da4b916517860983e4ae750b4e69ea34 +992645bd81eacbc6159ee6370f0fe3e5c2b8d3a0e7d1d75a8f7baaac0fae120c +687a87c8fe67c9c65222b09a1624e7229603ed41bb1c31e8ca6035c729a2e86e +1dfdbcacdf4ec7b17b7e1f3648474d1341ff370ec49ba285d919d88b1dfa03a2 +4f491b26eb1dc656b9c9f88015d231071e5e87694086d05e4f8e5e05fc814d3d +eb86db8d0cd804d8508e316636857e25aa90fdd69d7107438bca1fc816fb5299 +cfc6af918ffec351c806583913b7eed861e77eab0557353f45eec68500c3d82f +2492f932f8312ec4691d1801ae0cf7304af7314ad3434c877f0b44ccdca7faeb +f903b522c09968d538719c2ea1cd58bdac3d4af0904ad3ef0a4e3e4efcaa14eb +7290575cb38e67e534c8937558165d194b5f3bd6acf48f5e4775d2cd7a17a9d9 +fa0ec0a67011e397f50b4f3b17fd1b070e9267aaee4f71987e7fb0338c177703 +fb1a0996b702fd1520775f97d7c467cca3cf75a6cd67bc369d2ab175bd5b39da +f954d496b1e1669c8db2c171763a379e4ca6b58960073e74a85fe3d47b25a25d +9ab41c029c4705f1ec2800f8934d7bb96a37d756ebb15814dc1d289ff9168b2d +78111b72ce3582eaefa04f1b05a148ed3cae1d923c9ceb60ba22b8c43dc3d789 +7cb56f1af50cfff8ca2bcbc912494e57f56cedf1d4525fc42b621af1b574ff13 +cbb11f6314aff0b296fd1af2a56a3a6c71f135447e72abc7b02964d51b8cf1d0 +dc62ffdcaacb719bf698df7e24fbc429d8e4e6be344b96584091954d324408cc +963f4701a0802cbcbf00f6ad81c79ef8c4cc73640cdd7811386192c522fa64cf +ac05466236ac61c13cd599a71d1f999cda7ce2a67f95f60f8424bf93f1266ee2 +f595b8ce7c00d812fce669bfee31d905a881eaf8b51d6c8b02ddb275461e934b +47b8f63ea8079200999216b7bb9b01c91af024e6a1aae940c1a85a8bca13c67f +dc8d93eb74ed97d22c441aa83546c360e15ce65823e67040adde64c9aaed4262 +62d75053f3780495f508bcfaf9c39041eab9d31ea89e3c46e732c420a676f85c +898ee8e27202976e80b5b8ea0296d46310a64780d7a8afd2ca23d360e0a1fd0c +99e0a84d0b6b0a77cfd41ce794477382cf1358e08aafc4f63aa2aa2e573b1cc3 +97797d98aefa5288acdd517efcfe6caf7485a4d8fa034e5d2184b653e57a2ba9 +dab7db4933af96c94b49788cf8f63c66c96c08f609b3ed94aa751e8b607311eb +6cdc6e8dc8d4cb464ad6518946c0bc908f905bde90a85678f9132543809139d8 +776a1aee37df269ded879677e284e47b011591732bb9ab0cbfebf34c06911c5e +343cf808ba5fc8c834fa58ba7186715b6b8a49d6b005d393069aa25039e61950 +2f008ce4ee7184f9d5e6225debe6665970379839f62bff5eeeed9c187eae8c72 +b2ae42e63f9942e7919741030e3ef41db2101903689fa998b3a34fbee735d9cb +dec51719b6f93acf6e356906f658b9930b4fd4d9946ad7c842278bfd9f3ad910 +44a63f9c58cdb9713f5f304aafc72f6b02f3229c3c565129499e8ce112eeb4c1 +b3850dff46803b659ebd45522721b38f91c747678471f4e481e95d47e3311cb2 +9436a874cf87d61e19312952ab90c908d72284646ddd165edf96c95b184103b7 +2f43770dcafd181d2d97fddc1babbd5e3f91282e512acfc54fba8c6801331490 +88fabf08ccf4b6ffcfb3ae0e927e31b295cce6fc1d54b6f35aef07bd577e1fe1 +ab5db3d36fb8c9a6c41b04d3beae08cbf9347cb69ce1fb8fe919567c897d6144 +9f47469c7cf62cf2ee8725185cb21c96eb2cabeafdf6dda13e5d23ae6dd30ff0 +0e8229a2215e4ebb5a2be81166750f0ccceea7b0d9e14114621d72e47c995b50 +d6de7e490d587fc116bcd14307c2b0f236c96b8a7ad62959f2a59cf623a191ca +a61af509119cb1eb607997dd2ecfefc378e8be9f85f52aa0c4393c954c0a2650 +530297903b4544768be5ae8cb36c5bd7c377c0b092562ee02781424debfb0567 +03097172daae9f078da6363d6600d83a4ca10eb3d3730514c00c3ed23d0bc790 +6d452368dab19fd9d9e77368d39d3b3a9ccd25cb0a20d84da60ab033eb91dec8 +e4a437996e331f582a355cbed7f67817142d26bfb89106e15f75618f7facd537 +60f8e25a62505e6222bd3172fa8948c65cdcb54d63b4df1f45519bb0e284cbbb +6096a8f734c7a4687e041109f4447d9fe7b6920654fb602a5811d6abe470857e +3855802b13c4fbfe9b04a224b51abea99b199c9938ab3cef5e5df590b8544ecd +f89ffd8296b1ed531b23c7778850e51ea00aaf01f01934805b1a25efb95a1db5 +a392d73ce8248238ea529992ee52e25ec80898444cf8f030e07ad425e8c60e9b +2cb46235833b056b0c4c56d2aa35e7d765c48ba672dc5f68d5a1116287125673 +33a7e3aa96aab2b63bf53cadeec8641669a4a08e545e8715d7809c4434b771c7 +410dc0133e15cfda27efa523e776ca26dad3b27a3a7e33fd73ec9e8f7b5859d4 +5068eae3a934221219c096119e9d83ce70e24bd978ae7d38b6169e64d6c995de +b644397e0e0fc86aaf47f0f0940434e435068ab163aa963710ea914f5b4e6c19 +9c9005b869ef45e2d9beb3ff446ba1258c97faec99d59cfe674a154fb7d647be +7384e1e3d727d1f35fb1afb7ed16f0a9f6363df34ec66ecc4ada1b7e98b7992a +7031d7ac6633f56b493fe1a3011bb4a7ca6c83d8d0cc70cf83bfafbba64efc79 +ee1656fbf299ade5c7f5053b6ed002ec6da9b3afe8e25facd9fc7c37dd6b3382 +2a30efb91448b46eccf9101525493478b1d89aaf2d74b36d8a37df3667f16444 +7e6cf7fff5d05d7753d9c2254fd8a78d5c34d1a96349a6bc393c851c72fb876f +d2d7fcde10f52e559191b7f2bcc4ab90812188c1b5509d9035f2256b786f1b4f +5c9c713a2e3d9c9c57bce758ddbd0b4541475c636426729cc20c525f1d28c35d +5f552f95e0e33b1084d8e6edd848e992cd91e44a91024b8f5606df9c90b0486c +adcca028abee412a2e1e3bca866d3a27d48ab6cfba8b9b728456e4e68077f249 +29d754485153bc5398abe5e7bae4c0df65b867f33e87c87b95f5c3533111c0ce +58e92f6bf2b1a81bf1c388ced960b636077e6f919373ca9edc8eacfcea353d3c +d329364ea1f12e77a5270da0df336f0dccac0296cc6b105123e7c561295e7342 +30d7a610059bd0dd92208790bf53a3b866af7e41d755abecf0828047dc9f48ba +187b933216ca753e0b3279feea006564e28693aa03a4402452e25d284acc525d +497f3bedf42f439846e73a6cfb16acdb3676f96a66e0293f1211fa369fa546bf +4312c86a5c050c0c3f5f753a6910421842e0f26a501f1a92534159a65b2dc4e0 +046f68af0db555b4c1707caaed588db2e036eafa40766cbefb5c183e327be4e8 +84024145af204a3df67ddcfa785aae5a0bb3a4580476363440efb744e634735f +95fed5f06cc31c40ac4b9ae87834a15860041e4f069375e547a21cd42b38c1f0 +944c28f6beb7e3a960113b940b9a0afac5e69b84c018a93a4773b79032d82871 +d7f65f7ecc50e5effc983b647a0e5ea134b3f74fdb60613a2964d52ea4420b39 +afce2c80bf3cf145e402d8d4d43abdcefa2b27780d52b2c331360c904aca25c3 +d2936426e9deed9d968d7cdd8f31e8780f3de4aeb374a7ec723c35f37cf9fd9a +5d45e292b03bd62a13677c83d5aad30675aaeab27044c7492ef942e45096f304 +62bf062dc1a21da6a0a49b883145a360fb05478785b47231bdbaf85eb87ac824 +e2ec98fecffeec36a983aeb1fda15daaf6f74778b524146b2d30a02e898e0717 +b1b92e19b5d8838823c69323cb0723ce6948747a59fd8ad8839ddd83612ca910 +7003baf0550aee23de6e4dbfbda1fd901f73d6049f463af751b166827eaf6cd1 +85ae1342ae3709921ce9cacc41a4758ea0ad557d44daa2c1f8b7e8100d5d4d0e +b2b0c5b89bac53fc9075b7ecc6488f24a7ca879b64f0b32cf88a0b826b1b80c6 +427bc55028579db7b10bb7064bfc0c66ea8ef7b944e8d6ab1256c8f30437d107 +aa5efe6905898b1be5fc1be1ab87a643e77bd5ad3887a4e57c8acb9ddbf31f60 +ae4c44599b91c55dbc8b329a40a3f6355171d26a09dbc9eb31566f133f963004 +c62501c178acfa72a92f9049593a84cc9ce7f679dc3a879e3264353b850883af +07389672801bd132b609c22540cc5ce53e6bc64a6a112df84c0fe7d28b3251a2 +cd5bdf29bbcef2f00831739667f2f9613193c82187aa7624a8dd65059e16587a +2b04df11d0c83501804463f2410035bc5d25cd348b74f2bf1690c48d81973536 +2ed4850757c2410caa4afa1d69178abe118abc37008eb98276582f0a2835510d +b6d94944bd9c5307840a9818596b58376fa143828a162ec1dd223a615f20a067 +8c95e3bd23a91e344623de55226a6d65d8c1b5ae1dd5cedec93757b9415167f3 +9eddd35de5967174babb9ee6ead083025cbc1ff2f6e8043ad7140f406f28058d +8ad04aca4292e4154a1b2ff3f95a327b6cb1931288a00a83492b9cc909e16e63 +879cdc4da2b7a0959a10ce535aee643a558deb122b6cd733243452eb8f4c54ca +a1758e3069cd21c15e7768c9ce6335d1d3a7e5e365d352ce7bac9bc25ff5cbdf +a3f1ba8f14a6f032a842ffca22445d2bd61ed00e61a3b6f36cf71c0f0a74bd01 +7b0929ed4ff827378316f4d36af68823a63435fdca1d768628c01aa6f6f48d83 +1c5f29596409672fecbf761246fb1d24affac7ab4b9d4570164b98cba249c187 +b21b5d9ac4431a08d224b015d73fad60dde81ba6d663fa7f30680615a1c76e66 +6565bd44a5fdb00df11e7bbd72107757dcd094760697a33019757d74d3733877 +8a92ac1b6e13be1119b64111352ea0ce6fbf924e1c117d1bb91bab47c0357519 +e45acc4c6b8d3550cea042d894e177ecb982c3d840218883eaef00a87c053c43 +55789542d2daaafb8b303c72c68ab43b5255d8812b195523e698a9e7e53d0b4c +c9b93f0eb6220bcf19929718b194a33455ebbf37dfef58ae91bdf82ceea844cc +4e7df3ed312556ead2cae10a980a8aab0b55bad971fa87ba63844b9374a71253 +9c403a8aa1a44126eda154b03389750345d19abc3d81b84a5666c7995af5f91b +f2d1ab79a31a2c9675c18f90d77dce0dc498b17a952d3e0b6d772920ec704e34 +9d5214c3c5711d8a3e4f5310dc276eb5df5c93c809336fec269bfef55d563c97 +4f30229d75fceb8d9ca5391f8152be387909fb32e173eafbde513320ae0dcc96 +c898fff63c3914cf2278326fe90c250c3124c4ef66d672cfa0a38ca7af87d972 +e6b647be9f9e9e4bf4efaa2b8e8fc8c2235b356952651c773ef7abf15665e40a +284041bcd252c3a501a9523ca992dbd7f9f63f0f440a277f32a00eb9c0dd97f3 +6f2c541af63f6a589e16c60121ef459ba4259a4c4c97cc4c78a34a55fbe767e7 +a8efedbfa031d4d579c5f56f1e3522d0d17585d5084d6f6b14de8a36e50e5c62 +407de368a35bce42affefd55a6ad0ea91f0ad2c580d84563a5c983d7f0c222ef +4869481b4916040e5a505587139726bfd25b3b3323150523cc2ce03bba4f54fd +e638b7c26d08c7fa9d0972aa34e7210e8a9bff6566abd958c10773029a9277c5 +fb2c051d412a29f650467cd3621f044f2e6f84b0bc6d638fa037337eab2b4387 +28f75d05d2ef758ac3bc8ce0009b97573881f01b202c3412343c6bf2053a9905 +d661aa7384a4225f6056fbca8f1f5e273044cf781e5e1a8689f7510a7b6ea81e +77433ec4f50f4d50b86e74f634e54225e7cf61c7504e1fef60bbb84d179d5f99 +97f744b72ce03eac2f2c675d3f024d497e908c9f118d26ac7deb208ef531997d +02a99d2913490941a7bb03453e086a7eb6592f864623ae3c62c717742ee1af4b +f19decae1e5d3216d5ec47fa5215681c82354f6cd1e6e273f2cf427e5a3988d3 +de453fa04d0e07b463ddeab85010f93fbe4c85f740105f732b9aa63cb9ff7b3b +7b128e3f5ba593aca2799f584aa68aac71fa5f5ff4d0c751f024de5dfbf8470c +5d0652995e02ca02f60f9a9f588c1a9b5a5618d252b0aabab6f73d6274e97168 +aca26b60bbeb72ccaa91b3c5df1909cdcb409d75e6ddd1b49112cd934b5063e3 +eea902ad90a1d45360467af8a6bdc06e168074c51cc43658bd0e48e91e12c149 +5436f16db485f850333ac6cbdc09d8be9e27c76fdbd15e1f85feb151259ab359 +522c9976d5dd16b775900c0cf0f540ce6c498277acc6f0663c8a4deed0335d98 +7b06311399c48a8df1fb8c0ee01b23d2137b3ba76e5fc1a1e88dc763c4aba767 +74e06c41d692c6c741dca611594116b6ddeced30e843788f75463e605c7b655f +fc7e9bbc4b81817e9a373a99f6322b6bce04340a1dedb9b36b1015366ec367ec +037f8a631204134ff52ed407f55c60ff1709dbbd06b9887fccf6adcbd642b36f +a95b6e264bd1e69bf02a36b5b48f9cbf60d4c0c81376d0fa83f26370675c6980 +a4131e980fbc485b06ddb32d55ad76ca0d105c1dd387b8a4136c28b1a088253b +1504d32944bd3083547e42c2aaea2da3f9396621bacf60543421ebfa45d77a42 +0a7980f2a2b61e89c08cbf9dde671d54b82a260956a52b5e8c77fbec567141e9 +e5f8e75278e459dedc2335e9bdb6d3c4b98cce4d500fc6d0636e0398cbbccf2d +f76fe8303aa2ba599cccffdf84906bed5ba0ff000484e03c880b3d429755d0bf +967a6da4813daf7f8ec17ab61b1ce6e215ec9d15c493689416563c79d1bcd8b5 +9334bf423ccfdef43c93a81ffeebc74bdfc0205fadcac11a9a355038ccd0f608 +e96a815d4c347561f123e656a4308654b47a0cc733c1b487d9aeec318e8c4827 +70178170638491377c7b9ec5ddc283d8582979d123384a1bbff59de08092f0b9 +2dfa2dea557517a74632eaee181f773b8a0d2e45245fce7d7833ae58231a7e3c +0a380e8e8ac2f3d4ea8cda8511d162ed19436fd348f16363d1581d481613b226 +9268f0132713ec883102a083f36fe80d00b3b8576e4f0473b6a4d471bb5bc9af +46f3f764b7ea223f3431aadeb55dc0208574682e79ecd9bd313dad8ace2e794e +e0c843e295836f4bb99e96bbf2a44374b970fb85e2812ae6dd7b14a9539894e7 +660a487574762dfdbcc9268559429b456f617ef0139906d5986a6bb089ed0030 +a929121d5f72a567246454d7a8a2de4718da4f1f73b6099d8377d46e39523ffe +bb134776eff54d47b640092060df689803107ff21d03d2b1f74880556b46e270 +06c3f605727414348d157b60b7b43f152161929eb4ca2dca5d1649c06bac767c +e6662a0217a507452a733280425cee06d4547f7fa935f422de443ca5332de926 +b3697b3759e859c8035b455809a10699404e50fb19a27f9570ba99e1db5537c2 +c182e209dd3272dd274a4ef30ef5329f7cb948abde8516aecdb489b2fe612fd5 +f7e4a58795eff39bf979c37af38994be52de19475289cdfd44a814e61f082992 +5dd33629dd21237b0755907cd4b1f57613a40a1df5fb49e4c669bc6d9d9021ef +82d47116e9f0f2411b86f9d992306e6ce7d67023e719b4de162a56cf5179a122 +064790ea77462dada4aaa01e3712cf968a5d927a6345e57a38b1e39fd450a104 +55c4774876d425bd600a0d39f4bf40143d86c9482865acbf02103e8d5820c8fe +5e970f8c13716d6c2527bfc9f2a0379f9497d66ec0568a848ce1d27a5f35da87 +873b9fd0618fa1a21fe0cad26c94146ca1a7d2c3675c22edd8c65e382ef60951 +83367a8c20c5e03cf363bdc01a6b518c23b5a7af0199093dbaa827be1dca4716 +0890d2d0093f4f1542e5d4bb97b43d3d1d31080af30efe20a27ccbcf07db14be +614257b1e68eac82d68ae3dbdcd0615313450d751d66ce2d3be94cc2c1c2ff95 +8e92fae38e2ca53bc008f833012a59c250298fcb189bd53f5e480a582a677cc8 +d2cb0e808e3ca2012829789ba301445f03472fd4b8c420cb868d1e9212fd10e3 +61369358976feb648b7cc1f93f6b480237eabebc32b938c2121bb82eaff43593 +721a55506efc368c2c92282d3139d1352acd1d4ac198b92e613290575e824bba +6414fb1bdc7d67fce5bc6d60b0fbaede50ef85dd26c0bd6d27f9850272b02aae +396c5f2673f65cf547c683046c64fe90ed19e481199e708e65917163ae2f031a +de518d5064a5981ed1baeb1155cb080aca0fd2ce55bb8b085d4d15946ebc88c8 +7748ff4af7b88ce353dba4a4d2c420e0f788cb7c7a4a0b23c081fbb3c0959268 +61bdca395e27a3183080b4476e04d886400dd28cb01e1e14ee5c9f721c7b0f44 +739c4be12ce26be1a92feab1ea81638d61711c9e012e08a3eba26bc5ea9c00e1 +f70802c51d31ac4a905beef495b891d45b1a5439cc680e03556e9dc2560290e5 +05ddd0846d20f50884d42ed6c72527919a1465cb0b4143f4f215d895135c5b70 +4c41503eae0e06675ba7ac9ab88d49ec122625a338ec28fc01a7dd1812420e06 +d4630346ff874aba0a22454891e100d2a618002eaca5e9efe1fdafe2dbd2977d +1afad242ae5e7d2fda923db586f5e295ec83959c7c5e16012e5e31c82146445d +df96f31f8438f53726153700b5e6ba5538ce77cf3d3f3f49fe264ec6b449f4f2 +b8e1fed15cbe6523c248cbd608e005fabe621191d601fe1cc9acf5afefb1604b +919cc57d493bec27325557e0d9dd5dac25ff2c1a369603374f165e87a86ce022 +09c3e0c297ef44763d132a458ccef3195353ecc2043a0333e154f2df1a7d23d1 +33460042b9d33971bacdae39f7c2834d9e5a97974a0d697dbdcf6d5fbda7d581 +10658e2d71ec87f16eb4164422a2e8ee2735e0ea85547f9d3471351c2f710cb8 +642d5b8b6c877bf459c21f4fdfc4716b5184b187a7ee37050c5133219dae0b92 +b7a44974ea3cf1364f950e3901db4b5246b3908cf9dea59552362a6924b34586 +66a09be4067110bcdde3271fd9106d49697e0ad442513a16e9672c6cb53aed1e +33ec24ced53578b60cd1f7dd2b58be891b1d4205ef257d853377ed1ec37beee1 +e364a09fe3113775e9d76a55775c9eb227dc53f3645f339a9bba3d3483091447 +96fde4c1c5542a907e02d877b7532819beb7cdcd51e15bc39482d291f397db12 +aff63c263b47062086c5ecbf0e63e689da4b5b22deba60c9f4278f7b9a886c8d +99df9b261c68261cf0cb62f406c1401b687de891b7a0cf5788a4c1e877e095e3 +312c629a9f54a9cc60f02767a440f1b618973c76b43858fbc5ae0869ae88c7fc +e7174e54ce714bc8a571e225d8e1872a9d5a76741be3dfe06b7930e24ff33d25 +3c8ce59873a7c7ac75f82b6d1caf0c047a55042c726e18711f0a6c77abce9702 +d6f17479ece8e39b0cc6846ade7c2e20a57b362a18b535ae884ad6287f1ac74f +a2d714107f24c03eb17568f419e17e6a52036f68acf17c73aac73d3231b7984c +09b96f15b049c7eee6fd3193ccc673fb9796261bf3ea1b655d16cc4ef6320ca7 +ed485e424fe2e1b69a06018a70ec7458f42ab1a08962acf035e98a6f5db7057b +50da20a4f5348d94d3bdcb829cf08cbe700cf21ad654494bf4244c09217d1850 +01db22fa6217d524ce1cbf361cdf72374499ebb1fca85a1b3d60c862c7386728 +76e4f74d83196401c78febd87de92347c5bdb89ea0d960a46f0c0f433942ddfb +5326791254250ba4962b9068ffb8a4c695ff7706197fed23aaa680d551be80e1 +258d65da8d02dee4e2bb12cf98caa07aa6731f8ba25596bed3423ca5304662ad +9d309e28ce9c76e7416c50ba0bda904da834e43bc6e8e721f1bf73030cb5a500 +c7e03ef20f0b4efca4043edb3033dd5bf89f0d0913552190aec70f687c5464e3 +5e24aed17837c6f079146c17f973f8ecbdbb22c8e77206463ea32ea24935d738 +a5a6d5a1519486d5842c458a47d4bb04428e879df74c8835f995c4f0fd7870e8 +3e7930af0bc177eb8fa0920991e3d67e4672eeb2137a28a8fa09b88f4d4db0df +c19803a0b2d219784decc78a4d695039c22347b5911dd9ee8286eddf365e555d +24a14a5d22b89a915e436e4c23981eec1b6b5c3b3f3f84b7a678fa403ff96de5 +a6fbc31140ab5b24e89b0b460fc9526f726e39acd48abe50aa7173e725a1a9c4 +7d69435c4df08a506b2e68740fd7bf2dadf94082317229a399751c65e9972499 +6f988a9d141b52049b19474ce511a84240e4a52d57fea47bef625b187b1ab717 +b68009ab8ce303047c198a43db0ae0192d5facbcee1be3a37bcc47ab4cef09e3 +e9bd56a0196167ba1b45cd5ff5199826af968247bf48f00a70c9db5b0987572b +08e95940d78f95b0d1b5cbf7f0b3b70f76790b368b31929a14cd819304e7e0f9 +a381cde34cb8f11cc2bb8f6d5c01bc1f1fa51c18c404825148d2a2029160fb27 +8961533afdaead0dd09941d16e76c5da8e15cb13d92479a36ae85b8a02879334 +f1e3c173b4b4b2aff0a1f1914db36ca66f425fd340356eca0c080cba285565e7 +8f27e45cfc330e84d2a9879de18b4b2762fc761152cf9db4eac4c94ae999815e +60877a45ad33264fa712fc0d15d27053c595ee0f7c67648f600b892d94b8fbd5 +435fac8a5f3ffc0ca0f2181cdba4fc7a4862794e77a844a8906f4fd77ee915ff +8e96998ec36f32af55e3791fc6b20edb20cd01b7fc561396fc66b3833be4aaf6 +c5ce157a9421366965f6e49b97938f1ab4f1466abc7928c6adf247cde5a7d797 +fc7aa39e29967ed556f3c5d65c3a098209e0cdbfb1ecf59c9e735273a370d914 +8687c5c066d9cdef6d9c428792def3c98848cb360e5d55591839665fbb5c34d6 +4321b4f8722265a16e62277c33c7bdf4d6d2d9dd0778623de5682844ff7d4075 +9d626842eaa05da8a1a66b5721b88a494a5b84b21bf4dab98a34fcb44b7c3bd0 +6291edba92859a42bcc1184ea4415dd8499c7b2733dca7ceb807bf814e7c4b71 +0ce0c2c9da71383d14a6812ec9f2e6a85ef10341503918fa3e7a62873696ac99 +eeb41dc7ec50e88677b7f7c8d1f49d695c270d0d3aca3c045dee419bd190f348 +4b181171d988ca0199152774862a265ac6e2a5b96ea4ddc92bf9391ec0d13e5d +19fbd276afe0257edda975f14697c41e88fc6444bf2f1d6a404c1289163344e8 +55809fa6d91c746677246036befd28f5b3834c23172a7d3f52ca469aabfc13db +aecebf84553aa8b3ebe96894df63ebde8b2258575dad6e9356b19f07ca4d8ac7 +7600c166405c58efebc89dd5b6fd10ffdf8fe4d89caa056c9832dd874bc253dc +c3cb06c5ba28a7651238e7a2f2c0e116d7215cd09f5e57119b76f47feaaae478 +7a17220aa7644705494776f3707ca265290a0c52871343d147fa69a7b03cf871 +6e9a0039db590cdd1d03ec4f8f4e261260f9aea48c99a343bf2b151b13bae351 +6f743fd1620b3ee01d9e878e8c88c08efdbacf07306e345619ac82ebb7cf98ae +b0d3ed8b3839aca5045aa1339249a620a1967410dfba5148961530c0275fd700 +d4245b32375b0fd2d7c07149bb35a94caaff26baa4a31b9caf8838ac32a4fda8 +0fecf6ad67e090bf8fed16f4d1404a8af766dd4b125a7fedf3da3b79abadf3e9 +7c8bb36fdb2b88b8858ec9ad26eb971a23125ac4f62391f1e8f1e8e9c185409f +dfacd96200b5ca345320cad4bbef8239773ddfd65a8f8b58c886327de53c77e2 +ea8da37938762110f1cf8f1f0e12aec0fa3ec00f1de30587b0224089fe24ea82 +84b721bde34b01090fcb3b782b0022f25a61252c046841bab161186f2b38bdea +6a10d9669389192b901053901c2e4508bcdd4ca39e75a7b219df8bee291741b5 +f56de311b7a67947703e3c8d04372b608e7c8b7c623290add8960bf7e471dd22 +a148d87f116459b82c5414e1872493fec79cf27571c70e5074617a3a32f5b6e4 +3f195ff74d9e3247b7e9fde7e0b7ca6c9a498cf2d63d116b8b26dec8157346b7 +17f9fb6e7d6232754f00be17a7952e0c039758912979bb522c2cc0b6e94e7d6a +411dfce18f3ba0104e2ba7c2811645555880e247942ad15d9ea0a8319357edb0 +2b500a92f77bacb559ea30a96317377fe83bdd591e594a0df82513aba98bf3eb +cc0655c6d140a44b14aecda0b5ca90df3874a186a5bebe1ce16f2950813cd66c +25bae442c42bf9ed1ac5fcb996e587b424c021e6b7ded3c5a91f1015911e847f +79c6c6823b109a31ec4f4665a586112d3d504a0692ecff9dcc7ea9e518b28f1b +b29e168f08c496aae361762844cea22c2f1e1cb6f5fb26bc105034b52c73d8f2 +abe241b900f0e8426186cbeddfcd7225d29e3096064d3cf271c7dd0f514755a8 +b1db386c886552b1e8ba53695a3ae0d3b6e53142b4ab37bdebed75922313bc41 +6899c393cda735b1bcae0b41ecb03c9b31b2462280511c0c12bbe42fead3e023 +d988e587869ad1e63dc8753200a9a437a2260e1cb6007a807fc0f02563ec9dc8 +e835dedd7933b45b68b812d28f7f37d5bf01cf685bf37f04ef99314617b5e7e4 +f5fa6d64659da3200a978c021657323882ba209ec1a2a0acb9bf07ce427a41c6 +e7c1955f635f464cba024000a65f7fc33b60060448f203b908f4c3ff1d71d91d +d30a0382ebcc8fdd53370f08901858f02d3060c7644b545696e20ab605d6d803 +369337b5514d24878a5610e3eedd2d3ba82574e79b982327e460058090333b80 +83ab8c16cb516c78914abb58cd4618abfde26e7a3855719c6b2f3306dd5ccabd +789c4fd7db23b3a41475e643a0b473384406512dd75de0a89cc610dfb25a4d2f +f78ab16c330fb68b13c2867f20373169398d63eedb070be2adcc29a81a3132ab +8cf44516838268b807fef228e82ccb5c9dadf92dc57a3dc06a8f38e356ca4de3 +3e8c0bcb7326c5278a22b3736b08c2350e368b9a5d89672b3b92048613fbb7cb +57dd8fcf5e056ebcec9bee00eaad324aebcb5fda695a0af2452f41a816227113 +86039a36c9f196d65c924f30aa5ced77c8e3701487b1a33f2b1aa334de66fbe6 +b6d2101e664768cda8732c1d7c85e791238514b2858b21c3a775ab27b0fed6dd +513cd381234abdfe3e1dae6221b7878e9db26d739ca31ad11167a80381fa36dc +6b0f7623d8182b278359b00f245fb045365a9298fd5a3be7fa913076f364c5c0 +51a293871d527c5675ec8f36d72710299e269a40a34ad6138b8a1da8c1d66e03 +8a0f0de3501ad8d93b9d8020d1b46069b38bd8abe98be6712e61ccdfef23e82a +77a56eb056d60dd42d4aacd0bf4babe343571eaa8fc622d13c98884dcfe93a97 +8301b21bdd7773542a23c8fda8a8382096b4c206ef5bbe05cd76e622b8b2f0f9 +278a319ed57a024263a9bdc2ce79742116c82ec37c6014cd3b15e8b924f8eeb4 +e82ac6b2cf32a3c6f2a38d44633acb89b92679101808834cb1e13f5a1ff5ce4b +d3017a9da06c0ab45c2580a057f2cd74d5b203c27e9924af8aee6d416f186cf2 +b95605a705f98bf50a25835da882ea7630a70c6af4e04c9d736ff86e50bb11d5 +6ab515a9e73564c780b13c0300762aad0668d55dfc2db6a470099dc78cca0b12 +8100871e14579374422920abc312e508c57e95225daf5e0c0155d3343f9ed655 +ae052d55f46c8827c6247da2c813febc01e7733a6d66d251c15f5d5c0c38e84e +90b984a4450fb26510eea10ac3bb43326de906adf18f9591f30df1e067f85b44 +f95b7643d21932bb35311dea9000cb945a51ff01f36d82929dd4085b1689454a +48bd5a5ce75a16447072dfaa4f3d3c293038bbdcf48e03a5ba15eb44eccd5643 +3ce5d37bd1593295789abe8a8723cdc2417a9ba82c4c62ad4759da998bbdec83 +e9ff2c4334a27b8de8e1bb75ada62294fd7ea1f0c53c31b353fd38429b0824e1 +888753ee5da640ef8a218c2c3c207d45168bdab2ed0ed2e08ef4268d5cea574b +ec086e0a73cb318ed02484b2c2fc3eed6d0821774a77dfd70fc666eef2024872 +97fe21b04a47ff7f3176594f8a22b81937eca1fbbe8b910ac15378fd0b376112 +fdb8e069066ebec35a45e85466fc9f88b43cc03c337c46d98fd075e2a5e1e47c +1ca0df930e0cb2fccc0de3caaa41f73afcab61bddf7842257099a4de1331fff8 +b34dff2d15d14ce6cb17954bd04d8468b8ef8b6468ed2ecfbc442ecdb8693e07 +dd2d0ae55043534f2411bf89f29681de9a61d76010a4a7c6038815c47906983d +8ccf17d4576ef39ede68a055d50707b7213edc0e7929726d58f0b89a4839205b +0986e6671a981bab106740465fecce455154ac627ec02391fed4129e92c6f518 +e84d00a26a6a8207c7abb0148d2005fd4105657d9341bd3cbd0e373378ab3c67 +cd33e98e8d1473e2468365f849d3519abb3c3c260134d4e355cc499e39875124 +f330a5f3e80310e661520cbde3656936cf78672029d1b3468c77aaad7d8b3524 +a98c944bf56f44dd96e9261a8a157da4f8486736a2d2c3ecadd6d4fa623676ca +6964a6f97c46dcbcd7fd390e138b914368ffd17d873ea616651bf265428e1725 +8400e22960e4c58985ac3241a605e45374dee6ac0d8aa250b022921f40df733f +415cca0f91897c723587169c5f73270ebf424bbdd2a866784fe5e1cdca21cd23 +654e46093f3f54b5f28e163e60c4cf8ec3d3e57a31154a3f12e0a7e0ef8183b5 +eeb83111bd05d370743b505059ccd4cb669ddfee34a44a01a1afe49c254d0171 +d3b4426ed4d34b27b789396e6d32fd847c45eb629aaa44d24ba07461ec9e710b +ff26974bde239997db3df3eab61eb5ba8403e1e15fec22a114cfbf69e30e7f74 +13269f315145a82f1a97b49cf98a54aa48c8b663e0b613ea70e6e455f8d73318 +296d094ef68e78e52a91e0102f80fe013b1d92c965732c5703036a2a26fd5f9e +8580ace5e3371a2d7ec86c68c209c9b74f45b06ccf9adab496fce70e19eb6330 +a169e4d347f3648cea314d976135c9f289063d4ac7e5e971127011039afdaf8f +5fd7b5dac52eeb0cd6b090bbcd758befa34b303f987d5b208a30bc856b4d17a9 +d58c8ea780a83500cb0ea13a08fa4c2c264a393194419108996bdbf2c805d542 +ac1223ff71b7c31e53ae9be22122cd755d192cef5c80954ac5a6a7499e5d16dc +e6a90fc6bec67d6c91f5a22f598f7462104414f7ac5e66d3e332839cfe667192 +64079199396f3ed88bf3357d8a9301a09357bb43d00a5b8bb672835608523da4 +3bd2580e0e08928505b952d93bb90566cb3c2682b28d4e9e0a459a2561d71179 +6765d37d74b608087515e33355fd19026d04e621a9badbd738c888cba04c04c4 +a758ce6296675a0905ffec6e4d1d066c84f61aaa2daf83fe1e94c8995478762f +d14ddabfe22f868ffa55870c49001505f237d46a33e1c6c547918362f9b19c37 +442c9d0b10b331b9277a0cd59255d0722fa6ec3b8ba0b94ef8a8bc95acd3ff2a +cdfd7a888c2bceac43700a3ade9933667f65ad3ce4122e4477c996c742b43b5b +e2e67871365c7cfe613ea0bd1d2dd2b01ed893c346ca6be0f2f89c1f62319526 +806902427866c54ae37baf41e5da07191ba865c9cee70de58fc0e5d7b5afab9a +52da63afc2bea4f1bf2e12e4f4f70320accf53dc4d469b7bbbf8019f4b2eced3 +4163b8e5cb27686864fc0d4d00e7c1d0c42bfad143832e425d4ff4d83a2316a6 +10d65e27af207e302e39f2e66fe00f37e25667390826436012c6931abbca89da +c81f8ba7465670a39f9c9a276c2d6b287061794bdc1507f458edf3f88680966c +ad1ec5e21127ee4af4b3a87ab49802f1ac67f3d7208bf3976c0eb25cb2a0ff30 +0b2037a37a0ccc9c2b3fbc583510ad74a788076a9c40cf6c889e00b214861160 +f15c71811af98e2a0fe826701b8f33a1384bbac077e222a4db6f0e6857e7c9ce +a51590934ca3581abcd23cf2cb7c5d081db2404e0698cf8248935850d5484cba +a6e4ba4e5b025aa05ef5151a50398b57568aed4598f3c73868c6b0133f7b8600 +2641e949c95372fad6ae53d952a0e343a3fc04254ef10999d90a090279c16d14 +af937b1dc58f593a2259b9c8a4bb17b3ee7785df89ec9c349a3a67abec6fe0ac +48a30c667ee0707bc09ca108fb2c993404d61132a9322ccc1301e0a33cba3036 +689980c9ba55598d9dd524445ceb43545e42bb9e83f57580e06a0c51aa7d917b +8ed8be20b458aa060c5f19c491a6bb0781f5ddeda4c9cdf3284a7cec68170caf +be91a43a850aab12b53f87eae4cbc45e343a574e9651d0e1e3b031d3552ac311 +93c368c4634c2937f2be8407a97dc60d729262e7e47f7238e42b40a82dc66754 +9d172e070444039a8646610a2cda2b1fec5c5fab4f8f1890e5d5fbb5413b2e57 +4094692cdc63bce3ab0c2ba9f420297b4ae86ca7ce6220fc7ce4cb3faa39a11f +16ae53f607aab3280ac70f58c115357b592ef8ee51be0152f5faa8be3fc4374d +9446c76a89400d441e6ca06b1ce9c2f6ae97afe5acbe1dd4f339fc5439365d7f +d0138db5b90405b3091b62b240541c1d867a3cd19cdf44bafaf66265a99b1e7a +7a0af97c5687c0c204c2b7810089ab8ccede922d872fbe167f7cf24ca4f2639f +4f68e7820e61d5c25c9242e2df539fdce9e0be6c8efb3ed7b3d9b17230c5a48b +0ff4be192fb121edc0748da3970e8147a59eb78f8201a3d7a5550f165f6dfff3 +7cba3daa527de423696e448178b7e345adf977987323a329d04770d7b4fb0060 +eb688b0d90c8b588738455bc12ef67dff8abf04686533d45c1bac790cc317931 +20cac2d5b1aaa347020088b1e8ef244a62d1d759925d838958932e41113f80d0 +6c91ee932bab1b64f88313fae2eb0d55873a15c0ad0caf7c0c8312d93c9b5dd9 +12fe9e7f1ebca0364bd5afe4e9a834cfbd0380cac67f116f6ce5fad4f3d8abce +f0cc1250bc57179bb3f36f3539f234012dc27dff8db45a7dc4ac7739a3987594 +320ad7d4a1464ac3c46a56619d4915fb7d89be483fb77cf81c4c0fdfac87bec8 +4ea059a51815d4313837db4f775070442838f46f94ae1e4aaf9a40b635b38d67 +05d0f64b5bec93d746fdf56f8090492e056be449055406923d22c27e3143ff88 +1e0d1b52567a15c9d47fa64e172222a6eccb05b2e8f5a4cccbcdd26a0c5b31e5 +aaa53260e0be80167f594903af48b6c2a2830a76ab4f8a207acfebfb4691ae5c +4c9d6f2393309adee42cb9f45a58ed1838234e5f286436a2ac7de8af83912f92 +a5472b6602a7cffdc91261707c3864e6d19a77d7e60222fa554b1f269e89a88d +7237a44da6e3430fbf4b63f2f3183084f74b583c9cf8699dde0eb8a945959759 +355e55dfc4c229da611604903448e1729ac934933792300ad0dded4d44bedc1f +b8ff5c56d14712a9f5e8905dc6db96c8c25114b95f04b362aca5ba0fe443527b +6b0d1f2e6ed4c799bacb4c948816164f5408600a5e25a8e5dc0fc80d491603cb +a2fb43fd8715e5dd15cf5c584c07075b0465aa90778f516b1942a555d289488b +a9e1c9d2148cf6299a204f90466eedf14b020483eb9b4daa75c5b0cc4f9b9b11 +d06ec0aa0c3c1475daf006b10d19ffc2541763176034890957be10f62c3b499b +852854691f3e650480830d2066b9d3ed06a16d343d2d9d7d48c0a39202842d3f +40387191b2a7aa70fd2e31ee9267ba4e6535087f7a03331d1d1236eebd8433c7 +2f66fc5d7129aa2b41d91b8328f1e248be7b2e8da21551290a54e7531ea11a0b +ab9c9f20aecd5603fb2833f72c161832228a70b6fa25a5246ff866773e8b5c6c +9b8a73136e7bcb0341f73eeaf54b8d3987790d5c16ff7778e0790071b46e6693 +160b0acf76ece2451e2c8effaf5fe03e344eb547e000343431b38805a6dbdfef +54e080b7d3d367951e7d127465ecaf1da9e6185c456681c9ed3baffd508f36d9 +9d11eea551be9ffdb0fa5d55188aa04e3481353904ded48678be6673d753c2bb +bc8dbfef72afa9b71b316393a15bcaee74641a39b542765b406f1b497d58bf72 +8672deabe12745ef672565b88961c06a16cb174a067efc8b2d9131bc1dd2009b +80493611da547fb451aa19a519f86abddcf86b18de0f34e0174fce78706c9109 +621a18ae5a29e3af67e41585b465109493f437fa8b7d1494ad9183f17a748c00 +02b3c8a420e56a0d610f64834b51dd2aa0912469cfeab9ee151ad85aefa8eeca +874396941282bf80d6cf556df8295596f5100fb8a118d9dcc2cc93c8ea0df22d +6bec2f8598e54fdedf12ec77cc3b98d028a2942c76d923ebb99876e3a92e23df +6e0d05222036d64ee486fd0ef68bdef71e119a7a45df13b4102bcac2e3510658 +69c947a9e0bef7f2b95aba798cd79a232cefc07d5c1bc0a77e0a2b4acb93c51c +eb380f5809fbe96380da48f7b7bdc6591db3f75dc4bcead50a311542f86ce755 +db6be9e1e0984a3e98573558c644c04926d259e4ed344ddc943171a9cd35004f +7d4ace0fdfa0ae068ed7af368a9e5846213234924eaf47e3464c46abb67f4b3d +6685e8ba02f424660c69cb43ba4c4bf127cf833deb6dc5ea3dbd5e6ffba3ba7f +ab2de63babe5a211dbc6038028013b2a8dac9175b5e3431537ded48f2c09e69e +aba0e814b0356a9f05b217728e09aacc5db1a7d7278fb9e370dcbc2e6d913fb0 +a31f6d11b830d8ac16ef136517c25e47cce6e50adc9bae292231b8cfaf2b0640 +0cc522128a5e380185bd683c2d332f8512cab9e78a6d5c6fa35ac45dd18d60c0 +4be1db384bb65237bb7ff77ebb467c975bee1a668babee0575632b96b4daf48f +ed305319f98a94a86f0962dca973ab8417535b57d378240227f950d223070171 +12ab7643e9fe2309a7e11cfd31e7658db941d3c27d092c9512d97a21606d375f +83880e8a553b1cf46449e0350edb0c48dec5d2041a5724146d43131942c6f1ab +133fefc5f18461c9a36329fe38dc2436654d28553aab7d1741b550e2ff766333 +f671cdfe172c172bbf2ee8accc648fbbc7e3ace2875d4e5c561b9756494abf70 +abc556c70fe226697e3b27be31fb0fdc8202436df9c90f89bf885cb223dd6726 +cdedb7a0a4f7bc832e63516efd40e7661a840224de4adc0c6c9c03a565310dfb +c4ad440101a77a1aa546ab6178245090884ed4095d9712c35a700035762c2663 +f5da47624f3f9aaa573abd4a464b61aa921e2ffa2a24e63846089b21279e41e5 +4744e9e7ca1e9478417995624ac40b16e22662faf90796da1cf76aebcf01d68e +77a39532f40f3bd94b0fac09cb700776c67831c39a0f6baf962b27d0f3393c5f +f57e185b63cd10a019426ba4b7ff00dd61c8689ba9d7ccd06d6eaf336fac1e20 +60e2b09a73f71f1f074b12069f79ac6b2eabe5d9637d1e27b093907e96f799b8 +2f6ad492854a5fca3dd8ffa52fc1aa95a4ce81b64eedeaff9af16db6f3b6418d +0fb9807202d8b5e5b41ecaccd37456fe65d43cc7720cf80023ac0689a41b4aac +af7cd971c0b1d54ce1bccfaba32f4bced904b27dd38fb8d5acb1fd116ab8ea21 +28a747474d06a936632742e18956846d0a9ab9b67c903b7b3bab2cf6011f7eda +9fce017957e4ac8ba9a8d43eb94180244d3a81b29ee025825c7c5c4c1fe838e6 +7aae93f2cf034e42b42f378449230859a53796edc8ba4dbb53a286abab436646 +6f82af205d574dcea933d6ddddb84286ca92e31518de64c2aa790c3616ee4f76 +60642fa4f5f75bc162321ebafd3207ece99b37f6095576d17a1aaa02f922fd51 +54c7dd995930f4ddacd6c048148cca3683694e187b1a53b1830674f7649abb07 +d646ca670d13599f6d4d99dc0fadb7bbe582cc84e7d0bb0e436facb887b8c1e2 +45244971f972ac8ae95374e7abb60fe21934846634dbad542897cae445ddb7e1 +b87257c44ac8a8c4b1c75ecb038ed31bb99f764c09b5569affd0152981d51d9d +ee8e759d00106e881a90c87d23a56477886e6036bfcfa9f0e5bf214fba1dc6ad +e2376055e5970e561957f5e915c98c7546e9fb3bb7965638ff35c7e9230b9358 +9ad2f280ea37a7a475300828d004f4a565dbb400597851726dd1e49075883923 +dec3591fa5689f353eb622ae01b1e72a80766d02829c7a6bbf0b9704a5f88031 +84bd8304c6dca591c342e64fd631835a5881dbdf2377256932967482d265b3aa +de51023a57936092a7ddc742b4b5d5ba125cec271cb4edfbe0e3cb6900a5066b +109b7a9b255d15711816299a6a687e68931c3a4416972811ffec05ea47f699a9 +96446e1ddcc120b0852296e068462e2f4d951653532c15feb633abd09516c48d +c2890a54cfb26b0755f37dc2eaf8749dc9f9cdce4718997d7e85c84f269e852b +9995be889dfac69969d5edd03a4176774c42392bee0ae3ba7314c4474848fafb +f581f6acb6ceb0dfeb30bc534ad3fe86b44c2673d2da5770e740a5e94f4fcedb +171f3d7ed5d2952a59d9e055886bbda5be0a09deddfc59420aed00b6f8a592a6 +2f406f494cdd2c1c3c0a4b6f5d9c39acf16cb4466a2993765ede54951db9cf90 +0cb5ab6b4ab4d79fd06514745621afec39295d1935f9083acd8ab372d52b0dce +8e155f13d65393b4cbf582d18a139d8a433612bef85460f394e4ffcea41d5a6f +36166db76c3db309254630a67a38d65d9bc7c1c6a577c22e2e0288f4d9c7c872 +4dc4a5f09e09307b1cec575efcfdc4cca30a7351de4cfbf2ae9abc2f2d6c84d2 +6a2810ed8c2a7a01ebd671dd8abddea253838c86168960dd9c6a94d39bccbce4 +320bd5f5c2a3d329aedd2462a1f0c65b3fbce417516d4691a4af2c7c099c85f7 +518d71884523f12f9096186908911887c57916d9cbcd4338599d90abb6e06ea0 +9c096aa06516745fbce7d8e236af4756334c8f9e05550c6edc4ee8aae2e2b81b +8662dfb363abbcb1a084c19d574a9152b4eeeb2045cadb3205831a43863660dd +3c669c247e6c194bf14b6f2331be617a8f693bb6a93d5dbda69425e77522072d +dbfe63e79e6a87494cc66874719878a3fb22b3808209cdb4719b685ae3063cef +6a2b7025c95726fcc8b21866b85ebd3bbd4c0497be4d63dc62c6b53d05dca7e2 +b6ff467bb3142ffed621fe4e4358fbdb0d51d4f3fd496fbff714c25a32b75780 +be192c6b2b112ea3dc5e9ded480f7adba865d8cc9a27157f2e940e71f1911e76 +c4d2d1ad724c5d1bcaf609257ae4cf58998fca8e74d802fdcd205ada28f2b7ef +044ae178501b0086cfd5a894655a2eb16233964ccedce58bd3d8807a84074d4b +881e3394f229a54562fa4f5cac343eb38a69be1b06258e393d9433ff4634a1e8 +1b738c80fff7070f8bbaa5129441ef0f996d2e34fb5eaf642cb829489efeafad +bfee0e4f0a41d12a8bc0296b4b5ee82651463c9468595bb09ea3c39f41385cd5 +4838087fc3fa98b6a53e4f73a8b564aad5033aaf96e684f7dca8a2923dea718f +5fc17c93898492ff26ba5efbc82f03a53c4d7f96628806c340fde7748872efb6 +162f7fa1a160cd8cdc57e9d39e2618eb16d82f0ab76eb59b2cb340861599f416 +43ef3155f62dfb800923a9b4ec3e97c4249081713779f177b0ede94ef993d56e +5d20ee529a199ee7e661cd156d63bf019ca92b27681107f8f5e333b01676e9b7 +c1487556de27c4748028059dcffdcd98a0bccb76da67dc05a791735ac0224a21 +2aa444741df3d97d502bb84ee9cf9ac89375a0a6f519f56dd26fdd024e365b91 +ef6063c986b0b3f904daff17b576ef2847ce9234a24586b731d19c6ea1aedb45 +ad01025ab1f1644dd2dd6b3ec16e58f46b8088fd8df984cec2a0f81f5db2337d +45585cf901dea1961940899fd51a263fa6cb58eb94c74cd84ee06c7d3606270e +a51cdbce278081780b70baaa0dd408744ce5b84cece12523e38e705db4218979 +27538ee6e2cc67e991e6320ec9cdeeacfb642f99a4c2e065e4fd4090196b80b2 +14d4ac0bee545cf70b535e6b92d25d0f362fec6ae77a43656cd7f28eacc2a020 +d07c546c55621673e8c0e2425b89891f58a2c371f6022b0bca575b119180700a +bb0f90b4e2e04ae1d38dd61d8e5b4556e4ca380bca3d98c5607a5ee0cfeb383d +45be4578c747da830d9fdf6de80a0983494cc4f034293199d631fd11d98a05fa +6571c1e566c6817c433b6a71c0c38e353237a017e0a9d0f2dd19de2e047e8776 +701e2cf00e971b84464dc07d6dd43ffae4812b6d773242a5b04c9fd4ebbfacf3 +a06ac6c1a84eac01b133d0109ad5315ca3057879886d961403e8e1e5baccc5bb +1ba80afee9262edb32861600e132725c3349ab66794559363c0daebf794e6c05 +ff110dec413548e459475bdaa3c24c5f28b32f3b6a2ba6bdadb99fe6b9a3d90a +710199cda61cf424e1090dedde59f296cfed62cac54f8c639bca42ba0be9098b +8fe8d9d5898f704f7f7684db54abd970231bd7bd6fb1245d8758fe0dc7ead62a +1a90434a99161d95ee07482712d14a9d49bb2520b725b9a73321e5b0531b8771 +eba73f90e2dd19a7c1dc9aae9c25d8d7f78276ccf2abfe036684a02986dd2748 +c6bb4a21c7c57e293674cf2167919645605d835ab25a9f49754e97138066ebb7 +681b11266fd305dc469ff7cc6f17db89b1eaccfed44824e9082c71d0ffba5ab3 +34a03a070f7316081c80b8a2641e14c5f63fa6fea29b4cd2080f9dc1bbb431e7 +a05e4bc48c99dba378373200e3bb3a4c56506b28a99e5d743cf3396279f6d403 +6d8297dd9d254c80d8b134b068206ec4f950bf12ade37ccee67e2e44bcc0ed02 +842877a6e6ddf30ad54dcff3c884d455b372b5485630fc8ce25c3e84be781565 +b3212a2eebff8541b44704d5e2fa8edb7d70bcc411d5b73b8da182279ef2f77d +09d76b1fab0f55f2e3eeb18443a8c7e630c3dca2710558d022cee7cc516cecd1 +031b256c07ec52e0f50974a0e680cb3eb6f10b5332cbbbf859bbaeda5ac3d1f2 +cf6989178e19da2dcaf8a905cf22ad3546a2d5474f9b404474dbb3ef576b326d +2418213bcbf25d9260e7b70ca7b2a715eb62f69353eca010bcd1db1e827efb69 +a79c788f80b9a1ed34f35341ef9ce4df58534744a9601595b8cd0240b1941f66 +567dac2a2bffc830a970bc66e61acced24e88a4568e315e293448027039addd7 +4c6de6c15b47d2c9d04c9393661181e642553f01d1c7c6a6b49688ea979f9cda +3e3fd6562f706f916d998070c7952c118be015fa0d60be98fcfccbfb8437eb23 +23cd6f185996e56a95b4b371611b7d3910d2bfa6e4edd6afe62040cbeccc1d7c +edd5d520471c657f3ced6f8867129a3562ac7099bf6fc9773947773434fe2e2c +5543dbcd8280c71a56608508339c50c6d538a81f4d86225d695ed13aa26bc8b0 +89b65eff7d05559ab9ec44183951bd6e81b0ea95d705f7e2996f3c6f6066fef7 +2be92f6c717eed3981102855c56d96ca4fb6ee97c5fe41b24710fe1f99aed293 +e24b1752ea645cd4c0cdaf5f7433948b1ebcaac161462d18a2f57c748e971e9b +7138cd74e7cc703f7d62e44279559881e06b61239ee28a41fd09626a3cfb3746 +fe96c1d96a09f25c9f0a7f8d70b2aefb7d4e503f941464d6a57513da7b3df764 +dc99c560d23cb8dc53832fb08f3aeed682975387f2c2e6a78f5a151978e83603 +d2cccbe7e5aee9b5116d675644028528edc5f0dee57540d0fbb0c8db6540cbea +4370f4911b0b34e56b7e344bb486b58f7ee4daa3498cd5e6169df473a6a650cd +527eb8b74f71c65e65dda090ffc3a78b1d7665c8783a45e9cd273af6cc9f89c3 +89c0729f41f493a1e8d55a15d1d947570c0ea8178b9b7a654506e3637e41578e +2e4bb335f86e3579ad3a645ebae46357b38c885c8d4ac005904fbe0cf0a28950 +1b44db44587fd42150e469a428a1ef7dc1bad79a0625ea3daa63c631fe5d84a8 +153e04c1f5f6dfcca66de8c0e43a13b370d227176193654c5e3a90287209f01d +068f61e4897a6baf221cbe1aae45f00614e96ebfc9fccad0eede85e5ea6e888c +b34447fccf202cb6b1fa427f46f9a69dc79932aa4dc6dd019c3ef77a6fdfc49d +04005a0576615741655ae9ce079607256217f35a096b67caaa7e131493633077 +a34f079999e0a5406e5187413ead0d6422645d38227d5dd1d8300941edf9d882 +094db156794645fcf6208acce19bc0fd7f154312cd5e8a28155441421fda4e9e +e460ca62db34094c6a14fed56749665010b991884d5fd3fbf5161bc63a15b017 +9d75388bb80132c2fddb36c5a19d57352a9c22b296f3c695ff7efdecd732b529 +6af9a9f79f4c701b25255685b31bbe9e4e695e59aedc0228604e0b77d51d1056 +fb111621e740d271ef4c87a6faf102a199842e4b971cfdf854b8775349c85b25 +b28e21b5000a2461c2a528c1f26dcd2937bbbb4f2196c1633cf5b3e1d5f71647 +5034bd13da07608498b7996efed3df1e58a3661caf31c2ef147d76f91d29386d +04fb7a9e2c2f9a6792268cd6568d9c29d6b32a5d14a99c255499bb33c2cf5e41 +0b4f217f4ba1435841ae9f84f656aa21c63b584d3db03c35b391cbc4099cb56e +d3c6bd3e62bc3613ba7b26bcddb41cc38477e03625a40df1066ebf844452d369 +b9ca2041cb38016b2a37267b33aca449b5b0295c8337f77ba4c3d13b4b59472c +161fc90bf7051619efd67ca25439fc45f0ad37f39c1e852777a00da41ad19f6a +fc57d2d6c33ae5a5ff3f633c6ddc92c49efc43acbfe713491d3d95d1f177219f +695acb6112ee14118786df46acc8bc769f7adf79f1bb84deb8952d91d5f18039 +f4d4f972e76ee6905dcb19a14467c568382a6cd73050aea4acb40bd48d93fc77 +e294dd8d2401397584c8fd320baeb5d63f485bef786be0b83b1b8e615a419082 +284158aef6f3ed6e528cb0f8f696163764da19a95d51b4b42d085a3db800956f +36529af572ab0a41b21304f714869459af9aeab3749ecc2f50c840f6298b1085 +590250ef1342103160d9911181d39813d14a3faf570868385810225cf499e351 +2558730a7f53075c68266b7d332f8f5b5edff074866ad96d261c43a9b7f723e1 +7259f38010e94cb03911e18ea6fe843e153895a3d7a1e7c7c7fbf5dac998476a +c55a4c2075ec47a3b09391f5d5993a1952090e507aa3eeca3864e4fb330a5805 +855a86245b06d0c9b51b7563b1b4aff063db320337243d83527e314d779dc35e +a9d3de4d7656425f5ed403a95f7c21ff827b3fe382326b65a0c9cb3bd0b088d3 +d1a545b2dcd660a7b84811c4f550b7549873c4897c6cb4332c5ddc0ede76d7be +d91f6669e6f734e7c02f2c51ce5ac9e9dafc6bccf4f4cda82b457105a432426a +fb6c1f1a58b2e35c2455bca9aba08d3c98ec0afefacdced90c84cc2b657aaa60 +57e358bcf4217950ec5df087069d68ac806bef1c6e41772ebc345a255fcfe6cc +f8c55bad47494b9be3ab648551b37fa7cc4b6d20a252b154d9d7cf3b61e1b110 +a2a0668304de465d6e62694b366e32738b91acf63e57dcb24b5e9f0159463e2c +455c459f5105d4ead853928505417cf09cddfec5b3fbffee15eb107223248a20 +f6ec1feb9e9e98ae7b29d216e91dbe6ee85a77e9409b94358f2d74e8a72757c9 +be275a0b39efac8cb23824cd83e1a4ed92f6c28bb498ed1c66f0d0642a63e73b +484acede90200d99a7e31a2771b1694637a0c4227edc87bc4b2ae926c2e8a48b +4b038231e2b5d90e8ba8b31d78d52d035fb4bed72fa8a466a9adec132069f00e +a75f717dfd7a57456b89ede8e580f9a7bc808702e6395d9a0dbc1b0fce2e3297 +0e7243bb407f01242c79445e22b2378ec0e8d12a7bef467f02b3a723447da94f +429d4fc6ad5d8b4550fa71afefab7d7d33d315a99ba1497346723d83366407a5 +3714de90f68a5d6947e9b43316f29d4a12c67d09e58876e0993a1da56a7a67a0 +4935cef25eb01c13bfdb9951e3f21bd05293c35272fa4907f8d0d3473f68333f +318dfe1b8fd5eb9c08e44e24f8c4cf631b49c1933f5625b0390f82bb3bc4bdb5 +0900abe03868d04c60b3ef4a9542c39ec7e41272e82ae66c57692dd8490a30c8 +ac40fad0b9d61a7b85e3dc3e4b5eb6faabaeeadd1aa995a902aa92219e04b3f1 +cbf5b482799fbac0ed0dccb279872719e8e7e80418e57b7717ea4fc67783de21 +d3b52b653a89c6dee78ef873da7ca848ff5679821304aef509c16786ce500fdd +464e0308ead2d2cb71330d8cde2d2e31ec97b4ab4fbeb1f9013daf417f60aee1 +7ae301ae1072922b15027d6b042721490717b60872918105a0866b7ec1f470b7 +9abf54c6fd6cb79161171e4126ad4e3bfc12f62ac7e26ed2f76dafe3881c5211 +f295ccf54e4ee194abe59067f662f4af1d5c1c6c8e6defe5bccbb85a73ae8d8f +f4849c5a714d9f76df66518d3c4b0a13aa86238125a1615c03d0bb5847e2bb06 +c33e9fca60339e9a570209b52647c331a6efb0d310a363c5317b3382d25ed1fb +dfa05c2272a58ce31a49f7d48c6d3b7302711b0c6cd277c63a98de8acb69a9e9 +8417cd45fb483b961ae1f1153f75187ce279d8f4fccbca72283feb27964ddb99 +55e826bc567bdf937879347ca922a7e831af7344d0adfb70ca9f6897d2f91172 +988475be6e91625d5a664f5fa8dc85e527587c81a0d07b0ed618d1e825ac95e9 +5deb76d18862a940cfd7f49b470e7234b238a3dc4f72b997c9ac756704cbcabb +d2aebbcc23419ae57fbffbbc2b2cd8fa68852d731edd63904710156269504dae +423e960ee985754ca0db05d182aaebfa851e4174a5ae13957bd0790d1ec92cbc +536cc7d8b1a2f35e63183ae5bfb4faf3ce8cc51300689fce98dee68445e9144e +65eae6c9172a0f7d0ffb98432505890108de83878717ed96ff46cda8d1a2b970 +77251382a8de58a3fb564ff538e7cc786f314abbba4020565eb5b1ff931560cb +f5e054bfc9a0d8d46f34476916c7020f3979485bf7a2de9e43c6d949f1f6e49e +8ca4e3be6152cad19e487d910fdf3e164989ae859454a398c0bc5dd159b7e9e9 +ae3024bb77854b4912d65906081f8bc4dcabee7be0a4ff2557b950c09ef64b00 +1c8cdf3daef1dd63d345076f3c49ee20e8f71422f0fd6f4f7a98fc36d0601be0 +01af01efd401e05acf5a48306b29e954f1e5250170893ae33d18491711c5516c +0158cf63477ef03477a2815c0c51a47b7813cec6200ac1dc05bccd26b1fcebc5 +8f5ddcad5233e3b63cbad55464d18a04718af59cdfce9895de045fefb2bd38a2 +112f7ff9af159e1289b190552673355fd40fe72df45922f3a4fe3ab29c4bbad3 +b3479cb30b72980fcde0dbb910e0350bc97c55bb7cd8af0447367cb3b2312d49 +39518cff3bec251c90ff44cbf1110ba7daee0828d5301e62558df46d26353491 +a4dc26b6472e553ae46c2190ce4541b05c7b71a94824b4cef4a2fbbfc467b3c0 +61764010d748099ccb8818a5c165c3f3e4469feafcea2c3dba5ecd7c7741c131 +1adaa3140db182cdeabcc10d3956dfe2d35ddd28c593510b4079ad411274000c +001cc880e5eed850d0ecea8a280be913d6e459639cc5fdaee8b65d77c42d5080 +759db4ab69a6d32225f6b6243a40f9e3d9389da2eab4c2bec7166fd89407798f +0ec78214492eb47aa6fb4df9761fae9e6aab5ddad5dde8baf00a6c91ddad2f15 +732db023be0b3140126679a860d62ec2f128c399767bd7312d9ed43ff8c68889 +e463167a8d0127daad5486b44ba1b5bda1e24e944ade91c2433d4710ab630a67 +0295e03598956b9cc78e9abac7caeb62c8dea6a432254b49d4c959c406e972cd +741f5137b0e9103d10f5f5a3d96f918dea62d92c5da60fb9e1ccc0bec7e6f716 +9d3773d4677cceed6db4a8362260e9f24ff6fb305498e20138210e5d563f437c +8516d1c9eb056181f890e2305db63ad201b2caa2b982474039a390b0c133b525 +570258c25c999602c7ad83102f976dd9fc559adad64ccefbdc38f162a13d3bc4 +36c3d296c6852305e1ad41c77dd72c7300f3d0627bccaddc95535609d53713ec +0a1594b0c694a04cbe5deacdfd6c0055c7e20139a7b79d5db630283521523a3d +a7c9ac6000ae42950d2697ac85e930afdc7a09902811fc7e9b73f6d10fc24d93 +5586a08a9c847d3d9e6bb5f7fb908b67d70726f6b6fd679ddb13d6e8117c3ca1 +ba98d06d3ac6a214978a9d197d25b54c8e20de2a54704079206d31e06ce0cbb5 +f8e0421a1ccd91c64685f29bd6d779d8b1546298d39590f77ce9866c43ec9ea4 +897861d539fa24afd24be8969931621c87eaddd653d7fc910bc8cf6da745050f +d2e28710b990171e5b7e653f233f890259c970c0696ef7b022b1372996fe1a76 +f50407709dfa92f39ea4bda0fde91897c4b0b9bef349b7128b224ce8e54acf8a +025ffcb2524ec8cde156f066e952947470cdfff632ada33f89ff518f3462d70a +7b85c3281f8e5ab1212997cc3426821581273834d56c0a4c0a38e84b359b762a +6d265f9f54a4f2ddf611bf5f8701aebce82a040ff9564fabc2ecd639c64ad198 +8529da11e21667755a62e0dd1d10505b7ea15932ddc2cbdb5735190d73c1aad1 +12c8eeaa1d8772b4e6b714da532d798d0321cd94fdd6e7fc276eb98d07f2277c +09ffb2e0736bb093ea87f3c343835cb3b8a1e3ce9bd7d053f3060bf26b92189b +3377e9edcbea5c7724689b91d3f5a50c8531201c23097dbde2e8454203b3d24c +b32e33dc39a90bd50db8ad640897d6ed76d0adc0ebfd79783b69e30f1c687ef7 +be7d10cd1fd06d923ed34b5e434b2d63b355d1b98e3f5fee137e76b8c5aca1b8 +9bb4f6ba46e7eaaa75fdafec3c23e80eeb687821bf5e25baf57e1101e6b3ebb0 +88a61dc91c2cf1bb120a50b99b9fe80c8e1ccdcc0f94f0c9f76d2cd312418d0a +49ca321df616ee0030583dc3d3d55290605c8d3a6e3f85811e3ab36bdaf56725 +abc76d1c49e4df6cdab3827440662ca47370425d8ba17da04681ff7d5bd1863e +d168e7ad8c70d70d7af3c13da0d9cef3f8decdf3f5a237f8c9e58ce461ff8c1f +96a3e0cb3aa6ce07d01b9cdfacbddfe246a9bd86ce1881c62d0f82494384325b +ce6e3ccc1ca33b63df477b09b263ba547a65aa97476a18c373c05464b2a50487 +06bde82e7e4727b3561e4e9140748c73d19e35d38539e148322eb293978f1364 +b075c7dfa0f71596890c4615c13bd0cd7de2e75300c0d0a52aeb209a40ac0cca +283c86c116aaaa0b77c48eb264bcabd8cb3bf752e475dbe202c7bea8021b2cdf +08bf5140f2fd2f4e752649a7594c84d6b3e4eebc67f3eec9fd85b2e4a107b44f +d322dddfa5fac17ec535cb6b2b7dc602c3f11f3bd6e83b27b7ef93acf3a0d1b3 +27fbb02c97f3e02d4c505c6adf32eccf9a04cd5f9ba0fdd39600ca40542404f5 +188b471bb4e4f537337ef6c42a677985d634fd4edab093512e15d43023c17c7c +fa3917c4da14f60dcc623217ffbd25d4d5d73d177554c5142bdc2e37a7640358 +c99fc81378cf65b11355e465cf170fca258f51957d4f37759d375fb223611223 +45566b4ffa0a37428274c3723300cb3af8d024b81c6926f32d469b7fc0dc1b04 +32994d62d18ecb1c106ce6767e770dc4df3e45c4b4e16effd4e3be490d159bec +baa056b42edb5327d460cedc286e5377337e552d3be149bef2c14dca3726cbc5 +1ff672a563d51860a18839d4acc29d9d303b7570ff2fafd430cfc2a0ba2d9c2e +8781a845af259a8a239d2c0e13049cce35afd0f67a37f8f18254acf5535d0a6a +737106b02ee39a69a42d20138526f74c2daa06088df3bb7fd78405d3605b0e03 +deca35ea04ffa2d157dfad7d0596f70f7c317e59c018e8c0f0e424dd21f3d81b +5436c7983153c89ca759bb117389093d1e00a224437d1500f36c4f29162ecbe8 +d315d550a0c94c88711ee09f547caaeee8cfc10d6af34ba25a2c1c72f1dd6c3c +97e8dd9700743759bbae91c242187fa17a35484a979b47628ce47f2f46cd597e +3ce2ad40704446b9ef91482a6284a06a1d06213b1797b81057972784f6100de1 +d99fcf74bd02d63cda9fc557c1c41690308255c6251aeb7db0d89e6358613103 +4a361e9a3c5358743cc065ec10e059abd5b7232ce393b233b395de271b5d52f8 +0b805892472899cc72171400f52f992f387275dd1241c357916baf2ee2ac1731 +6a7fc42c339a0e94f6d144615a8c762cfeafe0527cfac41a28474695701f33ae +ea4249da7ba77b008441bb5c7ff23680a13f02cdbdb6c5544f89574884c50884 +907325800a20eb4ddb8d21317a9d432fd16234c5b01fe30f4b65195e8c532f47 +4d45e853e2c7414da9a51f8a94fd55bdd7b85d2de6c3064c7178fd724aff828c +47910597526839f59cf9313fc237ab0e0949ab3d102a66791c44cd5951ad0931 +c3057249a55faad0b6e8836f775fc0689b51418ee1fd995f7b79b5f1106f34a3 +bb32f7f9d439ad0c780a5c7ac8a63ba5b17a45b1cc483f4af5cd5c493513caa7 +2448f5228ba7354fab7c5cad235b71274bcd65080150c175d03d669ec3ab0dd2 +799db6dee8c0672a66cc82729ae86557b3f794d7577e347f9ed9f922309f3cbb +0b19d00bfd68b430e49148cd12d317d06debf8229374cdca3e56d1acb3d4b5d8 +6ae03bacc3afcf96b52191a2f5e4b13554e5bd661f2878b76d1b171de7cbfbc7 +e99e669586361b35252a2cccb7f27206c98eb609e4e6fed1c4fa51ac0d7b2815 +14bb5233332e6b2f95e7fdaaeb1bc291640c18f6c90b7bcf805748efa4f888e7 +24cb015baa965e8106403f1fe6744f5311337773e912581f66e8b27cec49615b +34fd833d810ebf140524aeee4772e41293bfb778e1da87a87fb2ce2165c915dc +277d3bd8c390145ccb630332d4ca1d6f073c5059a3ae66d531ebe1602d6be186 +6b2d49dcee6acc7932893ec4339fa0a1345dea85fcd7bff3c3e676d022004fcf +204001db4a46c13d2e5e1c938900dcbdf9227f42f0f6ada292449c225e06048a +5a4bbb6e14910b1a78997c1019c1ccd50c685226983f7527c40ff5f77a9acea4 +94422a6659efc9dcb389e5f1e7338b320786ba74ea00a3340e7d7ad0c18ef475 +ddd72581836d20d62c6cdd30b2b449cbee906ab37b6687a2239afb4a7fbbc09e +ba2de9622eff3c96a04120681210592336b4f4ce228c0003fd5713ce834c43e3 +ed283a927d423c62ef420021b61eb3095094a87e957dc49fc0136531f87d9916 +14130e6d918e9ec3c97359255711b743a8dafb150765429e47ec782bace49331 +99e7a85bb5bc82e46b7c8f51f4b6cd3d806e2bc598b1352fec0bccbe8edd2594 +2735d6229073cec47f76f0e5fa0da9beba52dfc70d96ed87350b171f9bc18ab0 +7d8f374bea9ded8f0533d2e94ba6a1bf58d321f7759a7400ec7d785dd4fc94dc +4b02091a145264c2c51a04ca32ffa2d3e0e46b505da3c57ef85dc7b207c2e93a +39af3921ae0f8df9f10589ed42a4c13b058f177749a3c03db7841243cacd5554 +2c46676213e931e3a541bd8d2a72525faeb6ff96b743c9e4060b050cd32a22c1 +330db734025efd6b33e285f4a23ca3053283010696956ae5428ed8fef8bc4e7d +574800c7e54a231ef9f07dbd2428ffb5b5bec82dbb541e9ad816385ff46853c2 +55908d0539c6c4b21e5ae78b395645aba3d7c89028b0f370a4df028514847647 +f585288c7332d152b487611378375ae520d1503a2e9542da763d0f2ae53a4aa9 +43e6373956aba78fff98390bf68034791ad58d7d1b9f3bb34856bb1c508e5bc2 +fa5abd423cf5943662b6c74e3413645433aa7df8b7c5d22ef5a4a2bf73f3d171 +a4ffa706b529ff41d0c299cb60a716058aef137d8ee578defc4dac22e5556fc1 +b81db2b9a2c75756461f8eb72830416b68109264f1c67dc28a220b57eb37e5d2 +782d6f5d35c8e45e52fb53eeaef933d9443174c41e47522ef72d3346770581c8 +6486c55bb15a6005161a47ad82d311bce127d4fe4ad976b239995675a04af910 +32396cd0c342fd51d5a1022dc0fdafd55f427b90c0b2ab29f4daacb4dd059a56 +666c2190f4b3709afa100aa0a7de755a4391e47c546095c80b63de7d303420df +6d2671d71345fff46c485daaf7636ee2b15c019e27dd9a19dc7da7e3aa585d49 +a2225308024814866655ecbbc88ffbe1b829f7ac74da6c922da5ac97b66c815d +378f2f2b374f82916cce652ee6dbf244f94388d35472fa12816e753b5f884679 +51e014d192e2a26e052e43d4a6982ff3cb7a85b8233e82bc6bc4a3ae29fa6189 +da4ae206f9d83c20a4f276f0e5a229631111e5ac9de23213c6d5c42a34326aab +8b9f1d5aa00080ff0c40d57b0e4fe76125f7c5e888e005c85989b6f82d1da44f +c756450a7d0fdd398cd64fbb3f31122103548fc69082f42ee11225c3c0556fa7 +e1d2ed7de277c5b707dd8d4a64e87bcd9a8c2a4855ed9df6fe6c456f713ae637 +87b7779dc109d501f4c7dc0907cb51ba8fe0dc6daddf45165eb9d5908675c7bc +72803e3d9b92dba16c1d3d5f3a5389f74409280d042cd1eab279f2cf88ed2820 +c6ddda8a97d620266dab13039b798c5942b7a166d2b193a1736336ae5de868ae +99dc922a322a48e1cd43bdd48a83489a82046685a8f3b2bef368efacafe66058 +0ef2990f299b84bac976aa256f2b8fef7dc4d949259de5bea6419133712332bb +692901bced530d81dfb7da98cd4d9965b8cc97c249a52364e32cc84fce84cd20 +bd39e2ed6469f058be753ccf09e925d616aa88e6dc5dd56a04e1c8a10d5cb5e5 +bbd0ef0d2466fa1aa00acc6f5f37da9d6c3a84b56bce200232b51a62e865e3d6 +6906a20a44324a29cc340ff54cdab96747eab64f7ec668cef33c2e95cc526ed7 +f900b7beb3e31f084c257d0de9a74f696e5134e3c155a48403a97c21e6dc6c34 +913f836f08299f9477fcb351f671c596984f27a33b950b40ea6523a622cb53c6 +a402f9fba9c84db0a5fd80e550ea85bb89429ac0ce77eb685c09f8d2cbf9b708 +d4fe8e6fa0575b3fa1c371493ff2d23f9a42c4cc0d1b69eb3f3e345fdc70b11c +88faa6d7b7e04ea059518e5b05fff0fe0c067419bcb23d125023799e8b270892 +77a9f08d33bafea135a773a5a24ff93eddbd7aa8d766af90a15abfbb3d84c1b3 +c475bccb235bd2f913bd4ea6402121e5fb7864cde421af29edd309a31f3237c3 +9f907b78e544c13f93436799a8b9e4711ff4d261166fcdaaad411de49b692f76 +8e140ef851a39d2a2f9a785403a226886ca98b85308cf3f74ee3b05a63d4f96c +0dfab95292c29a862bb3ba9613881a7dd14d035b074ed565615f86a2892bb496 +0b6cc5d25a21fcb15de4cbb1dc45b5e6ca896ddb98b69ec42e6c6ad37d9c269c +1a472f411cdd56fa8192df9b0ce0246cd0678e9160a488853f1a5631be94dbab +5552e14826507752840d4da62c089f0baea99d996773ff4b362ebae2f11a35c6 +7593a1aa3ced4c64e7d3c76ecf39c7e953e20885a69c75431af78d2b63e67c1e +08902a8582094078acd838722cad6d88f99ad12bdec7fd5d2de2556274860307 +af8bbd254d7fcb78824556721827eb44926b67ce88ddf57ad239512c1ae21cd3 +4e2a221f59f8289b0d9e947f0295c435052b42c30ece12e744f57b4b730fcbd5 +b07e8eb5a47b9c4caf22f837844803abc66d0c8d87f566548f4f08e42e5e14bd +07a79c642c81273915952da1f8ab85d1fd0f92847d755f311cdc972f679ce293 +45cb9851e417f03fd24118a0ef43ba408622cd94b5c96926a2180bb964fe76d0 +0251aece5fb921335bd7d32f616b403ffbd53f43552e5966f726e385c3fab1ac +2b4583735665cef2a55fe898c50df1bcf259d249d37c80e1cd61ee822dada5ea +b16b1d883a54b22c535e004eb8001a96ceef978a35418b6d9d6c7e7d9c20d8be +cde80a5ec0d2c0867b610ee3563a52d78d261f4418b155eb44a7b740aa97f768 +e29c329013f094eb7e3fa74e9820c323991b16ad0da873ca29b6d4ff10a4a125 +ab4cd76bfab2fa378f1cbcb3b20d3075ad862cded28fab1d5c60cc04dbc6e84f +6e94d49573d4d8aa82e1e3e28afe84e301da62375fca5d0f81af28c5a1f66c1d +2fd13a0843d70229c9e927ca0ab3a2117eef88431b794baa0a2878b3aca9167e +c0aedb650c677af0708cc0a0c0b8fd10b222d6d97a1b917fd8c380bd0257fb3c +d68cf314e984f7650165d2e2d42a8096b92a3ea4f08c5c396645cc318c831fbd +f65d90280630eaaaf1804c652540515c2ee95a911ddc5f6a48adbde1b5f609b5 +458d6c804a8818677e490627572b856209294bc37971a4cc68c81ac2a2fb28cb +078e149b11a5ab435f6198aa4a8a3f863d2155fc727013518dd8b1dfbc5728e1 +53b7b5f319d33f9c0b243ae6139ea4a7946eaa373c16532ab124b7886548a69e +084c8a37e69c0b11d9f2e4226313b9b706cace7afc1b4430a9d71143f2bc49a8 +44b2d7ca26b22ba7111fe3e92665cb53c3df01ee233da4fd6b92869f7e7c50a0 +9102fba004d1845baa478dba436937562be1440e1bf762bedae787cdc26b4830 +fef67b8b51f96dcc2fbd708b4e8d5f441f62052ebb5643d7b664849b0a4d7fc6 +774f8da74b43df8b084f0fc27cc4f0080811a7f47a93a4da9ffb8c0f3945935a +3a74193f43783dba76ab7e4a23c129609137d024b803adc05b78430e6d2e421c +ba986e67d014a9bcc9691630a3dedc18685d37680ca1193f110232fcf057dfb5 +72668f23d8ec30be16f276bb119202f136ad40015dcea75dc17d4f320ed6ec9d +37b28a4296382e49e4eddbe41f8126ec6f926c3f32619d508ee29dbc15bfc3a9 +145ba996101befdd7d861c0845e5dfa3c654091bc82e3efbc62724ea475d0e60 +e4ae7576fa444829a045ba14a8fe43d16bad056f736449186840ff36cceb3a10 +8e3fa1b59eca2f55d4a4e995049e283642a8ce2fcda4d1d5508b106d015ea22c +c6605097675432da8ed9c9e253b4736cb363ce13ce9e3a5d35f84b550eae9c4a +10fa8721516a1d5adab0cf1a066103a2fbd89e7bcdc29d11d904889bc8eabea2 +9670204c58cb87fbdf992a98866c5d3ceddc511cb0c87f9f15f29bb8494e95a3 +f95d2097e0eac6fdcbe62d024676463c7012185d7272170ea89b3f17617c78de +9f6bc90c8e567db2bcdd227852dd251cbb80d1119e4e19896232797d703bcea2 +b7858eb5f598a51c1e155ca9124b296639d484881a7e5a31461c182d9d618d10 +291c56724738cb79e25bf6a3802a744207a7042221ab4b3cc1f846a8fda116fe +d306db68e4979c7e11eae38c1cfc623333ecc9f160527c04f1c879dfe6489e0a +3497917d071ca3a611e95154f6e9efe96dd9b2023f7a7ac0e77c7be608ba13cb +bcaec1c71232933c98845e9263eff993d9d840e3a02d4d987bef06d20f001042 +0209b29962e76989f80c4df04b55135d1492978320c287352b5111a95e6e29ab +4aa8a5d51bb722efe7cf32c4f7760fedf849e8695c177fe070954e94d3b340d1 +4d584742531197b64c70cabbea602435dfb90bd0a2792c72d65ceb876966a080 +b395964d7d7dc069f43664385265f6a61558a10723e8f97757425fb8ff3fc24c +26c9b79a4e93319d77bb3db1821670c6480263d11f0b0bec4da7c4b7b26d6b78 +c858da4db33de8f4336cecd53e3395a505b0dda3580b78827c8c7a2b428d2192 +991c94d9ecebf07275f369254ff98c790a7315df86e074a79a5d373a7691da99 +6f36f09975ef6de834728c722f248ddfe50492ffa18f983c5888998ec10e2ef2 +3b0733b78ca9a5e51dce2a2ed0340238bebca874b8e9895df8163e8afa40afa4 +b6eb1a9b0fd1718d4d7f0fd94239d83b6f3bd1acf706c5886262fd6983ba102e +a5319aea2b526827a55c917073f54082767821ef3b672c856bec7ab9657bfd80 +90b7d1e5649d6429545e70cc96195b402745ab450268208db9f64239f041618a +7248a0dcbfcfcdee78df8ceed783fd172eb0dc5af2a1b39bd9618fe8b21de3a3 +014533589c6c39b42df79ff1096790df51a5d923619a4f547e5f32b81b2c5005 +565dcae7fdebbadbf8cedbef5c7885029d34544b996b27665909673b95ac678f +07d80e899406fb39fca48fe2df3d05fa4f80c2ffd9dba622a976d0de2d464942 +6d40b2a0bd911aa1c1e85d48e3245e66768dc7d4092279167dd7eaa9b07675e1 +806bbc6f4d6957fc3518a44a83583b22b74ea1bc70dbd69b6c01031d2e5fe6f4 +8b5ce0131c9d2071dec4f88aa0f611cdc538abc4ef29d3af8d71364458001c88 +c25be335edc66705bbe246f05a22463e1145571f3ac6ca321526cc083c5bea41 +b4e019e606582684858220471631fb6fa39fa42cdeb118fc26db6d50ee2de9ce +213b2dd54d33b082494c443c9116c92238cb07e241aba9d18e92ca3947dc1add +f1a8b70a5c09e72cd553d3720ef326c71fb45ff2ddd7f3e5815ef05d1554fcb8 +30e89e8e27baa07e51c6415dd109885a761eb4528dcdcf58dd1dcb7862ddd97a +b52d58fae5d4defa02e0a183d70a6d1189e7a7874cdec91563ea6265455159ab +ef2f1b204c156d289e613100d5721942cc1f03ce05e07d04607abaa9793cfcf5 +e856ad2a590c9255e4598702215a31edd65b66668d87be6116b7686dc42d7c20 +7e9ca22262a557e547eb23895676eb233b048fa04053fbcf32554605258b5a49 +ab64666d96056f28398815302a160018f6acfc15a5363f64c20177baba7ec82b +2de60567e9e7fb67cf761904d3f4f12fc3582d9c9ec23f9b72b0403aa4de3ee4 +7e22fca3e567cd6af49affef6069996ac084d363deb95e5fbd273a163d2d1228 +37e45c59ccc242ec3ae8650396a1bae6c086153cc49fd86ba7549500591becf3 +2f56b3571c612efc1c55247657c0dbaa60842c3a3fb67aef29bcfadbecd14fe8 +ca1c86c9f9756d66e0df8a3235692992aee405717d90cef833bc0c7bed7aecee +037191ff16ecd741abe0c44c3fd73e36fd1194cd20fbbe867ad2ca039ad434eb +39de0f50b4de63ecf8d635ab312fcef48142ef6839dcf84cb2bda76dbe69fb15 +c2375303e542bfbc8c04f47a237c214d12c0d6dd8746989fd66c0f2334c98dce +ec5b7e3ef8087e5c3a661eb1a32a8e86d6de99a24108c6aeec63c255bf1d3e90 +6f5b88eb3390a0d6fbfe5e60e0d8679a59dcebcb0df80c8b78737c49dd588ead +dab9d817b5416415b47652257c7d1f98d18957f87747fbd093b2820ab14a8dd4 +875418fc3bc1bd7cb751c7314b877ce803ea41e2daf74fe137d17c08e9a3bf1e +cc2070bccea63b479e1d3dd9c5f08ee728d3112262deceff42eaaa4b55da32ba +841a51a1adf146c040b9c566f0f733e4f6dc118ce20e370d53e1ae67f1839b85 +93feef4a7d23c991c22fd1f41386a46a4d57646a8a4d6621565245f578a9a6ee +b33e92a66ba4d34eed55f19324228af6f411824a029ee884fbe00e92a34b54bf +ad46e5e486b6ed4d2520daaa6ddd8fae72b4214893bb6b691d9b67e96cfe39d6 +8154c75c956a25ca428a706f241f08bb4e0e935bf2160033c3396abb91aaa24b +35564cf3434a01f574719caf3fd3fe02de62e561da2949bb6cd34a0211d03c8a +e705f9af97e68b5732747c30fe93d0ced1c5987b6ab41da740b235aebe21bccf +de1076d22ec110e77d59543ff037db0ed5880cf5bb8598f37d467b574bb51329 +94eec174f18a4e95ed39167e128f1a5e527fb4987ce8050fc485d1e7a59f7551 +3fce7694ba99aa08ed55bd83667efdc2245666e45580986d05f5bc7062bca256 +997ffe766b6243116c0e8f7ce3198c32cc82754695d2df64dc8a3496f45d01da +3813feb3db0ea6d580c82fbd130dca79b7ce2b1ef2c266e1beb1fa6fac58cd44 +cbce5b4cdf383003fafadf5ef450e8983fb8c7893315c278c69fb2f210803e46 +0dcf0b3f72d24e6de5bc65f9e5d336ae7b2fa01163f50ca6c521ba0ca330a812 +78f7f5304a9c81a63c971f4dec9decd6188b6745da72bccc97d226d1cac9675e +7dadcff4d5e9a8f6198a4fcf3f91259e492977affdd410b474b3ecc874cd46da +8af1ee630ecaf7e8b125cc8908856f79cd3a49d2212e88622889cfcb5a7f0027 +01b34b2a17d91eb58f68bbed2f8310365e3db63c451f78548300cc6586e626c3 +4b24192f1074566cbfbc9d18eb9ab8bb23991d07ceea8ea45f6739358d8d2762 +48cd1407f194bbd02a7c820596e9c2cdf19b9bc0e704263aa223581dcdfd64b3 +faa638df011ca2ea2442e3b0de5946f6955f95943826f0231b35d72a94ab6807 +f75e4957b635e13b43c942fbf4dc8ae3e484745fad2bc4022c69fe441d22a384 +d1899224262b6f29ae52026c9362e1de82f091486c8e289ff539e1c62fb85729 +c3110a138dc996cc34493f820ddef7a6aa8bb89b1aa44d2a337bc1d6ab46e711 +43bb602f3565af19cc5a16d245d57bee02c3a050f7afe716bc32b8cd2ff183d6 +c06c88988fbfb2b85c8287252b061b28686b4b970001dda7fbb702d81e9c13ca +f0ccd0060802e883cad3e3954b4f21f239a6b520bac5d20c8c4cd7484ffc945c +23678530a321e82a4e4e18270b1e47413dc86b755f7d383aa63498cab5a10ced +6487000b062fa73ecda7f67e3a839963b4a85f3fef8f4a368d5de29c015d4872 +14bdcf49974dd14b42681395baaa569db58e2ca8d6bb46733879da5946418b9f +24dd6600fc9d5ac7d462b3689aaa5f9b4ab8c25c85745312a43aaddaa9ffbde4 +c2a83da8b689255568f739f794ecef5f22734b64e5f4d453c3b31593a0d4e112 +2c449df261805154c376f78933f74f10f865612e83af51e7be607b1b2f2251e5 +03f7237e48344cf10303cfb25e2cb443a532216a2fe362881956ad860c47a452 +39820d27e9bc085b1fb5d55e41bf1a2f7b5efcb78280c9677d92eafca20cacec +1e02e733af30ba024f46ecdb2d060be3dd03c5c06a79b7593ad653c0692fae8f +5b5d11dcbfcbab8834e685bf39cbca5bdc1a69e7abb604ff7f189308c306eaeb +c77953df1b2ee4bef5c09443bf30021144f0b259937f061aeed230b382fb2c02 +c197ea93e18a0133304376926873a5699a7f3d890274dbc71acd5782419e7704 +7fb2a59fedfb27ba959b152719790282096ae63928a5cab1e2dd09ca9ec6d510 +55207dde0b49788e431476ce83f52e9ff913fc1bbe4735d1570ef0741e7c0789 +3a2b2d33386f931eab21b61042b34cfb32cb51b9dc64e90465ab28a50c74ffab +8963dd26dc20a7b3c0bec11e79ce982dcdfe15bcbcb9e204ee24d815b1a39666 +441d0b83897d84a8b3492c7a50773278a94a4e5175e669622ed49a9619f368ac +b7ef0f841f29d0a0bde1923b3c70c5014af46c2ed0087284329ccc60627a3814 +5393bc0a594aa8ce3bdbd7fe38df5e9ce89c1bc51debddbbaadf9d3b66e4011d +fe0dbb682d804366bf48cd36d9df7cf95060389c048294185d8eede8a231b167 +5633b0261de99086129fe626bee8e0b6ac6087e4098bf7bab0083c4b1da8fb5f +725d89ced1d54a52e5edb2c67b658ae999aa1db6801bf63e58c054bcb9b979b0 +44be3770f491622f30cb77681019106323a7ccfca47c8b833c9c229bcfed2878 +17ac07bb85318e014897e365dd2bff8dc2c30f72ff9a65f5435d97b440902f83 +0b07314f2d6f8fd3e527e7d70a5a4b6d2f08f4f3bac3911d48d490b56b7f9346 +0e357d2dfce2cc5b82af7a281e1b9c2639efa67bec4cdb56fe17da792b922fed +a119223fef41b33aa38adc6da423ea43182961ea8fc0b67b13493405efecf560 +c3139d6f4bb110a3d4c7e2719977ed80d39ce0f43cf43c65ec278e4be77c2881 +137e14665c04dbbebd78249599a7bdb68813fbdceb3c7a94c064a4728d055f8b +3d2841f3214896b5ab023b55d03d25c0e8905f4e4ef9a9cfb690e4ff0767cbb1 +81547cc0a48a5956710ca8b55f4e02632a5e20c07ae7678e25d1baaf5d433bdf +25e06f198238fad24184ef49aa9c4d963f1d85c874055f3bc9b9d4f834adb495 +472d98b443cc1a806342fd4a27073b5f3b8924544a643aa0e50bf591403a72f2 +9539407177fa2ba681b8ed6d39edf7b7960c733746c7ca8c51b9f5f78f5514dc +b677176b71729d8507fa775c981cea01664f0767e342d63de3936c6c09be4b1b +fde6522b07c5ecb9ab9c872479be2807b25fd9d66a6a180a316d8538339e4cc5 +5991a4f3f24e46f2550d17984caa6692d137b93c2abd4efb06db6334f41e246d +75801017ac071bb813fd2a13b0fb4165f06a241106a1e2ce1ef6d71d8f7c2a97 +ff01823f0d1dba051fb3e9b673492617ba48ed7e95446b2a74249c65d1396bea +d7fb99a983cf351a3d0fdcd835fdefd78d0de39797b674f9ca23f3ccdce704da +cc4ea6ff4cfad17690a915ebf6d2c770a0d40f1c618df8dcb36d369154492b72 +c7b9f409e757985a5e53ab6c233a73cafcae253ebeedeb06070f5e00957d2fe4 +ebd4c201338d741e12a30fef6864ccf1dd7d9a2fe1dc989eb8c689180967d035 +4b261603701b901839c794893480cd1e5fd8a60f4b63ccad923ee84ed0d7b57a +1abfa2f0056c50a9e0f03d8e0c43bf3682579cbe7d084fdf46504e1a8a7ef8fb +0f37ba52cb40e0e3cf1a725ca5de2313b113d3f54b4945aa2d37bfadf5361289 +2852b9239bf8d9594a07e45dac5f112a16c904b74745b83208154be26a92500c +a61dc77d628d4773ca16d4fa29ec536ef0b8df25a6815a6f910edeae012b8362 +ef8b5129fc9c198b345581947468c78393148c4be35e5e1c37f4088db48c1d8d +766d0f3b2ac21961d572194de6c3897ed5acfdc0382ac8f6fd696911f636d457 +c800fc11be2e1a7b386b4f6ca8cd5c2f24d17df5ffb348c358043f20ebf13ade +8320c681f789737c01b6cc1c84680eb33b23efef3301e9b1ad4ed1ab9e87e620 +d77a45f83a7948a6bb5c1c2bea25a83495ff1b0d97d5f90d84d2fc6f5a63a7a6 +1a35277a91efc5f9f6b3e53843b954b44157e514217e47283900284a87d8413e +6bfb7e86850cc80bd0e861747d291853a3f735661e4f08c65247c7c884bad225 +93a67ddb4fb179080c91b217973eb57048a985e6a9608da729edf2d7ccbfb76a +418fafec995fc01614000e782b6008c9548a01065e8054463b8c9a1917190f33 +d864e1d6c3c3aa3c09b25a4a41aa55f32898b50bd3fef5492a8f40756e2d53b1 +196342d58798a48f6c0f147a963509e9eb75650073c358de6f448bfce33ced7a +2bb9f3ccda14f4a9b9bb507c9fbf0bf1c1d57199ad46bff0e5000c0896acb0b8 +00162e63e32c136010118c7051f0529869a696a5ee28a6bd38841cc6c3f6128d +dfe8556c57dadb9bdb4d9b9edfeb0b269fa4ff0a3ec1572c1f374ea911e20be6 +696c464e5e2617c7913e8b910e722414b285ed96319420fc6d1fad3b04bc808d +16730b2eaf53a51b50b83e140f1b0703311da867d593fdaf857b1d18302ba9de +3f765230ca02519b04a56a01c03326365d22cf8037fa540b6f514bf12361f5d9 +03706642a162dda6ae610280bb7e0597ef825a76e7eab346a3af84a7edafe24c +0b64517d401bc26a81015f6340de9ebc5a0c356c36101a9b8a2abacd48ab83f2 +cc62684761a24476528b438074df1894cd26789c276e2336c9b9b739862f625e +57ba0606b33e63ad2164c8156b8fe3bc02e8ebeb61902e31bf8f9d4533cf167a +c9fe4a1e2e9159abc35ff38090ea3087f41d453827ec78d92d2330c4c945130e +7128676f56d5d91270f37ae4305f94190110a17400aa7d7d1c84dc7ec6421ba5 +aae3811a1acbf4a62a01deb6d729ec9c55559019c10c36d31ccdda0f2b93d5e7 +241f88dd6c33eda84388f6d539c98fc585523e592087bb4e574f2d74d940bef5 +ef0d4334a7440415ef44628544b6bc126a2015563891bef491adab2d8e4a63a2 +1fe93b1a7e731ee4b7d9b5f570de0620b97e3a0b36296da019a7c8e985014748 +d03f21759bf423bc83fe9bf8fca6ebfbc6954dbf16a5efe6b14a116124ad5dfd +3a4b948eb7f10a346ad70204f991439c6442e2349e417071da1bbbc0b966d3e9 +c5803e6eb08206b0f21c89e09cf4000db5ceda56594c943557f22d57a9725a5a +476a054f7a219a18e7fd62da0cfc53b7b8874c3a252f895e97eed04d5ba26585 +2d54d7b6cbf1c4b2c4dbb506b3025fc94bf0ee43c2c889456d5c8aa105075a30 +6be2c42fc992441286db6cd9e808788f2d8c03f0882dade1a19e97c0adcaa3dd +c8fb3cbf3b98bf46c486f4e1ff6ccf15cd04dfb5436375d75915764be9b8444d +f40781e36df7265b69f3d3e298f199f7a34e68a79929b7c1c20e83993c1a27c4 +80ded0d7373ead401c57ff67bb30e83b382adf6be243e58b1d0b1227bf93b292 +f3d7e4fbd4c7dc8bdd103562131b2e907c4f9e335c37c532e549229d8ffc9f4b +9735ad4e376ff07714d083bcac0659f7e8d3987f6c32888bc92bd94129442fb5 +0c9157c4a1070dc1d612a1c2045fdb984d768930918e4362a6ccf4c3167ae5a9 +ab0a925e827aa06f8bd7b1270fb7c2971c28cdcdb9c3c24468d22e80efa8c87d +8b061e93fb76faec80e879e0eca9f611a3b7e82eaec430bb019ba625f8513eb3 +5e3b9510ad70e82ca186e2927bf22a7fe0c3f9bca400aabec0fff49d4e0f477a +7dfb5e5378ebc48b81d783f531a312858e01dc7fee271e351777d052e557afe5 +9e17225e153dc589fdf0bc033b451304c08d9bc58b80b72ed6b28928f54700c5 +ff3c49ce70ce5513f29a3ed907251480d3f06d1f99e8b41fe5caefcb11b878f8 +77f8fd78c85764e49ddac4f44088792d5a3b522dc51ea27fb66e33b20371b9a0 +e7a122d915d382fe86cefe0d305015004f4ed4feb3bcb8b7bf49d1106b6ac266 +55855382d710616eeb5ee4099c360dddbaf2acf3be365a797c5cf6b2bd13c134 +a52ab1a3da661a2dba6f60bdca624b5051d1dacc2d65a6e29d6318fede214615 +858095e9ce16aadda399b9b1cfc8e1585e9320477275270b8602369fdf0a97da +1eee670a3a8e02b1d891d19a4f111c38d823a6863037338c62ab7ca1806e42ef +4d04237c37b219398a6e29c2d1ab9d2e86d1e4473bf83ffb4838ce928017ea63 +ff89f16c2b4e8f8e66a9a57014d41cc77c14559ee921a456928f8e9c50848fd5 +4116068ce74bc8edd0fc7767e826fcd82309399e15a324b20ac37a980ef7dbab +df7e4fd8ecc9885af152d694344cf09849602945ff20bf9cd16afe80f9b32933 +7da14addaa509483fa4694cb15d1b2d4c83fd4ed2e468fb19516f3837dfe6484 +7da72e2b14349ab133fd9c24eb7bc14fc3c0fe7bbf3bf8da1a57df3116795b25 +ce5948e2e83d717a49ada72dcaf420a4cee926d569d7e07229892e6a9862b009 +eb31ac90cd99a854cab3612d2c18f057fd70f05bb90408a2a62d0c2391c1e3c0 +3da4bf3e93f3e531c7d997a87c156b9b2d6d31b2fe1d3908e4bc800ec24b0283 +83dfab5b1aeb48541550839ffe6165235f5601246551da1f64338dd91414f6c1 +d24c5950b90801b58405c2469362c7c5120b89faf703e48f7898162a02fb29d7 +a20e75e5f3c5ed1adb04b6127a69d18d70936917c01d3318992b39956d0977b1 +532e2fe43b35ee11879d55d8d89c0351e21d47ae93f6ecd71321f6cf0cd7a74f +22d9a203c94d2cb0eec9553134d9cbde34e55690a1b274fc2433c9f083a13472 +e13f2f492e10c5e0bcf552b32901b7af4d6412b6d413c11067045fbc7757207b +0c3b737a840f18c20c6b8b74a66c0180a18d8b065c036552bde2c3c7bfa713d9 +a2ba8aad7557cac3d0bd2ba332e9181bc270ff1b1820d0cd156b668c0908003b +c36e3e7550658f59ec079a817f0988c1c1b96d528e8d58bfad9c99f1d44020ec +aad482ac8b2383fb9a92fd2fc0680dce9cc7db90de3caabb6e2c652222d767a9 +73662da9ff4b9bb1d979966d03f06c23fbe2c7ac15b8f742dceb78a651fdf470 +b41fddce5cfedd1677c8d01c187940d9af7dd5cdda5fb7523bb667735ecc9207 +46473c4c10a3a51c69f2e958b6a832c107ec0ff63e9194cdcf255034bf4d09d1 +19f364179f6ad8106f6ed68907729ca9a01196812bdbec90e78d5113d09f221f +89fc417e4f06842044c6ce9ac9ecbd85a0616757c28678a0a3c7f3624dcbe674 +5a8550f7557906c9aa6c90977b735d32bd77f25f9714de9595aea6a815a3e06e +f4fc046d55719d8cf993f60928231d4fb0aa1f9b80c0939b19aa931db23f17d4 +9d360cb9070108fb91c6573b117f68fdfc4285890ebb32b222171a65da5157df +7a6fdf3d296d0e13a86aec0a7a99b6cb8a3abbfbae7eb299c1cbf73160d7c213 +372f3455b416728e9173cbdbf7e6f8d4f5e185c94df556237fbe4cc389eceb54 +c21e71c1c82443a27bf7fc66e5c84b5963845d5560966a3c5dfb739b0506ec5b +f4733b72376556c6af37425ac0108d7b190fb26494473f8f720ebf66eb9c5417 +826a3041b1e7d57e980abcc79e870e1e49e7c1caa56b0a12ecbaaa34e1aa369c +968fd9e4b0314bbf86a08497dbf5e8cac4a47f41ae54729652a4ee3b12d85d51 +5324f8d4016967ee2ab1f934f41b22d97e5dd0a33f8448d62107cff14eab6892 +fae61f6faa3ded688b9b60f5756032d22bd9c57a383ed585ea9a263f4aa001a5 +8f88da41f506511f633ccc8a3766a7a687777a39d3d71e4329cce1ae07cd2dd1 +da96cb02f5b63e9ac0ed47a8beb46d0e0a3a9b813b1ba71df9b696a500bc0a02 +c66e1c2af94bd336ca10026f927dd78e0f148f72512158293253559178943fb5 +0923339332a9945d6a67a82dafb389d6fa49b04a8b8482b69f143ddfd7f2cfed +c64e0b6e173773cb2761d5024b3e3a7c9c9c4a39fc94d23b370f09332af958cb +f0e14676eaf816964e2fec497ea48307a9b8a47db797808d9e92377b346b30b2 +f5b8fbb311db72500b58b0d18062cc793ef5287c6217f185bd93c188426e8c1c +6bc52ce0f19998ae4fc3f2aa0b4ee7cf0c26443688d2bb27f825e46d558d61f1 +d24756e15728331419710fe16e0a8624ec0d03afe089c68d66b86c8cd9b1a7b0 +86d80adc06cab95034bc5e96f7250a7d59a2e4188b8ff8b39703fe1b7f262782 +d17034e308605eefcbe85aa6943aee75239d0a2af8c3a8f6fd7167f564db12ab +b9636b99e1349707eee6999afe3e6c6c4f9b4e4de1f6ccec259c7e3872174f89 +3efbeca7fac60593529125d4b014a9026cd55c450e026d6e813806c3a4cb65d3 +63c27d5e9a0007e8e1a9d1079ad9e6c194d8af82f16f3adab54806c1dac68356 +83fe6ebfb78d933ec30caa76347b8d733104649d943866b2efee4394020bf2a7 +ba05248c9b278280aeea776c3a8f674173e08390de4f587d286f529f20bb2a40 +593fd4aa33686ab100c3871ea9c0b6330f0a5e9b85db517b91b0c9eecd3885d1 +b054ebe900a0ef912106c68e5a36809501e5559f7a236da41693c00b17441ac2 +203ef5f518da5b69c78a064cf4c761f9ffaae1bac25718ec5165ed3ce5d9030f +74ade38604181475068d15f9a90e7ab08a930252cb600dd4add187b04810f80d +4400ded0db3b9eaf91254874f1f2d97a67081f36d21e8a8f162956556dd3eadf +451c2bc0c435fe2efd9649515c3bbc655d0a466d91e89390d02829e873357b97 +e7ef453498d586de919f9f6543633d282285d14fd243aeb76a6db11a196ddda4 +6e2fdd0f5980d7b84c1aeddf00f9d0ecf038588e26145d0fa74f18be798bfe63 +bcd800875be789718a23622e2d546e77dbef857869c9fcc41c537922cbcba96c +b4e8f741b1ab5837ac45dac68bbcc12f4291142617109e996992003d209271d2 +dd1184bbe9f210566faa12f62d8865ca4354f74f9322a5b7b3482a1b54680755 +e4f774fa24e181df6edad531be38877a60f68db94865b117bc1eab1876e4b89c +3f3db9c512989e70c9399d5bdeb80ceae0b034189c3faa53ae71bf943bd1f52e +1e76369eb77b6a3ff1ed3dbf2b1e3c4553cd1f4acc2dcb377f2f047d9885de6a +c499eab7160fc0d7302b0b90d00568fec3f4fea660e68d16b848942fce22a937 +00ee9609914128dcceebb9601ebc2dc8498d24b3eb93a960d6854da5b6601278 +9c9d8542caa1b8e6e283c8a51f1d736d919d1c5013f87326f4f06c7e085bcfbc +ecbebc43a1e0a67983a9916957b337952df707de1fac1144c40e2fd51dd57a1b +b9360180c4c3950439e5357d82ff2072720a6878e8e8733ed7b537c5733a5469 +3b18fe88f0ae10919c5c4e539835e272558733fc58c6aeaf7c9d26c544cd964a +53a0afe689a0ee40405c5962913adcdd3fe36f1ce608ec8c2ca86667a2734c34 +45e7a0e4400479a8c64ebd58cc550f38504a45ee8b443385d1f434faecd3ce99 +1f6704b83edd7b1ceae54a2c6e9ddbb7fa9ae3797e3a9b4132c7b136eec9cbff +4f7d5988d1b87698e8cf35654bd4ec772485e3f81cb33d745c4b0e5aff00df17 +083d49305205ca3c11df28ae29158f5cc6d0fdf0bf2953e7559c7c88d3104cf7 +61760eccfd97ffea10eb72517e03b3de2e9d0f752d66c423c4cfe7a4a6bbd565 +63ce56e05c7ab7141c39fda77ef85209ae258ecb37284de69a8c762913f20007 +d6b97dec7b6cd8cb083856b8de868234a5cbcb9cea80c42d52e0ff4202d16d8b +8dbb44c3de46428ede377bd53171ae21eb64a8c1aa80bcf59a0da23203fcf448 +c4c1192c2eedb282e09e8c8dc09fff5a40a5258ac415caa36d93f1b72cd96900 +c9b86e2eb70ad26a83c75d0e940fbd7783e80a5eff317554893362b5c95e66e4 +ecdd488cd818a83ceca3be0e954a7f86f10458728801e2cc8a9d407636beda43 +7f0e7d4847e491fceae350f35d0bcf89ba0e7d545c2a9ee2bbc99dc3c8dbf9b0 +a084d55bf3a96649fb6a16314e67430b69c60092f00cfc75e393ede69962f6ce +4a428e63773f38449b47c974dac7447c4e868e26cb15eefa02f204ae8495838e +d6fd0c146ae6d0692b50fed3014c7e5e37d2b1c1dcfb46eca6b6943223e7ffc3 +df110993bcd1a43bca72c8e41a7c1193ec82064da5cd018fe742d4e7a1b8b8f2 +332e55bd50dc8cb3cbbaec384d2e5f9a31771eb7b3c6f9e125ac11f84f0ae93a +74a2fc4ce192dda56e77cf999dc4f91c5fea94fdf0b521089669477dc219104f +73841f154f8685d0ede9288e528110562a43fd5fa2540cf9d7d290fe57164bc5 +2749dc8e7cb4c3bb1605714b3eb28fec94870e3061a9b5c00e7413b5fa0aff15 +917ac947f88ba0d7788c0bc70fd3b32a4921b822df3ecc79309badac5720b3ec +75d2c1eb94d422e67e7491cec125e00b06a0be47fae975bb8491c7d9df886c29 +b13cfb2a249da84025055ec10301ef893ce1faa6f49975a1fb20c56c7e8de086 +49de0e6f6510110c5e7ce39176683b1960b37339d1d8b37f2d605d9f2e587d04 +d1b16439952ead9ef56d84e1462146b96c5e1b648cc966a5902e48f91e520706 +f0b472d6e253c4bec560e5de92f42b29b0c29e0aa25842ea43bea4dc7c79708e +690c33e4e8d30755022f40b8a2d99984897596a31c4f0b95cfb742e41f0862cf +ba245497d6ecf7476a9b583db6e233b923d195d88c2ed6bb0aaaa99ad5f71851 +32326df6444e75517b96424503e2e99fdd16d8ba6a970832abced1828dce02e7 +5da65f28b4a9c4b0fb949a588fbec1d8cef39f23bf8b61b94f2726f58cb40487 +9d310e6b079b369ca94cd1f970069aecedd21e36249c69581b63cfa472de41cd +c954284696278219290fc8627b8f9c937c36bdeb3a8409105c26685e5edfade1 +2b402b7daafb9d431240280b0ed1f8e8aada88ad200975c22ccc16220f517666 +1e2fea46f7e60a8825985d41751477131d7a5991a2ad0c2e7e5f750e83c923d7 +c7a1c42449f2335685d9cd3e59d7761c60798e263c24792f958fb1aad9727691 +8e880fc1b090134530d686240381f7b2cd3e9106341a9d862c878771c8530048 +8889011e9b3aae67190de05286f59c9f1da533823f7437c0a66889ea6e8aedcd +77533ca527f5799559bd37f8d9e9f78a7e5a6be3cc056d82a46512cc3fb78f58 +5c69307652b45d616df6f32f48538d473a33fd8846c5b6eb456bbe45c1311d75 +94daa3a751a29a9646f0fdb8e2736f617828359fb05423ba42bb5549d95f4c0b +e7ec60670de406b80d3c826aa01c16cda3b6797dbbdee222ce3d53fd4c74f4a1 +9afd3e336a0199d260137e8fdfa03d6a2bbd6890379b0772676822dc84f71974 +27ddde5df607d64460074e37d6a220fd476b06d85069ab2baca29ca8d887eb1f +32dabef026a722d14a391599f85241f682b3b4903bcaafc3fbf650e8733b0598 +95c6ad12630af0d019bfc262826dbccb5a67b74aceecaf15f768a42317ae93b2 +a96b38c6f34e513f1b0144b979baad80384d239791bdec94105771c56708c192 +7537127968c5a969ac055d2dff16c5a2b577cb26e0cf2f11cddac62ec670de87 +4777ae70d9521f01d8d912cd13214e9d6e31f876c4b616ab6e3bd5b7e1ccb7a5 +6ca4feb7080ffa68ce96055b41339bfbe64eddb0626a4ed043f863d34283eb0a +53d0981f44a6bc331c2d9ddb1b74af01cd8a5f1afd19398aadbda6b254e3a603 +e2b460c6ce58b937fc8bff542dad32204a90459bee20d00792c7879f3469909e +0d74fcd184e98da2fbe9fe93bb8ffd799a8386415b3bb61cf5a805ac55d66b15 +01b12eca335d10803ab61ea66fc72101664e462ab72662bb3534c0ec10bc5b16 +51cd48e45faec6d73d46b52d1133d4b614dc35789555b2358c9de040cddc8e0d +7fedbfec032fd1e0e204b0e750a6e2665aeacb58771a662ed982bf1a770af880 +72fd5da06ae34fd25249178df00c52baa04185d263f04f02d6b0d222d4c5e26b +7758ab5e832560fd137999ec4ae6aed00f3e6a33b7a812a8340a00ae19bb7013 +2cc31702ef3e2e1e7004844923a55cda56b1640ac59cc7a9aec757d73bb700e4 +f56f9f0c1c74039d16c2c157300679c1e1bafedb016084a8978dee1fc53f8721 +47772bd1abae9fdc71392babb0d5254af6630306eb5b07fa60d0ff4b0b381e72 +b436279afcb436a531ba7f98ca8a5d7902e4fd7dc661376468f46117f57e4c16 +16237082bcd4f19ca5325f42dee8098442fe6f36ce7f269da4e21c380d3a4c6f +171a6c6d7788b909da37b4cb66f6537615b9e06bda8a0d276aa3c75f0d994c61 +4f5b4dc807d30608fe6f12bd6c7ba9ceb174c244c1a970b08b831fb5dc38e07c +73ee32d5ae8362a50e70cf1dfea6b4104c30ab189708ecd6ff2639bb127976fb +c6bf2c6b851816a2da34fc48954ad21ce91f4ba60517b7aa8b790d324c2ff78d +694a36db4f27460b3f5d3a462b68b5acf79d0ea5dcf233450149ae37415c49cf +6ca18d220e27864acb907ea2971ce67e53ae26d64743222af14690e5f8aaadb3 +aaac4a73200e2b9c4af1790553a3b36f24c45f32ecd41638d52502993763e7af +8582fa7cd7226aae9b1bbf5be24b1df2d44dddcaf6a815ff9f69fcdff3b29f0d +1224cebba370a5dc0b0bf53985ae7bac98fd743c647b6c4279e7ba7b0a636939 +52b4d24d173ab7b87b704e9a74828b7a69aa2bfce9edade4be0bf5332a741352 +522a048425249cedaef394a69f5c1d09718b90edf2c32a85bbd27c1bfc7791b4 +2a845980ccce379bc7a7ba91960949891fdb317e3871a88b123673c801fb4b2c +9a6b33c853c392553d8f4c4456518b65dc7e99a4ea18472be4fc7872972b9776 +6d8432e306574d12813bc2056a87bfb77c73ea6a9ccbd623c4756bfcc4271835 +e7bc41ff9272d09c6574d3a4e75cc7ceb97eb6943a2823d36d50e8c9694b9c40 +24a6c38de8d5e008ad69a6808d9d7e4e1c1b94c5666cf5a1d550963951d02d63 +2c04a7de5140804783a53e75e9190cf4ad761bed6232f0788d99d1ee55f49068 +2a5fa5d8bdac3d0a116fe2230e69c5b90ba3295b7d560c2ad3bea96a87fc1a9e +d3f68fe5d4bbf3d73c78355a1e017af51e33370743f6e202424423613a81c060 +e08daf6b0994928838d020e00aa9d01bad81351d15783fb881c58a21d5c7bfce +9e3177ba55132bd584681e4a5610637781c2de9a4385677e4cd7a8a51af6c091 +b1fdee405f6e8ed4223ce62a51dfce13d083a6df54c0d3b72995081987eaffbd +ac031a542f03d3dc6aebda1ad174194207802f0d58d800b1d0277a196892bdc6 +a1026709e646dde42e5490c915a2b1637f7acb1f37f08ac7e1ad640ba7a96c15 +b5d3feeee226ffeb8bd79ab9583e4e1823f9f4b244ec3bea7ed2b58f34600767 +0bb7109542f55d1bb0c0cb93326da0f1319b0af018ce04d2f01878364c68de8b +63b7f029de8b339fc4dfa32cad8a269389536d7fae8ca57cb916da95d8f4bb33 +5dfd155222e3a3dfa611bd5d5912acc19d93d1c5f9edd193089fa9f392b06191 +c2ee326e9c5c37e65e4f91ecefd4e59634465b1d8b3ecf73a6ffc82a0fac71f8 +205cdc50a1e5004d4196ef5806553a8c972e5593ff22e407a26530656fcdeef9 +401d700425604b5e3c2c2b6b45b610a406b3798c2c41a61674e1a55918f4793d +8c80f329145c60014f1467165b881c285fa5e1398da9a4c0fd51a777c31a5714 +798402af1ae06d63f3b803a979c6ca1a8dfbf4537fe620674d70fbe1e4410d1d +c08acce620eb01d8962ce2ad30bac1acbb6917c4612d4e80b2bcb668744bd1f0 +396f9a337218a7d194bd0d765e0799062309a460fdf4b216ddb0ad68da465346 +c9b48df61bd9076f93fb35b45c5016562ea3f8773de4fbd407124f05fa6070ec +e663de6a5f02b37787b7f2d1f754a7c8cef685b459617862b15150851330df33 +2210d6da7f784c750a920180fb11d1c34682f208fe868e6837b976bba84cb540 +d5d89f17912dccaaee97e8b567348be0d0dc6608df300aafbffe4e29d0d43e44 +64fc94e781b796023007141cd4e8648b0add02c970457f0ad982ff698a80d811 +e073cfa3ba6db7125f6b2b24eb312e180b09794758e338ba40cc2c114b60f862 +d45dffa383c72cc7f0c143489c5453f7f811152cb765fb30a8b49de5230fc36b +16b1707e6358f30e856221021cdfbf0865a0c5ead11ca45828fe8eeb45363b6c +7cf41a08284880f8de416a5a1003d93d755426ab0213be299be5aa539cab98d6 +5f5c03c406b5ae831f34872e315a8192432ef0bc48a5a1d1f064eeb4897d0a93 +2b72edd4639cb0902b98599f004aaadf287f743f6cb044aff228cb2e1b3a471a +06207bd139193b5196585c35c119c34da6c1eb44360b2bddfb3a885088321c19 +c4114a017daa77df610652ebdc172027e5860bdd4d787b2211577602b1704c7e +0dd71692df99c9c78ac0e470506a9b4d30a11492bc71b78c6e3b7b468e2c8b28 +524c5e260bb2bb31a02e27f30a2f29bc0773cbf5aaf3786e54c0372715eaa42f +a1b718b822de0d009d9d8aa0e45b5dcfff14e4c503aa73545a6d82b23c01e240 +a31b8b7dee871b9ea7ae8516e52dbd8cf878c330104c7ee3b525ad98052db19d +c7fb43963bb16b6e85113738291ea629c98ae4fdddd5868503624344d71553c2 +5e7326399040c9f136f8abbf1e853b535bad847465d96e235d0b26c49e231a89 +9ba2e3859d5f8889f4e2cb2d38161f4bdbf440824de741dd7111701309cbdffd +47b312a5095fbfbf986c03bef15496f2564df639ac45094b1baf86a1eb111dd1 +920ed35a04dffd0b456a1d055dce6403ba82394c9b3e2d34ec0dd9ecb343cf81 +83e1ff8c797bffdb20d727d0f2fc313461801fae5cd843f136aae5c95a6892fe +f09dd9fec7c2de536351e3a9b67f0d371552500feb2d37b3f29747a69707143e +ef62052c0efb012fd2470e1a8bbd443d504bb613ca9e90017538f397a2502294 +908c668337b532903d77272a1ef7c0df83b363c903b6a2653ce24fd9e67c82d2 +959ac88ddbf5421be23b19dfc025f12977c48621271427eae91c15f6d191a408 +e7b90f044979c2b5e6604d3dbfaaa460dc2c5799b5c58f3572621f9141ac9088 +00000706902551d709a1e72fea79e49eb34d70e94602cc2fa2ae0939a8ef47cc +7dc0419b8c5b71901124ee72686a293c62af9f424a458d28e14619494b241cc6 +5d3bbefdfcff6be295633c8ee90808078c984a310e5d2036d9742470b4012d6f +cd441ba9b27e843c2e97f0281a5519e76adcd4fd18503148d75d445bdb3573d3 +821c4e067e06bae09f1ef1fdea48c1f8682c642f0fdb4a5a0dbc3cb495807d3b +46cd22a5c2eea3f06288b40eb949530b9bb5c72426225672fe2b72d4fc4c213d +16fdb889e8ad999c09d4111785f70314a0278df3085f98653fb18fb967d6fa8f +99d26c7e31697d646b9bff7263f7f7065d8410dc058ce309bb4f3b3e380ba0b2 +714f94f683b246cbe4c5fcc9d63cf18a54d305afb505f395468bf5479460f8ae +64ad81e75e10692134a0fd9fd8eae8d67afedb8e3b7505381592687fbc72d593 +54eda94f5086bf4d8e498c33b9ce17ea8c1fb8818ec62a25d9dcd725151dae54 +0864c17f4c1db1c599c82f1a595869ba15598bb9aa0831efc25e41d2fa4d2c2b +4e6ce79395b8106e9ada4eaea7177674f2dd69d9494f492ed9ee87f9e4f08c8e +39f3909b8276fa81ff60f2829479ab2035dc07b8b54fc667bbb33fa80e0abb9a +602486d46f98b780a576f2c2703e8e99663cc91004bc1f80e34c0138c6117d41 +9cca9f6d6b692bf27691423605a6f592741061fde84082ee9df9e226ba2b283b +ff2c26c5310b50519cd41c4c28eda3a32aec1fc73391480aadaf834232aa79fc +00dd81a4f9e63c388cc6d299bad9961c0ef4fcae337e4810d0a1f9aaec0cf24a +4af6cab051e605f468aae1ef3e866b7c159eb6e4669a35d7e8c898591b72f6d1 +def8c45bb913d449f9d80362237378d3ce0c3cda82c0a4a96613e67086bf4880 +2a03d5ed6bab3f45d43dbe839d899f39c526f6f5331464f1b7d45c340d87d207 +22e5429356f14eaa9f664b7c1d6226aa3e3c42886c8c1cb0ed1c93dc909eec0a +f14214da7adf7a5e5d062765856bb5f3d759a93d54f972662356da086078a9d7 +4b073d165a49e3a0287cc8c3130806cefd311a90267d9a8e1e334d1c795462cb +b80e25951c0b06c5043f4fbb4ac2a467c75ce9fb9c88b71de2f58f44d7031510 +64ca2f71fbf7a67ab57cc83572febb3416f5c72c9a306c1e4fed1af006af7c9c +f0dadc83df3fd630f3ff3d3664a0045f4f2710ad7532052c4974d12ba8ddc070 +762ca39d567b91160c2cbccd27c42d0f417f7e1b15314b1b50a05ab828a9d29f +8c32b8459221fbf5838331db2741ffff2689fb9b812ac7381233f64627a3a889 +224d7a12e6ba029314052c91cbb0d70f91d16f95b77fc2b28ff7bcaf262ca8cf +c0e3f4c49ee6e2c9a0c4556a5f8b00c56eeef04af490d5aca632765f5cd5078d +7bef56e512151788ef48aad74b9a3ffaa2ce6493569643173d00b42a8d7f3b4b +c3b81adf393fd1a1458a7775a84f8245b34aa125df283afb14b2dff876316a24 +765b42a696dfb39492b7e8b03970507f9aaa86edc09e70da8e03f7491bcac251 +4f803afe78aefcc2ce129e133e0ec6f5322a90f1e2517acd6816be5bbbb92595 +cb6b7887ceb2626cec5b62cf1fa50901323ba325472f996fb01badf21c840ac7 +ae422e401f42b7fd70d5e8ed6d81487d8c6dbd070063e2da6181f9ab30cf541d +ebb7ef8a4af752cd02aecf84a10d412bf25135907cfae2406160011a66c76c3a +7c363ba0fca6368db1b89da3d8734dcaaf20c9b09e8e5132d9d629825ffabffb +de19b823c16a0150d7c1f13b7f1342256bb0dfaa2c28ab9f71042947689f69c3 +54ef5b6fe740d5d291f0ec1bd3289cdb4b8d64cbe60e7a2a7ce194fe1bd50099 +65b0ef12711186c7cecdbd3ea82b15113edede0c8605808f50a215c84ff18a2a +aa0b526a48b60509319cfbf293f627e746afe07bcf02ea06f4e4acc82f2eb3c3 +753a90867061a67ec3b0750635bccc3059a4d84159f72ce51da7886c29c170cb +5c64e919dc0ef5222a9e890112f483d78728ffd2140acb95521cf132995afb49 +aad0a0fff06f7c3c8dd8106cb48777fdb32f4e578ba5ae5273d88550f2b02158 +8cb6f1dd762e3a720a03fae8cf15457c9d61aab4c31df4c77e5c85857b3f749c +642803021cf9364090199a468741f8fdbaf40cb11926737819839f3ec097ce3b +c6f961f6dc9e4ffacb3a048a752ab0dfa119cb3537d04c202ef715fbceca9350 +adb9c8b21d2e6a7cdc1ba38cdedc1d19a64e58e3f5819950123f936f0c991e43 +0ab86c3e20810b8c13c06724e1e2e5521ec783c3d61f5581018ed8208a616a8a +287183bc922f116ecf2a5fd5a31e3e0f901cfbcfe538267e9597588a1d2931b7 +b75b143c8a9d710852c2dc41f5caacf35ce6173c43788552867bbb36ce1594b5 +0557f9e2dfc4fac92071888f37f67a2e567043b9338b5d92c708e139d308e2ef +063f5f116b87a581ed0cfddd312aadcf47dc17d4e540c902a9ea4d644244d1fc +be629cdb274a1add4ec7c3717dc5db43c73b394eb13c003be67529062e52a02f +d93bc4ba09a5e1f7d8548737d810638f7a9370ee1f74d92419e3f00396727ecd +d79b5f40b445ac717f28a283aa9f45d2478ee16c70579761d7f356889794a7fb +663a73b8c4f8da09936fb1ecd779eeeea29402696327cb1e64725dceebf7a508 +a126c91cb393eada5aead56f16633eed8ba3f05515bf9916fe5889c79c159683 +78e6cd8646afb91ad2c1335b1612672e70c3aa492daa53a20fe02414f0606a3e +520af2960b83a70523357fd68291809fffb5d04dc7e6a9ffb342967fe5d6f22a +169aa63d67860e6a58d59c476a6df226ba349cacfa55b044ba5df149257542a7 +bd902731d6fba07db5ba995a665eb6a9e4d62635bccef69d0ef1d55e1ae58d46 +c0d7020dce5d5656ded913bd8894b9ca3f664d851ea6607549cc55d02933fb35 +99559a8b6292c0823e9531b52a285112dce446840eaa90cbbbf6eddbc190c5be +8e2ebb5d4f3384ce8a309c43d499b73a1b8ec567f3fa528e71201afe4c762fd2 +c8a3ed81981c13b9f00eba6200b5377b90f6e82fe2e33d6453044bdb6ba77ab1 +4ad1f2dc683c997a777e56d66ae0719c458eacc0a451e0970827100f8ed6e0da +125fc0cd3ea4d601f74a62898252290dc2252fcdc93b735b8582f86240c81af4 +7a67c72dcf3bd2c7a640e4bf854d6c4ebdbeea2daf8d0cfe63ade559dae0e379 +21639a057cce78215bb83b901f310caf0c34f4e28434df6458b782e677fa39ff +2727f8b68d0c793c27ba85bddec977ac62e839cf1da5a895f4923df9890455b1 +ee5c168543df60eb27d5b14466c114a3a36a9ff09658e0e38c66fca6766d3401 +33fad16834ca98b96949597eb6b268039cd277a0ecb2faaf025bc9624b512675 +c0c43bbfd218d779dfa2d409b50965fa127a42b0a120ae0b1c750b5070a9fb76 +1c345ad6f3c42a743b35d89d869cb96149e761660725e37818c1f7293e90ddb8 +c78bec135aa47fc00170f53a3d263b20e8809766e6ae7576a669deaa91a2a297 +a002feaaa5b85a3bee9967d37806229a1d480f305b51f41c662812292e400a2b +c314e31afa74f8783ae04cff122b22111a984800ca0ef228224001eadc15191a +e5ef2c278ec0921fb6b0d41cd158796aa9f9f7e1a8f4fb52d8e73b41611606d9 +c2748d3e6a0297db2accf3c714581f63c5a0127e8c512cad85d9f98b0c9fd606 +f08091d18983c70c87cfba86900450c5b9d871ce39eb2c6a71d2baf7f7356fa4 +952d3bda92b0e4fc537d2d10c8f3b1e53eaeda75405362fe00d8b6e8eb64afd7 +f5a3640a6378c90392b6a3683121617b8d1d18c6d1589b59ae8998a1b1efd0f9 +3d2d3a405fff89819959d8ec5e86756d4e227714b69a4a8465863c9b86802463 +db47c629b3dc0daee90cb6c14eb150427e74e25282c9b9f82bbca1cea0892ce6 +bdd59e645ee6cb2589d55627a8da0d32226c363b6d5504387e1bdc425dd6d95f +57d0df364cb55137c3952266e3b1497df1b23be0b79d03b2840ef797317ab998 +7bad06467cdcb3ef5e4a1a02313d865b8355ccca2c1afae4d5d959f92792107d +4b4368ac7c349f77aa1f085f8a5ba7d7a1b372f3b252a82e5d3038bee30b0cc1 +0f232d504886e5700c0f75447aa43e8f12ffd3870eb5f22cd4e41764f848c7fa +42a04d90634cba334aafcb1a65b60ab4c22e278c835f978a67babb3bdfe6b039 +e7fa7535e3179133d42cf8ed361fd3fdfb43876213bdc8b01dd3fc4f96897546 +63ad48ab253dc6ff9026c6f28eb1b84957decbdae7a16285794a6276f031feab +769b208aa1d666220889771dc0a9b642f271e25628e213319d6003acd95126fd +a0e9eb48fe77fba6f5e720d720a4dd5bf93cd6b8723728124a7f38331fa5462a +a63250f00acc34cadb444040b1803d4f2b422453f6e5ee89af155c5b4cb34532 +ebaa21927d2e82578180d3a36cc9fa1d5d5f7820916dc8dcfce90ff3e1083e7b +a7bd1b78b69462104c15515cf44cb2b1f0af06fb07c2e0b246be8696185cd531 +59667fd1c7135252f6a1a5d8217ad74c9370e0446c9783ceff93e833dbfac4d8 +a453393798e6ef3f4b331b88811f1d047be2926e48cf9b5ea904075b9e536a2c +9a623b9c929e301044b0faf008d5d24190a35d412aa255ee231930a3673a57e6 +4ae07873cdcadff021abb9affa1029eecb3f2966846089acb3f9136db633d2e8 +327aa11720474bb13e90ef063596bab4cc32ad4d693aab59a1a49d03ff6f5bbe +fd7c06cb60c55f7c7b9c9da109e0a4e5d4bbcf80136280bcfc8bb2ecf7321c5b +310b5be6df4f26c47c83f445a52b294c86edb94152596e80dcdd7cde2fdfc8a2 +c30fff2dc8578980babb42141580f202c4d53da318d945077bf84ee07e492cd5 +b3e16c97fb89bf8fd35966bf3ecbcc0121eb2eb781ac3fdccc1ecf2deb4e152c +3e1eb0ed2dee3fa16fb66d1f4504f46cdcc9c37fa3716b8137025f1df03152db +0018e7631dad78c15a7aa0cdcc5b872f9d563279ceac87be46d67198fdd5bbef +1bbc7cca500df6ca81d102454116190cd7b87c938e73a722c6b4b1ee88d73259 +9a5ed21670c9d757ae0022bbcda87dedbca88a099035a62908d038bda0fc09a8 +86cb95a488bb3e81fa4d3b30ed1d1f4dc26c23aa2c5e64b6991240b4b5e4de16 +29ceea60f562580c5b42d99eb60753d91f5c2237fcf739767e6d978a1ce860cf +4786fe43ca67e99df025368de8521da58f224fb9b06d02b668d12930a3a3ff13 +787113c7be9ede6f307053edd7e0c6de06d57f843a5cc40c806f965fa6497206 +ea89e33665afc5c13f9fc5804145702a3541d91f405094d74efcfaa077d4b8b7 +a83678911f68cbd3254f32052b541f4400819907e48383d20fbb3067c1cece3c +091b8f5f15f495035670e7d7d48c5ff4489f4bcf9b82cbc3a0868f1055b3836c +bb1db3d1a7856149f8b7e893098b3479a1f5c800c3ece4b247aa4f975e4ef01b +13f0907975c9d594b599c5144e8d709712e9cf354750c856675b55c1f34a1549 +44dfb2b6b6123f09e3683a0f05518c4489e1751f70149e71633dbf5b80cb8108 +e2cfcd258f0ccc6b0615b6f02700824106bb875a80157eeba27fa779563d7d1d +28a15102731ab42b5619d20e43505c97136af055ee903723e98483582bc1cc65 +66e149b0464053a113982243260c5670b865ea02c2e1c935ffb840b5e6aa92d6 +36cee9a690e2e48c0795cc38b09b6518807036d977af0108f346fa5ca6fbbf14 +8d6b58964adcfdefa386284732dabdedeeb0cdeb41cbc6eae7ded459d67643ba +16264e4765ee37b7669b78f56f8a11bd2dd25f412c7ed451b5aed116f07fdbbc +4dbd67c64db7eab20647f590415230739b3e67cb9606091ebb2801f9d6d1fca7 +c9c7279da57e7f4062f38462e1173d8903f9de52d3f6f12c4a44b56c4ead8661 +682d44dcc514bdf12725dc7b20693d59a18442f915bc374ad2acbdba7622a81b +9cf013922f721d6bd6ad5c858eb5ea05535a92d7d46db9abc1f737b5b5781f30 +138420dc98382455bccd9a9748feb64b67482e41f41fcaecb30e1b22a7562eea +7bf4aaeae013c605e7eea4d1b1ba089b316e75202f901e336ca5d4a514afa228 +b561cd7e96f1b01a5281228baf36af972c9a3be5ddffe6154b1d5a8553f9dcf6 +45f4a99a2af89b45816eb5b75ddc9b4c0fecf32b6de97b6bf719f51fd99e7c0b +a562ba58e0b082620a2fa901a0e58e2e9de953ac4b97b3d1602e62aeb61a5a4d +a0ee6f50f3fedee2578ece3248a6e8b1330b0ba763cf58d60fcb382b6f13f76c +20bccffda6b84e3ea5d285618c4af3666ca8ba3fe971199b4dcde00829e474b5 +b39918c63d02dd6d53b87c8bf4d4be380f3839c9e12b3ec4618fac75aa29c971 +3602052615f48ee877804bb2cf46a04e94c1bc23a5abc1ae58b4c6e4afd7c813 +62ea198e39018c1e8f3c483c8af8f8c91c2c5bb28dbc81a7837992498fd338dd +3766480ae11d22806620a4bbdb495884944473e2eb5b1a17f9dd6863caac913f +c4f2e610dad5d666f578d5a9b7f874fb2de781c8d2ae236603c94cd083fdfe69 +24575f4017b25e694c3ac7feaf6b7f371a217bd5b62086cb13ec8dd32fb852ad +e065446f0f9fd97e860e174e18d14a7caf7ea2befdb3778382cc91ac5c705d92 +fd67e011d6d6316ad24305a453131cdda2a92fa89463a00e38773e1e13dc4d1d +c500046b2721763dfd2f8826f64b893187b4595482b2f4048de7eef61bbb6a33 +d0756bec77811e9ccfdff9fdd3d2d8ebdb73f18d2bb6aa9f2a2f936fb853697c +113289397bd3c673499877a5dd0be0dfb94dbae1e33dded9fc3217a57e47ae1e +1d5d89579202df5cedfc0e6b061a6f2bf616c835ab081bdce8630f019ebd22ad +e213020dfce9853e90c4651d6c9715c0d690e255e968146a1b8c94aee2533c0d +6c0aeecbc06324816eb752ff19cf4791467b37bd577f882f437d33a87b16874b +53c9c2a52486bb061f75fa93d4b77c6dc539167cb4e4a140f4abb9d85c9a8b98 +74d0681012d9c5ce3cd6909d56c1b7b15524f96adde56deb3dc2159eb1ecb5ad +f2753d4b32fc734818342d07233fd2a4db9b0db0462eac732e04bf1a6d729f45 +5f862a6a6423a12741305da44644c56d244d3078112f5f152c7ff6a1b6d95529 +4e97bf1d4ce7f954d537f7013175b81c79cd85bcb932e22cee9ebe4474fe8ef9 +08c0a97fa635ecf8609fb8590b3c34c8ec270cc582181a645ad5015044c69c6e +f5c4bdd6a63efee3b6773e301c558d4d501017788f518100a8477b38c4ad810e +e609ee77a99642f6ab056263e980ea99ec0192f670024d176e8784e9b12bf35f +5ca1c83e4709c69a936175b5ccecc58cef5c16a92f22fcd77e45452e69e3653f +01d1f142849647185346f0c14c57dab63b17a6caaa63c0a6209a39440e8ab783 +c02e0b36589600e7170b8342fed9cc01c35735ab32fbc2cb805e4899415ec113 +0b710564c9542d3359964fa0c6cf0f79a6e31df3fa89d43bb6603e0f654d35b6 +bea8cc7830a76c8f2c9626406069b5bcc40095c71f77246eeeadb5a4bfa83dd3 +87f2b72e02eb55336cdf8479ed33a5deb7e0789a4f0f8c86625863ef89b942af +6cde3c7b982da14a9b489580b8ed34a4a5b54bde3ab55700051c560f05d940f8 +51022c76ed87a882cd11981b161db7c3a7b6f98b3e426f0d212c3f2afd045cdd +a560f7b3bec58c956b52513b84ca624be699695d34e6b3dbb037a59cce366330 +b46ea31cabaab10ccee5bb86d9b47553954124ca07336f2726beaf033d5926d9 +231503b1a754f97b438853508b079f1343eff35c6e2740f386eef6b04fa40a68 +b8e9f8878d601c9e280aef245db798a15fa27d6df9b790b53ab47ba3f81a75b9 +9308b0e18864e5708ece120386c628f1ef662b7b2f60a0b66e64d8d3e5efb48f +dc4f4506bc01c5adc4a1fb7afabd27483aeceb61c16981c06e9ee2570a6e30f1 +32058dd115603933ced84bf693bd899093067b1479813d5cb72255421df88e96 +1d3e88b735f9a6137fc2f91a983f44f487d720f865ff710d669b7d1aa7de0f0d +8026bf0f32b8a42b7e8241f8cea027fd363a10d0384dfca31ed51efcc0184365 +0c048ccd17fb61c7dc2cec3ceade9b205be376c84d7f60f8fff720e1f97661f7 +1988d5ff5f5b721863deb8afe9cfbcd6d673a7bac7b929c039f130b3d1fa9217 +4933c65dc207092c0d413106c05a01eca2a92d7c39f0380543e2350691601b65 +d300a4d2b9fa3e43b26e2c9792186623a6cb32cfad44fb62b4f9f4ebdb1b8ce9 +5b5c00608fc185c041e141218dd1a391e9592b11e00027895ad32bcf69b9399f +6d4216b47320db608b4e38bb2d7e821b70ec7e3ac7bfb929fc54f36b4b4e2b1b +c334ea91900d4b7fd109fdd6d2ae28bccf75cc3aa65e67aab8e5158ac807defd +bec2d1ae678e5eebcb841f37cde6ff41c1a9d14f07cf420095422d781c82ba0e +498a7f00367e203f880ed50fc82f0b7df23ece4e1c239fd83f40efea3b9033da +bf17a9b8a8d614f2dd6c618319aab0dfa918f4e49e33fd8b3ac5aa66cb727db0 +b0d91a80ca48042f29dbfcd636ddc12f5559ae0c0a7444cc11f4a590a4e25262 +4b44b1e542b76128a64263952f955e5d822c5d0dff70a7c402d53dd4be7463c6 +6b5adae50cf38225e7a67ad8d60e630eafeaa26eb07ceb8f745040aaa0ee8911 +b36d817b4e0d40d026a84d9731832b32248b9eead9a42b5a0da56706942ac344 +1a6a2fd2462504ed912406ab8e87317af04593f50b0a28d04168890321f5dd5e +3e8b0c8c94aaf87055ece844e05eef2f316c65a91531e895100a17e2b4185395 +3ab47d5a5f3b1abbe4edb1d3e93481daa53706633c2e7c533eba3af56639ca21 +7944dc9fa75a3508cd1e063e5652dfdcb9ff15e734e07eb8a3780adadf8a2bc7 +2735d86bba29b78877496c8bb8c9251023b856c560eca5868ff9efd290f5f233 +f404b16e58f48f9695c39eaf022583d8ca9edbff8bf4910c48ab9f4878e4a315 +fcaff68d4a68258efd83bab03f20b394ebce37fa82a30b5a7e668bfee874692d +9cab1e9eebf4580153f7beb823bea8da6bc48d1b137e326d29df21e8450be652 +0e7e41556509e5bcc8b0c15f0fd158bfebc7787a7812112f9f6d048b587a8adc +a0094f71107e4b1abd7ddc1aec83da1f30387a97455ca87535784d301ff7662d +959917769ea0dda1a18e35be58382043ec3b51bdf59a7c7045e5807a2b9728bb +0a74eec85eb6ac343e0d62435d6c43682c8b7b8a2d7744efa5f251d7355b8e7a +bf31ee249f68158072ba6302088a52a9489d616d51ae01918a9538c1d9ad395a +16fe03867f7e8fd1af2211efb58ed843f9bd45a68e708d20b6dfc2054f959dd5 +2b6757aba1fa0ebb5d0df7f102e290e5fdea483cfc0fa7fcdc13b205c618d183 +74c6a1f362bea77b58c4f789afe4e47da55bec99619e8edf640695262ad7ed14 +aa64ebf0950b05a8ce32a378f4c2588f593a04dc5858c20dcb40435f44220a46 +38633113a74f8101f1c0fe2be961a894b2e47b302c4b70b9d77c8aacd214d9be +40d7cf219da496850ba2a1e7d4b214c7ef9ada82d6df4273fff726614d81fbcf +94bb7c0c724fb62714073f2a5fd4ee91d9f24a5b7c659b55bceb5bcdbabcb5bf +0bf89766473cecc78752f07e52393ba9bcf5ed7fbef6be56fccc82c0b083b14d +537faf2b3990ac24269e6b1268413ed4bb50c8b5c14e8f03779fa9dc6298c6f9 +f6e35148b1b8f30eaa957026c6ac31887606d8f641077abe01eaa33de4357719 +5f2deca1b92910bd68fa0089f46eb25d6320525aa3ea8422fc110b05eda5fd25 +bd7c84dddae5f06ea259869b1b462495969288ddbc604b9853f798b5d5a56afd +001f3658909be3ad5e5b4f8d7d31a7cc6e556499e67552bce47458c98c264186 +5ee230bf2e9fd017ad32407279fb55180d529445695770cbe9993046dd069499 +e538c64c3f0b4ef6ef97d319483c45433a1f04166528c8fb900dde5cee0ec737 +a25c4d7a03c171457cddf925b4f8a8b8ebbedc51e921d1328b2aa05308b3935e +7c43265828697f2bb7eb120a15015733443adc248406bf8d8b9e99b41d9c1585 +9a1e687994c606a5f5161f084723bae5c58e61c79e2ac71fddf8223f70d546bf +efba136a35d867078b59ff16de24e528a53bbfa2d0441a1b6ed0206c2f6db1fd +f7cf65a8b5543b5f481952de72a5a8a7276f1d73d17f3fc5dc01dae90668bad5 +3d7ebe6f6223a5b2ae68f5a06490191a1cca79306eebaa9e4d843049772f5f87 +48df9aac15e1aef0572a3e68319dc6d40207dedc2a80dd178a1e758d04ef595e +ca495467e7dfeffea304408ed92817f052d18cabae8b6a7f176934b9ffe4b88b +fad3122a7c62159f455c397eaeb6443c0a17a989ba40f5651196ddf9aa216be1 +b685dd4a0c0aff86077d7a2abbc87ee4e6b46da3a6272e7e35beb60cd40d2518 +d40eacb190744ed134a3c5f75e562dc6bafb1e0e4d254059adcb8f0dbc994264 +868780b8f72611b104fb03bf5fcc0110e29ee51744873fa5a4a5b00a743f9a78 +c8a79dda6971252ac4ebdae0107020bf98965095a119db836a68b48ee3f9b5bf +9d3cd3d27223fed47f063256b91cb9236ffea2a8b6d08af1e7d2e900a9cc7ada +ebd62c585c54975d9fd56a4af5a5b07b058a9cbba748c6edae1693e5d5934541 +394c35ede2b8b496d030788d3804a1c4f06fda1b6f0af56fc8f0b6c31c755820 +8446ee2f451e00f0c9d4e28fdbcc8b8d3cbc002246b04978174347a71c7c9728 +a10164c7f48c02243beddb7defb725e23d0d80aecc7921ff5acb439e54f9e917 +3bc74956c38cf2768baf0808f5437f99c280ec325fe85c96ec2a87062f26ef6c +cdeeb867ea7bf597b3f87327bb595c53677e5603e3b248b1fdc62a2a4c58ca3c +3e0ab2712a82571245ab4ccd803c3678cc8c4bca0ded1c2b925355128a9139a6 +647ac2a16b50deb2a2238407409159e6d0c1faa4a1f87c459f15db23c9a7b39e +d0cd289956ae0238195bf148d02454bb57169d28b738eedc50ca7784e4e09bb1 +d413a3131ede08f1eaa3bccc0beae5ee4838a699b947586c52c962e124e933b1 +f43c116ae511f35ec43df95033b1745db313d401d6992c6db9aff794f20480de +b159dbeba8c9e34f521f3350a192be69b9213fd4ac398c57f8756e8eb7a5d71b +f83362b9bcabcd7637700d450cc5fa919c1119e90c33a990578db7340e8158de +23dc2498a99fb6a8db305bae52e82141cf49cda9e717ef58f0624e83bbee9576 +33bb6d69c619ca3a40e3bcd6cbde7831c7036f818c15b75612175eaf762ec001 +51c658ae5eacad9e6fa14e1f2557359aa68042dcdf66e53ad5335977e466c26f +685bd27184f9352e18c0033c36218b31cc8bba3b5be12b04a66545aa27a0eebb +363b047d2b1ae57f9bce38b41504e46b3ac63fc61d6e0509fc55cab6ba28aacd +6373c1e097a56b9b48f3e9429d96b7a7e089a0d9d8f828fb238401a7eaed3d55 +57a97d51597b987072f210b088c782fa2d420589a67f824f383f7bf7a742a563 +933caa0adf94f1ecebd77c176ad69e16e18a8e0515a1dc38a4cde670dd5b151d +0decb79e3a384218b2dcb7143836244ee6a908e25099b5fba878a7c03731a5fe +1da7d562e5af3b9a243d42f8c4a9eaee24a6a825e5b1047555a38b31cf7b64e2 +50dc46414ef78e1c899acf9691324f02c16870d0fb2045c63fd1f6a046a94f6d +a6a8c7d21fd6575b14abbaa3bc4239ebdf3353a7f997a39692b81cfbea8b279b +6d475f06628f3eaacfe260a904ecb5cc514c3320eca98867981767a9d8a11bdc +f2a685c71afc1f9a3c4e149feaaef55a03ec19b2ea6432bf653b867adaf894bb +7fb5c6cbabc9a8c195e839782eec5a597718459da9ae46514e423198ff5d62b2 +02cd12ed62408040ff84f51e4e28d8f451e6713e4b6bb707daffbfd616895722 +07bb3236d2da5217ab665aae6d41a2ad907f13c049dcaee201e2207dcf4a356a +ede8bb08754677ca45e722792f36efb184dfecb7c6f555c2f74964c3f7c9f76d +da0f07b399084d55efd83cf4a4a1bae852d390179a55682e520807f4909c16e6 +2d8db470fe81479a32003f736a0abecacabfdcbd671da397951d1d13cd2b0e25 +a7bf2ad1709f4267c51621f349b9d24f533f7069fec5457181285ca427d20417 +8ddd8be103dc3668622501058529de2f97844cf44ca0524d760d405f6439d8de +80b87a40ee8752500dba319014f015e4963d67d65c73c46add9a0b3f71ae4da0 +74c310898b32102c2a4e62add7e4a1ce48fca53c6608167ad82fd30e7d360a8e +0b6f86216fe5893911becd06aff8dfb149e9c8396933fee262082fbef6a8f8e3 +c2eb43d39cdd87f6be0c03c90cdcce57afdc32443ea58b43a3113e835cbbf92c +8e8aeff653d6c15363c23d69be43f3afe1345f356342325baa4ad7e9fc3e59b8 +893b777aa57ec3f7d1fabfd73a3de15adaab64a182718fd01f3a35b5e3ad9640 +e4a9190133fd480be7b933d2cbc805c349738cc4efe623b5ad7f3174334ef1c2 +711dbefc67b42fcd7d530efa33a5b303c98ef61e3327ac843f90e3ce9cbe6944 +a944346bd63058f7d440bb4f4e8648a3dcef372ade50f676785f2d7db2644d4a +7bf741e0b74e741d8f2bec0b5681f48bb0df8d136d9ea2aa17098951ac2c7794 +11eeef6e9967ef1c9f95936144cd138fc4a953e88a047fb4f3c45bd4bcba7d40 +d8fa01ad396e4a2689fb803b3b9f2eecaa7c0b61449780b90ef98a56311dbcce +746212d70bd0a2f58693be692e35bdce93e69eef6273a82ea53b8c365ed4ec27 +b2546e3c74d11dc49f8ffa88dd47b4bc60fe4d402440ae62dd5977a63462b1d8 +cc6b0dd45076641aaf60a0d6ed67acf0dab693a67957012b4ab960b084320a62 +59a94f7061596c742c6cf8a489dafe2658e46d31aaefa68abd9a033e5907586f +6813b79f8bf6e9c70dfb3ce3d353e0de3fbf43450275d1a6668e3d362a0b96cc +a08a53d8c6ffa7097f421e3e0cb7992e846b41eade9223f2526b67420773cccb +d5219d64fdab5062785d7efaa3cae67ead720c35cb10a95b87f5afb155a0cf90 +46fefbd0d6f2464f4ddd6185bd1f4b6599588227f8b79212536dae68d71d9c6a +6ac78154dffa90accaee2299542cab0257148dad3683428cd9456f47fd8e643c +5641ede30fb2416cc9c77511239316b612cbf9c56ae697fd2d9e089df4330e5d +3ee5aa8031bf73407c1c76b991d3f5cd858f84df504828a18b27ddcaf91948bc +331330f7603bf11b5b1b44f3062584f861715ce0c24b3203bbb2a6024ce24819 +ab61a5693f87f4d9f90e326b7c462d2efd15410c3883d83b885325a252b10727 +30ff403ec1fbfee64af5f34e764e3885af92cade246212debfba97ad8a32af2d +a2ffbaef4eb5229ee1764be882c7ef2b77c30f20fb3ca641ea567fceb488177f +3ab4cee106f667a9690260e18c58c843e75cb19fa97d3dd5ff1e21c8a28e597b +d4304e7928a7236dd8eccac507efd75343a7a21f212b75dfc3973dcbaa54e5bc +f14e5a21fa4de7176fab9d55a8eaecb4f26bf07f95abc492fde37dd2dd883210 +36e82d78b5923a7d6ce860b5dce6f8188c835111221b6760d8e1b6bf1556e95d +5df81932b53353dfe6c40b8733035fdf85ae2782b73c3d9fe167107e7b088031 +58881fbe8ea285b5a805b14797669bf8970deafdbacec6ce6908a27edfc55260 +d96788c8baa567663fa72cdb014dde7aff4796fcfecdb3cff91b5ee1a2d7df69 +ca32107124c43157b7847cf136862afda282e5237ffc9a028a5cdbd917686bd2 +2d2d36772203cd60d421bc58edf4752ee5c5782285ec699d1d40ef1d0db21bd6 +551e74faa5921f0ff71e80740b1ee7e95ca612aaf69a977bb8bf182f98083f2c +51ff2833ad09f995f768a3856b5be22ea86e8c081c0d983e176d1cc1c1609b30 +261b84aa16b53aeb5abf9740eb8e03c8c0f4f7fd8c62fd8595259b1f97d8c789 +83a3c9279506091ca46deb372529bc9f9a5bc146f7181921e9f2ff025e9fce82 +e3b12ccbf6d74b71e6ec51212bfbb22d81d21cbcb18a766a63961931e4ac69e3 +4205e0ab1db1faaab63d3f8d64ccf69ac0b0dd99a2dc96b21bf8b8d6377f076b +f3af7ffcde4948e8f23195bfb0479612d280fe72ba886e08a3997203792e3512 +0e9263011780783abb055aa04f678cae49692cb89c371a8009dfe67aa35b454a +1b3af2f2060d43a354c068bd5f310ee33c8a6c3dbe054a042ad0019159e3e431 +073ac273795575f8546b1cea930608f825b8e6e1ec7509f440966b79a9f9e083 +66c8f4d9384925cc4d4176ed9d448baba332025dc2a389b3203d78122fb9de8c +2b7a7c153082b81c8a2536d28999d89c8ae381baf6f439b8660ea203946367a3 +b082cd8c5ef313f3e515bf0cd3fd5265a013db50bf49100f6dd508f23ece97a1 +14eb5ce749277914b12ebcdb0e6550cae4d0417530f86df8308b8d284c17d9d0 +05bdbf7d3dd5d8559c0214f1076953e19f2943ab034b44058f460ccbaca7d3bf +f63c9c81b3416f4ff3613a7da325aea08d269c66e670d41569865cd07779eba4 +75d7fa2c96b66ddc9c2e473d1a472e2928a3701889b0cdddd86145ae37438a74 +4a787d81100108280f7624ad82a472d41902257a2758ce9aa037959d83ef5e96 +cc7b179f04f8bb9c5769e1746b1084b7169d3fa55e1536ad14a49b9e615185e4 +c42426f65d1a2deb0f332eb0740d1887e9f6af20baa4b99edffb99f1802ce26a +b179476ba7ef71dcb131a6cfc1a31f9537249e09750b28e8979ff8283cc8a255 +9a50e3635d48c56377784ded25fcab2ff9139e495b57da75528de075cb04d91a +0a6a0d3f4b37f8d650b5e51e8e9fb985b75c61c69e336c75c9dfc1cf1aa681aa +ebffc191020969264fdd1912f44a07b5d13d112374102621e8a7631c1857a505 +d3e547b1109a60ba6031d71ea40b4c3695fb2c8bb755909b95737ee86823ff78 +540b33d1e64c10cd1068d1d5a5fdb2f6df2ceee009d6210a30f586701f77395c +f7c57c1c725e8d151936ab8dae8f5452dfac5d1e6954f3489d2be7cd227f769b +57fd86e96ab20df1e2840e5d884326049f89bea0369975bbdab892148571ac5a +e85b9457902ff3cda13a2e623f947bfa3d60cc5814d4372f09a15760e593c799 +716a7327e7c05ed7182dfe96cfe239f4cf10fc6eb4e1a51100340e58801e1ae3 +e71d1f85610ebaf89ee27ac6d3eb46f7d03e393db87e42c6485d04a0adb2ec3d +6c8e0c88f4653d6c57e122fc1d34aff45e8d4b43dcac7de1105814e9eceea95e +6c03daa0bead4faf3e9b0d75819a4b5a89b988e25ec418b51d648add3217cb01 +4f3ffcbc4fa2a495674b660fdab6f3458fcbcceafb0d366d30e85e3fa09bc362 +035399a0c2ac314364d4857a41edbce6054a66c3706fd03578d62b4f7d5f210d +d06dc913bfc669b1a4c50e7f56049d19aac212a25b731545bd006a11dcd226c2 +912ef4223c8091a838bc5ff7babf4862520a8e1833e7fce433bb5f2aa5452e75 +fad2135200964ac23d24b8bc91f64774b712abdbf4a0144ae7a567af05a85f4f +d44058fc8a59bcb5e0f3295eece5e7a89e3975b3b4ba19898f9ab7fa24b01785 +8a8ac6050e48fa2c51d39b51ee03d533c3fb1d0e1c74322bb33f19ee21736b79 +f17db82f4426911b12c1572e699ebf27a7af072c09a5b2a23c9000694ad30e92 +450e034deec78c0b8637de7b572396d896a358b4bb6b05ff00152dfdbd498ed9 +933eed8771c6260560de9bcb7e31720729bb39e332755c5eac0d11071fa3a286 +20b1a558ebb532076ae3bfe622a13f9b119cab8fb082a646fba8f7aee0313cdd +56e48ca0fd99e90098bab7542a02ff69ed56d786e14a099c8838f607158ab1bd +9ec4ea716e0079d2def6da45bdd14e27e804c81b31b6fe1745fe9ad9d758b988 +ef41bc6393521a777849825ae77c67db3893a9f662962232f38b9a99c3ce9b82 +aa9f787208d27503e85b1bb058ae7190e62e2ad6681f46ee506edcf43299f122 +5784ed41009add7f5ac2b3382d8fd7dc206d54c817394924be5d3ca0bda708f0 +67fbd541ba916d253ecfabfa24ab81d412b8b219158696bea27afa1125204312 +5b85f7958e567ce82f3b605444dfd0e13860bd3f8467df87bbb371b5e070e740 +0732510ac177c4d6f9221771f17b61cdfb6bb32807b8a99433ebfd0e0ba3c4c0 +57c0c0d23ec147874c295733bb1f128da64d039dc1732a28b6b93bb3ec1cfe25 +69aac2fbf36436e6ccbe7092b6b5fc3594c5502f116df7ea280b84a77f7144c5 +abc43f9af14fdb51e5c935693ddd3918ec4ee19d01bc718eeb5f544a13dc4e6e +01a61f148c3898c7c62df58809714f762a5b6d06eff4526e927fc701ae1aa647 +e4c95e7b009d9105b7c3c9505551d58ea5510fff8e22a5451590bcc55b8f9941 +e70c438505c2f524274ac86ac0cd59c96cf7ad035b231dc8caf3b19aaef0f5ed +4177585949dc6f8beb815d8cf8ef988082cd7a41cfb14cd013994554e90bc67a +e468ea623d13be032f4760af34217e768a6380a14908b3e7cdbefac30f4ccfab +5fa246e22da94b2bdd76b3e74bb87b71e69db58ffa0c6d71984f06c96c0ab5db +9878a521c5c2e6523a62cb327b9183ed2a8703dec324b0d68df8dcbcdcee2dae +c1935742e767cdc7d193396594bb0b28876a2bac6c6e59e2c877307476802dfd +0472ccce259c3da47352d3f4f88d069e8f0c6375f7712b10e25966c8fe4cebcf +15539da4e762a2095a3a8fc17880852507347fff106492b481e687d693205fc6 +cd654b3fc4ee1bdf2b422a89811f7c0b74b391b78ef82df1ca6e305dcc69ff2b +f5d324c467f6f56cc5e6c104485ad0ecc19f4ae6a75522f7cfc843bfe6edbaa0 +830c54d582903b78d8b8257a0ee6fcc5543f1b2edadc45290cc30f94435c4f6b +4b1bc7eb088440418f50a23b2d1070bc658c025f0917700f7fcef6701bcdfd0c +51d1cde8a4f0e349a148c965d3aedbd89975131316f3c197c1130776c75ba31c +5f4066d5181784da75f4ee258bf0370f8d8b34fae0eccb99c662da3743554840 +4c09ab577480ebb06bbd4675daea99deb2c38fec31dc56768bd433680fb53875 +c77bf579de5acbe02b5cf15561872d24dfd81dac03a53ff059c9b7b85547c595 +583a49c644c1c0402f6a6191be1ab614773d16e5832eecf0bdf7ca7f14872f39 +c505e25f615f34098372d78df535a5cee2ffe67b752578155ad8600543b4430c +99fec379916ed83a36e85b81fcadce80c15b381c381b7b60f5dcfdee8da98828 +05a1a53b665e4b2383aeba7988c74ce47756654b636ca5d02a3f3ad146a9d2dc +5f08f62ad94e7da2c9b5df872579c514b0a81271ba407f7eea739e9117568fe7 +841eed90e69428e3df60d3cc60d64e22d4b326d55a5eafdf690f55470dab2e99 +9703c2686cc9dab66e8f111258ba670f6a22680125d39b3983198f52f4255850 +8cac936cfe028e10ea2e9b110416e67d03737b27a26941e671e274fd1a3e08c8 +e79689c481d348e6c42cd5d1089d351e89dd4f1aafa781595ff0cf4adc959bd2 +487dcce627fe370eb5762ef3828e2312c0e45aa555ce05f2781d29526b4d1cf8 +5a2d3e60a270de917902225f24b6a515853c1bd317f6c54b266746293bc2eeea +3a6cacc79f666f5834f4d96736aab8873456527c279971df6a5afa314f6e0583 +b71196cb11f71848960e74ce272738f10ad7b626b9b16f1e69aeb2ea377e882b +c7649835dcf593463058db8d15494bb2cb38057e2b5326ae51cb97a53d945ac0 +2f7498ac690a4a168a76dc06aae34f2b14af612173c8c71c82d891db8bbb0b84 +706bcba2e6e05919c7966a32904eaa327ceefc31482354735d6630c617226cf5 +6a3865a77585fe22f99b22a841fbf19f7fafede2af8d411323d4cacf31a75c8c +e9b955c68f0c93741c3ab8c65f4457b17b4279205a9d818cadd9ca1fe0afbb3f +776e5ccdf4b1be99fbbe48e26e0dd03eec24d69d80c34d7cde434c40ae576e45 +1b31ca60bd418e4875e03412fb413441ca2b4daaa0c2905ef79c27af69b4a73d +6cd7a85ab22ea9808da4687fe04cfb410e7289f69ece255a7d577d480888fb54 +cba2ec08d908c77303b61686206ced2bdbb3bb80ab592cd6f611f313ae64020c +b123ab3f6f1e8c31cd591f4fdd992491cbf75f1b2a26dff2d3566415caafeaad +aed4497646a0217f95a1fcc861ac91f985c2497bc3f2eec6efee9a48e9150f3f +cacb26ee145a66ac3b4c3ca9ddc1c752649a97ba9e7f41c096e526d8dd0696dc +eccc0dfd15d5255dbb664af441ba58f92af41d738e51c0fae6859510242ce3a7 +904944831fdedd2832287235f7379143e3e134b6c1ae20a4d9de345b34141418 +a47ec292b7a683686e8db50b3859c0ebb99cadf5f4f08490f52b592416c616b8 +b77b3bbfc395ce785bc53401dec1d9573d0baf86b795b5998ffaee5f911d832e +ad667fc26d5a0f0ce658ab87351f423ec818b8a369494f9408a640c57e4c22e7 +7073c644d3b5c0caabb0b772f3528988f8acfdcb3d52dd9f517363c852e4cfb8 +fbd23d3da71d6331e59a9c9d3205b35a46c11d1a60001686372b9c9e3940570d +ab4674aaac0d78adcf92b436ea61f7a8b974a490d72aa03ad47c37b39f48b58d +18aba7e78f58cc1a9b4d70d323d3325811719aa4016a49a93cf1b622c0cb791f +a2013ea9013c3f55a10968df0e72d388b703c6be35e52ff915a1a01869eef72e +8422eccf5d97126dcf94a62399ef11000f63585707e023778b2bdb952de3a33d +d6501a4007378e7b6623ad4569a286e468ffaadc01603fa26599917472d1b68d +ff814675ac3a3bbfd00beaa783fe94355f8d3a18d4b84a2b1a186dddf545dc3d +fc3768c252680915434e8525a16ae2ef31ac5fd7529c353bc572ebdde69e3ed1 +9bab84bf55de3e7640b941a755d7229fa9cf5c3515fc898b5eb104ec3141dbba +768aab984351da0027ec8c7f22f7e834cb274e80519bb55a2258cb081f63e841 +f05208b73626c49447a7dacffd6a9d0ddf5e51e49a3d4e37710e7fa31e58c3c7 +a92c5210dda96428680098d4ca53d08924cdb0183841d20fce606ae5a0c06747 +b7086a16ba4c39466caa0ecfdfecb08c517774decc50726ca7d3c73a8985d27e +70fabeec4efc51b0f6556881c6e7b521c2a1342d5bd2710750f2606cacd3e495 +17538fe0d733d2b544288f8ff4cb30c10d753c0cbb3aa7c29f50137c24859954 +afcdda904a3c46967e2441347406fae07f2f1c60669f86de55417a7dc1874faa +66de7b01218b35a2423b715415d44c271c1949261161686da1863fe1c322b30c +79eb39137d1e8b7f2f47f69f9812cf81a2ccd6f3818e5138aa90afc438e3b670 +d0eee9894bfb4de2312656c112784e741673e8ce0e47215dd67677a87b0d20c2 +99f7810dfcec78e6f5b5a6c570c281bcb76075dda1a4ab96ee9f7bd540f8723e +32ee488e3151bfb2f670f8f33183e303b5a4f9c0aac4244f45546d03d9b9017f +63ee2e221379a0392080d5e5008032f11f3db7427914e2002e0d8f1e410ba9db +7a7266102b06c64c4b84eb94b37b607c7454c44d4397e94fe6382984daa10b80 +82770c73e54f56b35e5bc9a55202a6ebbaa02726022a875b9cdb2fbc9b252502 +2f9763cc14131ad2ad872974b9fcf11b13c178a45807baa1a524d8836fc99b8e +2af63cd82f5e2bda034555ecefdf0945ca2d6bf3d554a190f50fc2e8cd35262c +dfe47ac63dea0c56ad63d32aea0fba8a0a68da908d57c82e127d6b5298cb317d +aeed149c4b7980a7420653ec2362403eb064b17909e1ffcb7456d4527a830c7c +0adda5b408254795996126a255ada105c5b59de8edcc03f00d2e107bbc17efa3 +e4920e09edb63e5df684474fe9fcb732b6bbfa649bf11b506608fe2f067092b0 +e1479ff170e2d7e99d86abf8b84e5b9a850f5154b82f86c319272bc1979bc3d3 +15a2a40677b1cfa4f3422a8d300cef415d537e24eb58c812eca3aab1d96e747c +6f80c4c963f19391b440a188a7b94d003a0ce98b578afed5795657e927af9a44 +70d66556202cba602abd70fb66b7516047fe5b7f88ecb669d070af32beec1a38 +6e491af72453c2fe04945a2696dcd82ab5079f814dc34f3455b50f100f575361 +85578a64f32b83015337e36e574268f366e386b71063c949e79b0836de5c8022 +e346694f5a4b63ce16f0562b68286b07e857f636e487f613018919d1a731f4bc +c207cc5271e050e3685b5ef4d89508bab7d403e5144ba76c9dcdb9f277d1f0a3 +2883bc5ba4ec26e5968bf0c5307a482d82e96dfd176531783f19536bec91c45c +a9957f257f24b39fa50714a4bf93a0a65343f07bf346fa656706f24e0d3726c6 +bd84c9b30a89af8e97e0650f95ad87a36deb66aa6e6adae49ebbcb38219d9958 +8e2d30e469ef13bc2096ea4a1fe6a95d35191bdd998397f12b439cb6ea2bc9fa +2dd4524efb0228c8380a00ca0d386fc8437b7d4a7608e6649eba532bb0bad877 +a7988cef6c76034cd9570585ad9c89ac9d7997cda45b4653fb5e91a68b4a8a0d +081386fba61436561cb4e89d729934621ff92d7a71c6c46a0d8339f4b7c819ed +39ca9fff7aa1e67c355ccd879a7da940ae66c18f7cd1ea0e908f4d6f8788feae +4c01f84e6450d4a0fd3b4b32db955db709154a68d4f84931c27e0adcfc882880 +e3b28b048fb05cdf2c6dd5557719f33f9eaffbe9a734444f46489807215cb1d2 +aa9d9fed02cf8d9a66f69611f26a1fcb79768a04bd91bd6a65fe67636812602a +55bb201f62eefb6091b59287cc3eb9731aefc613f8eca67a8bc12251da7975d9 +1eeffd4b7eef98d348dd64ccbb181179b04ae3b945304c6e36a7be5cd74f4479 +d2fa1aa5e44e09ee7718073ab2649357a83b5236ab0a6698175311ae025bfca8 +89b2d9f3ed55d970dc5ae3217dac364bad286304e515b7ab869d83e188956b11 +3f73286b6434d8405528a243aa4c20ea31d515d2ec8c7c4ece638357fcd4e2ef +4325c6792828c8e2da9987f84693a6b525505d87b01341a71d274fcb51c54f1a +59d44cea928f9cd3a65dad29e140b47294023878b920591d4269b306396c6eec +0b690c97f693e7d79662079ddcf203fd5aa12534f3f2d31a02b4f8aa8de4bb9a +9e56037f29f8e4a3fff030b72ca7d2271e9ee1c7ca3a185ff53aba6be22f7704 +1a76bb36f98d0b95510c4ba85fd9c01098dbcdd29294461879bf162f0f7cd048 +7f4610ed0f7e97e4285ff4f9bc93f36344af2410671fab3d3afeb316a037524f +779e2497ee8d4572ab7ac5c19e7b445ae940a55935219a53df4840896e9e79c2 +b0ca07d0f887f5488bb03d0fb5b1ddf31026ad9e91f8b7bbed26671a7b10da46 +737b26cf570903f91b62ea4b349306e488c14ba4ac801a1fa8f3ddd40bbbdf04 +6a960c00837b289738ce792475a728ac8f5f4b29e4df5984d4869a7936cd99d3 +a082318d6e948832b46d71c2fbdb70fd4fe5832470b56f4ce76d7eafea04fdbf +89a02a2d3aad41b78bae846ce28427b41462a452ad278d4e87b72a96fd5c02b4 +9749f536ed0d48046ba24ccb6e8ead818e9a1f530fcee6ed893a8d98fbce8857 +b7a30d8f722884d6ecebce5918223df52f0693fd642fa2bb5162353854b7e3f1 +7b7f45a7802f8238d685c6a1c732d7f4dcd9496605bacc47cf2d166c85ba3d01 +a8ad7334dab2d26bea12893100b3d1a73765e4aa89cf6af3e8d08999400edfc1 +9aad644b7649df2ef437e6d8a6d48aafb9f89dbd500515bc4090a9c49475c409 +8e5529db9ace63e48caa7019a6adb8d1df8f7d5941648ab5e5b4b256d8b504c6 +f49fcbe1f578d958305032a5ab862145eba8829be82639ec55acdf80952ed9bd +043c37609fba7ff3eb7de9464842727492a13442247fcc0925489a2868657763 +039bf54d6e2f376e75e1bd8887314dc20e610289415f46e881ce0e9a62623574 +bbb4e01474e0f09832b92c5694d677e44c7a5e77fad0759a7823c7e3373a6bc4 +4d3c2c509d80c15f26ea48167052087a8bebdb7b70f54b3434e764198b30c66b +44bb0defd0af2a74b4cd2eca75a0ce7e76328a3716a09a8a4c50f413353d6174 +c7fd3db1742c1071a8188b4fdf44e973f4a08cc9d7adb51500f009a810e5d7b3 +2c4f32f34d5ee83fc3a8cee6ed25b69dda4829907244402d4cc1db95a417193b +f768faf3913f0fa8c1771b0037014ffc28e58fda7647a4b80931c1b3f32285f8 +4e62536272701e754296880dfd89c850167aa69e7e189a96dd4249767f15a0e4 +b412891a35741ad34beab6f2e46b071d8465c7f9b9e4c5aafc9215709eedf3c9 +c17b0bd9753b56af93ef0c7df9b8c958fa47b54694abce796e5367e5609416c0 +89c03184a4e267d19442a1a49bce27641a0a2924b91169eb64bc2c6f62e6998f +b5b79c7aa6247e80d75838615de8ab22f8445bed8177725b9f3545853d9010c7 +f45bbf8d794ff944ccadca461a4d5d06cce70655148e4c5751b8c2588cc37013 +6735f37bfb1c08b9128d6b1ab58d091512f198642d672ca166cf3702ab4426b1 +a8e6693ab5055f9495cef6fd2db335df17f01694ea56622d6c6dc5f17ed60250 +4ffc1cf14819318e9b74421309c85fa6c4cdebd0ff2cc34218723bdefa1cd21b +0fd65a4d8237dfd5700a2f502d77c63ab4565c5223a296dbf07f87af5b72f04b +27f80b66244c2bf08c74ac5d00abe49b3ef447c7917c94e9ef8e72d034dd18b8 +8c92b2cc1d754758f1593afbad91d657fa30d88673c5b9d7761ca36daf09a468 +70fb86e9f3bc84e11ab0cceda6c62234988cc48b398ba740eae29653ba2972e6 +2978a10b235510b2db15ce6e3fa1b7cc72e57dbca04b9d49921704fda621980f +f486fe3216c9e8e6f7eff27c05bbaa8c0fd1a39adf8de0e58389c3b5468afaac +2f3da5cadcdf2e89d323ed7296956c44e4c687a1c17bb7354d1162d8ee0f2497 +c96694fe9b345fe03aec50754f7f15c89a31f76dfc3f797366935d8596c11118 +8a7db4daf624c2b0dda4fc1d4aa589bdf14d074b1a97eb0d0ea365eb0d897d63 +1288baa0c525c875a15be4362d7ae58277800a4f0e0d0fa60e74c1cefc3c970d +d1fcea62be430eabc65ff0dac222132530fb42a3bf2564036717c963087951ff +ad089a321a486b4820282982f11f10825c28b4fda3c79f95698088c8575b7fd4 +c86b5cc6c440e256d76106333ea750ef8b94c33f4d6f6c0d995e28d952ef9e9b +7b952810c94a109b81e14b3028cba01996d038726d1a2a981c04cd69ab8a8e11 +e27a3afaec4f6389dfdffa83d20589dd4659b32734d96f11497855f8df1dcf26 +eea26cab2e56adf4d50e9f4a913f84ef8b01edf2f69d0d1ff3840ea0170766e9 +332584029820f4fa0e192707ca3ff65215bd8340d5c6b477acaee3b04a36fa15 +3314d84e36e19009f239869f88a1eb8725641a8ebb1f3197c1a9017a608a2d68 +7cf66aa18e7f7095c0c368368c60d7f8c4b694d65ab44a6f8d8bca94ef164281 +a391700b0de9185ffdba7f4561e2a1f2c3fb4a2f5ba9f6862ac6ae139a8d68c4 +36433d4c50551268bcfe732eaeb53a0a831ab06949a1d3b9e88fed215af5ec1f +bc83bd5cf62dd9cb8ea4004bdd4a6844f920950a8e5f6ddb6e8d27d4481d208a +821d1954a2361036e649ed4e8fe77d15023d132d40de3efe550a3ca434edbaf1 +a5f259277d23e1f6e518aef6ffce4b3b9793ff548bdeaa79696d3d16b9c36cac +b4d8da3432eac235422f55ed1daa0ef0e61c0ff579197c86e18cdfb45d17c2c7 +6078299a84d8e0297e93968d5698e9a1dd7880879401c7b52a0acddcc75226e6 +e6a8c1a2ed16d17567ff474867551dd34873c3061508679d5a4af084d4afd9cb +6b143ef3759cb5b099f7cda8a21ab4de377e0030401908b670866f73b56ad7fd +b9b681c7295745a865b772f3383f82068d2f0e89ba2e08dbd38af402aa8676d2 +375a972850efdfd7de7a45027e1c38743d79c1968135f116b61fc9dbbfb0cfd5 +1cfb355cc6a6901368e8f8ef4a56a288b1d4590e6962e8e11fbad97822fbd7c4 +1d8d44e0e14c723872184401d6f0d7ac69d69d1eaec5b21849fed9a26c07523d +87d60bbc96a4bc2538f512ebccf9b4b7caf6282f7fe00488fac09dc037850e2e +85a51e8714e1f3718cf89d97a604b40a053b7591b1c39ea8de3713c9fdb1182d +fc7dd601ec9d1e1a26d180690626e07fe4cb7b0fcb3b6b85ccc857a11c14879e +59d3dead393c2175874ef460d6364d77de810ad2278090071b5397ab16b5dd8a +d35c3827b2448bf2159d514b94edd357c12069923c2070d494ff17f345001221 +e334a80a740e849031b5736afe0fd4c83715570e0bd7a7b25a95e3051d2b7333 +18af69fde3140d6ea1102ea1ab4a6ca05350b05610174be84c86ce2dc40efcb3 +672bf69827c9c6d787ca3d0157cd6b39872e066def513f99ae66436c53e96138 +e8b15c35ffc07e03b5839fa27b482a3f63b36067e14eb7065308ba4d19c637ad +2e3663576414f515e2bf89fa0620b202d70a41134d361a491d7721060316b7f8 +0067436d75657b2d7ef960fb382d69c4d9fd5485cfdcc9f4da3d0993b759eb45 +8d513eb5141fde7e4df28c7e55428e21e8f91764c30c7579c29ed90ef9cd6db0 +8aace6479c5249fb306fcd1d21900e72d1554a4864adfac6f1d612cd2835fa26 +18f8a16388968275d53810da5c1f7543c57e29a73223da6cd59980d314e36322 +9543820029509eda0aca2dbd3d36108af310b0f52db41acd6216831d83c269dc +50518eead1c7ebebbe7cbe2e8ab928c2a1e4e8264798c0e969ce997256cdfc2d +6af9fdb36d6964f1df2253dc4def007e3ac8b41a13a07319fb729dc5df226ebf +45418608aadba84876531113aa524c22215c220d5c331f562c04563b6162e51d +2eb0e9335361c7d2f0f0086e5d1a10c70ea0740574939e36768fd1dbd48d6568 +78573004fc2eca60bcde7244ef4be88761818dfc040b8e435fa1e6dbc6b6ea16 +0d0e87314fcab94f9dcbe16daa4aa5ccaebecb2524c8667abcd4aef4083ca0db +48378e7221371b386f685a4b9e8d71f3b4f1721fd4670fcb13bb78bd6c6eec3d +59cd0f684f2c20fce387b94ef27f75d5e05bde7118c361f1dcf341e95b234e75 +d735f20570783715190fcd8db65cace232b745f97bc193b94a3efaa009b33a25 +f948fdecb6edab1d51d6c8c73fd0196cdd21ba01955a602c90771ec4f96b7eb1 +8b35ce0b795b615a00161bdf004dd85ef977050942dc1d345d541798a66827da +e9da5f61f50b60ec60ea384ec3435337fec2abeae117a31e5121af4247e725f4 +fb159a58fc527044351db5a3bc0416f6a31a9b92aade17fcd842cbe8cc42105c +81be8b49982730971baf837888071671297280cb7a1b6cf530afc3578ca702fe +b152bd3fad54e7f783d59a530d387718f6b4cfa7ef5022398f1157a9eba94b77 +90e0f53c13067095188448d2c28250da47be63261e2fac5096fffb7b22ec5427 +7934eec6bd1408a417d11bcb9a8ead6d62232eb55968e016095d22a83e99f0b1 +1a1484ad3c941e9a904eb93aee780797188d5d3a1d7142e4230db9726ccd1ec4 +ece9a0dd83f69df0b0fe6324e6e577f6ced7f9e7b6de17ded8d20a5143a24e13 +96ac7e6bddea24c8825bebe2e87fa1b30487c6217be92979090bf3c8ee7165fb +680d69838b452609c970f49ecd3e32517dcbbe773a772421eb35f1ae629f6a6d +5a3c2116b792d7173f8cf8e9a72271b0783239130ee96fe3be305251c3da4c59 +41ac5bf116752bd7fe9b08f65a4b82e4b3bef24042ae8f71644f56f28b5b8d25 +f7feeb742d3e372509c5a7bfb0b09ad083ec4e50b70f61f4ec54f0d5deba535d +1609826fb29f08203b1c5bb7d0d52328ab438d00e7568777353a54bb50a76654 +383edeba9ea3f3d1a9ad8bc7fe22c43962a9c2317b295031f4662e53dbb90d67 +79154602e4e1f0940942b1df76b8bc883e93b4ebfd29329a488e16b87168ac80 +0e91fe8b4705b62ac4e4588ec5239a7970415ae9f981e3c8b333c94dcd3920d9 +a5d18e5c7ff007e15276f09e6d90fcce8fb6bd6c9d8e192172ee0167f7bd3fdf +3a229ef62680c5546d9e40607989de32bc66dcb7840dc66f67294a5861e3bcd6 +7017e70d6ead00c49d18e7d9becd3583e3a8fb48d74ea789ccc37c62167e1b3f +c8229f9bbc8dc1f7b24dce4665255cb070bce6561f205caaaac4d7ded89a326e +a08f837ae047b73483416347cb9a7b94f7c1d3585551c60036466332fa1d98e4 +3df99e8b9833ecebb415c7c4297e9844dd590f0876d0352a3e9078285415c7a6 +7c85d2af390fbfb70b72757859fa5b770187623d59a8d4d29ba9d5a17c42b679 +50204c3b720f344dae963de359d342ba79f59e166469f6291dc359da5e1440c1 +89ebe32be098a1d1c8a6cc84b7b651a3c67f12b51528be0eb73395a1ab62bdbb +9e2ef9c04d85fb00b5d1bd8cebc577ba370e7657cf1cb5e819c6c2df15b216a4 +c6b35d1b51f4df14c066ece41809804463f75cd46c33216ea06fc64e04c3eada +524e7f603c255a62055f2192918620fbceb50bd4cbf9b43279601e9228d12e31 +d9adb2ab630980c58e2255d93a36bc945a1e0a20cdeb3b1c093a8a8415fa3dab +a6c8ec47cfafaef1e156f401942cd0b28402a6a6f7f3b15f62763ea88915b488 +a09c3105386fa0476313ff47c2740de4587ffe760cce4eef62c7031579b58491 +21d2fa319e1d0041524fa3a2d8638b2cb84861c8ece641e88325fc01d4082aab +fc6ade90bd26fdf0ed4ac41483a9594d76b6e084b54f63bee479ad0802eb35da +44e4021c287c705c908e095edd9b0f874e62f3a4fe69a80a24f085172070cdaf +c28430695555391c458f8f41c81e84779de2e32e7659e88c82ecebaa482fcc50 +b682a0ce721bc7a085af98bdfa1a8f97f27deedcbe7241c89f5290e92a9f005c +5048f3fceedc6e359a4808d9cb526171199ac24749af2dae98df031c8bc3f110 +360b1a3e6fbc087e511e4b959e9069be64de3508f91786aa0c6b502a5152c7b0 +1dd27211323105578122a1edf2ebd9dacfba9b41b9489194e27fc22ad39c0525 +8cdc775d0ccec79d40d472dd387479502b2328e5eab9716ca4ba4a39a1e0ac05 +56e7a27c539c1b32789948b23e65210752460c5e8c825aefe2f973eb4d218555 +20398611e7d207902cd2bb0feb6888cf1d6c00e3a90f9fc3eda91a0b894d5bc4 +1b6a87e8ce07e037806eb4d182a675df73a2c6627c5fd75e02b130c6bd7d0461 +bb14254d3a1c35ef3735f904038819b1688d1bdf33ea819f6fa16b4690152b0c +a6eae7b049deb3138b685ab9166f65425219c9d44f405a1cc21013aedea40073 +38363c9838275baad49ed98399051950feb0f42d0ca1f37f84773b6bdd23b630 +1643e03b03c3fe298e053d74be437fe850e0c991faf47bb47149d96a051e44a4 +7e6bc4733c4d3cd1512e42ae6b1fe4146d2671d94b1a898d2f3630aa840a5eb7 +6ec1a8cca0a56f43dce15880e21b687646f7c2acab9d82b71a5a9c3048b4226d +28c28dfb069b1894dfe5e7db967af4057e4072e17209b77aaa758113943fa3d7 +e599341c12d6ec7524a559f108e7e978803a715ccfb88cd1dc0821cc52cd4826 +4e906a4fb8cca0031183f8b32e944f35a8edf76f78c865ed84ffe7b452ddfba7 +d925e9f691d83f7f6fcc58261b713fd53143f6b8c1368737f61c0c5f13f339dc +2876f77e27372c572e57c6a5e82c997af33a6bc14e1fed56fc19d6f9d8bb0714 +17bb689b4dbe8d3beb01bcfe69156d87fddb54e49530a4056f53cb93000a7e7f +7b5bc27baca5261491322852a7bd0d73d307e5dedb29236aeff99cad1a7e9788 +bc2ba1315e87b1f41ec046b8eac45b2708171e73ab1bd4c8be7878d1c9e7b8bc +78c920cf5501790d95a7898b443d87e1a096faf28f8239c88ad031f02415ac10 +51855a0b399d1fc95bcae15c7da004379d95917460cfbc57054099fe1ff027ba +a5f9c69575b15e7ee934b40a60c3cdb05aa6f54c4a4884c0e6807b7f30927c3b +5e922e1bafda817e114d0fa30edb7715620d7509f9c3169d3be525c1d2958642 +bffe567733f3ebe76f32555c2ac816587f54d63087c633673192c09dd3325d5b +17d8afa0cf5c94be37b712202399b67c2a7ba1e01305600812501168de8cf3b7 +47a5ea70cfd892afce2ed51350df348457543ac036f23d48f3fd48f6eaa2a899 +6e303b4c1c4cc0268495694eef984e4dbe2b8324469fb9859181f0203a9f5bff +e6c4ecd3bd3af95c497fd847341bcc7941fd5296b3d10b4bd7680d436665491e +84810e7d13e11ffdc446a7896e88b91f57bc2c41f2162b13696a559367d65c7e +ef1057eae9093531aee1b03daf42776314211130a987a9408d54af7cf5aaa11c +c193904a3ee2743e24743ba5a6d9350e3d2c87436eb682d82c54a86a075950f9 +6013660890d3ac3916dfb15494d96259be03a4bcd7eef574b2a7b6c3e9dd1f26 +a9988134e5d475b1985c0a0f2e65784935ac59e4c13bdacb04940569c9ceee0e +6cab49a975e3c5325688fb51dcfbedfa0da6bd6d4aa92f9111f8d397e7ab510a +6394a811be882d8e7348ef725dc943db8a0dfea530854ca8608898b059678122 +ef0d101e88c7e67df407fb14e929cbf8d4c235c00c527f9d65909b293c921252 +b9b442e6362b4cccd829b06caceb8ef86b53bd06ee7c95d388d8447db8e601e8 +1dca63e6a61eb114ff7a5e0194dad11b9b5d8fd030a3e99d0861da13873431c9 +4aee217489b951beb2ec9f1378b1fd4bac70dc90d4132a562bd84ace553dd62e +3b696e0bc9390a0179307be8697fdd675d6133eeceeceb2c54df050c1fbaff5c +523be917681e84502de68406b1254fca2191a0d8c6c6007862e1f2f911d7d32a +41cbe4f725eadc6d2eb8a15363bc701f217758282d420e2d714a7be00e1d32f3 +3bf0efc9f475488c4e8633f72bfbfee399d66820f374a0da92c37dba2f81d212 +0b755e24be78d38657924fa1aa6f1076b919565737ab634ec96da578c428dd94 +a3b63b6a8d97f4525ce9fde9de04345b0ec2b96389e57a3ba5ed9fde31c37c7b +c91e5997b9439487ba26222ca6cbe87bb21147b9db42b85c8db0ae3a989dfa8f +38555ae0517108bf4a0cb1bf1e10b6a1758ab8c5c3debda4d80bced4c72a3ea7 +d2287c3360148767d2b900226294f55a5ecf198a9cfd8783e480d10ee115d6a4 +5161f073d88ff13f2f2cc59ef29e2455a02d5db20fe45c4bbdef96a58e8e38d5 +02fa57216479f31656cf619deda575c9d2f0fff7d7f6b491ce9f50e15c902f2f +be0cbcd891682c4a065d8592f3e172d2a44d7bd01e2958ba734653af979e19eb +5cc26592b4d9faf92f456a418554c63df26096c710961af9d0f169e4e8f3366d +4842f8685315184892f7d404d4d32217da25b7d0417c49a20075b5b2c54b34d5 +e02f07246998fe994cd1a871bb09ec1e14047477f86b80649a7c0006b2cde3e8 +31d9deefb06873e64767f8b780845108294423bbbda7ead8a369e591d406a811 +6c688baac04cb3259a7a53ae2c57ae131a2eeaa349dcbbd30738b5ec808e81a6 +bed6631ad29d055bcabeacd9827dc08b7523884761068ecaf2efba7f8cfdc96e +33308ce3620027ee07d8174ae835689a72b13f25e3781939c9411b28e4c96f94 +3441e9ae37c65146d28b974da19f63a8e1434084a095ac763728ee16deb1a37e +b35d379093a72dbc96d66aa8969f41ed56b65f75dbfe80a56720e3400563a7df +c6d1ec090442a716cab817492c7cac42b55391ac1642e6da41933bdc2e76abe1 +9d3b7f7c8c02ce662596a3c63f2d7eb1459cfd2c03c4fa433ed01eb9bd693738 +1e4144b4199507602556723e9a0219954a31e6b4f4e2e67189de2e427609c511 +c99db8972c4918ef31ac903010143853f21950341255f604ecfac59b480a7ee5 +c36131b4335fdbccef99c178e8222df984fce61284f74f650d5e9e62a8e38e43 +02a1e32e4b76ef0630df574ef333e89def284f127139e14d92ae04b270f20db3 +b7f35444d19c6d5b649db8e95ab585072ddebce553d9f63845d0259dae632538 +02ef42e5268e45687f3284fbfb2efeeb0476af4e7e54705897a0c11d80acbe88 +7c0d28c296e225ba30ff7135a3157102969a8c4cdb8375ac76ba351db4a9b98d +acb739283e661ccc87495d9ba27d31f7355764f144f68ea197f6489c29614c46 +dd0c35a0725e4be144b2b66317f4ec156437c62cb57e0b94886ef0da4a04614a +328bf3d6ba67f9a498d5fe19b2651a55b08be7a29de00295a4027aa1c3dd7ebc +4e98e471196b6e19d9f9ec1d93ae8576daf113e4ca96473f68cc523d540d9aed +056488420bc37a36da2a45f4ede644100ada2b97d5491e8ed39d26a63652c849 +f8981046cabaa01e31ea493f88847488189dda59e2dd0870765a003772a6fd4a +b76a5612625f19f6bae32ddad94bcf302526a8fea7d745b3837d2483827f6550 +c7040631ac17344ceb30da7566259c329b4678205206bad170934f8e2e505f0d +7d9e61acf85fd657d0768885e60cbf2ed4d28c64a187f4fbf5de0e22550fd058 +a75e05f076b69f54e5e5b9ec21504418cad09c50b1a80f2782b6fa76e4433a7e +f8d5f85b2b6f038a146cabe484289b4d94e0e3cf24c9fb63d65ed6daa71b1af5 +7cc0f9ad71d988c4ce24969dfd95889b98508a16022834a8a3939e9ff26b1f12 +fe7059378566e6c4bf4b41833ae9a8fe45b72671938c2f97a52922359687ca97 +644ac142827f0a662a961b53c528255c7f04841a0a015f0978935fee51fedc10 +1ba7ce7bbbe8ca29849e5a06ba219dfb36a190ea2bc7b29123eeadf611e5958f +ee53646285f4b17a2685a24b4decb62a86066c65b0d81b0f8b292fa3e2790c7d +900c1f54a56f2cdcb924acd34dc93d4b8fec4096cc13c9ab786bb21a33f6e369 +bf0a2dfc76d5f693f5b1f4dc90422e7ee002dd4027506bf45b3107a551147c61 +894a1def5eff276fab0a952062b7faa1e4e64cca89ffb1b6362f911396e67532 +e9554e3ab275abb09c9446ad9f88e1911a38501de5a0eb109536b62298a87aa7 +390d3a216ee7effe327d7a0337b5fa34f48f71c69a01579f506b9e03bd6e876a +05e404ca88e8f0045492dde6dde8c3f626a7a088cce735c1c5bd2fd952a9d22f +6991884a43812ce55b3eb9a391b7924fc782fe18e3d6749ce6e83e6589079903 +20fdb6b4ef946eee6b2d8bf416086795747bf7d27a23b9722f45e29bb1e806c8 +ac985961c47e0899e312b1fed1dd210703eddf1fe2cc1f376cd4548e68274383 +b6e5f56dd88323408334fe7e6e14ef393a7bbee1993f98da9283cbd1f0eef247 +55c5de629f355e8b7ca9f68312bdb8f51aaccfea8653aa06a56eda32a506f5d2 +d3ae861e2c98c872e94c7c16cc1c8acd6dfb649a9f9cb1274c602dbe2fe3f77d +e1123273d05e79bc957d32fda96bbf34d767e150f7924a260cd3046333f2a8dd +f1e8a3c44d971fdcc39d98e95f49fe63a74576463863b9baf6112394ed03ec3e +6bb51dffdc07a3c47c2cb683087896576e87fe71fa01a2279714389fb03807e0 +1f9873e9f2e0e050ff64852da7a474a94120daefc96dac8244e7a530d9ab4cf1 +0520453a53a32f682176156e83f2af670301b26cfa98a079c43e802bba99708b +f0726b9ea0de0de76db63c074c65cee69f1230ff48f388494eaa966a0550c812 +f0a9c4f26a3c13468f824068e8d9b3edb226a0b9e556fa5c55c8089fdd5e4e51 +e48ebda40a2b90681d7fcd922f979b7925c6f203e37ee2e27cfef00f82a24c43 +4852ef57b633426acfb3e382527a62fa3ee38087c9156a3999a6183406904265 +01415e08c738a18ad9120b7612a2347ca1098360532e5b4291d9f6d6753a5646 +ed8d0d900fffe4171dfd993a56a3feda62baa0e5a1212ae3195045354d8c592d +2421abc9d4a0ceb4058ec97f53ea0455a9d1a54ff5b4ac1232aa8b347699ea7c +5a923baecc7aa14ea7cc176def22ccf88af3392d072b211d2b02118c0d0467dd +9f4e76fd8ec705145f10e07accdc35377871a620424f23d5cc9fc7551c7e552c +e3ca9f5c1d75f9941fe11d41188291d40da52cfcfa3effd78d180432953e6f25 +047cabb753be659d05065b3fef07f1e16916c4f25e6c6d8c430519a9f098d8a3 +8511f6935ade41f43eac40e08339acab39366fe093fc7010ec2fdd35e0f6b5a3 +586b7b42ba7927e7721864809d9652f7a33b7ad78a7075b642ceb4d45143aa89 +886e779e1bc8d084239bffb8e78a86e6f4fc02aaa699f3640fa37d40e39b7db5 +ca233fb2abd84c0f201346aeb1175adb2006ca3cbaa2b0ab9276b5b5809a9af8 +fa76cb8d98f11f430a1c494bd1350cbea8dd245cb74a6efb729696e65a567640 +135b4624c016524aa14aa67ec9c90d89b488f89dc6ea52536d81c467653158c9 +303a381c8ba05146adef44a855ef3038d1d676dd44e6def16efc64187fd36faf +231127b8d8fd254984d5645368aaa9c8a0b586dde75361ec9f795461dda36d28 +a00c19488e9bd6c375b923d2ebc89e0710df782108ade9eb73eceee256905bdc +463e73a22448bcf789d253da514a9f5e8cb7539d17336932386dca7dff88a7fc +25ffa50a21fe2a64cde5a52e89d92ff956e2e48ae3bd6556910f18c5912cf17c +56e29ac8f45a9a8bfdfeea2386fdcf51f21e32a03d2e17b2d5dc5220a4935615 +5834c1eed31f5c70179ee8879b344a648e7313e054e8e706aa079e371e16a78f +2ac740699ab1dc61e1b751923614c0643452512a26ffbdd79b31b8dd4da95a7f +bd9ec5562ceaf99581f408d93b9eb9d338cae016d7d3646bc61fc12da310df59 +83ed05299ebc13c737c4c55757a84d993d8df91b269f4f36958234f419a13aba +bddde5dc24f551a1ada4975fccb625ef1a4f22015e0b6a8a0f8d66d6127cd76d +111719e406f6db257908fd1f57a9a5145f4f4532d8d280e69614dcd9b8ddeaec +62219c44a8496bf9df0ad4f292cfa36e35479ca0aeea312916d30932285a94a8 +29f8ef11fd537dc4a305a64f737a53f88b9ca7ea2692e30183218875d0931f0a +53203ff1282438436f076f7f718e445df21b7ac59c03db5fe56aa2d7ea0153e2 +5626b9610e28fa3582ecff1392bd44d323fc859bc11e8a768100637c1413bc6f +0bd6c586ae6abe9cbcf02d6fa1b2bbb68e0f530f491be98d485f39d30827cb95 +37ae4e5c7081e87e4797443a0770e8a043f2ab1596c0a434d029599b07c93e73 +b5498897a40e465949b03ea948fd77855f48896fdba50718d6b7db9074a51d2c +4260a13980a70942ee3dc3c4cf3fa88018f2a4e55d7f7680d0a18a1830ddd221 +7f3c28bf4c975bb9462f539e6a6d254330a1469b05790e6cefa46438d7d342b8 +34cb719641272471b139a29f3b2f729c17bb7a969366a8b4baac2a768790c435 +d4c8c7e9e7015ad96ef91e5ed4d6a971590fdc9d2d4eaa65394518c4684873c3 +c9548b00a4b4801bf63bf9732abf951a1a4e485f3a60969dcb2f0da30d846292 +0f1b5b858ace7407a0cd70977ddefd760c4275d37f3efbcd1259f3b9d0f22c27 +b8518e5fce1e5bff83c949ae043acaa85bb9024bb33c24c2041bda5866e41bb8 +ce7d3dbc862a0ced2cac22067e63612c7234906b2e6c99d00d13407c4000a85a +5dfe194e1d2271f9b37e3261eddfb517c88780a642599424e1741635c7b8ad56 +bf2cb593a3d71a978407a88707e54ee1afccb0cc0ca0dcd7770940ab96bfbd51 +9bd81f03a9a439318e2d6a17cc5915e595ce314bea1e4a03f1b7374bf9236d5c +2ea78ee9b5606722d4e451e51db973820828259a94c7bec0d11017e8d82943c7 +eecbd9f0d90fe831beb6a23a49691a85b51b79a026cd4d104b1caaaa91771753 +217caebbcb9ac489265c6d753a4cf9c8f3a1cda7ce2937e505a3313a3bab31d4 +6375a477a7d889b3fa8d5cfa92bd42a80f8e52f9aeba3269d40f5684a3883641 +4b9a249866e06a2ef59c2c2d1450258686e4a5083e9faf749a9678c0e56a94e4 +998aa1e9f8941b2ee42ce1279ffa76b8f01abdb8639edfdd626f0d5cc8a4fd96 +e96278628f09c67a336d105f8bc2df8fa1781c15b4bde5d240afedb1b9c3b3f5 +6906df16f28c235cd9f4bc34217c3c0283078ac174436b7e9e2b705555b30fc4 +707cf79ab07431f839fdebe1f2dbb509a753a0f9fedf72adf2a49ea00bec1598 +024b21bcb4a457263609296ad8e7cb64218e6bb6bc7c1995ad2940e95ac4307e +77bf6fb40328ed3600b76cce254051705fd709705efbe5f5da57015393b68a6f +328535e8225266b917099a4632174b976c6067a48c529ed27284100c204f2218 +648386bf2bde0e262af693baa89430afc07b93fb161d6e4686dc1e8bb994bc95 +09b24ec4ca894dfce3edd480803853b911a99db143021d4e253da4c2835b67ef +f8d0b497d8482d90f47cd3a37c7ce8a1d1d59daf2915b7ec82da29c8d5570a86 +e6ba0be6869f5050b95708f82b86f270dc45e800fecc67063f960e902973c36d +d40bb3006315e70aecc46e83ef60f620f5899f8fcb1f18fd5146273005edab76 +b01ef72f459b9b706749d43f5183ed9bbd7ebd0507ab2548f54c4c67f4410d46 +a2cc307474a9f0d2c8c856b79043b348c91eed6ed350cdaffebded562f683e95 +e5730d339c830ca8b40c4fd27236de18bf2f0812fecfdfc188b3ef6f62349e1a +e97032d515d07ef71130a122485b2b89d87289882c4e96be33755412462b322d +9c92942f74736bb34db6810eb084c4621030d44ba35378d09617e6cd0692252c +3d2c35d0b5718ae1b07cf24306a4c2fa248598b8813cd5f4dc39e6c21235050f +ccf0614d15be18c3cf89f5540062297d956dd94cb501fd0f982f2a9006635785 +ff23a9ba6752014f8a7206c11ddfbbe47f315988298855e30fd2723c7f4d1283 +ebc6e356c1c8629746f9a3ef068b41ca3a5ca6fac203ee8bec5b301d94fe82a0 +75a2e27fc5eab236f8f53498b6bd0e5902802728fe85cde7c4abe0cf8175cbbb +8c34e6ff97b848277beacb0a2f319e8121ad8681e1a0558b8dd16db6baf184c0 +0e89611f63f3aaad8a5a3f9efa7fb8b034dad32e06c3ba1a71814dea6077a4c1 +98c0ba6404903e6bfb5235b093d93058e4b7c287343f7ed24a53c30842bfb70c +f1a249487a933829d3e5e3c5a207667c706d1ff845fddef030c096b2a2a135e6 +1ab5a5ae99a85e477bb92e53b566250146ced05e443d548ae11e83e2c4d92527 +71786498d6a00f6b5a2315bd2068b608a6fce154ce7d43e217bc28a7008d93b7 +1fe461c6ad18b554cbbe3ad6ea62f15e3bb7ef3d20e286961e87783f0a20b22a +e0e47debb3b2ea57682981892bbe8b3ec0d79299af8b05d20d4bd4f1e078e5ce +8ceebef5a1a3199e11d9522a34091381052e640b94a7684585a93e8eecc704ab +eab23146958079f9f175080640f6b6503f84661d41db35f8e52c76dd28e29310 +10d5aed48de2beb79094885e60d8486afd7ae51d2ded4554f4aebf684a4866e6 +26dd9968011c7aaa2af1537e572cf7793676c6000bfeb0bd243966d59b27a41d +d77c0223a8083c2f37dc04053a6370587449d7b71cdc6afd5118b6caaf469ea2 +7dbb68cae5daa15df1a632b0c7be2d9553520fa0ba3e76361b534e7f637423ad +93f02bdb620534354e3a28b0c3536fdce32398271ff1264d150b53e2449aad0a +4790effe3df92291ced68516b1df02147cd78849302618525daefa83e3650c0e +171145c8a98a75c7bf07acab7bca2e962065884148c2396ad535c2303bd06384 +d793baf4a169aac0918e8b9e4d62b623cd23f65e130d31cdb99dd04a09eecae3 +0718fc31557b87c5f46b91bcbde14c0910302a70e5bf7a0e0d8f1d4a74df525d +587e66350278452af63418aa79a265211f08f80159084edfeb1d802a3564c664 +c1f1f447ee6dbf4a0bb98087e2fd42c6d9e779d72d4eb33b33a487df5e7a5146 +d08c984629ed129cab860f2f9830a7f98f3cfacd99db63a1b194d2ad90e31833 +05498d875d8fa4a10bdb384b1e24064a50add9fc2fc7298aea324ea673eb9ecc +f9833f99acce33463d0ef3913d439c068b6f447c675bca727d53fafd5cd83296 +2bc239967fb2c14eecf1d66812ddfe66adcbf230b9a5357fa547ec0892d15b9b +bf82d3696f7b2fc14134d5e26808b2fd50e36e2e0a35796c4b7707c67005a913 +c0a2069ba87ed2e5edcb48fd26d7ea47b7d94811d6def12a41ca7aafa9aaef2e +ba5ed07c71180409f316cf13f05b1814942fcff23f628687b53a42492aa1f443 +d0fed5ee5be085d2a048abefaa907272b2d31acc139fb8a036a24ba113a72661 +37a49d200b2891313dd13c55d1e392ff68088b7e9beca7cb9a0ea43b1a6eedc3 +4389dd6e8823c0f8a5ea98f77d7b392b916bb35b1942f83cdcc967fe06d5a872 +6a4648d04625226fa5fb018385deefbd70555e0a7e9d1e221a9005a4b5095bd7 +43c829a7c43f339a4d993ec2de7ce3d3f27d8daa76458e2b8fb708550c7422b8 +305ccce1be5026ea64dba4766ec25daf2bacdd3b1e05c7b52a1778d6b0409528 +e4da6323057a195deb155e26890a19e623b56584a1886bced82c0b4d79af93eb +db7002aca587a18d819f8a4beef80d3273e4cdff36bec37869704a86ffead4ab +22eea5618247a286ab74744cda88f47b85d3f0ed4043d89fc3c90dcfbf98c8a9 +971635a4c89c513fab552c18f7d258bebc839939aa4cd709bba2aed0fae5e294 +adfae71d8b9af280da612a3a7461f3235cd5fc8e55f9679b8d83a3184bf2021c +c6166c5addb9a52a2e8bc1a3830f05b5903a88a4894a25da6a4de51517b275ce +122cb8f1f4672e866ca6692d429726974cae9775690f37f5ffb50fd30008a613 +f29b7edd5fde862f1d80bc93955b2e3a2d3d71aeeb3d241a53d384c5426d7a11 +9bf76fa6d83753509b877dc29ccad45fd97b3d82375e20465710c0be9b7f043b +4aa419276715757628e3fa0d7f297a21df69d417126aedbe815bc67687276148 +b76ad721b4835c3dd3e5fb1719ba84898a86e8ae12f7c305d51efa23504b29fa +909161301cd5e5d65c94bb00e84a69783012a199b9b96ece3ff8968ada473446 +126b5b1fef3861f8ab91cce83815a10c575b6abca0181cacb3087528382d2438 +9a535811e58541fe36c6ca24743e37b348bd13e75e75b5067a16bb3c592de0bc +0c157fd2b12a44311494e532ca312b7b86c7c980efede75a1273d744877826e3 +85bb432bcb21563f9b021deaeb8a633d354f03466a0686d8e5dbb8fe222104bc +0fcd3b10027ac4ee5d23899b11b59ce989f0959d1a17ac408e39ced7340231f6 +9de107c8fc65a3a7f65b690884e2dc1b8d118c1d9006cd59525d5bda5378a3c1 +affeedeeee22ba2a05459682bea129b3c2288717e381d98622eae961bddd9786 +c4b843d0e7acf6d5b6bee6ad01368ea09f26dcad17b0c0ad838f567709a3f0dd +828b4df34c5cdb7a566e4a3bbffc9f5ff04bcf03ec6f492876fa96d1a34e3848 +8188b6c1be4c1ee414a3e5814f7ec32b94e3477524a0726503ec181e43b9700f +147043593dd4263ef683326cf57aad2b38656aef4885f4c41138d3b3efcce825 +b01418224c178379a814757ddf77c18a52dad07dbdfacb7e8f66d0d3a045586d +f0d93c10d411c3015f343436323fd1667f3a588535b6c061cdab290fd8a15a88 +70a7548944d5db7010bb7cee41e5a1c6f51f7bc9e73949880dfb502fa3581654 +047410ae05fcb79478f4cd3270567b6bb01fcdf85ae618160ceab54082b0185b +67681d9ee847e2b69dd312a5d995f2da716ca428f0ee3679f2970aecc2daa598 +931f197dcf1c9eb83fab2b7238501c205560915524a92daf1a8479373515057e +62c7c14f725be50bb72627404a34ac78b6e3fce48ff4058d405a7c5df40b380c +31e42a44acdcef827e19f73f33adf5d2eafdc6389b60a8cbc65ae68c42cefd3c +536a12e40f0753ec5ab3b14c91f38332c0f60765e5fbe9e66bc3eabcd7777485 +902caca09b1fbc8653e91b8dca0b0065b8cd9a439fb5b69549b75205f9cae36b +07fc2677c145f56a1557ea646d95fcd4bd8a263713552be6189ec873b1254295 +4d458ff4fb11ef768165575ca82bcd6666387098a8596fcc4d1bdf55a1980923 +9f68c046db69bfef9eba04060c2875cb7c8d96e27173062358a65e2cbe1c465f +3fbbce9ae0a5a918891e64f4de5d6e5e75b7ee434ddbd7dbfd873387af5bcfbc +1b8a69e84f4190a4375be5c93c9bfb6ee23d4ac8183a3d9ec5300f1a25ca2cde +b91f0aa3a2a1098cac98963856dd1105ca375114e345f65eba9162ddf0fb5a33 +ba9fbddaa13e829174cedc6e57ba8e2d5ff3ac08e6ae4baf124e04a8d10ecfb6 +9d44e084395aa06ca1b3d1b98d299b96f6751849a134f4ca2efe82866878a60d +4a52157b0ca7dc40286c821196d5aaec01b8dc0f4a7dbe535107986ed43e1022 +04787d2e3f03f693afdcb5c2584730648e51b814cc6cecb3a41cfcc918460f8a +828ddf68f67866037bffdc571a6471f5b0b8aa7360eaf5adf9cd2970bb285d75 +81debd1810f6415fddd2de6d3a249fdc3d8ce6bc1aff70701dffc4b1ad86f2c0 +3fc66fa8f307be46c54a255a58bf3ec5df7f64a8180d4cf8c1603ce8ad1be1ac +5b916fa050916b7c3c006a20f35c60b66b4605d732558b4152631a8346249ebe +79442f6df4eb764513e02a93cac27140a1cd70bc8e563149d7cfab9bd7d6a4ec +3d1210713df79e3ef422925b12c601808f03fc4ca2d283dbd188ab328c8cb2db +3fd6bdd91c7031431a6fb0d154d72a2bbf796934739070f65ca4ea92e0207f03 +9f8d73ad017ca24960c126cd289d3bdef26ef72a17d517b42012a3e22ecc761e +a60c2f156cdaf6ccb6a49f0503ead16e47977288e32df2c7e4fa9b359f52ffee +8060cf5eb42906a9d35bbe526336d8e93f9d56d76c40c7d61a7b7bdec95e2575 +250585e11909945256ba2e1dd96d420b8c5c0bb7636eb8234e419d04e85a629b +bd0072b089f5bb73c89e9f7bfdef84e2850090f72646f922392a725ebe2cb6c8 +343aeb9c8baf7154d8ca56aa817dabc2220b7258c980f7e7880ead81f9da6e59 +5efa0db3ea4c4b172b15509b5a6252e774c26df190de06994770b61316c978b2 +bd9d4b3644c5aa9a49042c8bcff9147214064201eaa9db2f2fbb695c5d3f5c3a +ad7401f15c4c00cea6b1cdce485dc35541d4aed99ebdcc335e3850ecc036e4a1 +29b1156ddb34a497c79c469f6ce70a2919eded2adf07453943fa76fb2a41000b +cd71d32076113f5e687d28b57e00bc8bd038f679f9d6c86168dc51bc8643ece1 +3d8caea46cb1ee1a7728fe6fc7a05cddf79bcdf68d4f755749c17e4434028006 +337d86cfc4a698a8a6a376d82fd2d49240ccc3ecf2203a1546a44dbe0a9c9fd2 +5eff1ea6b883b91df7dc0db60ee41ef68913e98b46470685ce276fbf41150619 +a39df7cb6e0dda07eee74dc41bd2759e6f57d8556941d7ac6350ec213b8246f3 +e2fa2b2fa15d9bae2fbe095ce9a217959ab7ba76bb5e6c3bf6cfc09a82292513 +a826aecb477345e4905da0d1af89b4c008c41fa2c0b093e256f4fdc814232066 +20870b29cd32ede41c54c174202f827f9ac05aa25dab391736af54dba404847f +edab37588b15a1570f96744abaa64d532ed4e76d91168afe8e6be37940393328 +2286145804418a1d5274d0f072e518c8b8c3aa4af4718053afde9d772faf920d +94ae066a16f80b075bbdbfb58a6cf11f4c5029279f1b971c9544bdff022be713 +c05b73a53e8f548410f9a611cb1904d3d76d4ed5117c1fd9adbb9af29848982e +47678dc905fb915ddaaff75947b1c41bc615c4e7b24b99c49919e786431a9303 +620908d7a996325d5ea27b14ee4a197776191e369954d3cf616e7b838f718aaa +640e48255a04450caf9f75bf0d40127ec8f675a249fb2600903b2e8adfba0f99 +c8c66cd3cde61284dc53f1b2ac81e230497f83877019fe512348a044b5c91f9b +9cca9404e56d81869d333102f564d4672971e9a5f6c90f596a1e1518aa18aaaa +db50f07fee75a56e95c234fdb18910b009fad7dc43c38978671ac4d1680ae563 +d5688407f9a486faf33bab104629f2a1c581a3ff5e5dd04c44310ae3fb2dbd6a +418203cc8c35b5c916b434d794b9c0bc41e80763a421b64f2edb8bea9e96d3b3 +9803b9ee01a595bc6175f0e3a9492a1fa097a0eab54002570a5f8ef291e8f9e6 +5b02ae79a0e9fee3437afbdefc580832243ac1e1ad94346d5d41aef946d8edba +66026bbe10d4f502d9edbcdd1d9e856d01aaadcf9e851dd9ed59352054a5dc18 +8f16dd9adf652f3cf9943224873c2e90fcdc9499c63ddf446d4ca87c1c1efe90 +15928c90b1a9fea971eb9119ccce106857d8fcedf94f700cf34de03ca35adec7 +9fd79ea2d465262a75cbb964f64ffa99d230b7343fa1ac54d8abb4a21c1225a0 +f17e29d70cf592cb1f5100d0330e481c370f6178924e13a81c6f43b94b224d2c +28dfc7b4d4b9c95709906d02916b1d6a7d5cd111eb0c74086ac1f15d9aae64b5 +a7dc9daccd3c2ed2be6ac5f8d6ac9c9e70eddea1ac134dec8175b25a1fdc3f84 +a194fea85267934b806d3384956959ce84e8aac7a119706b61fdb00712ba6435 +e8f70e84f399d06b90168c0fc1e5b26f618b0767424664c37c89e4b5cc2c95ff +256e6b7693c9fdd39b02362a916f6f5fc19a84173430362596f59e4c6271f098 +a6706b0bc2630d48d357c190e201087ae41587825415b572958a81a5c2f89f1f +79557d86c0b7ecda4ddc35ed71f458361647f9e78ade57b1fe1d502a3bf21718 +673d1421880695fbdc4f913c6f584dd95d3159546f58b49cd75f6ccb801b7894 +d26c48f0f6911233c056189d50738a653b31a12df225d07984a140e95e77791d +8c083f2342d1706a892a81af96977375d2f95d7e8b5207312286f919881e7921 +43f814470eea3bdadd08dee3020fd93dcb162e07f9b26997a1569feee19455e1 +edf38e5a37ae6f4a7cf77ce05eb75dbe446ed8197bdc9346d6d37800097b0885 +595271b36dab790c32d4b1154c3ab5fb04df0c9baac2cc45b2e7f3c871530ac7 +0a4380fe21c64afe24e92881ec30c00ef5f467cf43e3ea5b99b60b39a0684110 +b8e1df9a815c0a2713f955b43048a4bdd073d15c6dcafc4d421ddc76183c6e5b +2dd53990d9a06058b370aa3ff872ba4a6812080a1866a2fec8f7148eae7460ce +219e1627df1eabc83fd984cf1ae2a682e12649e0d5e386f12db42fbb3b025eb2 +3cae941c7cd68ce12c2029d28c14fa200210222ed09e8ebcaddcf384d10c5653 +8957d1de7dd4e0381378814585332d840e1aec5a50f437513737b08c03e74c22 +007b3b803d542e978ff10c57cbae202b3eabf442eb25cd5d86e1a2d7e300412f +ae851646e8d04d2bbc21452cbff685fb493941a352d572121df16568004e47ea +208a5f27b1c8fceaed0fb421a0181547c4ac1b3259349b6635276ca01bba317a +0373be80219d13db6dc364e21f91d1341ee3bf30454d26d5ebecd1fb35140b3e +2a33b15fe27e189c01827fad1563872932bf2e7ba4998bf7f4725e3f7f7695b5 +98ace4af950f0d08469b569319985463af4992cfd67fd7d91327c38ad6b76cdd +5e08049219fc44249096ba3c5b503d989844ea92dfb6f67cab05a36cdab31c83 +93ad419ce4609018b197c5e1116ec69166a0003e0dc81aff3a1b3ea5bf4461c3 +7c92d7a8658733260bd8251abc2abbb413f4f630734c89e4c306b5d814a73912 +d247a1f0af9cf52531221c065ce354590b5a9a37215de3460511acf32fa4f181 +2ad3edc3d2e60cb853105622a80429256cdcc0ddb4ea60d7a0c43e2a7ab632ea +c0f04d4ca17727c65519f5ec551999f66a3963d435b73a6383bf595fca7151ba +f486b1a1b4a17a14557c0bf56ace010216978c7e5546671407d4dfc1e92c5c10 +e6e1dcf0fccf6bb50bb5f9f70eef99e7a546cc887a053f9709c192c528a04ecb +6810e0efde77f7345fd128804fcf1fd8d6152da3de7bc0b80730b8b5803606d3 +2d81d2c54e8d8c9bb972110770321550c04b8090ea7d9a3c69a5b8c891342d9e +92f6162779ef6dd591169e9370a8087e33f37e63eb581b268836cb8cfd954c81 +85d3eb9610ff2d1fb82fa703be57509404fa614ba849203dca57045be6443209 +19baf2a3e59005c9477c3857254c205cb775a525fd2883ba78659f7b3712aa56 +3470a4e4fcc9d6dfc9bec668f4dfe3e4b0d6734bf3515d04bebf2f6043984583 +dbfcffac0e2019ee35be67093b5de42c8f6c9184b8c87f6012e5d5216c24a738 +bafc2697dbc0396a18183fceb1965c65428259dd290a6d44c66faaeda3674de9 +8a740570eaae745e2943a8bf44f333562782b5a0971b7d5eb3abd5f54630b455 +0ca16b241c532d92ed7053996d6928bdfa975c03074a4307519da07c2531f560 +4eb1aa98cb442af9f7a3bd33598bad6dc3d8dbf4e48f754386a78bb4e6155cf5 +dec39386977d4599a00cce76a0f37630169b2a8a183349b0677b733f97baad38 +83bccc62ce5b8656af930ca27fcb1b12af2ef2c2d4a0db1877a475aa90a6e10d +81b4f7f633e69e455e0dcdca16c991a2ee3d1ae57cc9b201b1e46baff9b68f18 +d916b5804424fa91bf72276da0abd4869b22424371dfd28416335fa4c674e431 +280f9ffe2677ec57c9cfb9db44c88e587858be1d8f8ea8ea276c5dd166500b6d +bdf495ccc08bf4fd630e7ddc090c60ec9b8deca957072fd89a9da58ac26990d4 +6d75b995142906c5c3c6b06782fb8bd33335061c3cdc2d74e5cc3b4e7e0ceeb9 +c92729e1481662617d822ca37a307a9bdd4abaafe1790b53d3a2bdfbd41be68b +44e15531afbcb18fb111b84f95d89bcd5568d18b450b77cf49662b4a1b3cb395 +49c9637a8676bb153714d56571f3aa808be09c81aa55c010c71df18cd6840453 +c81b449d572b52d29bf19328f808b6edc06e213868b96d4bcd0250cf997d2dad +c2bd698392c4a48c0a7149732e92f54a446456e00d03694decb6c2cf238dae44 +28ccce653213b76afb9631a11475a1a62c0c59ba53a5218cf19f336f20ac9375 +aa95fc15c37e7f3663d53e8b0b5b84a0e5c95596f73f4411ddaaf5c1c8d5182d +1d067c6be0ba970e33aa1b3f35fe6693b7d06e14e960f6e6c703be253cdb7cfe +a64bd40d393a8bed217a7189eabf1cc290007412ee2f8a16cef31f0fa45f6bc7 +ab92f600c117dd1a0e26f4823433f5e840da98de06aebf0b88004d7341f40295 +8e5eb7377c1f6f8d685be3a3d4c920603dcc3c1c6f988fcc951cecfaa79c5dd7 +7ddb39cad98e45dd127e19ef968ac6603bd72964245e1e890b4c78ed620209f8 +373be4dbeffca37bef421ad3cfa31c95bc7629be283ffca44d3a6f5bc141b84c +ae5d256ee7cbcb5d544a7392a8c29c41f57f6130fc7e46a12dc73e913a5fca4c +971124bf3120b532a43d3d5b395205f2611a1879454f7e82c327b48e4838c801 +d43658d121493f25671f7dbdb15e0edd0832eadd23380c9704b266685517cd10 +41b8951e9c33dfab2134df765b97b5971a7df2d87efdcddd8099659a9c549b1b +3dc2c37cfd01d9efbad73a552546b9fd621de30a63b043fbcccfb097757cf3f2 +32bb2a7db54129315890488a79f796fa1f42e14fdd60c380ba1298d164300478 +6a720fbd9b15ee15201697c89a7c8885f6b0245126c4fa3de3bce590526b9481 +f5f7151cbf02681576222ce30bf9632b1bde0029569c7cea5bc3eec357543524 +343bdb4b0c231d1f4b68e85cf00bd864a9d780b283f8689c4c260668f25918f0 +67a1584723f7f15ca3538c1146cc4550b7e0c20a12783dc56f04fff9b44ae037 +b9824abafbf6e65abca51e25597d4fb6190c8a23e436c9532b3d082eee1f7d25 +576ab267123d180aaeb198b7c1fce3821838041fbec5591380e8c20391a25af6 +a38923f665605e34a32fb1fba22753baa62d23c7d2a3dac38c544f41092e7a6e +06637c1a7574c589e7943a68f04f551ae7c77231820fcdb03cc4cbea5c43485e +4f096bb07306e7f401fd282301d9f7538c7908357fcff14ea839a6b81f448e56 +94c8eef01074224bb110688c21c208b022531e170ae021079952c96044770a2e +fb2ad9652965a8509ff5306096b4b0cf2423d009b65b4d8888050373b9f0ad4e +b4cb2bd602de157ccb2fe4a26f54623f3397b67e0f917771d035533aefd52465 +b14777c6d2b3de51de8a04668f614f77480758aede46ca821b0077aaff9356d2 +abbd6b13a3bff523f1de717fee462cc14afc54de700ef4e326deec5863eaddc7 +ade1c6a0903a7145324b3a1038ba2989af8e135ece66157e8046ba06256b469c +fe288a87ae7d18c96613ee6312db029b90fc370b0a15c82d7e61dd19b7062cc4 +4d13b89183fb7185f581c4072401927483f85b2dd1b5fdaee0a7f578b411f923 +951614645a50a78a38a6f32b05a481a54f9d8f1552104f66e2923cf3f4401410 +9e336022628aab9e947e6a4cb432f24bf2afd3989d48d905619e7062b71891dc +750b389e9e7481fd80433db8a0d85bfbfba4a782abdde1a4c114740767c1c620 +8c188edf5adfbb8f68343bc5dce92a59de5f452384b83f4aa810400750fd03bf +8ee6a2d0e570a661038ad1d76d4b9541bda0b7cb473b1416b360db548b0b22a6 +0d2ff4d67a54a290151052c5362e7365f39e5193bbc31a6be872540feb171208 +5642039e9bcb0a90ade728d7b88779e0a51d2efb42a9ea02e48a089ed7ed9dd4 +3bdfdbfa2a51201ed1519b4ceec89d03bce2961ba26ffd7fd7f0076f3259f491 +f790ddd9fbdd82e40de16791acdbecedf776fce9b3ef253c2de11cb7364bff3b +022f5a9c96bf66ba00aa3e6e17a010a3c5c4948ec587f1c24cc46f16ddc2f1a0 +dcb4cdf93e9c042427a08e47cdc3c6b58cca6a9fdec329bea92aa3e0e6f986f4 +5da5728a1ef1759984bdc3cbaadb9cce1e1b030ee80c68cd309a0bb207fda8d6 +38bd476ee0159c5b70737697c9a612b3f3ed49f08d773945f03268f07d34cf21 +8294549d77271ff575eba9969c245310617b03aae1f6246f57e3fae2c370b5f7 +baf2bd9d56e2627d88e4d773c4800b94e4f44793d29d6ced0f612054332c6b94 +9ac2180d8e4dc1caccf026d6a34178a2bff2efc96488f49c0bb2d1ec23fb665e +7cf32ab3841ae4482908d3e992ae15d87ff2c573af9d4cdb3e3bafd4816bcbc7 +196444a47e02e34b4feba700dc845303196351286fef1ae5345e58ae55679aa0 +71ea69e68ea53fc07988af914f827b68b124602be0b2378e264026ed196f68bc +458378d284517a26b75cf55c7544b4d2ee8af5b254b7b20eb1eb814ecb2d0d6e +06a9e1c1ba3e459918442ba220e0b2f986f2262d235f85541b65f064325d27a9 +749ac8fb95ae5873d4392ec142551cccf8a348790f2d36ea0ee48b7239365bb6 +75c9f4b54aab4ec1264a43e9fe5cddbee5ee992d9401097b60b752a1537905eb +93dc8e58ac22a6e795bfd6a69e0c695ddaa7846c7768b1f6cd9f7ce003550b1f +b65769fe9701f1cd2a2e721af2c4d1f6d0051226f16a1b017c1b12534354dfb1 +8d0c434affbf0a47eba707310a79d6df91e68a6e0e9ef1d5b90a475c2f85addf +2eefd34216396416d48e7872004e0585677771cb26d32cb01bfb908e7d8ccada +e8813619ed33023c3ed8e30e9c2caba72bb6b14c5764a2d7524ba0ffdf01df19 +66acb311c9150b7d4cb46d2e8de3bea434297f26150902ac6de41e8fca298d03 +62f38f136ab2bda46bf5fa41093be8da2e477f08cb9a7cddde3a2eec2acb7e5d +887061afeac6844ea5ce933165fb2e7d06e3e363296d8143dfab0f53c61dda36 +73e8cd6244fd04eb58f1c9c73de28745045620702b8afc35bf7d8a21a70659d5 +618a4b0f18c4a3199908770ffe29129f41f95932bb3c3265ffd6a660c4992858 +564ef834474c5908c87e3f48e93cfc62cc88fa7cf1d9fe10e947231f63b74b0a +22775830ac1af768fc366b0baeb9c78359fe4767d4186d8c1ef799237a3036bd +222209cb85f6c6ebc28eba5dfbd93ddabdd39012ecc79dce0453d0bc5365ee74 +122af8d88186ea05743eabb0cb2ba826f0546ea7204524ff0ee5477be9ba515b +1f8b1670532f6028c3a725907f3a8c3185185550332b90a8d44456f5d32361c9 +34b7a7f40f94b9523c1079e146017c2c289dd7ab2d907cd30e58b11723e55faa +c61fb6b0cc55f4a4dc47c1b4ff01d38672fb1d33e47e5d09e0c2ca0391fc4b25 +be1f8fd50018bb9e0db3779f2ab036e4c1b831c191f76636ff3bff76aabce300 +476e0122ed54cffdd8130ac52aa9363dc0eabb6ebda1e77a68b91e0fdc08536d +01916f6f15826f1fe6732dacf0cb69e0119e1fbe2c0415e06b6b258adb74b52a +7e126d27a3ef564834298f0722d686f76290149c19124bc5fea25d0bed08cdea +81905af28e74e4070131e18e7a3ad5271f56b5c3837c23e6a0feb11b51fb2cc4 +313173ad1457af7fd1c24a379445f23b7c90a70e8f54fbff6167840dc061febe +7ea57806f34e4d740332984cd5095d762774c68581475a42d4a58a4d7ac43c5e +21cab652a986ebca65cb1be8e3370c1225f9177345da66574e773a3ac1efb728 +e8ada71daf1d73288a33f1152187d9fe44bc68ae2726c39f6a2afa3c88fee542 +81961b758717bb63cb734b8fd55d85d7a9060d7c1d9d28eb6830a68238311eaf +86a7979603b5477078dd30f548a72142c28442b32e7690ade18d96bf703a6c91 +ce6ebf0f8a87ddc0e8ed699cf5ebe1dbe9c75cba9e47250f2079ed72e27c42c9 +d735ce9aaa89116780c1de3727935e4430e99f776819561b56a73791fec936aa +43856a125d89bced348644c3f91d6ebcb5d7b2ff3a72d50ae135d5780e6ea1ba +3bf610741595d94a0c711b998453a6c322b2bb651c81c09efeb3ffa1859ae2db +5c4db3f6129c677d33e24e4ef633220a4624ee6a949ce80e4484bb154a968e57 +055a8cb32a4c9e8686c3bf4aaaa2c29a521f0c0c4637dd110818459443e23e80 +be92bd008eba84934d1afbe27831b0afb4e526e13ffca5bb98aee53143c34b06 +b0878e8e437d5304c97f04699fb1a10e8f788d11e373397a467610e876896259 +765d0078dfa3fbe9f6feae501accdec1b1b1e091fc7a5ae263149db1aef53cc1 +70b7263fe4490ae5408d630687c68e2e04464162c552bbca4d5166ebd12e7ce5 +4538667ddf5bae827ad04d952a78544192b6ffb9cc739686990f4e3cae67acca +337146410dc7ad7195ff8083a647467e8c39cbe52067533a73178c5a5605d38e +8b9acc7344d832193c4b5f547f07e666bece10434771b306e4afb135a7cf99fb +4c328ea20d2a22dc1a17f9601324eaca49977a989f795737d84a11a461eb4e37 +c6814dedc2651e51d7edb5906f370aaae1e9d8b6a786e3347eb64a0206cbcc36 +2c5e18c751af1c4a4bb9ae77864cc90c27cf67f124397c87c79a07601d46b502 +d5355a8820173304b2c7599ff5c22842db273f5a941317bf3ec4df5cd13a7a6b +a333c49b78dc33076b8eeb0cde012a1257e6a823c0b4ce86fedfda050d83c61b +2602ba18b28a12eb8850ce04ca46c95a0aa27ced8fa25af61ec15136a1e9fd7b +e65bb9709fe7905037dd6680c2ed25fd1c1e258dc0e079b1c0bebb4c96e3a436 +bd43319a627568edce15e74b5571b5448f2cadb4fe2241afbadb24f90d216ec8 +7c1bca8bc43cdf99ab78806d5685f3adb10811935c14d568465f760da5182c7e +e0a2c25634b3b8efcd07098a138ea7f00bc08b613d403851346306658e06178a +1545f6f197773678de21f5a8d7be26d5729d92114ea4e54df7a171735317f0fd +6d79611212157bdb83c8899a59503a7886af884dc2697937c09276e4012eed1b +b147490217d213b575d0a9bcbcfbb19639b22330292267c36b1d2a7e9993d5d4 +5d675a7268f0d608797dd5685250ce89c059b97a686880270c77aa1ceaa4f8d5 +a373a0029a7b792e01d464ef7464109760c7f4ce41e6278504be5eaa9d8fc5d9 +36c09ea51f7a9aa8871155c5b9473e5186af63ddad940ef59e6eb237e1bfc68d +21f6376b16b8f04b46d4c6e96d53c8e14e2f41785f2cfbcedf100a9481d13a93 +44f1a8418fef517420f035f70c0033505b0de0b473255f534600b2daff9c2fce +d4c250adf25e1fd22c38e90d8c27df6eb519bcc3a0c8644f57af71854dbcb88f +6aa37493a6cd719c4c0272e7f2e0f55b64c3d90ec136e4e0a1af6cd69ca74c23 +328513c22c23bbc91833e76de82386daa0bc54a55f0bc0a9c9f9dd37a5b452af +551aa497e0b8a040a6955d28332a9e0877d5359f0d5d4dfae5983517de706c0e +2b2647463a46e1ff7ba5b576697817ccf43074aff425a727b41ebe9b1c09fe55 +d683b8947282a523dd017ac22067a3fe6423d60cacd9882d917478409e702dc1 +7b9ac08bb7817bd84c02f698d6f3839eb0296bbd3c00eaa8f162ff12c3220e1e +5736c3d5978dd6b161648f7fc880af2b28988b4a5e431722a7d81ea9a343e5bf +5664905b5f6f59d74f9e63208d63c3ebac615b3e680602ff2b8cab55dd72b6c9 +ccb919fc7ba52dbefce21b99594f159e48917c779300614411653151e0384377 +539274509a4f3811b6c9171a6904313ee7f1b52fde5638c81c82ac84b74c2c9e +241e9cc553d1d386dd29d8bfc9415fdc8a9449ec82cffb12ade0c6d4ec299947 +4916db9b2ccb0fd73e39f7dc2f5f9c3577c2ee242a982687fe40b76594b63dcf +94c7f6f84d965fb938d1e4cf0b9f693e37f820c5b0ac69a8defafaf1c8d23bca +4ddfb21da955c550a77ceb34c52b207fd59f8aed6197f1a9c7f523b6de9ac1c7 +a3d16bf7fabf08705766a74d9323ae61bab989aa506c971898729692a39852ea +8ec685c3269f7c4206491a83503c9f6ea2b9f4646cfa8ce06df9511410f2610c +45986cfcc9138932749a114202c1775244972c74d1ebd08262edd76401856a80 +f4996d1e379b7e07178b7618087fae5bf3a6ecb99e8378ab55fb43b0053b5086 +7453441cf966749fdc59dd356b47789acbd5a172dce4d7421471fc922c6beb9e +ab457f39216ad83012d682f629ab31147b29c5c85d0e3a5e7c30eb6b20f871c1 +8a008ec165a98615b30de91f44bf787aa7a58d221d520ad24f91ad7b9ff247b3 +e6e909cb515d3b396caa84ba9f7b803b04bc63bc4110cd283e9a44823d513d58 +f2edcab4ad36dcc2df9da533194d605eee8621a994a6c3413e16c3ba8ce9dfe7 +0449c61581bb436a99b4ab45de719c422575a2c69ab8b77177150216acebbb00 +3906f5583619121f9425262b44dd3fd77ccef640c7efa9c4dd9d813aee006f88 +3e66a4ab6c5048e15ef8aaecf79ce3c5b0c4553839c6f85a49dd497ee756d2c4 +b875787fb43469a2efa0dca4331ed0b164b94eac1ba96ad941afb98ef5765bb6 +28055424d97295ce0f7c9185cab0cc7b73acc1ea506bd111efd69f3c63012a77 +e387459969564555df03b50a5d65bb7535f8899bcb34f41f51167edffaeff18f +f354e040c8b7049d587873f39565b67cee55ccc6adec1a5609834763078f2b88 +76ba9da5a453e5bdfc854f34cee03655f2236f5f40624aaf5b5df6004c578da9 +97c7def8f00006fbb16ecccb6bf7e60fb03c15517897906f6d2e4cc252ea08f4 +a450bc2eed85908f822550741f3057666c635caf0d4c80e57c662daf3ec0e8bd +aa68e2445d0187719af4af90bbce1aec0733a99308fe1eb6383fa008e9d6d628 +40b015f61030d236416c02bd31b73fbf4c27392302893bf68b83708b795752fe +0f1a079a4135509d768895ba95ccffe0b96571c1f6809babec5688920c879140 +540d853e858fc12ff1048a1b460d4a581d6967c14812f4153653f93d7d560e12 +6d08f335b16bfb667ce3b2d1c6f195ac7a1072d8b43c50ce40cc2a6002ed1d11 +d9e61b975489d8d08e210f5b8c3f5e3f5d6389821f8aab32c1b01307b4218642 +f967318a019534024cf4d76f58410d445e7d29e3c5752a5fd9e2ce0837198c4a +111efdebe4c15c937fed958ddef976e7cccd2401a2fd79baad265701f8f39362 +aa860758cce007c5df093841f556263067236b88863f96b308fb97fe877842ea +d7a8fcc7ac7f055cca59338b4aefb1e7b9674d537bfcc6958cebc1146f887820 +a95541d461592cf9e37fea1133b4f5ead77e1f2368a1ad2ee391b568c2e67348 +dd41c03ede53df2888d52cba69c1ca9eab24b3ace6f826915cdfab79a6e39878 +6e1b233d7350cee1404b4db8e944a6ebac16451e20400ea24114c8402d5bb16f +95721975a8b25c2d3f97c18ea975c43154659b94f9261016a0acf8fdf47a12a9 +5ddedd88e338592ffe6ee52dd5d802e8d7b9d401248cdd341d89387207838f7a +3ec6e39a2e3affa2d98ca659a126b3138b5dd1e64238c320f121f595975f7c2f +45e0a83972a642e2d279dad8df1e26c15205e40a054c1f8f47e4a19df859e060 +ec365528180f6e0ea211579ce90a83d72d81f8815200f0e47cc0164c7ea84e32 +5d7d0f0e7daeff099a2b80336c6f0864a41571ffa7f0f9c06b80e00305b5e6de +e722a24b8ab8a8c842e3c5b61ac921ed31ab29dd1bf4172d5f736b9b80b8c7f5 +4d9b455eede1e499db9bb2f382839ef7922867c6fa734c2ac7ec010c6d6b81c1 +3354a59aa502f50325abb38b4be61bc2048bde4f525da48b99cd5bf849f8b002 +afdd66de45ca6cfd1ef420a3d506cbf51cef5c033bc23f79516d7d6c607adee5 +bfb4dbe6a752874358f8588dff6fb5eb12604e1229663fe5e600043a2230311c +2549cac22f85a0aa464d0ac9d181bc4de118a7c0d3232a553c80ecf9a5c37a4c +87818445427fbc0d8c57e2871bbd47ac1a0e83dfcd8a87fc17962e80c6c6fb2b +fae3a639e4d1b526aa0f3109b23fc50e831c3b790d7f5976d593db0db861d4fe +983c5cacae717a660c7a7e96f097f2a35bbf535e25627f270d305d1d0bf8bcbc +ca577cd64aefb186bff79ddc6dd0372c2ed351da16aa4f284047cf2f34f18e75 +cc6787333047ec7fb6894049f2625942db647417729d726c49814900d9f02085 +90b5343d488be07fbd18d5901facce3d0fe36a0902d5291a706d0eddf6012f50 +857d064f1a9ad5325aa4281f95c553d7da4d28330ba92025ba2de11d2fce5ab8 +a140b0c8505d5b70bb175fc2b95e612a785191dfea6d6759d9897951d8372750 +161cd05c623e5789d9aa4390d883779b0d9c79745cc9c9fc4610609e764d236e +61321979a473005ee8c9d2df23d5962f7fd1b447d580b9b4ec19baa44e14d1bd +0b62e7142cd43457448516bc725c5b714a2441125c58af63e0df29a3779953fb +81b8abe1bcfc5bc341cab609ca0973bed1a6013a48509080851b444d4e64f378 +89481e4e2b55e39e52046ef3aa1aeaca42e15f59845ab9c5c0889aeb4a672d14 +a5bbe9e566056af5408df596a0d950a29c88ba5e0654381ad22af59fcd95ba94 +396b93119c1eef03566e77a09d2a1dae2e89838cf076f8ff1b8377be1e042662 +38aaed91672f8eb1325f1fe468886ad383489e1a60b910148ba9f905cada719d +461a9c066d3020ffeef74360b07ce1d814a3f6ed7c272fee322fac716cb01bf9 +a230c885d1aec213d634824d6f986c78e5565a3ef4a6b2504d4795b021b7e3a9 +245bdc0c8a41489a96310a957dbc82bf114800280c8013af0c153faacbbbc020 +52b88f180f6f54ca210df9b551c6fda21344b05caccaee651f008e2f28de5aed +5a7e42dd459b3ae39bcd0977e7ba2119a7a3994109dff489fae509b5cd1c8ae3 +12844f0034904febab7963ad55015b9c0da446e794cacb4b7481bb3475f8238f +b94f136741c4dbeb2693df562beb0bdabb35486a62b0582a616f4e03db579662 +4cb5365cca7273244c0543c9b88f8352f2faa33487d6889285b08b10265440e8 +bdc3ad9efea1cea534864f390ba71e19d892a24befde42ce42dc10e1a6c2d66f +13bd4861a718b8ea0eec18cf3e2e73ffaeab593fb6f821c81ba9481ed3c518ec +65c55960681e7b02cf4711709704f9c7d6d6cb7d0af7cc878755f3654df3d9a7 +916b125224380ceabbc611577835a8c8ce838fb6fd0c7c1ef7a6f182e77fb8ea +5763fd9ac05d7935d85f2a66b76d98abb3db4927beab67022721c708fc2142de +0ff6ce5d1759f90c985e53e594ce9bbd8bfb1479f25d5fadefbae1693bfb870d +877b09c348065bf755a3f94ca1177cf5e0f9867b7afbab5630dee683c4014c4e +11051696760877e40f58df8efbcfe4b5b2f11794444559a8828e482e0b1fd108 +be763cc7a59f81929e5f244333313dfd77e3b10157ffb9e7bf8ba78da5b6950d +00d5b465c7b8521bdceb7757e28460969adee591946c3b9776f09046e1a3c89d +1fc33a1b92e4b86c283e5640cc83e1ace06ee6a3dc27e0eae9ad810ac44defd4 +b8e95d6fe1d9f643c0c461a2a3ac392eaed8e8fe5f5e8c6e56eace4e9072214f +991a769892446edf4b46be77c8923276965d8e42f91614adba885708719b9468 +5b21cb377802551608a6fc05a2126600b5be647d84632d9b676aa18e4d4adb77 +445c52577c1166088d4f565339fa93dcf6af49e2626f8fdf24427459a65e37c9 +362c873af0bbe44688c0782abb02e4e7f62ef9136566515ae944d7e1a86df46b +fee8d1412383bd1f2ef05a9337d4cfe04f7843d118d67902b6ed12c2f5ec2d9b +8a32c7340acbd1502e0309b282fe6be8d588a8d77da5f5913fbe25d4862cb9c4 +a32f10e0b3e8b1e33a08b48a8f87b63bfe77299a7fbc606eed2f0dde20380de5 +45be88f6325988f60634a9cbdd510172a744229fe884ada9b6199348976cbe18 +45b60f0141a27b36333ed7cba6a7178def83e2765da5bd5625aa84a7b2fe2ce6 +5543e7ea2e106cad4c58f1ee31802ecaac06897eabb1cad50ac2275141e29efa +25ef04962123bbc472175d9a1fb1c5526f9667fa32840d3305a07b37b4bd1c8d +8a10c057b9b44732e8b452cb9ef161f4747a376bc34de0ce1247e273bad1c795 +91d75add205842b56bc016e1032bdfda5ddd59cf52b6366c18f31380343e04cd +b72af6f735f38961c4f149832eaef49202ac2f4cd458837db9886d564bb4d1e4 +fe78d20882d6616ebf9f95d4fd90ca291b62f2db006cb462be94aa93f8c62f7d +c43910a0132a84a4c07fee2aa05fecd83fca08f6665b9a86823481e144e38fff +a096ea6560dc0ceffea5097c0d8c19b3775e10bf2c45eb9ff4d32625c22c2a30 +e1a4da703e69b640179b1c0cfdd9ae84bafc8a955f9cd0ca536a33d441ba1e65 +3439982aeab578821354f4717242ab793598bc01209b16e17cff4b44df6b61bc +c7aa2f3d616b9f7373977e507a9022d781182c971fc1817a4aa4314a7b99b54a +2f7affe02a0c77b156e082a6d7e06937bf50437af4c279f8aab2e89c3c794525 +ae6eec1f8ed02b1518a39d24810e1b1b56342167c3fe487f8841ba1728c6b062 +a93a48acaa9652e9e05a4005c0485f180c868aefb7c0ef4e195a07759b765aa5 +932a1eb8e03e282f8e0354b817db6e08bd562fe7a79162eaa08418efecbadd76 +990f0ce9b5947ca5138ec811c8637e525c01b3e0cb517e00bd556e32148cf5bd +a8b7cc7f7adca5c45db4e40902a68ed130247a5d735ae6b955a699f6c499a34b +d2a26a77b01fb53f787005874d6c74cbc5875abfc4ee6bc6715d160dcd5df49d +fb1e69d31534da4ef2c4869fb9d872c66e7e9879d529707ee414eea66ba69f54 +b6b2a5c1fe764fda1d7d1087b2b900b5b3aa1959321a1505b0aa709c70a4815d +e7ad7d14a37f1d82e4e36f33062fedaa3536c8bc21ab8162341a286d67947245 +648bfe3b4d9c3fc156a1d188a535695add00a84c868d93a04ce3dfce5081be97 +7dd5a65f674e2bae7ee174169626d1ef469e1157e132cb29001da093e1aff1b9 +5875ae9804748ad1d1538823c57991ee1615fc624fe33ca1497146218ae0e27b +3de8d5d9a489dff8bb53f00c8118fbc8ee4d6d02639a015a21b81f549ec8c504 +7075df836d07765f45ab840f0a3443055de480dde9c8bd111e20c0c2c5c50192 +a81f1a3071338131bab28a4631eeea975941c9fda0ef03ee7ca55ebd3dd20e3c +5cee8996e044f9ddcf5e0682215fe017356af14214475fe6ff22a58b8c3006ca +53a351253dbaf384f2a0c29cac3da0b4484159df1a4aac70a2e57ef9a623a132 +7c2b936312f52b360ea792cc68021e5a7408b00cfe1479013925b33ec2a520d9 +c17efd0d223ea60425ddcbb117fa75fc7ece0ce1550e3d3fa6a6aec57a2d2399 +f19271b39bbb92fbe8e59d0485bd2b1601d0f5ced636bb8a15c643b27367bad3 +7f18a6e6c236051f4eeb0fa48890bd1d430962980a0222cb134bfedb276bd0d8 +4e5d7e38f2428fbd752b05f12ace3075e31ad4a4d572318abc7d888c1ac5df3a +ac240fcf1ca37e7a1ca22bba05d3248f5b1fea2e0968dd438eb7cd97665e83da +70dea0cd94bfbfb5fba03144bfccc8c0c06ea19397c7be82837788e662606b5f +c9e330b753980c9036e93e77e00e968f94915ff55d12bb6d1071d90377ad4bd1 +b60537600314ae42582ff4aaab236a8b5a4a8025749014465c2977f90cff3fd7 +e01b3c3c79a6bb1009d6e4a403d31668142bcdacb63a60db63bd1a2b0f99a2a3 +0ebac082250178b0104469c36f626ab1248d44a9a2b8670b5b63d7a7f430423a +232246759edfd2bb106e067461ed77153f7ab6d79ce3c9589a51036358581062 +3cd58c5cc651f40e8838b684f65c09a945fed032efed63a5e4499129264ff25f +6663435b49c0b988f33be63ff22009c85b0b088e114c189cf70e7d0a5673000c +c74ce3d432ec454b3be66c700d93ae69c6c53c69fbe681731bc0b508f62dc4bd +6dde2b1985993a1d06d9afff8807974fc44fb45c5d1104df3dbfaf9d83e8d664 +9837648dd0bbbd7d3643e5f59acf57eca887f8a43ba98cb2b8e2e3c02872c70e +29ee7fc165c890fe15f516a4701230ea3e3e9a3c0a21e05ab71382af7278bb16 +9c95e5bb7e70b4f0a722262332acb7df42560c9acd835283469967f61b114ba1 +7e1b29a4e851a36255e36b84e00544f92d8e8595ee847243c02b4dbb8af5afd1 +8e7cadfd9ffab8cf8c565eeeef57904fc9e6c74ac163e39bf7a7b11165ee050c +ef1eb8522c851a056395a5c9fcefee0655fae739eed7782e6dbe742251b19a3b +6608727b46060050d108e0af2d2618e6e3b41a0df0b8778e57a6102875ec1ea8 +90901e138b1d675d2a01e4d2e3f83f8b658e0a9da2ca51e44f4d30684990430a +462ae89523919d1805bd3af12e9497bc680a95b1550118b464e79344cdc220e3 +405a652f072dd6fb8c0b8c02c06dbe55c0b42a2e77a8515786a90c4c8725a2b4 +951f8348468cddb1404cd840ccbdd304bfc62c4a07f70e4927e6ae98f96ffca3 +1004235a571758e6956efd46d32e31a750aeccf779578f738e43c131cc807ca3 +338c46badb33d7733957748fc74b51ef22c13b018331ed05c2addc8b723c668e +0533a6b983e5974e9af9f2b16b5152a4a4429a5060d1cc29788436e18b0c03ae +5647eb8b132578df8e3776201597e6da18b55162be04e9a08ea3179cfaec5873 +3283b6d844975abc8cbbf15e7432541fe41c7ab2b59ebdcb78a987234cf54c17 +e1d3aacb3dc26d45e50549abf8de12d5410e90333e6984befbbebdcea94f7db6 +3deba616b24dd013c3586ca0c6c2c980d8cdec2377246ab97e968b2b6b2954f0 +d1357c9b6bdb9ca552e4f74d0f370c3301d7ccca9973e36d5faa284d0a7e4686 +bfece1356ce2efe1072d2cb25c2cf912c74beaa3e3543384d2de41bc9acdb222 +743e1a54fda86f381d2f243fa9c51bf18c885bffbe32b2a6a2e3d883274d5319 +1bf841f3a0328cddf5b120856ab45177875b711e4f55dd2a074129701e4c5190 +428ed996562ec7b33161f8d043ad357eb007f88922518e0c8155ff9cf2087783 +4d876a777511928cd8d6fbce99d8910e40fe150ea31960f0932215381c8ea903 +07140f74313d9d6fc2131043fce65c5750f0bc1b7e47fb5f8c73609a881b803f +98f49e0f7328e4a2aa65cfe8db5d7451c869abfa5840ef78d427f0894128ff13 +e2d40fd97832a8c54463ce6673e5179b7942b4ca313da46fc984ad3f055e4403 +d721c36c8eaa781541a7f50362683d0ae21d1ca8cbe77ae938f4ef6d254416ac +b27c310e51f7692479b2c2e7b39802cfad847427c03795db5d3b7d97ec066eb5 +a3b7adbf9dd66f73567c9c39df064715a716c5db61361b5c2df5a797f9e31bf9 +ec029b666d48f3c54e427844d510839ef14f628c3db0e2e1eb6e9a86b6978cf2 +8e4a53b5252873fcbcf7f3e571bd36fc6658f3a5d117fdd06426c07d7cc670cd +753aae52eae16a3185525b1a3dc18c04264759e36462398d7e7e0ba9b609b2f0 +2e7cd5fb1abe7b8abc64d8138a2afe08f9412afd4b98e212ad958bf12965e619 +64f121923f5485c0c05bf2e8814c89f04cffaee2d1dfbad7fb679e1d3a3fea65 +d46d564cf8c95cbef0a7fa59b9a6e46c455d95d396ef2d89462969b30b43ae0c +d395ee09d0602c66ca6169ba099ef54202ffb28c5cc4a528c30f9f9ca910ab46 +bdf9ebf91b238b5db3929dd1b3f21bf8e4d6230abe740e882ef877791fe62322 +3c0f553589a19ecbf5ec49fa283a3818591f8602bd2cf8a081a64c920a3a7339 +f4c744d91ac5c6087ee7963ad78c6c7391c0edacf2c4a4647ee528f9b052613d +dc59f4e6f065fb2c5a8d22f8286c8942eb145cfb9691c453be12afacc93df77d +744b6f87c5bd21abfa92436ee65e8ec1a1fdf949444dff1055586d05e9cfd2f4 +c1c5848b014ab0489f900ec674eb934aeec65a7bfaa7d6ff77d4e92d4e219c5e +ae149f9a620b17def305d5b46a08950d258b05781c790c3c5404a004a842f8c7 +008494c5598c8115247c5afbc6abf8ff39f1b26443495eda2f840248389b972f +c8b5d508aa450ce60d1104b6044cba2aa07bbb0aecff4370d643d22f0a66cb08 +aeb47ea20346c8989d4f8b1bba75a1950ad6db6c60ac2726b35d3b5aadb04901 +97755dffdd498e9fc54d322c041f7e69211e06d5f92ad4fb1605f7ac4a36f5a1 +98d9c97c429342355c2cc990769626d5051d298bbbdd58969aba8c1237a78c41 +96f2367055a46d6c31795c317c67209c975c94513e9176b44d873bba66b0d975 +19e973e1738ccd2b7cab053b4ef7b1e5c0b5f2104f339c480953ce05a49ffbe5 +3149da2ebdaf47ccfc2cac057f58513c0c4b82482bb0b7aa0fd58f5691a871ff +9b53d2cb0bd092d2b63ab1536b522d39feed0906ef4bdcdcc2cc4c21a1e7e9b6 +dc665503a15c7e7ccee7c039470b584a381aaae9fa6500a38074daa357fbd746 +fffddcf9d56df90660387d0b2e9baf9fc9f1cbf3595f92703e776fbd32898206 +61df55696ae256d1c48ec6a3c874aa81cb9ffbe8b3b7997c15744a0916a5a4e5 +dd759822dee0869fc218f31cad84a2dfc3d11114beee3c161e1aaec661995dd3 +0436cf7ae4009015790a5fea7a9fd8a31e963f661d9fbe1af16666328cf741b7 +e9a493bf1503f8fdbc7c2befd4a92cb0bb88f7e5e09c8419cdb25e9554bc54b8 +b4ff1fd0d24735b2fa1acc00a62edceb3d6212aeb071ec4565be6486535a82e7 +16a58a282af8c38a04862c6a62600f957188a118bb365abcc60be3f319d4cd8f +8c39f5d1b6a37335ffedd8e83d6ac433960be6e72fb2169daf1b37703e2ecff6 +74fd1bbe40d42b89aabf3d97303ff6038ad34b34d3fbc8dc4dc17134d436afaa +4efc433643891c24b2c82f597b0e7f6e3ddd230e6e46115591e0ce37bf0b6570 +f7c5fdd27841ba05f6093777c8f16763d3fe33f1774caaeb34d740ca66ff9f3b +741228e435a48e8728e10a029e61dfd22dd60b76504a0da2df7e05831a1aa1a2 +71f928626393e1c65bf4cdb471a0a12fcbc6d28b2d5bb51875a505f9caec67c7 +e9fb344c92a3efe246f4190605bc243524644db6c03440a7fbd9420cb5bd5d45 +865132b52aec7f19cfc212585adf388ce8fd3b85181b009a9a2ba0d4a6d5d046 +73dbda91b2038eb39b4ecda24f932b33d3ca112748206f15c991aae3f745222b +b6a51bc3897134243a22a006dbc432c00e3b008918146bc49ca27cce9ae3fb34 +3e684ca188c3233522f23e880a462e99bd8f4d7f5fb1faf075e290be2d8897c1 +2e578e0aae723660f88c1b5a8d1a68d2cca9f80e652a76fde446f016e60de2a1 +8892839936ff385a8018441e993023c1b0f63c326e77c45284b1be877b4c7cfc +090cd2e86a20490fa23f477e86f3d045bc74f2ffa2a441c608641455a3a21e3c +63ab1ef26219ee198d02ab650218f1239b769d0dea2c94bc2fe7c237e5bba7e3 +d97913fe7bdcbe81342219b35105c808076971017be1734cf6059f5fca481882 +4ebea50a382044b96372ed6467a1aa3605abc889bd40cabf805873cee42ef2cd +92665af9a1c50cc531136c91bb2b17dd4f853434cdff6b379ec4383bdaa9c706 +c66c24a5f57bcba69cf375eec429f7a0f59634019f2b224f1d414e90477e05eb +7de38a22267d7147e1d880bd05f1444b9aad4da90067006d4ebb9f7c3aa8a3f9 +b17913d2b56b9c16d92d2be3195afc9773524ee4088248e71de06f91bdc858e9 +b1f7aa6894fd2c0e97c4a77355e825d9cb3bfabe43fce4d64f7e9d6b8c74a97f +532cf8fede7a4a8853ad07912371cdd9d78523c62adced0025944601e02a95bd +44b147b355a31dd1fb35ea2aa152e52a351e74cd860a325b4309309612ba0e7c +2636ff5112a52cbb8256cf537cfd7030a6bea1841d4c33f82569d0240911d153 +d1d5da41b61336762f70ed8ceaf9caef5af83385782ea4e9cf85344d86622963 +80ab5633b80826da9d3f3225f1284d338491c240e5f78811545db0c5431982c2 +1cabe4f206121c0882a0ff49908cb0a60815e22b614dfa17372a7a9fc48afa7b +28db0af1816cc2d1c0f89fb6e18c86e7a849fa837aaf9809fab92f2b28f2cc2e +ddfccc31fcca1295370d34b6e0acd1034ee4b7d95722d45b1195ae09f46432bd +b25e870c2c46bafa1d61bc1ee10fc28333af358ac11d39f6ad8cb2f4a184f48e +4b8422e64a55d346e82be62c50e74c092f8fbe320ad008e5dbeed50186d2e3bc +432152d95f38fab4b1a7c4b5cb6c924144c056928da4f60f88ed172694dab9b2 +83ef92e62906bab03a5b07e5e0e3572587ac771e8f7d6022d7f821494415c244 +19d752da2c8101b1da0b3e8e39ba22347643e549b81b0bddf5b6c43ec8b80db3 +5c107b7c12b77c9994360ee9c1ef243e41bdf97ee2a5e930e75b127733f5611a +5a5d418369d89a3cf9a2c8dd3a61808c8329e37a2901fb6d96bb5482a49c89cc +5918357ff901189d2760afb7ea71636fe212897481d891bb66375d87d98aa320 +beba9d5eb4b2c742f8fdc031bb571ce73c99b2e697ae91764b53ec680cef3a91 +f3d6d662eb4abbed7c7671af59a0f7019b3dbb6c72d1473d69dbbb00786d69b4 +39aba3e45c84aed07decc7ec4611ccb146b135f92556b594468b6139e6f59a5c +2ae275f970f736b55e5c8a20a9873161ec30cf7ae7c1a2e61daaa8310c0d8f82 +705673885da42e360d1594a2c2f25359f6a666931fca6bdaba25c25d5db5e649 +1128fc66f8f3aa3ab07ad57a1ba6bbdbe264f1f0885c15dca646910aace9c3d0 +01e466f128a7a92846c544e3838afb98e480e53fb0457a3e976c0a6b831e28d2 +d51dd22001c93e25da4aa99ad822c3174d78ec4a833cf489b9ffb9814d4b1876 +850277ff0c9749f1b194ed7f16b7aa506c213ab2cecf031fe836190c5024cfa9 +0175ee3b9b9387c4d1e76ab2c77406dcbb0e3378983b688ae583c1b476d8e243 +a2d8f00ddad5277b753467959f81603db2cede11215bb53f7a7d379e670bbd59 +68c2c1ff4025cb92e87e1e3d6543ac92b153e24631645065994cb9df4e45f716 +f64cc5b364accb7cf05e53d93f0236813f60f36860b14ee83af7a394f27f0198 +0000ad844984a2ea18de70ab354baa678ed437a78c48d82f7f4de383659227dc +8bda2531a800a34e3b19e5ebaaa71b3f17b665665c76c2190795a70250dc6a85 +5c27017c8a7e0768b01c979049080abe5c03dcd3f6627af8b561790f8ab2d9c8 +f3444f14f173016f4066d165cf2d19644d3b10cac3c1681af093010d955f4f05 +18bf0d4bb15c83db373079545dcbfdeec54e4df1de26bf8ad49393c7d533079f +ffe87f1f5973571bc2f3c26740bb3edff596e48f7027b610d8297905a7702680 +88828d4733a63f54f183312cb2036fbed1df6eb0560d8df038d0937836ac6835 +861f8e4cac607688d517e5937385caf9f9b96e08bf9d3f83705754761295d8a5 +bdaf8776b31f64b2c04433eebaf19b15e46343d3b879956cf2dcfcb3704bda0e +79af14d781ee7468730f697581037c421e86ca93673ec7cd77dda77fdaba7244 +42c629d682dd1435a66aef57d63c6c5a93794a3ff1ae329272d6e7ab1f1e57a0 +800d1eeb04cba7aeded1d4ae9fbbf78d7d38f7bd31e0b50b2521f61ca3bf4048 +245e98d27b439fee588924d13dea49fa2f53ad8581ecee20e2a8fcf74e1f89b3 +480172ffae755dc9ef3eb30995f7ef3ffe4b73e69968055785ea9d9562e9fab6 +e6414c1120a42e49562b78e449cc61c5eddbd428e1f63f749cf4416a836c2018 +af4560c6071f610b958f9d4176c81856f8252f0b3ef625cf247577e401a185b3 +ab9ffba5a763cd9612b877a52767f1d01b73c49961085d86ed3621fb1478f16e +226a679bdfa7979593ce92fbaf5c463ad163fc1e7e67e7626efefaed16dea9af +198b06a7042b45561be8c69ce85f9ad67213bbf589054c5fc836be20a3eec5ba +df75736a682053bc4d75f73ce5e6168863ac682cca4be41d7845d5cb4883548e +bf36d20790e8e5445df6283cb41a86cbd3adefaf2f51cd58ece7fe55e32bbbad +b4d6a962bae556e509ecf9d98c6bd490cfe636dfd437082346d093c0f89313f8 +7309c697dd332a4b82f340a129027bf504b32e9f711a3fcfe1e300b794699d7d +d45dfd89e61a7ea37371082923e76aa992a3b57f5263d7ec4a71a8e06bbe88a7 +598aa6422ecbba39a6291f940f51011de5b884d96aea72b32feed89d03c55b2b +c90d2dda93bc6d1d72871da9b51b0df786983367f650eef5891955d1e0646051 +223818c24383edd6674a362647c7f7210bc045954b5c1d53d4e98e94fe8aa214 +e55559b115dc28af1764137d10f127868ac7409719f3ef317f75bb418bef8b9b +71190940603f44a7bc6ae0e03f43a52dcceb93fc4ec6d63409f86f73cd9293fb +7a36c3a5bd854c1e6cece0f925864e6a17a9d3216f8214817b43c5cf5fbc6fe3 +03692fe1b142b382c561cbb9018b219e2d5e2e03b05dcc6942adf50f06ba0722 +854926d41ab3225dfc944f9f1b42d5da363fffbcb6c28aa22e88ecd634de217a +a7166837997f10129c1d4877e00d5488604b15a66cb4ed85ab7bbc922a23b7b0 +fea6f0621bb5e57cf06cd1e56239eb63f6c6ca958a94edd192efef4e96ff0e26 +9413adfd109a813b39862574b09dbc78e357be557cb0a5d7b8e259954a07dfa5 +9b42c9c82566db47ec17091627f73024131e629abd79f804446f87f5a956e94d +f4987ec8e2606036941181add7ce236b005bdf8c52ab816c971ab141579fd9b1 +9805e8f72442ad9afe690f9574c1e749726c083f6282fb206a9751f40458cb38 +e0e50adb0fa1f67ee19aeb79921c6bb1de4d55759951952e6db0edb8036ece0c +dea8457564631deef2ca2a3940e30114f73332573e602fc74d97b948a7b2f66b +728c96091d54788bbc995ce295088665a31dfe4f1b8e022cb7ef0b8c851bca66 +c4d2447610ab2f8de12bc955142d26ad71a5dfd38681f3a0591e1854ed535f49 +53486d7a7b416ee24a4bdc650f0bfd14871666081bceb7a3a5417dd52c115f37 +7a419411e70b7850fd2904bc5caf6f2aa9f2d63a4e16d9f8b09fbfe5f7795fe4 +61ec0dc2da6d59e10b367d7a2bfedb8714cfa199ba32331247ea553dc686c14a +c707b4f187d4315fbe021904fd8cdc487bed06edfb44d5325edc400fb28744d7 +40d1229541a870d002e99526866b7532d6af43c82797255e4d367a1dc2971f9d +cec641a9f09d2334c9d21edf7fc3cbe5302104905febca894defee3d673ab1c1 +b581f91841da7c3f6e3cab8051c57c1619a1863be9dab596c97f7055cf6cca2a +4f008b8772ebc546dc5f7c10b89d7b211d39f6d3717e5ee30f0e22bfae00dced +67c570a34d46b0cc0b31fb89657e5bfcae894a0472555ece5c93d41ab84c112a +f40f1a941e51fd16d7e62539ac3fe3d42aee225ed18652a8301d72a4873d80f4 +accb7652ba3c68765fed15293795b3063334f67626233f8dac67b65b9c80ceac +d1c9ad88b9c943463cd64b18c3fcd6869176254b2f23b35088cebb46add907b3 +6a800c20a180f0fe119a448ae713d17e359725bf5d859a348e33e9a32ec5f1cc +9f111fe3770fc6b6c42b39620fc8d12ad8aa40e2b0b572ee6aeb01db2698b21d +efe870a04be8d780399ab2e82a6caae5a6637f5d4f89fe50d0fd377005f4d514 +9c3a91af653903c3e7c4a6221b98f9ce74a22e72e3bee031582bcdfc9f7cad36 +dbc9b735f615edcfb499cdbc28f3127e2bcd7bbc1ee51643b49f3bf88a791df1 +d5e8460e86291c74b610eb7d9285f740325af7222c1e436a337a2a6591239bb9 +4e1daea7685c598a89963b5b84eeef8f1316dbba72bf4e37d752c0a88d031c39 +99e08f2c7af93a8b6d33f149dc699f79dacf2aef7b5258dd24e8047ec3094d76 +44d1bfd65247450b7824a8df2fa8d8328b544b62508ad3230bba77ea8c141112 +5e59b59e325fe83cffefa647510956fbb669e03aeb7a6394d7857f3284089bff +42648498b60dbca173f7b1bd6b38f30f146e88034ee9b1a88cc78e24f11de5a9 +4c62ccb0e8c1520ba4b09bf2e18450c0f0074e70ddb8e12f53f3b3b72a80f445 +0b1f8f007d4123aeed467baacf1cd68ca86a2995716c363802d3dd11826fb19d +8ee5dc41fcb05c9a42fb5be36c99113da155df9bd1a1d6cd5fbfe976518df999 +cc807c8f96ffe38b33c70745abf4061b80436657d5d0fe3491383267bacfbdf5 +ee391bf5d2ce07dd40737847a4773d8c2bb9fd97cd167a98256a48cd8d49bc7c +3b82943c5a18b029775e519154c0f738d9dd27ab3a8a9aa54b5a623d81b79678 +bd77868478087fa2d01d69d8194019c7df37159c0c955c0997552487f9caea4d +801e4ffda5ba8b1c5e286e636b3b925ad077b6c3736e838b62db74c44d18d42c +102f1044a52b3f6aabfe837304488cd4a7f4bb180081ad29f19291143f171d74 +0beaf90c5fad4a34cb1e8544518cbb0c906ed62dba904dc075eea9d616e042ba +1bb6414eba1d6c599de141773e9be2f6b80deb92592061287f4e22a5fa3d440a +86515a468f8166efd085b9d48c193b262217f10d1221fda332b45314e189917a +a9e58aeb016c8be4b63ce93ff13861b225550852dabc50fc0b8b55b8a8799a30 +eded52a1fbacd7eada4e73d273bf6bac8d34d069224e6fde5615473b377e55a9 +24a626cba22865ee57aa15f2ee76893efd5b3cae7a4db707d65c78e034796373 +2eb2d0bb1528537aac9f37fc907a80f300ff904b06cfb464a6e357bf4ad14ce2 +cbb004d6d09b2a1fc445c297b9891c87776303d5bc4f7b57c687d10ad11218cf +c767ae040993a92e62b252c28d9e960ba8aa03ffe0998b87456e3560b8afad25 +5dcabbfdf73d7d88a69d0ccbf0ad078d98f3e76a0c031149fdfc8ac9ebe9e7e5 +5bc942f5323dce3533bac5bf749096c7d6bfd308e688c157f23252a1e699f213 +f81f49060e3723c6da5147db2b6f6babe97d229ddd87b2468305191387668769 +a56fb1fb755f3e70782a3b1af9998eaa3d9119c3b00a867241f6f896c928aef9 +480ef59a81ee88c62269a65d0249c2fa0f8fcdff8cd23186eafb8c52456594c4 +6dd20aad4d5a92b82e552a0a2624494b3c59935209ee105670d3a9a9fc6823a0 +4953c0b5c68c8d39973791109e243053f124a3f43f1530ce37f262d36ceccc78 +9e3f3c5780c4fbfd5de919db66271c528dcf7bfd275c68325354bc02fcce61dd +e05eaf1ce5826bfce074f478041ea4d3024642042f7522f65467c6978045c9b7 +1731ccee58a591b02890d1065a2ebe4b3d0ae857b7425cbe5690d32013c8d868 +4f5c1e10f224d430e0f0e397edbb6406e8d55b12496ecc2897dce7b3cdd31cd2 +b464429dec6b61095ac9f91cf942cd8114128de0188990941087d45cb6dd3551 +fe96c002743fcc4b61a52193f7c9b66a98b917767eaba9c664fad69a152648d1 +04b9470204061a835d506a0c72ddd24e313b6b97eac5dfd14c7d77dc5e60fbc4 +3886af76660991b8710b997b41f784b53dc026c45f1a691249c9effdb798ab21 +a9cb9512bb6535defd3281decdd31490e1e905fc6aafb4945562e66b83490268 +ee9b465882805806783c958d1c0d03411476c5ef29f6f17334d687d6e1e1c88e +d0edcfc2290a6d55b642876b29aed1cc922fafc85a308dc7dcb5dc6a91811dfe +5a6b254f25810565b2e765cbdae5f31a252253e1c7d74ccecf3692581ba8b00e +93688d8ad5e4ad06c0a2feb689d1bd4257051c632d1bfdd0e1b69546491e1b57 +4d952af863c2fa695a8590c98157fb02a8209c29cbf223d61b9442f9fafe99bf +70b208a982df1dcb3a688209e03d10b7ff5cc3dbc0472e9cd9af762678019a36 +0492a59f8662927cce598b2a9a3737a72160ddfde2fec825832302b8e128d612 +4a97e53757e1e34b25ebc5455adfa2105658ab328087718e67c157336ad48796 +eb601d439393846747dbe34150b906411540fad9ac4d7c293ddcb7b8b53d6324 +b9e65dd68859fb70a71e3f8420030c5ad5160b3285cc13409b0dd58eda2c2f07 +2cb0868a393a134a9560298659c9a1661dd007b053826210edffcd291c942ffa +40a3e040204424d2b0fd0ec50ab91e4d07c64c23b5ea65f9355ca86a0ce4d10b +61e7e9f63463440f770efa4251ff5e55c7e97bf4e8bb164b8e69545668abe4cb +ef9a8add18d2415558d7228a8bb3ee62bf686e6a7ddfa2caa244e8366a992583 +d4b68ae572ba79fda7a2b5981559d372978912786d3e7584e192ee3e2508224d +a8c4b41123486f5d1f9bd153279cbc0d6a211e988570490c634ff4ae26b6a1c9 +aee78d65dff7d3d534522648e26cad18c29b7f1bb71c59a67931b619bbf4ccb2 +cada094ec149aac8afd198149cdf679ee3f65fe7badd85b801ab64863e294c11 +9ff4ff265611f041a672734c83bfd7952b94a01e8c48ee82192d4f3a7b082378 +4bdf73d423ae41bedbe7388cc84305d048e22f5678b2440ce1928fb9384775b9 +91116305394ddb3d66a1c7a3a0b4f5ec9ec89732d5c6c93dc1bb73702df8c523 +16933f0474c6b61c6d0198bb9eb7f537a6f138daa9a6363255f3b4bfcac82b16 +86d72ec295f298b5b6897017d8c2cef535ec4a3486b8a6996af31283f1d0bcd0 +2c24d2062b94f05093b0d7f27b74c98e05d265efe602996b524aa0a360592101 +6a9ea3239dad37915227f55921c7ed5fb4969217137fef1e8576fb82d274c69b +dcc3d9d868b4bc76f08fc7097c539230c1bfbd9b61fa268be5d354f826ec7161 +a414ae882d5ffaca6c7e08aafd6cd7eb40ff30ea9784c30e2f5a7832544130ce +9a524039777003e3d1d405940e9fdb64656372b18ee57df90a5ad00fb311ea96 +ab0e383a10b03869bca603d287a815ebff72c1ccaa677e173bbfeb4434c579e5 +bcd2271b8438e69edde033f502e96403a8d697e2c102a90fbda669fd5670e108 +f79bd0252186908d0d09acff3e8e3d41b48dd0ea63cd87282af53a55166236a2 +c89be70db782434f1096cac76284d05f6b792a5994951fd74276a2d22b907528 +e04b77372e8277d7400516a83333a56b313c33ef392d28aee8ac5b0efd0e64cc +d778730eea922b8394c443c154d30b05b059d1c8ad63b84dc269131f0750b4d1 +728a5cb9dbfc3d278815313b6be256b2617411b8c8db73c24fb1fadfb6a04f46 +2c743a73ec4062b8b777abc4a87dc517415c97631d3800f95600d4f7c66d518e +9c6c609fac65e636e17e73daf3d9d79241b83036028ac1b461e80725addf9d73 +5c1af28c53b1810dd60e451e692680846ac32e892887fb95eefddb6d74d4079a +1218a5b38c704a6f12a525de47631032c03f62901f3be9eb4c3d5717ccca71d2 +ef067677527e3058a6f6fe67ee3e46cf261af808731ebc5e27074af304177035 +202e188357ddab495c4c52ebb05f0c24e6670e920370182f8921726d2485d4d7 +ad0e3782887c5d1f198fa818917286f86434f7d854a0b544e3b886da8f2a80ac +b2d6deb33bf7b99da69a36010be0ca395a3d63648ba4a6bd2a199d34b34bf187 +e344a29a3c6f55e4d084703082655ba0f06f6ce0e44743b09f005236987e27b5 +4460fa181bed4a8999b5592ac20e099519c94980812286042606c90c562be1e9 +9693d3c8eaa609b63694b2e78ccb8aaaa32f59941f22612159a45fb8f1428c85 +71f6771dfa5fdfacb7f2f8717a2f97ff1b78ced9a81ebc4d395ff56df408f97b +967991d6cbea68f798d4596177d0ba76bb8c5030158585bb2a81e84ea68385e6 +18668836b8212f4953b910d70a94f5a929946b353adf12b03a68762b4c02c0ed +b244993cf912f1141de141b96b6338b9cede7766b2c4ac1c3731767be70581c2 +3a84ef8a01c7de2203719568e88b5fb8369b7424992b9154050182e45fc8d701 +2c359bf949a8c570757b5688f9eafc6c55c63cb525d7c177e2a300aeccd9a64e +3670d4ac535e39e209f123277c30c211cdfb93dc5c0e94d0ed393c9065abc78d +1fe648cfd6f0931e2cf2b884bc27843a53d197b1dcebc547e5ab4356bf35ff3b +86e673c92badb7370ab9746f560b0edbf41b62cdf79c5d589f17edff5f7cfdce +5b0ac5a4216b1b8e217d1a9ea53a49087fc97a4920e739938164f45877e1e0ef +20806c16db9f5148a3718859b7fba187c06f78954908bf50064c4b94bf9fda1e +a3f70467261ea101596bb21228eb6ed9dd126326d7bbecb6b94a89516daf9d01 +faa69e1fe5376d4030e51f18bf9aa0c2a9b87cc969954cc9720081fb0eb0a72e +b18e65eadda42354ef61f0db46e7cf55166e4213bb2b1627a090a324911c6fcc +d721263edf4e5140be38a892a07c8ac9cef90f0fd196f34007d3390a9c9b76bd +8a20367c050fe35a1b7d3d8b1265d44de1b6d24da58475acd88186329bdb62e4 +8270a57deacc9f1bb5b7432df1d21021820a90e5b508cbe133be1d6d7ac31652 +3477214f0614685d24a15e6b54d22ba2afdc2dec0304204fe62e7f9a17ce9846 +d21dc23f38127a6956ea2c5c3a028d6cfae6e076774f817cdb17b1352e1cf6f7 +0baa7878f5b0dd33ddce27e72435b4de648699f595a064e0ae1868267c8dd02e +e3a1083c093f04a58ceda75c10ea7d7de1883f9e6a891a37eb5f421661e43154 +6099a72d02a9459c9a75a1edb18e899724ad870a3ff3a1d001494b7a87b0a177 +4aba1af3fffe247e1157d9c6dcf44fc35b66d45b8b13deab9b446fc255aa3bf2 +0423b92154720021b6987c1d92ca3762f75e3aa56248615d1a1dd9c508a1825f +5c84b6b50fdd0f5c99422e943a963f3fd3a47d9339d8fb8b2c7ada2df5c1bcdc +42a04aa5a362eb91176f74c39fe53f452df73d7620bc678c4f836fed529820f1 +30377414ce8dfba51ade14c58acd69267f0145961298afaa5f79812a1032af9d +9daae3a58a30e11b5e9cdd0710aea3d454fbe4b8aea2b9b136ebea65d73d49ef +949feea04ec3c64be956ce1a51c7d21871257d5bba5ceadd5fe018d6dd6a0967 +103bc4300e7cd70aac8922f726c777c5c145bf8ea207bc46db6b6386e5025fcc +728517b0853eeff7df0de2b5deb912050e6021263544c18eaf9edc07f865be77 +8cddeced5e2fbfba63e8a38e55e0aab1ff820c4926f680ffe93cd4a20795470e +e68b7e72059b83a5e1ab62c8d9a1231c427367d5224de64b62a8c46903348c92 +311f27deeeb2a2fd07796c6559371d7a1ccc26025f24c3d85d6c89aa703cc595 +43111108c9cb4ce0494e57d13e9d5eaa8b1e85821a490f0b111556b880b5918d +00adf6954de59695190b1a3964330046a92359f1b8df3217128fc1e60145fc48 +c0d347efc9882145db1e4a1e8f0fa218ded491dcc162560ff4d94a49618821c9 +327c306d43e59f6ea366c9aa3a0c58f6748de22981e6b8836885d8a361b7ff85 +54b659c223a9495998f165da3143148510d765323efe9a1479cd3d019631ce63 +d5d576f4cc7c3a3cc4b8207eab9a0e3b6211f96421a5aa2f6ca94bdef47294ee +6ca7fc29c7a68d4f0b2f9316b9774349802c61fe6e30f0d3dfa0dc8d74e45b6e +b998ea869a3657fdc0cc109ff636aaa8c5c39214b1cec2f771f861da32b8da21 +8194af7a1ec7c3d13079951994613e1930f0bee02525cf0a8b9e3419b79d2f63 +af057f40c8964b8855be58003e43f259698240e18b46a23e36c443c5d7da630d +5e385c938505aaa86e9ffec45ffb4cdd58696f8b657e06f9d37fe2d22d55c767 +08da9bb99a1fa174782c003503a3dd8252e363c879970451114fb407829903a1 +81aabaa7efcae3e01b5e9dfdbec466d13879019f6757da957cc9bede41e95af7 +1f04e96cb6bec0a58c29b0eae0d0c98cfaad65bc7a6f8b7a19d01e4a3bee6c7f +fb33820f7c73aa8c3049479b0356c9fffd36ff1cbab1f4903ce8ae2379fe9935 +7ac7dd8768f19f4af38ae7c039231f47cb96c8927c9f83dbd2e179c85f09368b +a71f1e5b9a3141c337b46f97d03896fb24b2dc7737da2db618a7ebaa05038e48 +f9166c461cc850bf200d53ae071524c3723e92179b5ba4c269a2a8efabeda02f +1a4f027efa599783bb8a1fd21017ae234ecf2edd70da4ae8b337e12f9c8edc45 +9156086830b90a8eb3ed7b79e1e5863dcb354fec724a30ba0c3f6f831f424063 +7bcf7313e7efbaa548d28b48ff06ec16dbc2dbce150cfdb3a3146126617b1d53 +52c5531c158b157b231e8fc48910ab62f5da08b288a361e80bbaa49fd6a13d06 +1400a17b4abc85bf2787b3ed37269b3a79e236ca25bced2854080ef0fe98a2ba +d377774963bbe8a4feeedba11ab77bf9f09375efad241058ad0b662d848014ff +ee7e05738cd360c254e81f52ba3557e7e693e4a2fc782baa1214e33f799ad9d1 +60272b3ba6023c68e9ea2d7e8024963bcfd7244cbf2f6f0ad24221b5b543125f +d88afc073247eec95b417380bd7e39d28bc9cde7c6229e3ce0c11e999a16266f +9f3a9589b1d87cc99589c671548fc955616223ff54d9265f06c733ccfb045a5f +dbdd2a420ea9bfbf3e370abd1d598ddb0a18f257624bf55a7836ad6ecc9210fe +a69b4b012dbed65d14a6da7c2bebf8fd3b870a68b2a02a16b910deb7d3a1e935 +35163ff1d8cc52e7a8ea6fa48e232b26c53988c2b424761e56300e3c01ed3727 +88c2c6d5913d74e464622d044f31be7734d2d965de973642a2e5059bdef34d52 +3f9bd51bce13b862e38a713c578f194583f6b300f1575dd88eb1a035afd42d15 +c20e97f2536fc79af90cfc40231ac17b512350e4d1d1cbc0a19f775f37b66a2b +f67b60e5a0c861650cbfa96000942450fedec972e86cc4f417c6b0cbabedf661 +060381a991f6e019e9b20dc930633c9500e0c4238c7560b8ff31175588a21b46 +282f6892457f85e9e3b9eb674b3d4b3bbb86eb85385326e6484606663caddeda +70fe9ac9fb0a17f357d9a0b5b9c28f48575ae73122eaf5d0d9e8337d5d93a9c0 +b700c89b43d9fb502ad5decdf79169a817fd7560054b9e9ff15b1cb6bdc41118 +645da62cf4ca07754ddd45e99121f10eb2ffd0f31db3070dd386a514343f03c0 +57e3b530e3c8d209c32a2f616dd3ff60a22781a639a264147cfb14f617cb68e2 +5f3cdbdd9cc58748e70d2697a79cc2d59d137b9dc6fd2fd74b9f267b0678e724 +f27358f36d259ccf31c6ee4bff2fd0ee4c5870352bd3981cb674ec88774deb14 +51f3087e92d642dfb86739c3b7ac7c8c8e782b038aab6dd7a63da832c6bb41a3 +aa33278f9212e2ca1ba2ac3b011d2f9418821094361e7dc48c51b29be5b4a50e +0b8edf4a78b3e99fe9323ecc87d1b0421e7bff644619587092416aa754c96162 +132b040e6b4028525e5e3874ad80036b13bcbfdad2327a2242c31ab273a06aa4 +396d2f0e10b4fab4be6a9f2200a0f018b8414b558ca1e663433e9af36993e65b +7663881a0ee655389484b79beddae62edb8223d03c1cbb4edbad6b96690ddf88 +e2b04d0f367d4d227591a63709cae3a44b5d7125036a41ad762b3fb2a88b866f +17e1f1bd375e049917861ccf8c05248416fb200b909c80036b98b8a08b847e93 +c13b1224265bddecd5a80e169c1e342918dc741b1f96b6c0d623b6edcc032303 +258cc6916525a1a83b1e99605596b5dbb96047c243218f9009f935a3a6eeaec6 +7141321dcbabdf62930dedad38a68f0215667c4676e94c9f2abaa97694694ead +3b197e23710455e73cfcb9ee8801a5d6d362130d8e3165a5cc82def6c5dab033 +c478baf385d41c3a5f7b98a10bb5968a3ff8c4b6e89b3cc718253405742b8368 +dd22465b61e754bb9bc3025ceaa2b0a3086e3864913442bc67fd3bb154a76001 +82de768826604a658b2f5368838d9a3d0d79b7aaab1bd012b1de1ed8f61c692f +7be570f7d5d326cb59734a16c73c5298047ae35a2a9e503630ef556aca7333cf +a90e0f3b8fe304b07400c1074488e9812c534acfa7eca477e95519558c4747af +3a9ab70fef8e29da574cd1bfecfb4874bec13db3334a83601926ed69017469f3 +617c48754d949a17f4cc75670d55ea8fdf1c14c7da190ef75d753434e921ae27 +599173e95d8c7a8d813cb5ea4004021d4a4a2c8ab276b9f559d188cd6aec3fc8 +694294b4b379a4744983a4de9663f52ee3872cfd5e1e0b9d50e7e5e91fa71510 +d0e3fb5a6d5bbcc94dc1214aa8cf09b4ad4dbcb8da2dcb75fcfe405dc8f763f9 +2b6f8a26a00be9c135011d2e081be749d0ea4198b116dfec5b35b8b98293ab27 +4c519d0a510cf8c5af6def3058e8e72dffbe4d20f070bae20249290fdfc0a4a8 +78158beefa59bb1cc3356a85e4606fa4a4ba3fa8f5d95f30cb09f87eb73ccdc6 +639581e6a0bf798d4c5bf88ec278eeb9bb6acb8a2a106ae09648ec2f30cbfc19 +89e06e933d232eb43c79cd80863efd00888cc3bb1e5ce25379f6dea7e345ad71 +a36618f26a186a564d1cf377bb2032fc96f886addd351b9f511bbd6841ff045d +a3b6f69abb0230893bb6595478af59fd9d4b9a0e0b16c3887a034fc286f67823 +dea405c44ac71d02e088e5a377136cd5800ae5d6d670eb644237ded577b91492 +4c4aaf74a53bde7adff3b7776b82f2ccc4eac259cddbdfcd4da9137f8e0c6eee +021de0c2d7c8ec3bf3effd2a28cd5726b31848c3346ab5c05e7025ae326e3938 +364ec7960c921875e789c30f27356fc2da5ed310b6752ea493bb6edaacbe6780 +b286d3829a4f18e110f369d944fafe54bb9da1e757f83f2b01912a9b8b7cc379 +5deef3039d23338ff7250ba43d94f7846207a851756658b0d3fe11c7cd022df1 +aae8f0098aa2857cd535b6d5a2c0eaf93292a1f4764036b60d0f5ec01320d661 +58ab38e15798d3305512df53d5a6e5cd32ee44bde4b63643f6dff72d33a9f312 +7eb1fc78326d5ec5e53be40a96f5ff9139ce4c03ac0d4fee3aa6b888341dc440 +b6f4deea2e485ef17cefd47e3236f0c6ba722a58cc0134116c29d74cb09b1abf +d32d57b6062871302ab0634cbfbd3be7bc83921d914bc67515e1a2abe3d8dff6 +a9d71aad56798e1503bbc49702d6c957df99218e57c588620cec420cbdcd5882 +dae9d094ca8079484370f86b230c3ea8cd5233a3a8db3a46405c2f66b6e079f0 +0ca8901612ad5cda9f5e1e60beef876200da0c4b4a4ab198d8b053297aa7c3f8 +8a7ff8d9cd94d71963dc8886618a0eeecd19510a2e427f07e23776a2c1f229a2 +4a5b7e781aac58129bcac103f81ea7766cc81ab74937a96286a088b96554db50 +c87fa22c998f9feb073997e9932e33277ee3149823c24603b680b30fd84641a4 +65a2ac8f4bcb07f55175b136982313bf106954059c80f3930d23b6ca41e5aafe +fd26aa6389d4fd96922ff96468a9f0689fe0f0cbbd1a55f408aaba6b1435bf47 +45c0da4ce896195f9783e4844fef01088a991c004f64e0a7de42afe0526cfdbe +ba949a723572cb7761b909fb3255e8605d26598d7fcbea0502b79b9d7bfd75eb +d6b71908307af9718c211e375f0d544b7fb410628a7ab3428d3a5ab4da709ff9 +6ec1df440462ad954919e06cdd7b3daef6fef859ef7d5a14fb5b9a22bc027a7e +2ca589e00acb1b578c41bb44033bb5edb9fa6b8f2200b0bac9eb6f2aaac34bbc +63eca505aa37dfacf59f48a79df820bd8f0e36976e9a0f33ddc4bb037767d25e +91d559d81f3775f01f7f98f4b7f293ccb43d5991e626fbb753da2e8b94d0d864 +88835421652ad204e228044092ae0a5e6be4413f12ada4a5d2852cd863e55430 +4251d37b3fe96eeb4f895a9f265e06b5a8c2ba78c25bc53b4e728cfec4f5213c +5872b6f167ad81240986748669f4414d6921473c9b91c842654c7fabae3e3996 +f1effe2a78923791d83fc1b38f2910292b13f34c91a54124fa75ef6c521510e4 +9f267a945ccd13d9381f8f54b1d6322bfbf8337d7d5d564a4ee141a407d400b5 +2d54982f9cfc5671bdca32ff73083dfe398d150d9a6a260f78be4dbeaafdafe4 +281659413f6e915f1773ae5fe319e8881d02f077e4a8a3171cd88342e79df1e2 +5e28d1524b35699bb33cdd5b2f0c449205ba0ad92948f596422ad322d90ecfc6 +e5d90ac2fe1621aff448f49ae9f75c0744085d3020f7564589fd27c344e6b0de +208ac87e3241019d6efdb3ca1774c34d634a44f7964ce634e01331ef969bd0ba +a27488196f384294d74932def39b1835841ba50b1ddeb1d926c4fcf047e815d5 +a24568a222945342e44c05dda6f5134a71c83ab2f2f8820d057c7f65d796ad08 +57cf5bdab356126cf51a205fe751bc98189bc5ffd2ec088dd6eb39105e5e872f +740dc65f089083b030738aaf413aa590fe686d9781ec522d2085d2c00dedbcf8 +4ee1a9925b28627e86317da45064edbf33b3d8f3f09415787d4eeac258f24e42 +ece2698c6ecd3642afd575c5dd6b9ed0f467e17e9cb9b1a57709af3ca0b18cd7 +e63122f4d7a9b5f20cc12add1f35fd155ddd28224177819a300592cfe1067d39 +88b4290fa754f318af76237f73b0030b4cfc1eeac60930e26dacffe4bc4661e3 +860cbfb4bc0307b3978e4c1ffe387094a710e3c46a4c2fa5e411beb1c38db8e6 +546690b318303c2237712817a4b9758964afe00225fd572dfb20e528c1a632a1 +1b0911a77694da1255da5884cc6f152ba5b0006f82dab26d3bb4852e02f8c1e0 +a34e56e909112e9790778c26914e029fee5f54888bf491233d6eac63e5ff87b2 +73fc25979c3f1686f6ffcc4471f729d79036717f7009689f73504ce32a3fd867 +795275c727950ec49b2c41d0dc0af5ed406a357dc83eb9dafd5d799af3b192b0 +580dc9154552630c35e2a8bbd5c1496305d59763a5f3a5d415c4d3a97fc7a6f2 +d7eaf12a8bd4083c9d264fcd95eab7d8e18b4a33236666cfd2a2b673c07b1e29 +e2400e31753120c8de033b4332897b1f217c0f5cef0ed13a9faabfe4e33c94e9 +a2df7bdf990e4ee8333cd97b842df5641a83a760e9ff3d3c75f59a4be0835382 +4f9445040f50b49734fb61d255369dc481bb02aa0644b3b828fb63f35449d77a +0f18339f032303b016e64733f5b11b82172414706c8231b77de97017716bc7e8 +a8a02f0d2ca3d82042f8ddc6ff4c3c9335f895826cba8d1b7aa61238ade19ada +86055373810c870ad6c3249e06a395b1a712b9bfbff0033748a3f03e2c627c3e +c95427a325be766edd3921b38050cfe9faee1fad8842a374d505a091cd626186 +eaee63628fc135aa637d1692bde32428bbd323c8054bdf2b9ef1608145a7691f +7db4fdf71e191f82f0ed16040582ae286fe9e1893b05725901319427984fd50a +873efbf0c10c4f72ca78292ba068bb96b7d4e5f69f3e011bb13a5670c358c3e2 +1942de2fa4c48634cd06517c30e1159e5136c0567cb816612a4c06cb5db42195 +7448421b2356ba5618f9cd31f3c44c0efacb04b75384d17421a58c0b2b05b92e +4ab85ff7e31515514d5ae2935fcf3dc44ffa47e221776c0a80cfdb1a298a3e59 +3f9257a74c37c6bb7aaad65474eb5f971c95db0fd1c065ebd15f38f3861699a2 +56bc1f075d4b52847bae10ad457f34e3bcbe7e2e64a7654979ac60551faad547 +dff55dd0ec25e8950eeac9b6db7719af06a2ffc09e4d6a35b63c55e6771787e4 +ee845fa9da58669ea67743e8731d76bf02d2ff22720a0d73ee2515b32fd4ac0b +098be9c157278b01ba9f5bb4880453ceab6f6cc1ede07000ff12a68cbb6d4531 +8f200aee8a948266ee7e78377ed3d78e4fc0032eaa60a98dd39f193e2f33b544 +47997c1a362bfcbff345b6cc175d5c11cae9efece90512d0e0dc085a32d86f60 +c8766776696c0285eedc9f8812d02248b41183c48bdd72faa4bed53a3ea2a281 +6af6d1962045442296bbcea27af756155cfa358abf9fc04ad0f7c24cd247a649 +ef24926604770cb8b6026a1ace117901cb6735b517c242b0d05c16830c54f9d7 +4bf50df32791e3d0f9a36426f77ca744df23fc1e4910c7fd44727e28c3067d65 +1c4e24f1c075330be43fe03cc55fa77a4f0c26d94529024bb390696bb124237e +d3c3b2588c81640eee1caf0a599b0e695484262549e3fe21b165fa8db2d75130 +1d3e620edfaf0e3c905a099c21a0a356a6b8593cdab8664186bbeee500d846b9 +84dd3ab6de9d55af56f828c833d9c99aea15cb765a34dbff69ca5c46236a1881 +b9ebf618d093a4ef2ef82c3007ad44e1c50bed8e97c163c5ce73f9ede71dfd17 +178cc64d9d4763b81cc1717a4399db49f67aa2d419de60e262f2da8b1f6d8fda +aca2c6c7badcf6d945b58bf1eb6ede2a2562813b7c2f0e45a752068801617c0c +a465cf4a02abd13182f380ae6ecd21e92cef2622c5bdf295f40d3b9559ce91eb +b256e93820a46ce8e2269d3af2304e74daaf3dd2b84144ae131b342ad1cabc45 +076415815f885f93597baba494111aadaaa089b845fe3a730393fbf110fe3241 +9fb839c4a04d944ccab1e294060111058cbdb333a8e34e089b4fd517d396c001 +971dda246935d5d7a3dbff11cd32662d14564344eaac84ec7529fe7aa34159cb +4383e0ffac0bf5c1094948f84f079936c32e56f0967b03245e8c71cde8c31770 +35dde9c9823bffb056a8eb48b0f975695b5dfedb0a095ac12f80c46e70400f0a +79ba5fbb46b8bd695c08c0dc95d4a148684907ca98d7d601cd0b92077f887d92 +b06bb42366affb7fecb09ca1e19b1cc76f752ff5ddbf586db8c1b39c8f78be12 +8ea12d10a032c15cd0f1af8a0484b3ad9e363c78401f03150bed0bb922813190 +6983674d816054c634aa04563c99ce4c4977092b8c490de16e7145c411183fcf +dc915014a4dc4113b1185be27b67593ae938cf9c60b53096bd76cc400628157e +7524cb0821a63e914e0891e4f47f60e570d79ccb7ec90952e6da3bf2484167cd +cf51dcc2d6a660e3640edb8f7ab689e1b001647ddca21631fd4b8838adbc63c7 +c50dd60cea7edec89fb756699c9148b83bf65a3187b11a1400e8104fa4f0e61e +4e62cf0d66e759a69e50a5721c44c9f1af651e73ba72b3abc2782595bd24ae77 +f0ec01bba702afb857fcfffe8105dc647a753b4a4cd05e6196804da8e4b5a6c4 +023d996a960cab5c7d8f90eeebfeaf3cd61efcc015218fa7ab5f5827606381f4 +452468531b9ccf4859ff7331449bb7592a20b80feb3484a088baba8ac4dd29a7 +1038a3f885e5044da35c29304a0465199ddaad81efbfc9f5a41d13d3489ec736 +aba5046d1cc591134ed36989ce226ef103888f1310b6cc8a29075016e685c808 +747a3ad6a1b9c8eafaa263e2f405fc236971983f61a9a45e53e5d425b5cefaa9 +9685bcbcb9dc5baac89db82582d68f0b2ec557bc24421a3a6873174c433a8ef4 +dcae69f7560b9daea7760d9ba34ff4c6b84e4f10b2c1ab57aac9cede6b8a430b +6b506581ded879e2e82fccd0a920da6d390c290d3743b8e940c9c2045812ae39 +d2bf87a18e9626d03c0e3c2273d917009a209480cb144fe95d60102a4bcc2bc6 +0bd13d764af4b6fb88924984f63b8ddb0ac24a90c30fee4488b52092141027ba +1431b6e4bdec39b66b6703ea6d73d00ef0c028398b088f02cf3265ccabceef26 +054ddf3fd27f10f2703eeca2baba4eb2bb832cee63bc357d1002d0a475d5fe75 +2f793e7863b2255930b5fbe3edad8522e5e9889d47f1d3be145421a2cd885067 +be5824c3ba60eb1990d6ce6e39fd0a8696a4f139d8452627778cb961c1407d94 +1b01fc4c396f76ed0843c6d3db9a031f69d1036b4705c7880625c5e277dadcb4 +5e8edb6df08935ffe1bb7a1e3c6659a176ab1acf3767410781be0613bd67d2f8 +bfce6ccdfbaaaa0471936705349b61e39bf24d9291f41e9cedd75f2daf5c53ba +eac61e9132911365437912b9546ed3a75d10bcba0d26cfc49dd10a0896bc7b2a +77dc3e7e9933255fb1eb54ca2f0b93b83e5c51dd522ce09d906c0a9d256de715 +624ad5523b32b765399f842560554b84fdaa69a262c06fbaec4c498c9a221cca +912cecca680623026346e395468ff48f26fde31250e84d484600b2c179bf8ac4 +bd1e5ed00212316fe1d708eb77057d59cd05046eb936540a63f83bfcea53bd86 +4dba1b2e39ef3db4dc865898439940ddbada1c1396b9a9aef6aae5747b3787f8 +bafd41ab310a5ab22326103110886e5c80e5fd4894babe32dc7d7112973dc33a +2ad0a138466adc3a7b6d3fad48efde845bdabbb63282a310688695bbd3573a30 +a6f014f1fb11f372eb17c0b24548cc31408395a499e28b5457e91a8831c920f2 +488bf3d5aacae6c435b79191751d389dbce3948291f614c846016152c344b7c4 +39ff8919b7271368ae2defc5ad9b047bd1dc36b0b925474cc18eb8f57566a626 +68edebe55168cbf660a56c2178ae3364be9d729102be1169a86635a898a47845 +75104dc625ac8bd1bd317b9526e01e23b4e8b215d1d9723f532184dedb9dcf54 +48d8a1972986060ce6bf2489652e6149da56816cfff80bc004e574054ea19c57 +1290f986c260583e921937302e9bab3fbdbdf7b87df696b3581acc9250ad21a0 +c6f87e4d2b9877177f8598b7ef0cb56bb101552c7c4406c1b2389f2345e74d61 +aa25db0dd85c8d7e287a530403dc4530ad26c8d86104be3f4552e19578b28547 +11ca075c2093650fae35017f7b05a085180cf7e7055a1a2593a761c318e5b130 +303b2c3edaa70a94ceb27e1d9084992c54dd71becb06fb2d68a927b4310b5e44 +e8e75a44c9e9bbe1ada8026410bcfefc664d152eb659c1262c0c2adc52b2d5fb +1ba5c7478a100b673b3c0e6f9242dc779bd03d475f08a2fa62117d452b836172 +54c259d27d8ccce94884cd675d4306435910f6697dd9dcdeaaa514302d509969 +a7aacc4cf4a7b0eded706621ab26152c25eceb2d4a0c2506870db532f34e9793 +c088695ebb3bb93624be7b9570646d097e865ab916d6901932134dd2fd1dfab7 +97844c4b22efc2c6e81dfaec6cc5934ce98b9af1e50c110128064eb85292a32a +2b7d5260473ffe693a8dda1b4303af78a6def107d6b06af340a3355d706e9b1d +c16ca758c215ca67ede2e45f8d4e0d62f8aec2a473b50af8f24ff028a5e67751 +6de538f4b65361677b23bcc294c1d785a20d2436e9ed7c8727cd7f4647e1438a +1c5a133002ab5fa224b2ef80c4adda60d646db7aeae1fb329359e8dd45535165 +c9446a2d729a01fc3e83842e1f06fb507ff35445268c0a4e27037ee697a7f82b +af77b77878a172d69f5d3bf5b6d81ab7985fde13cacd3cd73ed9b965cee5df77 +61a9e9a293978c005a7f491df48dfdefb8da0781e73a1f122777d310b13c8057 +13358b742aef216c38e79136fc4b3cc61eb64f347a0c7781ca67eeeed1775fb6 +efd5eb792f440f305c53f0fabdf0e1b03ede8d1bbfe2f974c2da4774771c4ca6 +2ae401a2cd7a91354bd185cec69fb822af15265146effad3bf5cf1c796c69a94 +96fbff8b7f165e74643b775b0eabac9881cba7a45b3b505ff1c835330fe77704 +3e645fd372a5ab1c236db4daaf859cba7e28adfd438235cf648b098f74bac810 +1315791e5733431b3706cfbf848241569a883f9c49ee2b471c8459bd7251f4b9 +6b51cdd0fde839a29568ada192c8ada1fb06cc856f9e0546ebbcb8197b354af1 +b6b4b98f2833b5dabc46a90b8a928290ed2aa89ec657c7d6faae20776656c5fb +089379aa86fa6677eab83d7970a1fa2d3924e20f73c7cb4e25d21aee86110538 +b37059a856f2218451bdb7a2b34856c55434d65c0e9471be961df7c95157d770 +c01ea4bc7f6c4157fc688939c68ef615aa644ac838d82cdf9543ccab5783207f +4cdc1cb0a6d557a5b956f8b082f663e59e8eb03464a4c8a5b6f86a490ab5b06b +558e43ddc0e0155416880eb4bf2f1150ba86d8103fd26e447e9cc1ff9afeea80 +3b7f668ffb65af7c4f345ca86bc64443918e0453ba45edaac684603d9896fe50 +e80458f7565c4851c8aa4d1b4f5e8e27d12c79595adae2a092b19ffefd61a4ff +4fdbaf700a6e9a965b95d35415f86a297e7741a0027b787d011b3375b55c85e4 +888ebb8bc3a074585e7e4489544d71c34a9c971634250d2afaa19f31b71181e0 +678ce646f8d922ff862082420f6ff7f6e06835535e3b1b58f503624db81b1773 +2af7e8b9c09278d633a7195a9322c19779384bbf05f302158ce73dd769f403c5 +b651e2275e06bdda225a8f6c1f9e8a45209c3b944933547c89285c5cf7ee85d2 +bb78eb4a66924e938702662bd9f691d0e93add17d33472e6c53eb5da2abe1297 +fc8e57a9eb8c2e41eaa98ddf5ea6bebdb9a972bd1a24865db37773aee05b862a +6780d0212647aa7afec35543b9fef22cf499388ba3ad9fef7ed4216443e9f2cc +4d054c860e8f2524184ee4c7bb4f79e6610947a231bd5345207f840d9d5cbc74 +0c4f5f95338860351706c16d2373e708257d2e59be02889d23bfb4ff16f36cd5 +af8e70383a46e4da92749b8c50d448c7e18db340c649f510fcc18995ccce82a1 +c102c323d79c42a781851c04b7b3594f37960ff083a8dde29a5a1ebd30240cbf +a09e4e9c54ce7b19a40b28da083829d5a957806166f79f5b880d546c5d84dcbf +d7367461b982dcade6314ac722c6990d329b31030216b93899662482077ab97c +a3d66769414745e72fa40eb1592369c34a6e3e41b9aa58eb44a3a0b2959507e3 +714367f60bf84a88edad98f6cb38c706368246e40f7465098f099dbfce47fbfc +c2966f0a24cd31e40ff746ac6f36790d9d62d426096cc8811c42ba4691073fc0 +c3533609b425afe28d12542f078c0e7b368fd3714070304abbbb25b3fd82e873 +de52577249c8fcef7453fb4f2098362e8f97e24dc8e93efcec525e357761e422 +c305223218928c3902c4e5a3ee7886c511396a008611820d997b9e2eb1382639 +97b52d63d522b3e2309e6178776e71cb0452919a5ba3dbc34edeb545d45f5c48 +27ce9adf9467a99276210cbf0f904303944a0bf00a398401585122ab16af29ab +711ea132f61378cc736816ed6dbf2e81cab85ac1e0484a09d7a3276e627fde91 +b81d7673a90d350ed8877ff9915025d19e435c95c2868d24aa0c2de05ce68ef5 +915d30fe890ea0f43cc05eedecade250080f316f04090d75679235862ebde72b +daf6736fed7f64b4377db19a049717630654538bd7941aea1e4e44eda11443fb +93da2ca5a7f2e2621e8ac4accaaebc7a1350f7e8f477950d86ca189ab7c18ac8 +67ab1d5a447a4fcc1548d66b257baa5eb382206b1cd2be5020dd85509e269f23 +f0993149c23e92c93d43fb043a65e7cdd8a6d632de5fc0636ee0fedb27657026 +8fa3b7069cec8aa1ec0a9edd17b783df9e0ebef0ea1974a1da3c71c09ae1c649 +e4a39599432916d754700da66b9e5e0ae17232b4cb70d754e6874e784a7336d2 +6c531b366d24fa342f077fd76fb5aca2680037deaa7313caa5f0912f2d1610cb +f5464535baaca84ba618c2cbc997b82dd64f9fc322a9988ff9674306e0510c7a +9837150be6039e5231e2235635994976ea0a853dd743bc74c75f2ae325f3ffd3 +9462bf6809f298b6b701fa3d52feb2fb3c659d8d8fdf258d1637fea577b44337 +b1abe24ba151a04b22f50a43157d5ea9dc917c205b3f3629fb89a67a25c125b4 +549b9cbd79bb18ce526ac1759e3658366cad031b15490d6efd2ac399650e1c2b +e9f4af7343e95f09e11173ad0723b08db7f8a1a5b3a61dc5b6bd9f67998d85b8 +aff4fe6849c96419ea10e43376639eb01c6a4761620b0d2d92aff40439e00113 +d9803002c1521dc251a2a4ef8001f181e62a3454764db2c03eb9fdcaf7a0c58c +fbcbd95727b97e9958d6fe86065765cf837e41ee5bae89a085854fa1782be1ba +1e789120d9441082a65db3be4be079cfe7cf9eb48a4f5b6750e730822d760a31 +2a07ad2785642a0ce83a1aaa06d487f024a35ed6b5438cae5eaa927598ff6ff2 +9dc580410b946ca61b2c480e043be2493cf7f1755f91126659797cb6121403a8 +f75f622fdd1d851f15c92e170233c84a902d094ca5b696662d44cfa2e3494c46 +20612ad15dd9ccd47ff2e90d0caf042a9fb39a3fb2d19064c6b988f89b6be7eb +cb35eeabb3e8c1713213188ab4a673cfc2964dd24807d268043987419c139acf +3a3a17ebc667ca0c3d584e169d0cdbfea8fe173f120153432760162f391c0f90 +6b5f5dbb6b3b00eb6307b8d2fff9a4a12a32690610433be547ce700605d2e7e9 +123af081498357d198b533a391d6635a33244405905a746a9cd7a4681e2a4687 +63b2bcaeb248ad75c2dac2ada6687ba10e5b560852f353bb1f622cea9064728b +6b41a1cfacb658519f83ac156697ca591bcd873f0d937fab8e985b384331c2e2 +a61f0b5c0781abaf8d0d2f85943f5eecc547bcfe85325e78777688ee4fe42aba +dbe25a4f0e01e09406e7ff3a44d366a6072d6899542e7ffbd6d6fefc089f3c7f +55c3b15f137e8d448bd15eb90699542b552b32c4be4d09d6a82dc0cbb5a0844a +04a9345d6899fa3b714724745f3c2aff63b429e8f41901dd8b0259b8f27be3fd +f01a46262b634bfb4cd8e5a78819911a5a0d5c0d92d6bc31cef1dcf2b401917d +a88aaa74e7665fcab5518652c7062d0c48338336dd28e0cdb2ae80c6b4da5982 +3b4bb560bda9799f65887fa980d39eb80e2581d9aa10c337b2dc4bc058cc4a8d +a768846ea95e47a6adeaa4b83f7c00391cc1046a008b4be6e35be03bac81c12c +dbb250dc67295028a1ba2af69a0a8b5dea99e51eb1950471233df86003c0e01f +1635f6f95243c288eee268d0920f565ca657a0c9101e4439877a58e78e0a4a41 +5a38f0b165ecd6b8e3b842ec6aba8507597f23ef0fb2ff906b683e58cd733dcc +413c4e6f818a98e4d90368328c67e2efd6f330872014e225b5fb405591a91c55 +4084570824ec59ff61c7387cd34790fabb60e58820aa28bfd384a5f26c1d5108 +364625aff6bf3f497e85b39e59ad762001c9dca97e7e6b64670e3c31674172b2 +4e0de15a38fb77bad04638e77a1958378877faccbb2b499b5e93199203a9f0a5 +631c6086e2444d113fbc9031a3476a236775ee96f4f467ccf42ea4c50ce95a4e +f302076e1b50dae5602e9d6b41fa905765a334588b712e56a4419bd6f15252d4 +4e4ab835ac825732b2201a30f275f0cc785bbc0164607cbe6c1dacdab1ee8440 +44c4544bbe0690af14ea01936970faf1c02f06409d5576e98e42b00cef10420f +58ad350263cdc6343b494185d0a2920f5aab386c08e6a0ec038e7b26d70de878 +f6be5d03f2711e138cb930dfbb96b4103dec608f10eb526d19ad5b1c1b279869 +3ab68ee54156eaaf81a4f1f981ad43bd8abc51005e5f522a3551f6c957e68017 +f509fe4bd1c5296949a44eb4d1bf1e44333abb1e9d8fdc31ed2e22f8ca887f09 +21e912f5a139bbbc500f522ebf0877b1e2308a47f206354b50efc7223f166a96 +4a98ba5f1d28b833b367c50d97258039ca8e9ffe9c7acee7cc26f07e6d5f811a +05cde2b84fd8931412ccafe0ad39545238c569dabb007240bff2ddbef6a321a7 +c83b63fd1bc07eb0b9734b0e0fcf1ca5b4451c2f7fb51958468dc31397fbbdb9 +fbc956a5d0de83ff8f8d39f68964165e7366056abf6bc26f9a09f1d982201498 +63aa2d19324b49fe396a77b32c1cac9e82af3a2e03339c9de3240b0e3b6bd8eb +49a9515a34c27f8258d4c3cceb90a4bf92a0763d6b55c3f8abcabc2141ee914a +cfeb0b9de96a4bd92eb236d4c74077925567bd44f4db38b5e4e7a503017cccdf +1b82536845793ae5699f3121c712dbab95b092bbe2931e1cc4feb939df41a96c +0ec9452f14bb12f20368c7db6e596b76b6d6fe8832590eb2ee790720e8860fef +a0d73ca533d64664c919281513e8a5333b5a660c24e6fd4683faabb670cccb88 +8cad89eeef668c8fda727c6f608ed7be5cb8ac6f8af16d64ab436b6be894f488 +3219450646e313371e73fc3db28bf0c9f7c4a97c2ef7faa7bb0e794c53e3bb04 +04f545777733b8d4467c85e4c433bfe26a2538b64ce5e0345782cca3e106d749 +856f1ccf4bb14477938bca48d42746f9d8bce0822dd8e9c321db82ec01577c5b +6d608f448a9de7b5b308cc70a41548f5daf421039615e2f95d8cc38c4656b127 +35a0717ecbbb4582ab0ff367653dc183617ebfa64c6c2120f12c30b0fe1e1d53 +9e71c0258c58e7d6d2edd850144524b626a2abe828044e86ddec4d3ef59655ed +824029d104eff680bf3553487391b4741a083b80dc419e798d668b9793ba6413 +84f6972adc0f0caea96a35ceb0b2ac9675de31be1d7b26ef558f9437cdede1d5 +366a227a425b61fcfa63655823a4c95e0a3a8fce49e1c6653be9d891e38cd9ec +6a572b852b451d2e8dad4ed730249e777b53426367072e0b812c9c340f284961 +89861d8695de060b6552a01bed27497c6166aae6cf1c1b097f8b28f0fa6b464b +473fc0bec931872ab72c655d4aeb7ef93c3668a7333de4e592bd280bd2dd3f06 +df33ef8b66bfc278db5c2750291b190706c508977e0fb3dc501d4bc6e7e81d0a +23424d6ee4fed4634b8ea9fc74ac8db15d50e54a0c83b364b70fc17bdb065c3a +51d215102ae0134c6d1498528bdedb0ddb5ab9375fc49288caed2d40ef96b29e +e29c3132f862a1bd41e6961d60878c4d5396c75f967a54f89349ff3af0b50070 +bc9ddf6e7e5fa79e95d611bce6cda060b2c305c1a9ea4fff7022fe178afdee98 +37af039610af735610ec381cab4f2d26f38df7f9eafb9948373af081d679c2a7 +00b6ed45af9e39a40883fde23752c791772e57f4122f7def893ad40d17f9ff37 +44095c49b45b15679ed6a2f4a24c795d4ab26d912681cef9bf460604a12553dc +890854bad6b8a911d79668afca3ca1387be2025af0d743e1f86a4e62a5f3a1f0 +3f86d85568f50a57a8f6be6756aa12d2ea3335787ba458b751e15a79c047c843 +3615dfb17fbda7bb5bbf2b3a43bed4ee9bce6a6ad438cbc81bdb8ad1db1f6fcf +81bd69d3458633206c01223dda1871d78d686e7d7b4d3275a1680f1d384e9b10 +858d9df80da954e6a3fa320ecd2645bf880d2baa0e98b914dce61ac0e4b23063 +23816bbe4a8b20f88cff751755491a24ea1f3178e39eac832be9364a0133832b +fc99c99c171d983159ae6e806f2c84e1748694dd24eef9664ba3d8d85c538a17 +6b75de6c0b0fde541c9c20efd69e365a71617ea68cf8c798302ec0ff6ac1ea2b +33c9db8f9819c37c4d5d3bc84e7caefe16ac6cdfb31903594f363c8d90b06331 +47568a1ecf6642d615423cd149b3fb2ed528f375188d2a9a00a42126a08346a7 +05c7418a3219bf881b58c1deb58bb62d41ab0a75e8d63c01449393e6c63c21ce +c97533aebda945063d996d261518c152dc6334a467e497867aec3bcf8a488ef1 +d44cbe372bf0ebcba9f3783c03474a33277de31f2a0dd86e21672f45141061fa +f6b74355f9029370184d2b4750f34e8a4675b05e1dc9570fcc61a4218a0373db +ec01a16fd4fb9fc0c2de7841bfa0d57ddf2317969a2aefce888a9d0ea2fb0901 +723e3916b07913e79dab98e71bc2b62c0e7e88c9f2bb58f744ab97babbac3ef0 +4862717aa20d683647d8fe18bd40e9d6a27c97d7ab28414d49114468cfefdf1e +2918c2189ad39cc2a3c335bede7f4920b3d3c7cd36616f57e6852c65839b138f +0d4ff50493acfff757394510708298aed4dbb611ff8236b8ee94f718f745abde +ebbf1161c9c9c191656f937dd236cd2c85069bc4d25d63b9395c3837d038a6a1 +6510506c8b3a0537f05a3e1516d5d0e1dff6e1c8585509a4211d5802c67ea429 +c6eaa49f972c9c5c0e9f20e1d2b671bdbafcd696e5c6dd72538356317c53bc9c +78a1a251a2439829a273ff63e27a6c42f4ac611d201ff0b5f15b6b2ca91de8b1 +c451599c8b6a50d61b921cd8aef961de5b5c87c106475202869a1eb509342ccb +c06633f1befd3dcdf773eb70000bf7f2734b0e3a6fa7bd661fcf097fd02b92f2 +33af002ca98081e8ad5ed7ee4c98eb713b2efcf99e438539ad102376985fbcab +10d0f170d98e04c7f5e69df55e7a8ae551c8816f062267faae301c8005a467fd +c8b883aec2a74a283462789fbf4fea596f319025d91cadbced95cb8adb87a241 +0efb07b6a4a756818913bf23de832951ba921e3c03308dbe5cbc01e09567cfe7 +88da7e7cb4acdc70d1d20e46f6c9c3a5e1d870861ec52462dcc8b31a9f0542cf +b3aa829791a75a00955785a7e7488bc6603225e3ae8481b2b87a9b28163f65de +6c45dc893d6feee51662aee2b23821a10169e015b303c9238d4c367d9dc814c2 +bad01d346377ee7c179b8ee4cd281475165c8514242dacab1fb78ae32e3f3953 +7529855b6ae136b500c6a92510fe4220826af48ef09c37b773a999302424b17d +8288db737f90482a089004a5bcab79177b61b1953b5521b7d10e88fdae60b789 +0d1f547f1b46b36a2edae940b73f9701bc1711bef79fb786092d21bcacc65a2b +350a8a6a2f36177df3e9b6910736c9ea6417857294577d689c16cb5bbd1d889f +5e51fbd13f576914188fee55902e1e5f4ff58efecc038f382a9824352aa85dbe +f7a78c039f5f8246dfeb7e4c6f8aefc00e3da7f8c9c0622d6df136ada2796e41 +20807810dc99cadb7bfbb2df5a2c09db87a245e581af639128ea69c4d339dd7b +ab75b62054f3eb6ac2e6f5cb37eb2b7c2bea0d6a65a4b4318442460fcc0287f2 +5917e3a36a6a95590bb1a83668d777596a425c1b526807704f68c643da040c97 +308d2cca7d69cc834908dc5001a82b02897f831b0491b4c5a3c1161373168de2 +e1321bd2dda572077b2ec2f8b88aa430fca42d0af69c787a13f2386afc7c8daa +f5446e0448ca8772f6d0fd99f3140ede7b69183224e6e011b4fcfb7c594db4d6 +e8c185cc33b90d269803068e0a5f7bcae4f5a9fc2eea263cba4e4b75a642fab2 +169915adba620637d9d349beae5db9c371c61895dc5f784e1035c723d78c3c09 +e4a9dd3fd747ff068441b59989216cc248daa84736807d06b0a9ee91c381a033 +370ddd16080cb98795d226bf93a89eabd256318cc1ed755776020d5174e245ad +b45b69554735b834feaa42b7ed1db61b5d6b81edfba9f096548711036237859e +d0d8851a663442d6e5db6350254c016088eeed2a976647ba6d7b78b1a86dbd61 +5bb4ff0ba48656e4ffed976e62884b085bef7a10cdb49399ad2379259c9d02e3 +f89bb2f9e1369f5cd825c587e0a6b9bc4829e90fc5ca49e532dd685a46263787 +10c93d08502ad50c746594461b54b34a6c157ea9b9ed471e4c8e999d834c8d50 +1a05d3f26cc40bf010ad9156d7f6bbc459aa6a0f4499ac5ad7a29354aee21b1b +0bb49a004b91edbaccbcdb90e8a18e6c07d02b9e1954d66de69eba19b69757e8 +01c73d2641203e2423d6a7fe1257b8d34379b208a1e6805f9381a2f21c2a891c +15fe2fa515840075795393008a9581322703648591da93bed99ad109361a59e8 +c62825990a8440c274c80e65ef8dff2e8ade47ce3886f10c0c05bba0dfc727fd +136dd183d633b3c411dcf2cd24d532af295bb36f871f461fde35b1c8e3d3df25 +94cfac5d21d715e19124f5d7fea2d3875f7115dd1b786450bb2fd8279091cd77 +44b17c3682558d43f6eab340177eab3c82027ec15ad2e07a3bcd4de0121445dc +5a2a711010bfe13060edc9c0c376a5af472aeca1353d0c9dd2d49bdb2b8e646f +2a1fa00d8bb6dc6fdbd6276410baac7fa9484e8e6e6b3eba07aed18abd78c64c +8e0f76471b75811cee38fd2b47358b6f147351c57b7aa179f11171175fe22b6f +432033d08b9e5e0ffb80741dfd69355d1e5d9c8c07f33676f9479922da139cc4 +6d782673825562a6470b7a0e10461a66c285de24766357891bab39f01c8a4a05 +7aefe911de1e8d9e607d01dc9b8cdc9b29ada109661fe0e5934b268c6082169b +25c43f8b2e3360471ee8f44e9daa1b9acbecc2e51194e6d636d644ce0b6b377e +595d5b7bfd969b9a0be952e0b18b4cba81360b5f25ff7bd2c9b7885b6cd1011e +74f270c0402051ad23326bc7b2399477ea8fd3ead497a43bbc66ca029e99f84f +6aa9021cc9605232aad2577a12ec10bef66acf6c6769afb0e616b997520b3b27 +7bf453566f355a288515394e840b3cc3ee489ecc4503ce7f81b395949d403bee +eb2c59c3d0d6103c1551f664b4b1b3506afd9b4920a964dacf25a67fe3f89130 +1b472bfd6c7098563c07643d134f0d39fa60a292396e65c5a3c8791d50be06bf +e87e986f065e69741c78ebdc124e767125164c25e99e061c4b4d443b0f3a7a3b +48dacef7f9fe76a5b321d32b950d0ee36be4ccff7c56b427891106443b21fc0a +68d74a15fd8b3f2ee93063300dbf7d6fc271adf387ffc5f23366d0de5297c3b9 +a51d758c36c8f4be99aa50489c20d60646ef1887af0654a9759bf4b87263388f +bfc8ed7948ef10578c35fe90eb67e28acedd939e99c140ad8fe3a4b3d0538d10 +ce88a2e79cff50b821d8315f926b846aef2ece329b7e91b67dcaaf9f69031160 +67f7345ea4f5931499e84f7172d0e4a53a0a9e6f0aa22645c75bf780b0b7914d +a5b8812ef5a61a351c13bb2e4d2f76c27dca25609858cf2a26148d7a48d13003 +ac2bda07184f95dab06aac809ba50ec3a0db099d9bc9aaf3107fa6e1a15124d4 +5e609c4d7b3dd13dd3f932bcfa19ce5c01d9c3ccd7a2ff2e0b90228a975fec42 +4e2b7f80d8bdb6f3e1befbd9997bbdb3de791fe82ddeb96d1f959268621ed8d2 +0f534bb54bde0cb5dd0973909beec1496348d10d2ce1e4a5c9b46fd4b2ef7744 +55b0d015aa2b368009d934fe565ba5def3f1850a97eb1a2e3373864097ef00db +1635d2717db77cc6bdef0eedf599abedd401937c3f3c11bffb9de008159efc41 +a986e8ad1e5e8d5f9f69428a3f8fb80e1bef4436fc844c1b67005fffacb0709b +0f874ed4f0742fda758400f09bb2b26c162e0117c1e9749a60dc4f9b495bd136 +a101100b884b3f5e30aec67c000eb3057ac57a4c1eb72b3f373ff4fbade7d229 +742f05bca2e6919875be98607ccf6fac092051687a3444df7ed371b58e993de5 +dd1a1721ae5b6d1a43fe5f37fc4050c9b13c2ed5c983618dd1c763cfbc62eeb0 +cc2c05583884a537473f3c7f114d2ef9fa3ca54ce920bd22e9a4fc386966eb53 +88597fa7e08c753d95f9ace5b6df44c3922a7dbf6697e71c22d79e1a7c2af1ba +cbfa61ab6af64c84ff1fc0be29c2065bb44c202a1090333ff706266b789edfe8 +e48291964cc1b167f44f5dcc9ce0951de5f92193886ee2a58be64f20bfdebb4a +d5d6b4bd0081ce581a736efcbe15c038fac658ccf5e3172ed61fa198438a0899 +bddea82e4ff0004be423c1c7d8b74b8d193b817c1319e0039f3cba0f04d7e294 +c7ce1885cf3f8ea7ac1daabf1795ef575a007c815c5e9824c64188aabcb92ae7 +8d3d2ec8d97ce17bf9b85f1b7e957e21343759dd217f125cbc59b2859c2e104b +5e97e2af3f28b99ec5f1b8ae34437957d4df110a8b9fcb3474fc1229b351b800 +ad32d1eb9748b47c258a02d45176e994145e9dd4b596ac07ae815d46a05abe30 +93f6e65fbee64d7a1c6ecadba359c90593590ded3ad30918bc5d79062b7c94e5 +cd1ab9b034995d33549e3db1f32786ff5adbcdef3d08cf5f804171608a4aff4c +8f7b4a8b9f428d9ec51edc29291554fe62a1c8f68a72abba60d30bea0606a840 +1b583f37ab6753c36506e0269f9be05b2f8f5778fe340a832c8864f0dbbc9f5a +428494d420e2cd911baee09dbdd47ef580b93cc66ef68b0e8215ed48034541b6 +d403e8fdf9c3ab12d35db3ea70b671ecef6f4d8a93af267585eec6c9dfdcebf3 +d71e4ee309c689d3a784a08d58ce160d57ad6220e58f788851e34b895ac59c6d +fd9fc5338e98e49263d103012bde703826eb1cd6d3cd56d876287cb9cea1a05a +d02421d3a5343049ce2af9bb573097942621accf0c5c134477a20b5ded8af98e +0fab563ac3fdec4cdc090c59bc2c9537641d30f8ed8a695b76529a10c437b055 +dd600ad39dfe207ff3af60c3e486a8b2774d35f619cf529d72ba03d2be29cf1f +3324bae7b7be35f4154eb2e5d427f89560a35f559322f690b17ad5db51a0235e +b9d53d0f23cc5e202b0dc561366017867655f040ac069ba5b5083360c2220cdd +e9fb9734caceb88e8f98417997ee90b9fd60622e2ac4dbdbbb09b8c582d516d5 +b79d625449f6a40c43e003657820ca264ebe41dbb953e178f017e6d284c9cf9e +7d17c75ec6b8400c3d0edcc8948ffc80aad357616c05ce578c4f3d7bcadaa3e0 +16df796c318edcc908cff0fa5ddd914d9ef3356f658921f62669baa148757c56 +5918d31185451af525419197f7ddab80c37724d78ec530964ee7cc923d48ec2e +01ca696b493b7d8a8424e108eed4d9458ad5e20fd312dda34ecbb98e7ea10af4 +f2f6f382657a56f8607593b25f02e4cdbcf4ccfc5cea36388715b2f66297891e +4a9a87b08daf6ca44d02b054cf7db1bfb34eb8cb984f613a2c3f4688ef4df2d4 +9cc272bd5c6da992f1ea2673d1b5f056adde7c3a39b237422a9fa8646b11a6c4 +7155c70ce24ca1352c67e82d20c6ad534b4391a3c11baf892ca1309da7ac2d36 +d1215e0e73b3d666e2cd15099b3fb0bc720a36c288764a159400768b7ad5fded +ddf4de443aac0e0dc9f54e4f96038816aed77c043c6afc0c27f9363626d52a89 +e98fbef7bc39d965ae741b77305aa0df3248fc7ed66248b3f3501c750250df7c +17e402b28d6a5b5d5854039ff9ca675dc1eec6e287853926254a6712b403bb72 +70031c39ebcff8be522f1466268c68974c5cd3e9755b1f00eb463590674df837 +e9c796684467e17adbe6bc8c97540a4ff32a3664055217d97aa9229a908a7a3a +a7eaae57814f566c4c0058cb256b0497ee959b079939d804047e01ef8a7c78d4 +ada8428ab3c314c0bea6616910e938daec1527655b2203f511be858006f8467c +59cfda21574c51c7d604e7d3e4b2aef91f38895584c0440329b37012b9937d93 +34e87d92a65ba50bd5b04963ed4579934135d333817bcc80f4136bf510b4707b +a0be100d95340c192ba0bf40176d6e74e7652e00c23a29561156b6655fce7092 +1e1b2104bfefb61123f14e4a3146dc1df04d8127e42c2ace3787d7335e1a527f +4dd26986e6f2f3e3ed57a902e3a0147184ba7797e5ea8bbbfe00407857f094da +1e6eff62d586777a2032d295d61ee956b9f24b5551b675f82a0cee37a677e6e5 +47cde2e6b9d15fa725ea26c816503c9fe062abaeec06c739fc41fad9b5d18b61 +6476e227403aa3c7a21ef1330905d78eb7de2569676133a66a3ae8657b74bc42 +4ad4793d837d009ec2f59ec1a05f317c1f42e5c1e7072d08d61d897dc6bd4347 +499bb84206f74385921771556909dc66d16ce0fb8e3077d5ddfee7ac9571892f +a87f7f17fa5d9c7ae4cc53d63845d876805f27ff3d1b48ee3980e98d33ed6e69 +224b0115621c3b3be5f3f072db194024adbe8ede025d580c1bc4e1cdc41b668f +f23b3d7d741940a8a33c777b36a411aab50f077783b3c5f817eb7b320a8faea0 +193f21d1d20705361eff54ac32f51fd3ed67bbb89934631d515b4492890d4233 +b879bc1513cd538cf075b33e4b819bb54f7e3a3a4691a3e1020b902926b73d57 +6abc3bd44f55f03e24268e129593de555e44f6844adeed547d2e5f8d7cdc9f8a +f2474f7b32aae459c6cacea8d838cb527986ba8a1b3d79902b3059049d17dd76 +3eb5f58952e38a94f76ce59f868ac6e94c96be9fdea4c6285f208bde77fbb396 +18748bd910c92832c8e6ac9f44d22d918fa9d952074f3d4b5c47233fd2199b1a +9e98773a6b5f740404b04218e98c17c95044a133e271c1dfb0f074d8b43f1f3e +0fd7d3a8d254e82056cd89d55a65f621a1dac3cdc433f9a124db4fba1587af75 +09b5eb7444bc1bbd74226523076337f2c5712fd4113007f6154e5af81c9b0a99 +37459114e829009a1710b5f36e36728854e92d25cca4b0ef5a705c22ed0588da +5a3c5934931a34c3b8b174bc4b47933833342e1d42fa9f0963d467662810dc4e +bd291e7ff5459c55ad802a584429e0ae15c8b9573812d92631b556264507f634 +d8109bfa7346e32dc29120f567490ca3fb838c4c3de1b91e1e37f14e670f1167 +0fe9de5aefc66d1535338ffe014d60732078cc43d43d0fae5a966846eb4b279c +31c56cc7593a87e9cdca26f6f12d0e7b22cc68e65e749c3315bdcb172f5f2f62 +af74b29846efcfb196feb9d8b226dde567a1df5891eac5a1b570ca9c424ff41a +6c63d3fe5cea1acbcca1a5241b0f2c5836eeb70a26c5c497b973b33368b93ee9 +e743d765d0f44dc0046dba878775040aca86bacbb32dff12e3d35a6a7b5902e3 +13b72823adab1b3821efc8eb4371ec7ce0a2893bb62dd56071f5af634f44cdee +2eb28205d85fd8cf0f02a0ff3f84fd3a17d57305d992eb27c376e49b1c9f19b5 +4d4c9b7e293c8b84afe07c48838e98c5ffad17d9e0dee94953fa478c8444c6ed +865c585c3e2e6ae90ab2eeea3edee0d7b40f971bc10293eff05ed167a4aab9ab +929df5bfc60a89088e29ec21ccb091d0e0ded7c27d2ba28388db6485b8495511 +c60833c4d5dad64c9c33ab4fb76061060206113250f6e47d42b336526fd23213 +6e9ece77e66f63d4a54d7343e672df2f6f538e7c7268ac7f8ac2fa9567b51e9b +a36f99995c3d6a013d8ad41bce8483fab3cf2dde2542c9f0b46057fa45a455bf +c71dee6a4bbe16ce6126b792741329e7c33f30bfd6431d21f267c099c8b34be1 +fce08358bfce3ef549da7c0b89d3b42668d984d3034b5c3fa3f90c3d3eecfe88 +55e9afd1b57ed6611ba418b817b1870acfe6e86860a19352f2ed7d3f9fd381a2 diff --git a/bench/data/pathological/repeated-rare-huge.txt b/bench/data/pathological/repeated-rare-huge.txt new file mode 100644 index 0000000..b48cbcc --- /dev/null +++ b/bench/data/pathological/repeated-rare-huge.txt @@ -0,0 +1 @@ +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz \ No newline at end of file diff --git a/bench/data/pathological/repeated-rare-small.txt b/bench/data/pathological/repeated-rare-small.txt new file mode 100644 index 0000000..d806cc6 --- /dev/null +++ b/bench/data/pathological/repeated-rare-small.txt @@ -0,0 +1 @@ +zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz diff --git a/bench/data/sherlock/README.md b/bench/data/sherlock/README.md new file mode 100644 index 0000000..df5631c --- /dev/null +++ b/bench/data/sherlock/README.md @@ -0,0 +1,6 @@ +These were the original inputs used for the memchr benchmarks. In theory, they +could be replaced with the subtitle text in order to trim down the number of +inputs we use in the benchmark suite. + +The nice thing about the subtitle corpus is that it gives us a translation into +Russian and Chinese, which lets us measure our code on non-ASCII text. diff --git a/bench/data/sherlock-holmes-huge.txt b/bench/data/sherlock/huge.txt similarity index 100% rename from bench/data/sherlock-holmes-huge.txt rename to bench/data/sherlock/huge.txt diff --git a/bench/data/sherlock-holmes-small.txt b/bench/data/sherlock/small.txt similarity index 100% rename from bench/data/sherlock-holmes-small.txt rename to bench/data/sherlock/small.txt diff --git a/bench/data/sherlock-holmes-tiny.txt b/bench/data/sherlock/tiny.txt similarity index 100% rename from bench/data/sherlock-holmes-tiny.txt rename to bench/data/sherlock/tiny.txt diff --git a/bench/data/sliceslice/README.md b/bench/data/sliceslice/README.md new file mode 100644 index 0000000..bc1b14b --- /dev/null +++ b/bench/data/sliceslice/README.md @@ -0,0 +1,24 @@ +These benchmark inputs were taken from the sliceslice [project benchmarks][1]. + +These inputs drive two benchmarks, one on short haystacks and the other on long +haystacks, with a slightly unusual but interesting configuration. Neither of +these benchmarks include the time it takes to build a searcher. They only +measure actual search time. + +The short haystack benchmark starts by loading all of the words in `words.txt` +into memory and sorting them in ascending order by their length. Then, a +substring searcher is created for each of these words in the same order. The +actual benchmark consists of executing each searcher once on every needle that +appears after it in the list. In essence, this benchmark tests how quickly the +implementation can deal with tiny haystacks. The results of this benchmark tend +to come down to how much overhead the implementation has. In other words, this +benchmark tests latency. + +The long haystack benchmark has a setup similar to the short haystack +benchmark, except it also loads the contents of `i386.txt` into memory. The +actual benchmark itself executes each of the searchers built (from `words.txt`) +on the `i386.txt` haystack. This benchmark, executing on a much longer +haystack, tests throughput as opposed to latency across a wide variety of +needles. + +[1]: https://github.com/cloudflare/sliceslice-rs diff --git a/bench/data/sliceslice/i386-notutf8.txt b/bench/data/sliceslice/i386-notutf8.txt new file mode 100644 index 0000000..b0547fc --- /dev/null +++ b/bench/data/sliceslice/i386-notutf8.txt @@ -0,0 +1,20854 @@ +INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986 + +Intel Corporation makes no warranty for the use of its products and +assumes no responsibility for any errors which may appear in this document +nor does it make a commitment to update the information contained herein. + +Intel retains the right to make changes to these specifications at any +time, without notice. + +Contact your local sales office to obtain the latest specifications before +placing your order. + +The following are trademarks of Intel Corporation and may only be used to +identify Intel Products: + +Above, BITBUS, COMMputer, CREDIT, Data Pipeline, FASTPATH, Genius, i, , +ICE, iCEL, iCS, iDBP, iDIS, IICE, iLBX, im, iMDDX, iMMX, Inboard, +Insite, Intel, intel, intelBOS, Intel Certified, Intelevision, +inteligent Identifier, inteligent Programming, Intellec, Intellink, +iOSP, iPDS, iPSC, iRMK, iRMX, iSBC, iSBX, iSDM, iSXM, KEPROM, Library +Manager, MAPNET, MCS, Megachassis, MICROMAINFRAME, MULTIBUS, MULTICHANNEL, +MULTIMODULE, MultiSERVER, ONCE, OpenNET, OTP, PC BUBBLE, Plug-A-Bubble, +PROMPT, Promware, QUEST, QueX, Quick-Pulse Programming, Ripplemode, RMX/80, +RUPI, Seamless, SLD, SugarCube, SupportNET, UPI, and VLSiCEL, and the +combination of ICE, iCS, iRMX, iSBC, iSBX, iSXM, MCS, or UPI and a numerical +suffix, 4-SITE. + +MDS is an ordering code only and is not used as a product name or +trademark. MDS(R) is a registered trademark of Mohawk Data Sciences +Corporation. + +Additional copies of this manual or other Intel literature may be obtained +from: + +Intel Corporation +Literature Distribution +Mail Stop SC6-59 +3065 Bowers Avenue +Santa Clara, CA 95051 + +(c)INTEL CORPORATION 1987 CG-5/26/87 + + +Customer Support + + + +Customer Support is Intel's complete support service that provides Intel +customers with hardware support, software support, customer training, and +consulting services. For more information contact your local sales offices. + +After a customer purchases any system hardware or software product, +service and support become major factors in determining whether that +product will continue to meet a customer's expectations. Such support +requires an international support organization and a breadth of programs +to meet a variety of customer needs. As you might expect, Intel's customer +support is quite extensive. It includes factory repair services and +worldwide field service offices providing hardware repair services, +software support services, customer training classes, and consulting +services. + +Hardware Support Services + +Intel is committed to providing an international service support package +through a wide variety of service offerings available from Intel Hardware +Support. + +Software Support Services + +Intel's software support consists of two levels of contracts. Standard +support includes TIPS (Technical Information Phone Service), updates and +subscription service (product-specific troubleshooting guides and COMMENTS +Magazine). Basic support includes updates and the subscription service. +Contracts are sold in environments which represent product groupings +(i.e., iRMX environment). + +Consulting Services + +Intel provides field systems engineering services for any phase of your +development or support effort. You can use our systems engineers in a +variety of ways ranging from assistance in using a new product, developing +an application, personalizing training, and customizing or tailoring an +Intel product to providing technical and management consulting. Systems +Engineers are well versed in technical areas such as microcommunications, +real-time applications, embedded microcontrollers, and network services. +You know your application needs; we know our products. Working together we +can help you get a successful product to market in the least possible time. + +Customer Training + +Intel offers a wide range of instructional programs covering various +aspects of system design and implementation. In just three to ten days a +limited number of individuals learn more in a single workshop than in +weeks of self-study. For optimum convenience, workshops are scheduled +regularly at Training Centers woridwide or we can take our workshops to +you for on-site instruction. Covering a wide variety of topics, Intel's +major course categories include: architecture and assembly language, +programming and operating systems, bitbus and LAN applications. + +Training Center Locations + +To obtain a complete catalog of our workshops, call the nearest Training +Center in your area. + +Boston (617) 692-1000 +Chicago (312) 310-5700 +San Francisco (415) 940-7800 +Washington D.C. (301) 474-2878 +Isreal (972) 349-491-099 +Tokyo 03-437-6611 +Osaka (Call Tokyo) 03-437-6611 +Toronto, Canada (416) 675-2105 +London (0793) 696-000 +Munich (089) 5389-1 +Paris (01) 687-22-21 +Stockholm (468) 734-01-00 +Milan 39-2-82-44-071 +Benelux (Rotterdam) (10) 21-23-77 +Copenhagen (1) 198-033 +Hong Kong 5-215311-7 + + +Table of Contents + +Chapter 1 Introduction to the 80386 + +1.1 Organization of This Manual + 1.1.1 Part I Applications Programming + 1.1.2 Part II Systems Programming + 1.1.3 Part III Compatibility + 1.1.4 Part IV Instruction Set + 1.1.5 Appendices + +1.2 Related Literature +1.3 Notational Conventions + 1.3.1 Data-Structure Formats + 1.3.2 Undefined Bits and Software Compatibility + 1.3.3 Instruction Operands + 1.3.4 Hexadecimal Numbers + 1.3.5 Sub- and Super-Scripts + + PART I APPLICATIONS PROGRAMMING + +Chapter 2 Basic Programming Model + +2.1 Memory Organization and Segmentation + 2.1.1 The"Flat" Model + 2.1.2 The Segmented Model + +2.2 Data Types +2.3 Registers + 2.3.1 General Registers + 2.3.2 Segment Registers + 2.3.3 Stack Implementation + 2.3.4 Flags Register + 2.3.4.1 Status Flags + 2.3.4.2 Control Flag + 2.3.4.3 Instruction Pointer + +2.4 Instruction Format +2.5 Operand Selection + 2.5.1 Immediate Operands + 2.5.2 Register Operands + 2.5.3 Memory Operands + 2.5.3.1 Segment Selection + 2.5.3.2 Effective-Address Computation + +2.6 Interrupts and Exceptions + +Chapter 3 Applications Instruction Set + +3.1 Data Movement Instructions + 3.1.1 General-Purpose Data Movement Instructions + 3.1.2 Stack Manipulation Instructions + 3.1.3 Type Conversion Instructions + +3.2 Binary Arithmetic Instructions + 3.2.1 Addition and Subtraction Instructions + 3.2.2 Comparison and Sign Change Instruction + 3.2.3 Multiplication Instructions + 3.2.4 Division Instructions + +3.3 Decimal Arithmetic Instructions + 3.3.1 Packed BCD Adjustment Instructions + 3.3.2 Unpacked BCD Adjustment Instructions + +3.4 Logical Instructions + 3.4.1 Boolean Operation Instructions + 3.4.2 Bit Test and Modify Instructions + 3.4.3 Bit Scan Instructions + 3.4.4 Shift and Rotate Instructions + 3.4.4.1 Shift Instructions + 3.4.4.2 Double-Shift Instructions + 3.4.4.3 Rotate Instructions + 3.4.4.4 Fast"bit-blt" Using Double Shift + Instructions + 3.4.4.5 Fast Bit-String Insert and Extract + + 3.4.5 Byte-Set-On-Condition Instructions + 3.4.6 Test Instruction + +3.5 Control Transfer Instructions + 3.5.1 Unconditional Transfer Instructions + 3.5.1.1 Jump Instruction + 3.5.1.2 Call Instruction + 3.5.1.3 Return and Return-From-Interrupt Instruction + + 3.5.2 Conditional Transfer Instructions + 3.5.2.1 Conditional Jump Instructions + 3.5.2.2 Loop Instructions + 3.5.2.3 Executing a Loop or Repeat Zero Times + + 3.5.3 Software-Generated Interrupts + +3.6 String and Character Translation Instructions + 3.6.1 Repeat Prefixes + 3.6.2 Indexing and Direction Flag Control + 3.6.3 String Instructions + +3.7 Instructions for Block-Structured Languages +3.8 Flag Control Instructions + 3.8.1 Carry and Direction Flag Control Instructions + 3.8.2 Flag Transfer Instructions + +3.9 Coprocessor Interface Instructions +3.10 Segment Register Instructions + 3.10.1 Segment-Register Transfer Instructions + 3.10.2 Far Control Transfer Instructions + 3.10.3 Data Pointer Instructions + +3.11 Miscellaneous Instructions + 3.11.1 Address Calculation Instruction + 3.11.2 No-Operation Instruction + 3.11.3 Translate Instruction + + PART II SYSTEMS PROGRAMMING + +Chapter 4 Systems Architecture + +4.1 Systems Registers + 4.1.1 Systems Flags + 4.1.2 Memory-Management Registers + 4.1.3 Control Registers + 4.1.4 Debug Register + 4.1.5 Test Registers + +4.2 Systems Instructions + +Chapter 5 Memory Management + +5.1 Segment Translation + 5.1.1 Descriptors + 5.1.2 Descriptor Tables + 5.1.3 Selectors + 5.1.4 Segment Registers + +5.2 Page Translation + 5.2.1 Page Frame + 5.2.2 Linear Address + 5.2.3 Page Tables + 5.2.4 Page-Table Entries + 5.2.4.1 Page Frame Address + 5.2.4.2 Present Bit + 5.2.4.3 Accessed and Dirty Bits + 5.2.4.4 Read/Write and User/Supervisor Bits + + 5.2.5 Page Translation Cache + +5.3 Combining Segment and Page Translation + 5.3.1 "Flat" Architecture + 5.3.2 Segments Spanning Several Pages + 5.3.3 Pages Spanning Several Segments + 5.3.4 Non-Aligned Page and Segment Boundaries + 5.3.5 Aligned Page and Segment Boundaries + 5.3.6 Page-Table per Segment + +Chapter 6 Protection + +6.1 Why Protection? +6.2 Overview of 80386 Protection Mechanisms +6.3 Segment-Level Protection + 6.3.1 Descriptors Store Protection Parameters + 6.3.1.1 Type Checking + 6.3.1.2 Limit Checking + 6.3.1.3 Privilege Levels + + 6.3.2 Restricting Access to Data + 6.3.2.1 Accessing Data in Code Segments + + 6.3.3 Restricting Control Transfers + 6.3.4 Gate Descriptors Guard Procedure Entry Points + 6.3.4.1 Stack Switching + 6.3.4.2 Returning from a Procedure + + 6.3.5 Some Instructions are Reserved for Operating System + 6.3.5.1 Privileged Instructions + 6.3.5.2 Sensitive Instructions + + 6.3.6 Instructions for Pointer Validation + 6.3.6.1 Descriptor Validation + 6.3.6.2 Pointer Integrity and RPL + +6.4 Page-Level Protection + 6.4.1 Page-Table Entries Hold Protection Parameters + 6.4.1.1 Restricting Addressable Domain + 6.4.1.2 Type Checking + + 6.4.2 Combining Protection of Both Levels of Page Tables + 6.4.3 Overrides to Page Protection + +6.5 Combining Page and Segment Protection + +Chapter 7 Multitasking + +7.1 Task State Segment +7.2 TSS Descriptor +7.3 Task Register +7.4 Task Gate Descriptor +7.5 Task Switching +7.6 Task Linking + 7.6.1 Busy Bit Prevents Loops + 7.6.2 Modifying Task Linkages + +7.7 Task Address Space + 7.7.1 Task Linear-to-Physical Space Mapping + 7.7.2 Task Logical Address Space + +Chapter 8 Input/Output + +8.1 I/O Addressing + 8.1.1 I/O Address Space + 8.1.2 Memory-Mapped I/O + +8.2 I/O Instructions + 8.2.1 Register I/O Instructions + 8.2.2 Block I/O Instructions + +8.3 Protection and I/O + 8.3.1 I/O Privilege Level + 8.3.2 I/O Permission Bit Map + +Chapter 9 Exceptions and Interrupts + +9.1 Identifying Interrupts +9.2 Enabling and Disabling Interrupts + 9.2.1 NMI Masks Further NMls + 9.2.2 IF Masks INTR + 9.2.3 RF Masks Debug Faults + 9.2.4 MOV or POP to SS Masks Some Interrupts and Exceptions + +9.3 Priority Among Simultaneous Interrupts and Exceptions +9.4 Interrupt Descriptor Table +9.5 IDT Descriptors +9.6 Interrupt Tasks and Interrupt Procedures + 9.6.1 Interrupt Procedures + 9.6.1.1 Stack of Interrupt Procedure + 9.6.1.2 Returning from an Interrupt Procedure + 9.6.1.3 Flags Usage by Interrupt Procedure + 9.6.1.4 Protection in Interrupt Procedures + + 9.6.2 Interrupt Tasks + +9.7 Error Code +9.8 Exception Conditions + 9.8.1 Interrupt 0 Divide Error + 9.8.2 Interrupt 1 Debug Exceptions + 9.8.3 Interrupt 3 Breakpoint + 9.8.4 Interrupt 4 Overflow + 9.8.5 Interrupt 5 Bounds Check + 9.8.6 Interrupt 6 Invalid Opcode + 9.8.7 Interrupt 7 Coprocessor Not Available + 9.8.8 Interrupt 8 Double Fault + 9.8.9 Interrupt 9 Coprocessor Segment Overrun + 9.8.10 Interrupt 10 Invalid TSS + 9.8.11 Interrupt 11 Segment Not Present + 9.8.12 Interrupt 12 Stack Exception + 9.8.13 Interrupt 13 General Protection Exception + 9.8.14 Interrupt 14 Page Fault + 9.8.14.1 Page Fault during Task Switch + 9.8.14.2 Page Fault with Inconsistent Stack Pointer + + 9.8.15 Interrupt 16 Coprocessor Error + +9.9 Exception Summary + +9.10 Error Code Summary + +Chapter 10 Initialization + +10.1 Processor State after Reset +10.2 Software Initialization for Real-Address Mode + 10.2.1 Stack + 10.2.2 Interrupt Table + 10.2.3 First Instructions + +10.3 Switching to Protected Mode +10.4 Software Initialization for Protected Mode + 10.4.1 Interrupt Descriptor Table + 10.4.2 Stack + 10.4.3 Global Descriptor Table + 10.4.4 Page Tables + 10.4.5 First Task + +10.5 Initialization Example +10.6 TLB Testing + 10.6.1 Structure of the TLB + 10.6.2 Test Registers + 10.6.3 Test Operations + +Chapter 11 Coprocessing and Multiprocessing + +11.1 Coprocessing + 11.1.1 Coprocessor Identification + 11.1.2 ESC and WAIT Instructions + 11.1.3 EM and MP Flags + 11.1.4 The Task-Switched Flag + 11.1.5 Coprocessor Exceptions + 11.1.5.1 Interrupt 7 Coprocessor Not Available + 11.1.5.2 Interrupt 9 Coprocessor Segment Overrun + 11.1.5.3 Interrupt 16 Coprocessor Error + +11.2 General Multiprocessing + 11.2.1 LOCK and the LOCK# Signal + 11.2.2 Automatic Locking + 11.2.3 Cache Considerations + +Chapter 12 Debugging + +12.1 Debugging Features of the Architecture +12.2 Debug Registers + 12.2.1 Debug Address Registers (DRO-DR3) + 12.2.2 Debug Control Register (DR7) + 12.2.3 Debug Status Register (DR6) + 12.2.4 Breakpoint Field Recognition + +12.3 Debug Exceptions + 12.3.1 Interrupt 1 Debug Exceptions + 12.3.1.1 Instruction Address Breakpoint + 12.3.1.2 Data Address Breakpoint + 12.3.1.3 General Detect Fault + 12.3.1.4 Single-Step Trap + 12.3.1.5 Task Switch Breakpoint + + 12.3.2 Interrupt 3 Breakpoint Exception + + PART III COMPATIBILITY + +Chapter 13 Executing 80286 Protected-Mode Code + +13.1 80286 Code Executes as a Subset of the 80386 +13.2 Two Ways to Execute 80286 Tasks +13.3 Differences from 80286 + 13.3.1 Wraparound of 80286 24-Bit Physical Address Space + 13.3.2 Reserved Word of Descriptor + 13.3.3 New Descriptor Type Codes + 13.3.4 Restricted Semantics of LOCK + 13.3.5 Additional Exceptions + +Chapter 14 80386 Real-Address Mode + +14.1 Physical Address Formation +14.2 Registers and Instructions +14.3 Interrupt and Exception Handling +14.4 Entering and Leaving Real-Address Mode + 14.4.1 Switching to Protected Mode + +14.5 Switching Back to Real-Address Mode +14.6 Real-Address Mode Exceptions +14.7 Differences from 8086 +14.8 Differences from 80286 Real-Address Mode + 14.8.1 Bus Lock + 14.8.2 Location of First Instruction + 14.8.3 Initial Values of General Registers + 14.8.4 MSW Initialization + +Chapter 15 Virtual 8088 Mode + +15.1 Executing 8086 Code + 15.1.1 Registers and Instructions + 15.1.2 Linear Address Formation + +15.2 Structure of a V86 Task + 15.2.1 Using Paging for V86 Tasks + 15.2.2 Protection within a V86 Task + +15.3 Entering and Leaving V86 Mode + 15.3.1 Transitions Through Task Switches + 15.3.2 Transitions Through Trap Gates and Interrupt Gates + +15.4 Additional Sensitive Instructions + 15.4.1 Emulating 8086 Operating System Calls + 15.4.2 Virtualizing the Interrupt-Enable Flag + +15.5 Virtual I/O + 15.5.1 I/O-Mapped I/O + 15.5.2 Memory-Mapped I/O + 15.5.3 Special I/O Buffers + +15.6 Differences from 8086 +15.7 Differences from 80286 Real-Address Mode + +Chapter 16 Mixing 16-Bit and 32-Bit Code + +16.1 How the 80386 Implements 16-Bit and 32-Bit Features +16.2 Mixing 32-Bit and 16-Bit Operations +16.3 Sharing Data Segments among Mixed Code Segments +16.4 Transferring Control among Mixed Code Segments + 16.4.1 Size of Code-Segment Pointer + 16.4.2 Stack Management for Control Transfers + 16.4.2.1 Controlling the Operand-Size for a CALL + 16.4.2.2 Changing Size of Call + + 16.4.3 Interrupt Control Transfers + 16.4.4 Parameter Translation + 16.4.5 The Interface Procedure + + PART IV INSTRUCTION SET + +Chapter 17 80386 Instruction Set + +17.1 Operand-Size and Address-Size Attributes + 17.1.1 Default Segment Attribute + 17.1.2 Operand-Size and Address-Size Instruction Prefixes + 17.1.3 Address-Size Attribute for Stack + +17.2 Instruction Format + 17.2.1 ModR/M and SIB Bytes + 17.2.2 How to Read the Instruction Set Pages + 17.2.2.1 Opcode + 17.2.2.2 Instruction + 17.2.2.3 Clocks + 17.2.2.4 Description + 17.2.2.5 Operation + 17.2.2.6 Description + 17.2.2.7 Flags Affected + 17.2.2.8 Protected Mode Exceptions + 17.2.2.9 Real Address Mode Exceptions + 17.2.2.10 Virtual-8086 Mode Exceptions + +Instruction Sets + +AAA +AAD +AAM +AAS +ADC +ADD +AND +ARPL +BOUND +BSF +BSR +BT +BTC +BTR +BTS +CALL +CBW/CWDE +CLC +CLD +CLI +CLTS +CMC +CMP +CMPS/CMPSB/CMPSW/CMPSD +CWD/CDQ +DAA +DAS +DEC +DIV +ENTER +HLT +IDIV +IMUL +IN +INC +INS/INSB/INSW/INSD +INT/INTO +IRET/IRETD +Jcc +JMP +LAHF +LAR +LEA +LEAVE +LGDT/LIDT +LGS/LSS/LDS/LES/LFS +LLDT +LMSW +LOCK +LODS/LODSB/LODSW/LODSD +LOOP/LOOPcond +LSL +LTR +MOV +MOV +MOVS/MOVSB/MOVSW/MOVSD +MOVSX +MOVZX +MUL +NEG +NOP +NOT +OR +OUT +OUTS/OUTSB/OUTSW/OUTSD +POP +POPA/POPAD +POPF/POPFD +PUSH +PUSHA/PUSHAD +PUSHF/PUSHFD +RCL/RCR/ROL/ROR +REP/REPE/REPZ/REPNE/REPNZ +RET +SAHF +SAL/SAR/SHL/SHR +SBB +SCAS/SCASB/SCASW/SCASD +SETcc +SGDT/SIDT +SHLD +SHRD +SLDT +SMSW +STC +STD +STI +STOS/STOSB/STOSW/STOSD +STR +SUB +TEST +VERR,VERW +WAIT +XCHG +XLAT/XLATB +XOR + +Appendix A Opcode Map + +Appendix B Complete Flag Cross-Reference + +Appendix C Status Flag Summary + +Appendix D Condition Codes + + +Figures + +1-1 Example Data Structure + +2-1 Two-Component Pointer +2-2 Fundamental Data Types +2-3 Bytes, Words, and Doublewords in Memory +2-4 80386 Data Types +2-5 80386 Applications Register Set +2-6 Use of Memory Segmentation +2-7 80386 Stack +2-8 EFLAGS Register +2-9 Instruction Pointer Register +2-10 Effective Address Computation + +3-1 PUSH +3-2 PUSHA +3-3 POP +3-4 POPA +3-5 Sign Extension +3-6 SAL and SHL +3-7 SHR +3-8 SAR +3-9 Using SAR to Simulate IDIV +3-10 Shift Left Double +3-11 Shift Right Double +3-12 ROL +3-13 ROR +3-14 RCL +3-15 RCR +3-16 Formal Definition of the ENTER Instruction +3-17 Variable Access in Nested Procedures +3-18 Stack Frame for MAIN at Level 1 +3-19 Stack Frame for Prooedure A +3-20 Stack Frame for Procedure B at Level 3 Called from A +3-21 Stack Frame for Procedure C at Level 3 Called from B +3-22 LAHF and SAHF +3-23 Flag Format for PUSHF and POPF + +4-1 Systems Flags of EFLAGS Register +4-2 Control Registers + +5-1 Address Translation Overview +5-2 Segment Translation +5-3 General Segment-Descriptor Format +5-4 Format of Not-Present Descriptor +5-5 Descriptor Tables +5-6 Format of a Selector +5-7 Segment Registers +5-8 Format of a Linear Address +5-9 Page Translation +5-10 Format of a Page Table Entry +5-11 Invalid Page Table Entry +5-12 80386 Addressing Mechanism +5-13 Descriptor per Page Table + +6-1 Protection Fields of Segment Descriptors +6-2 Levels of Privilege +6-3 Privilege Check for Data Access +6-4 Privilege Check for Control Transfer without Gate +6-5 Format of 80386 Call Gate +6-6 Indirect Transfer via Call Gate +6-7 Privilege Check via Call Gate +6-8 Initial Stack Pointers of TSS +6-9 Stack Contents after an Interievel Call +6-10 Protection Fields of Page Table Entries + +7-1 80386 32-Bit Task State Segment +7-2 TSS Descriptor for 32-Bit TSS +7-3 Task Register +7-4 Task Gate Descriptor +7-5 Task Gate Indirectly Identifies Task +7-6 Partially-Overlapping Linear Spaces + +8-1 Memory-Mapped I/O +8-2 I/O Address Bit Map + +9-1 IDT Register and Table +9-2 Pseudo-Descriptor Format for LIDT and SIDT +9-3 80386 IDT Gate Descriptors +9-4 Interrupt Vectoring for Procedures +9-5 Stack Layout after Exception of Interrupt +9-6 Interrupt Vectoring for Tasks +9-7 Error Code Format +9-8 Page-Fault Error Code Format +9-9 CR2 Format + +10-1 Contents of EDX after RESET +10-2 Initial Contents of CRO +10-3 TLB Structure +10-4 Test Registers + +12-1 Debug Registers + +14-1 Real-Address Mode Address Formation + +15-1 V86 Mode Address Formation +15-2 Entering and Leaving an 8086 Program +15-3 PL 0 Stack after Interrupt in V86 Task + +16-1 Stack after Far 16-Bit and 32-Bit Calls + +17-1 80386 Instruction Format +17-2 ModR/M and SIB Byte Formats +17-3 Bit Offset for BIT[EAX, 21] +17-4 Memory Bit Indexing + + +Tables + +2-1 Default Segment Register Selection Rules +2-2 80386 Reserved Exceptions and Interrupts + +3-1 Bit Test and Modify Instructions +3-2 Interpretation of Conditional Transfers + +6-1 System and Gate Descriptor Types +6-2 Useful Combinations of E, G, and B Bits +6-3 Interievel Return Checks +6-4 Valid Descriptor Types for LSL +6-5 Combining Directory and Page Protection + +7-1 Checks Made during a Task Switch +7-2 Effect of Task Switch on BUSY, NT, and Back-Link + +9-1 Interrupt and Exception ID Assignments +9-2 Priority Among Simultaneous Interrupts and Exceptions +9-3 Double-Fault Detection Classes +9-4 Double-Fault Definition +9-5 Conditions That Invalidate the TSS +9-6 Exception Summary +9-7 Error-Code Summary + +10-1 Meaning of D, U, and W Bit Pairs + +12-1 Breakpeint Field Recognition Examples +12-2 Debug Exception Conditions + +14-1 80386 Real-Address Mode Exceptions +14-2 New 80386 Exceptions + +17-1 Effective Size Attributes +17-2 16-Bit Addressing Forms with the ModR/M Byte +17-3 32-Bit Addressing Forms with the ModR/M Byte +17-4 32-Bit Addressing Forms with the SIB Byte +17-5 Task Switch Times for Exceptions +17-6 80386 Exceptions + + +Chapter 1 Introduction to the 80386 + + + +The 80386 is an advanced 32-bit microprocessor optimized for multitasking +operating systems and designed for applications needing very high +performance. The 32-bit registers and data paths support 32-bit addresses +and data types. The processor can address up to four gigabytes of physical +memory and 64 terabytes (2^(46) bytes) of virtual memory. The on-chip +memory-management facilities include address translation registers, +advanced multitasking hardware, a protection mechanism, and paged virtual +memory. Special debugging registers provide data and code breakpoints even +in ROM-based software. + + +1.1 Organization of This Manual + +This book presents the architecture of the 80386 in five parts: + + Part I Applications Programming + Part II Systems Programming + Part III Compatibility + Part IV Instruction Set + Appendices + +These divisions are determined in part by the architecture itself and in +part by the different ways the book will be used. As the following table +indicates, the latter two parts are intended as reference material for +programmers actually engaged in the process of developing software for the +80386. The first three parts are explanatory, showing the purpose of +architectural features, developing terminology and concepts, and describing +instructions as they relate to specific purposes or to specific +architectural features. + +Explanation Part I Applications Programming + Part II Systems Programming + Part III Compatibility + +Reference Part IV Instruction Set + Appendices + +The first three parts follow the execution modes and protection features of +the 80386 CPU. The distinction between applications features and systems +features is determined by the protection mechanism of the 80386. One purpose +of protection is to prevent applications from interfering with the operating +system; therefore, the processor makes certain registers and instructions +inaccessible to applications programs. The features discussed in Part I are +those that are accessible to applications; the features in Part II are +available only to systems software that has been given special privileges or +in unprotected systems. + +The processing mode of the 80386 also determines the features that are +accessible. The 80386 has three processing modes: + + 1. Protected Mode. + 2. Real-Address Mode. + 3. Virtual 8086 Mode. + +Protected mode is the natural 32-bit environment of the 80386 processor. In +this mode all instructions and features are available. + +Real-address mode (often called just "real mode") is the mode of the +processor immediately after RESET. In real mode the 80386 appears to +programmers as a fast 8086 with some new instructions. Most applications of +the 80386 will use real mode for initialization only. + +Virtual 8086 mode (also called V86 mode) is a dynamic mode in the sense +that the processor can switch repeatedly and rapidly between V86 mode and +protected mode. The CPU enters V86 mode from protected mode to execute an +8086 program, then leaves V86 mode and enters protected mode to continue +executing a native 80386 program. + +The features that are available to applications programs in protected mode +and to all programs in V86 mode are the same. These features form the +content of Part I. The additional features that are available to systems +software in protected mode form Part II. Part III explains real-address +mode and V86 mode, as well as how to execute a mix of 32-bit and 16-bit +programs. + +Available in All Modes Part I Applications Programming + +Available in Protected Part II Systems Programming +Mode Only + +Compatibility Modes Part III Compatibility + + +1.1.1 Part I Applications Programming + +This part presents those aspects of the architecture that are customarily +used by applications programmers. + +Chapter 2 Basic Programming Model: Introduces the models of memory +organization. Defines the data types. Presents the register set used by +applications. Introduces the stack. Explains string operations. Defines the +parts of an instruction. Explains addressing calculations. Introduces +interrupts and exceptions as they may apply to applications programming. + +Chapter 3 Application Instruction Set: Surveys the instructions commonly +used for applications programming. Considers instructions in functionally +related groups; for example, string instructions are considered in one +section, while control-transfer instructions are considered in another. +Explains the concepts behind the instructions. Details of individual +instructions are deferred until Part IV, the instruction-set reference. + + +1.1.2 Part II Systems Programming + +This part presents those aspects of the architecture that are customarily +used by programmers who write operating systems, device drivers, debuggers, +and other software that supports applications programs in the protected mode +of the 80386. + +Chapter 4 Systems Architecture: Surveys the features of the 80386 that +are used by systems programmers. Introduces the remaining registers and data +structures of the 80386 that were not discussed in Part I. Introduces the +systems-oriented instructions in the context of the registers and data +structures they support. Points to the chapter where each register, data +structure, and instruction is considered in more detail. + +Chapter 5 Memory Management: Presents details of the data structures, +registers, and instructions that support virtual memory and the concepts of +segmentation and paging. Explains how systems designers can choose a model +of memory organization ranging from completely linear ("flat") to fully +paged and segmented. + +Chapter 6 Protection: Expands on the memory management features of the +80386 to include protection as it applies to both segments and pages. +Explains the implementation of privilege rules, stack switching, pointer +validation, user and supervisor modes. Protection aspects of multitasking +are deferred until the following chapter. + +Chapter 7 Multitasking: Explains how the hardware of the 80386 supports +multitasking with context-switching operations and intertask protection. + +Chapter 8 Input/Output: Reveals the I/O features of the 80386, including +I/O instructions, protection as it relates to I/O, and the I/O permission +map. + +Chapter 9 Exceptions and Interrupts: Explains the basic interrupt +mechanisms of the 80386. Shows how interrupts and exceptions relate to +protection. Discusses all possible exceptions, listing causes and including +information needed to handle and recover from the exception. + +Chapter 10 Initialization: Defines the condition of the processor after +RESET or power-up. Explains how to set up registers, flags, and data +structures for either real-address mode or protected mode. Contains an +example of an initialization program. + +Chapter 11 Coprocessing and Multiprocessing: Explains the instructions +and flags that support a numerics coprocessor and multiple CPUs with shared +memory. + +Chapter 12 Debugging: Tells how to use the debugging registers of the +80386. + + +1.1.3 Part III Compatibility + +Other parts of the book treat the processor primarily as a 32-bit machine, +omitting for simplicity its facilities for 16-bit operations. Indeed, the +80386 is a 32-bit machine, but its design fully supports 16-bit operands and +addressing, too. This part completes the picture of the 80386 by explaining +the features of the architecture that support 16-bit programs and 16-bit +operations in 32-bit programs. All three processor modes are used to +execute 16-bit programs: protected mode can directly execute 16-bit 80286 +protected mode programs, real mode executes 8086 programs and real-mode +80286 programs, and virtual 8086 mode executes 8086 programs in a +multitasking environment with other 80386 protected-mode programs. In +addition, 32-bit and 16-bit modules and individual 32-bit and 16-bit +operations can be mixed in protected mode. + +Chapter 13 Executing 80286 Protected-Mode Code: In its protected mode, +the 80386 can execute complete 80286 protected-mode systems, because 80286 +capabilities are a subset of 80386 capabilities. + +Chapter 14 80386 Real-Address Mode: Explains the real mode of the 80386 +CPU. In this mode the 80386 appears as a fast real-mode 80286 or fast 8086 +enhanced with additional instructions. + +Chapter 15 Virtual 8086 Mode: The 80386 can switch rapidly between its +protected mode and V86 mode, giving it the ability to multiprogram 8086 +programs along with "native mode" 32-bit programs. + +Chapter 16 Mixing 16-Bit and 32-Bit Code: Even within a program or task, +the 80386 can mix 16-bit and 32-bit modules. Furthermore, any given module +can utilize both 16-bit and 32-bit operands and addresses. + + +1.1.4 Part IV Instruction Set + +Parts I, II, and III present overviews of the instructions as they relate +to specific aspects of the architecture, but this part presents the +instructions in alphabetical order, providing the detail needed by +assembly-language programmers and programmers of debuggers, compilers, +operating systems, etc. Instruction descriptions include algorithmic +description of operation, effect of flag settings, effect on flag settings, +effect of operand- or address-size attributes, effect of processor modes, +and possible exceptions. + + +1.1.5 Appendices + +The appendices present tables of encodings and other details in a format +designed for quick reference by assembly-language and systems programmers. + + +1.2 Related Literature + +The following books contain additional material concerning the 80386 +microprocessor: + + Introduction to the 80386, order number 231252 + + 80386 Hardware Reference Manual, order number 231732 + + 80386 System Software Writer's Guide, order number 231499 + + 80386 High Performance 32-bit Microprocessor with Integrated Memory + Management (Data Sheet), order number 231630 + + +1.3 Notational Conventions + +This manual uses special notations for data-structure formats, for symbolic +representation of instructions, for hexadecimal numbers, and for super- and +sub-scripts. Subscript characters are surrounded by {curly brackets}, for +example 10{2} = 10 base 2. Superscript characters are preceeded by a caret +and enclosed within (parentheses), for example 10^(3) = 10 to the third +power. A review of these notations will make it easier to read the +manual. + +1.3.1 Data-Structure Formats + +In illustrations of data structures in memory, smaller addresses appear at +the lower-right part of the figure; addresses increase toward the left and +upwards. Bit positions are numbered from right to left. Figure 1-1 +illustrates this convention. + + +1.3.2 Undefined Bits and Software Compatibility + +In many register and memory layout descriptions, certain bits are marked as +undefined. When bits are marked as undefined (as illustrated in Figure +1-1), it is essential for compatibility with future processors that +software treat these bits as undefined. Software should follow these +guidelines in dealing with undefined bits: + + Do not depend on the states of any undefined bits when testing the + values of registers that contain such bits. Mask out the undefined bits + before testing. + + Do not depend on the states of any undefined bits when storing them in + memory or in another register. + + Do not depend on the ability to retain information written into any + undefined bits. + + When loading a register, always load the undefined bits as zeros or + reload them with values previously stored from the same register. + + +NOTE + Depending upon the values of undefined register bits will make software + dependent upon the unspecified manner in which the 80386 handles these + bits. Depending upon undefined values risks making software incompatible + with future processors that define usages for these bits. AVOID ANY + SOFTWARE DEPENDENCE UPON THE STATE OF UNDEFINED 80386 REGISTER BITS. + + + +Figure 1-1. Example Data Structure + + GREATEST DATA STRUCTURE + ADDRESS + 31 23 15 7 0 BIT + ͻ OFFSET + 28 + ͹ + 24 + ͹ + 20 + ͹ + 16 + ͹ + 12 + ͹ + 8 + ͹ + UNDEFINED 4 + ͹ SMALLEST + BYTE 3 BYTE 2 BYTE 1 BYTE 0 0 ADDRESS + ͼ + BYTE OFFSET + + +1.3.3 Instruction Operands + +When instructions are represented symbolically, a subset of the 80386 +Assembly Language is used. In this subset, an instruction has the following +format: + +label: prefix mnemonic argument1, argument2, argument3 + +where: + + A label is an identifier that is followed by a colon. + + A prefix is an optional reserved name for one of the instruction + prefixes. + + A mnemonic is a reserved name for a class of instruction opcodes that + have the same function. + + The operands argument1, argument2, and argument3 are optional. There + may be from zero to three operands, depending on the opcode. When + present, they take the form of either literals or identifiers for data + items. Operand identifiers are either reserved names of registers or + are assumed to be assigned to data items declared in another part of + the program (which may not be shown in the example). When two operands + are present in an instruction that modifies data, the right operand is + the source and the left operand is the destination. + +For example: + +LOADREG: MOV EAX, SUBTOTAL + +In this example LOADREG is a label, MOV is the mnemonic identifier of an +opcode, EAX is the destination operand, and SUBTOTAL is the source operand. + +1.3.4 Hexadecimal Numbers + +Base 16 numbers are represented by a string of hexadecimal digits followed +by the character H. A hexadecimal digit is a character from the set (0, 1, +2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). In some cases, especially in +examples of program syntax, a leading zero is added if the number would +otherwise begin with one of the digits A-F. For example, 0FH is equivalent +to the decimal number 15. + +1.3.5 Sub- and Super-Scripts + +This manual uses special notation to represent sub- and super-script +characters. Sub-script characters are surrounded by {curly brackets}, for +example 10{2} = 10 base 2. Super-script characters are preceeded by a +caret and enclosed within (parentheses), for example 10^(3) = 10 to the +third power. + + + PART I APPLICATIONS PROGRAMMING + + +Chapter 2 Basic Programming Model + + + +This chapter describes the 80386 application programming environment as +seen by assembly language programmers when the processor is executing in +protected mode. The chapter introduces programmers to those features of the +80386 architecture that directly affect the design and implementation of +80386 applications programs. Other chapters discuss 80386 features that +relate to systems programming or to compatibility with other processors of +the 8086 family. + +The basic programming model consists of these aspects: + + Memory organization and segmentation + Data types + Registers + Instruction format + Operand selection + Interrupts and exceptions + +Note that input/output is not included as part of the basic programming +model. Systems designers may choose to make I/O instructions available to +applications or may choose to reserve these functions for the operating +system. For this reason, the I/O features of the 80386 are discussed in Part +II. + +This chapter contains a section for each aspect of the architecture that is +normally visible to applications. + + +2.1 Memory Organization and Segmentation + +The physical memory of an 80386 system is organized as a sequence of 8-bit +bytes. Each byte is assigned a unique address that ranges from zero to a +maximum of 2^(32) -1 (4 gigabytes). + +80386 programs, however, are independent of the physical address space. +This means that programs can be written without knowledge of how much +physical memory is available and without knowledge of exactly where in +physical memory the instructions and data are located. + +The model of memory organization seen by applications programmers is +determined by systems-software designers. The architecture of the 80386 +gives designers the freedom to choose a model for each task. The model of +memory organization can range between the following extremes: + + A "flat" address space consisting of a single array of up to 4 + gigabytes. + + A segmented address space consisting of a collection of up to 16,383 + linear address spaces of up to 4 gigabytes each. + +Both models can provide memory protection. Different tasks may employ +different models of memory organization. The criteria that designers use to +determine a memory organization model and the means that systems programmers +use to implement that model are covered in Part IISystems Programming. + + +2.1.1 The "Flat" Model + +In a "flat" model of memory organization, the applications programmer sees +a single array of up to 2^(32) bytes (4 gigabytes). While the physical +memory can contain up to 4 gigabytes, it is usually much smaller; the +processor maps the 4 gigabyte flat space onto the physical address space by +the address translation mechanisms described in Chapter 5. Applications +programmers do not need to know the details of the mapping. + +A pointer into this flat address space is a 32-bit ordinal number that may +range from 0 to 2^(32) -1. Relocation of separately-compiled modules in this +space must be performed by systems software (e.g., linkers, locators, +binders, loaders). + + +2.1.2 The Segmented Model + +In a segmented model of memory organization, the address space as viewed by +an applications program (called the logical address space) is a much larger +space of up to 2^(46) bytes (64 terabytes). The processor maps the 64 +terabyte logical address space onto the physical address space (up to 4 +gigabytes) by the address translation mechanisms described in Chapter 5. +Applications programmers do not need to know the details of this mapping. + +Applications programmers view the logical address space of the 80386 as a +collection of up to 16,383 one-dimensional subspaces, each with a specified +length. Each of these linear subspaces is called a segment. A segment is a +unit of contiguous address space. Segment sizes may range from one byte up +to a maximum of 2^(32) bytes (4 gigabytes). + +A complete pointer in this address space consists of two parts (see Figure +2-1): + + 1. A segment selector, which is a 16-bit field that identifies a + segment. + + 2. An offset, which is a 32-bit ordinal that addresses to the byte level + within a segment. + +During execution of a program, the processor associates with a segment +selector the physical address of the beginning of the segment. Separately +compiled modules can be relocated at run time by changing the base address +of their segments. The size of a segment is variable; therefore, a segment +can be exactly the size of the module it contains. + + +2.2 Data Types + +Bytes, words, and doublewords are the fundamental data types (refer to +Figure 2-2). A byte is eight contiguous bits starting at any logical +address. The bits are numbered 0 through 7; bit zero is the least +significant bit. + +A word is two contiguous bytes starting at any byte address. A word thus +contains 16 bits. The bits of a word are numbered from 0 through 15; bit 0 +is the least significant bit. The byte containing bit 0 of the word is +called the low byte; the byte containing bit 15 is called the high byte. + +Each byte within a word has its own address, and the smaller of the +addresses is the address of the word. The byte at this lower address +contains the eight least significant bits of the word, while the byte at the +higher address contains the eight most significant bits. + +A doubleword is two contiguous words starting at any byte address. A +doubleword thus contains 32 bits. The bits of a doubleword are numbered from +0 through 31; bit 0 is the least significant bit. The word containing bit 0 +of the doubleword is called the low word; the word containing bit 31 is +called the high word. + +Each byte within a doubleword has its own address, and the smallest of the +addresses is the address of the doubleword. The byte at this lowest address +contains the eight least significant bits of the doubleword, while the byte +at the highest address contains the eight most significant bits. Figure 2-3 +illustrates the arrangement of bytes within words anddoublewords. + +Note that words need not be aligned at even-numbered addresses and +doublewords need not be aligned at addresses evenly divisible by four. This +allows maximum flexibility in data structures (e.g., records containing +mixed byte, word, and doubleword items) and efficiency in memory +utilization. When used in a configuration with a 32-bit bus, actual +transfers of data between processor and memory take place in units of +doublewords beginning at addresses evenly divisible by four; however, the +processor converts requests for misaligned words or doublewords into the +appropriate sequences of requests acceptable to the memory interface. Such +misaligned data transfers reduce performance by requiring extra memory +cycles. For maximum performance, data structures (including stacks) should +be designed in such a way that, whenever possible, word operands are aligned +at even addresses and doubleword operands are aligned at addresses evenly +divisible by four. Due to instruction prefetching and queuing within the +CPU, there is no requirement for instructions to be aligned on word or +doubleword boundaries. (However, a slight increase in speed results if the +target addresses of control transfers are evenly divisible by four.) + +Although bytes, words, and doublewords are the fundamental types of +operands, the processor also supports additional interpretations of these +operands. Depending on the instruction referring to the operand, the +following additional data types are recognized: + +Integer: +A signed binary numeric value contained in a 32-bit doubleword,16-bit word, +or 8-bit byte. All operations assume a 2's complement representation. The +sign bit is located in bit 7 in a byte, bit 15 in a word, and bit 31 in a +doubleword. The sign bit has the value zero for positive integers and one +for negative. Since the high-order bit is used for a sign, the range of an +8-bit integer is -128 through +127; 16-bit integers may range from -32,768 +through +32,767; 32-bit integers may range from -2^(31) through +2^(31) -1. +The value zero has a positive sign. + +Ordinal: +An unsigned binary numeric value contained in a 32-bit doubleword, +16-bit word, or 8-bit byte. All bits are considered in determining +magnitude of the number. The value range of an 8-bit ordinal number +is 0-255; 16 bits can represent values from 0 through 65,535; 32 bits +can represent values from 0 through 2^(32) -1. + +Near Pointer: +A 32-bit logical address. A near pointer is an offset within a segment. +Near pointers are used in either a flat or a segmented model of memory +organization. + +Far Pointer: +A 48-bit logical address of two components: a 16-bit segment selector +component and a 32-bit offset component. Far pointers are used by +applications programmers only when systems designers choose a +segmented memory organization. + +String: +A contiguous sequence of bytes, words, or doublewords. A string may +contain from zero bytes to 2^(32) -1 bytes (4 gigabytes). + +Bit field: +A contiguous sequence of bits. A bit field may begin at any bit position +of any byte and may contain up to 32 bits. + +Bit string: +A contiguous sequence of bits. A bit string may begin at any bit position +of any byte and may contain up to 2^(32) -1 bits. + +BCD: +A byte (unpacked) representation of a decimal digit in the range0 through +9. Unpacked decimal numbers are stored as unsigned byte quantities. One +digit is stored in each byte. The magnitude of the number is determined from +the low-order half-byte; hexadecimal values 0-9 are valid and are +interpreted as decimal numbers. The high-order half-byte must be zero for +multiplication and division; it may contain any value for addition and +subtraction. + +Packed BCD: +A byte (packed) representation of two decimal digits, each in the range +0 through 9. One digit is stored in each half-byte. The digit in the +high-order half-byte is the most significant. Values 0-9 are valid in each +half-byte. The range of a packed decimal byte is 0-99. + +Figure 2-4 graphically summarizes the data types supported by the 80386. + + +Figure 2-1. Two-Component Pointer + +   + + ͹Ŀ + 32 0 + ͻ ͻ ͹ + OFFSET Ķ +  OPERAND + ͼ ͼ ͹ SELECTED SEGMENT +  + 16 0 + ͻ + SEGMENT͹ + ͼ + + +   + + +Figure 2-2. Fundamental Data Types + + 7 0 + ͻ + BYTE BYTE + ͼ + + 15 7 0 + ͻ + HIGH BYTE LOW BYTE WORD + ͼ + address n+1 address n + + 31 23 15 7 0 + ͻ + HIGH WORD LOW WORD DOUBLEWORD + ͼ + address n+3 address n+2 address n+1 address n + + +Figure 2-3. Bytes, Words, and Doublewords in Memory + + MEMORY + BYTE VALUES +All values in hexadecimal + ADDRESS ͻ + E + ͹Ŀ + D 7A DOUBLE WORD AT ADDRESS A + ͹Ŀ CONTAINS 7AFE0636 + C FE + ͹ WORD AT ADDRESS B + B 06 CONTAINS FE06 + ͹ٳ + A 36 + ͹͵ + 9 1F WORD AT ADDRESS 9 + ͹ CONTAINS IF + 8 + ͹Ŀ + 7 23 + ͹ WORD AT ADDRESS 6 + 6 OB CONTAINS 23OB + ͹ + 5 + ͹ + 4 + ͹Ŀ + 3 74 + ͹Ŀ WORD AT ADDRESS 2 + 2 CB CONTAINS 74CB + ͹ + 1 31 WORD AT ADDRESS 1 + ͹ CONTAINS CB31 + 0 + ͼ + + +Figure 2-4. 80386 Data Types + + +1 0 + 7 0 7 0 15 14 8 7 0 + BYTE ѻ BYTE ѻ WORD ѻ + INTEGER ORDINAL INTEGER + ͼ ͼ ͼ + SIGN BIT SIGN BITMSB + MAGNITUDE MAGNITUDE + MAGNITUDE + + + +1 0 +3 +2 +1 0 + 15 0 31 16 15 0 + WORD ѻ DOUBLEWORD ѻ + ORDINAL INTEGER + ͼ ͼ + SIGN BITMSB + + MAGNITUDE MAGNITUDE + + + +3 +2 +1 0 + 31 0 + DOUBLEWORD ѻ + ORDINAL + ͼ + + MAGNITUDE + + +N +1 0 + 7 0 7 0 7 0 + BINARY CODED ѻ ѻ + DECIMAL (BCD)  + ͼ ͼ + BCD BCD BCD + DIGIT N DIGIT 1 DIGIT 0 + + +N +1 0 + 7 0 7 0 7 0 + PACKED ѻ ѻ + BCD  + ͼ ͼ + + MOST LEAST + SIGNIFICANT SIGNIFICANT + DIGIT DIGIT + + +N +1 0 + 7 0 7 0 7 0 + BYTE ѻ ѻ + STRING  + ͼ ͼ + + -2 GIGABYTES + +2 GIGABYTES 210 + BIT ѻ + STRING + ϼ + BIT 0 + + +3 +2 +1 0 + 31 0 +NEAR 32-BIT ѻ + POINTER + ͼ + + OFFSET + + +5 +4 +3 +2 +1 0 + 48 0 +FAR 48-BIT ѻ + POINTER + ͼ + + SELECTOR OFFSET + + +5 +4 +3 +2 +1 0 + 32-BIT ѻ + BIT FIELD + ͼ +  BIT FIELD  + 1 TO 32 BITS + + +2.3 Registers + +The 80386 contains a total of sixteen registers that are of interest to the +applications programmer. As Figure 2-5 shows, these registers may be +grouped into these basic categories: + + 1. General registers. These eight 32-bit general-purpose registers are + used primarily to contain operands for arithmetic and logical + operations. + + 2. Segment registers. These special-purpose registers permit systems + software designers to choose either a flat or segmented model of + memory organization. These six registers determine, at any given time, + which segments of memory are currently addressable. + + 3. Status and instruction registers. These special-purpose registers are + used to record and alter certain aspects of the 80386 processor state. + + +2.3.1 General Registers + +The general registers of the 80386 are the 32-bit registers EAX, EBX, ECX, +EDX, EBP, ESP, ESI, and EDI. These registers are used interchangeably to +contain the operands of logical and arithmetic operations. They may also be +used interchangeably for operands of address computations (except that ESP +cannot be used as an index operand). + +As Figure 2-5 shows, the low-order word of each of these eight registers +has a separate name and can be treated as a unit. This feature is useful for +handling 16-bit data items and for compatibility with the 8086 and 80286 +processors. The word registers are named AX, BX, CX, DX, BP, SP, SI, and DI. + +Figure 2-5 also illustrates that each byte of the 16-bit registers AX, BX, +CX, and DX has a separate name and can be treated as a unit. This feature is +useful for handling characters and other 8-bit data items. The byte +registers are named AH, BH, CH, and DH (high bytes); and AL, BL, CL, and DL +(low bytes). + +All of the general-purpose registers are available for addressing +calculations and for the results of most arithmetic and logical +calculations; however, a few functions are dedicated to certain registers. +By implicitly choosing registers for these functions, the 80386 architecture +can encode instructions more compactly. The instructions that use specific +registers include: double-precision multiply and divide, I/O, string +instructions, translate, loop, variable shift and rotate, and stack +operations. + + +2.3.2 Segment Registers + +The segment registers of the 80386 give systems software designers the +flexibility to choose among various models of memory organization. +Implementation of memory models is the subject of Part II Systems +Programming. Designers may choose a model in which applications programs do +not need to modify segment registers, in which case applications programmers +may skip this section. + +Complete programs generally consist of many different modules, each +consisting of instructions and data. However, at any given time during +program execution, only a small subset of a program's modules are actually +in use. The 80386 architecture takes advantage of this by providing +mechanisms to support direct access to the instructions and data of the +current module's environment, with access to additional segments on demand. + +At any given instant, six segments of memory may be immediately accessible +to an executing 80386 program. The segment registers CS, DS, SS, ES, FS, and +GS are used to identify these six current segments. Each of these registers +specifies a particular kind of segment, as characterized by the associated +mnemonics ("code," "data," or "stack") shown in Figure 2-6. Each register +uniquely determines one particular segment, from among the segments that +make up the program, that is to be immediately accessible at highest speed. + +The segment containing the currently executing sequence of instructions is +known as the current code segment; it is specified by means of the CS +register. The 80386 fetches all instructions from this code segment, using +as an offset the contents of the instruction pointer. CS is changed +implicitly as the result of intersegment control-transfer instructions (for +example, CALL and JMP), interrupts, and exceptions. + +Subroutine calls, parameters, and procedure activation records usually +require that a region of memory be allocated for a stack. All stack +operations use the SS register to locate the stack. Unlike CS, the SS +register can be loaded explicitly, thereby permitting programmers to define +stacks dynamically. + +The DS, ES, FS, and GS registers allow the specification of four data +segments, each addressable by the currently executing program. Accessibility +to four separate data areas helps programs efficiently access different +types of data structures; for example, one data segment register can point +to the data structures of the current module, another to the exported data +of a higher-level module, another to a dynamically created data structure, +and another to data shared with another task. An operand within a data +segment is addressed by specifying its offset either directly in an +instruction or indirectly via general registers. + +Depending on the structure of data (e.g., the way data is parceled into one +or more segments), a program may require access to more than four data +segments. To access additional segments, the DS, ES, FS, and GS registers +can be changed under program control during the course of a program's +execution. This simply requires that the program execute an instruction to +load the appropriate segment register prior to executing instructions that +access the data. + +The processor associates a base address with each segment selected by a +segment register. To address an element within a segment, a 32-bit offset is +added to the segment's base address. Once a segment is selected (by loading +the segment selector into a segment register), a data manipulation +instruction only needs to specify the offset. Simple rules define which +segment register is used to form an address when only an offset is +specified. + + +Figure 2-5. 80386 Applications Register Set + + GENERAL REGISTERS + + 31 23 15 7 0 + ͻ + EAX AH AX AL + ͹ + EDX DH DX DL + ͹ + ECX CH CX CL + ͹ + EBX BH BX BL + ͹ + EBP BP + ͹ + ESI SI + ͹ + EDI DI + ͹ + ESP SP + ͼ + + + 15 7 0 + ͻ + CS (CODE SEGMENT) + Ķ + SS (STACK SEGMENT) + SEGMENT Ķ + REGISTERS DS (DATA SEGMENT) + Ķ + ES (DATA SEGMENT) + Ķ + FS (DATA SEGMENT) + Ķ + GS (DATA SEGMENT) + ͼ + + + STATUS AND INSTRUCTION REGISTERS + + 31 23 15 7 0 + ͻ + EFLAGS + Ķ + EIP (INSTRUCTION POINTER) + ͼ + + +Figure 2-6. Use of Memory Segmentation + + ͻ ͻ + MODULE MODULE + A Ŀ  A + CODE DATA + ͼ ͻ ͼ + Ķ CS (CODE) + ͹ + ͻ Ķ SS (STACK) ͻ + ͹ DATA + STACK  DS (DATA)  STRUCTURE + ͹ 1 + ͼ ES (DATA) ͼ + ͹ + Ķ FS (DATA) + ͻ ͹ ͻ + DATA GS (DATA) Ŀ DATA + STRUCTURE  ͼ  STRUCTURE + 2 3 + ͼ ͼ + + +2.3.3 Stack Implementation + +Stack operations are facilitated by three registers: + + 1. The stack segment (SS) register. Stacks are implemented in memory. A + system may have a number of stacks that is limited only by the maximum + number of segments. A stack may be up to 4 gigabytes long, the maximum + length of a segment. One stack is directly addressable at a timethe + one located by SS. This is the current stack, often referred to simply + as "the" stack. SS is used automatically by the processor for all + stack operations. + + 2. The stack pointer (ESP) register. ESP points to the top of the + push-down stack (TOS). It is referenced implicitly by PUSH and POP + operations, subroutine calls and returns, and interrupt operations. + When an item is pushed onto the stack (see Figure 2-7), the processor + decrements ESP, then writes the item at the new TOS. When an item is + popped off the stack, the processor copies it from TOS, then + increments ESP. In other words, the stack grows down in memory toward + lesser addresses. + + 3. The stack-frame base pointer (EBP) register. The EBP is the best + choice of register for accessing data structures, variables and + dynamically allocated work space within the stack. EBP is often used + to access elements on the stack relative to a fixed point on the stack + rather than relative to the current TOS. It typically identifies the + base address of the current stack frame established for the current + procedure. When EBP is used as the base register in an offset + calculation, the offset is calculated automatically in the current + stack segment (i.e., the segment currently selected by SS). Because + SS does not have to be explicitly specified, instruction encoding in + such cases is more efficient. EBP can also be used to index into + segments addressable via other segment registers. + + +Figure 2-7. 80386 Stack + + 31 0 + ͻ BOTTOM OF STACK + (INITIAL ESP VALUE) + ͹ + + ͹  + POP + ͹ + + ͹ TOP OF ͻ + Ķ ESP + ͹ STACK ͼ + + + PUSH +  + + +2.3.4 Flags Register + +The flags register is a 32-bit register named EFLAGS. Figure 2-8 defines +the bits within this register. The flags control certain operations and +indicate the status of the 80386. + +The low-order 16 bits of EFLAGS is named FLAGS and can be treated as a +unit. This feature is useful when executing 8086 and 80286 code, because +this part of EFLAGS is identical to the FLAGS register of the 8086 and the +80286. + +The flags may be considered in three groups: the status flags, the control +flags, and the systems flags. Discussion of the systems flags is delayed +until Part II. + + +Figure 2-8. EFLAGS Register + + 16-BIT FLAGS REGISTER + A + Ŀ + 31 23 15 7 0 + ͻ + VR N IOODITSZ A P C + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 + MF T PLFFFFFF F F F + Ѽ + + VIRTUAL 8086 MODEX + RESUME FLAGX + NESTED TASK FLAGX + I/O PRIVILEGE LEVELX + OVERFLOWS + DIRECTION FLAGC + INTERRUPT ENABLEX + TRAP FLAGS + SIGN FLAGS + ZERO FLAGS + AUXILIARY CARRYS + PARITY FLAGS + CARRY FLAGS + + S = STATUS FLAG, C = CONTROL FLAG, X = SYSTEM FLAG + + NOTE: 0 OR 1 INDICATES INTEL RESERVED. DO NOT DEFINE + + +2.3.4.1 Status Flags + +The status flags of the EFLAGS register allow the results of one +instruction to influence later instructions. The arithmetic instructions use +OF, SF, ZF, AF, PF, and CF. The SCAS (Scan String), CMPS (Compare String), +and LOOP instructions use ZF to signal that their operations are complete. +There are instructions to set, clear, and complement CF before execution of +an arithmetic instruction. Refer to Appendix C for definition of each +status flag. + + +2.3.4.2 Control Flag + +The control flag DF of the EFLAGS register controls string instructions. + +DF (Direction Flag, bit 10) + + Setting DF causes string instructions to auto-decrement; that is, to + process strings from high addresses to low addresses. Clearing DF causes + string instructions to auto-increment, or to process strings from low + addresses to high addresses. + + +2.3.4.3 Instruction Pointer + +The instruction pointer register (EIP) contains the offset address, +relative to the start of the current code segment, of the next sequential +instruction to be executed. The instruction pointer is not directly visible +to the programmer; it is controlled implicitly by control-transfer +instructions, interrupts, and exceptions. + +As Figure 2-9 shows, the low-order 16 bits of EIP is named IP and can be +used by the processor as a unit. This feature is useful when executing +instructions designed for the 8086 and 80286 processors. + + +Figure 2-9. Instruction Pointer Register + + 16-BIT IP REGISTER + Ŀ + 31 23 15 7 0 + ͻ + EIP (INSTRUCTION POINTER) + ͼ + + +2.4 Instruction Format + +The information encoded in an 80386 instruction includes a specification of +the operation to be performed, the type of the operands to be manipulated, +and the location of these operands. If an operand is located in memory, the +instruction must also select, explicitly or implicitly, which of the +currently addressable segments contains the operand. + +80386 instructions are composed of various elements and have various +formats. The exact format of instructions is shown in Appendix B; the +elements of instructions are described below. Of these instruction elements, +only one, the opcode, is always present. The other elements may or may not +be present, depending on the particular operation involved and on the +location and type of the operands. The elements of an instruction, in order +of occurrence are as follows: + + Prefixes one or more bytes preceding an instruction that modify the + operation of the instruction. The following types of prefixes can be + used by applications programs: + + 1. Segment override explicitly specifies which segment register an + instruction should use, thereby overriding the default + segment-register selection used by the 80386 for that instruction. + + 2. Address size switches between 32-bit and 16-bit address + generation. + + 3. Operand size switches between 32-bit and 16-bit operands. + + 4. Repeat used with a string instruction to cause the instruction + to act on each element of the string. + + Opcode specifies the operation performed by the instruction. Some + operations have several different opcodes, each specifying a different + variant of the operation. + + Register specifier an instruction may specify one or two register + operands. Register specifiers may occur either in the same byte as the + opcode or in the same byte as the addressing-mode specifier. + + Addressing-mode specifier when present, specifies whether an operand + is a register or memory location; if in memory, specifies whether a + displacement, a base register, an index register, and scaling are to be + used. + + SIB (scale, index, base) byte when the addressing-mode specifier + indicates that an index register will be used to compute the address of + an operand, an SIB byte is included in the instruction to encode the + base register, the index register, and a scaling factor. + + Displacement when the addressing-mode specifier indicates that a + displacement will be used to compute the address of an operand, the + displacement is encoded in the instruction. A displacement is a signed + integer of 32, 16, or eight bits. The eight-bit form is used in the + common case when the displacement is sufficiently small. The processor + extends an eight-bit displacement to 16 or 32 bits, taking into + account the sign. + + Immediate operand when present, directly provides the value of an + operand of the instruction. Immediate operands may be 8, 16, or 32 bits + wide. In cases where an eight-bit immediate operand is combined in some + way with a 16- or 32-bit operand, the processor automatically extends + the size of the eight-bit operand, taking into account the sign. + + +2.5 Operand Selection + +An instruction can act on zero or more operands, which are the data +manipulated by the instruction. An example of a zero-operand instruction is +NOP (no operation). An operand can be in any of these locations: + + In the instruction itself (an immediate operand) + + In a register (EAX, EBX, ECX, EDX, ESI, EDI, ESP, or EBP in the case + of 32-bit operands; AX, BX, CX, DX, SI, DI, SP, or BP in the case of + 16-bit operands; AH, AL, BH, BL, CH, CL, DH, or DL in the case of 8-bit + operands; the segment registers; or the EFLAGS register for flag + operations) + + In memory + + At an I/O port + +Immediate operands and operands in registers can be accessed more rapidly +than operands in memory since memory operands must be fetched from memory. +Register operands are available in the CPU. Immediate operands are also +available in the CPU, because they are prefetched as part of the +instruction. + +Of the instructions that have operands, some specify operands implicitly; +others specify operands explicitly; still others use a combination of +implicit and explicit specification; for example: + +Implicit operand: AAM + + By definition, AAM (ASCII adjust for multiplication) operates on the + contents of the AX register. + +Explicit operand: XCHG EAX, EBX + + The operands to be exchanged are encoded in the instruction after the + opcode. + +Implicit and explicit operands: PUSH COUNTER + + The memory variable COUNTER (the explicit operand) is copied to the top of + the stack (the implicit operand). + +Note that most instructions have implicit operands. All arithmetic +instructions, for example, update the EFLAGS register. + +An 80386 instruction can explicitly reference one or two operands. +Two-operand instructions, such as MOV, ADD, XOR, etc., generally overwrite +one of the two participating operands with the result. A distinction can +thus be made between the source operand (the one unaffected by the +operation) and the destination operand (the one overwritten by the result). + +For most instructions, one of the two explicitly specified operandseither +the source or the destinationcan be either in a register or in memory. +The other operand must be in a register or be an immediate source operand. +Thus, the explicit two-operand instructions of the 80386 permit operations +of the following kinds: + + Register-to-register + Register-to-memory + Memory-to-register + Immediate-to-register + Immediate-to-memory + +Certain string instructions and stack manipulation instructions, however, +transfer data from memory to memory. Both operands of some string +instructions are in memory and are implicitly specified. Push and pop stack +operations allow transfer between memory operands and the memory-based +stack. + + +2.5.1 Immediate Operands + +Certain instructions use data from the instruction itself as one (and +sometimes two) of the operands. Such an operand is called an immediate +operand. The operand may be 32-, 16-, or 8-bits long. For example: + +SHR PATTERN, 2 + +One byte of the instruction holds the value 2, the number of bits by which +to shift the variable PATTERN. + +TEST PATTERN, 0FFFF00FFH + +A doubleword of the instruction holds the mask that is used to test the +variable PATTERN. + + +2.5.2 Register Operands + +Operands may be located in one of the 32-bit general registers (EAX, EBX, +ECX, EDX, ESI, EDI, ESP, or EBP), in one of the 16-bit general registers +(AX, BX, CX, DX, SI, DI, SP, or BP), or in one of the 8-bit general +registers (AH, BH, CH, DH, AL, BL, CL,or DL). + +The 80386 has instructions for referencing the segment registers (CS, DS, +ES, SS, FS, GS). These instructions are used by applications programs only +if systems designers have chosen a segmented memory model. + +The 80386 also has instructions for referring to the flag register. The +flags may be stored on the stack and restored from the stack. Certain +instructions change the commonly modified flags directly in the EFLAGS +register. Other flags that are seldom modified can be modified indirectly +via the flags image in the stack. + + +2.5.3 Memory Operands + +Data-manipulation instructions that address operands in memory must specify +(either directly or indirectly) the segment that contains the operand and +the offset of the operand within the segment. However, for speed and compact +instruction encoding, segment selectors are stored in the high speed segment +registers. Therefore, data-manipulation instructions need to specify only +the desired segment register and an offset in order to address a memory +operand. + +An 80386 data-manipulation instruction that accesses memory uses one of the +following methods for specifying the offset of a memory operand within its +segment: + + 1. Most data-manipulation instructions that access memory contain a byte + that explicitly specifies the addressing method for the operand. A + byte, known as the modR/M byte, follows the opcode and specifies + whether the operand is in a register or in memory. If the operand is + in memory, the address is computed from a segment register and any of + the following values: a base register, an index register, a scaling + factor, a displacement. When an index register is used, the modR/M + byte is also followed by another byte that identifies the index + register and scaling factor. This addressing method is the + mostflexible. + + 2. A few data-manipulation instructions implicitly use specialized + addressing methods: + + For a few short forms of MOV that implicitly use the EAX register, + the offset of the operand is coded as a doubleword in the + instruction. No base register, index register, or scaling factor + are used. + + String operations implicitly address memory via DS:ESI, (MOVS, + CMPS, OUTS, LODS, SCAS) or via ES:EDI (MOVS, CMPS, INS, STOS). + + Stack operations implicitly address operands via SS:ESP + registers; e.g., PUSH, POP, PUSHA, PUSHAD, POPA, POPAD, PUSHF, + PUSHFD, POPF, POPFD, CALL, RET, IRET, IRETD, exceptions, and + interrupts. + + +2.5.3.1 Segment Selection + +Data-manipulation instructions need not explicitly specify which segment +register is used. For all of these instructions, specification of a segment +register is optional. For all memory accesses, if a segment is not +explicitly specified by the instruction, the processor automatically chooses +a segment register according to the rules of Table 2-1. (If systems +designers have chosen a flat model of memory organization, the segment +registers and the rules that the processor uses in choosing them are not +apparent to applications programs.) + +There is a close connection between the kind of memory reference and the +segment in which that operand resides. As a rule, a memory reference implies +the current data segment (i.e., the implicit segment selector is in DS). +However, ESP and EBP are used to access items on the stack; therefore, when +the ESP or EBP register is used as a base register, the current stack +segment is implied (i.e., SS contains the selector). + +Special instruction prefix elements may be used to override the default +segment selection. Segment-override prefixes allow an explicit segment +selection. The 80386 has a segment-override prefix for each of the segment +registers. Only in the following special cases is there an implied segment +selection that a segment prefix cannot override: + + The use of ES for destination strings in string instructions. + The use of SS in stack instructions. + The use of CS for instruction fetches. + + +Table 2-1. Default Segment Register Selection Rules + +Memory Reference Needed Segment Implicit Segment Selection Rule + Register + Used + +Instructions Code (CS) Automatic with instruction prefetch +Stack Stack (SS) All stack pushes and pops. Any + memory reference that uses ESP or + EBP as a base register. +Local Data Data (DS) All data references except when + relative to stack or string + destination. +Destination Strings Extra (ES) Destination of string instructions. + + +2.5.3.2 Effective-Address Computation + +The modR/M byte provides the most flexible of the addressing methods, and +instructions that require a modR/M byte as the second byte of the +instruction are the most common in the 80386 instruction set. For memory +operands defined by modR/M, the offset within the desired segment is +calculated by taking the sum of up to three components: + + A displacement element in the instruction. + + A base register. + + An index register. The index register may be automatically multiplied + by a scaling factor of 2, 4, or 8. + +The offset that results from adding these components is called an effective +address. Each of these components of an effective address may have either a +positive or negative value. If the sum of all the components exceeds 2^(32), +the effective address is truncated to 32 bits.Figure 2-10 illustrates the +full set of possibilities for modR/M addressing. + +The displacement component, because it is encoded in the instruction, is +useful for fixed aspects of addressing; for example: + + Location of simple scalar operands. + Beginning of a statically allocated array. + Offset of an item within a record. + +The base and index components have similar functions. Both utilize the same +set of general registers. Both can be used for aspects of addressing that +are determined dynamically; for example: + + Location of procedure parameters and local variables in stack. + + The beginning of one record among several occurrences of the same + record type or in an array of records. + + The beginning of one dimension of multiple dimension array. + + The beginning of a dynamically allocated array. + +The uses of general registers as base or index components differ in the +following respects: + + ESP cannot be used as an index register. + + When ESP or EBP is used as the base register, the default segment is + the one selected by SS. In all other cases the default segment is DS. + +The scaling factor permits efficient indexing into an array in the common +cases when array elements are 2, 4, or 8 bytes wide. The shifting of the +index register is done by the processor at the time the address is evaluated +with no performance loss. This eliminates the need for a separate shift or +multiply instruction. + +The base, index, and displacement components may be used in any +combination; any of these components may be null. A scale factor can be used +only when an index is also used. Each possible combination is useful for +data structures commonly used by programmers in high-level languages and +assembly languages. Following are possible uses for some of the various +combinations of address components. + +DISPLACEMENT + + The displacement alone indicates the offset of the operand. This + combination is used to directly address a statically allocated scalar + operand. An 8-bit, 16-bit, or 32-bit displacement can be used. + +BASE + + The offset of the operand is specified indirectly in one of the general + registers, as for "based" variables. + +BASE + DISPLACEMENT + + A register and a displacement can be used together for two distinct + purposes: + + 1. Index into static array when element size is not 2, 4, or 8 bytes. + The displacement component encodes the offset of the beginning of + the array. The register holds the results of a calculation to + determine the offset of a specific element within the array. + + 2. Access item of a record. The displacement component locates an + item within record. The base register selects one of several + occurrences of record, thereby providing a compact encoding for + this common function. + + An important special case of this combination, is to access parameters + in the procedure activation record in the stack. In this case, EBP is + the best choice for the base register, because when EBP is used as a + base register, the processor automatically uses the stack segment + register (SS) to locate the operand, thereby providing a compact + encoding for this common function. + +(INDEX * SCALE) + DISPLACEMENT + + This combination provides efficient indexing into a static array when + the element size is 2, 4, or 8 bytes. The displacement addresses the + beginning of the array, the index register holds the subscript of the + desired array element, and the processor automatically converts the + subscript into an index by applying the scaling factor. + +BASE + INDEX + DISPLACEMENT + + Two registers used together support either a two-dimensional array (the + displacement determining the beginning of the array) or one of several + instances of an array of records (the displacement indicating an item + in the record). + +BASE + (INDEX * SCALE) + DISPLACEMENT + + This combination provides efficient indexing of a two-dimensional array + when the elements of the array are 2, 4, or 8 bytes wide. + + +Figure 2-10. Effective Address Computation + + SEGMENT + BASE + (INDEX * SCALE) + DISPLACEMENT + + + --- + EAX EAX 1 + CS ECX ECX + SS EDX EDX 2 NO DISPLACEMENT + Ĵ DS + Ĵ EBX + Ĵ EBX * Ĵ + Ĵ 8-BIT DISPLACEMENT + ES ESP --- 4 32-BIT DISPLACEMENT + FS EBP EBP + GS ESI ESI 6 + EDI EDI + + + +2.6 Interrupts and Exceptions + +The 80386 has two mechanisms for interrupting program execution: + + 1. Exceptions are synchronous events that are the responses of the CPU + to certain conditions detected during the execution of an instruction. + + 2. Interrupts are asynchronous events typically triggered by external + devices needing attention. + +Interrupts and exceptions are alike in that both cause the processor to +temporarily suspend its present program execution in order to execute a +program of higher priority. The major distinction between these two kinds of +interrupts is their origin. An exception is always reproducible by +re-executing with the program and data that caused the exception, whereas an +interrupt is generally independent of the currently executing program. + +Application programmers are not normally concerned with servicing +interrupts. More information on interrupts for systems programmers may be +found in Chapter 9. Certain exceptions, however, are of interest to +applications programmers, and many operating systems give applications +programs the opportunity to service these exceptions. However, the operating +system itself defines the interface between the applications programs and +the exception mechanism of the 80386. + +Table 2-2 highlights the exceptions that may be of interest to applications +programmers. + + A divide error exception results when the instruction DIV or IDIV is + executed with a zero denominator or when the quotient is too large for + the destination operand. (Refer to Chapter 3 for a discussion of DIV + and IDIV.) + + The debug exception may be reflected back to an applications program + if it results from the trap flag (TF). + + A breakpoint exception results when the instruction INT 3 is executed. + This instruction is used by some debuggers to stop program execution at + specific points. + + An overflow exception results when the INTO instruction is executed + and the OF (overflow) flag is set (after an arithmetic operation that + set the OF flag). (Refer to Chapter 3 for a discussion of INTO). + + A bounds check exception results when the BOUND instruction is + executed and the array index it checks falls outside the bounds of the + array. (Refer to Chapter 3 for a discussion of the BOUND instruction.) + + Invalid opcodes may be used by some applications to extend the + instruction set. In such a case, the invalid opcode exception presents + an opportunity to emulate the opcode. + + The "coprocessor not available" exception occurs if the program + contains instructions for a coprocessor, but no coprocessor is present + in the system. + + A coprocessor error is generated when a coprocessor detects an illegal + operation. + +The instruction INT generates an interrupt whenever it is executed; the +processor treats this interrupt as an exception. The effects of this +interrupt (and the effects of all other exceptions) are determined by +exception handler routines provided by the application program or as part of +the systems software (provided by systems programmers). The INT instruction +itself is discussed in Chapter 3. Refer to Chapter 9 for a more complete +description of exceptions. + + +Table 2-2. 80386 Reserved Exceptions and Interrupts + +Vector Number Description + +0 Divide Error +1 Debug Exceptions +2 NMI Interrupt +3 Breakpoint +4 INTO Detected Overflow +5 BOUND Range Exceeded +6 Invalid Opcode +7 Coprocessor Not Available +8 Double Exception +9 Coprocessor Segment Overrun +10 Invalid Task State Segment +11 Segment Not Present +12 Stack Fault +13 General Protection +14 Page Fault +15 (reserved) +16 Coprocessor Error +17-32 (reserved) + + +Chapter 3 Applications Instruction Set + + + +This chapter presents an overview of the instructions which programmers can +use to write application software for the 80386 executing in protected +virtual-address mode. The instructions are grouped by categories of related +functions. + +The instructions not discussed in this chapter are those that are normally +used only by operating-system programmers. Part II describes the operation +of these instructions. + +The descriptions in this chapter assume that the 80386 is operating in +protected mode with 32-bit addressing in effect; however, all instructions +discussed are also available when 16-bit addressing is in effect in +protected mode, real mode, or virtual 8086 mode. For any differences of +operation that exist in the various modes, refer to Chapter 13, +Chapter 14, or Chapter 15. + +The instruction dictionary in Chapter 17 contains more detailed +descriptions of all instructions, including encoding, operation, timing, +effect on flags, and exceptions. + + +3.1 Data Movement Instructions + +These instructions provide convenient methods for moving bytes, words, or +doublewords of data between memory and the registers of the base +architecture. They fall into the following classes: + + 1. General-purpose data movement instructions. + 2. Stack manipulation instructions. + 3. Type-conversion instructions. + + +3.1.1 General-Purpose Data Movement Instructions + +MOV (Move) transfers a byte, word, or doubleword from the source operand to +the destination operand. The MOV instruction is useful for transferring data +along any of these paths +There are also variants of MOV that operate on segment registers. These +are covered in a later section of this chapter.: + + To a register from memory + To memory from a register + Between general registers + Immediate data to a register + Immediate data to a memory + +The MOV instruction cannot move from memory to memory or from segment +register to segment register are not allowed. Memory-to-memory moves can be +performed, however, by the string move instruction MOVS. + +XCHG (Exchange) swaps the contents of two operands. This instruction takes +the place of three MOV instructions. It does not require a temporary +location to save the contents of one operand while load the other is being +loaded. XCHG is especially useful for implementing semaphores or similar +data structures for process synchronization. + +The XCHG instruction can swap two byte operands, two word operands, or two +doubleword operands. The operands for the XCHG instruction may be two +register operands, or a register operand with a memory operand. When used +with a memory operand, XCHG automatically activates the LOCK signal. (Refer +to Chapter 11 for more information on the bus lock.) + + +3.1.2 Stack Manipulation Instructions + +PUSH (Push) decrements the stack pointer (ESP), then transfers the source +operand to the top of stack indicated by ESP (see Figure 3-1). PUSH is +often used to place parameters on the stack before calling a procedure; it +is also the basic means of storing temporary variables on the stack. The +PUSH instruction operates on memory operands, immediate operands, and +register operands (including segment registers). + +PUSHA (Push All Registers) saves the contents of the eight general +registers on the stack (see Figure 3-2). This instruction simplifies +procedure calls by reducing the number of instructions required to retain +the contents of the general registers for use in a procedure. The processor +pushes the general registers on the stack in the following order: EAX, ECX, +EDX, EBX, the initial value of ESP before EAX was pushed, EBP, ESI, and +EDI. PUSHA is complemented by the POPA instruction. + +POP (Pop) transfers the word or doubleword at the current top of stack +(indicated by ESP) to the destination operand, and then increments ESP to +point to the new top of stack. See Figure 3-3. POP moves information from +the stack to a general register, or to memory +There are also a variant of POP that operates on segment registers. This +is covered in a later section of this chapter.. + +POPA (Pop All Registers) restores the registers saved on the stack by +PUSHA, except that it ignores the saved value of ESP. See Figure 3-4. + + +Figure 3-1. PUSH + + D O BEFORE PUSH AFTER PUSH + I F  31 0   31 0  + R + E E ͹ ͹ + C X + T P ͹ ͹ + I A + O N ͹ESP ͹ + N S OPERAND + I ͹ ͹ESP + O + N ͹ ͹ + +  ͹ ͹ + +     + + +Figure 3-2. PUSHA + + BEFORE PUSHA AFTER PUSHA +  31 0   31 0  + D O + I F ͹ ͹ + R + E E ͹ ͹ + C X + T P ͹ESP ͹ + I A EAX + O N ͹ ͹ + N S ECX + I ͹ ͹ + O EDX + N ͹ ͹ + EBX +  ͹ ͹ + OLD ESP + ͹ ͹ + EBP + ͹ ͹ + ESI + ͹ ͹ + EDI + ͹ ͹ESP + + ͹ ͹ + +     + + +3.1.3 Type Conversion Instructions + +The type conversion instructions convert bytes into words, words into +doublewords, and doublewords into 64-bit items (quad-words). These +instructions are especially useful for converting signed integers, because +they automatically fill the extra bits of the larger item with the value of +the sign bit of the smaller item. This kind of conversion, illustrated by +Figure 3-5, is called sign extension. + +There are two classes of type conversion instructions: + + 1. The forms CWD, CDQ, CBW, and CWDE which operate only on data in the + EAX register. + + 2. The forms MOVSX and MOVZX, which permit one operand to be in any + general register while permitting the other operand to be in memory or + in a register. + +CWD (Convert Word to Doubleword) and CDQ (Convert Doubleword to Quad-Word) +double the size of the source operand. CWD extends the sign of the +word in register AX throughout register DX. CDQ extends the sign of the +doubleword in EAX throughout EDX. CWD can be used to produce a doubleword +dividend from a word before a word division, and CDQ can be used to produce +a quad-word dividend from a doubleword before doubleword division. + +CBW (Convert Byte to Word) extends the sign of the byte in register AL +throughout AX. + +CWDE (Convert Word to Doubleword Extended) extends the sign of the word in +register AX throughout EAX. + +MOVSX (Move with Sign Extension) sign-extends an 8-bit value to a 16-bit +value and a 8- or 16-bit value to 32-bit value. + +MOVZX (Move with Zero Extension) extends an 8-bit value to a 16-bit value +and an 8- or 16-bit value to 32-bit value by inserting high-order zeros. + + +Figure 3-3. POP + + D O BEFORE POP AFTER POP + I F  31 0   31 0  + R + E E ͹ ͹ + C X + T P ͹ ͹ + I A + O N ͹ ͹ESP + N S OPERAND + I ͹ESP ͹ + O + N ͹ ͹ + +  ͹ ͹ + +     + + +Figure 3-4. POPA + + BEFORE POPA AFTER POPA +  31 0   31 0  + D O + I F ͹ ͹ + R + E E ͹ ͹ + C X + T P ͹ ͹ESP + I A EAX + O N ͹ ͹ + N S ECX + I ͹ ͹ + O EDX + N ͹ ͹ + EBX +  ͹ ͹ + ESP + ͹ ͹ + EPB + ͹ ͹ + ESI + ͹ ͹ + EDI + ͹ESP ͹ + + ͹ ͹ + +     + + +Figure 3-5. Sign Extension + + 15 7 0 + ͻ + BEFORE SIGN EXTENSIONS N N N N N N N N N N N N N N N + ͼ + AFTER SIGN EXTENSIONĿ + + 31 23  15 7 0 + ͻ + SS S S S S S S S S S S S S S S S N N N N N N N N N N N N N N N + ͼ + + +3.2 Binary Arithmetic Instructions + +The arithmetic instructions of the 80386 processor simplify the +manipulation of numeric data that is encoded in binary. Operations include +the standard add, subtract, multiply, and divide as well as increment, +decrement, compare, and change sign. Both signed and unsigned binary +integers are supported. The binary arithmetic instructions may also be used +as one step in the process of performing arithmetic on decimal integers. + +Many of the arithmetic instructions operate on both signed and unsigned +integers. These instructions update the flags ZF, CF, SF, and OF in such a +manner that subsequent instructions can interpret the results of the +arithmetic as either signed or unsigned. CF contains information relevant to +unsigned integers; SF and OF contain information relevant to signed +integers. ZF is relevant to both signed and unsigned integers; ZF is set +when all bits of the result are zero. + +If the integer is unsigned, CF may be tested after one of these arithmetic +operations to determine whether the operation required a carry or borrow of +a one-bit in the high-order position of the destination operand. CF is set +if a one-bit was carried out of the high-order position (addition +instructions ADD, ADC, AAA, and DAA) or if a one-bit was carried (i.e. +borrowed) into the high-order bit (subtraction instructions SUB, SBB, AAS, +DAS, CMP, and NEG). + +If the integer is signed, both SF and OF should be tested. SF always has +the same value as the sign bit of the result. The most significant bit (MSB) +of a signed integer is the bit next to the signbit 6 of a byte, bit 14 of +a word, or bit 30 of a doubleword. OF is set in either of these cases: + + A one-bit was carried out of the MSB into the sign bit but no one bit + was carried out of the sign bit (addition instructions ADD, ADC, INC, + AAA, and DAA). In other words, the result was greater than the greatest + positive number that could be contained in the destination operand. + + A one-bit was carried from the sign bit into the MSB but no one bit + was carried into the sign bit (subtraction instructions SUB, SBB, DEC, + AAS, DAS, CMP, and NEG). In other words, the result was smaller that + the smallest negative number that could be contained in the destination + operand. + +These status flags are tested by executing one of the two families of +conditional instructions: Jcc (jump on condition cc) or SETcc (byte set on +condition). + + +3.2.1 Addition and Subtraction Instructions + +ADD (Add Integers) replaces the destination operand with the sum of the +source and destination operands. Sets CF if overflow. + +ADC (Add Integers with Carry) sums the operands, adds one if CF is set, and +replaces the destination operand with the result. If CF is cleared, ADC +performs the same operation as the ADD instruction. An ADD followed by +multiple ADC instructions can be used to add numbers longer than 32 bits. + +INC (Increment) adds one to the destination operand. INC does not affect +CF. Use ADD with an immediate value of 1 if an increment that updates carry +(CF) is needed. + +SUB (Subtract Integers) subtracts the source operand from the destination +operand and replaces the destination operand with the result. If a borrow is +required, the CF is set. The operands may be signed or unsigned bytes, +words, or doublewords. + +SBB (Subtract Integers with Borrow) subtracts the source operand from the +destination operand, subtracts 1 if CF is set, and returns the result to the +destination operand. If CF is cleared, SBB performs the same operation as +SUB. SUB followed by multiple SBB instructions may be used to subtract +numbers longer than 32 bits. If CF is cleared, SBB performs the same +operation as SUB. + +DEC (Decrement) subtracts 1 from the destination operand. DEC does not +update CF. Use SUB with an immediate value of 1 to perform a decrement that +affects carry. + + +3.2.2 Comparison and Sign Change Instruction + +CMP (Compare) subtracts the source operand from the destination operand. It +updates OF, SF, ZF, AF, PF, and CF but does not alter the source and +destination operands. A subsequent Jcc or SETcc instruction can test the +appropriate flags. + +NEG (Negate) subtracts a signed integer operand from zero. The effect of +NEG is to reverse the sign of the operand from positive to negative or from +negative to positive. + + +3.2.3 Multiplication Instructions + +The 80386 has separate multiply instructions for unsigned and signed +operands. MUL operates on unsigned numbers, while IMUL operates on signed +integers as well as unsigned. + +MUL (Unsigned Integer Multiply) performs an unsigned multiplication of the +source operand and the accumulator. If the source is a byte, the processor +multiplies it by the contents of AL and returns the double-length result to +AH and AL. If the source operand is a word, the processor multiplies it by +the contents of AX and returns the double-length result to DX and AX. If the +source operand is a doubleword, the processor multiplies it by the contents +of EAX and returns the 64-bit result in EDX and EAX. MUL sets CF and OF +when the upper half of the result is nonzero; otherwise, they are cleared. + +IMUL (Signed Integer Multiply) performs a signed multiplication operation. +IMUL has three variations: + + 1. A one-operand form. The operand may be a byte, word, or doubleword + located in memory or in a general register. This instruction uses EAX + and EDX as implicit operands in the same way as the MUL instruction. + + 2. A two-operand form. One of the source operands may be in any general + register while the other may be either in memory or in a general + register. The product replaces the general-register operand. + + 3. A three-operand form; two are source and one is the destination + operand. One of the source operands is an immediate value stored in + the instruction; the second may be in memory or in any general + register. The product may be stored in any general register. The + immediate operand is treated as signed. If the immediate operand is a + byte, the processor automatically sign-extends it to the size of the + second operand before performing the multiplication. + +The three forms are similar in most respects: + + The length of the product is calculated to twice the length of the + operands. + + The CF and OF flags are set when significant bits are carried into the + high-order half of the result. CF and OF are cleared when the + high-order half of the result is the sign-extension of the low-order + half. + +However, forms 2 and 3 differ in that the product is truncated to the +length of the operands before it is stored in the destination register. +Because of this truncation, OF should be tested to ensure that no +significant bits are lost. (For ways to test OF, refer to the INTO and PUSHF +instructions.) + +Forms 2 and 3 of IMUL may also be used with unsigned operands because, +whether the operands are signed or unsigned, the low-order half of the +product is the same. + + +3.2.4 Division Instructions + +The 80386 has separate division instructions for unsigned and signed +operands. DIV operates on unsigned numbers, while IDIV operates on signed +integers as well as unsigned. In either case, an exception (interrupt zero) +occurs if the divisor is zero or if the quotient is too large for AL, AX, or +EAX. + +DIV (Unsigned Integer Divide) performs an unsigned division of the +accumulator by the source operand. The dividend (the accumulator) is twice +the size of the divisor (the source operand); the quotient and remainder +have the same size as the divisor, as the following table shows. + +Size of Source Operand + (divisor) Dividend Quotient Remainder + +Byte AX AL AH +Word DX:AX AX DX +Doubleword EDX:EAX EAX EDX + +Non-integral quotients are truncated to integers toward 0. The remainder is +always less than the divisor. For unsigned byte division, the largest +quotient is 255. For unsigned word division, the largest quotient is 65,535. +For unsigned doubleword division the largest quotient is 2^(32) -1. + +IDIV (Signed Integer Divide) performs a signed division of the accumulator +by the source operand. IDIV uses the same registers as the DIV instruction. + +For signed byte division, the maximum positive quotient is +127, and the +minimum negative quotient is -128. For signed word division, the maximum +positive quotient is +32,767, and the minimum negative quotient is -32,768. +For signed doubleword division the maximum positive quotient is 2^(31) -1, +the minimum negative quotient is -2^(31). Non-integral results are truncated +towards 0. The remainder always has the same sign as the dividend and is +less than the divisor in magnitude. + + +3.3 Decimal Arithmetic Instructions + +Decimal arithmetic is performed by combining the binary arithmetic +instructions (already discussed in the prior section) with the decimal +arithmetic instructions. The decimal arithmetic instructions are used in one +of the following ways: + + To adjust the results of a previous binary arithmetic operation to + produce a valid packed or unpacked decimal result. + + To adjust the inputs to a subsequent binary arithmetic operation so + that the operation will produce a valid packed or unpacked decimal + result. + +These instructions operate only on the AL or AH registers. Most utilize the +AF flag. + + +3.3.1 Packed BCD Adjustment Instructions + +DAA (Decimal Adjust after Addition) adjusts the result of adding two valid +packed decimal operands in AL. DAA must always follow the addition of two +pairs of packed decimal numbers (one digit in each half-byte) to obtain a +pair of valid packed decimal digits as results. The carry flag is set if +carry was needed. + +DAS (Decimal Adjust after Subtraction) adjusts the result of subtracting +two valid packed decimal operands in AL. DAS must always follow the +subtraction of one pair of packed decimal numbers (one digit in each half- +byte) from another to obtain a pair of valid packed decimal digits as +results. The carry flag is set if a borrow was needed. + + +3.3.2 Unpacked BCD Adjustment Instructions + +AAA (ASCII Adjust after Addition) changes the contents of register AL to a +valid unpacked decimal number, and zeros the top 4 bits. AAA must always +follow the addition of two unpacked decimal operands in AL. The carry flag +is set and AH is incremented if a carry is necessary. + +AAS (ASCII Adjust after Subtraction) changes the contents of register AL to +a valid unpacked decimal number, and zeros the top 4 bits. AAS must always +follow the subtraction of one unpacked decimal operand from another in AL. +The carry flag is set and AH decremented if a borrow is necessary. + +AAM (ASCII Adjust after Multiplication) corrects the result of a +multiplication of two valid unpacked decimal numbers. AAM must always follow +the multiplication of two decimal numbers to produce a valid decimal result. +The high order digit is left in AH, the low order digit in AL. + +AAD (ASCII Adjust before Division) modifies the numerator in AH and AL to +prepare for the division of two valid unpacked decimal operands so that the +quotient produced by the division will be a valid unpacked decimal number. +AH should contain the high-order digit and AL the low-order digit. This +instruction adjusts the value and places the result in AL. AH will contain +zero. + + +3.4 Logical Instructions + +The group of logical instructions includes: + + The Boolean operation instructions + Bit test and modify instructions + Bit scan instructions + Rotate and shift instructions + Byte set on condition + + +3.4.1 Boolean Operation Instructions + +The logical operations are AND, OR, XOR, and NOT. + +NOT (Not) inverts the bits in the specified operand to form a one's +complement of the operand. The NOT instruction is a unary operation that +uses a single operand in a register or memory. NOT has no effect on the +flags. + +The AND, OR, and XOR instructions perform the standard logical operations +"and", "(inclusive) or", and "exclusive or". These instructions can use the +following combinations of operands: + + Two register operands + + A general register operand with a memory operand + + An immediate operand with either a general register operand or a + memory operand. + +AND, OR, and XOR clear OF and CF, leave AF undefined, and update SF, ZF, +and PF. + + +3.4.2 Bit Test and Modify Instructions + +This group of instructions operates on a single bit which can be in memory +or in a general register. The location of the bit is specified as an offset +from the low-order end of the operand. The value of the offset either may be +given by an immediate byte in the instruction or may be contained in a +general register. + +These instructions first assign the value of the selected bit to CF, the +carry flag. Then a new value is assigned to the selected bit, as determined +by the operation. OF, SF, ZF, AF, PF are left in an undefined state. Table +3-1 defines these instructions. + + +Table 3-1. Bit Test and Modify Instructions + +Instruction Effect on CF Effect on + Selected Bit + +Bit (Bit Test) CF  BIT (none) +BTS (Bit Test and Set) CF  BIT BIT  1 +BTR (Bit Test and Reset) CF  BIT BIT  0 +BTC (Bit Test and Complement) CF  BIT BIT  NOT(BIT) + + +3.4.3 Bit Scan Instructions + +These instructions scan a word or doubleword for a one-bit and store the +index of the first set bit into a register. The bit string being scanned +may be either in a register or in memory. The ZF flag is set if the entire +word is zero (no set bits are found); ZF is cleared if a one-bit is found. +If no set bit is found, the value of the destination register is undefined. + +BSF (Bit Scan Forward) scans from low-order to high-order (starting from +bit index zero). + +BSR (Bit Scan Reverse) scans from high-order to low-order (starting from +bit index 15 of a word or index 31 of a doubleword). + + +3.4.4 Shift and Rotate Instructions + +The shift and rotate instructions reposition the bits within the specified +operand. + +These instructions fall into the following classes: + + Shift instructions + Double shift instructions + Rotate instructions + + +3.4.4.1 Shift Instructions + +The bits in bytes, words, and doublewords may be shifted arithmetically or +logically. Depending on the value of a specified count, bits can be shifted +up to 31 places. + +A shift instruction can specify the count in one of three ways. One form of +shift instruction implicitly specifies the count as a single shift. The +second form specifies the count as an immediate value. The third form +specifies the count as the value contained in CL. This last form allows the +shift count to be a variable that the program supplies during execution. +Only the low order 5 bits of CL are used. + +CF always contains the value of the last bit shifted out of the destination +operand. In a single-bit shift, OF is set if the value of the high-order +(sign) bit was changed by the operation. Otherwise, OF is cleared. Following +a multibit shift, however, the content of OF is always undefined. + +The shift instructions provide a convenient way to accomplish division or +multiplication by binary power. Note however that division of signed numbers +by shifting right is not the same kind of division performed by the IDIV +instruction. + +SAL (Shift Arithmetic Left) shifts the destination byte, word, or +doubleword operand left by one or by the number of bits specified in the +count operand (an immediate value or the value contained in CL). The +processor shifts zeros in from the right (low-order) side of the operand as +bits exit from the left (high-order) side. See Figure 3-6. + +SHL (Shift Logical Left) is a synonym for SAL (refer to SAL). + +SHR (Shift Logical Right) shifts the destination byte, word, or doubleword +operand right by one or by the number of bits specified in the count operand +(an immediate value or the value contained in CL). The processor shifts +zeros in from the left side of the operand as bits exit from the right side. +See Figure 3-7. + +SAR (Shift Arithmetic Right) shifts the destination byte, word, or +doubleword operand to the right by one or by the number of bits specified in +the count operand (an immediate value or the value contained in CL). The +processor preserves the sign of the operand by shifting in zeros on the left +(high-order) side if the value is positive or by shifting by ones if the +value is negative. See Figure 3-8. + +Even though this instruction can be used to divide integers by a power of +two, the type of division is not the same as that produced by the IDIV +instruction. The quotient of IDIV is rounded toward zero, whereas the +"quotient" of SAR is rounded toward negative infinity. This difference is +apparent only for negative numbers. For example, when IDIV is used to divide +-9 by 4, the result is -2 with a remainder of -1. If SAR is used to shift +-9 right by two bits, the result is -3. The "remainder" of this kind of +division is +3; however, the SAR instruction stores only the high-order bit +of the remainder (in CF). + +The code sequence in Figure 3-9 produces the same result as IDIV for any M += 2^(N), where 0 < N < 32. This sequence takes about 12 to 18 clocks, +depending on whether the jump is taken; if ECX contains M, the corresponding +IDIV ECX instruction will take about 43 clocks. + + +Figure 3-6. SAL and SHL + + OF CF OPERAND + + BEFORE SHL X X 10001000100010001000100010001111 + OR SAL + + AFTER SHL 1 1  00010001000100010001000100011110  0 + OR SAL BY 1 + + AFTER SHL X 0  00100010001000100011110000000000  0 + OR SAL BY 10 + +SHL (WHICH HAS THE SYNONYM SAL) SHIFTS THE BITS IN THE REGISTER OR MEMORY +OPERAND TO THE LEFT BY THE SPECIFIED NUMBER OF BIT POSITIONS. CF RECEIVES +THE LAST BIT SHIFTED OUT OF THE LEFT OF THE OPERAND. SHL SHIFTS IN ZEROS +TO FILL THE VACATED BIT LOCATIONS. THESE INSTRUCTIONS OPERATE ON BYTE, +WORD, AND DOUBLEWORD OPERANDS. + + +Figure 3-7. SHR + + OPERAND CF + + BEFORE SHR 10001000100010001000100010001111 X + + AFTER SHR 0010001000100010001000100010001111 + BY 1 + + AFTER SHR 000000000001000100010001000100010O + BY 10 + +SHR SHIFTS THE BITS OF THE REGISTER OR MEMORY OPERAND TO THE RIGHT BY THE +SPECIFIED NUMBER OF BIT POSITIONS. CF RECEIVES THE LAST BIT SHIFTED OUT OF +THE RIGHT OF THE OPERAND. SHR SHIFTS IN ZEROS TO FILL THE VACATED BIT +LOCATIONS. + + +Figure 3-8. SAR + + POSITIVE OPERAND CF + + BEFORE SAR 01000100010001000100010001000111 X + + AFTER SAR 0001000100010001000100010001000111 + BY 1 + + NEGATIVE OPERAND CF + + BEFORE SAR 11000100010001000100010001000111 X + + AFTER SAR 0111000100010001000100010001000111 + BY 1 + +SAR PRESERVES THE SIGN OF THE REGISTER OR MEMORY OPERAND AS IT SHIFTS THE +OPERAND TO THE RIGHT BY THE SPECIFIED NUMBER OF BIT POSITIONS. CF RECIEVES +THE LAST BIT SHIFTED OUT OF THE RIGHT OF THE OPERAND. + + +Figure 3-9. Using SAR to Simulate IDIV + + ; assuming N is in ECX, and the dividend is in EAX + ; CLOCKS + CMP EAX, 0 ; to set sign flag 2 + JGE NoAdjust ; jump if sign is zero 3 or 9 + ADD EAX, ECX ; 2 + DEC EAX ; EAX := EAX + (N-1) 2 +NoAdjust: + SAR EAX, CL ; 3 + ; TOTAL CLOCKS 12 or 18] + + +3.4.4.2 Double-Shift Instructions + +These instructions provide the basic operations needed to implement +operations on long unaligned bit strings. The double shifts operate either +on word or doubleword operands, as follows: + + 1. Taking two word operands as input and producing a one-word output. + + 2. Taking two doubleword operands as input and producing a doubleword + output. + +Of the two input operands, one may either be in a general register or in +memory, while the other may only be in a general register. The results +replace the memory or register operand. The number of bits to be shifted is +specified either in the CL register or in an immediate byte of the +instruction. + +Bits are shifted from the register operand into the memory or register +operand. CF is set to the value of the last bit shifted out of the +destination operand. SF, ZF, and PF are set according to the value of the +result. OF and AF are left undefined. + +SHLD (Shift Left Double) shifts bits of the R/M field to the left, while +shifting high-order bits from the Reg field into the R/M field on the right +(see Figure 3-10). The result is stored back into the R/M operand. The Reg +field is not modified. + +SHRD (Shift Right Double) shifts bits of the R/M field to the right, while +shifting low-order bits from the Reg field into the R/M field on the left +(see Figure 3-11). The result is stored back into the R/M operand. The Reg +field is not modified. + + +3.4.4.3 Rotate Instructions + +Rotate instructions allow bits in bytes, words, and doublewords to be +rotated. Bits rotated out of an operand are not lost as in a shift, but are +"circled" back into the other "end" of the operand. + +Rotates affect only the carry and overflow flags. CF may act as an +extension of the operand in two of the rotate instructions, allowing a bit +to be isolated and then tested by a conditional jump instruction (JC or +JNC). CF always contains the value of the last bit rotated out, even if the +instruction does not use this bit as an extension of the rotated operand. + +In single-bit rotates, OF is set if the operation changes the high-order +(sign) bit of the destination operand. If the sign bit retains its original +value, OF is cleared. On multibit rotates, the value of OF is always +undefined. + +ROL (Rotate Left) rotates the byte, word, or doubleword destination operand +left by one or by the number of bits specified in the count operand (an +immediate value or the value contained in CL). For each rotation specified, +the high-order bit that exits from the left of the operand returns at the +right to become the new low-order bit of the operand. See Figure 3-12. + +ROR (Rotate Right) rotates the byte, word, or doubleword destination +operand right by one or by the number of bits specified in the count operand +(an immediate value or the value contained in CL). For each rotation +specified, the low-order bit that exits from the right of the operand +returns at the left to become the new high-order bit of the operand. +See Figure 3-13. + +RCL (Rotate Through Carry Left) rotates bits in the byte, word, or +doubleword destination operand left by one or by the number of bits +specified in the count operand (an immediate value or the value contained in +CL). + +This instruction differs from ROL in that it treats CF as a high-order +one-bit extension of the destination operand. Each high-order bit that exits +from the left side of the operand moves to CF before it returns to the +operand as the low-order bit on the next rotation cycle. See Figure 3-14. + +RCR (Rotate Through Carry Right) rotates bits in the byte, word, or +doubleword destination operand right by one or by the number of bits +specified in the count operand (an immediate value or the value contained in +CL). + +This instruction differs from ROR in that it treats CF as a low-order +one-bit extension of the destination operand. Each low-order bit that exits +from the right side of the operand moves to CF before it returns to the +operand as the high-order bit on the next rotation cycle. See Figure 3-15. + + +Figure 3-10. Shift Left Double + + 31 DESTINATION 0 + ͻ ͻ + CF Ķ MEMORY OF REGISTER Ŀ + ͼ ͼ + + 31 SOURCE 0 + ͻ + Ķ REGISTER + ͼ + + +Figure 3-11. Shift Right Double + + 31 SOURCE 0 + ͻ + REGISTER Ŀ + ͼ + + 31 DESTINATION 0 + ͻ ͻ +  MEMORY OF REGISTER  CF + ͼ ͼ + + +Figure 3-12. ROL + + 31 DESTINATION 0 + ͻ ͻ + CF Ķ MEMORY OF REGISTER Ŀ + ͼ ͼ + + + +Figure 3-13. ROR + + Ŀ + 31 DESTINATION 0 + ͻ ͻ +  MEMORY OF REGISTER  CF + ͼ ͼ + + +Figure 3-14. RCL + + 31 DESTINATION 0 + ͻ ͻ + Ķ CF Ķ MEMORY OF REGISTER Ŀ + ͼ ͼ + + + +Figure 3-15. RCR + + Ŀ + 31 DESTINATION 0 + ͻ ͻ +  MEMORY OF REGISTER  CF + ͼ ͼ + + +3.4.4.4 Fast "BIT BLT" Using Double Shift Instructions + +One purpose of the double shifts is to implement a bit string move, with +arbitrary misalignment of the bit strings. This is called a "bit blt" (BIT +BLock Transfer.) A simple example is to move a bit string from an arbitrary +offset into a doubleword-aligned byte string. A left-to-right string is +moved 32 bits at a time if a double shift is used inside the move loop. + + MOV ESI,ScrAddr + MOV EDI,DestAddr + MOV EBX,WordCnt + MOV CL,RelOffset ; relative offset Dest-Src + MOV EDX,[ESI] ; load first word of source + ADD ESI,4 ; bump source address +BltLoop: + LODS ; new low order part + SHLD EDX,EAX,CL ; EDX overwritten with aligned stuff + XCHG EDX,EAS ; Swap high/low order parts + STOS ; Write out next aligned chunk + DEC EBX + JA BltLoop + +This loop is simple yet allows the data to be moved in 32-bit pieces for +the highest possible performance. Without a double shift, the best that can +be achieved is 16 bits per loop iteration by using a 32-bit shift and +replacing the XCHG with a ROR by 16 to swap high and low order parts of +registers. A more general loop than shown above would require some extra +masking on the first doubleword moved (before the main loop), and on the +last doubleword moved (after the main loop), but would have the same basic +32-bits per loop iteration as the code above. + + +3.4.4.5 Fast Bit-String Insert and Extract + +The double shift instructions also enable: + + Fast insertion of a bit string from a register into an arbitrary bit + location in a larger bit string in memory without disturbing the bits + on either side of the inserted bits. + + Fast extraction of a bits string into a register from an arbitrary bit + location in a larger bit string in memory without disturbing the bits + on either side of the extracted bits. + +The following coded examples illustrate bit insertion and extraction under +variousconditions: + + 1. Bit String Insert into Memory (when bit string is 1-25 bits long, + i.e., spans four bytes or less): + + ; Insert a right-justified bit string from register into + ; memory bit string. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate value + ; but the bit offset is held in a register. + ; + ; Register ESI holds the right-justified bit string + ; to be inserted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX and ECX are also used by this + ; "insert" operation. + ; + MOV ECX,EDI ; preserve original offset for later use + SHR EDI,3 ; signed divide offset by 8 (byte address) + AND CL,7H ; isolate low three bits of offset in CL + MOV EAX,[EDI]strg_base ; move string dword into EAX + ROR EAX,CL ; right justify old bit field + SHRD EAX,ESI,length ; bring in new bits + ROL EAX,length ; right justify new bit field + ROL EAX,CL ; bring to final position + MOV [EDI]strg_base,EAX ; replace dword in memory + + 2. Bit String Insert into Memory (when bit string is 1-31 bits long, i.e. + spans five bytes or less): + + ; Insert a right-justified bit string from register into + ; memory bit string. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate value + ; but the bit offset is held in a register. + ; + ; Register ESI holds the right-justified bit string + ; to be inserted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX, EBX, ECX, and EDI are also used by + ; this "insert" operation. + ; + MOV ECX,EDI ; temp storage for offset + SHR EDI,5 ; signed divide offset by 32 (dword address) + SHL EDI,2 ; multiply by 4 (in byte address format) + AND CL,1FH ; isolate low five bits of offset in CL + MOV EAX,[EDI]strg_base ; move low string dword into EAX + MOV EDX,[EDI]strg_base+4 ; other string dword into EDX + MOV EBX,EAX ; temp storage for part of string rotate + SHRD EAX,EDX,CL ; double shift by offset within dword EDX:EAX + SHRD EAX,EBX,CL ; double shift by offset within dword right + SHRD EAX,ESI,length ; bring in new bits + ROL EAX,length ; right justify new bit field + MOV EBX,EAX ; temp storage for part of string rotate + SHLD EAX,EDX,CL ; double shift back by offset within word EDX:EAX + SHLD EDX,EBX,CL ; double shift back by offset within word left + MOV [EDI]strg_base,EAX ; replace dword in memory + MOV [EDI]strg_base+4,EDX ; replace dword in memory + + 3. Bit String Insert into Memory (when bit string is exactly 32 bits + long, i.e., spans five or four types of memory): + + ; Insert right-justified bit string from register into + ; memory bit string. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is 32 + ; but the bit offset is held in a register. + ; + ; Register ESI holds the 32-bit string to be inserted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX, EBX, ECX, and EDI are also used by + ; this "insert" operation. + ; + MOV EDX,EDI ; preserve original offset for later use + SHR EDI,5 ; signed divide offset by 32 (dword address) + SHL EDI,2 ; multiply by 4 (in byte address format) + AND CL,1FH ; isolate low five bits of offset in CL + MOV EAX,[EDI]strg_base ; move low string dword into EAX + MOV EDX,[EDI]strg_base+4 ; other string dword into EDX + MOV EBX,EAX ; temp storage for part of string rotate + SHRD EAX,EDX ; double shift by offset within dword EDX:EAX + SHRD EDX,EBX ; double shift by offset within dword right + MOV EAX,ESI ; move 32-bit bit field into position + MOV EBX,EAX ; temp storage for part of string rotate + SHLD EAX,EDX ; double shift back by offset within word EDX:EAX + SHLD EDX,EBX ; double shift back by offset within word left + MOV [EDI]strg_base,EAX ; replace dword in memory + MOV [EDI]strg_base,+4,EDX ; replace dword in memory + + 4. Bit String Extract from Memory (when bit string is 1-25 bits long, + i.e., spans four bytes or less): + + ; Extract a right-justified bit string from memory bit + ; string into register + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate value + ; but the bit offset is held in a register. + ; + ; Register EAX holds the right-justified, zero-padded + ; bit string that was extracted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EDI, and ECX are also used by this "extract." + ; + MOV ECX,EDI ; temp storage for offset + SHR EDI,3 ; signed divide offset by 8 (byte address) + AND CL,7H ; isolate low three bits of offset + MOV EAX,[EDI]strg_base ; move string dword into EAX + SHR EAX,CL ; shift by offset within dword + AND EAX,mask ; extracted bit field in EAX + + 5. Bit String Extract from Memory (when bit string is 1-32 bits long, + i.e., spans five bytes or less): + + ; Extract a right-justified bit string from memory bit + ; string into register. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate + ; value but the bit offset is held in a register. + ; + ; Register EAX holds the right-justified, zero-padded + ; bit string that was extracted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX, EBX, and ECX are also used by this "extract." + MOV ECX,EDI ; temp storage for offset + SHR EDI,5 ; signed divide offset by 32 (dword address) + SHL EDI,2 ; multiply by 4 (in byte address format) + AND CL,1FH ; isolate low five bits of offset in CL + MOV EAX,[EDI]strg_base ; move low string dword into EAX + MOV EDX,[EDI]strg_base+4 ; other string dword into EDX + SHRD EAX,EDX,CL ; double shift right by offset within dword + AND EAX,mask ; extracted bit field in EAX + + +3.4.5 Byte-Set-On-Condition Instructions + +This group of instructions sets a byte to zero or one depending on any of +the 16 conditions defined by the status flags. The byte may be in memory or +may be a one-byte general register. These instructions are especially useful +for implementing Boolean expressions in high-level languages such as Pascal. + +SETcc (Set Byte on Condition cc) set a byte to one if condition cc is true; +sets the byte to zero otherwise. Refer to Appendix D for a definition of +the possible conditions. + + +3.4.6 Test Instruction + +TEST (Test) performs the logical "and" of the two operands, clears OF and +CF, leaves AF undefined, and updates SF, ZF, and PF. The flags can be tested +by conditional control transfer instructions or by the byte-set-on-condition +instructions. The operands may be doublewords, words, or bytes. + +The difference between TEST and AND is that TEST does not alter the +destination operand. TEST differs from BT in that TEST is useful for testing +the value of multiple bits in one operations, whereas BT tests a single bit. + + +3.5 Control Transfer Instructions + +The 80386 provides both conditional and unconditional control transfer +instructions to direct the flow of execution. Conditional control transfers +depend on the results of operations that affect the flag register. +Unconditional control transfers are always executed. + + +3.5.1 Unconditional Transfer Instructions + +JMP, CALL, RET, INT and IRET instructions transfer control from one code +segment location to another. These locations can be within the same code +segment (near control transfers) or in different code segments (far control +transfers). The variants of these instructions that transfer control to +other segments are discussed in a later section of this chapter. If the +model of memory organization used in a particular 80386 application does +not make segments visible to applications programmers, intersegment control +transfers will not be used. + + +3.5.1.1 Jump Instruction + +JMP (Jump) unconditionally transfers control to the target location. JMP is +a one-way transfer of execution; it does not save a return address on the +stack. + +The JMP instruction always performs the same basic function of transferring +control from the current location to a new location. Its implementation +varies depending on whether the address is specified directly within the +instruction or indirectly through a register or memory. + +A direct JMP instruction includes the destination address as part of the +instruction. An indirect JMP instruction obtains the destination address +indirectly through a register or a pointer variable. + +Direct near JMP. A direct JMP uses a relative displacement value contained +in the instruction. The displacement is signed and the size of the +displacement may be a byte, word, or doubleword. The processor forms an +effective address by adding this relative displacement to the address +contained in EIP. When the additions have been performed, EIP refers to the +next instruction to be executed. + +Indirect near JMP. Indirect JMP instructions specify an absolute address in +one of several ways: + + 1. The program can JMP to a location specified by a general register + (any of EAX, EDX, ECX, EBX, EBP, ESI, or EDI). The processor moves + this 32-bit value into EIP and resumes execution. + + 2. The processor can obtain the destination address from a memory + operand specified in the instruction. + + 3. A register can modify the address of the memory pointer to select a + destination address. + + +3.5.1.2 Call Instruction + +CALL (Call Procedure) activates an out-of-line procedure, saving on the +stack the address of the instruction following the CALL for later use by a +RET (Return) instruction. CALL places the current value of EIP on the stack. +The RET instruction in the called procedure uses this address to transfer +control back to the calling program. + +CALL instructions, like JMP instructions have relative, direct, and +indirect versions. + +Indirect CALL instructions specify an absolute address in one of these +ways: + + 1. The program can CALL a location specified by a general register (any + of EAX, EDX, ECX, EBX, EBP, ESI, or EDI). The processor moves this + 32-bit value into EIP. + + 2. The processor can obtain the destination address from a memory + operand specified in the instruction. + + +3.5.1.3 Return and Return-From-Interrupt Instruction + +RET (Return From Procedure) terminates the execution of a procedure and +transfers control through a back-link on the stack to the program that +originally invoked the procedure. RET restores the value of EIP that was +saved on the stack by the previous CALL instruction. + +RET instructions may optionally specify an immediate operand. By adding +this constant to the new top-of-stack pointer, RET effectively removes any +arguments that the calling program pushed on the stack before the execution +of the CALL instruction. + +IRET (Return From Interrupt) returns control to an interrupted procedure. +IRET differs from RET in that it also pops the flags from the stack into the +flags register. The flags are stored on the stack by the interrupt +mechanism. + + +3.5.2 Conditional Transfer Instructions + +The conditional transfer instructions are jumps that may or may not +transfer control, depending on the state of the CPU flags when the +instruction executes. + + +3.5.2.1 Conditional Jump Instructions + +Table 3-2 shows the conditional transfer mnemonics and their +interpretations. The conditional jumps that are listed as pairs are actually +the same instruction. The assembler provides the alternate mnemonics for +greater clarity within a program listing. + +Conditional jump instructions contain a displacement which is added to the +EIP register if the condition is true. The displacement may be a byte, a +word, or a doubleword. The displacement is signed; therefore, it can be used +to jump forward or backward. + + +Table 3-2. Interpretation of Conditional Transfers + +Unsigned Conditional Transfers + +Mnemonic Condition Tested "Jump If..." + +JA/JNBE (CF or ZF) = 0 above/not below nor equal +JAE/JNB CF = 0 above or equal/not below +JB/JNAE CF = 1 below/not above nor equal +JBE/JNA (CF or ZF) = 1 below or equal/not above +JC CF = 1 carry +JE/JZ ZF = 1 equal/zero +JNC CF = 0 not carry +JNE/JNZ ZF = 0 not equal/not zero +JNP/JPO PF = 0 not parity/parity odd +JP/JPE PF = 1 parity/parity even + +Signed Conditional Transfers + +Mnemonic Condition Tested "Jump If..." +JG/JNLE ((SF xor OF) or ZF) = 0 greater/not less nor equal +JGE/JNL (SF xor OF) = 0 greater or equal/not less +JL/JNGE (SF xor OF) = 1 less/not greater nor equal +JLE/JNG ((SF xor OF) or ZF) = 1 less or equal/not greater +JNO OF = 0 not overflow +JNS SF = 0 not sign (positive, including 0) +JO OF = 1 overflow +JS SF = 1 sign (negative) + + +3.5.2.2 Loop Instructions + +The loop instructions are conditional jumps that use a value placed in ECX +to specify the number of repetitions of a software loop. All loop +instructions automatically decrement ECX and terminate the loop when ECX=0. +Four of the five loop instructions specify a condition involving ZF that +terminates the loop before ECX reaches zero. + +LOOP (Loop While ECX Not Zero) is a conditional transfer that automatically +decrements the ECX register before testing ECX for the branch condition. If +ECX is non-zero, the program branches to the target label specified in the +instruction. The LOOP instruction causes the repetition of a code section +until the operation of the LOOP instruction decrements ECX to a value of +zero. If LOOP finds ECX=0, control transfers to the instruction immediately +following the LOOP instruction. If the value of ECX is initially zero, then +the LOOP executes 2^(32) times. + +LOOPE (Loop While Equal) and LOOPZ (Loop While Zero) are synonyms for the +same instruction. These instructions automatically decrement the ECX +register before testing ECX and ZF for the branch conditions. If ECX is +non-zero and ZF=1, the program branches to the target label specified in the +instruction. If LOOPE or LOOPZ finds that ECX=0 or ZF=0, control transfers +to the instruction immediately following the LOOPE or LOOPZ instruction. + +LOOPNE (Loop While Not Equal) and LOOPNZ (Loop While Not Zero) are synonyms +for the same instruction. These instructions automatically decrement the ECX +register before testing ECX and ZF for the branch conditions. If ECX is +non-zero and ZF=0, the program branches to the target label specified in the +instruction. If LOOPNE or LOOPNZ finds that ECX=0 or ZF=1, control transfers +to the instruction immediately following the LOOPNE or LOOPNZ instruction. + + +3.5.2.3 Executing a Loop or Repeat Zero Times + +JCXZ (Jump if ECX Zero) branches to the label specified in the instruction +if it finds a value of zero in ECX. JCXZ is useful in combination with the +LOOP instruction and with the string scan and compare instructions, all of +which decrement ECX. Sometimes, it is desirable to design a loop that +executes zero times if the count variable in ECX is initialized to zero. +Because the LOOP instructions (and repeat prefixes) decrement ECX before +they test it, a loop will execute 2^(32) times if the program enters the +loop with a zero value in ECX. A programmer may conveniently overcome this +problem with JCXZ, which enables the program to branch around the code +within the loop if ECX is zero when JCXZ executes. When used with repeated +string scan and compare instructions, JCXZ can determine whether the +repetitions terminated due to zero in ECX or due to satisfaction of the +scan or compare conditions. + + +3.5.3 Software-Generated Interrupts + +The INT n, INTO, and BOUND instructions allow the programmer to specify a +transfer to an interrupt service routine from within a program. + +INT n (Software Interrupt) activates the interrupt service routine that +corresponds to the number coded within the instruction. The INT instruction +may specify any interrupt type. Programmers may use this flexibility to +implement multiple types of internal interrupts or to test the operation of +interrupt service routines. (Interrupts 0-31 are reserved by Intel.) The +interrupt service routine terminates with an IRET instruction that returns +control to the instruction that follows INT. + +INTO (Interrupt on Overflow) invokes interrupt 4 if OF is set. Interrupt 4 +is reserved for this purpose. OF is set by several arithmetic, logical, and +string instructions. + +BOUND (Detect Value Out of Range) verifies that the signed value contained +in the specified register lies within specified limits. An interrupt (INT 5) +occurs if the value contained in the register is less than the lower bound +or greater than the upper bound. + +The BOUND instruction includes two operands. The first operand specifies +the register being tested. The second operand contains the effective +relative address of the two signed BOUND limit values. The BOUND instruction +assumes that the upper limit and lower limit are in adjacent memory +locations. These limit values cannot be register operands; if they are, an +invalid opcode exception occurs. + +BOUND is useful for checking array bounds before using a new index value to +access an element within the array. BOUND provides a simple way to check the +value of an index register before the program overwrites information in a +location beyond the limit of the array. + +The block of memory that specifies the lower and upper limits of an array +might typically reside just before the array itself. This makes the array +bounds accessible at a constant offset from the beginning of the array. +Because the address of the array will already be present in a register, this +practice avoids extra calculations to obtain the effective address of the +array bounds. + +The upper and lower limit values may each be a word or a doubleword. + + +3.6 String and Character Translation Instructions + +The instructions in this category operate on strings rather than on logical +or numeric values. Refer also to the section on I/O for information about +the string I/O instructions (also known as block I/O). + +The power of 80386 string operations derives from the following features of +the architecture: + +1. A set of primitive string operations + + MOVS Move String + CMPS Compare string + SCAS Scan string + LODS Load string + STOS Store string + +2. Indirect, indexed addressing, with automatic incrementing or + decrementing of the indexes. + + Indexes: + + ESI Source index register + EDI Destination index register + + Control flag: + + DF Direction flag + + Control flag instructions: + + CLD Clear direction flag instruction + STD Set direction flag instruction + +3. Repeat prefixes + + REP Repeat while ECX not xero + REPE/REPZ Repeat while equal or zero + REPNE/REPNZ Repeat while not equal or not zero + +The primitive string operations operate on one element of a string. A +string element may be a byte, a word, or a doubleword. The string elements +are addressed by the registers ESI and EDI. After every primitive operation +ESI and/or EDI are automatically updated to point to the next element of the +string. If the direction flag is zero, the index registers are incremented; +if one, they are decremented. The amount of the increment or decrement is +1, 2, or 4 depending on the size of the string element. + + +3.6.1 Repeat Prefixes + +The repeat prefixes REP (Repeat While ECX Not Zero), REPE/REPZ (Repeat +While Equal/Zero), and REPNE/REPNZ (Repeat While Not Equal/Not Zero) specify +repeated operation of a string primitive. This form of iteration allows the +CPU to process strings much faster than would be possible with a regular +software loop. + +When a primitive string operation has a repeat prefix, the operation is +executed repeatedly, each time using a different element of the string. The +repetition terminates when one of the conditions specified by the prefix is +satisfied. + +At each repetition of the primitive instruction, the string operation may +be suspended temporarily in order to handle an exception or external +interrupt. After the interruption, the string operation can be restarted +again where it left off. This method of handling strings allows operations +on strings of arbitrary length, without affecting interrupt response. + +All three prefixes causes the hardware to automatically repeat the +associated string primitive until ECX=0. The differences among the repeat +prefixes have to do with the second termination condition. REPE/REPZ and +REPNE/REPNZ are used exclusively with the SCAS (Scan String) and CMPS +(Compare String) primitives. When these prefixes are used, repetition of the +next instruction depends on the zero flag (ZF) as well as the ECX register. +ZF does not require initialization before execution of a repeated string +instruction, because both SCAS and CMPS set ZF according to the results of +the comparisons they make. The differences are summarized in the +accompanying table. + +Prefix Termination Termination + Condition 1 Condition 2 + +REP ECX = 0 (none) +REPE/REPZ ECX = 0 ZF = 0 +REPNE/REPNZ ECX = 0 ZF = 1 + + +3.6.2 Indexing and Direction Flag Control + +The addresses of the operands of string primitives are determined by the +ESI and EDI registers. ESI points to source operands. By default, ESI refers +to a location in the segment indicated by the DS segment register. A +segment-override prefix may be used, however, to cause ESI to refer to CS, +SS, ES, FS, or GS. EDI points to destination operands in the segment +indicated by ES; no segment override is possible. The use of two different +segment registers in one instruction allows movement of strings between +different segments. + +This use of ESI and DSI has led to the descriptive names source index and +destination index for the ESI and EDI registers, respectively. In all +cases other than string instructions, however, the ESI and EDI registers may +be used as general-purpose registers. + +When ESI and EDI are used in string primitives, they are automatically +incremented or decremented after to operation. The direction flag determines +whether they are incremented or decremented. The instruction CLD puts zero +in DF, causing the index registers to be incremented; the instruction STD +puts one in DF, causing the index registers to be decremented. Programmers +should always put a known value in DF before using string instructions in a +procedure. + + +3.6.3 String Instructions + +MOVS (Move String) moves the string element pointed to by ESI to the +location pointed to by EDI. MOVSB operates on byte elements, MOVSW operates +on word elements, and MOVSD operates on doublewords. The destination segment +register cannot be overridden by a segment override prefix, but the source +segment register can be overridden. + +The MOVS instruction, when accompanied by the REP prefix, operates as a +memory-to-memory block transfer. To set up for this operation, the program +must initialize ECX and the register pairs ESI and EDI. ECX specifies the +number of bytes, words, or doublewords in the block. + +If DF=0, the program must point ESI to the first element of the source +string and point EDI to the destination address for the first element. If +DF=1, the program must point these two registers to the last element of the +source string and to the destination address for the last element, +respectively. + +CMPS (Compare Strings) subtracts the destination string element (at ES:EDI) +from the source string element (at ESI) and updates the flags AF, SF, PF, CF +and OF. If the string elements are equal, ZF=1; otherwise, ZF=0. If DF=0, +the processor increments the memory pointers (ESI and EDI) for the two +strings. CMPSB compares bytes, CMPSW compares words, and CMPSD compares +doublewords. The segment register used for the source address can be changed +with a segment override prefix while the destination segment register +cannot be overridden. + +SCAS (Scan String) subtracts the destination string element at ES:EDI from +EAX, AX, or AL and updates the flags AF, SF, ZF, PF, CF and OF. If the +values are equal, ZF=1; otherwise, ZF=0. If DF=0, the processor increments +the memory pointer (EDI) for the string. SCASB scans bytes; SCASW scans +words; SCASD scans doublewords. The destination segment register (ES) cannot +be overridden. + +When either the REPE or REPNE prefix modifies either the SCAS or CMPS +primitives, the processor compares the value of the current string element +with the value in EAX for doubleword elements, in AX for word elements, or +in AL for byte elements. Termination of the repeated operation depends on +the resulting state of ZF as well as on the value in ECX. + +LODS (Load String) places the source string element at ESI into EAX for +doubleword strings, into AX for word strings, or into AL for byte strings. +LODS increments or decrements ESI according to DF. + +STOS (Store String) places the source string element from EAX, AX, or AL +into the string at ES:DSI. STOS increments or decrements EDI according to +DF. + + +3.7 Instructions for Block-Structured Languages + +The instructions in this section provide machine-language support for +functions normally found in high-level languages. These instructions include +ENTER and LEAVE, which simplify the programming of procedures. + +ENTER (Enter Procedure) creates a stack frame that may be used to implement +the scope rules of block-structured high-level languages. A LEAVE +instruction at the end of a procedure complements an ENTER at the beginning +of the procedure to simplify stack management and to control access to +variables for nested procedures. + +The ENTER instruction includes two parameters. The first parameter +specifies the number of bytes of dynamic storage to be allocated on the +stack for the routine being entered. The second parameter corresponds to the +lexical nesting level (0-31) of the routine. (Note that the lexical level +has no relationship to either the protection privilege levels or to the I/O +privilege level.) + +The specified lexical level determines how many sets of stack frame +pointers the CPU copies into the new stack frame from the preceding frame. +This list of stack frame pointers is sometimes called the display. The first +word of the display is a pointer to the last stack frame. This pointer +enables a LEAVE instruction to reverse the action of the previous ENTER +instruction by effectively discarding the last stack frame. + + Example: ENTER 2048,3 + + Allocates 2048 bytes of dynamic storage on the stack and sets up pointers + to two previous stack frames in the stack frame that ENTER creates for + this procedure. + +After ENTER creates the new display for a procedure, it allocates the +dynamic storage space for that procedure by decrementing ESP by the number +of bytes specified in the first parameter. This new value of ESP serves as a +starting point for all PUSH and POP operations within that procedure. + +To enable a procedure to address its display, ENTER leaves EBP pointing to +the beginning of the new stack frame. Data manipulation instructions that +specify EBP as a base register implicitly address locations within the stack +segment instead of the data segment. + +The ENTER instruction can be used in two ways: nested and non-nested. If +the lexical level is 0, the non-nested form is used. Since the second +operand is 0, ENTER pushes EBP, copies ESP to EBP and then subtracts the +first operand from ESP. The nested form of ENTER occurs when the second +parameter (lexical level) is not 0. + +Figure 3-16 gives the formal definition of ENTER. + +The main procedure (with other procedures nested within) operates at the +highest lexical level, level 1. The first procedure it calls operates at the +next deeper lexical level, level 2. A level 2 procedure can access the +variables of the main program which are at fixed locations specified by the +compiler. In the case of level 1, ENTER allocates only the requested +dynamic storage on the stack because there is no previous display to copy. + +A program operating at a higher lexical level calling a program at a lower +lexical level requires that the called procedure should have access to the +variables of the calling program. ENTER provides this access through a +display that provides addressability to the calling program's stack frame. + +A procedure calling another procedure at the same lexical level implies +that they are parallel procedures and that the called procedure should not +have access to the variables of the calling procedure. In this case, ENTER +copies only that portion of the display from the calling procedure which +refers to previously nested procedures operating at higher lexical levels. +The new stack frame does not include the pointer for addressing the calling +procedure's stack frame. + +ENTER treats a reentrant procedure as a procedure calling another procedure +at the same lexical level. In this case, each succeeding iteration of the +reentrant procedure can address only its own variables and the variables of +the calling procedures at higher lexical levels. A reentrant procedure can +always address its own variables; it does not require pointers to the stack +frames of previous iterations. + +By copying only the stack frame pointers of procedures at higher lexical +levels, ENTER makes sure that procedures access only those variables of +higher lexical levels, not those at parallel lexical levels (see Figure +3-17). Figures 3-18 through 3-21 demonstrate the actions of the ENTER +instruction if the modules shown in Figure 3-17 were to call one another in +alphabetic order. + +Block-structured high-level languages can use the lexical levels defined by +ENTER to control access to the variables of previously nested procedures. +Referring to Figure 3-17 for example, if PROCEDURE A calls PROCEDURE B +which, in turn, calls PROCEDURE C, then PROCEDURE C will have access to the +variables of MAIN and PROCEDURE A, but not PROCEDURE B because they operate +at the same lexical level. Following is the complete definition of access to +variables for Figure 3-17. + + 1. MAIN PROGRAM has variables at fixed locations. + + 2. PROCEDURE A can access only the fixed variables of MAIN. + + 3. PROCEDURE B can access only the variables of PROCEDURE A and MAIN. + PROCEDURE B cannot access the variables of PROCEDURE C or PROCEDURE D. + + 4. PROCEDURE C can access only the variables of PROCEDURE A and MAIN. + PROCEDURE C cannot access the variables of PROCEDURE B or PROCEDURE D. + + 5. PROCEDURE D can access the variables of PROCEDURE C, PROCEDURE A, and + MAIN. PROCEDURE D cannot access the variables of PROCEDURE B. + +ENTER at the beginning of the MAIN PROGRAM creates dynamic storage space +for MAIN but copies no pointers. The first and only word in the display +points to itself because there is no previous value for LEAVE to return to +EBP. See Figure 3-18. + +After MAIN calls PROCEDURE A, ENTER creates a new display for PROCEDURE A +with the first word pointing to the previous value of EBP (BPM for LEAVE to +return to the MAIN stack frame) and the second word pointing to the current +value of EBP. Procedure A can access variables in MAIN since MAIN is at +level 1. Therefore the base for the dynamic storage for MAIN is at [EBP-2]. +All dynamic variables for MAIN are at a fixed offset from this value. See +Figure 3-19. + +After PROCEDURE A calls PROCEDURE B, ENTER creates a new display for +PROCEDURE B with the first word pointing to the previous value of EBP, the +second word pointing to the value of EBP for MAIN, and the third word +pointing to the value of EBP for A and the last word pointing to the current +EBP. B can access variables in A and MAIN by fetching from the display the +base addresses of the respective dynamic storage areas. See Figure 3-20. + +After PROCEDURE B calls PROCEDURE C, ENTER creates a new display for +PROCEDURE C with the first word pointing to the previous value of EBP, the +second word pointing to the value of EBP for MAIN, and the third word +pointing to the EBP value for A and the third word pointing to the current +value of EBP. Because PROCEDURE B and PROCEDURE C have the same lexical +level, PROCEDURE C is not allowed access to variables in B and therefore +does not receive a pointer to the beginning of PROCEDURE B's stack frame. +See Figure 3-21. + +LEAVE (Leave Procedure) reverses the action of the previous ENTER +instruction. The LEAVE instruction does not include any operands. LEAVE +copies EBP to ESP to release all stack space allocated to the procedure by +the most recent ENTER instruction. Then LEAVE pops the old value of EBP from +the stack. A subsequent RET instruction can then remove any arguments that +were pushed on the stack by the calling program for use by the called +procedure. + + +Figure 3-16. Formal Definition of the ENTER Instruction + +The formal definition of the ENTER instruction for all cases is given by the +following listing. LEVEL denotes the value of the second operand. + +Push EBP +Set a temporary value FRAME_PTR := ESP +If LEVEL > 0 then + Repeat (LEVEL-1) times: + EBP :=EBP - 4 + Push the doubleword pointed to by EBP + End repeat + Push FRAME_PTR +End if +EBP := FRAME_PTR +ESP := ESP - first operand. + + +Figure 3-17. Variable Access in Nested Procedures + + ͻ + MAIN PROCEDURE (LEXICAL LEVEL 1) + ͻ + PROCEDURE A (LEXICAL LEVEL 2) + ͻ + PROCEDURE B (LEXICAL LEVEL 3) + ͼ + + ͻ + PROCEDURE C (LEXICAL LEVEL 3) + ͻ + PROCEDURE D (LEXICAL LEVEL 4) + ͼ + + ͼ + + ͼ + + ͼ + + +Figure 3-18. Stack Frame for MAIN at Level 1 + +  31 0  + D O + I F ͹ + R OLD ESP + E E DISPLAY Ĵ ͹EBP FOR + C X EBPM +EBPM = EBP VALUE FOR MAIN MAIN + T P ͹ + I A + O N ͹ + N S DYNAMIC Ĵ + I STORAGE ͹ + O + N ͹ESP + +    + + +Figure 3-19. Stack Frame for Procedure A + +  31 0  + D O + I F ͹ + R OLD ESP + E E ͹ + C X EBPM +EBPM = EBP VALUE FOR MAIN + T P ͹ + I A + O N ͹ + N S + I ͹ + O + N ͹ + EBPM +  ͹EBP FOR A + DISPLAY Ĵ EBPM + ͹ + EBPA +EBPA = EBP VALUE FOR PROCEDURE A + ͹ + + ͹ + DYNAMIC Ĵ + STORAGE ͹ + + ͹ESP + +   + + +Figure 3-20. Stack Frame for Procedure B at Level 3 Called from A + +  31 0  + D O + I F ͹ + R OLD ESP + E E ͹ + C X EBPM +EBPM = EBP VALUE FOR MAIN + T P ͹ + I A + O N ͹ + N S + I ͹ + O + N ͹ + EBPM +  ͹ + EBPM + ͹ + EBPA + ͹ + + ͹ + + ͹ + + ͹ + EBPA + ͹EBP + EBPM + DISPLAY Ĵ ͹ + EBPA + ͹ + EBPB +EBPB = EBP VALUE FOR PROCEDURE B + ͹ + + ͹ + DYNAMIC Ĵ + STORAGE ͹ + + ͹ESP + +   + + +Figure 3-21. Stack Frame for Procedure C at Level 3 Called from B + +  31 0  + D O + I F ͹ + R OLD ESP + E E ͹ + C X EBPM +EBPM = EBP VALUE FOR MAIN + T P ͹ + I A + O N ͹ + N S + I ͹ + O + N ͹ + EBPM +  ͹ + EBPM + ͹ + EBPA +EBPA = EBP VALUE FOR PROCEDURE A + ͹ + + ͹ + + ͹ + + ͹ + EBPA + ͹EBP + EBPM + DISPLAY Ĵ ͹ + EBPA + ͹ + EBPB +EBPB = EBP VALUE FOR PROCEDURE B + ͹ + + ͹ + DYNAMIC Ĵ + STORAGE ͹ + + ͹ESP + +   + + +3.8 Flag Control Instructions + +The flag control instructions provide a method for directly changing the +state of bits in the flag register. + + +3.8.1 Carry and Direction Flag Control Instructions + +The carry flag instructions are useful in conjunction with +rotate-with-carry instructions RCL and RCR. They can initialize the carry +flag, CF, to a known state before execution of a rotate that moves the carry +bit into one end of the rotated operand. + +The direction flag control instructions are specifically included to set or +clear the direction flag, DF, which controls the left-to-right or +right-to-left direction of string processing. If DF=0, the processor +automatically increments the string index registers, ESI and EDI, after each +execution of a string primitive. If DF=1, the processor decrements these +index registers. Programmers should use one of these instructions before any +procedure that uses string instructions to insure that DF is set properly. + +Flag Control Instruction Effect + +STC (Set Carry Flag) CF  1 +CLC (Clear Carry Flag) CF  0 +CMC (Complement Carry Flag) CF  NOT (CF) +CLD (Clear Direction Flag) DF  0 +STD (Set Direction Flag) DF  1 + + +3.8.2 Flag Transfer Instructions + +Though specific instructions exist to alter CF and DF, there is no direct +method of altering the other applications-oriented flags. The flag transfer +instructions allow a program to alter the other flag bits with the bit +manipulation instructions after transferring these flags to the stack or the +AH register. + +The instructions LAHF and SAHF deal with five of the status flags, which +are used primarily by the arithmetic and logical instructions. + +LAHF (Load AH from Flags) copies SF, ZF, AF, PF, and CF to AH bits 7, 6, 4, +2, and 0, respectively (see Figure 3-22). The contents of the remaining bits +(5, 3, and 1) are undefined. The flags remain unaffected. + +SAHF (Store AH into Flags) transfers bits 7, 6, 4, 2, and 0 from AH into +SF, ZF, AF, PF, and CF, respectively (see Figure 3-22). + +The PUSHF and POPF instructions are not only useful for storing the flags +in memory where they can be examined and modified but are also useful for +preserving the state of the flags register while executing a procedure. + +PUSHF (Push Flags) decrements ESP by two and then transfers the low-order +word of the flags register to the word at the top of stack pointed to by ESP +(see Figure 3-23). The variant PUSHFD decrements ESP by four, then +transfers both words of the extended flags register to the top of the stack +pointed to by ESP (the VM and RF flags are not moved, however). + +POPF (Pop Flags) transfers specific bits from the word at the top of stack +into the low-order byte of the flag register (see Figure 3-23), then +increments ESP by two. The variant POPFD transfers specific bits from the +doubleword at the top of the stack into the extended flags register (the RF +and VM flags are not changed, however), then increments ESP by four. + + +Figure 3-22. LAHF and SAHF + + 7 6 5 4 3 2 1 0 + ͻ + SF ZF UU AF UU PF UU CF + ͼ + + LAHF LOADS FIVE FLAGS FROM THE FLAG REGISTER INTO REGISTER AH. SAHF + STORES THESE SAME FIVE FLAGS FROM AH INTO THE FLAG REGISTER. THE BIT + POSITION OF EACH FLAG IS THE SAME IN AH AS IT IS IN THE FLAG REGISTER. + THE REMAINING BITS (MARKED UU) ARE RESERVED; DO NOT DEFINE. + + +3.9 Coprocessor Interface Instructions + +A numerics coprocessor (e.g., the 80387 or 80287) provides an extension to +the instruction set of the base architecture. The coprocessor extends the +instruction set of the base architecture to support high-precision integer +and floating-point calculations. This extended instruction set includes +arithmetic, comparison, transcendental, and data transfer instructions. The +coprocessor also contains a set of useful constants to enhance the speed of +numeric calculations. + +A program contains instructions for the coprocessor in line with the +instructions for the CPU. The system executes these instructions in the same +order as they appear in the instruction stream. The coprocessor operates +concurrently with the CPU to provide maximum throughput for numeric +calculations. + +The 80386 also has features to support emulation of the numerics +coprocessor when the coprocessor is absent. The software emulation of the +coprocessor is transparent to application software but requires more time +for execution. Refer to Chapter 11 for more information on coprocessor +emulation. + +ESC (Escape) is a 5-bit sequence that begins the opcodes that identify +floating point numeric instructions. The ESC pattern tells the 80386 to send +the opcode and addresses of operands to the numerics coprocessor. The +numerics coprocessor uses the escape instructions to perform +high-performance, high-precision floating point arithmetic that conforms to +the IEEE floating point standard 754. + +WAIT (Wait) is an 80386 instruction that suspends program execution until +the 80386 CPU detects that the BUSY pin is inactive. This condition +indicates that the coprocessor has completed its processing task and that +the CPU may obtain the results. + + +Figure 3-23. Flag Format for PUSHF and POPF + + PUSHFD/POPFD + Ŀ + PUSHF/POPF + Ŀ + 31 23 15 7 0 + ͻ + VR NID ODITSZ A P C + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 + MF T PLFFFFFF F F F + ͼ + + BITS MARKED 0 AND 1 ARE RESERVED BY INTEL. DO NOT DEFINE. + + SYSTEMS FLAGS (INCLUDING THE IOPL FIELD, AND THE VM, RF, AND IF FLAGS) + ARE PUSHED AND ARE VISIBLE TO APPLICATIONS PROGRAMS. HOWEVER, WHEN AN + APPLICATIONS PROGRAM POPS THE FLAGS, THESE ITEMS ARE NOT CHANGED, + REGARDLESS OF THE VALUES POPPED INTO THEM. + + +3.10 Segment Register Instructions + +This category actually includes several distinct types of instructions. +These various types are grouped together here because, if systems designers +choose an unsegmented model of memory organization, none of these +instructions is used by applications programmers. The instructions that deal +with segment registers are: + +1. Segment-register transfer instructions. + + MOV SegReg, ... + MOV ..., SegReg + PUSH SegReg + POP SegReg + +2. Control transfers to another executable segment. + + JMP far ; direct and indirect + CALL far + RET far + +3. Data pointer instructions. + + LDS + LES + LFS + LGS + LSS + +Note that the following interrupt-related instructions are different; all +are capable of transferring control to another segment, but the use of +segmentation is not apparent to the applications programmer. + +INT n +INTO +BOUND +IRET + + +3.10.1 Segment-Register Transfer Instructions + +The MOV, POP, and PUSH instructions also serve to load and store segment +registers. These variants operate similarly to their general-register +counterparts except that one operand can be a segment register. MOV cannot +move segment register to a segment register. Neither POP nor MOV can place a +value in the code-segment register CS; only the far control-transfer +instructions can change CS. + + +3.10.2 Far Control Transfer Instructions + +The far control-transfer instructions transfer control to a location in +another segment by changing the content of the CS register. + +Direct far JMP. Direct JMP instructions that specify a target location +outside the current code segment contain a far pointer. This pointer +consists of a selector for the new code segment and an offset within the new +segment. + +Indirect far JMP. Indirect JMP instructions that specify a target location +outside the current code segment use a 48-bit variable to specify the far +pointer. + +Far CALL. An intersegment CALL places both the value of EIP and CS on the +stack. + +Far RET. An intersegment RET restores the values of both CS and EIP which +were saved on the stack by the previous intersegment CALL instruction. + + +3.10.3 Data Pointer Instructions + +The data pointer instructions load a pointer (consisting of a segment +selector and an offset) to a segment register and a general register. + +LDS (Load Pointer Using DS) transfers a pointer variable from the source +operand to DS and the destination register. The source operand must be a +memory operand, and the destination operand must be a general register. DS +receives the segment-selector of the pointer. The destination register +receives the offset part of the pointer, which points to a specific location +within the segment. + +Example: LDS ESI, STRING_X + +Loads DS with the selector identifying the segment pointed to by a +STRING_X, and loads the offset of STRING_X into ESI. Specifying ESI as the +destination operand is a convenient way to prepare for a string operation on +a source string that is not in the current data segment. + +LES (Load Pointer Using ES) operates identically to LDS except that ES +receives the segment selector rather than DS. + +Example: LES EDI, DESTINATION_X + +Loads ES with the selector identifying the segment pointed to by +DESTINATION_X, and loads the offset of DESTINATION_X into EDI. This +instruction provides a convenient way to select a destination for a string +operation if the desired location is not in the current extra segment. + +LFS (Load Pointer Using FS) operates identically to LDS except that FS +receives the segment selector rather than DS. + +LGS (Load Pointer Using GS) operates identically to LDS except that GS +receives the segment selector rather than DS. + +LSS (Load Pointer Using SS) operates identically to LDS except that SS +receives the segment selector rather than DS. This instruction is +especially important, because it allows the two registers that identify the +stack (SS:ESP) to be changed in one uninterruptible operation. Unlike the +other instructions which load SS, interrupts are not inhibited at the end +of the LSS instruction. The other instructions (e.g., POP SS) inhibit +interrupts to permit the following instruction to load ESP, thereby forming +an indivisible load of SS:ESP. Since both SS and ESP can be loaded by LSS, +there is no need to inhibit interrupts. + + +3.11 Miscellaneous Instructions + +The following instructions do not fit in any of the previous categories, +but are nonetheless useful. + + +3.11.1 Address Calculation Instruction + +LEA (Load Effective Address) transfers the offset of the source operand +(rather than its value) to the destination operand. The source operand must +be a memory operand, and the destination operand must be a general register. +This instruction is especially useful for initializing registers before the +execution of the string primitives (ESI, EDI) or the XLAT instruction (EBX). +The LEA can perform any indexing or scaling that may be needed. + +Example: LEA EBX, EBCDIC_TABLE + +Causes the processor to place the address of the starting location of the +table labeled EBCDIC_TABLE into EBX. + + +3.11.2 No-Operation Instruction + +NOP (No Operation) occupies a byte of storage but affects nothing but the +instruction pointer, EIP. + + +3.11.3 Translate Instruction + +XLAT (Translate) replaced a byte in the AL register with a byte from a +user-coded translation table. When XLAT is executed, AL should have the +unsigned index to the table addressed by EBX. XLAT changes the contents of +AL from table index to table entry. EBX is unchanged. The XLAT instruction +is useful for translating from one coding system to another such as from +ASCII to EBCDIC. The translate table may be up to 256 bytes long. The +value placed in the AL register serves as an index to the location of the +corresponding translation value. + + + PART II SYSTEMS PROGRAMMING + + +Chapter 4 Systems Architecture + + + +Many of the architectural features of the 80386 are used only by systems +programmers. This chapter presents an overview of these aspects of the +architecture. + +The systems-level features of the 80386 architecture include: + + Memory Management + Protection + Multitasking + Input/Output + Exceptions and Interrupts + Initialization + Coprocessing and Multiprocessing + Debugging + +These features are implemented by registers and instructions, all of which +are introduced in the following sections. The purpose of this chapter is not +to explain each feature in detail, but rather to place the remaining +chapters of Part II in perspective. Each mention in this chapter of a +register or instruction is either accompanied by an explanation or a +reference to a following chapter where detailed information can be obtained. + + +4.1 Systems Registers + +The registers designed for use by systems programmers fall into these +classes: + + EFLAGS + Memory-Management Registers + Control Registers + Debug Registers + Test Registers + + +4.1.1 Systems Flags + +The systems flags of the EFLAGS register control I/O, maskable interrupts, +debugging, task switching, and enabling of virtual 8086 execution in a +protected, multitasking environment. These flags are highlighted in Figure +4-1. + +IF (Interrupt-Enable Flag, bit 9) + + Setting IF allows the CPU to recognize external (maskable) interrupt + requests. Clearing IF disables these interrupts. IF has no effect on + either exceptions or nonmaskable external interrupts. Refer to Chapter + 9 for more details about interrupts. + +NT (Nested Task, bit 14) + + The processor uses the nested task flag to control chaining of + interrupted and called tasks. NT influences the operation of the IRET + instruction. Refer to Chapter 7 and Chapter 9 for more information on + nested tasks. + +RF (Resume Flag, bit 16) + + The RF flag temporarily disables debug exceptions so that an instruction + can be restarted after a debug exception without immediately causing + another debug exception. Refer to Chapter 12 for details. + +TF (Trap Flag, bit 8) + + Setting TF puts the processor into single-step mode for debugging. In + this mode, the CPU automatically generates an exception after each + instruction, allowing a program to be inspected as it executes each + instruction. Single-stepping is just one of several debugging features of + the 80386. Refer to Chapter 12 for additional information. + +VM (Virtual 8086 Mode, bit 17) + + When set, the VM flag indicates that the task is executing an 8086 + program. Refer to Chapter 14 for a detailed discussion of how the 80386 + executes 8086 tasks in a protected, multitasking environment. + + +Figure 4-1. System Flags of EFLAGS Register + + 31 23 15 7 0 + ͻ + VRNID ODITSZAPC + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 001 + MFT PLFFFFFFFFF + ͼ + + VIRTUAL 8086 MODE + RESUME FLAG + NESTED TASK FLAG + I/O PRIVILEGE LEVEL + INTERRUPT ENABLE + + +NOTE + 0 OR 1 INDICATES INTEL RESERVED. DO NOT DEFINE. + + + +4.1.2 Memory-Management Registers + +Four registers of the 80386 locate the data structures that control +segmented memory management: + +GDTR Global Descriptor Table Register +LDTR Local Descriptor Table Register + + These registers point to the segment descriptor tables GDT and LDT. + Refer to Chapter 5 for an explanation of addressing via descriptor + tables. + +IDTR Interrupt Descriptor Table Register + + This register points to a table of entry points for interrupt handlers + (the IDT). Refer to Chapter 9 for details of the interrupt mechanism. + +TR Task Register + + This register points to the information needed by the processor to define + the current task. Refer to Chapter 7 for a description of the + multitasking features of the 80386. + + +4.1.3 Control Registers + +Figure 4-2 shows the format of the 80386 control registers CR0, CR2, and +CR3. These registers are accessible to systems programmers only via variants +of the MOV instruction, which allow them to be loaded from or stored in +general registers; for example: + +MOV EAX, CR0 +MOV CR3, EBX + +CR0 contains system control flags, which control or indicate conditions +that apply to the system as a whole, not to an individual task. + +EM (Emulation, bit 2) + + EM indicates whether coprocessor functions are to be emulated. Refer to + Chapter 11 for details. + +ET (Extension Type, bit 4) + + ET indicates the type of coprocessor present in the system (80287 or + 80387). Refer to Chapter 11 and Chapter 10 for details. + +MP (Math Present, bit 1) + + MP controls the function of the WAIT instruction, which is used to + coordinate a coprocessor. Refer to Chapter 11 for details. + +PE (Protection Enable, bit 0) + + Setting PE causes the processor to begin executing in protected mode. + Resetting PE returns to real-address mode. Refer to Chapter 14 and + Chapter 10 for more information on changing processor modes. + +PG (Paging, bit 31) + + PG indicates whether the processor uses page tables to translate linear + addresses into physical addresses. Refer to Chapter 5 for a description + of page translation; refer to Chapter 10 for a discussion of how to set + PG. + +TS (Task Switched, bit 3) + + The processor sets TS with every task switch and tests TS when + interpreting coprocessor instructions. Refer to Chapter 11 for details. + +CR2 is used for handling page faults when PG is set. The processor stores +in CR2 the linear address that triggers the fault. Refer to Chapter 9 for a +description of page-fault handling. + +CR3 is used when PG is set. CR3 enables the processor to locate the page +table directory for the current task. Refer to Chapter 5 for a description +of page tables and page translation. + + +Figure 4-2. Control Registers + + 31 23 15 7 0 +ͻ + + PAGE DIRECTORY BASE REGISTER (PDBR) RESERVED CR3 +Ķ + + PAGE FAULT LINEAR ADDRESS CR2 +Ķ + + RESERVED CR1 +Ķ +P ETEMP +G RESERVED TSMPECR0 +ͼ + + +4.1.4 Debug Register + +The debug registers bring advanced debugging abilities to the 80386, +including data breakpoints and the ability to set instruction breakpoints +without modifying code segments. Refer to Chapter 12 for a complete +description of formats and usage. + + +4.1.5 Test Registers + +The test registers are not a standard part of the 80386 architecture. They +are provided solely to enable confidence testing of the translation +lookaside buffer (TLB), the cache used for storing information from page +tables. Chapter 12 explains how to use these registers. + + +4.2 Systems Instructions + +Systems instructions deal with such functions as: + + 1. Verification of pointer parameters (refer to Chapter 6): + + ARPL Adjust RPL + LAR Load Access Rights + LSL Load Segment Limit + VERR Verify for Reading + VERW Verify for Writing + + 2. Addressing descriptor tables (refer to Chaper 5): + + LLDT Load LDT Register + SLDT Store LDT Register + LGDT Load GDT Register + SGDT Store GDT Register + + 3. Multitasking (refer to Chapter 7): + + LTR Load Task Register + STR Store Task Register + + 4. Coprocessing and Multiprocessing (refer to Chapter 11): + + CLTS Clear Task-Switched Flag + ESC Escape instructions + WAIT Wait until Coprocessor not Busy + LOCK Assert Bus-Lock Signal + + 5. Input and Output (refer to Chapter 8): + + IN Input + OUT Output + INS Input String + OUTS Output String + + 6. Interrupt control (refer to Chapter 9): + + CLI Clear Interrupt-Enable Flag + STI Set Interrupt-Enable Flag + LIDT Load IDT Register + SIDT Store IDT Register + + 7. Debugging (refer to Chapter 12): + + MOV Move to and from debug registers + + 8. TLB testing (refer to Chapter 10): + + MOV Move to and from test registers + + 9. System Control: + + SMSW Set MSW + LMSW Load MSW + HLT Halt Processor + MOV Move to and from control registers + +The instructions SMSW and LMSW are provided for compatibility with the +80286 processor. 80386 programs access the MSW in CR0 via variants of the +MOV instruction. HLT stops the processor until receipt of an INTR or RESET +signal. + +In addition to the chapters cited above, detailed information about each of +these instructions can be found in the instruction reference chapter, +Chapter 17. + + +Chapter 5 Memory Management + + + +The 80386 transforms logical addresses (i.e., addresses as viewed by +programmers) into physical address (i.e., actual addresses in physical +memory) in two steps: + + Segment translation, in which a logical address (consisting of a + segment selector and segment offset) are converted to a linear address. + + Page translation, in which a linear address is converted to a physical + address. This step is optional, at the discretion of systems-software + designers. + +These translations are performed in a way that is not visible to +applications programmers. Figure 5-1 illustrates the two translations at a +high level of abstraction. + +Figure 5-1 and the remainder of this chapter present a simplified view of +the 80386 addressing mechanism. In reality, the addressing mechanism also +includes memory protection features. For the sake of simplicity, however, +the subject of protection is taken up in another chapter, Chapter 6. + + +Figure 5-1. Address Translation Overview + + 15 0 31 0 + LOGICAL ͻ ͻ + ADDRESS SELECTOR OFFSET + ͼ ͼ +  + ͻ + SEGMENT TRANSLATION + ͼ + ͻ PAGING ENABLED + PG ?Ŀ + ͼ + 31 PAGING  DISABLED 0 + LINEAR ͻ + ADDRESS DIR PAGE OFFSET + ͼ +  + ͻ + PAGE TRANSLATION + ͼ +  + 31  0 + PHYSICAL ͻ + ADDRESS + ͼ + + +5.1 Segment Translation + +Figure 5-2 shows in more detail how the processor converts a logical +address into a linear address. + +To perform this translation, the processor uses the following data +structures: + + Descriptors + Descriptor tables + Selectors + Segment Registers + + +5.1.1 Descriptors + +The segment descriptor provides the processor with the data it needs to map +a logical address into a linear address. Descriptors are created by +compilers, linkers, loaders, or the operating system, not by applications +programmers. Figure 5-3 illustrates the two general descriptor formats. All +types of segment descriptors take one of these formats. Segment-descriptor +fields are: + +BASE: Defines the location of the segment within the 4 gigabyte linear +address space. The processor concatenates the three fragments of the base +address to form a single 32-bit value. + +LIMIT: Defines the size of the segment. When the processor concatenates the +two parts of the limit field, a 20-bit value results. The processor +interprets the limit field in one of two ways, depending on the setting of +the granularity bit: + + 1. In units of one byte, to define a limit of up to 1 megabyte. + + 2. In units of 4 Kilobytes, to define a limit of up to 4 gigabytes. The + limit is shifted left by 12 bits when loaded, and low-order one-bits + are inserted. + +Granularity bit: Specifies the units with which the LIMIT field is +interpreted. When thebit is clear, the limit is interpreted in units of one +byte; when set, the limit is interpreted in units of 4 Kilobytes. + +TYPE: Distinguishes between various kinds of descriptors. + +DPL (Descriptor Privilege Level): Used by the protection mechanism (refer +to Chapter 6). + +Segment-Present bit: If this bit is zero, the descriptor is not valid for +use in address transformation; the processor will signal an exception when a +selector for the descriptor is loaded into a segment register. Figure 5-4 +shows the format of a descriptor when the present-bit is zero. The operating +system is free to use the locations marked AVAILABLE. Operating systems that +implement segment-based virtual memory clear the present bit in either of +these cases: + + When the linear space spanned by the segment is not mapped by the + paging mechanism. + + When the segment is not present in memory. + +Accessed bit: The processor sets this bit when the segment is accessed; +i.e., a selector for the descriptor is loaded into a segment register or +used by a selector test instruction. Operating systems that implement +virtual memory at the segment level may, by periodically testing and +clearing this bit, monitor frequency of segment usage. + +Creation and maintenance of descriptors is the responsibility of systems +software, usually requiring the cooperation of compilers, program loaders or +system builders, and therating system. + + +Figure 5-2. Segment Translation + + 15 0 31 0 + LOGICAL ͻ ͻ + ADDRESS SELECTOR OFFSET + ͼ ͼ +  + DESCRIPTOR TABLE + ͻ + + + + + ͹ + SEGMENT BASE ͻ +  DESCRIPTOR  +  + ͹ ADDRESS ͼ + + ͼ +  + LINEAR ͻ + ADDRESS DIR PAGE OFFSET + ͼ + + +Figure 5-3. General Segment-Descriptor Format + + DESCRIPTORS USED FOR APPLICATIONS CODE AND DATA SEGMENTS + + 31 23 15 7 0 + ͻ + A + BASE 31..24 GXOV LIMIT P DPL 1 TYPEA BASE 23..16 4 + L 19..16 + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + DESCRIPTORS USED FOR SPECIAL SYSTEM SEGMENTS + + 31 23 15 7 0 + ͻ + A + BASE 31..24 GXOV LIMIT P DPL 0 TYPE BASE 23..16 4 + L 19..16 + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + A - ACCESSED + AVL - AVAILABLE FOR USE BY SYSTEMS PROGRAMMERS + DPL - DESCRIPTOR PRIVILEGE LEVEL + G - GRANULARITY + P - SEGMENT PRESENT + + +5.1.2 Descriptor Tables + +Segment descriptors are stored in either of two kinds of descriptor table: + + The global descriptor table (GDT) + A local descriptor table (LDT) + +A descriptor table is simply a memory array of 8-byte entries that contain +descriptors, as Figure 5-5 shows. A descriptor table is variable in length +and may contain up to 8192 (2^(13)) descriptors. The first entry of the GDT +(INDEX=0) is not used by the processor, however. + +The processor locates the GDT and the current LDT in memory by means of the +GDTR and LDTR registers. These registers store the base addresses of the +tables in the linear address space and store the segment limits. The +instructions LGDT and SGDT give access to the GDTR; the instructions LLDT +and SLDT give access to the LDTR. + + +Figure 5-4. Format of Not-Present Descriptor + + 31 23 15 7 0 + ͻ + + AVAILABLE O DPL S TYPE AVAILABLE 4 + + Ķ + + AVAILABLE 0 + + ͼ + + +Figure 5-5. Descriptor Tables + + GLOBAL DESCRIPTOR TABLE LOCAL DESCRIPTOR TABLE + ͻ ͻ + + Ķ Ķ + M M + ͼ ͼ + | | | | + | | | | + ͻ ͻ + + Ķ Ķ + N + 3 N + 3 + ͹ ͹ + + Ķ Ķ + N + 2 N + 2 + ͹ ͹ + + Ķ Ķ + N + 1 N + 1 + ͹ ͹ + + Ķ Ķ + N N + ͼ ͼ + | | | | + | | | | + ͻ ͻ + + (UNUSED)Ķ Ķ + + ͼ ͼ +   + ͻ ͻ + GDTR LDTR + ͼ ͼ + + +5.1.3 Selectors + +The selector portion of a logical address identifies a descriptor by +specifying a descriptor table and indexing a descriptor within that table. +Selectors may be visible to applications programs as a field within a +pointer variable, but the values of selectors are usually assigned (fixed +up) by linkers or linking loaders. Figure 5-6 shows the format of a +selector. + +Index: Selects one of 8192 descriptors in a descriptor table. The processor +simply multiplies this index value by 8 (the length of a descriptor), and +adds the result to the base address of the descriptor table in order to +access the appropriate segment descriptor in the table. + +Table Indicator: Specifies to which descriptor table the selector refers. A +zero indicates the GDT; a one indicates the current LDT. + +Requested Privilege Level: Used by the protection mechanism. (Refer to +Chapter 6.) + +Because the first entry of the GDT is not used by the processor, a selector +that has an index of zero and a table indicator of zero (i.e., a selector +that points to the first entry of the GDT), can be used as a null selector. +The processor does not cause an exception when a segment register (other +than CS or SS) is loaded with a null selector. It will, however, cause an +exception when the segment register is used to access memory. This feature +is useful for initializing unused segment registers so as to trap accidental +references. + + +Figure 5-6. Format of a Selector + + 15 4 3 0 + ͻ + T + INDEX RPL + I + ͼ + + TI - TABLE INDICATOR + RPL - REQUESTOR'S PRIVILEGE LEVEL + + +Figure 5-7. Segment Registers + + 16-BIT VISIBLE + SELECTOR HIDDEN DESCRIPTOR + ͻ + CS + Ķ + SS + Ķ + DS + Ķ + ES + Ķ + FS + Ķ + GS + ͼ + + +5.1.4 Segment Registers + +The 80386 stores information from descriptors in segment registers, thereby +avoiding the need to consult a descriptor table every time it accesses +memory. + +Every segment register has a "visible" portion and an "invisible" portion, +as Figure 5-7 illustrates. The visible portions of these segment address +registers are manipulated by programs as if they were simply 16-bit +registers. The invisible portions are manipulated by the processor. + +The operations that load these registers are normal program instructions +(previously described in Chapter 3). These instructions are of two classes: + + 1. Direct load instructions; for example, MOV, POP, LDS, LSS, LGS, LFS. + These instructions explicitly reference the segment registers. + + 2. Implied load instructions; for example, far CALL and JMP. These + instructions implicitly reference the CS register, and load it with a + new value. + +Using these instructions, a program loads the visible part of the segment +register with a 16-bit selector. The processor automatically fetches the +base address, limit, type, and other information from a descriptor table and +loads them into the invisible part of the segment register. + +Because most instructions refer to data in segments whose selectors have +already been loaded into segment registers, the processor can add the +segment-relative offset supplied by the instruction to the segment base +address with no additional overhead. + + +5.2 Page Translation + +In the second phase of address transformation, the 80386 transforms a +linear address into a physical address. This phase of address transformation +implements the basic features needed for page-oriented virtual-memory +systems and page-level protection. + +The page-translation step is optional. Page translation is in effect only +when the PG bit of CR0 is set. This bit is typically set by the operating +system during software initialization. The PG bit must be set if the +operating system is to implement multiple virtual 8086 tasks, page-oriented +protection, or page-oriented virtual memory. + + +5.2.1 Page Frame + +A page frame is a 4K-byte unit of contiguous addresses of physical memory. +Pages begin onbyte boundaries and are fixed in size. + + +5.2.2 Linear Address + +A linear address refers indirectly to a physical address by specifying a +page table, a page within that table, and an offset within that page. Figure +5-8 shows the format of a linear address. + +Figure 5-9 shows how the processor converts the DIR, PAGE, and OFFSET +fields of a linear address into the physical address by consulting two +levels of page tables. The addressing mechanism uses the DIR field as an +index into a page directory, uses the PAGE field as an index into the page +table determined by the page directory, and uses the OFFSET field to address +a byte within the page determined by the page table. + + +Figure 5-8. Format of a Linear Address + + 31 22 21 12 11 0 + ͻ + + DIR PAGE OFFSET + + ͼ + + +Figure 5-9. Page Translation + + PAGE FRAME + ͻ ͻ + DIR PAGE OFFSET + ͼ + +  PHYSICAL + ADDRESS + PAGE DIRECTORY PAGE TABLE + ͻ ͻ + ͼ + ͹  +  PG TBL ENTRY + ͹ ͹ +  DIR ENTRY Ŀ + ͹ + + ͼ ͼ +   +ͻ + CR3 +ͼ + + +5.2.3 Page Tables + +A page table is simply an array of 32-bit page specifiers. A page table is +itself a page, and therefore contains 4 Kilobytes of memory or at most 1K +32-bit entries. + +Two levels of tables are used to address a page of memory. At the higher +level is a page directory. The page directory addresses up to 1K page tables +of the second level. A page table of the second level addresses up to 1K +pages. All the tables addressed by one page directory, therefore, can +address 1M pages (2^(20)). Because each page contains 4K bytes 2^(12) +bytes), the tables of one page directory can span the entire physical +address space of the 80386 (2^(20) times 2^(12) = 2^(32)). + +The physical address of the current page directory is stored in the CPU +register CR3, also called the page directory base register (PDBR). Memory +management software has the option of using one page directory for all +tasks, one page directory for each task, or some combination of the two. +Refer to Chapter 10 for information on initialization of CR3. Refer to +Chapter 7 to see how CR3 can change for each task. + + +5.2.4 Page-Table Entries + +Entries in either level of page tables have the same format. Figure 5-10 +illustrates this format. + + +5.2.4.1 Page Frame Address + +The page frame address specifies the physical starting address of a page. +Because pages are located on 4K boundaries, the low-order 12 bits are always +zero. In a page directory, the page frame address is the address of a page +table. In a second-level page table, the page frame address is the address +of the page frame that contains the desired memory operand. + + +5.2.4.2 Present Bit + +The Present bit indicates whether a page table entry can be used in address +translation. P=1 indicates that the entry can be used. + +When P=0 in either level of page tables, the entry is not valid for address +translation, and the rest of the entry is available for software use; none +of the other bits in the entry is tested by the hardware. Figure 5-11 +illustrates the format of a page-table entry when P=0. + +If P=0 in either level of page tables when an attempt is made to use a +page-table entry for address translation, the processor signals a page +exception. In software systems that support paged virtual memory, the +page-not-present exception handler can bring the required page into physical +memory. The instruction that caused the exception can then be reexecuted. +Refer to Chapter 9 for more information on exception handlers. + +Note that there is no present bit for the page directory itself. The page +directory may be not-present while the associated task is suspended, but the +operating system must ensure that the page directory indicated by the CR3 +image in the TSS is present in physical memory before the task is +dispatched. Refer to Chapter 7 for an explanation of the TSS and task +dispatching. + + +Figure 5-10. Format of a Page Table Entry + + 31 12 11 0 + ͻ + UR + PAGE FRAME ADDRESS 31..12 AVAIL 0 0DA0 0//P + SW + ͼ + + P - PRESENT + R/W - READ/WRITE + U/S - USER/SUPERVISOR + D - DIRTY + AVAIL - AVAILABLE FOR SYSTEMS PROGRAMMER USE + + NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. + + +Figure 5-11. Invalid Page Table Entry + + 31 1 0 + ͻ + + AVAILABLE 0 + + ͼ + + +5.2.4.3 Accessed and Dirty Bits + +These bits provide data about page usage in both levels of the page tables. +With the exception of the dirty bit in a page directory entry, these bits +are set by the hardware; however, the processor does not clear any of these +bits. + +The processor sets the corresponding accessed bits in both levels of page +tables to one before a read or write operation to a page. + +The processor sets the dirty bit in the second-level page table to one +before a write to an address covered by that page table entry. The dirty bit +in directory entries is undefined. + +An operating system that supports paged virtual memory can use these bits +to determine what pages to eliminate from physical memory when the demand +for memory exceeds the physical memory available. The operating system is +responsible for testing and clearing these bits. + +Refer to Chapter 11 for how the 80386 coordinates updates to the accessed +and dirty bits in multiprocessor systems. + + +5.2.4.4 Read/Write and User/Supervisor Bits + +These bits are not used for address translation, but are used for +page-level protection, which the processor performs at the same time as +address translation. Refer to Chapter 6 where protection is discussed in +detail. + + +5.2.5 Page Translation Cache + +For greatest efficiency in address translation, the processor stores the +most recently used page-table data in an on-chip cache. Only if the +necessary paging information is not in the cache must both levels of page +tables be referenced. + +The existence of the page-translation cache is invisible to applications +programmers but not to systems programmers; operating-system programmers +must flush the cache whenever the page tables are changed. The +page-translation cache can be flushed by either of two methods: + + 1. By reloading CR3 with a MOV instruction; for example: + + MOV CR3, EAX + + 2. By performing a task switch to a TSS that has a different CR3 image + than the current TSS. (Refer to Chapter 7 for more information on + task switching.) + + +5.3 Combining Segment and Page Translation + +Figure 5-12 combines Figure 5-2 and Figure 5-9 to summarize both phases +of the transformation from a logical address to a physical address when +paging is enabled. By appropriate choice of options and parameters to both +phases, memory-management software can implement several different styles of +memory management. + + +5.3.1 "Flat" Architecture + +When the 80386 is used to execute software designed for architectures that +don't have segments, it may be expedient to effectively "turn off" the +segmentation features of the 80386. The 80386 does not have a mode that +disables segmentation, but the same effect can be achieved by initially +loading the segment registers with selectors for descriptors that encompass +the entire 32-bit linear address space. Once loaded, the segment registers +don't need to be changed. The 32-bit offsets used by 80386 instructions are +adequate to address the entire linear-address space. + + +5.3.2 Segments Spanning Several Pages + +The architecture of the 80386 permits segments to be larger or smaller than +the size of a page (4 Kilobytes). For example, suppose a segment is used to +address and protect a large data structure that spans 132 Kilobytes. In a +software system that supports paged virtual memory, it is not necessary for +the entire structure to be in physical memory at once. The structure is +divided into 33 pages, any number of which may not be present. The +applications programmer does not need to be aware that the virtual memory +subsystem is paging the structure in this manner. + + +Figure 5-12. 80306 Addressing Machanism + + 16 0 32 0 + ͻ LOGICAL + SELECTOR OFFSET ADDRESS + ͼ +  + DESCRIPTOR TABLE + ͻ + + + + + ͹ + SEGMENT ͻ +  DESCRIPTOR  +  + ͹ ͼ + + ͼ +  PAGE FRAME + LINEAR ͻ ͻ + ADDRESS DIR PAGE OFFSET + ͼ + +  PHYSICAL + ADDRESS + PAGE DIRECTORY PAGE TABLE + ͻ ͻ + + ͼ + ͹  +  PG TBL ENTRY + ͹ ͹ +  DIR ENTRY Ŀ + ͹ + + ͼ ͼ +   +ͻ + CR3 +ͼ + + +5.3.3 Pages Spanning Several Segments + +On the other hand, segments may be smaller than the size of a page. For +example, consider a small data structure such as a semaphore. Because of the +protection and sharing provided by segments (refer to Chapter 6), it may be +useful to create a separate segment for each semaphore. But, because a +system may need many semaphores, it is not efficient to allocate a page for +each. Therefore, it may be useful to cluster many related segments within a +page. + + +5.3.4 Non-Aligned Page and Segment Boundaries + +The architecture of the 80386 does not enforce any correspondence between +the boundaries of pages and segments. It is perfectly permissible for a page +to contain the end of one segment and the beginning of another. Likewise, a +segment may contain the end of one page and the beginning of another. + + +5.3.5 Aligned Page and Segment Boundaries + +Memory-management software may be simpler, however, if it enforces some +correspondence between page and segment boundaries. For example, if segments +are allocated only in units of one page, the logic for segment and page +allocation can be combined. There is no need for logic to account for +partially used pages. + + +5.3.6 Page-Table per Segment + +An approach to space management that provides even further simplification +of space-management software is to maintain a one-to-one correspondence +between segment descriptors and page-directory entries, as Figure 5-13 +illustrates. Each descriptor has a base address in which the low-order 22 +bits are zero; in other words, the base address is mapped by the first entry +of a page table. A segment may have any limit from 1 to 4 megabytes. +Depending on the limit, the segment is contained in from 1 to 1K page +frames. A task is thus limited to 1K segments (a sufficient number for many +applications), each containing up to 4 Mbytes. The descriptor, the +corresponding page-directory entry, and the corresponding page table can be +allocated and deallocated simultaneously. + + +Figure 5-13. Descriptor per Page Table + + PAGE FRAMES + ͻ + LDT PAGE DIRECTORY PAGE TABLES + ͻ ͻ ͻ + ͼ + ͹ ͹ ͹ + PTE ͻ + ͹ ͹ ͹ + PTE Ŀ + ͹ ͹ ͹ ͼ + PTE Ŀ + ͹ ͹ ͼ ͻ + DESCRIPTOR PDE + ͹ ͹ + DESCRIPTOR PDE Ŀ ͼ + ͹ ͹ ͻ + ͻ + ͹ ͹ ͹ + + ͹ ͹ ͹ ͼ + PTE + ͹ ͹ ͹ ͻ + PTE Ŀ + ͼ ͼ ͼ + LDT PAGE DIRECTORY PAGE TABLES ͼ + PAGE FRAMES + + +Chapter 6 Protection + + + +6.1 Why Protection? + +The purpose of the protection features of the 80386 is to help detect and +identify bugs. The 80386 supports sophisticated applications that may +consist of hundreds or thousands of program modules. In such applications, +the question is how bugs can be found and eliminated as quickly as possible +and how their damage can be tightly confined. To help debug applications +faster and make them more robust in production, the 80386 contains +mechanisms to verify memory accesses and instruction execution for +conformance to protection criteria. These mechanisms may be used or ignored, +according to system design objectives. + + +6.2 Overview of 80386 Protection Mechanisms + +Protection in the 80386 has five aspects: + + 1. Type checking + 2. Limit checking + 3. Restriction of addressable domain + 4. Restriction of procedure entry points + 5. Restriction of instruction set + +The protection hardware of the 80386 is an integral part of the memory +management hardware. Protection applies both to segment translation and to +page translation. + +Each reference to memory is checked by the hardware to verify that it +satisfies the protection criteria. All these checks are made before the +memory cycle is started; any violation prevents that cycle from starting and +results in an exception. Since the checks are performed concurrently with +address formation, there is no performance penalty. + +Invalid attempts to access memory result in an exception. Refer to +Chapter 9 for an explanation of the exception mechanism. The present +chapter defines the protection violations that lead to exceptions. + +The concept of "privilege" is central to several aspects of protection +(numbers 3, 4, and 5 in the preceeding list). Applied to procedures, +privilege is the degree to which the procedure can be trusted not to make a +mistake that might affect other procedures or data. Applied to data, +privilege is the degree of protection that a data structure should have +from less trusted procedures. + +The concept of privilege applies both to segment protection and to page +protection. + + +6.3 Segment-Level Protection + +All five aspects of protection apply to segment translation: + + 1. Type checking + 2. Limit checking + 3. Restriction of addressable domain + 4. Restriction of procedure entry points + 5. Restriction of instruction set + +The segment is the unit of protection, and segment descriptors store +protection parameters. Protection checks are performed automatically by the +CPU when the selector of a segment descriptor is loaded into a segment +register and with every segment access. Segment registers hold the +protection parameters of the currently addressable segments. + + +6.3.1 Descriptors Store Protection Parameters + +Figure 6-1 highlights the protection-related fields of segment descriptors. + +The protection parameters are placed in the descriptor by systems software +at the time a descriptor is created. In general, applications programmers do +not need to be concerned about protection parameters. + +When a program loads a selector into a segment register, the processor +loads not only the base address of the segment but also protection +information. Each segment register has bits in the invisible portion for +storing base, limit, type, and privilege level; therefore, subsequent +protection checks on the same segment do not consume additional clock +cycles. + + +Figure 6-1. Protection Fields of Segment Descriptors + + DATA SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24GB0V 19..16 P DPL BASE 23..16 4 + L 10EWA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + EXECUTABLE SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24GD0V 19..16 P DPL BASE 23..16 4 + L 10CRA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + SYSTEM SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT + BASE 31..24GX0V 19..16 P DPL 0 TYPE BASE 23..16 4 + L + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + + A - ACCESSED E - EXPAND-DOWN + AVL - AVAILABLE FOR PROGRAMMERS USE G - GRANULARITY + B - BIG P - SEGMENT PRESENT + C - CONFORMING R - READABLE + D - DEFAULT W - WRITABLE + DPL - DESCRIPTOR PRIVILEGE LEVEL + + +6.3.1.1 Type Checking + +The TYPE field of a descriptor has two functions: + + 1. It distinguishes among different descriptor formats. + 2. It specifies the intended usage of a segment. + +Besides the descriptors for data and executable segments commonly used by +applications programs, the 80386 has descriptors for special segments used +by the operating system and for gates. Table 6-1 lists all the types defined +for system segments and gates. Note that not all descriptors define +segments; gate descriptors have a different purpose that is discussed later +in this chapter. + +The type fields of data and executable segment descriptors include bits +which further define the purpose of the segment (refer to Figure 6-1): + + The writable bit in a data-segment descriptor specifies whether + instructions can write into the segment. + + The readable bit in an executable-segment descriptor specifies + whether instructions are allowed to read from the segment (for example, + to access constants that are stored with instructions). A readable, + executable segment may be read in two ways: + + 1. Via the CS register, by using a CS override prefix. + + 2. By loading a selector of the descriptor into a data-segment register + (DS, ES, FS,or GS). + +Type checking can be used to detect programming errors that would attempt +to use segments in ways not intended by the programmer. The processor +examines type information on two kinds of occasions: + + 1. When a selector of a descriptor is loaded into a segment register. + Certain segment registers can contain only certain descriptor types; + for example: + + The CS register can be loaded only with a selector of an executable + segment. + + Selectors of executable segments that are not readable cannot be + loaded into data-segment registers. + + Only selectors of writable data segments can be loaded into SS. + + 2. When an instruction refers (implicitly or explicitly) to a segment + register. Certain segments can be used by instructions only in certain + predefined ways; for example: + + No instruction may write into an executable segment. + + No instruction may write into a data segment if the writable bit is + not set. + + No instruction may read an executable segment unless the readable bit + is set. + + +Table 6-1. System and Gate Descriptor Types + +Code Type of Segment or Gate + + 0 -reserved + 1 Available 286 TSS + 2 LDT + 3 Busy 286 TSS + 4 Call Gate + 5 Task Gate + 6 286 Interrupt Gate + 7 286 Trap Gate + 8 -reserved + 9 Available 386 TSS + A -reserved + B Busy 386 TSS + C 386 Call Gate + D -reserved + E 386 Interrupt Gate + F 386 Trap Gate + + +6.3.1.2 Limit Checking + +The limit field of a segment descriptor is used by the processor to prevent +programs from addressing outside the segment. The processor's interpretation +of the limit depends on the setting of the G (granularity) bit. For data +segments, the processor's interpretation of the limit depends also on the +E-bit (expansion-direction bit) and the B-bit (big bit) (refer to Table +6-2). + +When G=0, the actual limit is the value of the 20-bit limit field as it +appears in the descriptor. In this case, the limit may range from 0 to +0FFFFFH (2^(20) - 1 or 1 megabyte). When G=1, the processor appends 12 +low-order one-bits to the value in the limit field. In this case the actual +limit may range from 0FFFH (2^(12) - 1 or 4 kilobytes) to 0FFFFFFFFH(2^(32) +- 1 or 4 gigabytes). + +For all types of segments except expand-down data segments, the value of +the limit is one less than the size (expressed in bytes) of the segment. The +processor causes a general-protection exception in any of these cases: + + Attempt to access a memory byte at an address > limit. + Attempt to access a memory word at an address limit. + Attempt to access a memory doubleword at an address (limit-2). + +For expand-down data segments, the limit has the same function but is +interpreted differently. In these cases the range of valid addresses is from +limit + 1 to either 64K or 2^(32) - 1 (4 Gbytes) depending on the B-bit. An +expand-down segment has maximum size when the limit is zero. + +The expand-down feature makes it possible to expand the size of a stack by +copying it to a larger segment without needing also to update intrastack +pointers. + +The limit field of descriptors for descriptor tables is used by the +processor to prevent programs from selecting a table entry outside the +descriptor table. The limit of a descriptor table identifies the last valid +byte of the last descriptor in the table. Since each descriptor is eight +bytes long, the limit value is N * 8 - 1 for a table that can contain up to +N descriptors. + +Limit checking catches programming errors such as runaway subscripts and +invalid pointer calculations. Such errors are detected when they occur, so +that identification of the cause is easier. Without limit checking, such +errors could corrupt other modules; the existence of such errors would not +be discovered until later, when the corrupted module behaves incorrectly, +and when identification of the cause is difficult. + + +Table 6-2. Useful Combinations of E, G, and B Bits + + +Case: 1 2 3 4 + +Expansion Direction U U D D +G-bit 0 1 0 1 +B-bit X X 0 1 + +Lower bound is: + 0 X X + LIMIT+1 X +shl(LIMIT,12,1)+1 X + +Upper bound is: + LIMIT X + shl(LIMIT,12,1) X + 64K-1 X + 4G-1 X + +Max seg size is: + 64K X + 64K-1 X + 4G-4K X + 4G X + +Min seg size is: + 0 X X + 4K X X + +shl (X, 12, 1) = shift X left by 12 bits inserting one-bits on the right + + +6.3.1.3 Privilege Levels + +The concept of privilege is implemented by assigning a value from zero to +three to key objects recognized by the processor. This value is called the +privilege level. The value zero represents the greatest privilege, the +value three represents the least privilege. The following +processor-recognized objects contain privilege levels: + + Descriptors contain a field called the descriptor privilege level + (DPL). + + Selectors contain a field called the requestor's privilege level + (RPL). The RPL is intended to represent the privilege level of + the procedure that originates a selector. + + An internal processor register records the current privilege level + (CPL). Normally the CPL is equal to the DPL of the segment that + the processor is currently executing. CPL changes as control is + transferred to segments with differing DPLs. + +The processor automatically evaluates the right of a procedure to access +another segment by comparing the CPL to one or more other privilege levels. +The evaluation is performed at the time the selector of a descriptor is +loaded into a segment register. The criteria used for evaluating access to +data differs from that for evaluating transfers of control to executable +segments; therefore, the two types of access are considered separately in +the following sections. + +Figure 6-2 shows how these levels of privilege can be interpreted as rings +of protection. The center is for the segments containing the most critical +software, usually the kernel of the operating system. Outer rings are for +the segments of less critical software. + +It is not necessary to use all four privilege levels. Existing software +that was designed to use only one or two levels of privilege can simply +ignore the other levels offered by the 80386. A one-level system should use +privilege level zero; a two-level system should use privilege levels zero +and three. + + +Figure 6-2. Levels of Privilege + + TASK C + Ŀ + ͻ + APPLICATIONS + ͻ + CUSTOM EXTENSIONS + ͻ + SYSTEM SERVICES + ͻ + KERNAL + Ķ͵ + LEVELLEVELLEVELLEVEL + 0 1 2 3 + ͼ + + ͼ + + ͼ + + TASK B ͼ TASK A + + + +6.3.2 Restricting Access to Data + +To address operands in memory, an 80386 program must load the selector of a +data segment into a data-segment register (DS, ES, FS, GS, SS). The +processor automatically evaluates access to a data segment by comparing +privilege levels. The evaluation is performed at the time a selector for the +descriptor of the target segment is loaded into the data-segment register. +As Figure 6-3 shows, three different privilege levels enter into this type +of privilege check: + + 1. The CPL (current privilege level). + + 2. The RPL (requestor's privilege level) of the selector used to specify + the target segment. + + 3. The DPL of the descriptor of the target segment. + +Instructions may load a data-segment register (and subsequently use the +target segment) only if the DPL of the target segment is numerically greater +than or equal to the maximum of the CPL and the selector's RPL. In other +words, a procedure can only access data that is at the same or less +privileged level. + +The addressable domain of a task varies as CPL changes. When CPL is zero, +data segments at all privilege levels are accessible; when CPL is one, only +data segments at privilege levels one through three are accessible; when CPL +is three, only data segments at privilege level three are accessible. This +property of the 80386 can be used, for example, to prevent applications +procedures from reading or changing tables of the operating system. + + +Figure 6-3. Privilege Check for Data Access + + 16-BIT VISIBLE + SELECTOR INVISIBLE DESCRIPTOR + ͻ + CS CPL + ͼ + + TARGET SEGMENT SELECTOR ͻ + ͻ  PRIVILEGE + INDEX RPL CHECK + ͼ  BY CPU + ͼ + DATA SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24 GB0V P DPL BASE 23..16 4 + L 19..16 10EWA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + + CPL - CURRENT PRIVILEGE LEVEL + RPL - REQUESTOR'S PRIVILEGE LEVEL + DPL - DESCRIPTOR PRIVILEGE LEVEL + + +6.3.2.1 Accessing Data in Code Segments + +Less common than the use of data segments is the use of code segments to +store data. Code segments may legitimately hold constants; it is not +possible to write to a segment described as a code segment. The following +methods of accessing data in code segments are possible: + + 1. Load a data-segment register with a selector of a nonconforming, + readable, executable segment. + + 2. Load a data-segment register with a selector of a conforming, + readable, executable segment. + + 3. Use a CS override prefix to read a readable, executable segment whose + selector is already loaded in the CS register. + +The same rules as for access to data segments apply to case 1. Case 2 is +always valid because the privilege level of a segment whose conforming bit +is set is effectively the same as CPL regardless of its DPL. Case 3 always +valid because the DPL of the code segment in CS is, by definition, equal to +CPL. + + +6.3.3 Restricting Control Transfers + +With the 80386, control transfers are accomplished by the instructions JMP, +CALL, RET, INT, and IRET, as well as by the exception and interrupt +mechanisms. Exceptions and interrupts are special cases that Chapter 9 +covers. This chapter discusses only JMP, CALL, and RET instructions. + +The "near" forms of JMP, CALL, and RET transfer within the current code +segment, and therefore are subject only to limit checking. The processor +ensures that the destination of the JMP, CALL, or RET instruction does not +exceed the limit of the current executable segment. This limit is cached in +the CS register; therefore, protection checks for near transfers require no +extra clock cycles. + +The operands of the "far" forms of JMP and CALL refer to other segments; +therefore, the processor performs privilege checking. There are two ways a +JMP or CALL can refer to another segment: + + 1. The operand selects the descriptor of another executable segment. + + 2. The operand selects a call gate descriptor. This gated form of + transfer is discussed in a later section on call gates. + +As Figure 6-4 shows, two different privilege levels enter into a privilege +check for a control transfer that does not use a call gate: + + 1. The CPL (current privilege level). + 2. The DPL of the descriptor of the target segment. + +Normally the CPL is equal to the DPL of the segment that the processor is +currently executing. CPL may, however, be greater than DPL if the conforming +bit is set in the descriptor of the current executable segment. The +processor keeps a record of the CPL cached in the CS register; this value +can be different from the DPL in the descriptor of the code segment. + +The processor permits a JMP or CALL directly to another segment only if one +of the following privilege rules is satisfied: + + DPL of the target is equal to CPL. + + The conforming bit of the target code-segment descriptor is set, and + the DPL of the target is less than or equal to CPL. + +An executable segment whose descriptor has the conforming bit set is called +a conforming segment. The conforming-segment mechanism permits sharing of +procedures that may be called from various privilege levels but should +execute at the privilege level of the calling procedure. Examples of such +procedures include math libraries and some exception handlers. When control +is transferred to a conforming segment, the CPL does not change. This is +the only case when CPL may be unequal to the DPL of the current executable +segment. + +Most code segments are not conforming. The basic rules of privilege above +mean that, for nonconforming segments, control can be transferred without a +gate only to executable segments at the same level of privilege. There is a +need, however, to transfer control to (numerically) smaller privilege +levels; this need is met by the CALL instruction when used with call-gate +descriptors, which are explained in the next section. The JMP instruction +may never transfer control to a nonconforming segment whose DPL does not +equal CPL. + + +Figure 6-4. Privilege Check for Control Transfer without Gate + + 16-BIT VISIBLE + SELECTOR INVISIBLE PART + ͻ + CPL CS + ͼ + + ͻ +  PRIVILEGE +  CHECK +  BY CPU + CODE-SEGMENT DESCRIPTOR ͼ + + 31 23 15 7 0 + ͻ + A LIMIT + BASE 31..24 GD0V P DPL BASE 23..16 4 + L 19..16 11CRA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + CPL - CURRENT PRIVILEGE LEVEL + DPL - DESCRIPTOR PRIVILEGE LEVEL + C - CONFORMING BIT + + +6.3.4 Gate Descriptors Guard Procedure Entry Points + +To provide protection for control transfers among executable segments +at different privilege levels, the 80386 uses gate descriptors. There are +four kinds of gate descriptors: + + Call gates + Trap gates + Interrupt gates + Task gates + +This chapter is concerned only with call gates. Task gates are used for +task switching, and therefore are discussed in Chapter 7. Chapter 9 +explains how trap gates and interrupt gates are used by exceptions and +interrupts. Figure 6-5 illustrates the format of a call gate. A call gate +descriptor may reside in the GDT or in an LDT, but not in the IDT. + +A call gate has two primary functions: + + 1. To define an entry point of a procedure. + 2. To specify the privilege level of the entry point. + +Call gate descriptors are used by call and jump instructions in the same +manner as code segment descriptors. When the hardware recognizes that the +destination selector refers to a gate descriptor, the operation of the +instruction is expanded as determined by the contents of the call gate. + +The selector and offset fields of a gate form a pointer to the entry point +of a procedure. A call gate guarantees that all transitions to another +segment go to a valid entry point, rather than possibly into the middle of a +procedure (or worse, into the middle of an instruction). The far pointer +operand of the control transfer instruction does not point to the segment +and offset of the target instruction; rather, the selector part of the +pointer selects a gate, and the offset is not used. Figure 6-6 illustrates +this style of addressing. + +As Figure 6-7 shows, four different privilege levels are used to check the +validity of a control transfer via a call gate: + + 1. The CPL (current privilege level). + + 2. The RPL (requestor's privilege level) of the selector used to specify + the call gate. + + 3. The DPL of the gate descriptor. + + 4. The DPL of the descriptor of the target executable segment. + +The DPL field of the gate descriptor determines what privilege levels can +use the gate. One code segment can have several procedures that are intended +for use by different privilege levels. For example, an operating system may +have some services that are intended to be used by applications, whereas +others may be intended only for use by other systems software. + +Gates can be used for control transfers to numerically smaller privilege +levels or to the same privilege level (though they are not necessary for +transfers to the same level). Only CALL instructions can use gates to +transfer to smaller privilege levels. A gate may be used by a JMP +instruction only to transfer to an executable segment with the same +privilege level or to a conforming segment. + +For a JMP instruction to a nonconforming segment, both of the following +privilege rules must be satisfied; otherwise, a general protection exception +results. + + MAX (CPL,RPL) gate DPL + target segment DPL = CPL + +For a CALL instruction (or for a JMP instruction to a conforming segment), +both of the following privilege rules must be satisfied; otherwise, a +general protection exception results. + + MAX (CPL,RPL) gate DPL + target segment DPL CPL + + +Figure 6-5. Format of 80386 Call Gate + + 31 23 15 7 0 + ͻ + TYPE DWORD + OFFSET 31..16 P DPL 0 0 0 4 + 0 1 1 0 0 COUNT + Ķ + + SELECTOR OFFSET 15..0 0 + + ͼ + + +Figure 6-6. Indirect Transfer via Call Gate + + OPCODE OFFSET SELECTOR + ͻ + CALL (NOT USED) INDEX RPL + ͼ + + DESCRIPTOR TABLE + ͻ + + Ķ + + ͼ +   +   +   + ͻ + GATE OFFSET DPL COUNT  EXECUTABLE + DESCRIPTOR Ķ SEGMENT + Ķ SELECTOR OFFSET Ŀ ͻ + ͹ + + Ķ + + ͹ +  PROCEDURE + Ķ + +  ͹ + EXECUTABLE BASE DPL BASE + SEGMENT Ķ ͼ + DESCRIPTOR BASE + ͼ +   +   +   + ͻ + + Ķ + + ͼ + + +Figure 6-7. Privilege Check via Call Gate + + 16-BIT VISIBLE + SELECTOR INVISIBLE DESCRIPTOR + ͻ + CS CPL + ͼ + + TARGET SELECTOR ͻ + ͻ  PRIVILEGE + INDEX RPL CHECK + ͼ  BY +  CPU + ͼ + + GATE DESCRIPTOR  + ͻ + OFFSET DPL COUNT + ͹ + SELECTOR OFFSET + ͼ + + + ͻ + EXECUTABLE BASE LIMIT DPL BASE + SEGMENT ͹ + DESCRIPTOR BASE LIMIT + ͼ + + CPL - CURRENT PRIVILEGE LEVEL + RPL - REQUESTOR'S PRIVILEGE LEVEL + DPL - DESCRIPTOR PRIVILEGE LEVEL + + +6.3.4.1 Stack Switching + +If the destination code segment of the call gate is at a different +privilege level than the CPL, an interlevel transfer is being requested. + +To maintain system integrity, each privilege level has a separate stack. +These stacks assure sufficient stack space to process calls from less +privileged levels. Without them, a trusted procedure would not work +correctly if the calling procedure did not provide sufficient space on the +caller's stack. + +The processor locates these stacks via the task state segment (see Figure +6-8). Each task has a separate TSS, thereby permitting tasks to have +separate stacks. Systems software is responsible for creating TSSs and +placing correct stack pointers in them. The initial stack pointers in the +TSS are strictly read-only values. The processor never changes them during +the course of execution. + +When a call gate is used to change privilege levels, a new stack is +selected by loading a pointer value from the Task State Segment (TSS). The +processor uses the DPL of the target code segment (the new CPL) to index the +initial stack pointer for PL 0, PL 1, or PL 2. + +The DPL of the new stack data segment must equal the new CPL; if it does +not, a stack exception occurs. It is the responsibility of systems software +to create stacks and stack-segment descriptors for all privilege levels that +are used. Each stack must contain enough space to hold the old SS:ESP, the +return address, and all parameters and local variables that may be required +to process a call. + +As with intralevel calls, parameters for the subroutine are placed on the +stack. To make privilege transitions transparent to the called procedure, +the processor copies the parameters to the new stack. The count field of a +call gate tells the processor how many doublewords (up to 31) to copy from +the caller's stack to the new stack. If the count is zero, no parameters are +copied. + +The processor performs the following stack-related steps in executing an +interlevel CALL. + + 1. The new stack is checked to assure that it is large enough to hold + the parameters and linkages; if it is not, a stack fault occurs with + an error code of 0. + + 2. The old value of the stack registers SS:ESP is pushed onto the new + stack as two doublewords. + + 3. The parameters are copied. + + 4. A pointer to the instruction after the CALL instruction (the former + value of CS:EIP) is pushed onto the new stack. The final value of + SS:ESP points to this return pointer on the new stack. + +Figure 6-9 illustrates the stack contents after a successful interlevel +call. + +The TSS does not have a stack pointer for a privilege level 3 stack, +because privilege level 3 cannot be called by any procedure at any other +privilege level. + +Procedures that may be called from another privilege level and that require +more than the 31 doublewords for parameters must use the saved SS:ESP link +to access all parameters beyond the last doubleword copied. + +A call via a call gate does not check the values of the words copied onto +the new stack. The called procedure should check each parameter for +validity. A later section discusses how the ARPL, VERR, VERW, LSL, and LAR +instructions can be used to check pointer values. + + +Figure 6-8. Initial Stack Pointers of TSS + + 31 23 15 7 0 + ͻ64 +   +   +   + + ͹ + EFLAGS 24 + ͹ + INSTRUCTION POINTER (EIP) 20 + ͹ + CR3 (PDBR) 1C + ͹ Ŀ + 00000000 00000000 SS2 1018 + ͹ + ESP2 14 + ͹ + 00000000 00000000 SS1 0110 INITIAL + ͹ STACK + ESP1 0C POINTERS + ͹ + 00000000 00000000 SS0 008 + ͹ + ESP0 4 + ͹ + 00000000 00000000 TSS BACK LINK 0 + ͼ + + +Figure 6-9. Stack Contents after an Interlevel Call + + 31 0 SS:ESP + ͻFROM TSS + 31 0 OLD SS + ͻ ͹ + D O OLD ESP + I F ͹ + R PARM 3 + E E ͹ + C X PARM 2 + T P ͹ ͹ + I A PARM 3 PARM 1 + O N ͹ ͹ + N S PARM 2 OLD CS NEW + I ͹ OLD ͹ SS:ESP + O PARM 1 SS:ESP OLD EIP + N ͹ ͹ + +  + ͼ ͼ + OLD STACK NEW STACK + + +6.3.4.2 Returning from a Procedure + +The "near" forms of the RET instruction transfer control within the current +code segment and therefore are subject only to limit checking. The offset of +the instruction following the corresponding CALL, is popped from the stack. +The processor ensures that this offset does not exceed the limit of the +current executable segment. + +The "far" form of the RET instruction pops the return pointer that was +pushed onto the stack by a prior far CALL instruction. Under normal +conditions, the return pointer is valid, because of its relation to the +prior CALL or INT. Nevertheless, the processor performs privilege checking +because of the possibility that the current procedure altered the pointer or +failed to properly maintain the stack. The RPL of the CS selector popped +off the stack by the return instruction identifies the privilege level of +the calling procedure. + +An intersegment return instruction can change privilege levels, but only +toward procedures of lesser privilege. When the RET instruction encounters a +saved CS value whose RPL is numerically greater than the CPL, an interlevel +return occurs. Such a return follows these steps: + + 1. The checks shown in Table 6-3 are made, and CS:EIP and SS:ESP are + loaded with their former values that were saved on the stack. + + 2. The old SS:ESP (from the top of the current stack) value is adjusted + by the number of bytes indicated in the RET instruction. The resulting + ESP value is not compared to the limit of the stack segment. If ESP is + beyond the limit, that fact is not recognized until the next stack + operation. (The SS:ESP value of the returning procedure is not + preserved; normally, this value is the same as that contained in the + TSS.) + + 3. The contents of the DS, ES, FS, and GS segment registers are checked. + If any of these registers refer to segments whose DPL is greater than + the new CPL (excluding conforming code segments), the segment register + is loaded with the null selector (INDEX = 0, TI = 0). The RET + instruction itself does not signal exceptions in these cases; + however, any subsequent memory reference that attempts to use a + segment register that contains the null selector will cause a general + protection exception. This prevents less privileged code from + accessing more privileged segments using selectors left in the + segment registers by the more privileged procedure. + + +6.3.5 Some Instructions are Reserved for Operating System + +Instructions that have the power to affect the protection mechanism or to +influence general system performance can only be executed by trusted +procedures. The 80386 has two classes of such instructions: + + 1. Privileged instructions those used for system control. + + 2. Sensitive instructions those used for I/O and I/O related + activities. + + +Table 6-3. Interlevel Return Checks + + +Type of Check Exception +SF Stack Fault +GP General Protection Exception +NP Segment-Not-Present Exception Error Code + +ESP is within current SS segment SF 0 +ESP + 7 is within current SS segment SF 0 +RPL of return CS is greater than CPL GP Return CS +Return CS selector is not null GP Return CS +Return CS segment is within descriptor +table limit GP Return CS +Return CS descriptor is a code segment GP Return CS +Return CS segment is present NP Return CS +DPL of return nonconforming code +segment = RPL of return CS, or DPL of +return conforming code segment RPL +of return CS GP Return CS +ESP + N + 15 is within SS segment +N Immediate Operand of RET N Instruction SF Return SS +SS selector at ESP + N + 12 is not null GP Return SS +SS selector at ESP + N + 12 is within +descriptor table limit GP Return SS +SS descriptor is writable data segment GP Return SS +SS segment is present SF Return SS +Saved SS segment DPL = RPL of saved +CS GP Return SS +Saved SS selector RPL = Saved SS +segment DPL GP Return SS + + +6.3.5.1 Privileged Instructions + +The instructions that affect system data structures can only be executed +when CPL is zero. If the CPU encounters one of these instructions when CPL +is greater than zero, it signals a general protection exception. These +instructions include: + + CLTS Clear TaskSwitched Flag + HLT Halt Processor + LGDT Load GDL Register + LIDT Load IDT Register + LLDT Load LDT Register + LMSW Load Machine Status Word + LTR Load Task Register + MOV to/from CRn Move to Control Register n + MOV to /from DRn Move to Debug Register n + MOV to/from TRn Move to Test Register n + + +6.3.5.2 Sensitive Instructions + +Instructions that deal with I/O need to be restricted but also need to be +executed by procedures executing at privilege levels other than zero. The +mechanisms for restriction of I/O operations are covered in detail in +Chapter 8, "Input/Output". + + +6.3.6 Instructions for Pointer Validation + +Pointer validation is an important part of locating programming errors. +Pointer validation is necessary for maintaining isolation between the +privilege levels. Pointer validation consists of the following steps: + + 1. Check if the supplier of the pointer is entitled to access the + segment. + + 2. Check if the segment type is appropriate to its intended use. + + 3. Check if the pointer violates the segment limit. + +Although the 80386 processor automatically performs checks 2 and 3 during +instruction execution, software must assist in performing the first check. +The unprivileged instruction ARPL is provided for this purpose. Software can +also explicitly perform steps 2 and 3 to check for potential violations +(rather than waiting for an exception). The unprivileged instructions LAR, +LSL, VERR, and VERW are provided for this purpose. + +LAR (Load Access Rights) is used to verify that a pointer refers to a +segment of the proper privilege level and type. LAR has one operanda +selector for a descriptor whose access rights are to be examined. The +descriptor must be visible at the privilege level which is the maximum of +the CPL and the selector's RPL. If the descriptor is visible, LAR obtains a +masked form of the second doubleword of the descriptor, masks this value +with 00FxFF00H, stores the result into the specified 32-bit destination +register, and sets the zero flag. (The x indicates that the corresponding +four bits of the stored value are undefined.) Once loaded, the access-rights +bits can be tested. All valid descriptor types can be tested by the LAR +instruction. If the RPL or CPL is greater than DPL, or if the selector is +outside the table limit, no access-rights value is returned, and the zero +flag is cleared. Conforming code segments may be accessed from any privilege +level. + +LSL (Load Segment Limit) allows software to test the limit of a descriptor. +If the descriptor denoted by the given selector (in memory or a register) is +visible at the CPL, LSL loads the specified 32-bit register with a 32-bit, +byte granular, unscrambled limit that is calculated from fragmented limit +fields and the G-bit of that descriptor. This can only be done for segments +(data, code, task state, and local descriptor tables); gate descriptors are +inaccessible. (Table 6-4 lists in detail which types are valid and which +are not.) Interpreting the limit is a function of the segment type. For +example, downward expandable data segments treat the limit differently than +code segments do. For both LAR and LSL, the zero flag (ZF) is set if the +loading was performed; otherwise, the ZF is cleared. + + +Table 6-4. Valid Descriptor Types for LSL + + Type Descriptor Type Valid? + Code + + 0 (invalid) NO + 1 Available 286 TSS YES + 2 LDT YES + 3 Busy 286 TSS YES + 4 286 Call Gate NO + 5 Task Gate NO + 6 286 Trap Gate NO + 7 286 Interrupt Gate NO + 8 (invalid) NO + 9 Available 386 TSS YES + A (invalid) NO + B Busy 386 TSS YES + C 386 Call Gate NO + D (invalid) NO + E 386 Trap Gate NO + F 386 Interrupt Gate NO + + +6.3.6.1 Descriptor Validation + +The 80386 has two instructions, VERR and VERW, which determine whether a +selector points to a segment that can be read or written at the current +privilege level. Neither instruction causes a protection fault if the result +is negative. + +VERR (Verify for Reading) verifies a segment for reading and loads ZF with +1 if that segment is readable from the current privilege level. VERR checks +that: + + The selector points to a descriptor within the bounds of the GDT or + LDT. + + It denotes a code or data segment descriptor. + + The segment is readable and of appropriate privilege level. + +The privilege check for data segments and nonconforming code segments is +that the DPL must be numerically greater than or equal to both the CPL and +the selector's RPL. Conforming segments are not checked for privilege level. + +VERW (Verify for Writing) provides the same capability as VERR for +verifying writability. Like the VERR instruction, VERW loads ZF if the +result of the writability check is positive. The instruction checks that the +descriptor is within bounds, is a segment descriptor, is writable, and that +its DPL is numerically greater or equal to both the CPL and the selector's +RPL. Code segments are never writable, conforming or not. + + +6.3.6.2 Pointer Integrity and RPL + +The Requestor's Privilege Level (RPL) feature can prevent inappropriate use +of pointers that could corrupt the operation of more privileged code or data +from a less privileged level. + +A common example is a file system procedure, FREAD (file_id, n_bytes, +buffer_ptr). This hypothetical procedure reads data from a file into a +buffer, overwriting whatever is there. Normally, FREAD would be available at +the user level, supplying only pointers to the file system procedures and +data located and operating at a privileged level. Normally, such a procedure +prevents user-level procedures from directly changing the file tables. +However, in the absence of a standard protocol for checking pointer +validity, a user-level procedure could supply a pointer into the file tables +in place of its buffer pointer, causing the FREAD procedure to corrupt them +unwittingly. + +Use of RPL can avoid such problems. The RPL field allows a privilege +attribute to be assigned to a selector. This privilege attribute would +normally indicate the privilege level of the code which generated the +selector. The 80386 processor automatically checks the RPL of any selector +loaded into a segment register to determine whether the RPL allows access. + +To take advantage of the processor's checking of RPL, the called procedure +need only ensure that all selectors passed to it have an RPL at least as +high (numerically) as the original caller's CPL. This action guarantees that +selectors are not more trusted than their supplier. If one of the selectors +is used to access a segment that the caller would not be able to access +directly, i.e., the RPL is numerically greater than the DPL, then a +protection fault will result when that selector is loaded into a segment +register. + +ARPL (Adjust Requestor's Privilege Level) adjusts the RPL field of a +selector to become the larger of its original value and the value of the RPL +field in a specified register. The latter is normally loaded from the image +of the caller's CS register which is on the stack. If the adjustment changes +the selector's RPL, ZF (the zero flag) is set; otherwise, ZF is cleared. + + +6.4 Page-Level Protection + +Two kinds of protection are related to pages: + + 1. Restriction of addressable domain. + 2. Type checking. + + +6.4.1 Page-Table Entries Hold Protection Parameters + +Figure 6-10 highlights the fields of PDEs and PTEs that control access to +pages. + + +Figure 6-10. Protection Fields of Page Table Entries + + 31 12 11 7 0 + ͻ + UR + PAGE FRAME ADDRESS 31..12AVAIL00DA00//P + SW + ͼ + R/W - READ/WRITE + U/S - USER/SUPERVISOR + + +6.4.1.1 Restricting Addressable Domain + +The concept of privilege for pages is implemented by assigning each page to +one of two levels: + + 1. Supervisor level (U/S=0) for the operating system and other systems + software and related data. + + 2. User level (U/S=1) for applications procedures and data. + +The current level (U or S) is related to CPL. If CPL is 0, 1, or 2, the +processor is executing at supervisor level. If CPL is 3, the processor is +executing at user level. + +When the processor is executing at supervisor level, all pages are +addressable, but, when the processor is executing at user level, only pages +that belong to the user level are addressable. + + +6.4.1.2 Type Checking + +At the level of page addressing, two types are defined: + + 1. Read-only access (R/W=0) + 2. Read/write access (R/W=1) + +When the processor is executing at supervisor level, all pages are both +readable and writable. When the processor is executing at user level, only +pages that belong to user level and are marked for read/write access are +writable; pages that belong to supervisor level are neither readable nor +writable from user level. + + +6.4.2 Combining Protection of Both Levels of Page Tables + +For any one page, the protection attributes of its page directory entry may +differ from those of its page table entry. The 80386 computes the effective +protection attributes for a page by examining the protection attributes in +both the directory and the page table. Table 6-5 shows the effective +protection provided by the possible combinations of protection attributes. + + +6.4.3 Overrides to Page Protection + +Certain accesses are checked as if they are privilege-level 0 references, +even if CPL = 3: + + LDT, GDT, TSS, IDT references. + Access to inner stack during ring-crossing CALL/INT. + + +6.5 Combining Page and Segment Protection + +When paging is enabled, the 80386 first evaluates segment protection, then +evaluates page protection. If the processor detects a protection violation +at either the segment or the page level, the requested operation cannot +proceed; a protection exception occurs instead. + +For example, it is possible to define a large data segment which has some +subunits that are read-only and other subunits that are read-write. In this +case, the page directory (or page table) entries for the read-only subunits +would have the U/S and R/W bits set to x0, indicating no write rights for +all the pages described by that directory entry (or for individual pages). +This technique might be used, for example, in a UNIX-like system to define +a large data segment, part of which is read only (for shared data or ROMmed +constants). This enables UNIX-like systems to define a "flat" data space as +one large segment, use "flat" pointers to address within this "flat" space, +yet be able to protect shared data, shared files mapped into the virtual +space, and supervisor areas. + + +Table 6-5. Combining Directory and Page Protection + +Page Directory Entry Page Table Entry Combined Protection + U/S R/W U/S R/W U/S R/W + + S-0 R-0 S-0 R-0 S x + S-0 R-0 S-0 W-1 S x + S-0 R-0 U-1 R-0 S x + S-0 R-0 U-1 W-1 S x + S-0 W-1 S-0 R-0 S x + S-0 W-1 S-0 W-1 S x + S-0 W-1 U-1 R-0 S x + S-0 W-1 U-1 W-1 S x + U-1 R-0 S-0 R-0 S x + U-1 R-0 S-0 W-1 S x + U-1 R-0 U-1 R-0 U R + U-1 R-0 U-1 W-1 U R + U-1 W-1 S-0 R-0 S x + U-1 W-1 S-0 W-1 S x + U-1 W-1 U-1 R-0 U R + U-1 W-1 U-1 W-1 U W + + +NOTE + S Supervisor + R Read only + U User + W Read and Write + x indicates that when the combined U/S attribute is S, the R/W attribute + is not checked. + + + +Chapter 7 Multitasking + + + +To provide efficient, protected multitasking, the 80386 employs several +special data structures. It does not, however, use special instructions to +control multitasking; instead, it interprets ordinary control-transfer +instructions differently when they refer to the special data structures. The +registers and data structures that support multitasking are: + + Task state segment + Task state segment descriptor + Task register + Task gate descriptor + +With these structures the 80386 can rapidly switch execution from one task +to another, saving the context of the original task so that the task can be +restarted later. In addition to the simple task switch, the 80386 offers two +other task-management features: + + 1. Interrupts and exceptions can cause task switches (if needed in the + system design). The processor not only switches automatically to the + task that handles the interrupt or exception, but it automatically + switches back to the interrupted task when the interrupt or exception + has been serviced. Interrupt tasks may interrupt lower-priority + interrupt tasks to any depth. + + 2. With each switch to another task, the 80386 can also switch to + another LDT and to another page directory. Thus each task can have a + different logical-to-linear mapping and a different linear-to-physical + mapping. This is yet another protection feature, because tasks can be + isolated and prevented from interfering with one another. + + +7.1 Task State Segment + +All the information the processor needs in order to manage a task is stored +in a special type of segment, a task state segment (TSS). Figure 7-1 shows +the format of a TSS for executing 80386 tasks. (Another format is used for +executing 80286 tasks; refer to Chapter 13.) + +The fields of a TSS belong to two classes: + + 1. A dynamic set that the processor updates with each switch from the + task. This set includes the fields that store: + + The general registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI). + + The segment registers (ES, CS, SS, DS, FS, GS). + + The flags register (EFLAGS). + + The instruction pointer (EIP). + + The selector of the TSS of the previously executing task (updated + only when a return is expected). + + 2. A static set that the processor reads but does not change. This set + includes the fields that store: + + The selector of the task's LDT. + + The register (PDBR) that contains the base address of the task's + page directory (read only when paging is enabled). + + Pointers to the stacks for privilege levels 0-2. + + The T-bit (debug trap bit) which causes the processor to raise a + debug exception when a task switch occurs. (Refer to Chapter 12 + for more information on debugging.) + + The I/O map base (refer to Chapter 8 for more information on the + use of the I/O map). + +Task state segments may reside anywhere in the linear space. The only case +that requires caution is when the TSS spans a page boundary and the +higher-addressed page is not present. In this case, the processor raises an +exception if it encounters the not-present page while reading the TSS during +a task switch. Such an exception can be avoided by either of two strategies: + + 1. By allocating the TSS so that it does not cross a page boundary. + + 2. By ensuring that both pages are either both present or both + not-present at the time of a task switch. If both pages are + not-present, then the page-fault handler must make both pages present + before restarting the instruction that caused the task switch. + + +Figure 7-1. 80386 32-Bit Task State Segment + + 31 23 15 7 0 + ͻ + I/O MAP BASE 0 0 0 0 0 0 0 0 0 0 0 0 0 T64 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 LDT 60 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GS 5C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FS 58 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DS 54 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS 50 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 CS 4C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ES 48 + Ķ + EDI 44 + Ķ + ESI 40 + Ķ + EBP 3C + Ķ + ESP 38 + Ķ + EBX 34 + Ķ + EDX 30 + ͹ + ECX 2C + Ķ + EAX 28 + Ķ + EFLAGS 24 + Ķ + INSTRUCTION POINTER (EIP) 20 + Ķ + CR3 (PDPR) 1C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS2 18 + Ķ + ESP2 14 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS1 10 + Ķ + ESP1 0C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS0 8 + Ķ + ESP0 4 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 BACK LINK TO PREVIOUS TSS 0 + ͼ + + +NOTE + 0 MEANS INTEL RESERVED. DO NOT DEFINE. + + + +7.2 TSS Descriptor + +The task state segment, like all other segments, is defined by a +descriptor. Figure 7-2 shows the format of a TSS descriptor. + +The B-bit in the type field indicates whether the task is busy. A type code +of 9 indicates a non-busy task; a type code of 11 indicates a busy task. +Tasks are not reentrant. The B-bit allows the processor to detect an attempt +to switch to a task that is already busy. + +The BASE, LIMIT, and DPL fields and the G-bit and P-bit have functions +similar to their counterparts in data-segment descriptors. The LIMIT field, +however, must have a value equal to or greater than 103. An attempt to +switch to a task whose TSS descriptor has a limit less that 103 causes an +exception. A larger limit is permissible, and a larger limit is required if +an I/O permission map is present. A larger limit may also be convenient for +systems software if additional data is stored in the same segment as the +TSS. + +A procedure that has access to a TSS descriptor can cause a task switch. In +most systems the DPL fields of TSS descriptors should be set to zero, so +that only trusted software has the right to perform task switching. + +Having access to a TSS-descriptor does not give a procedure the right to +read or modify a TSS. Reading and modification can be accomplished only with +another descriptor that redefines the TSS as a data segment. An attempt to +load a TSS descriptor into any of the segment registers (CS, SS, DS, ES, FS, +GS) causes an exception. + +TSS descriptors may reside only in the GDT. An attempt to identify a TSS +with a selector that has TI=1 (indicating the current LDT) results in an +exception. + + +Figure 7-2. TSS Descriptor for 32-bit TSS + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24 G00V P DPL BASE 23..16 4 + L 19..16 010B1 + Ķ + + BASE 15..0 LIMIT 15..0 0 + + ͼ + + +7.3 Task Register + +The task register (TR) identifies the currently executing task by pointing +to the TSS. Figure 7-3 shows the path by which the processor accesses the +current TSS. + +The task register has both a "visible" portion (i.e., can be read and +changed by instructions) and an "invisible" portion (maintained by the +processor to correspond to the visible portion; cannot be read by any +instruction). The selector in the visible portion selects a TSS descriptor +in the GDT. The processor uses the invisible portion to cache the base and +limit values from the TSS descriptor. Holding the base and limit in a +register makes execution of the task more efficient, because the processor +does not need to repeatedly fetch these values from memory when it +references the TSS of the current task. + +The instructions LTR and STR are used to modify and read the visible +portion of the task register. Both instructions take one operand, a 16-bit +selector located in memory or in a general register. + +LTR (Load task register) loads the visible portion of the task register +with the selector operand, which must select a TSS descriptor in the GDT. +LTR also loads the invisible portion with information from the TSS +descriptor selected by the operand. LTR is a privileged instruction; it may +be executed only when CPL is zero. LTR is generally used during system +initialization to give an initial value to the task register; thereafter, +the contents of TR are changed by task switch operations. + +STR (Store task register) stores the visible portion of the task register +in a general register or memory word. STR is not privileged. + + +Figure 7-3. Task Register + + ͻ + + + TASK STATE + SEGMENT Ŀ + + + ͼ + 16-BIT VISIBLE  + REGISTER HIDDEN REGISTER + ͻ + TR SELECTOR (BASE) (LIMT) + ͼ +   + Ŀ + GLOBAL DESCRIPTOR TABLE + ͸ + | TSS DESCRIPTOR | + ͻ + + ͹ +  + ͼ + | | + ; + + +7.4 Task Gate Descriptor + +A task gate descriptor provides an indirect, protected reference to a TSS. +Figure 7-4 illustrates the format of a task gate. + +The SELECTOR field of a task gate must refer to a TSS descriptor. The value +of the RPL in this selector is not used by the processor. + +The DPL field of a task gate controls the right to use the descriptor to +cause a task switch. A procedure may not select a task gate descriptor +unless the maximum of the selector's RPL and the CPL of the procedure is +numerically less than or equal to the DPL of the descriptor. This constraint +prevents untrusted procedures from causing a task switch. (Note that when a +task gate is used, the DPL of the target TSS descriptor is not used for +privilege checking.) + +A procedure that has access to a task gate has the power to cause a task +switch, just as a procedure that has access to a TSS descriptor. The 80386 +has task gates in addition to TSS descriptors to satisfy three needs: + + 1. The need for a task to have a single busy bit. Because the busy-bit + is stored in the TSS descriptor, each task should have only one such + descriptor. There may, however, be several task gates that select the + single TSS descriptor. + + 2. The need to provide selective access to tasks. Task gates fulfill + this need, because they can reside in LDTs and can have a DPL that is + different from the TSS descriptor's DPL. A procedure that does not + have sufficient privilege to use the TSS descriptor in the GDT (which + usually has a DPL of 0) can still switch to another task if it has + access to a task gate for that task in its LDT. With task gates, + systems software can limit the right to cause task switches to + specific tasks. + + 3. The need for an interrupt or exception to cause a task switch. Task + gates may also reside in the IDT, making it possible for interrupts + and exceptions to cause task switching. When interrupt or exception + vectors to an IDT entry that contains a task gate, the 80386 switches + to the indicated task. Thus, all tasks in the system can benefit from + the protection afforded by isolation from interrupt tasks. + +Figure 7-5 illustrates how both a task gate in an LDT and a task gate in +the IDT can identify the same task. + + +Figure 7-4. Task Gate Descriptor + + 31 23 15 7 0 + ͻ + + (NOT USED)P DPL 0 0 1 0 1(NOT USED) 4 + + Ķ + + SELECTOR (NOT USED) 0 + + ͼ + + +Figure 7-5. Task Gate Indirectly Identifies Task + + LOCAL DESCRIPTOR TABLE INTERRUPT DESCRIPTOR TABLE + ͸ ͸ + | | | | + | TASK GATE | | TASK GATE | + ͻ ͻ + + Ķ Ķ + Ķ Ķ + ͼ ͼ + | | | | + | | | | + ; ; + Ŀ + GLOBAL DESCRIPTOR TABLE + ͸ + | | + | TASK DESCRIPTOR | + ͻ + + Ķ +  Ŀ + ͼ + | | + | | + ; + + ͻ + + + + TASK STATE + SEGMENT + + + + ͼ + + +7.5 Task Switching + +The 80386 switches execution to another task in any of four cases: + + 1. The current task executes a JMP or CALL that refers to a TSS + descriptor. + + 2. The current task executes a JMP or CALL that refers to a task gate. + + 3. An interrupt or exception vectors to a task gate in the IDT. + + 4. The current task executes an IRET when the NT flag is set. + +JMP, CALL, IRET, interrupts, and exceptions are all ordinary mechanisms of +the 80386 that can be used in circumstances that do not require a task +switch. Either the type of descriptor referenced or the NT (nested task) bit +in the flag word distinguishes between the standard mechanism and the +variant that causes a task switch. + +To cause a task switch, a JMP or CALL instruction can refer either to a TSS +descriptor or to a task gate. The effect is the same in either case: the +80386 switches to the indicated task. + +An exception or interrupt causes a task switch when it vectors to a task +gate in the IDT. If it vectors to an interrupt or trap gate in the IDT, a +task switch does not occur. Refer to Chapter 9 for more information on the +interrupt mechanism. + +Whether invoked as a task or as a procedure of the interrupted task, an +interrupt handler always returns control to the interrupted procedure in the +interrupted task. If the NT flag is set, however, the handler is an +interrupt task, and the IRET switches back to the interrupted task. + +A task switching operation involves these steps: + + 1. Checking that the current task is allowed to switch to the designated + task. Data-access privilege rules apply in the case of JMP or CALL + instructions. The DPL of the TSS descriptor or task gate must be less + than or equal to the maximum of CPL and the RPL of the gate selector. + Exceptions, interrupts, and IRETs are permitted to switch tasks + regardless of the DPL of the target task gate or TSS descriptor. + + 2. Checking that the TSS descriptor of the new task is marked present + and has a valid limit. Any errors up to this point occur in the + context of the outgoing task. Errors are restartable and can be + handled in a way that is transparent to applications procedures. + + 3. Saving the state of the current task. The processor finds the base + address of the current TSS cached in the task register. It copies the + registers into the current TSS (EAX, ECX, EDX, EBX, ESP, EBP, ESI, + EDI, ES, CS, SS, DS, FS, GS, and the flag register). The EIP field of + the TSS points to the instruction after the one that caused the task + switch. + + 4. Loading the task register with the selector of the incoming task's + TSS descriptor, marking the incoming task's TSS descriptor as busy, + and setting the TS (task switched) bit of the MSW. The selector is + either the operand of a control transfer instruction or is taken from + a task gate. + + 5. Loading the incoming task's state from its TSS and resuming + execution. The registers loaded are the LDT register; the flag + register; the general registers EIP, EAX, ECX, EDX, EBX, ESP, EBP, + ESI, EDI; the segment registers ES, CS, SS, DS, FS, and GS; and PDBR. + Any errors detected in this step occur in the context of the incoming + task. To an exception handler, it appears that the first instruction + of the new task has not yet executed. + +Note that the state of the outgoing task is always saved when a task switch +occurs. If execution of that task is resumed, it starts after the +instruction that caused the task switch. The registers are restored to the +values they held when the task stopped executing. + +Every task switch sets the TS (task switched) bit in the MSW (machine +status word). The TS flag is useful to systems software when a coprocessor +(such as a numerics coprocessor) is present. The TS bit signals that the +context of the coprocessor may not correspond to the current 80386 task. +Chapter 11 discusses the TS bit and coprocessors in more detail. + +Exception handlers that field task-switch exceptions in the incoming task +(exceptions due to tests 4 thru 16 of Table 7-1) should be cautious about +taking any action that might load the selector that caused the exception. +Such an action will probably cause another exception, unless the exception +handler first examines the selector and fixes any potential problem. + +The privilege level at which execution resumes in the incoming task is +neither restricted nor affected by the privilege level at which the outgoing +task was executing. Because the tasks are isolated by their separate address +spaces and TSSs and because privilege rules can be used to prevent improper +access to a TSS, no privilege rules are needed to constrain the relation +between the CPLs of the tasks. The new task begins executing at the +privilege level indicated by the RPL of the CS selector value that is loaded +from the TSS. + + +Table 7-1. Checks Made during a Task Switch + + +Test Test Description Exception +NP = Segment-not-present exception, GP = General protection fault, TS = +Invalid TSS, SF = Stack fault Error Code Selects + + 1 Incoming TSS descriptor is NP Incoming TSS + present + 2 Incoming TSS descriptor is GP Incoming TSS + marked not-busy + 3 Limit of incoming TSS is TS Incoming TSS + greater than or equal to 103 + + All register and selector values are loaded + + 4 LDT selector of incoming TS Incoming TSS + task is valid + 5 LDT of incoming task is TS Incoming TSS + present + 6 CS selector is valid +Validity tests of a selector check that the selector is in the proper +table (eg., the LDT selector refers to the GDT), lies within the bounds of +the table, and refers to the proper type of descriptor (e.g., the LDT +selector refers to an LDT descriptor). TS Code segment + 7 Code segment is present NP Code segment + 8 Code segment DPL matches TS Code segment + CS RPL + 9 Stack segment is valid +Validity tests of a selector check that the selector is in the proper +table (eg., the LDT selector refers to the GDT), lies within the bounds of +the table, and refers to the proper type of descriptor (e.g., the LDT +selector refers to an LDT descriptor). GP Stack segment + 10 Stack segment is present SF Stack segment + 11 Stack segment DPL = CPL SF Stack segment + 12 Stack-selector RPL = CPL GP Stack segment + 13 DS, ES, FS, GS selectors are GP Segment + valid +Validity tests of a selector check that the selector is in the proper +table (eg., the LDT selector refers to the GDT), lies within the bounds of +the table, and refers to the proper type of descriptor (e.g., the LDT +selector refers to an LDT descriptor). + + + 14 DS, ES, FS, GS segments GP Segment + are readable + 15 DS, ES, FS, GS segments NP Segment + are present + 16 DS, ES, FS, GS segment DPL GP Segment + CPL (unless these are + conforming segments) + + +7.6 Task Linking + +The back-link field of the TSS and the NT (nested task) bit of the flag +word together allow the 80386 to automatically return to a task that CALLed +another task or was interrupted by another task. When a CALL instruction, an +interrupt instruction, an external interrupt, or an exception causes a +switch to a new task, the 80386 automatically fills the back-link of the new +TSS with the selector of the outgoing task's TSS and, at the same time, +sets the NT bit in the new task's flag register. The NT flag indicates +whether the back-link field is valid. The new task releases control by +executing an IRET instruction. When interpreting an IRET, the 80386 examines +the NT flag. If NT is set, the 80386 switches back to the task selected by +the back-link field. Table 7-2 summarizes the uses of these fields. + + +Table 7-2. Effect of Task Switch on BUSY, NT, and Back-Link + +Affected Field Effect of JMP Effect of Effect of + Instruction CALL Instruction IRET Instruction + +Busy bit of Set, must be Set, must be 0 Unchanged, +incoming task 0 before before must be set + +Busy bit of Cleared Unchanged Cleared +outgoing task (already set) + +NT bit of Cleared Set Unchanged +incoming task + +NT bit of Unchanged Unchanged Cleared +outgoing task + +Back-link of Unchanged Set to outgoing Unchanged +incoming task TSS selector + +Back-link of Unchanged Unchanged Unchanged +outgoing task + + +7.6.1 Busy Bit Prevents Loops + +The B-bit (busy bit) of the TSS descriptor ensures the integrity of the +back-link. A chain of back-links may grow to any length as interrupt tasks +interrupt other interrupt tasks or as called tasks call other tasks. The +busy bit ensures that the CPU can detect any attempt to create a loop. A +loop would indicate an attempt to reenter a task that is already busy; +however, the TSS is not a reentrable resource. + +The processor uses the busy bit as follows: + + 1. When switching to a task, the processor automatically sets the busy + bit of the new task. + + 2. When switching from a task, the processor automatically clears the + busy bit of the old task if that task is not to be placed on the + back-link chain (i.e., the instruction causing the task switch is JMP + or IRET). If the task is placed on the back-link chain, its busy bit + remains set. + + 3. When switching to a task, the processor signals an exception if the + busy bit of the new task is already set. + +By these actions, the processor prevents a task from switching to itself or +to any task that is on a back-link chain, thereby preventing invalid reentry +into a task. + +The busy bit is effective even in multiprocessor configurations, because +the processor automatically asserts a bus lock when it sets or clears the +busy bit. This action ensures that two processors do not invoke the same +task at the same time. (Refer to Chapter 11 for more on multiprocessing.) + + +7.6.2 Modifying Task Linkages + +Any modification of the linkage order of tasks should be accomplished only +by software that can be trusted to correctly update the back-link and the +busy-bit. Such changes may be needed to resume an interrupted task before +the task that interrupted it. Trusted software that removes a task from the +back-link chain must follow one of the following policies: + + 1. First change the back-link field in the TSS of the interrupting task, + then clear the busy-bit in the TSS descriptor of the task removed from + the list. + + 2. Ensure that no interrupts occur between updating the back-link chain + and the busy bit. + + +7.7 Task Address Space + +The LDT selector and PDBR fields of the TSS give software systems designers +flexibility in utilization of segment and page mapping features of the +80386. By appropriate choice of the segment and page mappings for each task, +tasks may share address spaces, may have address spaces that are largely +distinct from one another, or may have any degree of sharing between these +two extremes. + +The ability for tasks to have distinct address spaces is an important +aspect of 80386 protection. A module in one task cannot interfere with a +module in another task if the modules do not have access to the same address +spaces. The flexible memory management features of the 80386 allow systems +designers to assign areas of shared address space to those modules of +different tasks that are designed to cooperate with each other. + + +7.7.1 Task Linear-to-Physical Space Mapping + +The choices for arranging the linear-to-physical mappings of tasks fall +into two general classes: + + 1. One linear-to-physical mapping shared among all tasks. + + When paging is not enabled, this is the only possibility. Without page + tables, all linear addresses map to the same physical addresses. + + When paging is enabled, this style of linear-to-physical mapping + results from using one page directory for all tasks. The linear space + utilized may exceed the physical space available if the operating + system also implements page-level virtual memory. + + 2. Several partially overlapping linear-to-physical mappings. + + This style is implemented by using a different page directory for each + task. Because the PDBR (page directory base register) is loaded from + the TSS with each task switch, each task may have a different page + directory. + +In theory, the linear address spaces of different tasks may map to +completely distinct physical addresses. If the entries of different page +directories point to different page tables and the page tables point to +different pages of physical memory, then the tasks do not share any physical +addresses. + +In practice, some portion of the linear address spaces of all tasks must +map to the same physical addresses. The task state segments must lie in a +common space so that the mapping of TSS addresses does not change while the +processor is reading and updating the TSSs during a task switch. The linear +space mapped by the GDT should also be mapped to a common physical space; +otherwise, the purpose of the GDT is defeated. Figure 7-6 shows how the +linear spaces of two tasks can overlap in the physical space by sharing +page tables. + + +7.7.2 Task Logical Address Space + +By itself, a common linear-to-physical space mapping does not enable +sharing of data among tasks. To share data, tasks must also have a common +logical-to-linear space mapping; i.e., they must also have access to +descriptors that point into a shared linear address space. There are three +ways to create common logical-to-physical address-space mappings: + + 1. Via the GDT. All tasks have access to the descriptors in the GDT. If + those descriptors point into a linear-address space that is mapped to + a common physical-address space for all tasks, then the tasks can + share data and instructions. + + 2. By sharing LDTs. Two or more tasks can use the same LDT if the LDT + selectors in their TSSs select the same LDT segment. Those + LDT-resident descriptors that point into a linear space that is mapped + to a common physical space permit the tasks to share physical memory. + This method of sharing is more selective than sharing by the GDT; the + sharing can be limited to specific tasks. Other tasks in the system + may have different LDTs that do not give them access to the shared + areas. + + 3. By descriptor aliases in LDTs. It is possible for certain descriptors + of different LDTs to point to the same linear address space. If that + linear address space is mapped to the same physical space by the page + mapping of the tasks involved, these descriptors permit the tasks to + share the common space. Such descriptors are commonly called + "aliases". This method of sharing is even more selective than the + prior two; other descriptors in the LDTs may point to distinct linear + addresses or to linear addresses that are not shared. + + +Figure 7-6. Partially-Overlapping Linear Spaces + + TSSs PAGE FRAMES + ͻ + TASK A TSS PAGE DIRECTORIES PAGE TABLES TASK A + ͻ ͻ ͻ  PAGE + ͼ + ͹ ͹ ͻ + PTE TASK A + ͹ ͹  PAGE + PTE ͼ + ͹ ͹ ͹ ͻ + PDBR  PDE  PTE Ŀ TASK A + ͹ ͹ ͼ  PAGE + PDE Ŀ SHARED PT ͼ + ͼ ͼ ͻ ͻ + SHARED + ͹  PAGE + ͼ + ͹ ͻ + PTE SHARED + ͹  PAGE +  PTE ͼ + TASK B TSS ͼ ͻ + ͻ ͻ TASK B +  PAGE + ͹ ͻ ͼ + ͻ + ͹ ͹ TASK B +  PAGE + ͹ ͹ ͹ ͼ + PDBR  PDE PTE PAGE FRAMES + ͹ ͹ ͹ + PDE  PTE + ͼ ͼ ͼ + TSSs PAGE DIRECTORIES PAGE TABLES + + +Chapter 8 Input/Output + + + +This chapter presents the I/O features of the 80386 from the following +perspectives: + + Methods of addressing I/O ports + + Instructions that cause I/O operations + + Protection as it applies to the use of I/O instructions and I/O port + addresses. + + +8.1 I/O Addressing + +The 80386 allows input/output to be performed in either of two ways: + + By means of a separate I/O address space (using specific I/O + instructions) + + By means of memory-mapped I/O (using general-purpose operand + manipulationinstructions). + + +8.1.1 I/O Address Space + +The 80386 provides a separate I/O address space, distinct from physical +memory, that can be used to address the input/output ports that are used for +external 16 devices. The I/O address space consists of 2^(16) (64K) +individually addressable 8-bit ports; any two consecutive 8-bit ports can be +treated as a 16-bit port; and four consecutive 8-bit ports can be treated +as a 32-bit port. Thus, the I/O address space can accommodate up to 64K +8-bit ports, up to 32K 16-bit ports, or up to 16K 32-bit ports. + +The program can specify the address of the port in two ways. Using an +immediate byte constant, the program can specify: + + 256 8-bit ports numbered 0 through 255. + 128 16-bit ports numbered 0, 2, 4, . . . , 252, 254. + 64 32-bit ports numbered 0, 4, 8, . . . , 248, 252. + +Using a value in DX, the program can specify: + + 8-bit ports numbered 0 through 65535 + 16-bit ports numbered 0, 2, 4, . . . , 65532, 65534 + 32-bit ports numbered 0, 4, 8, . . . , 65528, 65532 + +The 80386 can transfer 32, 16, or 8 bits at a time to a device located in +the I/O space. Like doublewords in memory, 32-bit ports should be aligned at +addresses evenly divisible by four so that the 32 bits can be transferred in +a single bus access. Like words in memory, 16-bit ports should be aligned at +even-numbered addresses so that the 16 bits can be transferred in a single +bus access. An 8-bit port may be located at either an even or odd address. + +The instructions IN and OUT move data between a register and a port in the +I/O address space. The instructions INS and OUTS move strings of data +between the memory address space and ports in the I/O address space. + + +8.1.2 Memory-Mapped I/O + +I/O devices also may be placed in the 80386 memory address space. As long +as the devices respond like memory components, they are indistinguishable to +the processor. + +Memory-mapped I/O provides additional programming flexibility. Any +instruction that references memory may be used to access an I/O port located +in the memory space. For example, the MOV instruction can transfer data +between any register and a port; and the AND, OR, and TEST instructions may +be used to manipulate bits in the internal registers of a device (see Figure +8-1). Memory-mapped I/O performed via the full instruction set maintains +the full complement of addressing modes for selecting the desired I/O +device (e.g., direct address, indirect address, base register, index +register, scaling). + +Memory-mapped I/O, like any other memory reference, is subject to access +protection and control when executing in protected mode. Refer to Chapter 6 +for a discussion of memory protection. + + +8.2 I/O Instructions + +The I/O instructions of the 80386 provide access to the processor's I/O +ports for the transfer of data to and from peripheral devices. These +instructions have as one operand the address of a port in the I/O address +space. There are two classes of I/O instruction: + + 1. Those that transfer a single item (byte, word, or doubleword) located + in a register. + + 2. Those that transfer strings of items (strings of bytes, words, or + doublewords) located in memory. These are known as "string I/O + instructions" or "block I/O instructions". + + +8.2.1 Register I/O Instructions + +The I/O instructions IN and OUT are provided to move data between I/O ports +and the EAX (32-bit I/O), the AX (16-bit I/O), or AL (8-bit I/O) general +registers. IN and OUT instructions address I/O ports either directly, with +the address of one of up to 256 port addresses coded in the instruction, or +indirectly via the DX register to one of up to 64K port addresses. + +IN (Input from Port) transfers a byte, word, or doubleword from an input +port to AL, AX, or EAX. If a program specifies AL with the IN instruction, +the processor transfers 8 bits from the selected port to AL. If a program +specifies AX with the IN instruction, the processor transfers 16 bits from +the port to AX. If a program specifies EAX with the IN instruction, the +processor transfers 32 bits from the port to EAX. + +OUT (Output to Port) transfers a byte, word, or doubleword to an output +port from AL, AX, or EAX. The program can specify the number of the port +using the same methods as the IN instruction. + + +Figure 8-1. Memory-Mapped I/O + + MEMORY + ADDRESS SPACE I/O DEVICE 1 + ͻ ͻ + INTERNAL REGISTER + Ķ ĺͻ + + Ķ ĺͼ + ͼ + + + + I/O DEVICE 2 + ͻ + INTERNAL REGISTER + Ķ ĺͻ + + Ķ ĺͼ + ͼ + ͼ + + +8.2.2 Block I/O Instructions + +The block (or string) I/O instructions INS and OUTS move blocks of data +between I/O ports and memory space. Block I/O instructions use the DX +register to specify the address of a port in the I/O address space. INS and +OUTS use DX to specify: + + 8-bit ports numbered 0 through 65535 + 16-bit ports numbered 0, 2, 4, . . . , 65532, 65534 + 32-bit ports numbered 0, 4, 8, . . . , 65528, 65532 + +Block I/O instructions use either SI or DI to designate the source or +destination memory address. For each transfer, SI or DI are automatically +either incremented or decremented as specified by the direction bit in the +flags register. + +INS and OUTS, when used with repeat prefixes, cause block input or output +operations. REP, the repeat prefix, modifies INS and OUTS to provide a means +of transferring blocks of data between an I/O port and memory. These block +I/O instructions are string primitives (refer also to Chapter 3 for more on +string primitives). They simplify programming and increase the speed of data +transfer by eliminating the need to use a separate LOOP instruction or an +intermediate register to hold the data. + +The string I/O primitives can operate on byte strings, word strings, or +doubleword strings. After each transfer, the memory address in ESI or EDI is +updated by 1 for byte operands, by 2 for word operands, or by 4 for +doubleword operands. The value in the direction flag (DF) determines whether +the processor automatically increments ESI or EDI (DF=0) or whether it +automatically decrements these registers (DF=1). + +INS (Input String from Port) transfers a byte or a word string element from +an input port to memory. The mnemonics INSB, INSW, and INSD are variants +that explicitly specify the size of the operand. If a program specifies +INSB, the processor transfers 8 bits from the selected port to the memory +location indicated by ES:EDI. If a program specifies INSW, the processor +transfers 16 bits from the port to the memory location indicated by ES:EDI. +If a program specifies INSD, the processor transfers 32 bits from the port +to the memory location indicated by ES:EDI. The destination segment register +choice (ES) cannot be changed for the INS instruction. Combined with the REP +prefix, INS moves a block of information from an input port to a series of +consecutive memory locations. + +OUTS (Output String to Port) transfers a byte, word, or doubleword string +element to an output port from memory. The mnemonics OUTSB, OUTSW, and OUTSD +are variants that explicitly specify the size of the operand. If a program +specifies OUTSB, the processor transfers 8 bits from the memory location +indicated by ES:EDI to the the selected port. If a program specifies OUTSW, +the processor transfers 16 bits from the memory location indicated by ES:EDI +to the the selected port. If a program specifies OUTSD, the processor +transfers 32 bits from the memory location indicated by ES:EDI to the the +selected port. Combined with the REP prefix, OUTS moves a block of +information from a series of consecutive memory locations indicated by +DS:ESI to an output port. + + +8.3 Protection and I/O + +Two mechanisms provide protection for I/O functions: + + 1. The IOPL field in the EFLAGS register defines the right to use + I/O-related instructions. + + 2. The I/O permission bit map of a 80386 TSS segment defines the right + to use ports in the I/O address space. + +These mechanisms operate only in protected mode, including virtual 8086 +mode; they do not operate in real mode. In real mode, there is no protection +of the I/O space; any procedure can execute I/O instructions, and any I/O +port can be addressed by the I/O instructions. + + +8.3.1 I/O Privilege Level + +Instructions that deal with I/O need to be restricted but also need to be +executed by procedures executing at privilege levels other than zero. For +this reason, the processor uses two bits of the flags register to store the +I/O privilege level (IOPL). The IOPL defines the privilege level +needed to execute I/O-related instructions. + +The following instructions can be executed only if CPL IOPL: + +IN Input +INS Input String +OUT Output +OUTS Output String +CLI Clear Interrupt-Enable Flag +STI Set Interrupt-Enable + +These instructions are called "sensitive" instructions, because they are +sensitive to IOPL. + +To use sensitive instructions, a procedure must execute at a privilege +level at least as privileged as that specified by the IOPL (CPL IOPL). Any +attempt by a less privileged procedure to use a sensitive instruction +results in a general protection exception. + +Because each task has its own unique copy of the flags register, each task +can have a different IOPL. A task whose primary function is to perform I/O +(a device driver) can benefit from having an IOPL of three, thereby +permitting all procedures of the task to performI/O. Other tasks typically +have IOPL set to zero or one, reserving the right to perform I/O +instructions for the most privileged procedures. + +A task can change IOPL only with the POPF instruction; however, such +changes are privileged. No procedure may alter IOPL (the I/O privilege level +in the flag register) unless the procedure is executing at privilege level +0. An attempt by a less privileged procedure to alter IOPL does not result +in an exception; IOPL simply remains unaltered. + +The POPF instruction may be used in addition to CLI and STI to alter the +interrupt-enable flag (IF); however, changes to IF by POPF are +IOPL-sensitive. A procedure may alter IF with a POPF instruction only when +executing at a level that is at least as privileged as IOPL. An attempt by a +less privileged procedure to alter IF in this manner does not result in an +exception; IF simply remains unaltered. + + +8.3.2 I/O Permission Bit Map + +The I/O instructions that directly refer to addresses in the processor's +I/O space are IN, INS, OUT, OUTS. The 80386 has the ability to selectively +trap references to specific I/O addresses. The structure that enables +selective trapping is the I/O Permission Bit Map in the TSS segment (see +Figure 8-2). The I/O permission map is a bit vector. The size of the map +and its location in the TSS segment are variable. The processor locates the +I/O permission map by means of the I/O map base field in the fixed portion +of the TSS. The I/O map base field is 16 bits wide and contains the offset +of the beginning of the I/O permission map. The upper limit of the I/O +permission map is the same as the limit of the TSS segment. + +In protected mode, when it encounters an I/O instruction (IN, INS, OUT, or +OUTS), the processor first checks whether CPL IOPL. If this condition is +true, the I/O operation may proceed. If not true, the processor checks the +I/O permission map. (In virtual 8086 mode, the processor consults the map +without regard for IOPL. Refer to Chapter 15.) + +Each bit in the map corresponds to an I/O port byte address; for example, +the bit for port 41 is found at I/O map base + 5, bit offset 1. The +processor tests all the bits that correspond to the I/O addresses spanned by +an I/O operation; for example, a doubleword operation tests four bits +corresponding to four adjacent byte addresses. If any tested bit is set, +the processor signals a general protection exception. If all the tested bits +are zero, the I/O operation may proceed. + +It is not necessary for the I/O permission map to represent all the I/O +addresses. I/O addresses not spanned by the map are treated as if they had +one bits in the map. For example, if TSS limit is equal to I/O map base + +31, the first 256 I/O ports are mapped; I/O operations on any port greater +than 255 cause an exception. + +If I/O map base is greater than or equal to TSS limit, the TSS segment has +no I/O permission map, and all I/O instructions in the 80386 program cause +exceptions when CPL > IOPL. + +Because the I/O permission map is in the TSS segment, different tasks can +have different maps. Thus, the operating system can allocate ports to a task +by changing the I/O permission map in the task's TSS. + + +Figure 8-2. I/O Address Bit Map + + TSS SEGMEMT + + 31 23 15 7 0 + ͻ + LIMIT + +   +  I/O PERMISSION BIT MAP  +   + +  + Ķ +   +   +   + Ķ + Ķ I/O MAP BASE uuuuuuuu uuuuuuuT64 + Ķ + 00000000 00000000 LOT 60 + Ķ + 00000000 00000000 GS 5C + Ķ + 58 +   +   +   + 4 + Ķ + 00000000 00000000 TSS BACK LINK 0 + ͼ + + +Chapter 9 Exceptions and Interrupts + + + +Interrupts and exceptions are special kinds of control transfer; they work +somewhat like unprogrammed CALLs. They alter the normal program flow to +handle external events or to report errors or exceptional conditions. The +difference between interrupts and exceptions is that interrupts are used to +handle asynchronous events external to the processor, but exceptions handle +conditions detected by the processor itself in the course of executing +instructions. + +There are two sources for external interrupts and two sources for +exceptions: + + 1. Interrupts + + Maskable interrupts, which are signalled via the INTR pin. + + Nonmaskable interrupts, which are signalled via the NMI + (Non-Maskable Interrupt) pin. + + 2. Exceptions + + Processor detected. These are further classified as faults, traps, + and aborts. + + Programmed. The instructions INTO, INT 3, INT n, and BOUND can + trigger exceptions. These instructions are often called "software + interrupts", but the processor handles them as exceptions. + +This chapter explains the features that the 80386 offers for controlling +and responding to interrupts when it is executing in protected mode. + + +9.1 Identifying Interrupts + +The processor associates an identifying number with each different type of +interrupt or exception. + +The NMI and the exceptions recognized by the processor are assigned +predetermined identifiers in the range 0 through 31. Not all of these +numbers are currently used by the 80386; unassigned identifiers in this +range are reserved by Intel for possible future expansion. + +The identifiers of the maskable interrupts are determined by external +interrupt controllers (such as Intel's 8259A Programmable Interrupt +Controller) and communicated to the processor during the processor's +interrupt-acknowledge sequence. The numbers assigned by an 8259A PIC can be +specified by software. Any numbers in the range 32 through 255 can be used. +Table 9-1 shows the assignment of interrupt and exception identifiers. + +Exceptions are classified as faults, traps, or aborts depending on the way +they are reported and whether restart of the instruction that caused the +exception is supported. + +Faults Faults are exceptions that are reported "before" the + instruction causingthe exception. Faults are either detected before + the instruction begins to execute, or during execution of the + instruction. If detected during the instruction, the fault is + reported with the machine restored to a state that permits the + instruction to be restarted. + +Traps A trap is an exception that is reported at the instruction + boundary immediately after the instruction in which the + exception was detected. + +Aborts An abort is an exception that permits neither precise location + of the instruction causing the exception nor restart of the program + that caused the exception. Aborts are used to report severe errors, + such as hardware errors and inconsistent or illegal values in system + tables. + + +Table 9-1. Interrupt and Exception ID Assignments + +Identifier Description + +0 Divide error +1 Debug exceptions +2 Nonmaskable interrupt +3 Breakpoint (one-byte INT 3 instruction) +4 Overflow (INTO instruction) +5 Bounds check (BOUND instruction) +6 Invalid opcode +7 Coprocessor not available +8 Double fault +9 (reserved) +10 Invalid TSS +11 Segment not present +12 Stack exception +13 General protection +14 Page fault +15 (reserved) +16 Coprecessor error +17-31 (reserved) +32-255 Available for external interrupts via INTR pin + + +9.2 Enabling and Disabling Interrupts + +The processor services interrupts and exceptions only between the end of +one instruction and the beginning of the next. When the repeat prefix is +used to repeat a string instruction, interrupts and exceptions may occur +between repetitions. Thus, operations on long strings do not delay interrupt +response. + +Certain conditions and flag settings cause the processor to inhibit certain +interrupts and exceptions at instruction boundaries. + + +9.2.1 NMI Masks Further NMIs + +While an NMI handler is executing, the processor ignores further interrupt +signals at the NMI pin until the next IRET instruction is executed. + + +9.2.2 IF Masks INTR + +The IF (interrupt-enable flag) controls the acceptance of external +interrupts signalled via the INTR pin. When IF=0, INTR interrupts are +inhibited; when IF=1, INTR interrupts are enabled. As with the other flag +bits, the processor clears IF in response to a RESET signal. The +instructions CLI and STI alter the setting of IF. + +CLI (Clear Interrupt-Enable Flag) and STI (Set Interrupt-Enable Flag) +explicitly alter IF (bit 9 in the flag register). These instructions may be +executed only if CPL IOPL. A protection exception occurs if they are +executed when CPL > IOPL. + +The IF is also affected implicitly by the following operations: + + The instruction PUSHF stores all flags, including IF, in the stack + where they can be examined. + + Task switches and the instructions POPF and IRET load the flags + register; therefore, they can be used to modify IF. + + Interrupts through interrupt gates automatically reset IF, disabling + interrupts. (Interrupt gates are explained later in this chapter.) + + +9.2.3 RF Masks Debug Faults + +The RF bit in EFLAGS controls the recognition of debug faults. This permits +debug faults to be raised for a given instruction at most once, no matter +how many times the instruction is restarted. (Refer to Chapter 12 for more +information on debugging.) + + +9.2.4 MOV or POP to SS Masks Some Interrupts and Exceptions + +Software that needs to change stack segments often uses a pair of +instructions; for example: + + MOV SS, AX + MOV ESP, StackTop + +If an interrupt or exception is processed after SS has been changed but +before ESP has received the corresponding change, the two parts of the stack +pointer SS:ESP are inconsistent for the duration of the interrupt handler or +exception handler. + +To prevent this situation, the 80386, after both a MOV to SS and a POP to +SS instruction, inhibits NMI, INTR, debug exceptions, and single-step traps +at the instruction boundary following the instruction that changes SS. Some +exceptions may still occur; namely, page fault and general protection fault. +Always use the 80386 LSS instruction, and the problem will not occur. + + +9.3 Priority Among Simultaneous Interrupts and Exceptions + +If more than one interrupt or exception is pending at an instruction +boundary, the processor services one of them at a time. The priority among +classes of interrupt and exception sources is shown in Table 9-2. The +processor first services a pending interrupt or exception from the class +that has the highest priority, transferring control to the first +instruction of the interrupt handler. Lower priority exceptions are +discarded; lower priority interrupts are held pending. Discarded exceptions +will be rediscovered when the interrupt handler returns control to the point +of interruption. + + +9.4 Interrupt Descriptor Table + +The interrupt descriptor table (IDT) associates each interrupt or exception +identifier with a descriptor for the instructions that service the +associated event. Like the GDT and LDTs, the IDT is an array of 8-byte +descriptors. Unlike the GDT and LDTs, the first entry of the IDT may contain +a descriptor. To form an index into the IDT, the processor multiplies the +interrupt or exception identifier by eight. Because there are only 256 +identifiers, the IDT need not contain more than 256 descriptors. It can +contain fewer than 256 entries; entries are required only for interrupt +identifiers that are actually used. + +The IDT may reside anywhere in physical memory. As Figure 9-1 shows, the +processor locates the IDT by means of the IDT register (IDTR). The +instructions LIDT and SIDT operate on the IDTR. Both instructions have one +explicit operand: the address in memory of a 6-byte area. Figure 9-2 shows +the format of this area. + +LIDT (Load IDT register) loads the IDT register with the linear base +address and limit values contained in the memory operand. This instruction +can be executed only when the CPL is zero. It is normally used by the +initialization logic of an operating system when creating an IDT. An +operating system may also use it to change from one IDT to another. + +SIDT (Store IDT register) copies the base and limit value stored in IDTR +to a memory location. This instruction can be executed at any privilege +level. + + +Table 9-2. Priority Among Simultaneous Interrupts and Exceptions + +Priority Class of Interrupt or Exception + +HIGHEST Faults except debug faults + Trap instructions INTO, INT n, INT 3 + Debug traps for this instruction + Debug faults for next instruction + NMI interrupt +LOWEST INTR interrupt + + +Figure 9-1. IDT Register and Table + + INTERRUPT DESCRIPTOR TABLE + ͻ +  + GATE FOR INTERRUPT #N Ķ + + ͼ +   +   +   + ͻ + + GATE FOR INTERRUPT #2 Ķ + + ͹ + IDT REGISTER + GATE FOR INTERRUPT #1 Ķ + 15 0 + ͻ ͹ + IDT LIMIT + ͹ GATE FOR INTERRUPT #0 Ķ + IDT BASE  + ͼ ͼ + 31 0 + + +Figure 9-2. Pseudo-Descriptor Format for LIDT and SIDT + + 31 23 15 7 0 + ͻ + BASE 2 + ͹ + LIMIT 0 + ͼ + + +9.5 IDT Descriptors + +The IDT may contain any of three kinds of descriptor: + + Task gates + Interrupt gates + Trap gates + +Figure 9-3 illustrates the format of task gates and 80386 interrupt gates +and trap gates. (The task gate in an IDT is the same as the task gate +already discussed in Chapter 7.) + + +Figure 9-3. 80306 IDT Gate Descriptors + + 80386 TASK GATE + 31 23 15 7 0 + ͻ + (NOT USED) P DPL0 0 1 0 1(NOT USED)4 + Ķ + SELECTOR (NOT USED)0 + ͼ + + 80386 INTERRUPT GATE + 31 23 15 7 0 + ͻ + OFFSET 31..16 P DPL0 1 1 1 00 0 0(NOT USED) 4 + Ķ + SELECTOR OFFSET 15..0 0 + ͼ + + 80386 TRAP GATE + 31 23 15 7 0 + ͻ + OFFSET 31..16 P DPL0 1 1 1 10 0 0(NOT USED) 4 + Ķ + SELECTOR OFFSET 15..0 0 + ͼ + + +9.6 Interrupt Tasks and Interrupt Procedures + +Just as a CALL instruction can call either a procedure or a task, so an +interrupt or exception can "call" an interrupt handler that is either a +procedure or a task. When responding to an interrupt or exception, the +processor uses the interrupt or exception identifier to index a descriptor +in the IDT. If the processor indexes to an interrupt gate or trap gate, it +invokes the handler in a manner similar to a CALL to a call gate. If the +processor finds a task gate, it causes a task switch in a manner similar to +a CALL to a task gate. + + +9.6.1 Interrupt Procedures + +An interrupt gate or trap gate points indirectly to a procedure which will +execute in the context of the currently executing task as illustrated by +Figure 9-4. The selector of the gate points to an executable-segment +descriptor in either the GDT or the current LDT. The offset field of the +gate points to the beginning of the interrupt or exception handling +procedure. + +The 80386 invokes an interrupt or exception handling procedure in much the +same manner as it CALLs a procedure; the differences are explained in the +following sections. + + +Figure 9-4. Interrupt Vectoring for Procedures + + IDT EXECUTABLE SEGMENT + ͻ ͻ + OFFSET + ͹  ENTRY POINT + LDT OR GDT + ͹ ͻ + +INTERRUPT ͹ ͹ + ID TRAP GATE OR + INTERRUPT GATE Ŀ ͹ + ͹ + ͹ + ͹  SEGMENT Ŀ + DESCRIPTOR + ͹ ͹ + + ͹ ͹ + BASE + ͼ ͹ ͼ + + + + ͼ + + +9.6.1.1 Stack of Interrupt Procedure + +Just as with a control transfer due to a CALL instruction, a control +transfer to an interrupt or exception handling procedure uses the stack to +store the information needed for returning to the original procedure. As +Figure 9-5 shows, an interrupt pushes the EFLAGS register onto the stack +before the pointer to the interrupted instruction. + +Certain types of exceptions also cause an error code to be pushed on the +stack. An exception handler can use the error code to help diagnose the +exception. + + +9.6.1.2 Returning from an Interrupt Procedure + +An interrupt procedure also differs from a normal procedure in the method +of leaving the procedure. The IRET instruction is used to exit from an +interrupt procedure. IRET is similar to RET except that IRET increments EIP +by an extra four bytes (because of the flags on the stack) and moves the +saved flags into the EFLAGS register. The IOPL field of EFLAGS is changed +only if the CPL is zero. The IF flag is changed only if CPL IOPL. + + +Figure 9-5. Stack Layout after Exception of Interrupt + + WITHOUT PRIVILEGE TRANSITION + + D O 31 0 31 0 + I F ͹ ͹ + R OLD OLD + E E ͹ SS:ESP ͹ SS:ESP + C X + T P ͹ ͹ + I A OLD EFLAGS OLD EFLAGS + O N ͹ ͹ + N S OLD CS NEW OLD CS + I ͹ SS:ESP ͹ + O OLD EIP OLD EIP NEW + N ͹ ͹ SS:ESP + ERROR CODE +    ͹ +   +   + WITHOUT ERROR CODE WITH ERROR CODE + + WITH PRIVILEGE TRANSITION + + D O 31 0 31 0 + I F ͻĿ ͻĿ + R OLD SS OLD SS + E E ͹ SS:ESP ͹ SS:ESP + C X OLD ESP FROM TSS OLD ESP FROM TSS + T P ͹ ͹ + I A OLD EFLAGS OLD EFLAGS + O N ͹ ͹ + N S OLD CS NEW OLD CS + I ͹ SS:EIP ͹ + O OLD EIP OLD EIP NEW + N ͹ ͹ SS:ESP + ERROR CODE +    ͹ +   +   + WITHOUT ERROR CODE WITH ERROR CODE + + +9.6.1.3 Flags Usage by Interrupt Procedure + +Interrupts that vector through either interrupt gates or trap gates cause +TF (the trap flag) to be reset after the current value of TF is saved on the +stack as part of EFLAGS. By this action the processor prevents debugging +activity that uses single-stepping from affecting interrupt response. A +subsequent IRET instruction restores TF to the value in the EFLAGS image on +the stack. + +The difference between an interrupt gate and a trap gate is in the effect +on IF (the interrupt-enable flag). An interrupt that vectors through an +interrupt gate resets IF, thereby preventing other interrupts from +interfering with the current interrupt handler. A subsequent IRET +instruction restores IF to the value in the EFLAGS image on the stack. An +interrupt through a trap gate does not change IF. + + +9.6.1.4 Protection in Interrupt Procedures + +The privilege rule that governs interrupt procedures is similar to that for +procedure calls: the CPU does not permit an interrupt to transfer control to +a procedure in a segment of lesser privilege (numerically greater privilege +level) than the current privilege level. An attempt to violate this rule +results in a general protection exception. + +Because occurrence of interrupts is not generally predictable, this +privilege rule effectively imposes restrictions on the privilege levels at +which interrupt and exception handling procedures can execute. Either of the +following strategies can be employed to ensure that the privilege rule is +never violated. + + Place the handler in a conforming segment. This strategy suits the + handlers for certain exceptions (divide error, for example). Such a + handler must use only the data available to it from the stack. If it + needed data from a data segment, the data segment would have to have + privilege level three, thereby making it unprotected. + + Place the handler procedure in a privilege level zero segment. + + +9.6.2 Interrupt Tasks + +A task gate in the IDT points indirectly to a task, as Figure 9-6 +illustrates. The selector of the gate points to a TSS descriptor in the GDT. + +When an interrupt or exception vectors to a task gate in the IDT, a task +switch results. Handling an interrupt with a separate task offers two +advantages: + + The entire context is saved automatically. + + The interrupt handler can be isolated from other tasks by giving it a + separate address space, either via its LDT or via its page directory. + +The actions that the processor takes to perform a task switch are discussed +in Chapter 7. The interrupt task returns to the interrupted task by +executing an IRET instruction. + +If the task switch is caused by an exception that has an error code, the +processor automatically pushes the error code onto the stack that +corresponds to the privilege level of the first instruction to be executed +in the interrupt task. + +When interrupt tasks are used in an operating system for the 80386, there +are actually two schedulers: the software scheduler (part of the operating +system) and the hardware scheduler (part of the processor's interrupt +mechanism). The design of the software scheduler should account for the fact +that the hardware scheduler may dispatch an interrupt task whenever +interrupts are enabled. + + +Figure 9-6. Interrupt Vectoring for Tasks + + IDT GDT + ͻ ͻ + TSS + Ķ Ķ ͻ + + Ķ Ķ + + Ķ Ķ +  TASK GATE Ŀ + Ķ Ķ +  TSS DESCRIPTOR Ŀ + Ķ Ķ + + Ķ Ķ ͼ + + Ķ Ķ + + ͼ ͼ + + INTERRUPT ID + + +9.7 Error Code + +With exceptions that relate to a specific segment, the processor pushes an +error code onto the stack of the exception handler (whether procedure or +task). The error code has the format shown in Figure 9-7. The format of the +error code resembles that of a selector; however, instead of an RPL field, +the error code contains two one-bit items: + + 1. The processor sets the EXT bit if an event external to the program + caused the exception. + + 2. The processor sets the I-bit (IDT-bit) if the index portion of the + error code refers to a gate descriptor in the IDT. + +If the I-bit is not set, the TI bit indicates whether the error code refers +to the GDT (value 0) or to the LDT (value 1). The remaining 14 bits are the +upper 14 bits of the segment selector involved. In some cases the error code +on the stack is null, i.e., all bits in the low-order word are zero. + + +Figure 9-7. Error Code Format + + 31 15 2 1 0 + ͻ + T E + UNDEFINED SELECTOR INDEX I + I X + ͼ + + +9.8 Exception Conditions + +The following sections describe each of the possible exception conditions +in detail. Each description classifies the exception as a fault, trap, or +abort. This classification provides information needed by systems +programmers for restarting the procedure in which the exception occurred: + +Faults The CS and EIP values saved when a fault is reported point to the + instruction causing the fault. + +Traps The CS and EIP values stored when the trap is reported point to the + instruction dynamically after the instruction causing the trap. If + a trap is detected during an instruction that alters program flow, + the reported values of CS and EIP reflect the alteration of program + flow. For example, if a trap is detected in a JMP instruction, the + CS and EIP values pushed onto the stack point to the target of the + JMP, not to the instruction after the JMP. + +Aborts An abort is an exception that permits neither precise location of + the instruction causing the exception nor restart of the program + that caused the exception. Aborts are used to report severe errors, + such as hardware errors and inconsistent or illegal values in + system tables. + + +9.8.1 Interrupt 0 Divide Error + +The divide-error fault occurs during a DIV or an IDIV instruction when the +divisor is zero. + + +9.8.2 Interrupt 1 Debug Exceptions + +The processor triggers this interrupt for any of a number of conditions; +whether the exception is a fault or a trap depends on the condition: + + Instruction address breakpoint fault. + Data address breakpoint trap. + General detect fault. + Single-step trap. + Task-switch breakpoint trap. + +The processor does not push an error code for this exception. An exception +handler can examine the debug registers to determine which condition caused +the exception. Refer to Chapter 12 for more detailed information about +debugging and the debug registers. + + +9.8.3 Interrupt 3 Breakpoint + +The INT 3 instruction causes this trap. The INT 3 instruction is one byte +long, which makes it easy to replace an opcode in an executable segment with +the breakpoint opcode. The operating system or a debugging subsystem can use +a data-segment alias for an executable segment to place an INT 3 anywhere it +is convenient to arrest normal execution so that some sort of special +processing can be performed. Debuggers typically use breakpoints as a way of +displaying registers, variables, etc., at crucial points in a task. + +The saved CS:EIP value points to the byte following the breakpoint. If a +debugger replaces a planted breakpoint with a valid opcode, it must subtract +one from the saved EIP value before returning. Refer also to Chapter 12 for +more information on debugging. + + +9.8.4 Interrupt 4 Overflow + +This trap occurs when the processor encounters an INTO instruction and the +OF (overflow) flag is set. Since signed arithmetic and unsigned arithmetic +both use the same arithmetic instructions, the processor cannot determine +which is intended and therefore does not cause overflow exceptions +automatically. Instead it merely sets OF when the results, if interpreted as +signed numbers, would be out of range. When doing arithmetic on signed +operands, careful programmers and compilers either test OF directly or use +the INTO instruction. + + +9.8.5 Interrupt 5 Bounds Check + +This fault occurs when the processor, while executing a BOUND instruction, +finds that the operand exceeds the specified limits. A program can use the +BOUND instruction to check a signed array index against signed limits +defined in a block of memory. + + +9.8.6 Interrupt 6 Invalid Opcode + +This fault occurs when an invalid opcode is detected by the execution unit. +(The exception is not detected until an attempt is made to execute the +invalid opcode; i.e., prefetching an invalid opcode does not cause this +exception.) No error code is pushed on the stack. The exception can be +handled within the same task. + +This exception also occurs when the type of operand is invalid for the +given opcode. Examples include an intersegment JMP referencing a register +operand, or an LES instruction with a register source operand. + + +9.8.7 Interrupt 7 Coprocessor Not Available + +This exception occurs in either of two conditions: + + The processor encounters an ESC (escape) instruction, and the EM + (emulate) bit ofCR0 (control register zero) is set. + + The processor encounters either the WAIT instruction or an ESC + instruction, and both the MP (monitor coprocessor) and TS (task + switched) bits of CR0 are set. + +Refer to Chapter 11 for information about the coprocessor interface. + + +9.8.8 Interrupt 8 Double Fault + +Normally, when the processor detects an exception while trying to invoke +the handler for a prior exception, the two exceptions can be handled +serially. If, however, the processor cannot handle them serially, it signals +the double-fault exception instead. To determine when two faults are to be +signalled as a double fault, the 80386 divides the exceptions into three +classes: benign exceptions, contributory exceptions, and page faults. Table +9-3 shows this classification. + +Table 9-4 shows which combinations of exceptions cause a double fault and +which do not. + +The processor always pushes an error code onto the stack of the +double-fault handler; however, the error code is always zero. The faulting +instruction may not be restarted. If any other exception occurs while +attempting to invoke the double-fault handler, the processor shuts down. + + +Table 9-3. Double-Fault Detection Classes + +Class ID Description + + 1 Debug exceptions + 2 NMI + 3 Breakpoint +Benign 4 Overflow +Exceptions 5 Bounds check + 6 Invalid opcode + 7 Coprocessor not available + 16 Coprocessor error + + 0 Divide error + 9 Coprocessor Segment Overrun +Contributory 10 Invalid TSS +Exceptions 11 Segment not present + 12 Stack exception + 13 General protection + +Page Faults 14 Page fault + + +Table 9-4. Double-Fault Definition + + SECOND EXCEPTION + + Benign Contributory Page + Exception Exception Fault + + + Benign OK OK OK + Exception + +FIRST Contributory OK DOUBLE OK +EXCEPTION Exception + + Page + Fault OK DOUBLE DOUBLE + + +9.8.9 Interrupt 9 Coprocessor Segment Overrun + +This exception is raised in protected mode if the 80386 detects a page or +segment violation while transferring the middle portion of a coprocessor +operand to the NPX. This exception is avoidable. Refer to Chapter 11 for +more information about the coprocessor interface. + + +9.8.10 Interrupt 10 Invalid TSS + +Interrupt 10 occurs if during a task switch the new TSS is invalid. A TSS +is considered invalid in the cases shown in Table 9-5. An error code is +pushed onto the stack to help identify the cause of the fault. The EXT bit +indicates whether the exception was caused by a condition outside the +control of the program; e.g., an external interrupt via a task gate +triggered a switch to an invalid TSS. + +This fault can occur either in the context of the original task or in the +context of the new task. Until the processor has completely verified the +presence of the new TSS, the exception occurs in the context of the original +task. Once the existence of the new TSS is verified, the task switch is +considered complete; i.e., TR is updated and, if the switch is due to a +CALL or interrupt, the backlink of the new TSS is set to the old TSS. Any +errors discovered by the processor after this point are handled in the +context of the new task. + +To insure a proper TSS to process it, the handler for exception 10 must be +a task invoked via a task gate. + + +Table 9-5. Conditions That Invalidate the TSS + +Error Code Condition + +TSS id + EXT The limit in the TSS descriptor is less than 103 +LTD id + EXT Invalid LDT selector or LDT not present +SS id + EXT Stack segment selector is outside table limit +SS id + EXT Stack segment is not a writable segment +SS id + EXT Stack segment DPL does not match new CPL +SS id + EXT Stack segment selector RPL < > CPL +CS id + EXT Code segment selector is outside table limit +CS id + EXT Code segment selector does not refer to code + segment +CS id + EXT DPL of non-conforming code segment < > new CPL +CS id + EXT DPL of conforming code segment > new CPL +DS/ES/FS/GS id + EXT DS, ES, FS, or GS segment selector is outside + table limits +DS/ES/FS/GS id + EXT DS, ES, FS, or GS is not readable segment + + +9.8.11 Interrupt 11 Segment Not Present + +Exception 11 occurs when the processor detects that the present bit of a +descriptor is zero. The processor can trigger this fault in any of these +cases: + + While attempting to load the CS, DS, ES, FS, or GS registers; loading + the SS register, however, causes a stack fault. + + While attempting loading the LDT register with an LLDT instruction; + loading the LDT register during a task switch operation, however, + causes the "invalid TSS" exception. + + While attempting to use a gate descriptor that is marked not-present. + +This fault is restartable. If the exception handler makes the segment +present and returns, the interrupted program will resume execution. + +If a not-present exception occurs during a task switch, not all the steps +of the task switch are complete. During a task switch, the processor first +loads all the segment registers, then checks their contents for validity. If +a not-present exception is discovered, the remaining segment registers have +not been checked and therefore may not be usable for referencing memory. The +not-present handler should not rely on being able to use the values found +in CS, SS, DS, ES, FS, and GS without causing another exception. The +exception handler should check all segment registers before trying to resume +the new task; otherwise, general protection faults may result later under +conditions that make diagnosis more difficult. There are three ways to +handle this case: + + 1. Handle the not-present fault with a task. The task switch back to the + interrupted task will cause the processor to check the registers as it + loads them from the TSS. + + 2. PUSH and POP all segment registers. Each POP causes the processor to + check the new contents of the segment register. + + 3. Scrutinize the contents of each segment-register image in the TSS, + simulating the test that the processor makes when it loads a segment + register. + +This exception pushes an error code onto the stack. The EXT bit of the +error code is set if an event external to the program caused an interrupt +that subsequently referenced a not-present segment. The I-bit is set if the +error code refers to an IDT entry, e.g., an INT instruction referencing a +not-present gate. + +An operating system typically uses the "segment not present" exception to +implement virtual memory at the segment level. A not-present indication in a +gate descriptor, however, usually does not indicate that a segment is not +present (because gates do not necessarily correspond to segments). +Not-present gates may be used by an operating system to trigger exceptions +of special significance to the operating system. + + +9.8.12 Interrupt 12 Stack Exception + +A stack fault occurs in either of two general conditions: + + As a result of a limit violation in any operation that refers to the + SS register. This includes stack-oriented instructions such as POP, + PUSH, ENTER, and LEAVE, as well as other memory references that + implicitly use SS (for example, MOV AX, [BP+6]). ENTER causes this + exception when the stack is too small for the indicated local-variable + space. + + When attempting to load the SS register with a descriptor that is + marked not-present but is otherwise valid. This can occur in a task + switch, an interlevel CALL, an interlevel return, an LSS instruction, + or a MOV or POP instruction to SS. + +When the processor detects a stack exception, it pushes an error code onto +the stack of the exception handler. If the exception is due to a not-present +stack segment or to overflow of the new stack during an interlevel CALL, the +error code contains a selector to the segment in question (the exception +handler can test the present bit in the descriptor to determine which +exception occurred); otherwise the error code is zero. + +An instruction that causes this fault is restartable in all cases. The +return pointer pushed onto the exception handler's stack points to the +instruction that needs to be restarted. This instruction is usually the one +that caused the exception; however, in the case of a stack exception due to +loading of a not-present stack-segment descriptor during a task switch, the +indicated instruction is the first instruction of the new task. + +When a stack fault occurs during a task switch, the segment registers may +not be usable for referencing memory. During a task switch, the selector +values are loaded before the descriptors are checked. If a stack fault is +discovered, the remaining segment registers have not been checked and +therefore may not be usable for referencing memory. The stack fault handler +should not rely on being able to use the values found in CS, SS, DS, ES, +FS, and GS without causing another exception. The exception handler should +check all segment registers before trying to resume the new task; otherwise, +general protection faults may result later under conditions that make +diagnosis more difficult. + + +9.8.13 Interrupt 13 General Protection Exception + +All protection violations that do not cause another exception cause a +general protection exception. This includes (but is not limited to): + + 1. Exceeding segment limit when using CS, DS, ES, FS, or GS + + 2. Exceeding segment limit when referencing a descriptor table + + 3. Transferring control to a segment that is not executable + + 4. Writing into a read-only data segment or into a code segment + + 5. Reading from an execute-only segment + + 6. Loading the SS register with a read-only descriptor (unless the + selector comes from the TSS during a task switch, in which case a TSS + exception occurs + + 7. Loading SS, DS, ES, FS, or GS with the descriptor of a system segment + + 8. Loading DS, ES, FS, or GS with the descriptor of an executable + segment that is not also readable + + 9. Loading SS with the descriptor of an executable segment + + 10. Accessing memory via DS, ES, FS, or GS when the segment register + contains a null selector + + 11. Switching to a busy task + + 12. Violating privilege rules + + 13. Loading CR0 with PG=1 and PE=0. + + 14. Interrupt or exception via trap or interrupt gate from V86 mode to + privilege level other than zero. + + 15. Exceeding the instruction length limit of 15 bytes (this can occur + only if redundant prefixes are placed before an instruction) + +The general protection exception is a fault. In response to a general +protection exception, the processor pushes an error code onto the exception +handler's stack. If loading a descriptor causes the exception, the error +code contains a selector to the descriptor; otherwise, the error code is +null. The source of the selector in an error code may be any of the +following: + + 1. An operand of the instruction. + 2. A selector from a gate that is the operand of the instruction. + 3. A selector from a TSS involved in a task switch. + + +9.8.14 Interrupt 14 Page Fault + +This exception occurs when paging is enabled (PG=1) and the processor +detects one of the following conditions while translating a linear address +to a physical address: + + The page-directory or page-table entry needed for the address + translation has zero in its present bit. + + The current procedure does not have sufficient privilege to access the + indicated page. + +The processor makes available to the page fault handler two items of +information that aid in diagnosing the exception and recovering from it: + + An error code on the stack. The error code for a page fault has a + format different from that for other exceptions (see Figure 9-8). The + error code tells the exception handler three things: + + 1. Whether the exception was due to a not present page or to an access + rights violation. + + 2. Whether the processor was executing at user or supervisor level at + the time of the exception. + + 3. Whether the memory access that caused the exception was a read or + write. + + CR2 (control register two). The processor stores in CR2 the linear + address used in the access that caused the exception (see Figure 9-9). + The exception handler can use this address to locate the corresponding + page directory and page table entries. If another page fault can occur + during execution of the page fault handler, the handler should push CR2 + onto the stack. + + +Figure 9-8. Page-Fault Error Code Format + + ͻ + FieldValue Description + Ķ + U/S 0 The access causing the fault originated when the processor + was executing in supervisor mode. + + 1 The access causing the fault originated when the processor + was executing in user mode. + + W/R 0 The access causing the fault was a read. + + 1 The access causing the fault was a write. + + P 0 The fault was caused by a not-present page. + + 1 The fault was caused by a page-level protection violation. + ͼ + + 31 15 7 3 2 1 0 + ͻ + UW + UNDEFINED//P + SR + ͼ + + +9.8.14.1 Page Fault During Task Switch + +The processor may access any of four segments during a task switch: + + 1. Writes the state of the original task in the TSS of that task. + + 2. Reads the GDT to locate the TSS descriptor of the new task. + + 3. Reads the TSS of the new task to check the types of segment + descriptors from the TSS. + + 4. May read the LDT of the new task in order to verify the segment + registers stored in the new TSS. + +A page fault can result from accessing any of these segments. In the latter +two cases the exception occurs in the context of the new task. The +instruction pointer refers to the next instruction of the new task, not to +the instruction that caused the task switch. If the design of the operating +system permits page faults to occur during task-switches, the page-fault +handler should be invoked via a task gate. + + +Figure 9-9. CR2 Format + + 31 23 15 7 0 + ͻ + + PAGE FAULT LINEAR ADDRESS + + ͼ + + +9.8.14.2 Page Fault with Inconsistent Stack Pointer + +Special care should be taken to ensure that a page fault does not cause the +processor to use an invalid stack pointer (SS:ESP). Software written for +earlier processors in the 8086 family often uses a pair of instructions to +change to a new stack; for example: + +MOV SS, AX +MOV SP, StackTop + +With the 80386, because the second instruction accesses memory, it is +possible to get a page fault after SS has been changed but before SP has +received the corresponding change. At this point, the two parts of the stack +pointer SS:SP (or, for 32-bit programs, SS:ESP) are inconsistent. + +The processor does not use the inconsistent stack pointer if the handling +of the page fault causes a stack switch to a well defined stack (i.e., the +handler is a task or a more privileged procedure). However, if the page +fault handler is invoked by a trap or interrupt gate and the page fault +occurs at the same privilege level as the page fault handler, the processor +will attempt to use the stack indicated by the current (invalid) stack +pointer. + +In systems that implement paging and that handle page faults within the +faulting task (with trap or interrupt gates), software that executes at the +same privilege level as the page fault handler should initialize a new stack +by using the new LSS instruction rather than an instruction pair shown +above. When the page fault handler executes at privilege level zero (the +normal case), the scope of the problem is limited to privilege-level zero +code, typically the kernel of the operating system. + + +9.8.15 Interrupt 16 Coprocessor Error + +The 80386 reports this exception when it detects a signal from the 80287 or +80387 on the 80386's ERROR# input pin. The 80386 tests this pin only at the +beginning of certain ESC instructions and when it encounters a WAIT +instruction while the EM bit of the MSW is zero (no emulation). Refer to +Chapter 11 for more information on the coprocessor interface. + + +9.9 Exception Summary + + +Table 9-6 summarizes the exceptions recognized by the 386. + +Table 9-6. Exception Summary + + +Description Interrupt Return Address Exception Function That Can Generate + Number Points to Type the Exception + Faulting + Instruction + +Divide error 0 YES FAULT DIV, IDIV +Debug exceptions 1 +Some debug exceptions are traps and some are faults. The exception +handler can determine which has occurred by examining DR6. (Refer to +Chapter 12.) +Some debug exceptions are traps and some are faults. The exception +handler can determine which has occurred by examining DR6. (Refer to +Chapter 12.) Any instruction +Breakpoint 3 NO TRAP One-byte INT 3 +Overflow 4 NO TRAP INTO +Bounds check 5 YES FAULT BOUND +Invalid opcode 6 YES FAULT Any illegal instruction +Coprocessor not available 7 YES FAULT ESC, WAIT +Double fault 8 YES ABORT Any instruction that can + generate an exception +Coprocessor Segment +Overrun 9 NO ABORT Any operand of an ESC + instruction that wraps around + the end of a segment. +Invalid TSS 10 YES FAULT +An invalid-TSS fault is not restartable if it occurs during the +processing of an external interrupt. JMP, CALL, IRET, any interrupt +Segment not present 11 YES FAULT Any segment-register modifier +Stack exception 12 YES FAULT Any memory reference thru SS +General Protection 13 YES FAULT/ABORT +All GP faults are restartable. If the fault occurs while attempting to +vector to the handler for an external interrupt, the interrupted program is +restartable, but the interrupt may be lost. Any memory reference or code + fetch +Page fault 14 YES FAULT Any memory reference or code + fetch +Coprocessor error 16 YES FAULT +Coprocessor errors are reported as a fault on the first ESC or WAIT +instruction executed after the ESC instruction that caused the error. ESC, WAIT +Two-byte SW Interrupt 0-255 NO TRAP INT n + + +9.10 Error Code Summary + +Table 9-7 summarizes the error information that is available with each +exception. + + +Table 9-7. Error-Code Summary + +Description Interrupt Error Code + Number + +Divide error 0 No +Debug exceptions 1 No +Breakpoint 3 No +Overflow 4 No +Bounds check 5 No +Invalid opcode 6 No +Coprocessor not available 7 No +System error 8 Yes (always 0) +Coprocessor Segment Overrun 9 No +Invalid TSS 10 Yes +Segment not present 11 Yes +Stack exception 12 Yes +General protection fault 13 Yes +Page fault 14 Yes +Coprocessor error 16 No +Two-byte SW interrupt 0-255 No + + +Chapter 10 Initialization + + + +After a signal on the RESET pin, certain registers of the 80386 are set to +predefined values. These values are adequate to enable execution of a +bootstrap program, but additional initialization must be performed by +software before all the features of the processor can be utilized. + + +10.1 Processor State After Reset + +The contents of EAX depend upon the results of the power-up self test. The +self-test may be requested externally by assertion of BUSY# at the end of +RESET. The EAX register holds zero if the 80386 passed the test. A nonzero +value in EAX after self-test indicates that the particular 80386 unit is +faulty. If the self-test is not requested, the contents of EAX after RESET +is undefined. + +DX holds a component identifier and revision number after RESET as Figure +10-1 illustrates. DH contains 3, which indicates an 80386 component. DL +contains a unique identifier of the revision level. + +Control register zero (CR0) contains the values shown in Figure 10-2. The +ET bit of CR0 is set if an 80387 is present in the configuration (according +to the state of the ERROR# pin after RESET). If ET is reset, the +configuration either contains an 80287 or does not contain a coprocessor. A +software test is required to distinguish between these latter two +possibilities. + +The remaining registers and flags are set as follows: + + EFLAGS =00000002H + IP =0000FFF0H + CS selector =000H + DS selector =0000H + ES selector =0000H + SS selector =0000H + FS selector =0000H + GS selector =0000H + IDTR: + base =0 + limit =03FFH + +All registers not mentioned above are undefined. + +These settings imply that the processor begins in real-address mode with +interrupts disabled. + + +Figure 10-1. Contents of EDX after RESET + + EDX REGISTER + + 31 23 15 7 0 + ͻ + DH DL + UNDEFINED DEVICE ID STEPPING ID + 3 (UNIQUE) + ͼ + + +Figure 10-2. Initial Contents of CR0 + + CONTROL REGISTER ZERO + + 31 23 15 7 4 3 1 0 + ͻ + P ETEMP + UNDEFINED + G TSMPE + Ѽ + + 0 - PAGING DISABLED + * - INDICATES PRESENCE OF 80387 + 0 - NO TASK SWITCH + 0 - DO NOT MONITOR COPROCESSOR + 0 - COPROCESSOR NOT PRESENT + 0 - PROTECTION NOT ENABLED (REAL ADDRESS MODE) + + +10.2 Software Initialization for Real-Address Mode + +In real-address mode a few structures must be initialized before a program +can take advantage of all the features available in this mode. + + +10.2.1 Stack + +No instructions that use the stack can be used until the stack-segment +register (SS) has been loaded. SS must point to an area in RAM. + + +10.2.2 Interrupt Table + +The initial state of the 80386 leaves interrupts disabled; however, the +processor will still attempt to access the interrupt table if an exception +or nonmaskable interrupt (NMI) occurs. Initialization software should take +one of the following actions: + + Change the limit value in the IDTR to zero. This will cause a shutdown + if an exception or nonmaskable interrupt occurs. (Refer to the 80386 + Hardware Reference Manual to see how shutdown is signalled externally.) + + Put pointers to valid interrupt handlers in all positions of the + interrupt table that might be used by exceptions or interrupts. + + Change the IDTR to point to a valid interrupt table. + + +10.2.3 First Instructions + +After RESET, address lines A{31-20} are automatically asserted for +instruction fetches. This fact, together with the initial values of CS:IP, +causes instruction execution to begin at physical address FFFFFFF0H. Near +(intrasegment) forms of control transfer instructions may be used to pass +control to other addresses in the upper 64K bytes of the address space. The +first far (intersegment) JMP or CALL instruction causes A{31-20} to drop +low, and the 80386 continues executing instructions in the lower one +megabyte of physical memory. This automatic assertion of address lines +A{31-20} allows systems designers to use a ROM at the high end of +the address space to initialize the system. + + +10.3 Switching to Protected Mode + +Setting the PE bit of the MSW in CR0 causes the 80386 to begin executing in +protected mode. The current privilege level (CPL) starts at zero. The +segment registers continue to point to the same linear addresses as in real +address mode (in real address mode, linear addresses are the same physical +addresses). + +Immediately after setting the PE flag, the initialization code must flush +the processor's instruction prefetch queue by executing a JMP instruction. +The 80386 fetches and decodes instructions and addresses before they are +used; however, after a change into protected mode, the prefetched +instruction information (which pertains to real-address mode) is no longer +valid. A JMP forces the processor to discard the invalid information. + + +10.4 Software Initialization for Protected Mode + +Most of the initialization needed for protected mode can be done either +before or after switching to protected mode. If done in protected mode, +however, the initialization procedures must not use protected-mode features +that are not yet initialized. + + +10.4.1 Interrupt Descriptor Table + +The IDTR may be loaded in either real-address or protected mode. However, +the format of the interrupt table for protected mode is different than that +for real-address mode. It is not possible to change to protected mode and +change interrupt table formats at the same time; therefore, it is inevitable +that, if IDTR selects an interrupt table, it will have the wrong format at +some time. An interrupt or exception that occurs at this time will have +unpredictable results. To avoid this unpredictability, interrupts should +remain disabled until interrupt handlers are in place and a valid IDT has +been created in protected mode. + + +10.4.2 Stack + +The SS register may be loaded in either real-address mode or protected +mode. If loaded in real-address mode, SS continues to point to the same +linear base-address after the switch to protected mode. + + +10.4.3 Global Descriptor Table + +Before any segment register is changed in protected mode, the GDT register +must point to a valid GDT. Initialization of the GDT and GDTR may be done in +real-address mode. The GDT (as well as LDTs) should reside in RAM, because +the processor modifies the accessed bit of descriptors. + + +10.4.4 Page Tables + +Page tables and the PDBR in CR3 can be initialized in either real-address +mode or in protected mode; however, the paging enabled (PG) bit of CR0 +cannot be set until the processor is in protected mode. PG may be set +simultaneously with PE, or later. When PG is set, the PDBR in CR3 should +already be initialized with a physical address that points to a valid page +directory. The initialization procedure should adopt one of the following +strategies to ensure consistent addressing before and after paging is +enabled: + + The page that is currently being executed should map to the same + physical addresses both before and after PG is set. + + A JMP instruction should immediately follow the setting of PG. + + +10.4.5 First Task + +The initialization procedure can run awhile in protected mode without +initializing the task register; however, before the first task switch, the +following conditions must prevail: + + There must be a valid task state segment (TSS) for the new task. The + stack pointers in the TSS for privilege levels numerically less than or + equal to the initial CPL must point to valid stack segments. + + The task register must point to an area in which to save the current + task state. After the first task switch, the information dumped in this + area is not needed, and the area can be used for other purposes. + + +10.5 Initialization Example + +$TITLE ('Initial Task') + + NAME INIT + +init_stack SEGMENT RW + DW 20 DUP(?) +tos LABEL WORD +init_stack ENDS + +init_data SEGMENT RW PUBLIC + DW 20 DUP(?) +init_data ENDS + +init_code SEGMENT ER PUBLIC + +ASSUME DS:init_data + + nop + nop + nop +init_start: + ; set up stack + mov ax, init_stack + mov ss, ax + mov esp, offset tos + + mov a1,1 +blink: + xor a1,1 + out 0e4h,a1 + mov cx,3FFFh +here: + dec cx + jnz here + + jmp SHORT blink + + hlt +init_code ends + + END init_start, SS:init_stack, DS:init_data + +$TITLE('Protected Mode Transition -- 386 initialization') +NAME RESET + +;***************************************************************** +; Upon reset the 386 starts executing at address 0FFFFFFF0H. The +; upper 12 address bits remain high until a FAR call or jump is +; executed. +; +; Assume the following: +; +; +; - a short jump at address 0FFFFFFF0H (placed there by the +; system builder) causes execution to begin at START in segment +; RESET_CODE. +; +; +; - segment RESET_CODE is based at physical address 0FFFF0000H, +; i.e. at the start of the last 64K in the 4G address space. +; Note that this is the base of the CS register at reset. If +; you locate ROMcode above this address, you will need to +; figure out an adjustment factor to address things within this +; segment. +; +;***************************************************************** +$EJECT ; + +; Define addresses to locate GDT and IDT in RAM. +; These addresses are also used in the BLD386 file that defines +; the GDT and IDT. If you change these addresses, make sure you +; change the base addresses specified in the build file. + +GDTbase EQU 00001000H ; physical address for GDT base +IDTbase EQU 00000400H ; physical address for IDT base + +PUBLIC GDT_EPROM +PUBLIC IDT_EPROM +PUBLIC START + +DUMMY segment rw ; ONLY for ASM386 main module stack init + DW 0 +DUMMY ends + +;***************************************************************** +; +; Note: RESET CODE must be USEl6 because the 386 initally executes +; in real mode. +; + +RESET_CODE segment er PUBLIC USE16 + +ASSUME DS:nothing, ES:nothing + +; +; 386 Descriptor template + +DESC STRUC + lim_0_15 DW 0 ; limit bits (0..15) + bas_0_15 DW 0 ; base bits (0..15) + bas_16_23 DB 0 ; base bits (16..23) + access DB 0 ; access byte + gran DB 0 ; granularity byte + bas_24_31 DB 0 ; base bits (24..31) +DESC ENDS + +; The following is the layout of the real GDT created by BLD386. +; It is located in EPROM and will be copied to RAM. +; +; GDT[O] ... NULL +; GDT[1] ... Alias for RAM GDT +; GDT[2] ... Alias for RAM IDT +; GDT[2] ... initial task TSS +; GDT[3] ... initial task TSS alias +; GDT[4] ... initial task LDT +; GDT[5] ... initial task LDT alias + +; +; define entries in GDT and IDT. + +GDT_ENTRIES EQU 8 +IDT_ENTRIES EQU 32 + +; define some constants to index into the real GDT + +GDT_ALIAS EQU 1*SIZE DESC +IDT_ALIAS EQU 2*SIZE DESC +INIT_TSS EQU 3*SIZE DESC +INIT_TSS_A EQU 4*SIZE DESC +INIT_LDT EQU 5*SIZE DESC +INIT_LDT_A EQU 6*SIZE DESC + +; +; location of alias in INIT_LDT + +INIT_LDT_ALIAS EQU 1*SIZE DESC + +; +; access rights byte for DATA and TSS descriptors + +DS_ACCESS EQU 010010010B +TSS_ACCESS EQU 010001001B + + +; +; This temporary GDT will be used to set up the real GDT in RAM. + +Temp_GDT LABEL BYTE ; tag for begin of scratch GDT + +NULL_DES DESC <> ; NULL descriptor + + ; 32-Gigabyte data segment based at 0 +FLAT_DES DESC <0FFFFH,0,0,92h,0CFh,0> + +GDT_eprom DP ? ; Builder places GDT address and limit + ; in this 6 byte area. + +IDT_eprom DP ? ; Builder places IDT address and limit + ; in this 6 byte area. + +; +; Prepare operand for loadings GDTR and LDTR. + + +TGDT_pword LABEL PWORD ; for temp GDT + DW end_Temp_GDT_Temp_GDT -1 + DD 0 + +GDT_pword LABEL PWORD ; for GDT in RAM + DW GDT_ENTRIES * SIZE DESC -1 + DD GDTbase + +IDT_pword LABEL PWORD ; for IDT in RAM + DW IDT_ENTRIES * SIZE DESC -1 + DD IDTbase + + +end_Temp_GDT LABEL BYTE + +; +; Define equates for addressing convenience. + +GDT_DES_FLAT EQU DS:GDT_ALIAS +GDTbase +IDT_DES_FLAT EQU DS:IDT_ALIAS +GDTbase + +INIT_TSS_A_OFFSET EQU DS:INIT_TSS_A +INIT_TSS_OFFSET EQU DS:INIT_TSS + +INIT_LDT_A_OFFSET EQU DS:INIT_LDT_A +INIT_LDT_OFFSET EQU DS:INIT_LDT + + +; define pointer for first task switch + +ENTRY POINTER LABEL DWORD + DW 0, INIT_TSS + +;****************************************************************** +; +; Jump from reset vector to here. + +START: + + CLI ;disable interrupts + CLD ;clear direction flag + + LIDT NULL_des ;force shutdown on errors + +; +; move scratch GDT to RAM at physical 0 + + XOR DI,DI + MOV ES,DI ;point ES:DI to physical location 0 + + + MOV SI,OFFSET Temp_GDT + MOV CX,end_Temp_GDT-Temp_GDT ;set byte count + INC CX +; +; move table + + REP MOVS BYTE PTR ES:[DI],BYTE PTR CS:[SI] + + LGDT tGDT_pword ;load GDTR for Temp. GDT + ;(located at 0) + +; switch to protected mode + + MOV EAX,CR0 ;get current CRO + MOV EAX,1 ;set PE bit + MOV CRO,EAX ;begin protected mode +; +; clear prefetch queue + + JMP SHORT flush +flush: + +; set DS,ES,SS to address flat linear space (0 ... 4GB) + + MOV BX,FLAT_DES-Temp_GDT + MOV US,BX + MOV ES,BX + MOV SS,BX +; +; initialize stack pointer to some (arbitrary) RAM location + + MOV ESP, OFFSET end_Temp_GDT + +; +; copy eprom GDT to RAM + + MOV ESI,DWORD PTR GDT_eprom +2 ; get base of eprom GDT + ; (put here by builder). + + MOV EDI,GDTbase ; point ES:EDI to GDT base in RAM. + + MOV CX,WORD PTR gdt_eprom +0 ; limit of eprom GDT + INC CX + SHR CX,1 ; easier to move words + CLD + REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] + +; +; copy eprom IDT to RAM +; + MOV ESI,DWORD PTR IDT_eprom +2 ; get base of eprom IDT + ; (put here by builder) + + MOV EDI,IDTbase ; point ES:EDI to IDT base in RAM. + + MOV CX,WORD PTR idt_eprom +0 ; limit of eprom IDT + INC CX + SHR CX,1 + CLD + REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] + +; switch to RAM GDT and IDT +; + LIDT IDT_pword + LGDT GDT_pword + +; + MOV BX,GDT_ALIAS ; point DS to GDT alias + MOV DS,BX +; +; copy eprom TSS to RAM +; + MOV BX,INIT_TSS_A ; INIT TSS A descriptor base + ; has RAM location of INIT TSS. + + MOV ES,BX ; ES points to TSS in RAM + + MOV BX,INIT_TSS ; get inital task selector + LAR DX,BX ; save access byte + MOV [BX].access,DS_ACCESS ; set access as data segment + MOV FS,BX ; FS points to eprom TSS + + XOR si,si ; FS:si points to eprom TSS + XOR di,di ; ES:di points to RAM TSS + + MOV CX,[BX].lim_0_15 ; get count to move + INC CX + +; +; move INIT_TSS to RAM. + + REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si] + + MOV [BX].access,DH ; restore access byte + +; +; change base of INIT TSS descriptor to point to RAM. + + MOV AX,INIT_TSS_A_OFFSET.bas_0_15 + MOV INIT_TSS_OFFSET.bas_0_15,AX + MOV AL,INIT_TSS_A_OFFSET.bas_16_23 + MOV INIT_TSS_OFFSET.bas_16_23,AL + MOV AL,INIT_TSS_A_OFFSET.bas_24_31 + MOV INIT_TSS_OFFSET.bas_24_31,AL + +; +; change INIT TSS A to form a save area for TSS on first task +; switch. Use RAM at location 0. + + MOV BX,INIT_TSS_A + MOV WORD PTR [BX].bas_0_15,0 + MOV [BX].bas_16_23,0 + MOV [BX].bas_24_31,0 + MOV [BX].access,TSS_ACCESS + MOV [BX].gran,O + LTR BX ; defines save area for TSS + +; +; copy eprom LDT to RAM + + MOV BX,INIT_LDT_A ; INIT_LDT_A descriptor has + ; base address in RAM for INIT_LDT. + + MOV ES,BX ; ES points LDT location in RAM. + + MOV AH,[BX].bas_24_31 + MOV AL,[BX].bas_16_23 + SHL EAX,16 + MOV AX,[BX].bas_0_15 ; save INIT_LDT base (ram) in EAX + + MOV BX,INIT_LDT ; get inital LDT selector + LAR DX,BX ; save access rights + MOV [BX].access,DS_ACCESS ; set access as data segment + MOV FS,BX ; FS points to eprom LDT + + XOR si,si ; FS:SI points to eprom LDT + XOR di,di ; ES:DI points to RAM LDT + + MOV CX,[BX].lim_0_15 ; get count to move + INC CX +; +; move initial LDT to RAM + + REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si] + + MOV [BX].access,DH ; restore access rights in + ; INIT_LDT descriptor + +; +; change base of alias (of INIT_LDT) to point to location in RAM. + + MOV ES:[INIT_LDT_ALIAS].bas_0_15,AX + SHR EAX,16 + MOV ES:[INIT_LDT_ALIAS].bas_16_23,AL + MOV ES:[INIT_LDT_ALIAS].bas_24_31,AH + +; +; now set the base value in INIT_LDT descriptor + + MOV AX,INIT_LDT_A_OFFSET.bas_0_15 + MOV INIT_LDT_OFFSET.bas_0_15,AX + MOV AL,INIT_LDT_A_OFFSET.bas_16_23 + MOV INIT_LDT_OFFSET.bas_16_23,AL + MOV AL,INIT_LDT_A_OFFSET.bas_24_31 + MOV INIT_LDT_OFFSET.bas_24_31,AL + +; +; Now GDT, IDT, initial TSS and initial LDT are all set up. +; +; Start the first task! +' + JMP ENTRY_POINTER + +RESET_CODE ends + END START, SS:DUMMY,DS:DUMMY + + +10.6 TLB Testing + +The 80386 provides a mechanism for testing the Translation Lookaside Buffer +(TLB), the cache used for translating linear addresses to physical +addresses. Although failure of the TLB hardware is extremely unlikely, users +may wish to include TLB confidence tests among other power-up confidence +tests for the 80386. + + +NOTE + This TLB testing mechanism is unique to the 80386 and may not be + continued in the same way in future processors. Sortware that uses + this mechanism may be incompatible with future processors. + + +When testing the TLB it is recommended that paging be turned off (PG=0 in +CR0) to avoid interference with the test data being written to the TLB. + + +10.6.1 Structure of the TLB + +The TLB is a four-way set-associative memory. Figure 10-3 illustrates the +structure of the TLB. There are four sets of eight entries each. Each entry +consists of a tag and data. Tags are 24-bits wide. They contain the +high-order 20 bits of the linear address, the valid bit, and three attribute +bits. The data portion of each entry contains the high-order 20 bits of the +physical address. + + +10.6.2 Test Registers + +Two test registers, shown in Figure 10-4, are provided for the purpose of +testing. TR6 is the test command register, and TR7 is the test data +register. These registers are accessed by variants of the MOV +instruction. A test register may be either the source operand or destination +operand. The MOV instructions are defined in both real-address mode and +protected mode. The test registers are privileged resources; in protected +mode, the MOV instructions that access them can only be executed at +privilege level 0. An attempt to read or write the test registers when +executing at any other privilege level causes a general +protection exception. + +The test command register (TR6) contains a command and an address tag to +use in performing the command: + +C This is the command bit. There are two TLB testing commands: + write entries into the TLB, and perform TLB lookups. To cause an + immediate write into the TLB entry, move a doubleword into TR6 + that contains a 0 in this bit. To cause an immediate TLB lookup, + move a doubleword into TR6 that contains a 1 in this bit. + +Linear On a TLB write, a TLB entry is allocated to this linear address; +Address the rest of that TLB entry is set per the value of TR7 and the + value just written into TR6. On a TLB lookup, the TLB is + interrogated per this value; if one and only one TLB entry + matches, the rest of the fields of TR6 and TR7 are set from the + matching TLB entry. + +V The valid bit for this TLB entry. The TLB uses the valid bit to + identify entries that contain valid data. Entries of the TLB + that have not been assigned values have zero in the valid bit. + All valid bits can be cleared by writing to CR3. + +D, D# The dirty bit (and its complement) for/from the TLB entry. + +U, U# The U/S bit (and its complement) for/from the TLB entry. + +W, W# The R/W bit (and its complement) for/from the TLB entry. + + The meaning of these pairs of bits is given by Table 10-1, + where X represents D, U, or W. + +The test data register (TR7) holds data read from or data to be written to +the TLB. + +Physical This is the data field of the TLB. On a write to the TLB, the +Address TLB entry allocated to the linear address in TR6 is set to this + value. On a TLB lookup, if HT is set, the data field (physical + address) from the TLB is read out to this field. If HT is not + set, this field is undefined. + +HT For a TLB lookup, the HT bit indicates whether the lookup was a + hit (HT  1) or a miss (HT  0). For a TLB write, HT must be set + to 1. + +REP For a TLB write, selects which of four associative blocks of the + TLB is to be written. For a TLB read, if HT is set, REP reports + in which of the four associative blocks the tag was found; if HT + is not set, REP is undefined. + + +Table 10-1. Meaning of D, U, and W Bit Pairs + +X X# Effect during Value of bit X + TLB Lookup after TLB Write + +0 0 (undefined) (undefined) +0 1 Match if X=0 Bit X becomes 0 +1 0 Match if X=1 Bit X becomes 1 +1 1 (undefined) (undefined) + + +Figure 10-3. TLB Structure + + ͻ + 7 TAG DATA + ͹ +    +    + SET 11    + ͹ + 1 TAG DATA + ͹ + 0 TAG DATA + ͼ + + ͻ + 7 TAG DATA + ͹ +    +    + SET 10    + ͹ + 1 TAG DATA + D ͹ + A 0 TAG DATA + T ͼ + A + Ŀ ͻ + B 7 TAG DATA + U ͹ + S    +    + SET 01    + ͹ + 1 TAG DATA + ͹ + 0 TAG DATA + ͼ + + ͻ + 7 TAG DATA + ͹ +    +    + SET 00    + ͹ + 1 TAG DATA + ͹ + 0 TAG DATA + ͼ + + +Figure 10-4. Test Registers + + 31 23 15 11 7 0 + ͻ + H + PHYSICAL ADDRESS 0 0 0 0 0 0 0 REP0 0 TR7 + T + Ķ + D U W + LINEAR ADDRESS VD U 0 0 0 0C TR8 + # # # + ͼ + + NOTE: 0 INDICATES INTEL RESERVED. NO NOT DEFINE + + +10.6.3 Test Operations + +To write a TLB entry: + + 1. Move a doubleword to TR7 that contains the desired physical address, + HT, and REP values. HT must contain 1. REP must point to the + associative block in which to place the entry. + + 2. Move a doubleword to TR6 that contains the appropriate linear + address, and values for V, D, U, and W. Be sure C=0 for "write" + command. + +Be careful not to write duplicate tags; the results of doing so are +undefined. + +To look up (read) a TLB entry: + + 1. Move a doubleword to TR6 that contains the appropriate linear address + and attributes. Be sure C=1 for "lookup" command. + + 2. Store TR7. If the HT bit in TR7 indicates a hit, then the other + values reveal the TLB contents. If HT indicates a miss, then the other + values in TR7 are indeterminate. + +For the purposes of testing, the V bit functions as another bit of +addresss. The V bit for a lookup request should usually be set, so that +uninitialized tags do not match. Lookups with V=0 are unpredictable if any +tags are uninitialized. + + +Chapter 11 Coprocessing and Multiprocessing + + + +The 80386 has two levels of support for multiple parallel processing units: + + A highly specialized interface for very closely coupled processors of + a type known as coprocessors. + + A more general interface for more loosely coupled processors of + unspecified type. + + +11.1 Coprocessing + +The components of the coprocessor interface include: + + ET bit of control register zero (CR0) + The EM, and MP bits of CR0 + The ESC instructions + The WAIT instruction + The TS bit of CR0 + Exceptions + + +11.1.1 Coprocessor Identification + +The 80386 is designed to operate with either an 80287 or 80387 math +coprocessor. The ET bit of CR0 indicates which type of coprocessor is +present. ET is set automatically by the 80386 after RESET according to the +level detected on the ERROR# input. If desired, ET may also be set or reset +by loading CR0 with a MOV instruction. If ET is set, the 80386 uses the +32-bit protocol of the 80387; if reset, the 80386 uses the 16-bit protocol +of the 80287. + + +11.1.2 ESC and WAIT Instructions + +The 80386 interprets the pattern 11011B in the first five bits of an +instruction as an opcode intended for a coprocessor. Instructions thus +marked are called ESCAPE or ESC instructions. The CPU performs the following +functions upon encountering an ESC instruction before sending the +instruction to the coprocessor: + + Tests the emulation mode (EM) flag to determine whether coprocessor + functions are being emulated by software. + + Tests the TS flag to determine whether there has been a context change + since the last ESC instruction. + + For some ESC instructions, tests the ERROR# pin to determine whether + the coprocessor detected an error in the previous ESC instruction. + +The WAIT instruction is not an ESC instruction, but WAIT causes the CPU to +perform some of the same tests that it performs upon encountering an ESC +instruction. The processor performs the following actions for a WAIT +instruction: + + Waits until the coprocessor no longer asserts the BUSY# pin. + + Tests the ERROR# pin (after BUSY# goes inactive). If ERROR# is active, + the 80386 signals exception 16, which indicates that the coprocessor + encountered an error in the previous ESC instruction. + + WAIT can therefore be used to cause exception 16 if an error is + pending from a previous ESC instruction. Note that, if no coprocessor + is present, the ERROR# and BUSY# pins should be tied inactive to + prevent WAIT from waiting forever or causing spurious exceptions. + + +11.1.3 EM and MP Flags + +The EM and MP flags of CR0 control how the processor reacts to coprocessor +instructions. + +The EM bit indicates whether coprocessor functions are to be emulated. If +the processor finds EM set when executing an ESC instruction, it signals +exception 7, giving the exception handler an opportunity to emulate the ESC +instruction. + +The MP (monitor coprocessor) bit indicates whether a coprocessor is +actually attached. The MP flag controls the function of the WAIT +instruction. If, when executing a WAIT instruction, the CPU finds MP set, +then it tests the TS flag; it does not otherwise test TS during a WAIT +instruction. If it finds TS set under these conditions, the CPU signals +exception 7. + +The EM and MP flags can be changed with the aid of a MOV instruction using +CR0 as the destination operand and read with the aid of a MOV instruction +with CR0 as the source operand. These forms of the MOV instruction can be +executed only at privilege level zero. + + +11.1.4 The Task-Switched Flag + +The TS bit of CR0 helps to determine when the context of the coprocessor +does not match that of the task being executed by the 80386 CPU. The 80386 +sets TS each time it performs a task switch (whether triggered by software +or by hardware interrupt). If, when interpreting one of the ESC +instructions, the CPU finds TS already set, it causes exception 7. The WAIT +instruction also causes exception 7 if both TS and MP are set. Operating +systems can use this exception to switch the context of the coprocessor to +correspond to the current task. Refer to the 80386 System Software Writer's +Guide for an example. + +The CLTS instruction (legal only at privilege level zero) resets the TS +flag. + + +11.1.5 Coprocessor Exceptions + +Three exceptions aid in interfacing to a coprocessor: interrupt 7 +(coprocessor not available), interrupt 9 (coprocessor segment overrun), and +interrupt 16 (coprocessor error). + + +11.1.5.1 Interrupt 7 Coprocessor Not Available + +This exception occurs in either of two conditions: + + 1. The CPU encounters an ESC instruction and EM is set. In this case, + the exception handler should emulate the instruction that caused the + exception. TS may also be set. + + 2. The CPU encounters either the WAIT instruction or an ESC instruction + when both MP and TS are set. In this case, the exception handler + should update the state of the coprocessor, if necessary. + + +11.1.5.2 Interrupt 9 Coprocessor Segment Overrun + +This exception occurs in protected mode under the following conditions: + + An operand of a coprocessor instruction wraps around an addressing + limit (0FFFFH for small segments, 0FFFFFFFFH for big segments, zero for + expand-down segments). An operand may wrap around an addressing limit + when the segment limit is near an addressing limit and the operand is + near the largest valid address in the segment. Because of the + wrap-around, the beginning and ending addresses of such an operand + will be near opposite ends of the segment. + + Both the first byte and the last byte of the operand (considering + wrap-around) are at addresses located in the segment and in present and + accessible pages. + + The operand spans inaccessible addresses. There are two ways that such + an operand may also span inaccessible addresses: + + 1. The segment limit is not equal to the addressing limit (e.g., + addressing limit is FFFFH and segment limit is FFFDH); therefore, + the operand will span addresses that are not within the segment + (e.g., an 8-byte operand that starts at valid offset FFFC will span + addresses FFFC-FFFF and 0000-0003; however, addresses FFFE and FFFF + are not valid, because they exceed the limit); + + 2. The operand begins and ends in present and accessible pages but + intermediate bytes of the operand fall either in a not-present page + or in a page to which the current procedure does not have access + rights. + +The address of the failing numerics instruction and data operand may be +lost; an FSTENV does not return reliable addresses. As with the 80286/80287, +the segment overrun exception should be handled by executing an FNINIT +instruction (i.e., an FINIT without a preceding WAIT). The return address on +the stack does not necessarily point to the failing instruction nor to the +following instruction. The failing numerics instruction is not restartable. + +Case 2 can be avoided by either aligning all segments on page boundaries or +by not starting them within 108 bytes of the start or end of a page. (The +maximum size of a coprocessor operand is 108 bytes.) Case 1 can be avoided +by making sure that the gap between the last valid offset and the first +valid offset of a segment is either no less than 108 bytes or is zero (i.e., +the segment is of full size). If neither software system design constraint +is acceptable, the exception handler should execute FNINIT and should +probably terminate the task. + + +11.1.5.3 Interrupt 16 Coprocessor Error + +The numerics coprocessors can detect six different exception conditions +during instruction execution. If the detected exception is not masked by a +bit in the control word, the coprocessor communicates the fact that an error +occurred to the CPU by a signal at the ERROR# pin. The CPU causes interrupt +16 the next time it checks the ERROR# pin, which is only at the beginning of +a subsequent WAIT or certain ESC instructions. If the exception is masked, +the numerics coprocessor handles the exception according to on-board logic; +it does not assert the ERROR# pin in this case. + + +11.2 General Multiprocessing + +The components of the general multiprocessing interface include: + + The LOCK# signal + + The LOCK instruction prefix, which gives programmed control of the + LOCK# signal. + + Automatic assertion of the LOCK# signal with implicit memory updates + by the processor + + +11.2.1 LOCK and the LOCK# Signal + +The LOCK instruction prefix and its corresponding output signal LOCK# can +be used to prevent other bus masters from interrupting a data movement +operation. LOCK may only be used with the following 80386 instructions when +they modify memory. An undefined-opcode exception results from using LOCK +before any instruction other than: + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + +A locked instruction is only guaranteed to lock the area of memory defined +by the destination operand, but it may lock a larger memory area. For +example, typical 8086 and 80286 configurations lock the entire physical +memory space. The area of memory defined by the destination operand is +guaranteed to be locked against access by a processor executing a locked +instruction on exactly the same memory area, i.e., an operand with +identical starting address and identical length. + +The integrity of the lock is not affected by the alignment of the memory +field. The LOCK signal is asserted for as many bus cycles as necessary to +update the entire operand. + + +11.2.2 Automatic Locking + +In several instances, the processor itself initiates activity on the data +bus. To help ensure that such activities function correctly in +multiprocessor configurations, the processor automatically asserts the LOCK# +signal. These instances include: + + Acknowledging interrupts. + + After an interrupt request, the interrupt controller uses the data bus + to send the interrupt ID of the interrupt source to the CPU. The CPU + asserts LOCK# to ensure that no other data appears on the data bus + during this time. + + Setting busy bit of TSS descriptor. + + The processor tests and sets the busy-bit in the type field of the TSS + descriptor when switching to a task. To ensure that two different + processors cannot simultaneously switch to the same task, the processor + asserts LOCK# while testing and setting this bit. + + Loading of descriptors. + + While copying the contents of a descriptor from a descriptor table into + a segment register, the processor asserts LOCK# so that the descriptor + cannot be modified by another processor while it is being loaded. For + this action to be effective, operating-system procedures that update + descriptors should adhere to the following steps: + + Use a locked update to the access-rights byte to mark the + descriptor not-present. + + Update the fields of the descriptor. (This may require several + memory accesses; therefore, LOCK cannot be used.) + + Use a locked update to the access-rights byte to mark the + descriptor present again. + + Updating page-table A and D bits. + + The processor exerts LOCK# while updating the A (accessed) and D + (dirty) bits of page-table entries. Also the processor bypasses the + page-table cache and directly updates these bits in memory. + + Executing XCHG instruction. + + The 80386 always asserts LOCK during an XCHG instruction that + references memory (even if the LOCK prefix is not used). + + +11.2.3 Cache Considerations + +Systems programmers must take care when updating shared data that may also +be stored in on-chip registers and caches. With the 80386, such shared +data includes: + + Descriptors, which may be held in segment registers. + + A change to a descriptor that is shared among processors should be + broadcast to all processors. Segment registers are effectively + "descriptor caches". A change to a descriptor will not be utilized by + another processor if that processor already has a copy of the old + version of the descriptor in a segment register. + + Page tables, which may be held in the page-table cache. + + A change to a page table that is shared among processors should be + broadcast to all processors, so that others can flush their page-table + caches and reload them with up-to-date page tables from memory. + +Systems designers can employ an interprocessor interrupt to handle the +above cases. When one processor changes data that may be cached by other +processors, it can send an interrupt signal to all other processors that may +be affected by the change. If the interrupt is serviced by an interrupt +task, the task switch automatically flushes the segment registers. The task +switch also flushes the page-table cache if the PDBR (the contents of CR3) +of the interrupt task is different from the PDBR of every other task. + +In multiprocessor systems that need a cacheability signal from the CPU, it +is recommended that physical address pin A31 be used to indicate +cacheability. Such a system can then possess up to 2 Gbytes of physical +memory. The virtual address range available to the programmer is not +affected by this convention. + + +Chapter 12 Debugging + + + +The 80386 brings to Intel's line of microprocessors significant advances in +debugging power. The single-step exception and breakpoint exception of +previous processors are still available in the 80386, but the principal +debugging support takes the form of debug registers. The debug registers +support both instruction breakpoints and data breakpoints. Data breakpoints +are an important innovation that can save hours of debugging time by +pinpointing, for example, exactly when a data structure is being +overwritten. The breakpoint registers also eliminate the complexities +associated with writing a breakpoint instruction into a code segment +(requires a data-segment alias for the code segment) or a code segment +shared by multiple tasks (the breakpoint exception can occur in the context +of any of the tasks). Breakpoints can even be set in code contained in ROM. + + +12.1 Debugging Features of the Architecture + +The features of the 80386 architecture that support debugging include: + +Reserved debug interrupt vector + +Permits processor to automatically invoke a debugger task or procedure when +an event occurs that is of interest to the debugger. + +Four debug address registers + +Permit programmers to specify up to four addresses that the CPU will +automatically monitor. + +Debug control register + +Allows programmers to selectively enable various debug conditions +associated with the four debug addresses. + +Debug status register + +Helps debugger identify condition that caused debug exception. + +Trap bit of TSS (T-bit) + +Permits monitoring of task switches. + +Resume flag (RF) of flags register + +Allows an instruction to be restarted after a debug exception without +immediately causing another debug exception due to the same condition. + +Single-step flag (TF) + +Allows complete monitoring of program flow by specifying whether the CPU +should cause a debug exception with the execution of every instruction. + +Breakpoint instruction + +Permits debugger intervention at any point in program execution and aids +debugging of debugger programs. + +Reserved interrupt vector for breakpoint exception + +Permits processor to automatically invoke a handler task or procedure upon +encountering a breakpoint instruction. + +These features make it possible to invoke a debugger that is either a +separate task or a procedure in the context of the current task. The +debugger can be invoked under any of the following kinds of conditions: + + Task switch to a specific task. + Execution of the breakpoint instruction. + Execution of every instruction. + Execution of any instruction at a given address. + Read or write of a byte, word, or doubleword at any specified address. + Write to a byte, word, or doubleword at any specified address. + Attempt to change a debug register. + + +12.2 Debug Registers + +Six 80386 registers are used to control debug features. These registers are +accessed by variants of the MOV instruction. A debug register may be either +the source operand or destination operand. The debug registers are +privileged resources; the MOV instructions that access them can only be +executed at privilege level zero. An attempt to read or write the debug +registers when executing at any other privilege level causes a general +protection exception. Figure 12-1 shows the format of the debug registers. + + +Figure 12-1. Debug Registers + + 31 23 15 7 0 + ͻ + LENR/WLENR/WLENR/WLENR/W GLGLGLGLGL + 0 000 0 0 DR7 + 3 3 2 2 1 1 0 0 EE33221100 + Ķ + BBB BBBB + 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 DR6 + TSD 3210 + Ķ + + RESERVED DR5 + + Ķ + + RESERVED DR4 + + Ķ + + BREAKPOINT 3 LINEAR ADDRESS DR3 + + Ķ + + BREAKPOINT 2 LINEAR ADDRESS DR2 + + Ķ + + BREAKPOINT 1 LINEAR ADDRESS DR1 + + Ķ + + BREAKPOINT 0 LINEAR ADDRESS DR0 + + ͼ + + +NOTE + 0 MEANS INTEL RESERVED. DO NOT DEFINE. + + + +12.2.1 Debug Address Registers (DR0-DR3) + +Each of these registers contains the linear address associated with one of +four breakpoint conditions. Each breakpoint condition is further defined by +bits in DR7. + +The debug address registers are effective whether or not paging is enabled. +The addresses in these registers are linear addresses. If paging is enabled, +the linear addresses are translated into physical addresses by the +processor's paging mechanism (as explained in Chapter 5). If paging is not +enabled, these linear addresses are the same as physical addresses. + +Note that when paging is enabled, different tasks may have different +linear-to-physical address mappings. When this is the case, an address in a +debug address register may be relevant to one task but not to another. For +this reason the 80386 has both global and local enable bits in DR7. These +bits indicate whether a given debug address has a global (all tasks) or +local (current task only) relevance. + + +12.2.2 Debug Control Register (DR7) + +The debug control register shown in Figure 12-1 both helps to define the +debug conditions and selectively enables and disables those conditions. + +For each address in registers DR0-DR3, the corresponding fields R/W0 +through R/W3 specify the type of action that should cause a breakpoint. The +processor interprets these bits as follows: + + 00 Break on instruction execution only + 01 Break on data writes only + 10 undefined + 11 Break on data reads or writes but not instruction fetches + +Fields LEN0 through LEN3 specify the length of data item to be monitored. A +length of 1, 2, or 4 bytes may be specified. The values of the length fields +are interpreted as follows: + + 00 one-byte length + 01 two-byte length + 10 undefined + 11 four-byte length + +If RWn is 00 (instruction execution), then LENn should also be 00. Any other +length is undefined. + +The low-order eight bits of DR7 (L0 through L3 and G0 through G3) +selectively enable the four address breakpoint conditions. There are two +levels of enabling: the local (L0 through L3) and global (G0 through G3) +levels. The local enable bits are automatically reset by the processor at +every task switch to avoid unwanted breakpoint conditions in the new task. +The global enable bits are not reset by a task switch; therefore, they can +be used for conditions that are global to all tasks. + +The LE and GE bits control the "exact data breakpoint match" feature of the +processor. If either LE or GE is set, the processor slows execution so that +data breakpoints are reported on the instruction that causes them. It is +recommended that one of these bits be set whenever data breakpoints are +armed. The processor clears LE at a task switch but does not clear GE. + + +12.2.3 Debug Status Register (DR6) + +The debug status register shown in Figure 12-1 permits the debugger to +determine which debug conditions have occurred. + +When the processor detects an enabled debug exception, it sets the +low-order bits of this register (B0 thru B3) before entering the debug +exception handler. Bn is set if the condition described by DRn, LENn, and +R/Wn occurs. (Note that the processor sets Bn regardless of whether Gn or +Ln is set. If more than one breakpoint condition occurs at one time and if +the breakpoint trap occurs due to an enabled condition other than n, Bn may +be set, even though neither Gn nor Ln is set.) + +The BT bit is associated with the T-bit (debug trap bit) of the TSS (refer +to 7 for the location of the T-bit). The processor sets the BT bit before +entering the debug handler if a task switch has occurred and the T-bit of +the new TSS is set. There is no corresponding bit in DR7 that enables and +disables this trap; the T-bit of the TSS is the sole enabling bit. + +The BS bit is associated with the TF (trap flag) bit of the EFLAGS +register. The BS bit is set if the debug handler is entered due to the +occurrence of a single-step exception. The single-step trap is the +highest-priority debug exception; therefore, when BS is set, any of the +other debug status bits may also be set. + +The BD bit is set if the next instruction will read or write one of the +eight debug registers and ICE-386 is also using the debug registers at the +same time. + +Note that the bits of DR6 are never cleared by the processor. To avoid any +confusion in identifying the next debug exception, the debug handler should +move zeros to DR6 immediately before returning. + + +12.2.4 Breakpoint Field Recognition + +The linear address and LEN field for each of the four breakpoint conditions +define a range of sequential byte addresses for a data breakpoint. The LEN +field permits specification of a one-, two-, or four-byte field. Two-byte +fields must be aligned on word boundaries (addresses that are multiples of +two) and four-byte fields must be aligned on doubleword boundaries +(addresses that are multiples of four). These requirements are enforced by +the processor; it uses the LEN bits to mask the low-order bits of the +addresses in the debug address registers. Improperly aligned code or data +breakpoint addresses will not yield the expected results. + +A data read or write breakpoint is triggered if any of the bytes +participating in a memory access is within the field defined by a breakpoint +address register and the corresponding LEN field. Table 12-1 gives some +examples of breakpoint fields with memory references that both do and do not +cause traps. + +To set a data breakpoint for a misaligned field longer than one byte, it +may be desirable to put two sets of entries in the breakpoint register such +that each entry is properly aligned and the two entries together span the +length of the field. + +Instruction breakpoint addresses must have a length specification of one +byte (LEN = 00); other values are undefined. The processor recognizes an +instruction breakpoint address only when it points to the first byte of an +instruction. If the instruction has any prefixes, the breakpoint address +must point to the first prefix. + + +Table 12-1. Breakpoint Field Recognition Examples + + Address (hex) Length + + DR0 0A0001 1 (LEN0 = 00) +Register Contents DR1 0A0002 1 (LEN1 = 00) + DR2 0B0002 2 (LEN2 = 01) + DR3 0C0000 4 (LEN3 = 11) + +Some Examples of Memory 0A0001 1 +References That Cause Traps 0A0002 1 + 0A0001 2 + 0A0002 2 + 0B0002 2 + 0B0001 4 + 0C0000 4 + 0C0001 2 + 0C0003 1 + +Some Examples of Memory 0A0000 1 +References That Don't Cause Traps 0A0003 4 + 0B0000 2 + 0C0004 4 + + +12.3 Debug Exceptions + +Two of the interrupt vectors of the 80386 are reserved for exceptions that +relate to debugging. Interrupt 1 is the primary means of invoking debuggers +designed expressly for the 80386; interrupt 3 is intended for debugging +debuggers and for compatibility with prior processors in Intel's 8086 +processor family. + + +12.3.1 Interrupt 1 Debug Exceptions + +The handler for this exception is usually a debugger or part of a debugging +system. The processor causes interrupt 1 for any of several conditions. The +debugger can check flags in DR6 and DR7 to determine what condition caused +the exception and what other conditions might be in effect at the same time. +Table 12-2 associates with each breakpoint condition the combination of +bits that indicate when that condition has caused the debug exception. + +Instruction address breakpoint conditions are faults, while other debug +conditions are traps. The debug exception may report either or both at one +time. The following paragraphs present details for each class of debug +exception. + + +Table 12-2. Debug Exception Conditions + +Flags to Test Condition + +BS=1 Single-step trap +B0=1 AND (GE0=1 OR LE0=1) Breakpoint DR0, LEN0, R/W0 +B1=1 AND (GE1=1 OR LE1=1) Breakpoint DR1, LEN1, R/W1 +B2=1 AND (GE2=1 OR LE2=1) Breakpoint DR2, LEN2, R/W2 +B3=1 AND (GE3=1 OR LE3=1) Breakpoint DR3, LEN3, R/W3 +BD=1 Debug registers not available; in use by ICE-386. +BT=1 Task switch + + +12.3.1.1 Instruction Addrees Breakpoint + +The processor reports an instruction-address breakpoint before it executes +the instruction that begins at the given address; i.e., an instruction- +address breakpoint exception is a fault. + +The RF (restart flag) permits the debug handler to retry instructions that +cause other kinds of faults in addition to debug faults. When it detects a +fault, the processor automatically sets RF in the flags image that it pushes +onto the stack. (It does not, however, set RF for traps and aborts.) + +When RF is set, it causes any debug fault to be ignored during the next +instruction. (Note, however, that RF does not cause breakpoint traps to be +ignored, nor other kinds of faults.) + +The processor automatically clears RF at the successful completion of every +instruction except after the IRET instruction, after the POPF instruction, +and after a JMP, CALL, or INT instruction that causes a task switch. These +instructions set RF to the value specified by the memory image of the EFLAGS +register. + +The processor automatically sets RF in the EFLAGS image on the stack before +entry into any fault handler. Upon entry into the fault handler for +instruction address breakpoints, for example, RF is set in the EFLAGS image +on the stack; therefore, the IRET instruction at the end of the handler will +set RF in the EFLAGS register, and execution will resume at the breakpoint +address without generating another breakpoint fault at the same address. + +If, after a debug fault, RF is set and the debug handler retries the +faulting instruction, it is possible that retrying the instruction will +raise other faults. The retry of the instruction after these faults will +also be done with RF=1, with the result that debug faults continue to be +ignored. The processor clears RF only after successful completion of the +instruction. + +Real-mode debuggers can control the RF flag by using a 32-bit IRET. A +16-bit IRET instruction does not affect the RF bit (which is in the +high-order 16 bits of EFLAGS). To use a 32-bit IRET, the debugger must +rearrange the stack so that it holds appropriate values for the 32-bit EIP, +CS, and EFLAGS (with RF set in the EFLAGS image). Then executing an IRET +with an operand size prefix causes a 32-bit return, popping the RF flag +into EFLAGS. + + +12.3.1.2 Data Address Breakpoint + +A data-address breakpoint exception is a trap; i.e., the processor reports +a data-address breakpoint after executing the instruction that accesses the +given memory item. + +When using data breakpoints it is recommended that either the LE or GE bit +of DR7 be set also. If either LE or GE is set, any data breakpoint trap is +reported exactly after completion of the instruction that accessed the +specified memory item. This exact reporting is accomplished by forcing the +80386 execution unit to wait for completion of data operand transfers before +beginning execution of the next instruction. If neither GE nor LE is set, +data breakpoints may not be reported until one instruction after the data is +accessed or may not be reported at all. This is due to the fact that, +normally, instruction execution is overlapped with memory transfers to such +a degree that execution of the next instruction may begin before memory +transfers for the prior instruction are completed. + +If a debugger needs to preserve the contents of a write breakpoint +location, it should save the original contents before setting a write +breakpoint. Because data breakpoints are traps, a write into a breakpoint +location will complete before the trap condition is reported. The handler +can report the saved value after the breakpoint is triggered. The data in +the debug registers can be used to address the new value stored by the +instruction that triggered the breakpoint. + + +12.3.1.3 General Detect Fault + +This exception occurs when an attempt is made to use the debug registers at +the same time that ICE-386 is using them. This additional protection feature +is provided to guarantee that ICE-386 can have full control over the +debug-register resources when required. ICE-386 uses the debug-registers; +therefore, a software debugger that also uses these registers cannot run +while ICE-386 is in use. The exception handler can detect this condition by +examining the BD bit of DR6. + + +12.3.1.4 Single-Step Trap + +This debug condition occurs at the end of an instruction if the trap flag +(TF) of the flags register held the value one at the beginning of that +instruction. Note that the exception does not occur at the end of an +instruction that sets TF. For example, if POPF is used to set TF, a +single-step trap does not occur until after the instruction that follows +POPF. + +The processor clears the TF bit before invoking the handler. If TF=1 in +the flags image of a TSS at the time of a task switch, the exception occurs +after the first instruction is executed in the new task. + +The single-step flag is normally not cleared by privilege changes inside a +task. INT instructions, however, do clear TF. Therefore, software +debuggers that single-step code must recognize and emulate INT n or INTO +rather than executing them directly. + +To maintain protection, system software should check the current execution +privilege level after any single step interrupt to see whether single +stepping should continue at the current privilege level. + +The interrupt priorities in hardware guarantee that if an external +interrupt occurs, single stepping stops. When both an external interrupt and +a single step interrupt occur together, the single step interrupt is +processed first. This clears the TF bit. After saving the return address or +switching tasks, the external interrupt input is examined before the first +instruction of the single step handler executes. If the external interrupt +is still pending, it is then serviced. The external interrupt handler is not +single-stepped. To single step an interrupt handler, just single step an INT +n instruction that refers to the interrupt handler. + + +12.3.1.5 Task Switch Breakpoint + +The debug exception also occurs after a switch to an 80386 task if the +T-bit of the new TSS is set. The exception occurs after control has passed +to the new task, but before the first instruction of that task is executed. +The exception handler can detect this condition by examining the BT bit of +the debug status register DR6. + +Note that if the debug exception handler is a task, the T-bit of its TSS +should not be set. Failure to observe this rule will cause the processor to +enter an infinite loop. + + +12.3.2 Interrupt 3 Breakpoint Exception + +This exception is caused by execution of the breakpoint instruction INT 3. +Typically, a debugger prepares a breakpoint by substituting the opcode of +the one-byte breakpoint instruction in place of the first opcode byte of the +instruction to be trapped. When execution of the INT 3 instruction causes +the exception handler to be invoked, the saved value of ES:EIP points to the +byte following the INT 3 instruction. + +With prior generations of processors, this feature is used extensively for +trapping execution of specific instructions. With the 80386, the needs +formerly filled by this feature are more conveniently solved via the debug +registers and interrupt 1. However, the breakpoint exception is still +useful for debugging debuggers, because the breakpoint exception can vector +to a different exception handler than that used by the debugger. The +breakpoint exception can also be useful when it is necessary to set a +greater number of breakpoints than permitted by the debug registers. + + + PART III COMPATIBILITY + + +Chapter 13 Executing 80286 Protected-Mode Code + + + +13.1 80286 Code Executes as a Subset of the 80386 + +In general, programs designed for execution in protected mode on an 80286 +execute without modification on the 80386, because the features of the 80286 +are a subset of those of the 80386. + +All the descriptors used by the 80286 are supported by the 80386 as long as +the Intel-reserved word (last word) of the 80286 descriptor is zero. + +The descriptors for data segments, executable segments, local descriptor +tables, and task gates are common to both the 80286 and the 80386. Other +80286 descriptorsTSS segment, call gate, interrupt gate, and trap +gateare supported by the 80386. The 80386 also has new versions of +descriptors for TSS segment, call gate, interrupt gate, and trap gate that +support the 32-bit nature of the 80386. Both sets of descriptors can be +used simultaneously in the same system. + +For those descriptors that are common to both the 80286 and the 80386, the +presence of zeros in the final word causes the 80386 to interpret these +descriptors exactly as 80286 does; for example: + +Base Address The high-order eight bits of the 32-bit base address are + zero, limiting base addresses to 24 bits. + +Limit The high-order four bits of the limit field are zero, + restricting the value of the limit field to 64K. + +Granularity bit The granularity bit is zero, which implies that the value + of the 16-bit limit is interpreted in units of one byte. + +B-bit In a data-segment descriptor, the B-bit is zero, implying + that the segment is no larger than 64 Kbytes. + +D-bit In an executable-segment descriptor, the D-bit is zero, + implying that 16-bit addressing and operands are the + default. + +For formats of these descriptors and documentation of their use refer to +the iAPX 286 Programmer's Reference Manual. + + +13.2 Two ways to Execute 80286 Tasks + +When porting 80286 programs to the 80386, there are two cases to consider: + + 1. Porting an entire 80286 system to the 80386, complete with 80286 + operating system, loader, and system builder. + + In this case, all tasks will have 80286 TSSs. The 80386 is being used + as a faster 286. + + 2. Porting selected 80286 applications to run in an 80386 environment + with an 80386 operating system, loader, and system builder. + + In this case, the TSSs used to represent 80286 tasks should be + changed to 80386 TSSs. It is theoretically possible to mix 80286 and + 80386 TSSs, but the benefits are slight and the problems are great. It + is recommended that all tasks in a 80386 software system have 80386 + TSSs. It is not necessary to change the 80286 object modules + themselves; TSSs are usually constructed by the operating system, by + the loader, or by the system builder. Refer to Chapter 16 for further + discussion of the interface between 16-bit and 32-bit code. + + +13.3 Differences From 80286 + +The few differences that do exist primarily affect operating system code. + + +13.3.1 Wraparound of 80286 24-Bit Physical Address Space + +With the 80286, any base and offset combination that addresses beyond 16M +bytes wraps around to the first megabyte of the 80286 address space. With +the 80386, since it has a greater physical address space, any such address +falls into the 17th megabyte. In the unlikely event that any software +depends on this anomaly, the same effect can be simulated on the 80386 by +using paging to map the first 64K bytes of the 17th megabyte of logical +addresses to physical addresses in the first megabyte. + + +13.3.2 Reserved Word of Descriptor + +Because the 80386 uses the contents of the reserved word (last word) of +every descriptor, 80286 programs that place values in this word may not +execute correctly on the 80386. + + +13.3.3 New Descriptor Type Codes + +Operating-system code that manages space in descriptor tables often uses an +invalid value in the access-rights field of descriptor-table entries to +identify unused entries. Access rights values of 80H and 00H remain invalid +for both the 80286 and 80386. Other values that were invalid on for the +80286 may be valid for the 80386 because of the additional descriptor types +defined by the 80386. + + +13.3.4 Restricted Semantics of LOCK + +The 80286 processor implements the bus lock function differently than the +80386. Programs that use forms of memory locking specific to the 80286 may +not execute properly when transported to a specific application of the +80386. + +The LOCK prefix and its corresponding output signal should only be used to +prevent other bus masters from interrupting a data movement operation. LOCK +may only be used with the following 80386 instructions when they modify +memory. An undefined-opcode exception results from using LOCK before any +other instruction. + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + +A locked instruction is guaranteed to lock only the area of memory defined +by the destination operand, but may lock a larger memory area. For example, +typical 8086 and 80286 configurations lock the entire physical memory space. +With the 80386, the defined area of memory is guaranteed to be locked +against access by a processor executing a locked instruction on exactly the +same memory area, i.e., an operand with identical starting address and +identical length. + + +13.3.5 Additional Exceptions + +The 80386 defines new exceptions that can occur even in systems designed +for the 80286. + + Exception #6 invalid opcode + + This exception can result from improper use of the LOCK instruction. + + Exception #14 page fault + + This exception may occur in an 80286 program if the operating system + enables paging. Paging can be used in a system with 80286 tasks as long + as all tasks use the same page directory. Because there is no place in + an 80286 TSS to store the PDBR, switching to an 80286 task does not + change the value of PDBR. Tasks ported from the 80286 should be given + 80386 TSSs so they can take full advantage of paging. + + +Chapter 14 80386 Real-Address Mode + + + +The real-address mode of the 80386 executes object code designed for +execution on 8086, 8088, 80186, or 80188 processors, or for execution in the +real-address mode of an 80286: + +In effect, the architecture of the 80386 in this mode is almost identical +to that of the 8086, 8088, 80186, and 80188. To a programmer, an 80386 in +real-address mode appears as a high-speed 8086 with extensions to the +instruction set and registers. The principal features of this architecture +are defined in Chapters 2 and 3. + +This chapter discusses certain additional topics that complete the system +programmer's view of the 80386 in real-address mode: + + Address formation. + Extensions to registers and instructions. + Interrupt and exception handling. + Entering and leaving real-address mode. + Real-address-mode exceptions. + Differences from 8086. + Differences from 80286 real-address mode. + + +14.1 Physical Address Formation + +The 80386 provides a one Mbyte + 64 Kbyte memory space for an 8086 program. +Segment relocation is performed as in the 8086: the 16-bit value in a +segment selector is shifted left by four bits to form the base address of a +segment. The effective address is extended with four high order zeros and +added to the base to form a linear address as Figure 14-1 illustrates. (The +linear address is equivalent to the physical address, because paging is not +used in real-address mode.) Unlike the 8086, the resulting linear address +may have up to 21 significant bits. There is a possibility of a carry when +the base address is added to the effective address. On the 8086, the carried +bit is truncated, whereas on the 80386 the carried bit is stored in bit +position 20 of the linear address. + +Unlike the 8086 and 80286, 32-bit effective addresses can be generated (via +the address-size prefix); however, the value of a 32-bit address may not +exceed 65535 without causing an exception. For full compatibility with 80286 +real-address mode, pseudo-protection faults (interrupt 12 or 13 with no +error code) occur if an effective address is generated outside the range 0 +through 65535. + + +Figure 14-1. Real-Address Mode Address Formation + + 19 3 0 + ͻ + BASE 16-BIT SEGMENT SELECTOR 0 0 0 0 + ͼ + + + + 19 15 0 + ͻ + OFFSET 0 0 0 0 16-BIT EFFECTIVE ADDRESS + ͼ + + = + 20 0 + LINEAR ͻ + ADDRESS X X X X X X X X X X X X X X X X X X X X X X + ͼ + + +14.2 Registers and Instructions + +The register set available in real-address mode includes all the registers +defined for the 8086 plus the new registers introduced by the 80386: FS, GS, +debug registers, control registers, and test registers. New instructions +that explicitly operate on the segment registers FS and GS are available, +and the new segment-override prefixes can be used to cause instructions to +utilize FS and GS for address calculations. Instructions can utilize 32-bit +operands through the use of the operand size prefix. + +The instruction codes that cause undefined opcode traps (interrupt 6) +include instructions of the protected mode that manipulate or interrogate +80386 selectors and descriptors; namely, VERR, VERW, LAR, LSL, LTR, STR, +LLDT, and SLDT. Programs executing in real-address mode are able to take +advantage of the new applications-oriented instructions added to the +architecture by the introduction of the 80186/80188, 80286 and 80386: + + New instructions introduced by 80186/80188 and 80286. + + PUSH immediate data + Push all and pop all (PUSHA and POPA) + Multiply immediate data + Shift and rotate by immediate count + String I/O + ENTER and LEAVE + BOUND + + New instructions introduced by 80386. + + LSS, LFS, LGS instructions + Long-displacement conditional jumps + Single-bit instructions + Bit scan + Double-shift instructions + Byte set on condition + Move with sign/zero extension + Generalized multiply + MOV to and from control registers + MOV to and from test registers + MOV to and from debug registers + + +14.3 Interrupt and Exception Handling + +Interrupts and exceptions in 80386 real-address mode work as much as they +do on an 8086. Interrupts and exceptions vector to interrupt procedures via +an interrupt table. The processor multiplies the interrupt or exception +identifier by four to obtain an index into the interrupt table. The entries +of the interrupt table are far pointers to the entry points of interrupt or +exception handler procedures. When an interrupt occurs, the processor +pushes the current values of CS:IP onto the stack, disables interrupts, +clears TF (the single-step flag), then transfers control to the location +specified in the interrupt table. An IRET instruction at the end of the +handler procedure reverses these steps before returning control to the +interrupted procedure. + +The primary difference in the interrupt handling of the 80386 compared to +the 8086 is that the location and size of the interrupt table depend on the +contents of the IDTR (IDT register). Ordinarily, this fact is not apparent +to programmers, because, after RESET, the IDTR contains a base address of 0 +and a limit of 3FFH, which is compatible with the 8086. However, the LIDT +instruction can be used in real-address mode to change the base and limit +values in the IDTR. Refer to Chapter 9 for details on the IDTR, and the +LIDT and SIDT instructions. If an interrupt occurs and the corresponding +entry of the interrupt table is beyond the limit stored in the IDTR, the +processor raises exception 8. + + +14.4 Entering and Leaving Real-Address Mode + +Real-address mode is in effect after a signal on the RESET pin. Even if the +system is going to be used in protected mode, the start-up program will +execute in real-address mode temporarily while initializing for protected +mode. + + +14.4.1 Switching to Protected Mode + +The only way to leave real-address mode is to switch to protected mode. The +processor enters protected mode when a MOV to CR0 instruction sets the PE +(protection enable) bit in CR0. (For compatibility with the 80286, the LMSW +instruction may also be used to set the PE bit.) + +Refer to Chapter 10 "Initialization" for other aspects of switching to +protected mode. + + +14.5 Switching Back to Real-Address Mode + +The processor reenters real-address mode if software clears the PE bit in +CR0 with a MOV to CR0 instruction. A procedure that attempts to do this, +however, should proceed as follows: + + 1. If paging is enabled, perform the following sequence: + + Transfer control to linear addresses that have an identity mapping; + i.e., linear addresses equal physical addresses. + + Clear the PG bit in CR0. + + Move zeros to CR3 to clear out the paging cache. + + 2. Transfer control to a segment that has a limit of 64K (FFFFH). This + loads the CS register with the limit it needs to have in real mode. + + 3. Load segment registers SS, DS, ES, FS, and GS with a selector that + points to a descriptor containing the following values, which are + appropriate to real mode: + + Limit = 64K (FFFFH) + Byte granular (G = 0) + Expand up (E = 0) + Writable (W = 1) + Present (P = 1) + Base = any value + + 4. Disable interrupts. A CLI instruction disables INTR interrupts. NMIs + can be disabled with external circuitry. + + 5. Clear the PE bit. + + 6. Jump to the real mode code to be executed using a far JMP. This + action flushes the instruction queue and puts appropriate values in + the access rights of the CS register. + + 7. Use the LIDT instruction to load the base and limit of the real-mode + interrupt vector table. + + 8. Enable interrupts. + + 9. Load the segment registers as needed by the real-mode code. + + +14.6 Real-Address Mode Exceptions + +The 80386 reports some exceptions differently when executing in +real-address mode than when executing in protected mode. Table 14-1 details +the real-address-mode exceptions. + + +14.7 Differences From 8086 + +In general, the 80386 in real-address mode will correctly execute ROM-based +software designed for the 8086, 8088, 80186, and 80188. Following is a list +of the minor differences between 8086 execution on the 80386 and on an 8086. + + 1. Instruction clock counts. + + The 80386 takes fewer clocks for most instructions than the 8086/8088. + The areas most likely to be affected are: + + Delays required by I/O devices between I/O operations. + + Assumed delays with 8086/8088 operating in parallel with an 8087. + + 2. Divide Exceptions Point to the DIV instruction. + + Divide exceptions on the 80386 always leave the saved CS:IP value + pointing to the instruction that failed. On the 8086/8088, the CS:IP + value points to the next instruction. + + 3. Undefined 8086/8088 opcodes. + + Opcodes that were not defined for the 8086/8088 will cause exception + 6 or will execute one of the new instructions defined for the 80386. + + 4. Value written by PUSH SP. + + The 80386 pushes a different value on the stack for PUSH SP than the + 8086/8088. The 80386 pushes the value of SP before SP is incremented + as part of the push operation; the 8086/8088 pushes the value of SP + after it is incremented. If the value pushed is important, replace + PUSH SP instructions with the following three instructions: + + PUSH BP + MOV BP, SP + XCHG BP, [BP] + + This code functions as the 8086/8088 PUSH SP instruction on the 80386. + + 5. Shift or rotate by more than 31 bits. + + The 80386 masks all shift and rotate counts to the low-order five + bits. This MOD 32 operation limits the count to a maximum of 31 bits, + thereby limiting the time that interrupt response is delayed while + the instruction is executing. + + 6. Redundant prefixes. + + The 80386 sets a limit of 15 bytes on instruction length. The only + way to violate this limit is by putting redundant prefixes before an + instruction. Exception 13 occurs if the limit on instruction length + is violated. The 8086/8088 has no instruction length limit. + + 7. Operand crossing offset 0 or 65,535. + + On the 8086, an attempt to access a memory operand that crosses + offset 65,535 (e.g., MOV a word to offset 65,535) or offset 0 (e.g., + PUSH a word when SP = 1) causes the offset to wrap around modulo + 65,536. The 80386 raises an exception in these casesexception 13 if + the segment is a data segment (i.e., if CS, DS, ES, FS, or GS is being + used to address the segment), exception 12 if the segment is a stack + segment (i.e., if SS is being used). + + 8. Sequential execution across offset 65,535. + + On the 8086, if sequential execution of instructions proceeds past + offset 65,535, the processor fetches the next instruction byte from + offset 0 of the same segment. On the 80386, the processor raises + exception 13 in such a case. + + 9. LOCK is restricted to certain instructions. + + The LOCK prefix and its corresponding output signal should only be + used to prevent other bus masters from interrupting a data movement + operation. The 80386 always asserts the LOCK signal during an XCHG + instruction with memory (even if the LOCK prefix is not used). LOCK + may only be used with the following 80386 instructions when they + update memory: BTS, BTR, BTC, XCHG, ADD, ADC, SUB, SBB, INC, DEC, + AND, OR, XOR, NOT, and NEG. An undefined-opcode exception + (interrupt 6) results from using LOCK before any other instruction. + + 10. Single-stepping external interrupt handlers. + + The priority of the 80386 single-step exception is different from that + of the 8086/8088. The change prevents an external interrupt handler + from being single-stepped if the interrupt occurs while a program is + being single-stepped. The 80386 single-step exception has higher + priority that any external interrupt. The 80386 will still single-step + through an interrupt handler invoked by the INT instructions or by an + exception. + + 11. IDIV exceptions for quotients of 80H or 8000H. + + The 80386 can generate the largest negative number as a quotient for + the IDIV instruction. The 8086/8088 causes exception zero instead. + + 12. Flags in stack. + + The setting of the flags stored by PUSHF, by interrupts, and by + exceptions is different from that stored by the 8086 in bit positions + 12 through 15. On the 8086 these bits are stored as ones, but in + 80386 real-address mode bit 15 is always zero, and bits 14 through 12 + reflect the last value loaded into them. + + 13. NMI interrupting NMI handlers. + + After an NMI is recognized on the 80386, the NMI interrupt is masked + until an IRET instruction is executed. + + 14. Coprocessor errors vector to interrupt 16. + + Any 80386 system with a coprocessor must use interrupt vector 16 for + the coprocessor error exception. If an 8086/8088 system uses another + vector for the 8087 interrupt, both vectors should point to the + coprocessor-error exception handler. + + 15. Numeric exception handlers should allow prefixes. + + On the 80386, the value of CS:IP saved for coprocessor exceptions + points at any prefixes before an ESC instruction. On 8086/8088 + systems, the saved CS:IP points to the ESC instruction. + + 16. Coprocessor does not use interrupt controller. + + The coprocessor error signal to the 80386 does not pass through an + interrupt controller (an 8087 INT signal does). Some instructions in + a coprocessor error handler may need to be deleted if they deal with + the interrupt controller. + + 17. Six new interrupt vectors. + + The 80386 adds six exceptions that arise only if the 8086 program has + a hidden bug. It is recommended that exception handlers be added that + treat these exceptions as invalid operations. This additional + software does not significantly affect the existing 8086 software + because the interrupts do not normally occur. These interrupt + identifiers should not already have been used by the 8086 software, + because they are in the range reserved by Intel. Table 14-2 describes + the new 80386 exceptions. + + 18. One megabyte wraparound. + + The 80386 does not wrap addresses at 1 megabyte in real-address mode. + On members of the 8086 family, it possible to specify addresses + greater than one megabyte. For example, with a selector value 0FFFFH + and an offset of 0FFFFH, the effective address would be 10FFEFH (1 + Mbyte + 65519). The 8086, which can form adresses only up to 20 bits + long, truncates the high-order bit, thereby "wrapping" this address + to 0FFEFH. However, the 80386, which can form addresses up to 32 + bits long does not truncate such an address. + + +Table 14-1. 80386 Real-Address Mode Exceptions + + +Description Interrupt Function that Can Return Address + Number Generate the Exception Points to Faulting + Instruction +Divide error 0 DIV, IDIV YES +Debug exceptions 1 All +Some debug exceptions point to the faulting instruction, others to the +next instruction. The exception handler can determine which has occurred by +examining DR6. + + + + + +Breakpoint 3 INT NO +Overflow 4 INTO NO +Bounds check 5 BOUND YES +Invalid opcode 6 Any undefined opcode or LOCK YES + used with wrong instruction +Coprocessor not available 7 ESC or WAIT YES +Interrupt table limit too small 8 INT vector is not within IDTR YES + limit +Reserved 9-12 +Stack fault 12 Memory operand crosses offset YES + 0 or 0FFFFH +Pseudo-protection exception 13 Memory operand crosses offset YES + 0FFFFH or attempt to execute + past offset 0FFFFH or + instruction longer than 15 + bytes +Reserved 14,15 +Coprocessor error 16 ESC or WAIT YES +Coprocessor errors are reported on the first ESC or WAIT instruction +after the ESC instruction that caused the error. + + + + + +Two-byte SW interrupt 0-255 INT n NO + + +Table 14-2. New 80386 Exceptions + +Interrupt Function +Identifier + + 5 A BOUND instruction was executed with a register value outside + the limit values. + + 6 An undefined opcode was encountered or LOCK was used improperly + before an instruction to which it does not apply. + + 7 The EM bit in the MSW is set when an ESC instruction was + encountered. This exception also occurs on a WAIT instruction + if TS is set. + + 8 An exception or interrupt has vectored to an interrupt table + entry beyond the interrupt table limit in IDTR. This can occur + only if the LIDT instruction has changed the limit from the + default value of 3FFH, which is enough for all 256 interrupt + IDs. + + 12 Operand crosses extremes of stack segment, e.g., MOV operation + at offset 0FFFFH or push with SP=1 during PUSH, CALL, or INT. + + 13 Operand crosses extremes of a segment other than a stack + segment; or sequential instruction execution attempts to + proceed beyond offset 0FFFFH; or an instruction is longer than + 15 bytes (including prefixes). + + +14.8 Differences From 80286 Real-Address Mode + +The few differences that exist between 80386 real-address mode and 80286 +real-address mode are not likely to affect any existing 80286 programs +except possibly the system initialization procedures. + + +14.8.1 Bus Lock + +The 80286 processor implements the bus lock function differently than the +80386. Programs that use forms of memory locking specific to the 80286 may +not execute properly if transported to a specific application of the 80386. + +The LOCK prefix and its corresponding output signal should only be used to +prevent other bus masters from interrupting a data movement operation. LOCK +may only be used with the following 80386 instructions when they modify +memory. An undefined-opcode exception results from using LOCK before any +other instruction. + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + +A locked instruction is guaranteed to lock only the area of memory defined +by the destination operand, but may lock a larger memory area. For example, +typical 8086 and 80286 configurations lock the entire physical memory space. +With the 80386, the defined area of memory is guranteed to be locked against +access by a processor executing a locked instruction on exactly the same +memory area, i.e., an operand with identical starting address and identical +length. + + +14.8.2 Location of First Instruction + +The starting location is 0FFFFFFF0H (sixteen bytes from end of 32-bit +address space) on the 80386 rather than 0FFFFF0H (sixteen bytes from end of +24-bit address space) as on the 80286. Many 80286 ROM initialization +programs will work correctly in this new environment. Others can be made to +work correctly with external hardware that redefines the signals on +A{31-20}. + + +14.8.3 Initial Values of General Registers + +On the 80386, certain general registers may contain different values after +RESET than on the 80286. This should not cause compatibility problems, +because the content of 8086 registers after RESET is undefined. If +self-test is requested during the reset sequence and errors are detected in +the 80386 unit, EAX will contain a nonzero value. EDX contains the component +and revision identifier. Refer to Chapter 10 for more information. + + +14.8.4 MSW Initialization + +The 80286 initializes the MSW register to FFF0H, but the 80386 initializes +this register to 0000H. This difference should have no effect, because the +bits that are different are undefined on the 80286. Programs that read the +value of the MSW will behave differently on the 80386 only if they depend on +the setting of the undefined, high-order bits. + + +Chapter 15 Virtual 8086 Mode + + + +The 80386 supports execution of one or more 8086, 8088, 80186, or 80188 +programs in an 80386 protected-mode environment. An 8086 program runs in +this environment as part of a V86 (virtual 8086) task. V86 tasks take +advantage of the hardware support of multitasking offered by the protected +mode. Not only can there be multiple V86 tasks, each one executing an 8086 +program, but V86 tasks can be multiprogrammed with other 80386 tasks. + +The purpose of a V86 task is to form a "virtual machine" with which to +execute an 8086 program. A complete virtual machine consists not only of +80386 hardware but also of systems software. Thus, the emulation of an 8086 +is the result of cooperation between hardware and software: + + The hardware provides a virtual set of registers (via the TSS), a + virtual memory space (the first megabyte of the linear address space of + the task), and directly executes all instructions that deal with these + registers and with this address space. + + The software controls the external interfaces of the virtual machine + (I/O, interrupts, and exceptions) in a manner consistent with the + larger environment in which it executes. In the case of I/O, software + can choose either to emulate I/O instructions or to let the hardware + execute them directly without software intervention. + +Software that helps implement virtual 8086 machines is called a V86 +monitor. + + +15.1 Executing 8086 Code + +The processor executes in V86 mode when the VM (virtual machine) bit in the +EFLAGS register is set. The processor tests this flag under two general +conditions: + + 1. When loading segment registers to know whether to use 8086-style + address formation. + + 2. When decoding instructions to determine which instructions are + sensitive to IOPL. + +Except for these two modifications to its normal operations, the 80386 in +V86 mode operated much as in protected mode. + + +15.1.1 Registers and Instructions + +The register set available in V86 mode includes all the registers defined +for the 8086 plus the new registers introduced by the 80386: FS, GS, debug +registers, control registers, and test registers. New instructions that +explicitly operate on the segment registers FS and GS are available, and the +new segment-override prefixes can be used to cause instructions to utilize +FS and GS for address calculations. Instructions can utilize 32-bit +operands through the use of the operand size prefix. + +8086 programs running as V86 tasks are able to take advantage of the new +applications-oriented instructions added to the architecture by the +introduction of the 80186/80188, 80286 and 80386: + + New instructions introduced by 80186/80188 and 80286. + PUSH immediate data + Push all and pop all (PUSHA and POPA) + Multiply immediate data + Shift and rotate by immediate count + String I/O + ENTER and LEAVE + BOUND + + New instructions introduced by 80386. + LSS, LFS, LGS instructions + Long-displacement conditional jumps + Single-bit instructions + Bit scan + Double-shift instructions + Byte set on condition + Move with sign/zero extension + Generalized multiply + + +15.1.2 Linear Address Formation + +In V86 mode, the 80386 processor does not interpret 8086 selectors by +referring to descriptors; instead, it forms linear addresses as an 8086 +would. It shifts the selector left by four bits to form a 20-bit base +address. The effective address is extended with four high-order zeros and +added to the base address to create a linear address as Figure 15-1 +illustrates. + +Because of the possibility of a carry, the resulting linear address may +contain up to 21 significant bits. An 8086 program may generate linear +addresses anywhere in the range 0 to 10FFEFH (one megabyte plus +approximately 64 Kbytes) of the task's linear address space. + +V86 tasks generate 32-bit linear addresses. While an 8086 program can only +utilize the low-order 21 bits of a linear address, the linear address can be +mapped via page tables to any 32-bit physical address. + +Unlike the 8086 and 80286, 32-bit effective addresses can be generated (via +the address-size prefix); however, the value of a 32-bit address may not +exceed 65,535 without causing an exception. For full compatibility with +80286 real-address mode, pseudo-protection faults (interrupt 12 or 13 with +no error code) occur if an address is generated outside the range 0 through +65,535. + + +Figure 15-1. V86 Mode Address Formation + + 19 3 0 + ͻ + BASE 16-BIT SEGMENT SELECTOR 0 0 0 0 + ͼ + + + + 19 15 0 + ͻ + OFFSET 0 0 0 0 16-BIT EFFECTIVE ADDRESS + ͼ + + = + 20 0 + LINEAR ͻ + ADDRESS X X X X X X X X X X X X X X X X X X X X X X + ͼ + + +15.2 Structure of a V86 Task + +A V86 task consists partly of the 8086 program to be executed and partly of +80386 "native mode" code that serves as the virtual-machine monitor. The +task must be represented by an 80386 TSS (not an 80286 TSS). The processor +enters V86 mode to execute the 8086 program and returns to protected mode to +execute the monitor or other 80386 tasks. + +To run successfully in V86 mode, an existing 8086 program needs the +following: + + A V86 monitor. + Operating-system services. + +The V86 monitor is 80386 protected-mode code that executes at +privilege-level zero. The monitor consists primarily of initialization and +exception-handling procedures. As for any other 80386 program, +executable-segment descriptors for the monitor must exist in the GDT or in +the task's LDT. The linear addresses above 10FFEFH are available for the +V86 monitor, the operating system, and other systems software. The monitor +may also need data-segment descriptors so that it can examine the interrupt +vector table or other parts of the 8086 program in the first megabyte of the +address space. + +In general, there are two options for implementing the 8086 operating +system: + + 1. The 8086 operating system may run as part of the 8086 code. This + approach is desirable for any of the following reasons: + + The 8086 applications code modifies the operating system. + + There is not sufficient development time to reimplement the 8086 + operating system as 80386 code. + + 2. The 8086 operating system may be implemented or emulated in the V86 + monitor. This approach is desirable for any of the following reasons: + + Operating system functions can be more easily coordinated among + several V86 tasks. + + The functions of the 8086 operating system can be easily emulated + by calls to the 80386 operating system. + +Note that, regardless of the approach chosen for implementing the 8086 +operating system, different V86 tasks may use different 8086 operating +systems. + + +15.2.1 Using Paging for V86 Tasks + +Paging is not necessary for a single V86 task, but paging is useful or +necessary for any of the following reasons: + + To create multiple V86 tasks. Each task must map the lower megabyte of + linear addresses to different physical locations. + + To emulate the megabyte wrap. On members of the 8086 family, it is + possible to specify addresses larger than one megabyte. For example, + with a selector value of 0FFFFH and an offset of 0FFFFH, the effective + address would be 10FFEFH (one megabyte + 65519). The 8086, which can + form addresses only up to 20 bits long, truncates the high-order bit, + thereby "wrapping" this address to 0FFEFH. The 80386, however, which + can form addresses up to 32 bits long does not truncate such an + address. If any 8086 programs depend on this addressing anomaly, the + same effect can be achieved in a V86 task by mapping linear addresses + between 100000H and 110000H and linear addresses between 0 and 10000H + to the same physical addresses. + + To create a virtual address space larger than the physical address + space. + + To share 8086 OS code or ROM code that is common to several 8086 + programs that are executing simultaneously. + + To redirect or trap references to memory-mapped I/O devices. + + +15.2.2 Protection within a V86 Task + +Because it does not refer to descriptors while executing 8086 programs, the +processor also does not utilize the protection mechanisms offered by +descriptors. To protect the systems software that runs in a V86 task from +the 8086 program, software designers may follow either of these approaches: + + Reserve the first megabyte (plus 64 kilobytes) of each task's linear + address space for the 8086 program. An 8086 task cannot generate + addresses outside this range. + + Use the U/S bit of page-table entries to protect the virtual-machine + monitor and other systems software in each virtual 8086 task's space. + When the processor is in V86 mode, CPL is 3. Therefore, an 8086 program + has only user privileges. If the pages of the virtual-machine monitor + have supervisor privilege, they cannot be accessed by the 8086 program. + + +15.3 Entering and Leaving V86 Mode + +Figure 15-2 summarizes the ways that the processor can enter and leave an +8086 program. The processor can enter V86 by either of two means: + + 1. A task switch to an 80386 task loads the image of EFLAGS from the new + TSS. The TSS of the new task must be an 80386 TSS, not an 80286 TSS, + because the 80286 TSS does not store the high-order word of EFLAGS, + which contains the VM flag. A value of one in the VM bit of the new + EFLAGS indicates that the new task is executing 8086 instructions; + therefore, while loading the segment registers from the TSS, the + processor forms base addresses as the 8086 would. + + 2. An IRET from a procedure of an 80386 task loads the image of EFLAGS + from the stack. A value of one in VM in this case indicates that the + procedure to which control is being returned is an 8086 procedure. The + CPL at the time the IRET is executed must be zero, else the processor + does not change VM. + +The processor leaves V86 mode when an interrupt or exception occurs. There +are two cases: + + 1. The interrupt or exception causes a task switch. A task switch from a + V86 task to any other task loads EFLAGS from the TSS of the new task. + If the new TSS is an 80386 TSS and the VM bit in the EFLAGS image is + zero or if the new TSS is an 80286 TSS, then the processor clears the + VM bit of EFLAGS, loads the segment registers from the new TSS using + 80386-style address formation, and begins executing the instructions + of the new task according to 80386 protected-mode semantics. + + 2. The interrupt or exception vectors to a privilege-level zero + procedure. The processor stores the current setting of EFLAGS on the + stack, then clears the VM bit. The interrupt or exception handler, + therefore, executes as "native" 80386 protected-mode code. If an + interrupt or exception vectors to a conforming segment or to a + privilege level other than three, the processor causes a + general-protection exception; the error code is the selector of the + executable segment to which transfer was attempted. + +Systems software does not manipulate the VM flag directly, but rather +manipulates the image of the EFLAGS register that is stored on the stack or +in the TSS. The V86 monitor sets the VM flag in the EFLAGS image on the +stack or in the TSS when first creating a V86 task. Exception and interrupt +handlers can examine the VM flag on the stack. If the interrupted procedure +was executing in V86 mode, the handler may need to invoke the V86 monitor. + + +Figure 15-2. Entering and Leaving the 8086 Program + + MODE TRANSITION DIAGRAM + + ͻ + TASK SWITCH INITIAL + Ķ ENTRY + OR IRET ͼ + +  + ͻ INTERRUPT, EXCEPTION ͻ + 8086 PROGRAM  V86 MONITOR + (V86 MODE) Ķ (PROTECTED + ͼ IRET MODE) +  ͼ +  + + + TASK SWITCH ͻ TASK SWITCH +  OTHER 80386 TASKS  + Ķ (PROTECTED MODE) + TASK SWITCH ͼ TASK SWITCH + + +15.3.1 Transitions Through Task Switches + +A task switch to or from a V86 task may be due to any of three causes: + + 1. An interrupt that vectors to a task gate. + 2. An action of the scheduler of the 80386 operating system. + 3. An IRET when the NT flag is set. + +In any of these cases, the processor changes the VM bit in EFLAGS according +to the image of EFLAGS in the new TSS. If the new TSS is an 80286 TSS, the +high-order word of EFLAGS is not in the TSS; the processor clears VM in this +case. The processor updates VM prior to loading the segment registers from +the images in the new TSS. The new setting of VM determines whether the +processor interprets the new segment-register images as 8086 selectors or +80386/80286 selectors. + + +15.3.2 Transitions Through Trap Gates and Interrupt Gates + +The processor leaves V86 mode as the result of an exception or interrupt +that vectors via a trap or interrupt gate to a privilege-level zero +procedure. The exception or interrupt handler returns to the 8086 code by +executing an IRET. + +Because it was designed for execution by an 8086 processor, an 8086 program +in a V86 task will have an 8086-style interrupt table starting at linear +address zero. However, the 80386 does not use this table directly. For all +exceptions and interrupts that occur in V86 mode, the processor vectors +through the IDT. The IDT entry for an interrupt or exception that occurs in +a V86 task must contain either: + + A task gate. + + An 80386 trap gate (type 14) or an 80386 interrupt gate (type 15), + which must point to a nonconforming, privilege-level zero, code + segment. + +Interrupts and exceptions that have 80386 trap or interrupt gates in the +IDT vector to the appropriate handler procedure at privilege-level zero. The +contents of all the 8086 segment registers are stored on the PL 0 stack. +Figure 15-3 shows the format of the PL 0 stack after an exception or +interrupt that occurs while a V86 task is executing an 8086 program. + +After the processor stores all the 8086 segment registers on the PL 0 +stack, it loads all the segment registers with zeros before starting to +execute the handler procedure. This permits the interrupt handler to safely +save and restore the DS, ES, FS, and GS registers as 80386 selectors. +Interrupt handlers that may be invoked in the context of either a regular +task or a V86 task, can use the same prolog and epilog code for register +saving regardless of the kind of task. Restoring zeros to these registers +before execution of the IRET does not cause a trap in the interrupt handler. +Interrupt procedures that expect values in the segment registers or that +return values via segment registers have to use the register images stored +on the PL 0 stack. Interrupt handlers that need to know whether the +interrupt occurred in V86 mode can examine the VM bit in the stored EFLAGS +image. + +An interrupt handler passes control to the V86 monitor if the VM bit is set +in the EFLAGS image stored on the stack and the interrupt or exception is +one that the monitor needs to handle. The V86 monitor may either: + + Handle the interrupt completely within the V86 monitor. + Invoke the 8086 program's interrupt handler. + +Reflecting an interrupt or exception back to the 8086 code involves the +following steps: + + 1. Refer to the 8086 interrupt vector to locate the appropriate handler + procedure. + + 2. Store the state of the 8086 program on the privilege-level three + stack. + + 3. Change the return link on the privilege-level zero stack to point to + the privilege-level three handler procedure. + + 4. Execute an IRET so as to pass control to the handler. + + 5. When the IRET by the privilege-level three handler again traps to the + V86 monitor, restore the return link on the privilege-level zero stack + to point to the originally interrupted, privilege-level three + procedure. + + 6. Execute an IRET so as to pass control back to the interrupted + procedure. + + +Figure 15-3. PL 0 Stack after Interrupt in V86 Task + + + WITHOUT ERROR CODE WITH ERROR CODE + 31 0 31 0 + ͻĿ ͻĿ + OLD GS OLD GS + ͹ SS:ESP ͹ SS:ESP + D O OLD FS FROM TSS OLD FS FROM TSS + I F ͹ ͹ + R OLD DS OLD DS + E E ͹ ͹ + C X OLD ES OLD ES + T P ͹ ͹ + I A OLD SS OLD SS + O N ͹ ͹ + N S OLD ESP OLD ESP + I ͹ ͹ + O OLD EFLAGS OLD EFLAGS + N ͹ ͹ + OLD CS NEW OLD CS +  ͹ SS:EIP ͹ + OLD EIP OLD EIP NEW + ͹ ͹ SS:EIP + ERROR CODE +   ͹ +   +     + + +15.4 Additional Sensitive Instructions + +When the 80386 is executing in V86 mode, the instructions PUSHF, POPF, +INT n, and IRET are sensitive to IOPL. The instructions IN, INS, OUT, and +OUTS, which are ordinarily sensitive in protected mode, are not sensitive +in V86 mode. Following is a complete list of instructions that are sensitive +in V86 mode: + + CLI Clear Interrupt-Enable Flag + STI Set Interrupt-Enable Flag + LOCK Assert Bus-Lock Signal + PUSHF Push Flags + POPF Pop Flags + INT n Software Interrupt + RET Interrupt Return + +CPL is always three in V86 mode; therefore, if IOPL < 3, these instructions +will trigger a general-protection exceptions. These instructions are made +sensitive so that their functions can be simulated by the V86 monitor. + + +15.4.1 Emulating 8086 Operating System Calls + +INT n is sensitive so that the V86 monitor can intercept calls to the +8086 OS. Many 8086 operating systems are called by pushing parameters onto +the stack, then executing an INT n instruction. If IOPL < 3, INT n +instructions will be intercepted by the V86 monitor. The V86 monitor can +then emulate the function of the 8086 operating system or reflect the +interrupt back to the 8086 operating system in V86 mode. + + +15.4.2 Virtualizing the Interrupt-Enable Flag + +When the processor is executing 8086 code in a V86 task, the instructions +PUSHF, POPF, and IRET are sensitive to IOPL so that the V86 monitor can +control changes to the interrupt-enable flag (IF). Other instructions that +affect IF (STI and CLI) are IOPL sensitive both in 8086 code and in +80386/80386 code. + +Many 8086 programs that were designed to execute on single-task systems set +and clear IF to control interrupts. However, when these same programs are +executed in a multitasking environment, such control of IF can be +disruptive. If IOPL is less than three, all instructions that change or +interrogate IF will trap to the V86 monitor. The V86 monitor can then +control IF in a manner that both suits the needs of the larger environment +and is transparent to the 8086 program. + + +15.5 Virtual I/O + +Many 8086 programs that were designed to execute on single-task systems use +I/O devices directly. However, when these same programs are executed in a +multitasking environment, such use of devices can be disruptive. The 80386 +provides sufficient flexibility to control I/O in a manner that both suits +the needs of the new environment and is transparent to the 8086 program. +Designers may take any of several possible approaches to controlling I/O: + + Implement or emulate the 8086 operating system as an 80386 program and + require the 8086 application to do I/O via software interrupts to the + operating system, trapping all attempts to do I/O directly. + + Let the 8086 program take complete control of all I/O. + + Selectively trap and emulate references that a task makes to specific + I/O ports. + + Trap or redirect references to memory-mapped I/O addresses. + +The method of controlling I/O depends upon whether I/O ports are I/O mapped +or memory mapped. + + +15.5.1 I/O-Mapped I/O + +I/O-mapped I/O in V86 mode differs from protected mode only in that the +protection mechanism does not consult IOPL when executing the I/O +instructions IN, INS, OUT, OUTS. Only the I/O permission bit map controls +the right for V86 tasks to execute these I/O instructions. + +The I/O permission map traps I/O instructions selectively depending on the +I/O addresses to which they refer. The I/O permission bit map of each V86 +task determines which I/O addresses are trapped for that task. Because each +task may have a different I/O permission bit map, the addresses trapped for +one task may be different from those trapped for others. Refer to Chapter 8 +for more information about the I/O permission map. + + +15.5.2 Memory-Mapped I/O + +In hardware designs that utilize memory-mapped I/O, the paging facilities +of the 80386 can be used to trap or redirect I/O operations. Each task that +executes memory-mapped I/O must have a page (or pages) for the memory-mapped +address space. The V86 monitor may control memory-mapped I/O by any of +these means: + + Assign the memory-mapped page to appropriate physical addresses. + Different tasks may have different physical addresses, thereby + preventing the tasks from interfering with each other. + + Cause a trap to the monitor by forcing a page fault on the + memory-mapped page. Read-only pages trap writes. Not-present pages trap + both reads and writes. + +Intervention for every I/O might be excessive for some kinds of I/O +devices. A page fault can still be used in this case to cause intervention +on the first I/O operation. The monitor can then at least make sure that the +task has exclusive access to the device. Then the monitor can change the +page status to present and read/write, allowing subsequent I/O to proceed at +full speed. + + +15.5.3 Special I/O Buffers + +Buffers of intelligent controllers (for example, a bit-mapped graphics +buffer) can also be virtualized via page mapping. The linear space for the +buffer can be mapped to a different physical space for each virtual 8086 +task. The V86 monitor can then assume responsibility for spooling the data +or assigning the virtual buffer to the real buffer at appropriate times. + + +15.6 Differences From 8086 + +In general, V86 mode will correctly execute software designed for the 8086, +8088, 80186, and 80188. Following is a list of the minor differences between +8086 execution on the 80386 and on an 8086. + + 1. Instruction clock counts. + + The 80386 takes fewer clocks for most instructions than the + 8086/8088. The areas most likely to be affected are: + + Delays required by I/O devices between I/O operations. + + Assumed delays with 8086/8088 operating in parallel with an 8087. + + 2. Divide exceptions point to the DIV instruction. + + Divide exceptions on the 80386 always leave the saved CS:IP value + pointing to the instruction that failed. On the 8086/8088, the CS:IP + value points to the next instruction. + + 3. Undefined 8086/8088 opcodes. + + Opcodes that were not defined for the 8086/8088 will cause exception + 6 or will execute one of the new instructions defined for the 80386. + + 4. Value written by PUSH SP. + + The 80386 pushes a different value on the stack for PUSH SP than the + 8086/8088. The 80386 pushes the value of SP before SP is incremented + as part of the push operation; the 8086/8088 pushes the value of SP + after it is incremented. If the value pushed is important, replace + PUSH SP instructions with the following three instructions: + + PUSH BP + MOV BP, SP + XCHG BP, [BP] + + This code functions as the 8086/8088 PUSH SP instruction on the + 80386. + + 5. Shift or rotate by more than 31 bits. + + The 80386 masks all shift and rotate counts to the low-order five + bits. This MOD 32 operation limits the count to a maximum of 31 bits, + thereby limiting the time that interrupt response is delayed while + the instruction is executing. + + 6. Redundant prefixes. + + The 80386 sets a limit of 15 bytes on instruction length. The only + way to violate this limit is by putting redundant prefixes before an + instruction. Exception 13 occurs if the limit on instruction length + is violated. The 8086/8088 has no instruction length limit. + + 7. Operand crossing offset 0 or 65,535. + + On the 8086, an attempt to access a memory operand that crosses + offset 65,535 (e.g., MOV a word to offset 65,535) or offset 0 (e.g., + PUSH a word when SP = 1) causes the offset to wrap around modulo + 65,536. The 80386 raises an exception in these casesexception 13 if + the segment is a data segment (i.e., if CS, DS, ES, FS, or GS is + being used to address the segment), exception 12 if the segment is a + stack segment (i.e., if SS is being used). + + 8. Sequential execution across offset 65,535. + + On the 8086, if sequential execution of instructions proceeds past + offset 65,535, the processor fetches the next instruction byte from + offset 0 of the same segment. On the 80386, the processor raises + exception 13 in such a case. + + 9. LOCK is restricted to certain instructions. + + The LOCK prefix and its corresponding output signal should only be + used to prevent other bus masters from interrupting a data movement + operation. The 80386 always asserts the LOCK signal during an XCHG + instruction with memory (even if the LOCK prefix is not used). LOCK + may only be used with the following 80386 instructions when they + update memory: BTS, BTR, BTC, XCHG, ADD, ADC, SUB, SBB, INC, DEC, + AND, OR, XOR, NOT, and NEG. An undefined-opcode exception (interrupt + 6) results from using LOCK before any other instruction. + + 10. Single-stepping external interrupt handlers. + + The priority of the 80386 single-step exception is different from + that of the 8086/8088. The change prevents an external interrupt + handler from being single-stepped if the interrupt occurs while a + program is being single-stepped. The 80386 single-step exception has + higher priority that any external interrupt. The 80386 will still + single-step through an interrupt handler invoked by the INT + instructions or by an exception. + + 11. IDIV exceptions for quotients of 80H or 8000H. + + The 80386 can generate the largest negative number as a quotient for + the IDIV instruction. The 8086/8088 causes exception zero instead. + + 12. Flags in stack. + + The setting of the flags stored by PUSHF, by interrupts, and by + exceptions is different from that stored by the 8086 in bit positions + 12 through 15. On the 8086 these bits are stored as ones, but in V86 + mode bit 15 is always zero, and bits 14 through 12 reflect the last + value loaded into them. + + 13. NMI interrupting NMI handlers. + + After an NMI is recognized on the 80386, the NMI interrupt is masked + until an IRET instruction is executed. + + 14. Coprocessor errors vector to interrupt 16. + + Any 80386 system with a coprocessor must use interrupt vector 16 for + the coprocessor error exception. If an 8086/8088 system uses another + vector for the 8087 interrupt, both vectors should point to the + coprocessor-error exception handler. + + 15. Numeric exception handlers should allow prefixes. + + On the 80386, the value of CS:IP saved for coprocessor exceptions + points at any prefixes before an ESC instruction. On 8086/8088 + systems, the saved CS:IP points to the ESC instruction itself. + + 16. Coprocessor does not use interrupt controller. + + The coprocessor error signal to the 80386 does not pass through an + interrupt controller (an 8087 INT signal does). Some instructions in + a coprocessor error handler may need to be deleted if they deal with + the interrupt controller. + + +15.7 Differences From 80286 Real-Address Mode + +The 80286 processor implements the bus lock function differently than the +80386. This fact may or may not be apparent to 8086 programs, depending on +how the V86 monitor handles the LOCK prefix. LOCKed instructions are +sensitive to IOPL; therefore, software designers can choose to emulate its +function. If, however, 8086 programs are allowed to execute LOCK directly, +programs that use forms of memory locking specific to the 8086 may not +execute properly when transported to a specific application of the 80386. + +The LOCK prefix and its corresponding output signal should only be used to +prevent other bus masters from interrupting a data movement operation. LOCK +may only be used with the following 80386 instructions when they modify +memory. An undefined-opcode exception results from using LOCK before any +other instruction. + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + +A locked instruction is guaranteed to lock only the area of memory defined +by the destination operand, but may lock a larger memory area. For example, +typical 8086 and 80286 configurations lock the entire physical memory space. +With the 80386, the defined area of memory is guaranteed to be locked +against access by a processor executing a locked instruction on exactly the +same memory area, i.e., an operand with identical starting address and +identical length. + + +Chapter 16 Mixing 16-Bit and 32 Bit Code + + + +The 80386 running in protected mode is a 32-bit microprocessor, but it is +designed to support 16-bit processing at three levels: + + 1. Executing 8086/80286 16-bit programs efficiently with complete + compatibility. + + 2. Mixing 16-bit modules with 32-bit modules. + + 3. Mixing 16-bit and 32-bit addresses and operands within one module. + +The first level of support for 16-bit programs has already been discussed +in Chapter 13, Chapter 14, and Chapter 15. This chapter shows how 16-bit +and 32-bit modules can cooperate with one another, and how one module can +utilize both 16-bit and 32-bit operands and addressing. + +The 80386 functions most efficiently when it is possible to distinguish +between pure 16-bit modules and pure 32-bit modules. A pure 16-bit module +has these characteristics: + + All segments occupy 64 Kilobytes or less. + Data items are either 8 bits or 16 bits wide. + Pointers to code and data have 16-bit offsets. + Control is transferred only among 16-bit segments. + +A pure 32-bit module has these characteristics: + + Segments may occupy more than 64 Kilobytes (zero bytes to 4 + gigabytes). + + Data items are either 8 bits or 32 bits wide. + + Pointers to code and data have 32-bit offsets. + + Control is transferred only among 32-bit segments. + +Pure 16-bit modules do exist; they are the modules designed for 16-bit +microprocessors. Pure 32-bit modules may exist in new programs designed +explicitly for the 80386. However, as systems designers move applications +from 16-bit processors to the 32-bit 80386, it will not always be possible +to maintain these ideals of pure 16-bit or 32-bit modules. It may be +expedient to execute old 16-bit modules in a new 32-bit environment without +making source-code changes to the old modules if any of the following +conditions is true: + + Modules will be converted one-by-one from 16-bit environments to + 32-bit environments. + + Older, 16-bit compilers and software-development tools will be + utilized in the new32-bit operating environment until new 32-bit + versions can be created. + + The source code of 16-bit modules is not available for modification. + + The specific data structures used by a given module inherently utilize + 16-bit words. + + The native word size of the source language is 16 bits. + +On the 80386, 16-bit modules can be mixed with 32-bit modules. To design a +system that mixes 16- and 32-bit code requires an understanding of the +mechanisms that the 80386 uses to invoke and control its 32-bit and 16-bit +features. + + +16.1 How the 80386 Implements 16-Bit and 32-Bit Features + +The features of the architecture that permit the 80386 to work equally well +with 32-bit and 16-bit address and operand sizes include: + + The D-bit (default bit) of code-segment descriptors, which determines + the default choice of operand-size and address-size for the + instructions of a code segment. (In real-address mode and V86 mode, + which do not use descriptors, the default is 16 bits.) A code segment + whose D-bit is set is known as a USE32 segment; a code segment whose + D-bit is zero is a USE16 segment. The D-bit eliminates the need to + encode the operand size and address size in instructions when all + instructions use operands and effective addresses of the same size. + + Instruction prefixes that explicitly override the default choice of + operand size and address size (available in protected mode as well as + in real-address mode and V86 mode). + + Separate 32-bit and 16-bit gates for intersegment control transfers + (including call gates, interrupt gates, and trap gates). The operand + size for the control transfer is determined by the type of gate, not by + the D-bit or prefix of the transfer instruction. + + Registers that can be used both for 32-bit and 16-bit operands and + effective-address calculations. + + The B-bit (big bit) of data-segment descriptors, which determines the + size of stack pointer (32-bit ESP or 16-bit SP) used by the CPU for + implicit stack references. + + +16.2 Mixing 32-Bit and 16-Bit Operations + +The 80386 has two instruction prefixes that allow mixing of 32-bit and +16-bit operations within one segment: + + The operand-size prefix (66H) + The address-size prefix (67H) + +These prefixes reverse the default size selected by the D-bit. For example, +the processor can interpret the word-move instruction MOV mem, reg in any of +four ways: + + In a USE32 segment: + + 1. Normally moves 32 bits from a 32-bit register to a 32-bit + effective address in memory. + + 2. If preceded by an operand-size prefix, moves 16 bits from a 16-bit + register to 32-bit effective address in memory. + + 3. If preceded by an address-size prefix, moves 32 bits from a 32-bit + register to a16-bit effective address in memory. + + 4. If preceded by both an address-size prefix and an operand-size + prefix, moves 16 bits from a 16-bit register to a 16-bit effective + address in memory. + + In a USE16 segment: + + 1. Normally moves 16 bits from a 16-bit register to a 16-bit + effective address in memory. + + 2. If preceded by an operand-size prefix, moves 32 bits from a 32-bit + register to 16-bit effective address in memory. + + 3. If preceded by an address-size prefix, moves 16 bits from a 16-bit + register to a32-bit effective address in memory. + + 4. If preceded by both an address-size prefix and an operand-size + prefix, moves 32 bits from a 32-bit register to a 32-bit effective + address in memory. + +These examples illustrate that any instruction can generate any combination +of operand size and address size regardless of whether the instruction is in +a USE16 or USE32 segment. The choice of the USE16 or USE32 attribute for a +code segment is based upon these criteria: + + 1. The need to address instructions or data in segments that are larger + than 64 Kilobytes. + + 2. The predominant size of operands. + + 3. The addressing modes desired. (Refer to Chapter 17 for an explanation + of the additional addressing modes that are available when 32-bit + addressing is used.) + +Choosing a setting of the D-bit that is contrary to the predominant size of +operands requires the generation of an excessive number of operand-size +prefixes. + + +16.3 Sharing Data Segments Among Mixed Code Segments + +Because the choice of operand size and address size is defined in code +segments and their descriptors, data segments can be shared freely among +both USE16 and USE32 code segments. The only limitation is the one imposed +by pointers with 16-bit offsets, which can only point to the first 64 +Kilobytes of a segment. When a data segment that contains more than 64 +Kilobytes is to be shared among USE32 and USE16 segments, the data that is +to be accessed by the USE16 segments must be located within the first 64 +Kilobytes. + +A stack that spans addresses less than 64K can be shared by both USE16 and +USE32 code segments. This class of stacks includes: + + Stacks in expand-up segments with G=0 and B=0. + + Stacks in expand-down segments with G=0 and B=0. + + Stacks in expand-up segments with G=1 and B=0, in which the stack is + contained completely within the lower 64 Kilobytes. (Offsets greater + than 64K can be used for data, other than the stack, that is not + shared.) + +The B-bit of a stack segment cannot, in general, be used to change the size +of stack used by a USE16 code segment. The size of stack pointer used by the +processor for implicit stack references is controlled by the B-bit of the +data-segment descriptor for the stack. Implicit references are those caused +by interrupts, exceptions, and instructions such as PUSH, POP, CALL, and +RET. One might be tempted, therefore, to try to increase beyond 64K the +size of the stack used by 16-bit code simply by supplying a larger stack +segment with the B-bit set. However, the B-bit does not control explicit +stack references, such as accesses to parameters or local variables. A USE16 +code segment can utilize a "big" stack only if the code is modified so that +all explicit references to the stack are preceded by the address-size +prefix, causing those references to use 32-bit addressing. + +In big, expand-down segments (B=1, G=1, and E=1), all offsets are greater +than 64K, therefore USE16 code cannot utilize such a stack segment unless +the code segment is modified to employ 32-bit addressing. (Refer to Chapter +6 for a review of the B, G, and E bits.) + + +16.4 Transferring Control Among Mixed Code Segments + +When transferring control among procedures in USE16 and USE32 code +segments, programmers must be aware of three points: + + Addressing limitations imposed by pointers with 16-bit offsets. + + Matching of operand-size attribute in effect for the CALL/RET pair and + theInterrupt/IRET pair so as to manage the stack correctly. + + Translation of parameters, especially pointer parameters. + +Clearly, 16-bit effective addresses cannot be used to address data or code +located beyond 64K in a 32-bit segment, nor can large 32-bit parameters be +squeezed into a 16-bit word; however, except for these obvious limits, most +interfacing problems between 16-bit and 32-bit modules can be solved. Some +solutions involve inserting interface procedures between the procedures in +question. + + +16.4.1 Size of Code-Segment Pointer + +For control-transfer instructions that use a pointer to identify the next +instruction (i.e., those that do not use gates), the size of the offset +portion of the pointer is determined by the operand-size attribute. The +implications of the use of two different sizes of code-segment pointer are: + + JMP, CALL, or RET from 32-bit segment to 16-bit segment is always + possible using a 32-bit operand size. + + JMP, CALL, or RET from 16-bit segment using a 16-bit operand size + cannot address the target in a 32-bit segment if the address of the + target is greater than 64K. + +An interface procedure can enable transfers from USE16 segments to 32-bit +addresses beyond 64K without requiring modifications any more extensive than +relinking or rebinding the old programs. The requirements for such an +interface procedure are discussed later in this chapter. + + +16.4.2 Stack Management for Control Transfers + +Because stack management is different for 16-bit CALL/RET than for 32-bit +CALL/RET, the operand size of RET must match that of CALL. (Refer to Figure +16-1.) A 16-bit CALL pushes the 16-bit IP and (for calls between privilege +levels) the 16-bit SP register. The corresponding RET must also use a 16-bit +operand size to POP these 16-bit values from the stack into the 16-bit +registers. A 32-bit CALL pushes the 32-bit EIP and (for interlevel calls) +the 32-bit ESP register. The corresponding RET must also use a 32-bit +operand size to POP these 32-bit values from the stack into the 32-bit +registers. If the two halves of a CALL/RET pair do not have matching operand +sizes, the stack will not be managed correctly and the values of the +instruction pointer and stack pointer will not be restored to correct +values. + +When the CALL and its corresponding RET are in segments that have D-bits +with the same values (i.e., both have 32-bit defaults or both have 16-bit +defaults), there is no problem. When the CALL and its corresponding RET are +in segments that have different D-bit values, however, programmers (or +program development software) must ensure that the CALL and RET match. + +There are three ways to cause a 16-bit procedure to execute a 32-bit call: + + 1. Use a 16-bit call to a 32-bit interface procedure that then uses a + 32-bit call to invoke the intended target. + + 2. Bind the 16-bit call to a 32-bit call gate. + + 3. Modify the 16-bit procedure, inserting an operand-size prefix before + the call, thereby changing it to a 32-bit call. + +Likewise, there are three ways to cause a 32-bit procedure to execute a +16-bit call: + + 1. Use a 32-bit call to a 32-bit interface procedure that then uses a + 16-bit call to invoke the intended target. + + 2. Bind the 32-bit call to a 16-bit call gate. + + 3. Modify the 32-bit procedure, inserting an operand-size prefix before + the call, thereby changing it to a 16-bit call. (Be certain that the + return offset does not exceed 64K.) + +Programmers can utilize any of the preceding methods to make a CALL in a +USE16 segment match the corresponding RET in a USE32 segment, or to make a +CALL in a USE32 segment match the corresponding RET in a USE16 segment. + + +Figure 16-1. Stack after Far 16-Bit and 32-Bit Calls + + WITHOUT PRIVILEGE TRANSITION + + AFTER 16-BIT CALL AFTER 32-BIT CALL + + 31 0 31 0 + D O + I F ͹ ͹ + R + E E ͹ ͹ + C X PARM2 PARM1 PARM2 + T P ͹ ͹ + I A CS IP SP PARM1 + O N ͹ ͹ + N S CS + I ͹ ͹ + O EIP ESP + N ͹ ͹ + +      + + WITH PRIVILEGE TRANSITION + + AFTER 16-BIT CALL AFTER 32-BIT CALL + + D O 31 0 31 0 + I F ͻ ͻ + R SS SP SS + E E ͹ ͹ + C X PARM2 PARM1 ESP + T P ͹ ͹ + I A CS IP SP PARM2 + O N ͹ ͹ + N S PARM1 + I ͹ ͹ + O CS + N ͹ ͹ + EIP ESP +  ͹ ͹ + +     + + +16.4.2.1 Controlling the Operand-Size for a Call + +When the selector of the pointer referenced by a CALL instruction selects a +segment descriptor, the operand-size attribute in effect for the CALL +instruction is determined by the D-bit in the segment descriptor and by any +operand-size instruction prefix. + +When the selector of the pointer referenced by a CALL instruction selects a +gate descriptor, the type of call is determined by the type of call gate. A +call via an 80286 call gate (descriptor type 4) always has a 16-bit +operand-size attribute; a call via an 80386 call gate (descriptor type 12) +always has a 32-bit operand-size attribute. The offset of the target +procedure is taken from the gate descriptor; therefore, even a 16-bit +procedure can call a procedure that is located more than 64 kilobytes from +the base of a 32-bit segment, because a 32-bit call gate contains a 32-bit +target offset. + +An unmodified 16-bit code segment that has run successfully on an 8086 or +real-mode 80286 will always have a D-bit of zero and will not use +operand-size override prefixes; therefore, it will always execute 16-bit +versions of CALL. The only modification needed to make a16-bit procedure +effect a 32-bit call is to relink the call to an 80386 call gate. + + +16.4.2.2 Changing Size of Call + +When adding 32-bit gates to 16-bit procedures, it is important to consider +the number of parameters. The count field of the gate descriptor specifies +the size of the parameter string to copy from the current stack to the stack +of the more privileged procedure. The count field of a 16-bit gate specifies +the number of words to be copied, whereas the count field of a 32-bit gate +specifies the number of doublewords to be copied; therefore, the 16-bit +procedure must use an even number of words as parameters. + + +16.4.3 Interrupt Control Transfers + +With a control transfer due to an interrupt or exception, a gate is always +involved. The operand-size attribute for the interrupt is determined by the +type of IDT gate. + +A 386 interrupt or trap gate (descriptor type 14 or 15) to a 32-bit +interrupt procedure can be used to interrupt either 32-bit or 16-bit +procedures. However, it is not generally feasible to permit an interrupt or +exception to invoke a 16-bit handler procedure when 32-bit code is +executing, because a 16-bit interrupt procedure has a return offset of only +16-bits on its stack. If the 32-bit procedure is executing at an address +greater than 64K, the 16-bit interrupt procedure cannot return correctly. + + +16.4.4 Parameter Translation + +When segment offsets or pointers (which contain segment offsets) are passed +as parameters between 16-bit and 32-bit procedures, some translation is +required. Clearly, if a 32-bit procedure passes a pointer to data located +beyond 64K to a 16-bit procedure, the 16-bit procedure cannot utilize it. +Beyond this natural limitation, an interface procedure can perform any +format conversion between 32-bit and 16-bit pointers that may be needed. + +Parameters passed by value between 32-bit and 16-bit code may also require +translation between 32-bit and 16-bit formats. Such translation requirements +are application dependent. Systems designers should take care to limit the +range of values passed so that such translations are possible. + + +16.4.5 The Interface Procedure + +Interposing an interface procedure between 32-bit and 16-bit procedures can +be the solution to any of several interface requirements: + + Allowing procedures in 16-bit segments to transfer control to + instructions located beyond 64K in 32-bit segments. + + Matching of operand size for CALL/RET. + + Parameter translation. + +Interface procedures between USE32 and USE16 segments can be constructed +with these properties: + + The procedures reside in a code segment whose D-bit is set, indicating + a default operand size of 32-bits. + + All entry points that may be called by 16-bit procedures have offsets + that are actually less than 64K. + + All points to which called 16-bit procedures may return also lie + within 64K. + +The interface procedures do little more than call corresponding procedures +in other segments. There may be two kinds of procedures: + + Those that are called by 16-bit procedures and call 32-bit procedures. + These interface procedures are called by 16-bit CALLs and use the + operand-size prefix before RET instructions to cause a 16-bit RET. + CALLs to 32-bit segments are 32-bit calls (by default, because the + D-bit is set), and the 32-bit code returns with 32-bit RET + instructions. + + Those that are called by 32-bit procedures and call 16-bit procedures. + These interface procedures are called by 32-bit CALL instructions, and + return with 32-bit RET instructions (by default, because the D-bit is + set). CALLs to 16-bit procedures use the operand-size prefix; + procedures in the 16-bit code return with 16-bit RET instructions. + + + PART IV INSTRUCTION SET + + +Chapter 17 80386 Instruction Set + + + +This chapter presents instructions for the 80386 in alphabetical order. For +each instruction, the forms are given for each operand combination, +including object code produced, operands required, execution time, and a +description. For each instruction, there is an operational description and a +summary of exceptions generated. + + +17.1 Operand-Size and Address-Size Attributes + +When executing an instruction, the 80386 can address memory using either 16 +or 32-bit addresses. Consequently, each instruction that uses memory +addresses has associated with it an address-size attribute of either 16 or +32 bits. 16-bit addresses imply both the use of a 16-bit displacement in +the instruction and the generation of a 16-bit address offset (segment +relative address) as the result of the effective address calculation. +32-bit addresses imply the use of a 32-bit displacement and the generation +of a 32-bit address offset. Similarly, an instruction that accesses words +(16 bits) or doublewords (32 bits) has an operand-size attribute of either +16 or 32 bits. + +The attributes are determined by a combination of defaults, instruction +prefixes, and (for programs executing in protected mode) size-specification +bits in segment descriptors. + + +17.1.1 Default Segment Attribute + +For programs executed in protected mode, the D-bit in executable-segment +descriptors determines the default attribute for both address size and +operand size. These default attributes apply to the execution of all +instructions in the segment. A value of zero in the D-bit sets the default +address size and operand size to 16 bits; a value of one, to 32 bits. + +Programs that execute in real mode or virtual-8086 mode have 16-bit +addresses and operands by default. + + +17.1.2 Operand-Size and Address-Size Instruction Prefixes + +The internal encoding of an instruction can include two byte-long prefixes: +the address-size prefix, 67H, and the operand-size prefix, 66H. (A later +section, "Instruction Format," shows the position of the prefixes in an +instruction's encoding.) These prefixes override the default segment +attributes for the instruction that follows. Table 17-1 shows the effect of +each possible combination of defaults and overrides. + + +17.1.3 Address-Size Attribute for Stack + +Instructions that use the stack implicitly (for example: POP EAX also have +a stack address-size attribute of either 16 or 32 bits. Instructions with a +stack address-size attribute of 16 use the 16-bit SP stack pointer register; +instructions with a stack address-size attribute of 32 bits use the 32-bit +ESP register to form the address of the top of the stack. + +The stack address-size attribute is controlled by the B-bit of the +data-segment descriptor in the SS register. A value of zero in the B-bit +selects a stack address-size attribute of 16; a value of one selects a stack +address-size attribute of 32. + + +Table 17-1. Effective Size Attributes + +Segment Default D = ... 0 0 0 0 1 1 1 1 +Operand-Size Prefix 66H N N Y Y N N Y Y +Address-Size Prefix 67H N Y N Y N Y N Y + +Effective Operand Size 16 16 32 32 32 32 16 16 +Effective Address Size 16 32 16 32 32 16 32 16 + +Y = Yes, this instruction prefix is present +N = No, this instruction prefix is not present + + +17.2 Instruction Format + +All instruction encodings are subsets of the general instruction format +shown in Figure 17-1. Instructions consist of optional instruction +prefixes, one or two primary opcode bytes, possibly an address specifier +consisting of the ModR/M byte and the SIB (Scale Index Base) byte, a +displacement, if required, and an immediate data field, if required. + +Smaller encoding fields can be defined within the primary opcode or +opcodes. These fields define the direction of the operation, the size of the +displacements, the register encoding, or sign extension; encoding fields +vary depending on the class of operation. + +Most instructions that can refer to an operand in memory have an addressing +form byte following the primary opcode byte(s). This byte, called the ModR/M +byte, specifies the address form to be used. Certain encodings of the ModR/M +byte indicate a second addressing byte, the SIB (Scale Index Base) byte, +which follows the ModR/M byte and is required to fully specify the +addressing form. + +Addressing forms can include a displacement immediately following either +the ModR/M or SIB byte. If a displacement is present, it can be 8-, 16- or +32-bits. + +If the instruction specifies an immediate operand, the immediate operand +always follows any displacement bytes. The immediate operand, if specified, +is always the last field of the instruction. + +The following are the allowable instruction prefix codes: + + F3H REP prefix (used only with string instructions) + F3H REPE/REPZ prefix (used only with string instructions + F2H REPNE/REPNZ prefix (used only with string instructions) + F0H LOCK prefix + +The following are the segment override prefixes: + + 2EH CS segment override prefix + 36H SS segment override prefix + 3EH DS segment override prefix + 26H ES segment override prefix + 64H FS segment override prefix + 65H GS segment override prefix + 66H Operand-size override + 67H Address-size override + + +Figure 17-1. 80386 Instruction Format + + ͻ + INSTRUCTION ADDRESS- OPERAND- SEGMENT + PREFIX SIZE PREFIX SIZE PREFIX OVERRIDE + ͹ + 0 OR 1 0 OR 1 0 OR 1 0 OR 1 + Ķ + NUMBER OF BYTES + ͼ + + ͻ + OPCODE MODR/M SIB DISPLACEMENT IMMEDIATE + + ͹ + 1 OR 2 0 OR 1 0 OR 1 0,1,2 OR 4 0,1,2 OR 4 + Ķ + NUMBER OF BYTES + ͼ + + +17.2.1 ModR/M and SIB Bytes + +The ModR/M and SIB bytes follow the opcode byte(s) in many of the 80386 +instructions. They contain the following information: + + The indexing type or register number to be used in the instruction + The register to be used, or more information to select the instruction + The base, index, and scale information + +The ModR/M byte contains three fields of information: + + The mod field, which occupies the two most significant bits of the + byte, combines with the r/m field to form 32 possible values: eight + registers and 24 indexing modes + + The reg field, which occupies the next three bits following the mod + field, specifies either a register number or three more bits of opcode + information. The meaning of the reg field is determined by the first + (opcode) byte of the instruction. + + The r/m field, which occupies the three least significant bits of the + byte, can specify a register as the location of an operand, or can form + part of the addressing-mode encoding in combination with the field as + described above + +The based indexed and scaled indexed forms of 32-bit addressing require the +SIB byte. The presence of the SIB byte is indicated by certain encodings of +the ModR/M byte. The SIB byte then includes the following fields: + + The ss field, which occupies the two most significant bits of the + byte, specifies the scale factor + + The index field, which occupies the next three bits following the ss + field and specifies the register number of the index register + + The base field, which occupies the three least significant bits of the + byte, specifies the register number of the base register + +Figure 17-2 shows the formats of the ModR/M and SIB bytes. + +The values and the corresponding addressing forms of the ModR/M and SIB +bytes are shown in Tables 17-2, 17-3, and 17-4. The 16-bit addressing +forms specified by the ModR/M byte are in Table 17-2. The 32-bit addressing +forms specified by ModR/M are in Table 17-3. Table 17-4 shows the 32-bit +addressing forms specified by the SIB byte + + +Figure 17-2. ModR/M and SIB Byte Formats + + MODR/M BYTE + + 7 6 5 4 3 2 1 0 + ͻ + MOD REG/OPCODE R/M + ͼ + + SIB (SCALE INDEX BASE) BYTE + + 7 6 5 4 3 2 1 0 + ͻ + SS INDEX BASE + ͼ + + +Table 17-2. 16-Bit Addressing Forms with the ModR/M Byte + + +r8(/r) AL CL DL BL AH CH DH BH +r16(/r) AX CX DX BX SP BP SI DI +r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI +/digit (Opcode) 0 1 2 3 4 5 6 7 +REG = 000 001 010 011 100 101 110 111 + + Effective +Address +disp8 denotes an 8-bit displacement following the ModR/M byte, to be +sign-extended and added to the index. disp16 denotes a 16-bit displacement +following the ModR/M byte, to be added to the index. Default segment +register is SS for the effective addresses containing a BP index, DS for +other effective addresses.Ŀ Mod R/M ModR/M Values in HexadecimalĿ + +[BX + SI] 000 00 08 10 18 20 28 30 38 +[BX + DI] 001 01 09 11 19 21 29 31 39 +[BP + SI] 010 02 0A 12 1A 22 2A 32 3A +[BP + DI] 011 03 0B 13 1B 23 2B 33 3B +[SI] 00 100 04 0C 14 1C 24 2C 34 3C +[DI] 101 05 0D 15 1D 25 2D 35 3D +disp16 110 06 0E 16 1E 26 2E 36 3E +[BX] 111 07 0F 17 1F 27 2F 37 3F + +[BX+SI]+disp8 000 40 48 50 58 60 68 70 78 +[BX+DI]+disp8 001 41 49 51 59 61 69 71 79 +[BP+SI]+disp8 010 42 4A 52 5A 62 6A 72 7A +[BP+DI]+disp8 011 43 4B 53 5B 63 6B 73 7B +[SI]+disp8 01 100 44 4C 54 5C 64 6C 74 7C +[DI]+disp8 101 45 4D 55 5D 65 6D 75 7D +[BP]+disp8 110 46 4E 56 5E 66 6E 76 7E +[BX]+disp8 111 47 4F 57 5F 67 6F 77 7F + +[BX+SI]+disp16 000 80 88 90 98 A0 A8 B0 B8 +[BX+DI]+disp16 001 81 89 91 99 A1 A9 B1 B9 +[BX+SI]+disp16 010 82 8A 92 9A A2 AA B2 BA +[BX+DI]+disp16 011 83 8B 93 9B A3 AB B3 BB +[SI]+disp16 10 100 84 8C 94 9C A4 AC B4 BC +[DI]+disp16 101 85 8D 95 9D A5 AD B5 BD +[BP]+disp16 110 86 8E 96 9E A6 AE B6 BE +[BX]+disp16 111 87 8F 97 9F A7 AF B7 BF + +EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 +ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 +EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA +EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB +ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC +EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD +ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE +EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF + + + +NOTES: + disp8 denotes an 8-bit displacement following the ModR/M byte, to be + sign-extended and added to the index. disp16 denotes a 16-bit displacement + following the ModR/M byte, to be added to the index. Default segment + register is SS for the effective addresses containing a BP index, DS for + other effective addresses. + + + +Table 17-3. 32-Bit Addressing Forms with the ModR/M Byte + + +r8(/r) AL CL DL BL AH CH DH BH +r16(/r) AX CX DX BX SP BP SI DI +r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI +/digit (Opcode) 0 1 2 3 4 5 6 7 +REG = 000 001 010 011 100 101 110 111 + + Effective +Address +[--] [--] means a SIB follows the ModR/M byte. disp8 denotes an 8-bit +displacement following the SIB byte, to be sign-extended and added to the +index. disp32 denotes a 32-bit displacement following the ModR/M byte, to +be added to the index.Ŀ Mod R/M ModR/M Values in HexadecimalĿ + +[EAX] 000 00 08 10 18 20 28 30 38 +[ECX] 001 01 09 11 19 21 29 31 39 +[EDX] 010 02 0A 12 1A 22 2A 32 3A +[EBX] 011 03 0B 13 1B 23 2B 33 3B +[--] [--] 00 100 04 0C 14 1C 24 2C 34 3C +disp32 101 05 0D 15 1D 25 2D 35 3D +[ESI] 110 06 0E 16 1E 26 2E 36 3E +[EDI] 111 07 0F 17 1F 27 2F 37 3F + +disp8[EAX] 000 40 48 50 58 60 68 70 78 +disp8[ECX] 001 41 49 51 59 61 69 71 79 +disp8[EDX] 010 42 4A 52 5A 62 6A 72 7A +disp8[EPX]; 011 43 4B 53 5B 63 6B 73 7B +disp8[--] [--] 01 100 44 4C 54 5C 64 6C 74 7C +disp8[ebp] 101 45 4D 55 5D 65 6D 75 7D +disp8[ESI] 110 46 4E 56 5E 66 6E 76 7E +disp8[EDI] 111 47 4F 57 5F 67 6F 77 7F + +disp32[EAX] 000 80 88 90 98 A0 A8 B0 B8 +disp32[ECX] 001 81 89 91 99 A1 A9 B1 B9 +disp32[EDX] 010 82 8A 92 9A A2 AA B2 BA +disp32[EBX] 011 83 8B 93 9B A3 AB B3 BB +disp32[--] [--] 10 100 84 8C 94 9C A4 AC B4 BC +disp32[EBP] 101 85 8D 95 9D A5 AD B5 BD +disp32[ESI] 110 86 8E 96 9E A6 AE B6 BE +disp32[EDI] 111 87 8F 97 9F A7 AF B7 BF + +EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 +ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 +EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA +EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB +ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC +EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD +ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE +EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF + + + +NOTES: + [--] [--] means a SIB follows the ModR/M byte. disp8 denotes an 8-bit + displacement following the SIB byte, to be sign-extended and added to the + index. disp32 denotes a 32-bit displacement following the ModR/M byte, to + be added to the index. + + + +Table 17-4. 32-Bit Addressing Forms with the SIB Byte + + + r32 EAX ECX EDX EBX ESP [*] +[*] means a disp32 with no base if MOD is 00, [ESP] otherwise. This provides +the following addressing modes: + disp32[index] (MOD=00) + disp8[EBP][index] (MOD=01) + disp32[EBP][index] (MOD=10) ESI EDI + Base = 0 1 2 3 4 5 6 7 + Base = 000 001 010 011 100 101 110 111 + +Scaled Index +[*] means a disp32 with no base if MOD is 00, [ESP] otherwise. This provides +the following addressing modes: + disp32[index] (MOD=00) + disp8[EBP][index] (MOD=01) + disp32[EBP][index] (MOD=10)SS Index ModR/M Values in HexadecimalĿ + +[EAX] 000 00 01 02 03 04 05 06 07 +[ECX] 001 08 09 0A 0B 0C 0D 0E 0F +[EDX] 010 10 11 12 13 14 15 16 17 +[EBX] 011 18 19 1A 1B 1C 1D 1E 1F +none 00 100 20 21 22 23 24 25 26 27 +[EBP] 101 28 29 2A 2B 2C 2D 2E 2F +[ESI] 110 30 31 32 33 34 35 36 37 +[EDI] 111 38 39 3A 3B 3C 3D 3E 3F + +[EAX*2] 000 40 41 42 43 44 45 46 47 +[ECX*2] 001 48 49 4A 4B 4C 4D 4E 4F +[ECX*2] 010 50 51 52 53 54 55 56 57 +[EBX*2] 011 58 59 5A 5B 5C 5D 5E 5F +none 01 100 60 61 62 63 64 65 66 67 +[EBP*2] 101 68 69 6A 6B 6C 6D 6E 6F +[ESI*2] 110 70 71 72 73 74 75 76 77 +[EDI*2] 111 78 79 7A 7B 7C 7D 7E 7F + +[EAX*4] 000 80 81 82 83 84 85 86 87 +[ECX*4] 001 88 89 8A 8B 8C 8D 8E 8F +[EDX*4] 010 90 91 92 93 94 95 96 97 +[EBX*4] 011 98 89 9A 9B 9C 9D 9E 9F +none 10 100 A0 A1 A2 A3 A4 A5 A6 A7 +[EBP*4] 101 A8 A9 AA AB AC AD AE AF +[ESI*4] 110 B0 B1 B2 B3 B4 B5 B6 B7 +[EDI*4] 111 B8 B9 BA BB BC BD BE BF + +[EAX*8] 000 C0 C1 C2 C3 C4 C5 C6 C7 +[ECX*8] 001 C8 C9 CA CB CC CD CE CF +[EDX*8] 010 D0 D1 D2 D3 D4 D5 D6 D7 +[EBX*8] 011 D8 D9 DA DB DC DD DE DF +none 11 100 E0 E1 E2 E3 E4 E5 E6 E7 +[EBP*8] 101 E8 E9 EA EB EC ED EE EF +[ESI*8] 110 F0 F1 F2 F3 F4 F5 F6 F7 +[EDI*8] 111 F8 F9 FA FB FC FD FE FF + + + +NOTES: + [*] means a disp32 with no base if MOD is 00, [ESP] otherwise. This + provides the following addressing modes: + disp32[index] (MOD=00) + disp8[EBP][index] (MOD=01) + disp32[EBP][index] (MOD=10) + + + +17.2.2 How to Read the Instruction Set Pages + +The following is an example of the format used for each 80386 instruction +description in this chapter: + +CMC Complement Carry Flag + +Opcode Instruction Clocks Description + +F5 CMC 2 Complement carry flag + +The above table is followed by paragraphs labelled "Operation," +"Description," "Flags Affected," "Protected Mode Exceptions," "Real +Address Mode Exceptions," and, optionally, "Notes." The following sections +explain the notational conventions and abbreviations used in these +paragraphs of the instruction descriptions. + + +17.2.2.1 Opcode + +The "Opcode" column gives the complete object code produced for each form +of the instruction. When possible, the codes are given as hexadecimal bytes, +in the same order in which they appear in memory. Definitions of entries +other than hexadecimal bytes are as follows: + +/digit: (digit is between 0 and 7) indicates that the ModR/M byte of the +instruction uses only the r/m (register or memory) operand. The reg field +contains the digit that provides an extension to the instruction's opcode. + +/r: indicates that the ModR/M byte of the instruction contains both a +register operand and an r/m operand. + +cb, cw, cd, cp: a 1-byte (cb), 2-byte (cw), 4-byte (cd) or 6-byte (cp) +value following the opcode that is used to specify a code offset and +possibly a new value for the code segment register. + +ib, iw, id: a 1-byte (ib), 2-byte (iw), or 4-byte (id) immediate operand to +the instruction that follows the opcode, ModR/M bytes or scale-indexing +bytes. The opcode determines if the operand is a signed value. All words and +doublewords are given with the low-order byte first. + ++rb, +rw, +rd: a register code, from 0 through 7, added to the hexadecimal +byte given at the left of the plus sign to form a single opcode byte. The +codes are + + rb rw rd + AL = 0 AX = 0 EAX = 0 + CL = 1 CX = 1 ECX = 1 + DL = 2 DX = 2 EDX = 2 + BL = 3 BX = 3 EBX = 3 + AH = 4 SP = 4 ESP = 4 + CH = 5 BP = 5 EBP = 5 + DH = 6 SI = 6 ESI = 6 + BH = 7 DI = 7 EDI = 7 + + +17.2.2.2 Instruction + +The "Instruction" column gives the syntax of the instruction statement as +it would appear in an ASM386 program. The following is a list of the symbols +used to represent operands in the instruction statements: + +rel8: a relative address in the range from 128 bytes before the end of the +instruction to 127 bytes after the end of the instruction. + +rel16, rel32: a relative address within the same code segment as the +instruction assembled. rel16 applies to instructions with an operand-size +attribute of 16 bits; rel32 applies to instructions with an operand-size +attribute of 32 bits. + +ptr16:16, ptr16:32: a FAR pointer, typically in a code segment different +from that of the instruction. The notation 16:16 indicates that the value of +the pointer has two parts. The value to the right of the colon is a 16-bit +selector or value destined for the code segment register. The value to the +left corresponds to the offset within the destination segment. ptr16:16 is +used when the instruction's operand-size attribute is 16 bits; ptr16:32 is +used with the 32-bit attribute. + +r8: one of the byte registers AL, CL, DL, BL, AH, CH, DH, or BH. + +r16: one of the word registers AX, CX, DX, BX, SP, BP, SI, or DI. + +r32: one of the doubleword registers EAX, ECX, EDX, EBX, ESP, EBP, ESI, or +EDI. + +imm8: an immediate byte value. imm8 is a signed number between -128 and ++127 inclusive. For instructions in which imm8 is combined with a word or +doubleword operand, the immediate value is sign-extended to form a word or +doubleword. The upper byte of the word is filled with the topmost bit of the +immediate value. + +imm16: an immediate word value used for instructions whose operand-size +attribute is 16 bits. This is a number between -32768 and +32767 inclusive. + +imm32: an immediate doubleword value used for instructions whose +operand-size attribute is 32-bits. It allows the use of a number between ++2147483647 and -2147483648. + +r/m8: a one-byte operand that is either the contents of a byte register +(AL, BL, CL, DL, AH, BH, CH, DH), or a byte from memory. + +r/m16: a word register or memory operand used for instructions whose +operand-size attribute is 16 bits. The word registers are: AX, BX, CX, DX, +SP, BP, SI, DI. The contents of memory are found at the address provided by +the effective address computation. + +r/m32: a doubleword register or memory operand used for instructions whose +operand-size attribute is 32-bits. The doubleword registers are: EAX, EBX, +ECX, EDX, ESP, EBP, ESI, EDI. The contents of memory are found at the +address provided by the effective address computation. + +m8: a memory byte addressed by DS:SI or ES:DI (used only by string +instructions). + +m16: a memory word addressed by DS:SI or ES:DI (used only by string +instructions). + +m32: a memory doubleword addressed by DS:SI or ES:DI (used only by string +instructions). + +m16:16, M16:32: a memory operand containing a far pointer composed of two +numbers. The number to the left of the colon corresponds to the pointer's +segment selector. The number to the right corresponds to its offset. + +m16 & 32, m16 & 16, m32 & 32: a memory operand consisting of data item pairs +whose sizes are indicated on the left and the right side of the ampersand. +All memory addressing modes are allowed. m16 & 16 and m32 & 32 operands are +used by the BOUND instruction to provide an operand containing an upper and +lower bounds for array indices. m16 & 32 is used by LIDT and LGDT to +provide a word with which to load the limit field, and a doubleword with +which to load the base field of the corresponding Global and Interrupt +Descriptor Table Registers. + +moffs8, moffs16, moffs32: (memory offset) a simple memory variable of type +BYTE, WORD, or DWORD used by some variants of the MOV instruction. The +actual address is given by a simple offset relative to the segment base. No +ModR/M byte is used in the instruction. The number shown with moffs +indicates its size, which is determined by the address-size attribute of the +instruction. + +Sreg: a segment register. The segment register bit assignments are ES=0, +CS=1, SS=2, DS=3, FS=4, and GS=5. + + +17.2.2.3 Clocks + +The "Clocks" column gives the number of clock cycles the instruction takes +to execute. The clock count calculations makes the following assumptions: + + The instruction has been prefetched and decoded and is ready for + execution. + + Bus cycles do not require wait states. + + There are no local bus HOLD requests delaying processor access to the + bus. + + No exceptions are detected during instruction execution. + + Memory operands are aligned. + +Clock counts for instructions that have an r/m (register or memory) operand +are separated by a slash. The count to the left is used for a register +operand; the count to the right is used for a memory operand. + +The following symbols are used in the clock count specifications: + + n, which represents a number of repetitions. + + m, which represents the number of components in the next instruction + executed, where the entire displacement (if any) counts as one + component, the entire immediate data (if any) counts as one component, + and every other byte of the instruction and prefix(es) each counts as + one component. + + pm=, a clock count that applies when the instruction executes in + Protected Mode. pm= is not given when the clock counts are the same for + Protected and Real Address Modes. + +When an exception occurs during the execution of an instruction and the +exception handler is in another task, the instruction execution time is +increased by the number of clocks to effect a task switch. This parameter +depends on several factors: + + The type of TSS used to represent the current task (386 TSS or 286 + TSS). + + The type of TSS used to represent the new task. + + Whether the current task is in V86 mode. + + Whether the new task is in V86 mode. + +Table 17-5 summarizes the task switch times for exceptions. + + +Table 17-5. Task Switch Times for Exceptions + + New Task + +Old 386 TSS 286 TSS +Task VM = 0 + +386 VM = 0 309 282 +TSS + +386 VM = 1 314 231 +TSS + +286 307 282 +TSS + + +17.2.2.4 Description + +The "Description" column following the "Clocks" column briefly explains the +various forms of the instruction. The "Operation" and "Description" sections +contain more details of the instruction's operation. + + +17.2.2.5 Operation + +The "Operation" section contains an algorithmic description of the +instruction which uses a notation similar to the Algol or Pascal language. +The algorithms are composed of the following elements: + +Comments are enclosed within the symbol pairs "(*" and "*)". + +Compound statements are enclosed between the keywords of the "if" statement +(IF, THEN, ELSE, FI) or of the "do" statement (DO, OD), or of the "case" +statement (CASE ... OF, ESAC). + +A register name implies the contents of the register. A register name +enclosed in brackets implies the contents of the location whose address is +contained in that register. For example, ES:[DI] indicates the contents of +the location whose ES segment relative address is in register DI. [SI] +indicates the contents of the address contained in register SI relative to +SI's default segment (DS) or overridden segment. + +Brackets also used for memory operands, where they mean that the contents +of the memory location is a segment-relative offset. For example, [SRC] +indicates that the contents of the source operand is a segment-relative +offset. + +A  B; indicates that the value of B is assigned to A. + +The symbols =, <>, , and are relational operators used to compare two +values, meaning equal, not equal, greater or equal, less or equal, +respectively. A relational expression such as A = B is TRUE if the value of +A is equal to B; otherwise it is FALSE. + +The following identifiers are used in the algorithmic descriptions: + + OperandSize represents the operand-size attribute of the instruction, + which is either 16 or 32 bits. AddressSize represents the address-size + attribute, which is either 16 or 32 bits. For example, + + IF instruction = CMPSW + THEN OperandSize  16; + ELSE + IF instruction = CMPSD + THEN OperandSize  32; + FI; + FI; + +indicates that the operand-size attribute depends on the form of the CMPS +instruction used. Refer to the explanation of address-size and operand-size +attributes at the beginning of this chapter for general guidelines on how +these attributes are determined. + + StackAddrSize represents the stack address-size attribute associated + with the instruction, which has a value of 16 or 32 bits, as explained + earlier in the chapter. + + SRC represents the source operand. When there are two operands, SRC is + the one on the right. + + DEST represents the destination operand. When there are two operands, + DEST is the one on the left. + + LeftSRC, RightSRC distinguishes between two operands when both are + source operands. + + eSP represents either the SP register or the ESP register depending on + the setting of the B-bit for the current stack segment. + +The following functions are used in the algorithmic descriptions: + + Truncate to 16 bits(value) reduces the size of the value to fit in 16 + bits by discarding the uppermost bits as needed. + + Addr(operand) returns the effective address of the operand (the result + of the effective address calculation prior to adding the segment base). + + ZeroExtend(value) returns a value zero-extended to the operand-size + attribute of the instruction. For example, if OperandSize = 32, + ZeroExtend of a byte value of -10 converts the byte from F6H to + doubleword with hexadecimal value 000000F6H. If the value passed to + ZeroExtend and the operand-size attribute are the same size, + ZeroExtend returns the value unaltered. + + SignExtend(value) returns a value sign-extended to the operand-size + attribute of the instruction. For example, if OperandSize = 32, + SignExtend of a byte containing the value -10 converts the byte from + F6H to a doubleword with hexadecimal value FFFFFFF6H. If the value + passed to SignExtend and the operand-size attribute are the same size, + SignExtend returns the value unaltered. + + Push(value) pushes a value onto the stack. The number of bytes pushed + is determined by the operand-size attribute of the instruction. The + action of Push is as follows: + + IF StackAddrSize = 16 + THEN + IF OperandSize = 16 + THEN + SP  SP - 2; + SS:[SP]  value; (* 2 bytes assigned starting at + byte address in SP *) + ELSE (* OperandSize = 32 *) + SP  SP - 4; + SS:[SP]  value; (* 4 bytes assigned starting at + byte address in SP *) + FI; + ELSE (* StackAddrSize = 32 *) + IF OperandSize = 16 + THEN + ESP  ESP - 2; + SS:[ESP]  value; (* 2 bytes assigned starting at + byte address in ESP*) + ELSE (* OperandSize = 32 *) + ESP  ESP - 4; + SS:[ESP]  value; (* 4 bytes assigned starting at + byte address in ESP*) + FI; + FI; + + Pop(value) removes the value from the top of the stack and returns it. + The statement EAX  Pop( ); assigns to EAX the 32-bit value that Pop + took from the top of the stack. Pop will return either a word or a + doubleword depending on the operand-size attribute. The action of Pop + is as follows: + + IF StackAddrSize = 16 + THEN + IF OperandSize = 16 + THEN + ret val  SS:[SP]; (* 2-byte value *) + SP  SP + 2; + ELSE (* OperandSize = 32 *) + ret val  SS:[SP]; (* 4-byte value *) + SP  SP + 4; + FI; + ELSE (* StackAddrSize = 32 *) + IF OperandSize = 16 + THEN + ret val  SS:[ESP]; (* 2 bytes value *) + ESP  ESP + 2; + ELSE (* OperandSize = 32 *) + ret val  SS:[ESP]; (* 4 bytes value *) + ESP  ESP + 4; + FI; + FI; + RETURN(ret val); (*returns a word or doubleword*) + + Bit[BitBase, BitOffset] returns the address of a bit within a bit + string, which is a sequence of bits in memory or a register. Bits are + numbered from low-order to high-order within registers and within + memory bytes. In memory, the two bytes of a word are stored with the + low-order byte at the lower address. + + If the base operand is a register, the offset can be in the range 0..31. + This offset addresses a bit within the indicated register. An example, + "BIT[EAX, 21]," is illustrated in Figure 17-3. + + If BitBase is a memory address, BitOffset can range from -2 gigabits to 2 + gigabits. The addressed bit is numbered (Offset MOD 8) within the byte at + address (BitBase + (BitOffset DIV 8)), where DIV is signed division with + rounding towards negative infinity, and MOD returns a positive number. + This is illustrated in Figure 17-4. + + I-O-Permission(I-O-Address, width) returns TRUE or FALSE depending on + the I/O permission bitmap and other factors. This function is defined as + follows: + + IF TSS type is 286 THEN RETURN FALSE; FI; + Ptr  [TSS + 66]; (* fetch bitmap pointer *) + BitStringAddr  SHR (I-O-Address, 3) + Ptr; + MaskShift  I-O-Address AND 7; + CASE width OF: + BYTE: nBitMask  1; + WORD: nBitMask  3; + DWORD: nBitMask  15; + ESAC; + mask  SHL (nBitMask, MaskShift); + CheckString  [BitStringAddr] AND mask; + IF CheckString = 0 + THEN RETURN (TRUE); + ELSE RETURN (FALSE); + FI; + + Switch-Tasks is the task switching function described in Chapter 7. + + +17.2.2.6 Description + +The "Description" section contains further explanation of the instruction's +operation. + + +Figure 17-3. Bit Offset for BIT[EAX, 21] + + 31 21 0 + ͻ + + ͼ +   + BITOFFSET = 21 + + +Figure 17-4. Memory Bit Indexing + + BIT INDEXING (POSITIVE OFFSET) + + 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + ͻ + + ͼ + BITBASE + 1 BITBASE BITBASE - 1 +  + OFFSET = 13 + + BIT INDEXING (NEGATIVE OFFSET) + + 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + ͻ + + ͼ + BITBASE BITBASE - 1 BITBASE - 2 +  + OFFSET = -11 + + +17.2.2.7 Flags Affected + +The "Flags Affected" section lists the flags that are affected by the +instruction, as follows: + + If a flag is always cleared or always set by the instruction, the + value is given (0 or 1) after the flag name. Arithmetic and logical + instructions usually assign values to the status flags in the uniform + manner described in Appendix C. Nonconventional assignments are + described in the "Operation" section. + + The values of flags listed as "undefined" may be changed by the + instruction in an indeterminate manner. + +All flags not listed are unchanged by the instruction. + + +17.2.2.8 Protected Mode Exceptions + +This section lists the exceptions that can occur when the instruction is +executed in 80386 Protected Mode. The exception names are a pound sign (#) +followed by two letters and an optional error code in parentheses. For +example, #GP(0) denotes a general protection exception with an error code of +0. Table 17-6 associates each two-letter name with the corresponding +interrupt number. + +Chapter 9 describes the exceptions and the 80386 state upon entry to the +exception. + +Application programmers should consult the documentation provided with +their operating systems to determine the actions taken when exceptions +occur. + + +Table 17-6. 80386 Exceptions + +Mnemonic Interrupt Description + +#UD 6 Invalid opcode +#NM 7 Coprocessor not available +#DF 8 Double fault +#TS 10 Invalid TSS +#NP 11 Segment or gate not present +#SS 12 Stack fault +#GP 13 General protection fault +#PF 14 Page fault +#MF 16 Math (coprocessor) fault + + +17.2.2.9 Real Address Mode Exceptions + +Because less error checking is performed by the 80386 in Real Address Mode, +this mode has fewer exception conditions. Refer to Chapter 14 for further +information on these exceptions. + + +17.2.2.10 Virtual-8086 Mode Exceptions + +Virtual 8086 tasks provide the ability to simulate Virtual 8086 machines. +Virtual 8086 Mode exceptions are similar to those for the 8086 processor, +but there are some differences. Refer to Chapter 15 for details. + + +AAA ASCII Adjust after Addition + +Opcode Instruction Clocks Description + +37 AAA 4 ASCII adjust AL after addition + + +Operation + +IF ((AL AND 0FH) > 9) OR (AF = 1) +THEN + AL  (AL + 6) AND 0FH; + AH  AH + 1; + AF  1; + CF  1; +ELSE + CF  0; + AF  0; +FI; + +Description + +Execute AAA only following an ADD instruction that leaves a byte result +in the AL register. The lower nibbles of the operands of the ADD instruction +should be in the range 0 through 9 (BCD digits). In this case, AAA adjusts +AL to contain the correct decimal digit result. If the addition produced a +decimal carry, the AH register is incremented, and the carry and auxiliary +carry flags are set to 1. If there was no decimal carry, the carry and +auxiliary flags are set to 0 and AH is unchanged. In either case, AL is left +with its top nibble set to 0. To convert AL to an ASCII result, follow the +AAA instruction with OR AL, 30H. + +Flags Affected + +AF and CF as described above; OF, SF, ZF, and PF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +AAD ASCII Adjust AX before Division + +Opcode Instruction Clocks Description + +D5 0A AAD 19 ASCII adjust AX before division + + +Operation + +AL  AH * 10 + AL; +AH  0; + +Description + +AAD is used to prepare two unpacked BCD digits (the least-significant +digit in AL, the most-significant digit in AH) for a division operation that +will yield an unpacked result. This is accomplished by setting AL to +AL + (10 * AH), and then setting AH to 0. AX is then equal to the binary +equivalent of the original unpacked two-digit number. + +Flags Affected + +SF, ZF, and PF as described in Appendix C; OF, AF, and CF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +AAM ASCII Adjust AX after Multiply + +Opcode Instruction Clocks Description + +D4 0A AAM 17 ASCII adjust AX after multiply + + +Operation + +AH  AL / 10; +AL  AL MOD 10; + +Description + +Execute AAM only after executing a MUL instruction between two unpacked +BCD digits that leaves the result in the AX register. Because the result is +less than 100, it is contained entirely in the AL register. AAM unpacks the +AL result by dividing AL by 10, leaving the quotient (most-significant +digit) in AH and the remainder (least-significant digit) in AL. + +Flags Affected + +SF, ZF, and PF as described in Appendix C; OF, AF, and CF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +AAS ASCII Adjust AL after Subtraction + +Opcode Instruction Clocks Description + +3F AAS 4 ASCII adjust AL after subtraction + + +Operation + +IF (AL AND 0FH) > 9 OR AF = 1 +THEN + AL  AL - 6; + AL  AL AND 0FH; + AH  AH - 1; + AF  1; + CF  1; +ELSE + CF  0; + AF  0; +FI; + +Description + +Execute AAS only after a SUB instruction that leaves the byte result in the +AL register. The lower nibbles of the operands of the SUB instruction must +have been in the range 0 through 9 (BCD digits). In this case, AAS adjusts +AL so it contains the correct decimal digit result. If the subtraction +produced a decimal carry, the AH register is decremented, and the carry and +auxiliary carry flags are set to 1. If no decimal carry occurred, the carry +and auxiliary carry flags are set to 0, and AH is unchanged. In either case, +AL is left with its top nibble set to 0. To convert AL to an ASCII result, +follow the AAS with OR AL, 30H. + +Flags Affected + +AF and CF as described above; OF, SF, ZF, and PF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +ADC Add with Carry + + +Opcode Instruction Clocks Description + +14 ib ADC AL,imm8 2 Add with carry immediate byte to AL +15 iw ADC AX,imm16 2 Add with carry immediate word to AX +15 id ADC EAX,imm32 2 Add with carry immediate dword to EAX +80 /2 ib ADC r/m8,imm8 2/7 Add with carry immediate byte to r/m + byte +81 /2 iw ADC r/m16,imm16 2/7 Add with carry immediate word to r/m + word +81 /2 id ADC r/m32,imm32 2/7 Add with CF immediate dword to r/m + dword +83 /2 ib ADC r/m16,imm8 2/7 Add with CF sign-extended immediate + byte to r/m word +83 /2 ib ADC r/m32,imm8 2/7 Add with CF sign-extended immediate + byte into r/m dword +10 /r ADC r/m8,r8 2/7 Add with carry byte register to r/m + byte +11 /r ADC r/m16,r16 2/7 Add with carry word register to r/m + word +11 /r ADC r/m32,r32 2/7 Add with CF dword register to r/m dword +12 /r ADC r8,r/m8 2/6 Add with carry r/m byte to byte + register +13 /r ADC r16,r/m16 2/6 Add with carry r/m word to word + register +13 /r ADC r32,r/m32 2/6 Add with CF r/m dword to dword register + + +Operation + +DEST  DEST + SRC + CF; + +Description + +ADC performs an integer addition of the two operands DEST and SRC and the +carry flag, CF. The result of the addition is assigned to the first operand +(DEST), and the flags are set accordingly. ADC is usually executed as part +of a multi-byte or multi-word addition operation. When an immediate byte +value is added to a word or doubleword operand, the immediate value is first +sign-extended to the size of the word or doubleword operand. + +Flags Affected + +OF, SF, ZF, AF, CF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) if page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +ADD Add + +Opcode Instruction Clocks Description + +04 ib ADD AL,imm8 2 Add immediate byte to AL +05 iw ADD AX,imm16 2 Add immediate word to AX +05 id ADD EAX,imm32 2 Add immediate dword to EAX +80 /0 ib ADD r/m8,imm8 2/7 Add immediate byte to r/m byte +81 /0 iw ADD r/m16,imm16 2/7 Add immediate word to r/m word +81 /0 id ADD r/m32,imm32 2/7 Add immediate dword to r/m dword +83 /0 ib ADD r/m16,imm8 2/7 Add sign-extended immediate byte + to r/m word +83 /0 ib ADD r/m32,imm8 2/7 Add sign-extended immediate byte + to r/m dword +00 /r ADD r/m8,r8 2/7 Add byte register to r/m byte +01 /r ADD r/m16,r16 2/7 Add word register to r/m word +01 /r ADD r/m32,r32 2/7 Add dword register to r/m dword +02 /r ADD r8,r/m8 2/6 Add r/m byte to byte register +03 /r ADD r16,r/m16 2/6 Add r/m word to word register +03 /r ADD r32,r/m32 2/6 Add r/m dword to dword register + + +Operation + +DEST  DEST + SRC; + +Description + +ADD performs an integer addition of the two operands (DEST and SRC). The +result of the addition is assigned to the first operand (DEST), and the +flags are set accordingly. + +When an immediate byte is added to a word or doubleword operand, the +immediate value is sign-extended to the size of the word or doubleword +operand. + +Flags Affected + +OF, SF, ZF, AF, CF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +AND Logical AND + +Opcode Instruction Clocks Description + +24 ib AND AL,imm8 2 AND immediate byte to AL +25 iw AND AX,imm16 2 AND immediate word to AX +25 id AND EAX,imm32 2 AND immediate dword to EAX +80 /4 ib AND r/m8,imm8 2/7 AND immediate byte to r/m byte +81 /4 iw AND r/m16,imm16 2/7 AND immediate word to r/m word +81 /4 id AND r/m32,imm32 2/7 AND immediate dword to r/m dword +83 /4 ib AND r/m16,imm8 2/7 AND sign-extended immediate byte + with r/m word +83 /4 ib AND r/m32,imm8 2/7 AND sign-extended immediate byte + with r/m dword +20 /r AND r/m8,r8 2/7 AND byte register to r/m byte +21 /r AND r/m16,r16 2/7 AND word register to r/m word +21 /r AND r/m32,r32 2/7 AND dword register to r/m dword +22 /r AND r8,r/m8 2/6 AND r/m byte to byte register +23 /r AND r16,r/m16 2/6 AND r/m word to word register +23 /r AND r32,r/m32 2/6 AND r/m dword to dword register + + +Operation + +DEST  DEST AND SRC; +CF  0; +OF  0; + +Description + +Each bit of the result of the AND instruction is a 1 if both corresponding +bits of the operands are 1; otherwise, it becomes a 0. + +Flags Affected + +CF = 0, OF = 0; PF, SF, and ZF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +ARPL Adjust RPL Field of Selector + +Opcode Instruction Clocks Description + +63 /r ARPL r/m16,r16 pm=20/21 Adjust RPL of r/m16 to not + less than RPL of r16 + + +Operation + +IF RPL bits(0,1) of DEST < RPL bits(0,1) of SRC +THEN + ZF  1; + RPL bits(0,1) of DEST  RPL bits(0,1) of SRC; +ELSE + ZF  0; +FI; + +Description + +The ARPL instruction has two operands. The first operand is a 16-bit +memory variable or word register that contains the value of a selector. The +second operand is a word register. If the RPL field ("requested privilege +level"bottom two bits) of the first operand is less than the RPL field of +the second operand, the zero flag is set to 1 and the RPL field of the +first operand is increased to match the second operand. Otherwise, the zero +flag is set to 0 and no change is made to the first operand. + +ARPL appears in operating system software, not in application programs. It +is used to guarantee that a selector parameter to a subroutine does not +request more privilege than the caller is allowed. The second operand of +ARPL is normally a register that contains the CS selector value of the +caller. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 6; ARPL is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BOUND Check Array Index Against Bounds + +Opcode Instruction Clocks Description + +62 /r BOUND r16,m16&16 10 Check if r16 is within bounds + (passes test) +62 /r BOUND r32,m32&32 10 Check if r32 is within bounds + (passes test) + + +Operation + +IF (LeftSRC < [RightSRC] OR LeftSRC > [RightSRC + OperandSize/8]) + (* Under lower bound or over upper bound *) +THEN Interrupt 5; +FI; + +Description + +BOUND ensures that a signed array index is within the limits specified by a +block of memory consisting of an upper and a lower bound. Each bound uses +one word for an operand-size attribute of 16 bits and a doubleword for an +operand-size attribute of 32 bits. The first operand (a register) must be +greater than or equal to the first bound in memory (lower bound), and less +than or equal to the second bound in memory (upper bound). If the register +is not within bounds, an Interrupt 5 occurs; the return EIP points to the +BOUND instruction. + +The bounds limit data structure is usually placed just before the array +itself, making the limits addressable via a constant offset from the +beginning of the array. + +Flags Affected + +None + +Protected Mode Exceptions + +Interrupt 5 if the bounds test fails, as described above; #GP(0) for an +illegal memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +The second operand must be a memory operand, not a register. If BOUND is +executed with a ModRM byte representing a register as the second operand, +#UD occurs. + +Real Address Mode Exceptions + +Interrupt 5 if the bounds test fails; Interrupt 13 if any part of the +operand would lie outside of the effective address space from 0 to 0FFFFH; +Interrupt 6 if the second operand is a register + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BSF Bit Scan Forward + +Opcode Instruction Clocks Description + +0F BC BSF r16,r/m16 10+3n Bit scan forward on r/m word +0F BC BSF r32,r/m32 10+3n Bit scan forward on r/m dword + + +Notes + + is the number of leading zero bits. + +Operation + +IF r/m = 0 +THEN + ZF  1; + register  UNDEFINED; +ELSE + temp  0; + ZF  0; + WHILE BIT[r/m, temp = 0] + DO + temp  temp + 1; + register  temp; + OD; +FI; + +Description + +BSF scans the bits in the second word or doubleword operand starting with +bit 0. The ZF flag is cleared if the bits are all 0; otherwise, the ZF flag +is set and the destination register is loaded with the bit index of the +first set bit. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BSR Bit Scan Reverse + +Opcode Instruction Clocks Description + +0F BD BSR r16,r/m16 10+3n Bit scan reverse on r/m word +0F BD BSR r32,r/m32 10+3n Bit scan reverse on r/m dword + + +Operation + +IF r/m = 0 +THEN + ZF  1; + register  UNDEFINED; +ELSE + temp  OperandSize - 1; + ZF  0; + WHILE BIT[r/m, temp] = 0 + DO + temp  temp - 1; + register  temp; + OD; +FI; + +Description + +BSR scans the bits in the second word or doubleword operand from the most +significant bit to the least significant bit. The ZF flag is cleared if the +bits are all 0; otherwise, ZF is set and the destination register is loaded +with the bit index of the first set bit found when scanning in the reverse +direction. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BT Bit Test + +Opcode Instruction Clocks Description + +0F A3 BT r/m16,r16 3/12 Save bit in carry flag +0F A3 BT r/m32,r32 3/12 Save bit in carry flag +0F BA /4 ib BT r/m16,imm8 3/6 Save bit in carry flag +0F BA /4 ib BT r/m32,imm8 3/6 Save bit in carry flag + + +Operation + +CF  BIT[LeftSRC, RightSRC]; + +Description + +BT saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 are supported by using the immediate bit offset field in +combination with the displacement field of the memory operand. The low-order +3 to 5 bits of the immediate bit offset are stored in the immediate bit +offset field, and the high-order 27 to 29 bits are shifted and combined with +the byte displacement in the addressing mode. + +When accessing a bit in memory, the 80386 may access four bytes starting +from the memory address given by: + + Effective Address + (4 * (BitOffset DIV 32)) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + (2 * (BitOffset DIV 16)) + +for a 16-bit operand size. It may do so even when only a single byte needs +to be accessed in order to reach the given bit. You must therefore avoid +referencing areas of memory close to address space holes. In particular, +avoid references to memory-mapped I/O registers. Instead, use the MOV +instructions to load from or store to these addresses, and use the register +form of these instructions to manipulate the data. + + +BTC Bit Test and Complement + +Opcode Instruction Clocks Description + +0F BB BTC r/m16,r16 6/13 Save bit in carry flag and complement +0F BB BTC r/m32,r32 6/13 Save bit in carry flag and complement +0F BA /7 ib BTC r/m16,imm8 6/8 Save bit in carry flag and complement +0F BA /7 ib BTC r/m32,imm8 6/8 Save bit in carry flag and complement + + +Operation + +CF  BIT[LeftSRC, RightSRC]; +BIT[LeftSRC, RightSRC]  NOT BIT[LeftSRC, RightSRC]; + +Description + +BTC saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag and then complements the +bit. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 are supported by using the immediate bit offset field in +combination with the displacement field of the memory operand. The low-order +3 to 5 bits of the immediate bit offset are stored in the immediate bit +offset field, and the high-order 27 to 29 bits are shifted and combined with +the byte displacement in the addressing mode. + +When accessing a bit in memory, the 80386 may access four bytes starting +from the memory address given by: + + Effective Address + (4 * (BitOffset DIV 32)) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + (2 * (BitOffset DIV 16)) + +for a 16-bit operand size. It may do so even when only a single byte needs +to be accessed in order to reach the given bit. You must therefore avoid +referencing areas of memory close to address space holes. In particular, +avoid references to memory-mapped I/O registers. Instead, use the MOV +instructions to load from or store to these addresses, and use the register +form of these instructions to manipulate the data. + + +BTR Bit Test and Reset + +Opcode Instruction Clocks Description + +0F B3 BTR r/m16,r16 6/13 Save bit in carry flag and reset +0F B3 BTR r/m32,r32 6/13 Save bit in carry flag and reset +0F BA /6 ib BTR r/m16,imm8 6/8 Save bit in carry flag and reset +0F BA /6 ib BTR r/m32,imm8 6/8 Save bit in carry flag and reset + + +Operation + +CF  BIT[LeftSRC, RightSRC]; +BIT[LeftSRC, RightSRC]  0; + +Description + +BTR saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag and then stores 0 in the +bit. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 (or 15) are supported by using the immediate bit offset field +in combination with the displacement field of the memory operand. The +low-order 3 to 5 bits of the immediate bit offset are stored in the +immediate bit offset field, and the high-order 27 to 29 bits are shifted and +combined with the byte displacement in the addressing mode. + +When accessing a bit in memory, the 80386 may access four bytes starting +from the memory address given by: + + Effective Address + 4 * (BitOffset DIV 32) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + 2 * (BitOffset DIV 16) + +for a 16-bit operand size. It may do so even when only a single byte needs +to be accessed in order to reach the given bit. You must therefore avoid +referencing areas of memory close to address space holes. In particular, +avoid references to memory-mapped I/O registers. Instead, use the MOV +instructions to load from or store to these addresses, and use the register +form of these instructions to manipulate the data. + + +BTS Bit Test and Set + +Opcode Instruction Clocks Description + +0F AB BTS r/m16,r16 6/13 Save bit in carry flag and set +0F AB BTS r/m32,r32 6/13 Save bit in carry flag and set +0F BA /5 ib BTS r/m16,imm8 6/8 Save bit in carry flag and set +0F BA /5 ib BTS r/m32,imm8 6/8 Save bit in carry flag and set + + +Operation + +CF  BIT[LeftSRC, RightSRC]; +BIT[LeftSRC, RightSRC]  1; + +Description + +BTS saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag and then stores 1 in the +bit. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 are supported by using the immediate bit offset field in +combination with the displacement field of the memory operand. The +low-order 3 to 5 bits of the immediate bit offset are stored in the +immediate bit offset field, and the high order 27 to 29 bits are shifted and +combined with the byte displacement in the addressing mode. + +When accessing a bit in memory, the processor may access four bytes starting +from the memory address given by: + + Effective Address + (4 * (BitOffset DIV 32)) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + (2 * (BitOffset DIV 16)) + +for a 16-bit operand size. It may do this even when only a single byte needs +to be accessed in order to get at the given bit. Thus the programmer must be +careful to avoid referencing areas of memory close to address space holes. +In particular, avoid references to memory-mapped I/O registers. Instead, use +the MOV instructions to load from or store to these addresses, and use the +register form of these instructions to manipulate the data. + + +CALL Call Procedure + + +Opcode Instruction Clocks + Values of ts are given by the following table: + + New Task + 386 TSS 386 TSS 286 TSS + Old VM = 0 VM = 1 + Task Via Task Gate? + + N Y N Y N Y + +386 300 309 217 226 273 282 +TSS VM=0 + +286 298 307 217 226 273 282 +TSS Description + +E8 cw CALL rel16 7+m Call near, displacement relative + to next instruction +FF /2 CALL r/m16 7+m/10+m Call near, register + indirect/memory indirect +9A cd CALL ptr16:16 17+m,pm=34+m Call intersegment, to full + pointer given +9A cd CALL ptr16:16 pm=52+m Call gate, same privilege +9A cd CALL ptr16:16 pm=86+m Call gate, more privilege, no + parameters +9A cd CALL ptr16:16 pm=94+4x+m Call gate, more privilege, x + parameters +9A cd CALL ptr16:16 ts Call to task +FF /3 CALL m16:16 22+m,pm=38+m Call intersegment, address at + r/m dword +FF /3 CALL m16:16 pm=56+m Call gate, same privilege +FF /3 CALL m16:16 pm=90+m Call gate, more privilege, no + parameters +FF /3 CALL m16:16 pm=98+4x+m Call gate, more privilege, x + parameters +FF /3 CALL m16:16 5 + ts Call to task +E8 cd CALL rel32 7+m Call near, displacement relative + to next instruction +FF /2 CALL r/m32 7+m/10+m Call near, indirect +9A cp CALL ptr16:32 17+m,pm=34+m Call intersegment, to full + pointer given +9A cp CALL ptr16:32 pm=52+m Call gate, same privilege +9A cp CALL ptr16:32 pm=86+m Call gate, more privilege, no + parameters +9A cp CALL ptr32:32 pm=94+4x+m Call gate, more privilege, x + parameters +9A cp CALL ptr16:32 ts Call to task +FF /3 CALL m16:32 22+m,pm=38+m Call intersegment, address at + r/m dword +FF /3 CALL m16:32 pm=56+m Call gate, same privilege +FF /3 CALL m16:32 pm=90+m Call gate, more privilege, no + parameters +FF /3 CALL m16:32 pm=98+4x+m Call gate, more privilege, x + parameters +FF /3 CALL m16:32 5 + ts Call to task + + + +NOTE: + Values of ts are given by the following table: + + New Task + 386 TSS 386 TSS 286 TSS + Old VM = 0 VM = 1 + Task Via Task Gate? + + N Y N Y N Y + +386 300 309 217 226 273 282 +TSS VM=0 + +286 298 307 217 226 273 282 +TSS + + +Operation + +IF rel16 or rel32 type of call +THEN (* near relative call *) + IF OperandSize = 16 + THEN + Push(IP); + EIP  (EIP + rel16) AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + Push(EIP); + EIP  EIP + rel32; + FI; +FI; + +IF r/m16 or r/m32 type of call +THEN (* near absolute call *) + IF OperandSize = 16 + THEN + Push(IP); + EIP  [r/m16] AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + Push(EIP); + EIP  [r/m32]; + FI; +FI; + +IF (PE = 0 OR (PE = 1 AND VM = 1)) +(* real mode or virtual 8086 mode *) + AND instruction = far CALL + (* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *) +THEN + IF OperandSize = 16 + THEN + Push(CS); + Push(IP); (* address of next instruction; 16 bits *) + ELSE + Push(CS); (* padded with 16 high-order bits *) + Push(EIP); (* address of next instruction; 32 bits *) + FI; + IF operand type is m16:16 or m16:32 + THEN (* indirect far call *) + IF OperandSize = 16 + THEN + CS:IP  [m16:16]; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  [m16:32]; + FI; + FI; + IF operand type is ptr16:16 or ptr16:32 + THEN (* direct far call *) + IF OperandSize = 16 + THEN + CS:IP  ptr16:16; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  ptr16:32; + FI; + FI; +FI; + +IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *) + AND instruction = far CALL +THEN + If indirect, then check access of EA doubleword; + #GP(0) if limit violation; + New CS selector must not be null else #GP(0); + Check that new CS selector index is within its + descriptor table limits; else #GP(new CS selector); + Examine AR byte of selected descriptor for various legal values; + depending on value: + go to CONFORMING-CODE-SEGMENT; + go to NONCONFORMING-CODE-SEGMENT; + go to CALL-GATE; + go to TASK-GATE; + go to TASK-STATE-SEGMENT; + ELSE #GP(code segment selector); +FI; + +CONFORMING-CODE-SEGMENT: + DPL must be CPL ELSE #GP(code segment selector); + Segment must be present ELSE #NP(code segment selector); + Stack must be big enough for return address ELSE #SS(0); + Instruction pointer must be in code segment limit ELSE #GP(0); + Load code segment descriptor into CS register; + Load CS with new code segment selector; + Load EIP with zero-extend(new offset); + IF OperandSize=16 THEN EIP  EIP AND 0000FFFFH; FI; + +NONCONFORMING-CODE-SEGMENT: + RPL must be CPL ELSE #GP(code segment selector) + DPL must be = CPL ELSE #GP(code segment selector) + Segment must be present ELSE #NP(code segment selector) + Stack must be big enough for return address ELSE #SS(0) + Instruction pointer must be in code segment limit ELSE #GP(0) + Load code segment descriptor into CS register + Load CS with new code segment selector + Set RPL of CS to CPL + Load EIP with zero-extend(new offset); + IF OperandSize=16 THEN EIP  EIP AND 0000FFFFH; FI; + +CALL-GATE: + Call gate DPL must be CPL ELSE #GP(call gate selector) + Call gate DPL must be RPL ELSE #GP(call gate selector) + Call gate must be present ELSE #NP(call gate selector) + Examine code segment selector in call gate descriptor: + Selector must not be null ELSE #GP(0) + Selector must be within its descriptor table + limits ELSE #GP(code segment selector) + AR byte of selected descriptor must indicate code + segment ELSE #GP(code segment selector) + DPL of selected descriptor must be CPL ELSE + #GP(code segment selector) + IF non-conforming code segment AND DPL < CPL + THEN go to MORE-PRIVILEGE + ELSE go to SAME-PRIVILEGE + FI; + +MORE-PRIVILEGE: + Get new SS selector for new privilege level from TSS + Check selector and descriptor for new SS: + Selector must not be null ELSE #TS(0) + Selector index must be within its descriptor + table limits ELSE #TS(SS selector) + Selector's RPL must equal DPL of code segment + ELSE #TS(SS selector) + Stack segment DPL must equal DPL of code + segment ELSE #TS(SS selector) + Descriptor must indicate writable data segment + ELSE #TS(SS selector) + Segment present ELSE #SS(SS selector) + IF OperandSize=32 + THEN + New stack must have room for parameters plus 16 bytes + ELSE #SS(0) + EIP must be in code segment limit ELSE #GP(0) + Load new SS:eSP value from TSS + Load new CS:EIP value from gate + ELSE + New stack must have room for parameters plus 8 bytes ELSE #SS(0) + IP must be in code segment limit ELSE #GP(0) + Load new SS:eSP value from TSS + Load new CS:IP value from gate + FI; + Load CS descriptor + Load SS descriptor + Push long pointer of old stack onto new stack + Get word count from call gate, mask to 5 bits + Copy parameters from old stack onto new stack + Push return address onto new stack + Set CPL to stack segment DPL + Set RPL of CS to CPL + +SAME-PRIVILEGE: + IF OperandSize=32 + THEN + Stack must have room for 6-byte return address (padded to 8 bytes) + ELSE #SS(0) + EIP must be within code segment limit ELSE #GP(0) + Load CS:EIP from gate + ELSE + Stack must have room for 4-byte return address ELSE #SS(0) + IP must be within code segment limit ELSE #GP(0) + Load CS:IP from gate + FI; + Push return address onto stack + Load code segment descriptor into CS register + Set RPL of CS to CPL + +TASK-GATE: + Task gate DPL must be CPL ELSE #TS(gate selector) + Task gate DPL must be RPL ELSE #TS(gate selector) + Task Gate must be present ELSE #NP(gate selector) + Examine selector to TSS, given in Task Gate descriptor: + Must specify global in the local/global bit ELSE #TS(TSS selector) + Index must be within GDT limits ELSE #TS(TSS selector) + TSS descriptor AR byte must specify nonbusy TSS + ELSE #TS(TSS selector) + Task State Segment must be present ELSE #NP(TSS selector) + SWITCH-TASKS (with nesting) to TSS + IP must be in code segment limit ELSE #TS(0) + +TASK-STATE-SEGMENT: + TSS DPL must be CPL else #TS(TSS selector) + TSS DPL must be RPL ELSE #TS(TSS selector) + TSS descriptor AR byte must specify available TSS + ELSE #TS(TSS selector) + Task State Segment must be present ELSE #NP(TSS selector) + SWITCH-TASKS (with nesting) to TSS + IP must be in code segment limit ELSE #TS(0) + +Description + +The CALL instruction causes the procedure named in the operand to be +executed. When the procedure is complete (a return instruction is executed +within the procedure), execution continues at the instruction that follows +the CALL instruction. + +The action of the different forms of the instruction are described below. + +Near calls are those with destinations of type r/m16, r/m32, rel16, rel32; +changing or saving the segment register value is not necessary. The CALL +rel16 and CALL rel32 forms add a signed offset to the address of the +instruction following CALL to determine the destination. The rel16 form is +used when the instruction's operand-size attribute is 16 bits; rel32 is used +when the operand-size attribute is 32 bits. The result is stored in the +32-bit EIP register. With rel16, the upper 16 bits of EIP are cleared, +resulting in an offset whose value does not exceed 16 bits. CALL r/m16 and +CALL r/m32 specify a register or memory location from which the absolute +segment offset is fetched. The offset fetched from r/m is 32 bits for an +operand-size attribute of 32 (r/m32), or 16 bits for an operand-size of 16 +(r/m16). The offset of the instruction following CALL is pushed onto the +stack. It will be popped by a near RET instruction within the procedure. The +CS register is not changed by this form of CALL. + +The far calls, CALL ptr16:16 and CALL ptr16:32, use a four-byte or six-byte +operand as a long pointer to the procedure called. The CALL m16:16 and +m16:32 forms fetch the long pointer from the memory location +specified (indirection). In Real Address Mode or Virtual 8086 Mode, the long +pointer provides 16 bits for the CS register and 16 or 32 bits for the EIP +register (depending on the operand-size attribute). These forms of the +instruction push both CS and IP or EIP as a return address. + +In Protected Mode, both long pointer forms consult the AR byte in the +descriptor indexed by the selector part of the long pointer. Depending on +the value of the AR byte, the call will perform one of the following types +of control transfers: + + A far call to the same protection level + An inter-protection level far call + A task switch + +For more information on Protected Mode control transfers, refer to +Chapter 6 and Chapter 7. + +Flags Affected + +All flags are affected if a task switch occurs; no flags are affected if a +task switch does not occur + +Protected Mode Exceptions + +For far calls: #GP, #NP, #SS, and #TS, as indicated in the list above + +For near direct calls: #GP(0) if procedure location is beyond the code +segment limits; #SS(0) if pushing the return address exceeds the bounds of +the stack segment; #PF (fault-code) for a page fault + +For a near indirect call: #GP(0) for an illegal memory operand effective +address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address +in the SS segment; #GP(0) if the indirect offset obtained is beyond the code +segment limits; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +Any far call from a 32-bit code segment to 16-bit code segments should be +made from the first 64K bytes of the 32-bit code segment, since the +operand-size attribute of the instruction is set to 16, thus allowing only a +16-bit return address offset to be saved. + + +CBW/CWDE Convert Byte to Word/Convert Word to Doubleword + +Opcode Instruction Clocks Description + +98 CBW 3 AX  sign-extend of AL +98 CWDE 3 EAX  sign-extend of AX + + +Operation + +IF OperandSize = 16 (* instruction = CBW *) +THEN AX  SignExtend(AL); +ELSE (* OperandSize = 32, instruction = CWDE *) + EAX  SignExtend(AX); +FI; + +Description + +CBW converts the signed byte in AL to a signed word in AX by extending the +most significant bit of AL (the sign bit) into all of the bits of AH. CWDE +converts the signed word in AX to a doubleword in EAX by extending the most +significant bit of AX into the two most significant bytes of EAX. Note that +CWDE is different from CWD. CWD uses DX:AX rather than EAX as a destination. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CLC Clear Carry Flag + +Opcode Instruction Clocks Description + +F8 CLC 2 Clear carry flag + + +Operation + +CF  0; + +Description + +CLC sets the carry flag to zero. It does not affect other flags or +registers. + +Flags Affected + +CF = 0 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CLD Clear Direction Flag + +Opcode Instruction Clocks Description + +FC CLD 2 Clear direction flag; SI and DI + will increment during string + instructions + + +Operation + +DF  0; + +Description + +CLD clears the direction flag. No other flags or registers are affected. +After CLD is executed, string operations will increment the index registers +(SI and/or DI) that they use. + +Flags Affected + +DF = 0 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CLI Clear Interrupt Flag + +Opcode Instruction Clocks Description + +FA CLI 3 Clear interrupt flag; interrupts disabled + + +Operation + +IF  0; + +Description + +CLI clears the interrupt flag if the current privilege level is at least as +privileged as IOPL. No other flags are affected. External interrupts are not +recognized at the end of the CLI instruction or from that point on until the +interrupt flag is set. + +Flags Affected + +IF = 0 + +Protected Mode Exceptions + +#GP(0) if the current privilege level is greater (has less privilege) than +the IOPL in the flags register. IOPL specifies the least privileged level at +which I/O can be performed. + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) as for Protected Mode + + +CLTS Clear Task-Switched Flag in CR0 + +Opcode Instruction Clocks Description + +OF 06 CLTS 5 Clear task-switched flag + + +Operation + +TS Flag in CR0  0; + +Description + +CLTS clears the task-switched (TS) flag in register CR0. This flag is set by +the 80386 every time a task switch occurs. The TS flag is used to manage +processor extensions as follows: + + Every execution of an ESC instruction is trapped if the TS flag is set. + + Execution of a WAIT instruction is trapped if the MP flag and the TS + flag are both set. + +Thus, if a task switch was made after an ESC instruction was begun, the +processor extension's context may need to be saved before a new ESC +instruction can be issued. The fault handler saves the context and resets +the TS flag. + +CLTS appears in operating system software, not in application programs. It +is a privileged instruction that can only be executed at privilege level 0. + +Flags Affected + +TS = 0 (TS is in CR0, not the flag register) + +Protected Mode Exceptions + +#GP(0) if CLTS is executed with a current privilege level other than 0 + +Real Address Mode Exceptions + +None (valid in Real Address Mode to allow initialization for Protected +Mode) + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +CMC Complement Carry Flag + +Opcode Instruction Clocks Description + +F5 CMC 2 Complement carry flag + + +Operation + +CF  NOT CF; + +Description + +CMC reverses the setting of the carry flag. No other flags are affected. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CMP Compare Two Operands + + +Opcode Instruction Clocks Description + +3C ib CMP AL,imm8 2 Compare immediate byte to AL +3D iw CMP AX,imm16 2 Compare immediate word to AX +3D id CMP EAX,imm32 2 Compare immediate dword to EAX +80 /7 ib CMP r/m8,imm8 2/5 Compare immediate byte to r/m + byte +81 /7 iw CMP r/m16,imm16 2/5 Compare immediate word to r/m + word +81 /7 id CMP r/m32,imm32 2/5 Compare immediate dword to r/m + dword +83 /7 ib CMP r/m16,imm8 2/5 Compare sign extended immediate + byte to r/m word +83 /7 ib CMP r/m32,imm8 2/5 Compare sign extended immediate + byte to r/m dword +38 /r CMP r/m8,r8 2/5 Compare byte register to r/m + byte +39 /r CMP r/m16,r16 2/5 Compare word register to r/m + word +39 /r CMP r/m32,r32 2/5 Compare dword register to r/m + dword +3A /r CMP r8,r/m8 2/6 Compare r/m byte to byte + register +3B /r CMP r16,r/m16 2/6 Compare r/m word to word + register +3B /r CMP r32,r/m32 2/6 Compare r/m dword to dword + register + + +Operation + +LeftSRC - SignExtend(RightSRC); +(* CMP does not store a result; its purpose is to set the flags *) + +Description + +CMP subtracts the second operand from the first but, unlike the SUB +instruction, does not store the result; only the flags are changed. CMP is +typically used in conjunction with conditional jumps and the SETcc +instruction. (Refer to Appendix D for the list of signed and unsigned flag +tests provided.) If an operand greater than one byte is compared to an +immediate byte, the byte value is first sign-extended. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +CMPS/CMPSB/CMPSW/CMPSD Compare String Operands + +Opcode Instruction Clocks Description + +A6 CMPS m8,m8 10 Compare bytes ES:[(E)DI] (second + operand) with [(E)SI] (first + operand) +A7 CMPS m16,m16 10 Compare words ES:[(E)DI] (second + operand) with [(E)SI] (first + operand) +A7 CMPS m32,m32 10 Compare dwords ES:[(E)DI] + (second operand) with [(E)SI] + (first operand) +A6 CMPSB 10 Compare bytes ES:[(E)DI] with + DS:[SI] +A7 CMPSW 10 Compare words ES:[(E)DI] with + DS:[SI] +A7 CMPSD 10 Compare dwords ES:[(E)DI] with + DS:[SI] + + +Operation + +IF (instruction = CMPSD) OR + (instruction has operands of type DWORD) +THEN OperandSize  32; +ELSE OperandSize  16; +FI; +IF AddressSize = 16 +THEN + use SI for source-index and DI for destination-index +ELSE (* AddressSize = 32 *) + use ESI for source-index and EDI for destination-index; +FI; +IF byte type of instruction +THEN + [source-index] - [destination-index]; (* byte comparison *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + [source-index] - [destination-index]; (* word comparison *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + [source-index] - [destination-index]; (* dword comparison *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index = source-index + IncDec; +destination-index = destination-index + IncDec; + +Description + +CMPS compares the byte, word, or doubleword pointed to by the source-index +register with the byte, word, or doubleword pointed to by the +destination-index register. + +If the address-size attribute of this instruction is 16 bits, SI and DI +will be used for source- and destination-index registers; otherwise ESI and +EDI will be used. Load the correct index values into SI and DI (or ESI and +EDI) before executing CMPS. + +The comparison is done by subtracting the operand indexed by +the destination-index register from the operand indexed by the source-index +register. + +Note that the direction of subtraction for CMPS is [SI] - [DI] or +[ESI] - [EDI]. The left operand (SI or ESI) is the source and the right +operand (DI or EDI) is the destination. This is the reverse of the usual +Intel convention in which the left operand is the destination and the right +operand is the source. + +The result of the subtraction is not stored; only the flags reflect the +change. The types of the operands determine whether bytes, words, or +doublewords are compared. For the first operand (SI or ESI), the DS register +is used, unless a segment override byte is present. The second operand (DI +or EDI) must be addressable from the ES register; no segment override is +possible. + +After the comparison is made, both the source-index register and +destination-index register are automatically advanced. If the direction flag +is 0 (CLD was executed), the registers increment; if the direction flag is 1 +(STD was executed), the registers decrement. The registers increment or +decrement by 1 if a byte is compared, by 2 if a word is compared, or by 4 if +a doubleword is compared. + +CMPSB, CMPSW and CMPSD are synonyms for the byte, word, and +doubleword CMPS instructions, respectively. + +CMPS can be preceded by the REPE or REPNE prefix for block comparison of CX +or ECX bytes, words, or doublewords. Refer to the description of the REP +instruction for more information on this operation. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF (fault-code) for a page fault + + +CWD/CDQ Convert Word to Doubleword/Convert Doubleword to + Quadword + +Opcode Instruction Clocks Description + +99 CWD 2 DX:AX  sign-extend of AX +99 CDQ 2 EDX:EAX  sign-extend of EAX + + +Operation + +IF OperandSize = 16 (* CWD instruction *) +THEN + IF AX < 0 THEN DX  0FFFFH; ELSE DX  0; FI; +ELSE (* OperandSize = 32, CDQ instruction *) + IF EAX < 0 THEN EDX  0FFFFFFFFH; ELSE EDX  0; FI; +FI; + +Description + +CWD converts the signed word in AX to a signed doubleword in DX:AX +by extending the most significant bit of AX into all the bits of DX. CDQ +converts the signed doubleword in EAX to a signed 64-bit integer in the +register pair EDX:EAX by extending the most significant bit of EAX +(the sign bit) into all the bits of EDX. Note that CWD is different from +CWDE. CWDE uses EAX as a destination, instead of DX:AX. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +DAA Decimal Adjust AL after Addition + +Opcode Instruction Clocks Description + +27 DAA 4 Decimal adjust AL after addition + + +Operation + +IF ((AL AND 0FH) > 9) OR (AF = 1) +THEN + AL  AL + 6; + AF  1; +ELSE + AF  0; +FI; +IF (AL > 9FH) OR (CF = 1) +THEN + AL  AL + 60H; + CF  1; +ELSE CF  0; +FI; + +Description + +Execute DAA only after executing an ADD instruction that leaves a +two-BCD-digit byte result in the AL register. The ADD operands should +consist of two packed BCD digits. The DAA instruction adjusts AL to +contain the correct two-digit packed decimal result. + +Flags Affected + +AF and CF as described above; SF, ZF, PF, and CF as described in +Appendix C. + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +DAS Decimal Adjust AL after Subtraction + +Opcode Instruction Clocks Description + +2F DAS 4 Decimal adjust AL after subtraction + + +Operation + +IF (AL AND 0FH) > 9 OR AF = 1 +THEN + AL  AL - 6; + AF  1; +ELSE + AF  0; +FI; +IF (AL > 9FH) OR (CF = 1) +THEN + AL  AL - 60H; + CF  1; +ELSE CF  0; +FI; + +Description + +Execute DAS only after a subtraction instruction that leaves a +two-BCD-digit byte result in the AL register. The operands should consist +of two packed BCD digits. DAS adjusts AL to contain the correct packed +two-digit decimal result. + +Flags Affected + +AF and CF as described above; SF, ZF, and PF as described in Appendix C. + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +DEC Decrement by 1 + +Opcode Instruction Clocks Description + +FE /1 DEC r/m8 2/6 Decrement r/m byte by 1 +FF /1 DEC r/m16 2/6 Decrement r/m word by 1 + DEC r/m32 2/6 Decrement r/m dword by 1 +48+rw DEC r16 2 Decrement word register by 1 +48+rw DEC r32 2 Decrement dword register by 1 + + +Operation + +DEST  DEST - 1; + +Description + +DEC subtracts 1 from the operand. DEC does not change the carry flag. +To affect the carry flag, use the SUB instruction with an immediate +operand of 1. + +Flags Affected + +OF, SF, ZF, AF, and PF as described in Appendix C. + +Protected Mode Exceptions + +#GP(0) if the result is a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +DIV Unsigned Divide + +Opcode Instruction Clocks Description + +F6 /6 DIV AL,r/m8 14/17 Unsigned divide AX by r/m byte + (AL=Quo, AH=Rem) +F7 /6 DIV AX,r/m16 22/25 Unsigned divide DX:AX by r/m + word (AX=Quo, DX=Rem) +F7 /6 DIV EAX,r/m32 38/41 Unsigned divide EDX:EAX by r/m + dword (EAX=Quo, EDX=Rem) + + +Operation + +temp  dividend / divisor; +IF temp does not fit in quotient +THEN Interrupt 0; +ELSE + quotient  temp; + remainder  dividend MOD (r/m); +FI; + + +Note: + Divisions are unsigned. The divisor is given by the r/m operand. + The dividend, quotient, and remainder use implicit registers. Refer to + the table under "Description." + + +Description + +DIV performs an unsigned division. The dividend is implicit; only the +divisor is given as an operand. The remainder is always less than the +divisor. The type of the divisor determines which registers to use as +follows: + + Size Dividend Divisor Quotient Remainder + byte AX r/m8 AL AH + word DX:AX r/m16 AX DX + dword EDX:EAX r/m32 EAX EDX + +Flags Affected + +OF, SF, ZF, AR, PF, CF are undefined. + +Protected Mode Exceptions + +Interrupt 0 if the quotient is too large to fit in the designated register +(AL, AX, or EAX), or if the divisor is 0; #GP(0) for an illegal memory +operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) +for an illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 0 if the quotient is too big to fit in the designated register +(AL, AX, or EAX), or if the divisor is 0; Interrupt 13 if any part of the +operand would lie outside of the effective address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +ENTER Make Stack Frame for Procedure Parameters + +Opcode Instruction Clocks Description + +C8 iw 00 ENTER imm16,0 10 Make procedure stack frame +C8 iw 01 ENTER imm16,1 12 Make stack frame for procedure + parameters +C8 iw ib ENTER imm16,imm8 15+4(n-1) Make stack frame for + procedure parameters + + +Operation + +level  level MOD 32 +IF OperandSize = 16 THEN Push(BP) ELSE Push (EBP) FI; + (* Save stack pointer *) +frame-ptr  eSP +IF level > 0 +THEN (* level is rightmost parameter *) + FOR i  1 TO level - 1 + DO + IF OperandSize = 16 + THEN + BP  BP - 2; + Push[BP] + ELSE (* OperandSize = 32 *) + EBP  EBP - 4; + Push[EBP]; + FI; + OD; + Push(frame-ptr) +FI; +IF OperandSize = 16 THEN BP  frame-ptr ELSE EBP  frame-ptr; FI; +IF StackAddrSize = 16 +THEN SP  SP - First operand; +ELSE ESP  ESP - ZeroExtend(First operand); +FI; + +Description + +ENTER creates the stack frame required by most block-structured +high-level languages. The first operand specifies the number of bytes of +dynamic storage allocated on the stack for the routine being entered. +The second operand gives the lexical nesting level (0 to 31) of the routine +within the high-level language source code. It determines the number of +stack frame pointers copied into the new stack frame from the preceding +frame. BP (or EBP, if the operand-size attribute is 32 bits) is the current +stack frame pointer. + +If the operand-size attribute is 16 bits, the processor uses BP as the +frame pointer and SP as the stack pointer. If the operand-size attribute is +32 bits, the processor uses EBP for the frame pointer and ESP for the stack +pointer. + +If the second operand is 0, ENTER pushes the frame pointer (BP or +EBP) onto the stack; ENTER then subtracts the first operand from the +stack pointer and sets the frame pointer to the current stack-pointer +value. + +For example, a procedure with 12 bytes of local variables would have an +ENTER 12,0 instruction at its entry point and a LEAVE instruction +before every RET. The 12 local bytes would be addressed as negative +offsets from the frame pointer. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if SP or ESP would exceed the stack limit at any point during +instruction execution; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +HLT Halt + +Opcode Instruction Clocks Description + +F4 HLT 5 Halt + + +Operation + +Enter Halt state; + +Description + +HALT stops instruction execution and places the 80386 in a HALT state. +An enabled interrupt, NMI, or a reset will resume execution. If an +interrupt (including NMI) is used to resume execution after HLT, the saved +CS:IP (or CS:EIP) value points to the instruction following HLT. + +Flags Affected + +None + +Protected Mode Exceptions + +HLT is a privileged instruction; #GP(0) if the current privilege level is +not 0 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0); HLT is a privileged instruction + + +IDIV Signed Divide + +Opcode Instruction Clocks Description + +F6 /7 IDIV r/m8 19 Signed divide AX by r/m byte + (AL=Quo, AH=Rem) +F7 /7 IDIV AX,r/m16 27 Signed divide DX:AX by EA word + (AX=Quo, DX=Rem) +F7 /7 IDIV EAX,r/m32 43 Signed divide EDX:EAX by DWORD + byte (EAX=Quo, EDX=Rem) + + +Operation + +temp  dividend / divisor; +IF temp does not fit in quotient +THEN Interrupt 0; +ELSE + quotient  temp; + remainder  dividend MOD (r/m); +FI; + + +Notes: + Divisions are signed. The divisor is given by the r/m operand. The + dividend, quotient, and remainder use implicit registers. Refer to the + table under "Description." + + +Description + +IDIV performs a signed division. The dividend, quotient, and remainder +are implicitly allocated to fixed registers. Only the divisor is given as +an explicit r/m operand. The type of the divisor determines which registers +to use as follows: + +Size Divisor Quotient Remainder Dividend +byte r/m8 AL AH AX +word r/m16 AX DX DX:AX +dword r/m32 EAX EDX EDX:EAX + +If the resulting quotient is too large to fit in the destination, or if the +division is 0, an Interrupt 0 is generated. Nonintegral quotients are +truncated toward 0. The remainder has the same sign as the dividend +and the absolute value of the remainder is always less than the absolute +value of the divisor. + +Flags Affected + +OF, SF, ZF, AR, PF, CF are undefined. + +Protected Mode Exceptions + +Interrupt 0 if the quotient is too large to fit in the designated register +(AL or AX), or if the divisor is 0; #GP (0) for an illegal memory operand +effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an +illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 0 if the quotient is too large to fit in the designated register +(AL or AX), or if the divisor is 0; Interrupt 13 if any part of the operand +would lie outside of the effective address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +IMUL Signed Multiply + + +Opcode Instruction Clocks Description + +F6 /5 IMUL r/m8 9-14/12-17 AX AL * r/m byte +F7 /5 IMUL r/m16 9-22/12-25 DX:AX  AX * r/m word +F7 /5 IMUL r/m32 9-38/12-41 EDX:EAX  EAX * r/m dword +0F AF /r IMUL r16,r/m16 9-22/12-25 word register  word + register * r/m word +0F AF /r IMUL r32,r/m32 9-38/12-41 dword register  dword + register * r/m dword +6B /r ib IMUL r16,r/m16,imm8 9-14/12-17 word register  r/m16 * + sign-extended immediate byte +6B /r ib IMUL r32,r/m32,imm8 9-14/12-17 dword register  r/m32 * + sign-extended immediate byte +6B /r ib IMUL r16,imm8 9-14/12-17 word register  word + register * sign-extended + immediate byte +6B /r ib IMUL r32,imm8 9-14/12-17 dword register  dword + register * sign-extended + immediate byte +69 /r iw IMUL r16,r/m16,imm16 9-22/12-25 word register  r/m16 * + immediate word +69 /r id IMUL r32,r/m32,imm32 9-38/12-41 dword register  r/m32 * + immediate dword +69 /r iw IMUL r16,imm16 9-22/12-25 word register  r/m16 * + immediate word +69 /r id IMUL r32,imm32 9-38/12-41 dword register  r/m32 * + immediate dword + + + +NOTES: + The 80386 uses an early-out multiply algorithm. The actual number of + clocks depends on the position of the most significant bit in the + optimizing multiplier, shown underlined above. The optimization occurs for + positive and negative values. Because of the early-out algorithm, clock + counts given are minimum to maximum. To calculate the actual clocks, use + the following formula: + + + Actual clock = if m <> 0 then max(ceiling(log{2} m), 3) + 6 clocks + Actual clock = if m = 0 then 9 clocks + (where m is the multiplier) + +Add three clocks if the multiplier is a memory operand. + +Operation + +result  multiplicand * multiplier; + +Description + +IMUL performs signed multiplication. Some forms of the instruction +use implicit register operands. The operand combinations for all forms +of the instruction are shown in the "Description" column above. + +IMUL clears the overflow and carry flags under the following conditions: + + Instruction Form Condition for Clearing CF and OF + r/m8 AL = sign-extend of AL to 16 bits + r/m16 AX = sign-extend of AX to 32 bits + r/m32 EDX:EAX = sign-extend of EAX to 32 bits + r16,r/m16 Result exactly fits within r16 + r/32,r/m32 Result exactly fits within r32 + r16,r/m16,imm16 Result exactly fits within r16 + r32,r/m32,imm32 Result exactly fits within r32 + +Flags Affected + +OF and CF as described above; SF, ZF, AF, and PF are undefined + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exeptions as in Real Address Mode; #PF(fault-code) for a page +fault + +Notes + +When using the accumulator forms (IMUL r/m8, IMUL r/m16, or IMUL +r/m32), the result of the multiplication is available even if the overflow +flag is set because the result is two times the size of the multiplicand +and multiplier. This is large enough to handle any possible result. + + +IN Input from Port + +Opcode Instruction Clocks Description + +E4 ib IN AL,imm8 12,pm=6*/26** Input byte from immediate port + into AL +E5 ib IN AX,imm8 12,pm=6*/26** Input word from immediate port + into AX +E5 ib IN EAX,imm8 12,pm=6*/26** Input dword from immediate port + into EAX +EC IN AL,DX 13,pm=7*/27** Input byte from port DX into AL +ED IN AX,DX 13,pm=7*/27** Input word from port DX into AX +ED IN EAX,DX 13,pm=7*/27** Input dword from port DX into + EAX + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (SRC, width(SRC)) + THEN #GP(0); + FI; +FI; +DEST  [SRC]; (* Reads from I/O address space *) + +Description + +IN transfers a data byte or data word from the port numbered by the +second operand into the register (AL, AX, or EAX) specified by the first +operand. Access any port from 0 to 65535 by placing the port number +in the DX register and using an IN instruction with DX as the second +parameter. These I/O instructions can be shortened by using an 8-bit +port I/O in the instruction. The upper eight bits of the port address will +be 0 when 8-bit port I/O is used. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is larger (has less privilege) than +IOPL and any of the corresponding I/O permission bits in TSS equals 1 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1 + + +INC Increment by 1 + +Opcode Instruction Clocks Description + +FE /0 INC r/m8 Increment r/m byte by 1 +FF /0 INC r/m16 Increment r/m word by 1 +FF /6 INC r/m32 Increment r/m dword by 1 +40 + rw INC r16 Increment word register by 1 +40 + rd INC r32 Increment dword register by 1 + + +Operation + +DEST  DEST + 1; + +Description + +INC adds 1 to the operand. It does not change the carry flag. To affect +the carry flag, use the ADD instruction with a second operand of 1. + +Flags Affected + +OF, SF, ZF, AF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the operand is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +INS/INSB/INSW/INSD Input from Port to String + +Opcode Instruction Clocks Description + +6C INS r/m8,DX 15,pm=9*/29** Input byte from port DX into ES:(E)DI +6D INS r/m16,DX 15,pm=9*/29** Input word from port DX into ES:(E)DI +6D INS r/m32,DX 15,pm=9*/29** Input dword from port DX into ES:(E)DI +6C INSB 15,pm=9*/29** Input byte from port DX into ES:(E)DI +6D INSW 15,pm=9*/29** Input word from port DX into ES:(E)DI +6D INSD 15,pm=9*/29** Input dword from port DX into ES:(E)DI + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF AddressSize = 16 +THEN use DI for dest-index; +ELSE (* AddressSize = 32 *) + use EDI for dest-index; +FI; +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (SRC, width(SRC)) + THEN #GP(0); + FI; +FI; +IF byte type of instruction +THEN + ES:[dest-index]  [DX]; (* Reads byte at DX from I/O address space *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +FI; +IF OperandSize = 16 +THEN + ES:[dest-index]  [DX]; (* Reads word at DX from I/O address space *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; +FI; +IF OperandSize = 32 +THEN + ES:[dest-index]  [DX]; (* Reads dword at DX from I/O address space *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; +FI; +dest-index  dest-index + IncDec; + +Description + +INS transfers data from the input port numbered by the DX register to +the memory byte or word at ES:dest-index. The memory operand must +be addressable from ES; no segment override is possible. The destination +register is DI if the address-size attribute of the instruction is 16 bits, +or EDI if the address-size attribute is 32 bits. + +INS does not allow the specification of the port number as an immediate +value. The port must be addressed through the DX register value. Load +the correct value into DX before executing the INS instruction. + +The destination address is determined by the contents of the destination +index register. Load the correct index into the destination index register +before executing INS. + +After the transfer is made, DI or EDI advances automatically. If the +direction flag is 0 (CLD was executed), DI or EDI increments; if the +direction flag is 1 (STD was executed), DI or EDI decrements. DI +increments or decrements by 1 if a byte is input, by 2 if a word is input, +or by 4 if a doubleword is input. + +INSB, INSW and INSD are synonyms of the byte, word, and doubleword +INS instructions. INS can be preceded by the REP prefix for block input of +CX bytes or words. Refer to the REP instruction for details of this +operation. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if CPL is numerically greater than IOPL and any of the +corresponding I/O permission bits in TSS equals 1; #GP(0) if the +destination is in a nonwritable segment; #GP(0) for an illegal memory +operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for +an illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1; #PF(fault-code) for a page fault + + +INT/INTO Call to Interrupt Procedure + + +Opcode Instruction Clocks Description + +CC INT 3 33 Interrupt 3--trap to debugger +CC INT 3 pm=59 Interrupt 3--Protected Mode, same + privilege +CC INT 3 pm=99 Interrupt 3--Protected Mode, more + privilege +CC INT 3 pm=119 Interrupt 3--from V86 mode to PL 0 +CC INT 3 ts Interrupt 3--Protected Mode, via + task gate +CD ib INT imm8 37 Interrupt numbered by immediate + byte +CD ib INT imm8 pm=59 Interrupt--Protected Mode, same + privilege +CD ib INT imm8 pm=99 Interrupt--Protected Mode, more + privilege +CD ib INT imm8 pm=119 Interrupt--from V86 mode to PL 0 +CD ib INT imm8 ts Interrupt--Protected Mode, via task + gate +CE INTO Fail:3,pm=3; + Pass:35 Interrupt 4--if overflow flag is 1 +CE INTO pm=59 Interrupt 4--Protected Mode, same + privilege +CE INTO pm=99 Interrupt 4--Protected Mode, more + privilege +CE INTO pm=119 Interrupt 4--from V86 mode to PL 0 +CE INTO ts Interrupt 4--Protected Mode, via + task gate + + + +NOTE: + Approximate values of ts are given by the following table: + + New Task + +Old Task 386 TSS 386 TSS 286 TSS + VM = 0 VM = 1 + +386 +TSS VM=0 309 226 282 + +386 +TSS VM=1 314 231 287 + +286 +TSS 307 224 280 + + +Operation + + +NOTE: + The following operational description applies not only to the + above instructions but also to external interrupts and exceptions. + + +IF PE = 0 +THEN GOTO REAL-ADDRESS-MODE; +ELSE GOTO PROTECTED-MODE; +FI; + +REAL-ADDRESS-MODE: + Push (FLAGS); + IF  0; (* Clear interrupt flag *) + TF  0; (* Clear trap flag *) + Push(CS); + Push(IP); + (* No error codes are pushed *) + CS  IDT[Interrupt number * 4].selector; + IP  IDT[Interrupt number * 4].offset; + +PROTECTED-MODE: + Interrupt vector must be within IDT table limits, + else #GP(vector number * 8+2+EXT); + Descriptor AR byte must indicate interrupt gate, trap gate, or task gate, + else #GP(vector number * 8+2+EXT); + IF software interrupt (* i.e. caused by INT n, INT 3, or INTO *) + THEN + IF gate descriptor DPL < CPL + THEN #GP(vector number * 8+2+EXT); + FI; + FI; + Gate must be present, else #NP(vector number * 8+2+EXT); + IF trap gate OR interrupt gate + THEN GOTO TRAP-GATE-OR-INTERRUPT-GATE; + ELSE GOTO TASK-GATE; + FI; + +TRAP-GATE-OR-INTERRUPT-GATE: + Examine CS selector and descriptor given in the gate descriptor; + Selector must be non-null, else #GP (EXT); + Selector must be within its descriptor table limits + ELSE #GP(selector+EXT); + Descriptor AR byte must indicate code segment + ELSE #GP(selector + EXT); + Segment must be present, else #NP(selector+EXT); + IF code segment is non-conforming AND DPL < CPL + THEN GOTO INTERRUPT-TO-INNER-PRIVILEGE; + ELSE + IF code segment is conforming OR code segment DPL = CPL + THEN GOTO INTERRUPT-TO-SAME-PRIVILEGE-LEVEL; + ELSE #GP(CS selector + EXT); + FI; + FI; + +INTERRUPT-TO-INNER-PRIVILEGE: + Check selector and descriptor for new stack in current TSS; + Selector must be non-null, else #GP(EXT); + Selector index must be within its descriptor table limits + ELSE #TS(SS selector+EXT); + Selector's RPL must equal DPL of code segment, else #TS(SS + selector+EXT); + Stack segment DPL must equal DPL of code segment, else #TS(SS + selector+EXT); + Descriptor must indicate writable data segment, else #TS(SS + selector+EXT); + Segment must be present, else #SS(SS selector+EXT); + IF 32-bit gate + THEN New stack must have room for 20 bytes else #SS(0) + ELSE New stack must have room for 10 bytes else #SS(0) + FI; + Instruction pointer must be within CS segment boundaries else #GP(0); + Load new SS and eSP value from TSS; + IF 32-bit gate + THEN CS:EIP  selector:offset from gate; + ELSE CS:IP  selector:offset from gate; + FI; + Load CS descriptor into invisible portion of CS register; + Load SS descriptor into invisible portion of SS register; + IF 32-bit gate + THEN + Push (long pointer to old stack) (* 3 words padded to 4 *); + Push (EFLAGS); + Push (long pointer to return location) (* 3 words padded to 4*); + ELSE + Push (long pointer to old stack) (* 2 words *); + Push (FLAGS); + Push (long pointer to return location) (* 2 words *); + FI; + Set CPL to new code segment DPL; + Set RPL of CS to CPL; + IF interrupt gate THEN IF  0 (* interrupt flag to 0 (disabled) *); FI; + TF  0; + NT  0; + +INTERRUPT-FROM-V86-MODE: + TempEFlags  EFLAGS; + VM  0; + TF  0; + IF service through Interrupt Gate THEN IF  0; + TempSS  SS; + TempESP  ESP; + SS  TSS.SS0; (* Change to level 0 stack segment *) + ESP  TSS.ESP0; (* Change to level 0 stack pointer *) + Push(GS); (* padded to two words *) + Push(FS); (* padded to two words *) + Push(DS); (* padded to two words *) + Push(ES); (* padded to two words *) + GS  0; + FS  0; + DS  0; + ES  0; + Push(TempSS); (* padded to two words *) + Push(TempESP); + Push(TempEFlags); + Push(CS); (* padded to two words *) + Push(EIP); + CS:EIP  selector:offset from interrupt gate; + (* Starts execution of new routine in 80386 Protected Mode *) + +INTERRUPT-TO-SAME-PRIVILEGE-LEVEL: + IF 32-bit gate + THEN Current stack limits must allow pushing 10 bytes, else #SS(0); + ELSE Current stack limits must allow pushing 6 bytes, else #SS(0); + FI; + IF interrupt was caused by exception with error code + THEN Stack limits must allow push of two more bytes; + ELSE #SS(0); + FI; + Instruction pointer must be in CS limit, else #GP(0); + IF 32-bit gate + THEN + Push (EFLAGS); + Push (long pointer to return location); (* 3 words padded to 4 *) + CS:EIP  selector:offset from gate; + ELSE (* 16-bit gate *) + Push (FLAGS); + Push (long pointer to return location); (* 2 words *) + CS:IP  selector:offset from gate; + FI; + Load CS descriptor into invisible portion of CS register; + Set the RPL field of CS to CPL; + Push (error code); (* if any *) + IF interrupt gate THEN IF  0; FI; + TF  0; + NT  0; + +TASK-GATE: + Examine selector to TSS, given in task gate descriptor; + Must specify global in the local/global bit, else #TS(TSS selector); + Index must be within GDT limits, else #TS(TSS selector); + AR byte must specify available TSS (bottom bits 00001), + else #TS(TSS selector; + TSS must be present, else #NP(TSS selector); + SWITCH-TASKS with nesting to TSS; + IF interrupt was caused by fault with error code + THEN + Stack limits must allow push of two more bytes, else #SS(0); + Push error code onto stack; + FI; + Instruction pointer must be in CS limit, else #GP(0); + +Description + +The INT instruction generates via software a call to an interrupt +handler. The immediate operand, from 0 to 255, gives the index number +into the Interrupt Descriptor Table (IDT) of the interrupt routine to be +called. In Protected Mode, the IDT consists of an array of eight-byte +descriptors; the descriptor for the interrupt invoked must indicate an +interrupt, trap, or task gate. In Real Address Mode, the IDT is an array +of four byte-long pointers. In Protected and Real Address Modes, the +base linear address of the IDT is defined by the contents of the IDTR. + +The INTO conditional software instruction is identical to the INT +interrupt instruction except that the interrupt number is implicitly 4, +and the interrupt is made only if the 80386 overflow flag is set. + +The first 32 interrupts are reserved by Intel for system use. Some of +these interrupts are use for internally generated exceptions. + +INT n generally behaves like a far call except that the flags register is +pushed onto the stack before the return address. Interrupt procedures +return via the IRET instruction, which pops the flags and return address +from the stack. + +In Real Address Mode, INT n pushes the flags, CS, and the return IP +onto the stack, in that order, then jumps to the long pointer indexed by +the interrupt number. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #NP, #SS, and #TS as indicated under "Operation" above + +Real Address Mode Exceptions + +None; if the SP or ESP = 1, 3, or 5 before executing INT or INTO, +the 80386 will shut down due to insufficient stack space + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, for INT only, to permit emulation; +Interrupt 3 (0CCH) generates Interrupt 3; INTO generates Interrupt 4 +if the overflow flag equals 1 + + +IRET/IRETD Interrupt Return + +Opcode Instruction Clocks Description + +CF IRET 22,pm=38 Interrupt return (far return and pop + flags) +CF IRET pm=82 Interrupt return to lesser privilege +CF IRET ts Interrupt return, different task (NT = 1) +CF IRETD 22,pm=38 Interrupt return (far return and pop + flags) +CF IRETD pm=82 Interrupt return to lesser privilege +CF IRETD pm=60 Interrupt return to V86 mode +CF IRETD ts Interrupt return, different task (NT = 1) + + + +NOTE: + Values of ts are given by the following table: + + New Task + +Old Task 386 TSS 386 TSS 286 TSS + VM = 0 VM = 1 + +386 +TSS VM=0 275 224 271 + +286 +TSS 265 214 232 + + +Operation + +IF PE = 0 +THEN (* Real-address mode *) + IF OperandSize = 32 (* Instruction = IRETD *) + THEN EIP  Pop(); + ELSE (* Instruction = IRET *) + IP  Pop(); + FI; + CS  Pop(); + IF OperandSize = 32 (* Instruction = IRETD *) + THEN EFLAGS  Pop(); + ELSE (* Instruction = IRET *) + FLAGS  Pop(); + FI; +ELSE (* Protected mode *) + IF VM = 1 + THEN #GP(0); + ELSE + IF NT = 1 + THEN GOTO TASK-RETURN; + ELSE + IF VM = 1 in flags image on stack + THEN GO TO STACK-RETURN-TO-V86; + ELSE GOTO STACK-RETURN; + FI; + FI; + FI; +FI;STACK-RETURN-TO-V86: (* Interrupted procedure was in V86 mode *) + IF return CS selector RPL < > 3 + THEN #GP(Return selector); + FI; + IF top 36 bytes of stack not within limits + THEN #SS(0); + FI; + Examine return CS selector and associated descriptor: + IF selector is null, THEN #GP(0); FI; + IF selector index not within its descriptor table limits; + THEN #GP(Return selector); + FI; + IF AR byte does not indicate code segment + THEN #GP(Return selector); + FI; + IF code segment DPL not = 3; + THEN #GP(Return selector); + FI; + IF code segment not present + THEN #NP(Return selector); + FI; + + Examine return SS selector and associated descriptor: + IF selector is null THEN #GP(0); FI; + IF selector index not within its descriptor table limits + THEN #GP(SS selector); + FI; + IF selector RPL not = RPL of return CS selector + THEN #GP(SS selector); + FI; + IF AR byte does not indicate a writable data segment + THEN #GP(SS selector); + FI; + IF stack segment DPL not = RPL of return CS selector + THEN #GP(SS selector); + FI; + IF SS not present + THEN #NP(SS selector); + FI; + + IF instruction pointer not within code segment limit THEN #GP(0); + FI; + EFLAGS  SS:[eSP + 8]; (* Sets VM in interrupted routine *) + EIP  Pop(); + CS  Pop(); (* CS behaves as in 8086, due to VM = 1 *) + throwaway  Pop(); (* pop away EFLAGS already read *) + ES  Pop(); (* pop 2 words; throw away high-order word *) + DS  Pop(); (* pop 2 words; throw away high-order word *) + FS  Pop(); (* pop 2 words; throw away high-order word *) + GS  Pop(); (* pop 2 words; throw away high-order word *) + IF CS.RPL > CPL + THEN + TempESP  Pop(); + TempSS  Pop(); + SS:ESP  TempSS:TempESP; + FI; + + (* Resume execution in Virtual 8086 mode *) + +TASK-RETURN: + Examine Back Link Selector in TSS addressed by the current task + register: + Must specify global in the local/global bit, else #TS(new TSS + selector); + Index must be within GDT limits, else #TS(new TSS selector); + AR byte must specify TSS, else #TS(new TSS selector); + New TSS must be busy, else #TS(new TSS selector); + TSS must be present, else #NP(new TSS selector); + SWITCH-TASKS without nesting to TSS specified by back link selector; + Mark the task just abandoned as NOT BUSY; + Instruction pointer must be within code segment limit ELSE #GP(0); + +STACK-RETURN: + IF OperandSize=32 + THEN Third word on stack must be within stack limits, else #SS(0); + ELSE Second word on stack must be within stack limits, else #SS(0); + FI; + Return CS selector RPL must be CPL, else #GP(Return selector); + IF return selector RPL = CPL + THEN GOTO RETURN-SAME-LEVEL; + ELSE GOTO RETURN-OUTER-LEVEL; + FI; + +RETURN-SAME-LEVEL: + IF OperandSize=32 + THEN + Top 12 bytes on stack must be within limits, else #SS(0); + Return CS selector (at eSP+4) must be non-null, else #GP(0); + ELSE + Top 6 bytes on stack must be within limits, else #SS(0); + Return CS selector (at eSP+2) must be non-null, else #GP(0); + FI; + Selector index must be within its descriptor table limits, else #GP + (Return selector); + AR byte must indicate code segment, else #GP(Return selector); + IF non-conforming + THEN code segment DPL must = CPL; + ELSE #GP(Return selector); + FI; + IF conforming + THEN code segment DPL must be CPL, else #GP(Return selector); + Segment must be present, else #NP(Return selector); + Instruction pointer must be within code segment boundaries, else #GP(0); + FI; + IF OperandSize=32 + THEN + Load CS:EIP from stack; + Load CS-register with new code segment descriptor; + Load EFLAGS with third doubleword from stack; + Increment eSP by 12; + ELSE + Load CS-register with new code segment descriptor; + Load FLAGS with third word on stack; + Increment eSP by 6; + FI; + +RETURN-OUTER-LEVEL: + IF OperandSize=32 + THEN Top 20 bytes on stack must be within limits, else #SS(0); + ELSE Top 10 bytes on stack must be within limits, else #SS(0); + FI; + Examine return CS selector and associated descriptor: + Selector must be non-null, else #GP(0); + Selector index must be within its descriptor table limits; + ELSE #GP(Return selector); + AR byte must indicate code segment, else #GP(Return selector); + IF non-conforming + THEN code segment DPL must = CS selector RPL; + ELSE #GP(Return selector); + FI; + IF conforming + THEN code segment DPL must be > CPL; + ELSE #GP(Return selector); + FI; + Segment must be present, else #NP(Return selector); + Examine return SS selector and associated descriptor: + Selector must be non-null, else #GP(0); + Selector index must be within its descriptor table limits + ELSE #GP(SS selector); + Selector RPL must equal the RPL of the return CS selector + ELSE #GP(SS selector); + AR byte must indicate a writable data segment, else #GP(SS selector); + Stack segment DPL must equal the RPL of the return CS selector + ELSE #GP(SS selector); + SS must be present, else #NP(SS selector); + + Instruction pointer must be within code segment limit ELSE #GP(0); + IF OperandSize=32 + THEN + Load CS:EIP from stack; + Load EFLAGS with values at (eSP+8); + ELSE + Load CS:IP from stack; + Load FLAGS with values at (eSP+4); + FI; + Load SS:eSP from stack; + Set CPL to the RPL of the return CS selector; + Load the CS register with the CS descriptor; + Load the SS register with the SS descriptor; + FOR each of ES, FS, GS, and DS + DO; + IF the current value of the register is not valid for the outer level; + THEN zero the register and clear the valid flag; + FI; + To be valid, the register setting must satisfy the following + properties: + Selector index must be within descriptor table limits; + AR byte must indicate data or readable code segment; + IF segment is data or non-conforming code, + THEN DPL must be CPL, or DPL must be RPL; + OD; + +Description + +In Real Address Mode, IRET pops the instruction pointer, CS, and the +flags register from the stack and resumes the interrupted routine. + +In Protected Mode, the action of IRET depends on the setting of the +nested task flag (NT) bit in the flag register. When popping the new +flag image from the stack, the IOPL bits in the flag register are changed +only when CPL equals 0. + +If NT equals 0, IRET returns from an interrupt procedure without a +task switch. The code returned to must be equally or less privileged than +the interrupt routine (as indicated by the RPL bits of the CS selector +popped from the stack). If the destination code is less privileged, IRET +also pops the stack pointer and SS from the stack. + +If NT equals 1, IRET reverses the operation of a CALL or INT that +caused a task switch. The updated state of the task executing IRET is +saved in its task state segment. If the task is reentered later, the code +that follows IRET is executed. + +Flags Affected + +All; the flags register is popped from stack + +Protected Mode Exceptions + +#GP, #NP, or #SS, as indicated under "Operation" above + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand being popped lies beyond address +0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, to permit emulation + + +Jcc Jump if Condition is Met + + +Opcode Instruction Clocks Description + +77 cb JA rel8 7+m,3 Jump short if above (CF=0 and + ZF=0) +73 cb JAE rel8 7+m,3 Jump short if above or equal + (CF=0) +72 cb JB rel8 7+m,3 Jump short if below (CF=1) +76 cb JBE rel8 7+m,3 Jump short if below or equal + (CF=1 or ZF=1) +72 cb JC rel8 7+m,3 Jump short if carry (CF=1) +E3 cb JCXZ rel8 9+m,5 Jump short if CX register is 0 +E3 cb JECXZ rel8 9+m,5 Jump short if ECX register is 0 +74 cb JE rel8 7+m,3 Jump short if equal (ZF=1) +74 cb JZ rel8 7+m,3 Jump short if 0 (ZF=1) +7F cb JG rel8 7+m,3 Jump short if greater (ZF=0 and + SF=OF) +7D cb JGE rel8 7+m,3 Jump short if greater or equal + (SF=OF) +7C cb JL rel8 7+m,3 Jump short if less (SF<>OF) +7E cb JLE rel8 7+m,3 Jump short if less or equal + (ZF=1 and SF<>OF) +76 cb JNA rel8 7+m,3 Jump short if not above (CF=1 or + ZF=1) +72 cb JNAE rel8 7+m,3 Jump short if not above or equal + (CF=1) +73 cb JNB rel8 7+m,3 Jump short if not below (CF=0) +77 cb JNBE rel8 7+m,3 Jump short if not below or equal + (CF=0 and ZF=0) +73 cb JNC rel8 7+m,3 Jump short if not carry (CF=0) +75 cb JNE rel8 7+m,3 Jump short if not equal (ZF=0) +7E cb JNG rel8 7+m,3 Jump short if not greater (ZF=1 + or SF<>OF) +7C cb JNGE rel8 7+m,3 Jump short if not greater or + equal (SF<>OF) +7D cb JNL rel8 7+m,3 Jump short if not less (SF=OF) +7F cb JNLE rel8 7+m,3 Jump short if not less or equal + (ZF=0 and SF=OF) +71 cb JNO rel8 7+m,3 Jump short if not overflow + (OF=0) +7B cb JNP rel8 7+m,3 Jump short if not parity (PF=0) +79 cb JNS rel8 7+m,3 Jump short if not sign (SF=0) +75 cb JNZ rel8 7+m,3 Jump short if not zero (ZF=0) +70 cb JO rel8 7+m,3 Jump short if overflow (OF=1) +7A cb JP rel8 7+m,3 Jump short if parity (PF=1) +7A cb JPE rel8 7+m,3 Jump short if parity even (PF=1) +7B cb JPO rel8 7+m,3 Jump short if parity odd (PF=0) +78 cb JS rel8 7+m,3 Jump short if sign (SF=1) +74 cb JZ rel8 7+m,3 Jump short if zero (ZF = 1) +0F 87 cw/cd JA rel16/32 7+m,3 Jump near if above (CF=0 and + ZF=0) +0F 83 cw/cd JAE rel16/32 7+m,3 Jump near if above or equal + (CF=0) +0F 82 cw/cd JB rel16/32 7+m,3 Jump near if below (CF=1) +0F 86 cw/cd JBE rel16/32 7+m,3 Jump near if below or equal + (CF=1 or ZF=1) +0F 82 cw/cd JC rel16/32 7+m,3 Jump near if carry (CF=1) +0F 84 cw/cd JE rel16/32 7+m,3 Jump near if equal (ZF=1) +0F 84 cw/cd JZ rel16/32 7+m,3 Jump near if 0 (ZF=1) +0F 8F cw/cd JG rel16/32 7+m,3 Jump near if greater (ZF=0 and + SF=OF) +0F 8D cw/cd JGE rel16/32 7+m,3 Jump near if greater or equal + (SF=OF) +0F 8C cw/cd JL rel16/32 7+m,3 Jump near if less (SF<>OF) +0F 8E cw/cd JLE rel16/32 7+m,3 Jump near if less or equal (ZF=1 + and SF<>OF) +0F 86 cw/cd JNA rel16/32 7+m,3 Jump near if not above (CF=1 or + ZF=1) +0F 82 cw/cd JNAE rel16/32 7+m,3 Jump near if not above or equal + (CF=1) +0F 83 cw/cd JNB rel16/32 7+m,3 Jump near if not below (CF=0) +0F 87 cw/cd JNBE rel16/32 7+m,3 Jump near if not below or equal + (CF=0 and ZF=0) +0F 83 cw/cd JNC rel16/32 7+m,3 Jump near if not carry (CF=0) +0F 85 cw/cd JNE rel16/32 7+m,3 Jump near if not equal (ZF=0) +0F 8E cw/cd JNG rel16/32 7+m,3 Jump near if not greater (ZF=1 + or SF<>OF) +0F 8C cw/cd JNGE rel16/32 7+m,3 Jump near if not greater or + equal (SF<>OF) +0F 8D cw/cd JNL rel16/32 7+m,3 Jump near if not less (SF=OF) +0F 8F cw/cd JNLE rel16/32 7+m,3 Jump near if not less or equal + (ZF=0 and SF=OF) +0F 81 cw/cd JNO rel16/32 7+m,3 Jump near if not overflow (OF=0) +0F 8B cw/cd JNP rel16/32 7+m,3 Jump near if not parity (PF=0) +0F 89 cw/cd JNS rel16/32 7+m,3 Jump near if not sign (SF=0) +0F 85 cw/cd JNZ rel16/32 7+m,3 Jump near if not zero (ZF=0) +0F 80 cw/cd JO rel16/32 7+m,3 Jump near if overflow (OF=1) +0F 8A cw/cd JP rel16/32 7+m,3 Jump near if parity (PF=1) +0F 8A cw/cd JPE rel16/32 7+m,3 Jump near if parity even (PF=1) +0F 8B cw/cd JPO rel16/32 7+m,3 Jump near if parity odd (PF=0) +0F 88 cw/cd JS rel16/32 7+m,3 Jump near if sign (SF=1) +0F 84 cw/cd JZ rel16/32 7+m,3 Jump near if 0 (ZF=1) + + + +NOTES: + The first clock count is for the true condition (branch taken); the + second clock count is for the false condition (branch not taken). rel16/32 + indicates that these instructions map to two; one with a 16-bit relative + displacement, the other with a 32-bit relative displacement, depending on + the operand-size attribute of the instruction. + + +Operation + +IF condition +THEN + EIP  EIP + SignExtend(rel8/16/32); + IF OperandSize = 16 + THEN EIP  EIP AND 0000FFFFH; + FI; +FI; + +Description + +Conditional jumps (except JCXZ) test the flags which have been set by +a previous instruction. The conditions for each mnemonic are given in +parentheses after each description above. The terms "less" and "greater" +are used for comparisons of signed integers; "above" and "below" are +used for unsigned integers. + +If the given condition is true, a jump is made to the location provided as +the operand. Instruction coding is most efficient when the target for the +conditional jump is in the current code segment and within -128 to ++127 bytes of the next instruction's first byte. The jump can also target +-32768 thru +32767 (segment size attribute 16) or -2^(31) thru +2^(31) -1 +(segment size attribute 32) relative to the next instruction's first byte. +When the target for the conditional jump is in a different segment, use +the opposite case of the jump instruction (i.e., JE and JNE), and then +access the target with an unconditional far jump to the other segment. +For example, you cannot code + +JZ FARLABEL; + +You must instead code + + JNZ BEYOND; + JMP FARLABEL; +BEYOND: + +Because there can be several ways to interpret a particular state of the +flags, ASM386 provides more than one mnemonic for most of the +conditional jump opcodes. For example, if you compared two characters in +AX and want to jump if they are equal, use JE; or, if you ANDed AX +with a bit field mask and only want to jump if the result is 0, use JZ, a +synonym for JE. + +JCXZ differs from other conditional jumps because it tests the contents of +the CX or ECX register for 0, not the flags. JCXZ is useful at the beginning +of a conditional loop that terminates with a conditional loop instruction +(such as LOOPNE TARGET LABEL. The JCXZ prevents entering the loop with CX or +ECX equal to zero, which would cause the loop to execute 64K or 32G times +instead of zero times. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the offset jumped to is beyond the limits of the code segment + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +JMP Jump + + +Opcode Instruction Clocks Description + +EB cb JMP rel8 7+m Jump short +E9 cw JMP rel16 7+m Jump near, displacement relative + to next instruction +FF /4 JMP r/m16 7+m/10+m Jump near indirect +EA cd JMP ptr16:16 12+m,pm=27+m Jump intersegment, 4-byte + immediate address +EA cd JMP ptr16:16 pm=45+m Jump to call gate, same + privilege +EA cd JMP ptr16:16 ts Jump via task state segment +EA cd JMP ptr16:16 ts Jump via task gate +FF /5 JMP m16:16 43+m,pm=31+m Jump r/m16:16 indirect and + intersegment +FF /5 JMP m16:16 pm=49+m Jump to call gate, same + privilege +FF /5 JMP m16:16 5 + ts Jump via task state segment +FF /5 JMP m16:16 5 + ts Jump via task gate +E9 cd JMP rel32 7+m Jump near, displacement relative + to next instruction +FF /4 JMP r/m32 7+m,10+m Jump near, indirect +EA cp JMP ptr16:32 12+m,pm=27+m Jump intersegment, 6-byte + immediate address +EA cp JMP ptr16:32 pm=45+m Jump to call gate, same + privilege +EA cp JMP ptr16:32 ts Jump via task state segment +EA cp JMP ptr16:32 ts Jump via task gate +FF /5 JMP m16:32 43+m,pm=31+m Jump intersegment, address at + r/m dword +FF /5 JMP m16:32 pm=49+m Jump to call gate, same + privilege +FF /5 JMP m16:32 5 + ts Jump via task state segment +FF /5 JMP m16:32 5 + ts Jump via task gate + + + +NOTE: +Values of ts are given by the following table: + + New Task + + 386 TSS 386 TASK 286 TSS + VM = 0 VM = 1 + +Old Task Via Task Gate? + + N Y N Y N Y +386 +TSS VM=0 303 312 220 229 276 285 + +286 +TSS 301 310 218 227 274 283 + + +Operation + +IF instruction = relative JMP + (* i.e. operand is rel8, rel16, or rel32 *) +THEN + EIP  EIP + rel8/16/32; + IF OperandSize = 16 + THEN EIP  EIP AND 0000FFFFH; + FI; +FI; +IF instruction = near indirect JMP + (* i.e. operand is r/m16 or r/m32 *) +THEN + IF OperandSize = 16 + THEN + EIP  [r/m16] AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + EIP  [r/m32]; + FI; +FI; + +IF (PE = 0 OR (PE = 1 AND VM = 1)) (* real mode or V86 mode *) + AND instruction = far JMP + (* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *) +THEN GOTO REAL-OR-V86-MODE; + IF operand type = m16:16 or m16:32 + THEN (* indirect *) + IF OperandSize = 16 + THEN + CS:IP  [m16:16]; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  [m16:32]; + FI; + FI; + IF operand type = ptr16:16 or ptr16:32 + THEN + IF OperandSize = 16 + THEN + CS:IP  ptr16:16; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  ptr16:32; + FI; + FI; +FI; + +IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *) + AND instruction = far JMP +THEN + IF operand type = m16:16 or m16:32 + THEN (* indirect *) + check access of EA dword; + #GP(0) or #SS(0) IF limit violation; + FI; + Destination selector is not null ELSE #GP(0) + Destination selector index is within its descriptor table limits ELSE +#GP(selector) + Depending on AR byte of destination descriptor: + GOTO CONFORMING-CODE-SEGMENT; + GOTO NONCONFORMING-CODE-SEGMENT; + GOTO CALL-GATE; + GOTO TASK-GATE; + GOTO TASK-STATE-SEGMENT; + ELSE #GP(selector); (* illegal AR byte in descriptor *) +FI; + +CONFORMING-CODE-SEGMENT: + Descriptor DPL must be CPL ELSE #GP(selector); + Segment must be present ELSE #NP(selector); + Instruction pointer must be within code-segment limit ELSE #GP(0); + IF OperandSize = 32 + THEN Load CS:EIP from destination pointer; + ELSE Load CS:IP from destination pointer; + FI; + Load CS register with new segment descriptor; + +NONCONFORMING-CODE-SEGMENT: + RPL of destination selector must be CPL ELSE #GP(selector); + Descriptor DPL must be = CPL ELSE #GP(selector); + Segment must be present ELSE # NP(selector); + Instruction pointer must be within code-segment limit ELSE #GP(0); + IF OperandSize = 32 + THEN Load CS:EIP from destination pointer; + ELSE Load CS:IP from destination pointer; + FI; + Load CS register with new segment descriptor; + Set RPL field of CS register to CPL; + +CALL-GATE: + Descriptor DPL must be CPL ELSE #GP(gate selector); + Descriptor DPL must be gate selector RPL ELSE #GP(gate selector); + Gate must be present ELSE #NP(gate selector); + Examine selector to code segment given in call gate descriptor: + Selector must not be null ELSE #GP(0); + Selector must be within its descriptor table limits ELSE + #GP(CS selector); + Descriptor AR byte must indicate code segment + ELSE #GP(CS selector); + IF non-conforming + THEN code-segment descriptor, DPL must = CPL + ELSE #GP(CS selector); + FI; + IF conforming + THEN code-segment descriptor DPL must be CPL; + ELSE #GP(CS selector); + Code segment must be present ELSE #NP(CS selector); + Instruction pointer must be within code-segment limit ELSE #GP(0); + IF OperandSize = 32 + THEN Load CS:EIP from call gate; + ELSE Load CS:IP from call gate; + FI; + Load CS register with new code-segment descriptor; + Set RPL of CS to CPL + +TASK-GATE: + Gate descriptor DPL must be CPL ELSE #GP(gate selector); + Gate descriptor DPL must be gate selector RPL ELSE #GP(gate + selector); + Task Gate must be present ELSE #NP(gate selector); + Examine selector to TSS, given in Task Gate descriptor: + Must specify global in the local/global bit ELSE #GP(TSS selector); + Index must be within GDT limits ELSE #GP(TSS selector); + Descriptor AR byte must specify available TSS (bottom bits 00001); + ELSE #GP(TSS selector); + Task State Segment must be present ELSE #NP(TSS selector); +SWITCH-TASKS (without nesting) to TSS; +Instruction pointer must be within code-segment limit ELSE #GP(0); + +TASK-STATE-SEGMENT: + TSS DPL must be CPL ELSE #GP(TSS selector); + TSS DPL must be TSS selector RPL ELSE #GP(TSS selector); + Descriptor AR byte must specify available TSS (bottom bits 00001) + ELSE #GP(TSS selector); + Task State Segment must be present ELSE #NP(TSS selector); + SWITCH-TASKS (without nesting) to TSS; + Instruction pointer must be within code-segment limit ELSE #GP(0); + +Description + +The JMP instruction transfers control to a different point in the +instruction stream without recording return information. + +The action of the various forms of the instruction are shown below. + +Jumps with destinations of type r/m16, r/m32, rel16, and rel32 are near +jumps and do not involve changing the segment register value. + +The JMP rel16 and JMP rel32 forms of the instruction add an offset to +the address of the instruction following the JMP to determine the +destination. The rel16 form is used when the instruction's operand-size +attribute is 16 bits (segment size attribute 16 only); rel32 is used when +the operand-size attribute is 32 bits (segment size attribute 32 only). The +result is stored in the 32-bit EIP register. With rel16, the upper 16 bits +of EIP are cleared, which results in an offset whose value does not exceed +16 bits. + +JMP r/m16 and JMP r/m32 specifies a register or memory location from which +the absolute offset from the procedure is fetched. The offset fetched from +r/m is 32 bits for an operand-size attribute of 32 bits (r/m32), or 16 bits +for an operand-size attribute of 16 bits (r/m16). + +The JMP ptr16:16 and ptr16:32 forms of the instruction use a four-byte +or six-byte operand as a long pointer to the destination. The JMP +and forms fetch the long pointer from the memory location +specified (indirection). In Real Address Mode or Virtual 8086 Mode, +the long pointer provides 16 bits for the CS register and 16 or 32 bits +for the EIP register (depending on the operand-size attribute). In +Protected Mode, both long pointer forms consult the Access Rights (AR) +byte in the descriptor indexed by the selector part of the long pointer. + +Depending on the value of the AR byte, the jump will perform one of +the following types of control transfers: + + A jump to a code segment at the same privilege level + A task switch + +For more information on protected mode control transfers, refer to +Chapter 6 and Chapter 7. + +Flags Affected + +All if a task switch takes place; none if no task switch occurs + +Protected Mode Exceptions + +Far jumps: #GP, #NP, #SS, and #TS, as indicated in the list above. + +Near direct jumps: #GP(0) if procedure location is beyond the code +segment limits. + +Near indirect jumps: #GP(0) for an illegal memory operand effective +address in the CS, DS, ES, FS, or GS segments: #SS(0) for an illegal +address in the SS segment; #GP if the indirect offset obtained is beyond +the code segment limits; #PF(fault-code) for a page fault. + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would be outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as under Real Address Mode; #PF(fault-code) for a +page fault + + +LAHF Load Flags into AH Register + +Opcode Instruction Clocks Description + +9F LAHF 2 Load: AH = flags SF ZF xx AF xx PF xx CF + + +Operation + +AH  SF:ZF:xx:AF:xx:PF:xx:CF; + +Description + +LAHF transfers the low byte of the flags word to AH. The bits, from +MSB to LSB, are sign, zero, indeterminate, auxiliary, carry, +indeterminate, parity, indeterminate, and carry. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +LAR Load Access Rights Byte + +Opcode Instruction Clocks Description + +0F 02 /r LAR r16,r/m16 pm=15/16 r16  r/m16 masked by FF00 +0F 02 /r LAR r32,r/m32 pm=15/16 r32  r/m32 masked by 00FxFF00 + + +Description + +The LAR instruction stores a marked form of the second doubleword of +the descriptor for the source selector if the selector is visible at the +CPL (modified by the selector's RPL) and is a valid descriptor type. The +destination register is loaded with the high-order doubleword of the +descriptor masked by 00FxFF00, and ZF is set to 1. The x indicates that the +four bits corresponding to the upper four bits of the limit are undefined in +the value loaded by LAR. If the selector is invisible or of the wrong type, +ZF is cleared. + +If the 32-bit operand size is specified, the entire 32-bit value is loaded +into the 32-bit destination register. If the 16-bit operand size is +specified, the lower 16-bits of this value are stored in the 16-bit +destination register. + +All code and data segment descriptors are valid for LAR. + +The valid special segment and gate descriptor types for LAR are given +in the following table: + +Type Name Valid/Invalid + + 0 Invalid Invalid + 1 Available 80286 TSS Valid + 2 LDT Valid + 3 Busy 80286 TSS Valid + 4 80286 call gate Valid + 5 80286/80386 task gate Valid + 6 80286 trap gate Valid + 7 80286 interrupt gate Valid + 8 Invalid Invalid + 9 Available 80386 TSS Valid + A Invalid Invalid + B Busy 80386 TSS Valid + C 80386 call gate Valid + D Invalid Invalid + E 80386 trap gate Valid + F 80386 interrupt gate Valid + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; LAR is unrecognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LEA Load Effective Address + +Opcode Instruction Clocks Description + +8D /r LEA r16,m 2 Store effective address for m in register r16 +8D /r LEA r32,m 2 Store effective address for m in register r32 +8D /r LEA r16,m 2 Store effective address for m in register r16 +8D /r LEA r32,m 2 Store effective address for m in register r32 + + +Operation + +IF OperandSize = 16 AND AddressSize = 16 +THEN r16  Addr(m); +ELSE + IF OperandSize = 16 AND AddressSize = 32 + THEN + r16  Truncate_to_16bits(Addr(m)); (* 32-bit address *) + ELSE + IF OperandSize = 32 AND AddressSize = 16 + THEN + r32  Truncate_to_16bits(Addr(m)); + ELSE + IF OperandSize = 32 AND AddressSize = 32 + THEN r32  Addr(m); + FI; + FI; + FI; +FI; + +Description + +LEA calculates the effective address (offset part) and stores it in the +specified register. The operand-size attribute of the instruction +(represented by OperandSize in the algorithm under "Operation" above) is +determined by the chosen register. The address-size attribute (represented +by AddressSize) is determined by the USE attribute of the segment containing +the second operand. The address-size and operand-size attributes affect the +action performed by LEA, as follows: + +Operand Size Address Size Action Performed + + 16 16 16-bit effective address is calculated and + stored in requested 16-bit register + destination. + + 16 32 32-bit effective address is calculated. The + lower 16 bits of the address are stored in + the requested 16-bit register destination. + + 32 16 16-bit effective address is calculated. The + 16-bit address is zero-extended and stored + in the requested 32-bit register destination. + + 32 32 32-bit effective address is calculated and + stored in the requested 32-bit register + destination. + +Flags Affected + +None + +Protected Mode Exceptions + +#UD if the second operand is a register + +Real Address Mode Exceptions + +Interrupt 6 if the second operand is a register + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LEAVE High Level Procedure Exit + +Opcode Instruction Clocks Description + +C9 LEAVE 4 Set SP to BP, then pop BP +C9 LEAVE 4 Set ESP to EBP, then pop EBP + + +Operation + +IF StackAddrSize = 16 +THEN + SP  BP; +ELSE (* StackAddrSize = 32 *) + ESP  EBP; +FI; +IF OperandSize = 16 +THEN + BP  Pop(); +ELSE (* OperandSize = 32 *) + EBP  Pop(); +FI; + +Description + +LEAVE reverses the actions of the ENTER instruction. By copying the +frame pointer to the stack pointer, LEAVE releases the stack space used +by a procedure for its local variables. The old frame pointer is popped +into BP or EBP, restoring the caller's frame. A subsequent RET +instruction removes any arguments pushed onto the stack of the exiting +procedure. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if BP does not point to a location within the limits of the current +stack segment + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LGDT/LIDT Load Global/Interrupt Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 01 /2 LGDT m16&32 11 Load m into GDTR +0F 01 /3 LIDT m16&32 11 Load m into IDTR + + +Operation + +IF instruction = LIDT +THEN + IF OperandSize = 16 + THEN IDTR.Limit:Base  m16:24 (* 24 bits of base loaded *) + ELSE IDTR.Limit:Base  m16:32 + FI; +ELSE (* instruction = LGDT *) + IF OperandSize = 16 + THEN GDTR.Limit:Base  m16:24 (* 24 bits of base loaded *) + ELSE GDTR.Limit:Base  m16:32; + FI; +FI; + +Description + +The LGDT and LIDT instructions load a linear base address and limit +value from a six-byte data operand in memory into the GDTR or IDTR, +respectively. If a 16-bit operand is used with LGDT or LIDT, the +register is loaded with a 16-bit limit and a 24-bit base, and the +high-order eight bits of the six-byte data operand are not used. If a 32-bit +operand is used, a 16-bit limit and a 32-bit base is loaded; the high-order +eight bits of the six-byte operand are used as high-order base address bits. + +The SGDT and SIDT instructions always store into all 48 bits of the +six-byte data operand. With the 80286, the upper eight bits are undefined +after SGDT or SIDT is executed. With the 80386, the upper eight bits +are written with the high-order eight address bits, for both a 16-bit +operand and a 32-bit operand. If LGDT or LIDT is used with a 16-bit +operand to load the register stored by SGDT or SIDT, the upper eight +bits are stored as zeros. + +LGDT and LIDT appear in operating system software; they are not used +in application programs. They are the only instructions that directly load +a linear address (i.e., not a segment relative address) in 80386 Protected +Mode. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0; #UD if the source operand +is a register; #GP(0) for an illegal memory operand effective address in +the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address in +the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH; Interrupt 6 if the source operand is a +register + + +Note: + These instructions are valid in Real Address Mode to allow + power-up initialization for Protected Mode + + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +LGS/LSS/LDS/LES/LFS Load Full Pointer + +Opcode Instruction Clocks Description + +C5 /r LDS r16,m16:16 7,p=22 Load DS:r16 with pointer from memory +C5 /r LDS r32,m16:32 7,p=22 Load DS:r32 with pointer from memory +0F B2 /r LSS r16,m16:16 7,p=22 Load SS:r16 with pointer from memory +0F B2 /r LSS r32,m16:32 7,p=22 Load SS:r32 with pointer from memory +C4 /r LES r16,m16:16 7,p=22 Load ES:r16 with pointer from memory +C4 /r LES r32,m16:32 7,p=22 Load ES:r32 with pointer from memory +0F B4 /r LFS r16,m16:16 7,p=25 Load FS:r16 with pointer from memory +0F B4 /r LFS r32,m16:32 7,p=25 Load FS:r32 with pointer from memory +0F B5 /r LGS r16,m16:16 7,p=25 Load GS:r16 with pointer from memory +0F B5 /r LGS r32,m16:32 7,p=25 Load GS:r32 with pointer from memory + + +Operation + +CASE instruction OF + LSS: Sreg is SS; (* Load SS register *) + LDS: Sreg is DS; (* Load DS register *) + LES: Sreg is ES; (* Load ES register *) + LFS: Sreg is FS; (* Load FS register *) + LGS: Sreg is DS; (* Load GS register *) +ESAC; +IF (OperandSize = 16) +THEN + r16  [Effective Address]; (* 16-bit transfer *) + Sreg  [Effective Address + 2]; (* 16-bit transfer *) + (* In Protected Mode, load the descriptor into the segment register *) +ELSE (* OperandSize = 32 *) + r32  [Effective Address]; (* 32-bit transfer *) + Sreg  [Effective Address + 4]; (* 16-bit transfer *) + (* In Protected Mode, load the descriptor into the segment register *) +FI; + +Description + +These instructions read a full pointer from memory and store it in the +selected segment register:register pair. The full pointer loads 16 bits +into the segment register SS, DS, ES, FS, or GS. The other register loads 32 +bits if the operand-size attribute is 32 bits, or loads 16 bits if the +operand-size attribute is 16 bits. The other 16- or 32-bit register to be +loaded is determined by the r16 or r32 register operand specified. + +When an assignment is made to one of the segment registers, the +descriptor is also loaded into the segment register. The data for the +register is obtained from the descriptor table entry for the selector +given. + +A null selector (values 0000-0003) can be loaded into DS, ES, FS, or +GS registers without causing a protection exception. (Any subsequent +reference to a segment whose corresponding segment register is loaded +with a null selector to address memory causes a #GP(0) exception. No +memory reference to the segment occurs.) + +The following is a listing of the Protected Mode checks and actions taken in +the loading of a segment register: + +IF SS is loaded: + IF selector is null THEN #GP(0); FI; + Selector index must be within its descriptor table limits ELSE + #GP(selector); + Selector's RPL must equal CPL ELSE #GP(selector); + AR byte must indicate a writable data segment ELSE #GP(selector); + DPL in the AR byte must equal CPL ELSE #GP(selector); + Segment must be marked present ELSE #SS(selector); + Load SS with selector; + Load SS with descriptor; +IF DS, ES, FS, or GS is loaded with non-null selector: + Selector index must be within its descriptor table limits ELSE + #GP(selector); + AR byte must indicate data or readable code segment ELSE + #GP(selector); + IF data or nonconforming code + THEN both the RPL and the CPL must be less than or equal to DPL in + AR byte; + ELSE #GP(selector); + Segment must be marked present ELSE #NP(selector); +Load segment register with selector and RPL bits; +Load segment register with descriptor; +IF DS, ES, FS or GS is loaded with a null selector: + Clear descriptor valid bit; + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +the second operand must be a memory operand, not a register; #GP(0) +if a null selector is loaded into SS; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +The second operand must be a memory operand, not a register; Interrupt +13 if any part of the operand would lie outside of the effective address +space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +LLDT Load Local Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 00 /2 LLDT r/m16 20 Load selector r/m16 into LDTR + + +Operation + +LDTR  SRC; + +Description + +LLDT loads the Local Descriptor Table register (LDTR). The word +operand (memory or register) to LLDT should contain a selector to the +Global Descriptor Table (GDT). The GDT entry should be a Local Descriptor +Table. If so, then the LDTR is loaded from the entry. The descriptor +registers DS, ES, SS, FS, GS, and CS are not affected. The LDT field in the +task state segment does not change. + +The selector operand can be 0; if so, the LDTR is marked invalid. All +descriptor references (except by the LAR, VERR, VERW or LSL +instructions) cause a #GP fault. + +LLDT is used in operating system software; it is not used in application +programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0; #GP(selector) if the +selector operand does not point into the Global Descriptor Table, or if the +entry in the GDT is not a Local Descriptor Table; #NP(selector) if the +LDT descriptor is not present; #GP(0) for an illegal memory operand +effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an +illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; LLDT is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode (because the instruction is +not recognized, it will not execute or perform a memory reference) + +Note + +The operand-size attribute has no effect on this instruction. + + +LMSW Load Machine Status Word + +Opcode Instruction Clocks Description + +0F 01 /6 LMSW r/m16 10/13 Load r/m16 in machine status word + + +Operation + +MSW  r/m16; (* 16 bits is stored in the machine status word *) + +Description + +LMSW loads the machine status word (part of CR0) from the source +operand. This instruction can be used to switch to Protected Mode; if so, +it must be followed by an intrasegment jump to flush the instruction +queue. LMSW will not switch back to Real Address Mode. + +LMSW is used only in operating system software. It is not used in +application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + +Notes + +The operand-size attribute has no effect on this instruction. This +instruction is provided for compatibility with the 80286; 80386 programs +should use MOV CR0, ... instead. + + +LOCK Assert LOCK# Signal Prefix + +Opcode Instruction Clocks Description + +F0 LOCK 0 Assert LOCK# signal for the next instruction + + +Description + +The LOCK prefix causes the LOCK# signal of the 80386 to be asserted +during execution of the instruction that follows it. In a multiprocessor +environment, this signal can be used to ensure that the 80386 has +exclusive use of any shared memory while LOCK# is asserted. The +read-modify-write sequence typically used to implement test-and-set on the +80386 is the BTS instruction. + +The LOCK prefix functions only with the following instructions: + +BT, BTS, BTR, BTC mem, reg/imm +XCHG reg, mem +XCHG mem, reg +ADD, OR, ADC, SBB, AND, SUB, XOR mem, reg/imm +NOT, NEG, INC, DEC mem + +An undefined opcode trap will be generated if a LOCK prefix is used +with any instruction not listed above. + +XCHG always asserts LOCK# regardless of the presence or absence of +the LOCK prefix. + +The integrity of the LOCK is not affected by the alignment of the +memory field. Memory locking is observed for arbitrarily misaligned +fields. + +Locked access is not assured if another 80386 processor is executing an +instruction concurrently that has one of the following characteristics: + + Is not preceded by a LOCK prefix + + Is not one of the instructions in the preceding list + + Specifies a memory operand that does not exactly overlap the + destination operand. Locking is not guaranteed for partial overlap, + even if one memory operand is wholly contained within another. + +Flags Affected + +None + +Protected Mode Exceptions + +#UD if LOCK is used with an instruction not listed in the "Description" +section above; other exceptions can be generated by the subsequent +(locked) instruction + +Real Address Mode Exceptions + +Interrupt 6 if LOCK is used with an instruction not listed in the +"Description" section above; exceptions can still be generated by the +subsequent (locked) instruction + +Virtual 8086 Mode Exceptions + +#UD if LOCK is used with an instruction not listed in the "Description" +section above; exceptions can still be generated by the subsequent (locked) +instruction + + +LODS/LODSB/LODSW/LODSD Load String Operand + +Opcode Instruction Clocks Description + +AC LODS m8 5 Load byte [(E)SI] into AL +AD LODS m16 5 Load word [(E)SI] into AX +AD LODS m32 5 Load dword [(E)SI] into EAX +AC LODSB 5 Load byte DS:[(E)SI] into AL +AD LODSW 5 Load word DS:[(E)SI] into AX +AD LODSD 5 Load dword DS:[(E)SI] into EAX + + +Operation + +IF AddressSize = 16 +THEN use SI for source-index +ELSE (* AddressSize = 32 *) + use ESI for source-index; +FI; +IF byte type of instruction +THEN + AL  [source-index]; (* byte load *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + AX  [source-index]; (* word load *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + EAX  [source-index]; (* dword load *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index  source-index + IncDec + +Description + +LODS loads the AL, AX, or EAX register with the memory byte, word, +or doubleword at the location pointed to by the source-index register. +After the transfer is made, the source-index register is automatically +advanced. If the direction flag is 0 (CLD was executed), the source index +increments; if the direction flag is 1 (STD was executed), it decrements. +The increment or decrement is 1 if a byte is loaded, 2 if a word is loaded, +or 4 if a doubleword is loaded. + +If the address-size attribute for this instruction is 16 bits, SI is used +for the source-index register; otherwise the address-size attribute is 32 +bits, and the ESI register is used. The address of the source data is +determined solely by the contents of ESI/SI. Load the correct index value +into SI before executing the LODS instruction. LODSB, LODSW, LODSD are +synonyms for the byte, word, and doubleword LODS instructions. + +LODS can be preceded by the REP prefix; however, LODS is used more typically +within a LOOP construct, because further processing of the data moved into +EAX, AX, or AL is usually necessary. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +LOOP/LOOPcond Loop Control with CX Counter + +Opcode Instruction Clocks Description + +E2 cb LOOP rel8 11+m DEC count; jump short if count <> 0 +E1 cb LOOPE rel8 11+m DEC count; jump short if count <> 0 and ZF=1 +E1 cb LOOPZ rel8 11+m DEC count; jump short if count <> 0 and ZF=1 +E0 cb LOOPNE rel8 11+m DEC count; jump short if count <> 0 and ZF=0 +E0 cb LOOPNZ rel8 11+m DEC count; jump short if count <> 0 and ZF=0 + + +Operation + +IF AddressSize = 16 THEN CountReg is CX ELSE CountReg is ECX; FI; +CountReg  CountReg - 1; +IF instruction <> LOOP +THEN + IF (instruction = LOOPE) OR (instruction = LOOPZ) + THEN BranchCond  (ZF = 1) AND (CountReg <> 0); + FI; + IF (instruction = LOOPNE) OR (instruction = LOOPNZ) + THEN BranchCond  (ZF = 0) AND (CountReg <> 0); + FI; +FI; + +IF BranchCond +THEN + IF OperandSize = 16 + THEN + IP  IP + SignExtend(rel8); + ELSE (* OperandSize = 32 *) + EIP  EIP + SignExtend(rel8); + FI; +FI; + +Description + +LOOP decrements the count register without changing any of the flags. +Conditions are then checked for the form of LOOP being used. If the +conditions are met, a short jump is made to the label given by the operand +to LOOP. If the address-size attribute is 16 bits, the CX register is used +as the count register; otherwise the ECX register is used. The operand +of LOOP must be in the range from 128 (decimal) bytes before the +instruction to 127 bytes ahead of the instruction. + +The LOOP instructions provide iteration control and combine loop index +management with conditional branching. Use the LOOP instruction by +loading an unsigned iteration count into the count register, then code the +LOOP at the end of a series of instructions to be iterated. The +destination of LOOP is a label that points to the beginning of the +iteration. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the offset jumped to is beyond the limits of the current code +segment + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +LSL Load Segment Limit + +Opcode Instruction Clocks Description + +0F 03 /r LSL r16,r/m16 pm=20/21 Load: r16  segment limit, + selector r/m16 (byte granular) +0F 03 /r LSL r32,r/m32 pm=20/21 Load: r32  segment limit, + selector r/m32 (byte granular) +0F 03 /r LSL r16,r/m16 pm=25/26 Load: r16  segment limit, + selector r/m16 (page granular) +0F 03 /r LSL r32,r/m32 pm=25/26 Load: r32  segment limit, + selector r/m32 (page granular) + + +Description + +The LSL instruction loads a register with an unscrambled segment limit, +and sets ZF to 1, provided that the source selector is visible at the CPL +weakened by RPL, and that the descriptor is a type accepted by LSL. +Otherwise, ZF is cleared to 0, and the destination register is unchanged. +The segment limit is loaded as a byte granular value. If the descriptor +has a page granular segment limit, LSL will translate it to a byte limit +before loading it in the destination register (shift left 12 the 20-bit +"raw" limit from descriptor, then OR with 00000FFFH). + +The 32-bit forms of this instruction store the 32-bit byte granular limit +in the 16-bit destination register. + +Code and data segment descriptors are valid for LSL. + +The valid special segment and gate descriptor types for LSL are given +in the following table: + +Type Name Valid/Invalid + + 0 Invalid Invalid + 1 Available 80286 TSS Valid + 2 LDT Valid + 3 Busy 80286 TSS Valid + 4 80286 call gate Invalid + 5 80286/80386 task gate Invalid + 6 80286 trap gate Invalid + 7 80286 interrupt gate Invalid + 8 Invalid Valid + 9 Available 80386 TSS Valid + A Invalid Invalid + B Busy 80386 TSS Valid + C 80386 call gate Invalid + D Invalid Invalid + E 80386 trap gate Invalid + F 80386 interrupt gate Invalid + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; LSL is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LTR Load Task Register + +Opcode Instruction Clocks Description + +0F 00 /3 LTR r/m16 pm=23/27 Load EA word into task register + + +Description + +LTR loads the task register from the source register or memory location +specified by the operand. The loaded task state segment is marked busy. +A task switch does not occur. + +LTR is used only in operating system software; it is not used in +application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#GP(0) if the current privilege level is not 0; #GP(selector) if the object +named by the source selector is not a TSS or is already busy; +#NP(selector) if the TSS is marked "not present"; #PF(fault-code) for +a page fault + +Real Address Mode Exceptions + +Interrupt 6; LTR is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + +Notes + +The operand-size attribute has no effect on this instruction. + + +MOV Move Data + + +Opcode Instruction Clocks Description + +88 /r MOV r/m8,r8 2/2 Move byte register to r/m byte +89 /r MOV r/m16,r16 2/2 Move word register to r/m word +89 /r MOV r/m32,r32 2/2 Move dword register to r/m dword +8A /r MOV r8,r/m8 2/4 Move r/m byte to byte register +8B /r MOV r16,r/m16 2/4 Move r/m word to word register +8B /r MOV r32,r/m32 2/4 Move r/m dword to dword register +8C /r MOV r/m16,Sreg 2/2 Move segment register to r/m word +8D /r MOV Sreg,r/m16 2/5,pm=18/19 Move r/m word to segment register +A0 MOV AL,moffs8 4 Move byte at (seg:offset) to AL +A1 MOV AX,moffs16 4 Move word at (seg:offset) to AX +A1 MOV EAX,moffs32 4 Move dword at (seg:offset) to EAX +A2 MOV moffs8,AL 2 Move AL to (seg:offset) +A3 MOV moffs16,AX 2 Move AX to (seg:offset) +A3 MOV moffs32,EAX 2 Move EAX to (seg:offset) +B0 + rb MOV reg8,imm8 2 Move immediate byte to register +B8 + rw MOV reg16,imm16 2 Move immediate word to register +B8 + rd MOV reg32,imm32 2 Move immediate dword to register +C6 MOV r/m8,imm8 2/2 Move immediate byte to r/m byte +C7 MOV r/m16,imm16 2/2 Move immediate word to r/m word +C7 MOV r/m32,imm32 2/2 Move immediate dword to r/m dword + + + +NOTES: + moffs8, moffs16, and moffs32 all consist of a simple offset relative + to the segment base. The 8, 16, and 32 refer to the size of the data. The + address-size attribute of the instruction determines the size of the + offset, either 16 or 32 bits. + + +Operation + +DEST  SRC; + +Description + +MOV copies the second operand to the first operand. + +If the destination operand is a segment register (DS, ES, SS, etc.), then +data from a descriptor is also loaded into the register. The data for the +register is obtained from the descriptor table entry for the selector +given. A null selector (values 0000-0003) can be loaded into DS and ES +registers without causing an exception; however, use of DS or ES causes a +#GP(0), and no memory reference occurs. + +A MOV into SS inhibits all interrupts until after the execution of the +next instruction (which is presumably a MOV into eSP). + +Loading a segment register under 80386 Protected Mode results in special +checks and actions, as described in the following listing: + +IF SS is loaded; +THEN + IF selector is null THEN #GP(0); +FI; + Selector index must be within its descriptor table limits else + #GP(selector); + Selector's RPL must equal CPL else #GP(selector); +AR byte must indicate a writable data segment else #GP(selector); + DPL in the AR byte must equal CPL else #GP(selector); + Segment must be marked present else #SS(selector); + Load SS with selector; + Load SS with descriptor. +FI; +IF DS, ES, FS or GS is loaded with non-null selector; +THEN + Selector index must be within its descriptor table limits + else #GP(selector); + AR byte must indicate data or readable code segment else + #GP(selector); + IF data or nonconforming code segment + THEN both the RPL and the CPL must be less than or equal to DPL in + AR byte; + ELSE #GP(selector); + FI; + Segment must be marked present else #NP(selector); + Load segment register with selector; + Load segment register with descriptor; +FI; +IF DS, ES, FS or GS is loaded with a null selector; +THEN + Load segment register with selector; + Clear descriptor valid bit; +FI; + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #SS, and #NP if a segment register is being loaded; otherwise, +#GP(0) if the destination is in a nonwritable segment; #GP(0) for an +illegal memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MOV Move to/from Special Registers + +Opcode Instruction Clocks Description + +0F 20 /r MOV r32,CR0/CR2/CR3 6 Move (control register) to + (register) +0F 22 /r MOV CR0/CR2/CR3,r32 10/4/5 Move (register) to (control + register) +0F 21 /r MOV r32,DR0 -- 3 22 Move (debug register) to + (register) +0F 21 /r MOV r32,DR6/DR7 14 Move (debug register) to + (register) +0F 23 /r MOV DR0 -- 3,r32 22 Move (register) to (debug + register) +0F 23 /r MOV DR6/DR7,r32 16 Move (register) to (debug + register) +0F 24 /r MOV r32,TR6/TR7 12 Move (test register) to + (register) +0F 26 /r MOV TR6/TR7,r32 12 Move (register) to (test + register) + + +Operation + +DEST  SRC; + +Description + +The above forms of MOV store or load the following special registers in +or from a general purpose register: + + Control registers CR0, CR2, and CR3 + Debug Registers DR0, DR1, DR2, DR3, DR6, and DR7 + Test Registers TR6 and TR7 + +32-bit operands are always used with these instructions, regardless of the +operand-size attribute. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF are undefined + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) if instruction execution is attempted + +Notes + +The instructions must be executed at privilege level 0 or in real-address +mode; otherwise, a protection exception will be raised. + +The reg field within the ModRM byte specifies which of the special +registers in each category is involved. The two bits in the field are +always 11. The r/m field specifies the general register involved. + + +MOVS/MOVSB/MOVSW/MOVSD Move Data from String to String + +Opcode Instruction Clocks Description + +A4 MOVS m8,m8 7 Move byte [(E)SI] to ES:[(E)DI] +A5 MOVS m16,m16 7 Move word [(E)SI] to ES:[(E)DI] +A5 MOVS m32,m32 7 Move dword [(E)SI] to ES:[(E)DI] +A4 MOVSB 7 Move byte DS:[(E)SI] to ES:[(E)DI] +A5 MOVSW 7 Move word DS:[(E)SI] to ES:[(E)DI] +A5 MOVSD 7 Move dword DS:[(E)SI] to ES:[(E)DI] + + +Operation + +IF (instruction = MOVSD) OR (instruction has doubleword operands) +THEN OperandSize  32; +ELSE OperandSize  16; +IF AddressSize = 16 +THEN use SI for source-index and DI for destination-index; +ELSE (* AddressSize = 32 *) + use ESI for source-index and EDI for destination-index; +FI; +IF byte type of instruction +THEN + [destination-index]  [source-index]; (* byte assignment *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + [destination-index]  [source-index]; (* word assignment *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + [destination-index]  [source-index]; (* doubleword assignment *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index  source-index + IncDec; +destination-index  destination-index + IncDec; + +Description + +MOVS copies the byte or word at [(E)SI] to the byte or word at +ES:[(E)DI]. The destination operand must be addressable from the ES +register; no segment override is possible for the destination. A segment +override can be used for the source operand; the default is DS. + +The addresses of the source and destination are determined solely by the +contents of (E)SI and (E)DI. Load the correct index values into (E)SI +and (E)DI before executing the MOVS instruction. MOVSB, MOVSW, +and MOVSD are synonyms for the byte, word, and doubleword MOVS +instructions. + +After the data is moved, both (E)SI and (E)DI are advanced +automatically. If the direction flag is 0 (CLD was executed), the registers +are incremented; if the direction flag is 1 (STD was executed), the +registers are decremented. The registers are incremented or decremented by 1 +if a byte was moved, 2 if a word was moved, or 4 if a doubleword was moved. + +MOVS can be preceded by the REP prefix for block movement of CX +bytes or words. Refer to the REP instruction for details of this operation. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MOVSX Move with Sign-Extend + +Opcode Instruction Clocks Description + +0F BE /r MOVSX r16,r/m8 3/6 Move byte to word with sign-extend +0F BE /r MOVSX r32,r/m8 3/6 Move byte to dword, sign-extend +0F BF /r MOVSX r32,r/m16 3/6 Move word to dword, sign-extend + + +Operation + +DEST  SignExtend(SRC); + +Description + +MOVSX reads the contents of the effective address or register as a byte +or a word, sign-extends the value to the operand-size attribute of the +instruction (16 or 32 bits), and stores the result in the destination +register. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MOVZX Move with Zero-Extend + +Opcode Instruction Clocks Description + +0F B6 /r MOVZX r16,r/m8 3/6 Move byte to word with zero-extend +0F B6 /r MOVZX r32,r/m8 3/6 Move byte to dword, zero-extend +0F B7 /r MOVZX r32,r/m16 3/6 Move word to dword, zero-extend + + +Operation + +DEST  ZeroExtend(SRC); + +Description + +MOVZX reads the contents of the effective address or register as a byte +or a word, zero extends the value to the operand-size attribute of the +instruction (16 or 32 bits), and stores the result in the destination +register. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MUL Unsigned Multiplication of AL or AX + +Opcode Instruction Clocks Description + +F6 /4 MUL AL,r/m8 9-14/12-17 Unsigned multiply (AX  AL * r/m byte) +F7 /4 MUL AX,r/m16 9-22/12-25 Unsigned multiply (DX:AX  AX * r/m + word) +F7 /4 MUL EAX,r/m32 9-38/12-41 Unsigned multiply (EDX:EAX  EAX * r/m + dword) + + + +NOTES: + The 80386 uses an early-out multiply algorithm. The actual number of + clocks depends on the position of the most significant bit in the + optimizing multiplier, shown underlined above. The optimization occurs + for positive and negative multiplier values. Because of the early-out + algorithm, clock counts given are minimum to maximum. To calculate the + actual clocks, use the following formula: + + Actual clock = if <> 0 then max(ceiling(log{2} m), 3) + 6 clocks; + + Actual clock = if = 0 then 9 clocks + + where m is the multiplier. + + +Operation + +IF byte-size operation +THEN AX  AL * r/m8 +ELSE (* word or doubleword operation *) + IF OperandSize = 16 + THEN DX:AX  AX * r/m16 + ELSE (* OperandSize = 32 *) + EDX:EAX  EAX * r/m32 + FI; +FI; + +Description + +MUL performs unsigned multiplication. Its actions depend on the size +of its operand, as follows: + + A byte operand is multiplied by AL; the result is left in AX. The + carry and overflow flags are set to 0 if AH is 0; otherwise, they are + set to 1. + + A word operand is multiplied by AX; the result is left in DX:AX. + DX contains the high-order 16 bits of the product. The carry and + overflow flags are set to 0 if DX is 0; otherwise, they are set to 1. + + A doubleword operand is multiplied by EAX and the result is left in + EDX:EAX. EDX contains the high-order 32 bits of the product. The + carry and overflow flags are set to 0 if EDX is 0; otherwise, they are + set to 1. + +Flags Affected + +OF and CF as described above; SF, ZF, AF, PF, and CF are undefined + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +NEG Two's Complement Negation + +Opcode Instruction Clocks Description + +F6 /3 NEG r/m8 2/6 Two's complement negate r/m byte +F7 /3 NEG r/m16 2/6 Two's complement negate r/m word +F7 /3 NEG r/m32 2/6 Two's complement negate r/m dword + + +Operation + +IF r/m = 0 THEN CF  0 ELSE CF  1; FI; +r/m  - r/m; + +Description + +NEG replaces the value of a register or memory operand with its two's +complement. The operand is subtracted from zero, and the result is placed +in the operand. + +The carry flag is set to 1, unless the operand is zero, in which case the +carry flag is cleared to 0. + +Flags Affected + +CF as described above; OF, SF, ZF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +NOP No Operation + +Opcode Instruction Clocks Description + +90 NOP 3 No operation + + +Description + +NOP performs no operation. NOP is a one-byte instruction that takes +up space but affects none of the machine context except (E)IP. + +NOP is an alias mnemonic for the XCHG (E)AX, (E)AX instruction. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +NOT One's Complement Negation + +Opcode Instruction Clocks Description + +F6 /2 NOT r/m8 2/6 Reverse each bit of r/m byte +F7 /2 NOT r/m16 2/6 Reverse each bit of r/m word +F7 /2 NOT r/m32 2/6 Reverse each bit of r/m dword + + +Operation + +r/m  NOT r/m; + +Description + +NOT inverts the operand; every 1 becomes a 0, and vice versa. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +OR Logical Inclusive OR + +Opcode Instruction Clocks Description + +0C ib OR AL,imm8 2 OR immediate byte to AL +0D iw OR AX,imm16 2 OR immediate word to AX +0D id OR EAX,imm32 2 OR immediate dword to EAX +80 /1 ib OR r/m8,imm8 2/7 OR immediate byte to r/m byte +81 /1 iw OR r/m16,imm16 2/7 OR immediate word to r/m word +81 /1 id OR r/m32,imm32 2/7 OR immediate dword to r/m dword +83 /1 ib OR r/m16,imm8 2/7 OR sign-extended immediate byte + with r/m word +83 /1 ib OR r/m32,imm8 2/7 OR sign-extended immediate byte + with r/m dword +08 /r OR r/m8,r8 2/6 OR byte register to r/m byte +09 /r OR r/m16,r16 2/6 OR word register to r/m word +09 /r OR r/m32,r32 2/6 OR dword register to r/m dword +0A /r OR r8,r/m8 2/7 OR byte register to r/m byte +0B /r OR r16,r/m16 2/7 OR word register to r/m word +0B /r OR r32,r/m32 2/7 OR dword register to r/m dword + + +Operation + +DEST  DEST OR SRC; +CF  0; +OF  0 + +Description + +OR computes the inclusive OR of its two operands and places the result +in the first operand. Each bit of the result is 0 if both corresponding +bits of the operands are 0; otherwise, each bit is 1. + +Flags Affected + +OF  0, CF  0; SF, ZF, and PF as described in Appendix C; AF is +undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +OUT Output to Port + +Opcode Instruction Clocks Description + +E6 ib OUT imm8,AL 10,pm=4*/24** Output byte AL to immediate port + number +E7 ib OUT imm8,AX 10,pm=4*/24** Output word AL to immediate port + number +E7 ib OUT imm8,EAX 10,pm=4*/24** Output dword AL to immediate + port number +EE OUT DX,AL 11,pm=5*/25** Output byte AL to port number in +DX +EF OUT DX,AX 11,pm=5*/25** Output word AL to port number in +DX +EF OUT DX,EAX 11,pm=5*/25** Output dword AL to port number + in DX + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (DEST, width(DEST)) + THEN #GP(0); + FI; +FI; +[DEST]  SRC; (* I/O address space used *) + +Description + +OUT transfers a data byte or data word from the register (AL, AX, or +EAX) given as the second operand to the output port numbered by the +first operand. Output to any port from 0 to 65535 is performed by placing +the port number in the DX register and then using an OUT instruction +with DX as the first operand. If the instruction contains an eight-bit port +ID, that value is zero-extended to 16 bits. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is higher (has less privilege) than +IOPL and any of the corresponding I/O permission bits in TSS equals 1 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1 + + +OUTS/OUTSB/OUTSW/OUTSD Output String to Port + +Opcode Instruction Clocks Description + +6E OUTS DX,r/m8 14,pm=8*/28** Output byte [(E)SI] to port in DX +6F OUTS DX,r/m16 14,pm=8*/28** Output word [(E)SI] to port in DX +6F OUTS DX,r/m32 14,pm=8*/28** Output dword [(E)SI] to port in DX +6E OUTSB 14,pm=8*/28** Output byte DS:[(E)SI] to port in + DX +6F OUTSW 14,pm=8*/28** Output word DS:[(E)SI] to port in + DX +6F OUTSD 14,pm=8*/28** Output dword DS:[(E)SI] to port in + DX + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF AddressSize = 16 +THEN use SI for source-index; +ELSE (* AddressSize = 32 *) + use ESI for source-index; +FI; + +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (DEST, width(DEST)) + THEN #GP(0); + FI; +FI; +IF byte type of instruction +THEN + [DX]  [source-index]; (* Write byte at DX I/O address *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +FI; +IF OperandSize = 16 +THEN + [DX]  [source-index]; (* Write word at DX I/O address *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; +FI; +IF OperandSize = 32 +THEN + [DX]  [source-index]; (* Write dword at DX I/O address *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index  source-index + IncDec; + +Description + +OUTS transfers data from the memory byte, word, or doubleword at the +source-index register to the output port addressed by the DX register. If +the address-size attribute for this instruction is 16 bits, SI is used for +the source-index register; otherwise, the address-size attribute is 32 bits, +and ESI is used for the source-index register. + +OUTS does not allow specification of the port number as an immediate value. +The port must be addressed through the DX register value. Load the correct +value into DX before executing the OUTS instruction. + +The address of the source data is determined by the contents of +source-index register. Load the correct index value into SI or ESI before +executing the OUTS instruction. + +After the transfer, source-index register is advanced automatically. If +the direction flag is 0 (CLD was executed), the source-index register is +incremented; if the direction flag is 1 (STD was executed), it is +decremented. The amount of the increment or decrement is 1 if a byte is +output, 2 if a word is output, or 4 if a doubleword is output. + +OUTSB, OUTSW, and OUTSD are synonyms for the byte, word, and +doubleword OUTS instructions. OUTS can be preceded by the REP +prefix for block output of CX bytes or words. Refer to the REP +instruction for details on this operation. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if CPL is greater than IOPL and any of the corresponding I/O +permission bits in TSS equals 1; #GP(0) for an illegal memory operand +effective address in the CS, DS, or ES segments; #SS(0) for an illegal +address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1; #PF(fault-code) for a page fault + + +POP Pop a Word from the Stack + +Opcode Instruction Clocks Description + +8F /0 POP m16 5 Pop top of stack into memory word +8F /0 POP m32 5 Pop top of stack into memory dword +58 + rw POP r16 4 Pop top of stack into word register +58 + rd POP r32 4 Pop top of stack into dword register +1F POP DS 7,pm=21 Pop top of stack into DS +07 POP ES 7,pm=21 Pop top of stack into ES +17 POP SS 7,pm=21 Pop top of stack into SS +0F A1 POP FS 7,pm=21 Pop top of stack into FS +0F A9 POP GS 7,pm=21 Pop top of stack into GS + + +Operation + +IF StackAddrSize = 16 +THEN + IF OperandSize = 16 + THEN + DEST  (SS:SP); (* copy a word *) + SP  SP + 2; + ELSE (* OperandSize = 32 *) + DEST  (SS:SP); (* copy a dword *) + SP  SP + 4; + FI; +ELSE (* StackAddrSize = 32 * ) + IF OperandSize = 16 + THEN + DEST  (SS:ESP); (* copy a word *) + ESP  ESP + 2; + ELSE (* OperandSize = 32 *) + DEST  (SS:ESP); (* copy a dword *) + ESP  ESP + 4; + FI; +FI; + +Description + +POP replaces the previous contents of the memory, the register, or the +segment register operand with the word on the top of the 80386 stack, +addressed by SS:SP (address-size attribute of 16 bits) or SS:ESP +(addresssize attribute of 32 bits). The stack pointer SP is incremented +by 2 for an operand-size of 16 bits or by 4 for an operand-size of 32 bits. +It then points to the new top of stack. + +POP CS is not an 80386 instruction. Popping from the stack into the CS +register is accomplished with a RET instruction. + +If the destination operand is a segment register (DS, ES, FS, GS, or +SS), the value popped must be a selector. In protected mode, loading the +selector initiates automatic loading of the descriptor information +associated with that selector into the hidden part of the segment register; +loading also initiates validation of both the selector and the descriptor +information. + +A null value (0000-0003) may be popped into the DS, ES, FS, or GS +register without causing a protection exception. An attempt to reference +a segment whose corresponding segment register is loaded with a null +value causes a #GP(0) exception. No memory reference occurs. The saved +value of the segment register is null. + +A POP SS instruction inhibits all interrupts, including NMI, until after +execution of the next instruction. This allows sequential execution of POP +SS and POP eSP instructions without danger of having an invalid stack +during an interrupt. However, use of the LSS instruction is the preferred +method of loading the SS and eSP registers. + +Loading a segment register while in protected mode results in special +checks and actions, as described in the following listing: + +IF SS is loaded: + IF selector is null THEN #GP(0); + Selector index must be within its descriptor table limits ELSE + #GP(selector); + Selector's RPL must equal CPL ELSE #GP(selector); + AR byte must indicate a writable data segment ELSE #GP(selector); + DPL in the AR byte must equal CPL ELSE #GP(selector); + Segment must be marked present ELSE #SS(selector); + Load SS register with selector; + Load SS register with descriptor; + +IF DS, ES, FS or GS is loaded with non-null selector: + AR byte must indicate data or readable code segment ELSE + #GP(selector); + IF data or nonconforming code + THEN both the RPL and the CPL must be less than or equal to DPL in + AR byte + ELSE #GP(selector); + FI; + Segment must be marked present ELSE #NP(selector); + Load segment register with selector; + Load segment register with descriptor; + +IF DS, ES, FS, or GS is loaded with a null selector: + Load segment register with selector + Clear valid bit in invisible portion of register + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #SS, and #NP if a segment register is being loaded; #SS(0) if the +current top of stack is not within the stack segment; #GP(0) if the result +is in a nonwritable segment; #GP(0) for an illegal memory operand +effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an +illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +POPA/POPAD Pop all General Registers + +Opcode Instruction Clocks Description + +61 POPA 24 Pop DI, SI, BP, SP, BX, DX, CX, and AX +61 POPAD 24 Pop EDI, ESI, EBP, ESP, EDX, ECX, and EAX + + +Operation + +IF OperandSize = 16 (* instruction = POPA *) +THEN + DI  Pop(); + SI  Pop(); + BP  Pop(); + throwaway  Pop (); (* Skip SP *) + BX  Pop(); + DX  Pop(); + CX  Pop(); + AX  Pop(); +ELSE (* OperandSize = 32, instruction = POPAD *) + EDI  Pop(); + ESI  Pop(); + EBP  Pop(); + throwaway  Pop (); (* Skip ESP *) + EBX  Pop(); + EDX  Pop(); + ECX  Pop(); + EAX  Pop(); +FI; + +Description + +POPA pops the eight 16-bit general registers. However, the SP value is +discarded instead of loaded into SP. POPA reverses a previous PUSHA, +restoring the general registers to their values before PUSHA was +executed. The first register popped is DI. + +POPAD pops the eight 32-bit general registers. The ESP value is +discarded instead of loaded into ESP. POPAD reverses the previous +PUSHAD, restoring the general registers to their values before PUSHAD +was executed. The first register popped is EDI. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the starting or ending stack address is not within the stack +segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +POPF/POPFD Pop Stack into FLAGS or EFLAGS Register + +Opcode Instruction Clocks Description + +9D POPF 5 Pop top of stack FLAGS +9D POPFD 5 Pop top of stack into EFLAGS + + +Operation + +Flags  Pop(); + +Description + +POPF/POPFD pops the word or doubleword on the top of the stack and +stores the value in the flags register. If the operand-size attribute of +the instruction is 16 bits, then a word is popped and the value is stored in +FLAGS. If the operand-size attribute is 32 bits, then a doubleword is popped +and the value is stored in EFLAGS. + +Refer to Chapter 2 and Chapter 4 for information about the FLAGS +and EFLAGS registers. Note that bits 16 and 17 of EFLAGS, called +VM and RF, respectively, are not affected by POPF or POPFD. + +The I/O privilege level is altered only when executing at privilege level +0. The interrupt flag is altered only when executing at a level at least as +privileged as the I/O privilege level. (Real-address mode is equivalent to +privilege level 0.) If a POPF instruction is executed with insufficient +privilege, an exception does not occur, but the privileged bits do not +change. + +Flags Affected + +All flags except VM and RF + +Protected Mode Exceptions + +#SS(0) if the top of stack is not within the stack segment + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, to permit emulation + + +PUSH Push Operand onto the Stack + +Opcode Instruction Clocks Description + +FF /6 PUSH m16 5 Push memory word +FF /6 PUSH m32 5 Push memory dword +50 + /r PUSH r16 2 Push register word +50 + /r PUSH r32 2 Push register dword +6A PUSH imm8 2 Push immediate byte +68 PUSH imm16 2 Push immediate word +68 PUSH imm32 2 Push immediate dword +0E PUSH CS 2 Push CS +16 PUSH SS 2 Push SS +1E PUSH DS 2 Push DS +06 PUSH ES 2 Push ES +0F A0 PUSH FS 2 Push FS +OF A8 PUSH GS 2 Push GS + + +Operation + +IF StackAddrSize = 16 +THEN + IF OperandSize = 16 THEN + SP  SP - 2; + (SS:SP)  (SOURCE); (* word assignment *) + ELSE + SP  SP - 4; + (SS:SP)  (SOURCE); (* dword assignment *) + FI; +ELSE (* StackAddrSize = 32 *) + IF OperandSize = 16 + THEN + ESP  ESP - 2; + (SS:ESP)  (SOURCE); (* word assignment *) + ELSE + ESP  ESP - 4; + (SS:ESP)  (SOURCE); (* dword assignment *) + FI; +FI; + +Description + +PUSH decrements the stack pointer by 2 if the operand-size attribute of +the instruction is 16 bits; otherwise, it decrements the stack pointer by +4. PUSH then places the operand on the new top of stack, which is +pointed to by the stack pointer. + +The 80386 PUSH eSP instruction pushes the value of eSP as it existed +before the instruction. This differs from the 8086, where PUSH SP +pushes the new value (decremented by 2). + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the new value of SP or ESP is outside the stack segment limit; +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +None; if SP or ESP is 1, the 80386 shuts down due to a lack of stack +space + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +PUSHA/PUSHAD Push all General Registers + +Opcode Instruction Clocks Description + +60 PUSHA 18 Push AX, CX, DX, BX, original SP, BP, SI, and + DI +60 PUSHAD 18 Push EAX, ECX, EDX, EBX, original ESP, EBP, + ESI, and EDI + + +Operation + +IF OperandSize = 16 (* PUSHA instruction *) +THEN + Temp  (SP); + Push(AX); + Push(CX); + Push(DX); + Push(BX); + Push(Temp); + Push(BP); + Push(SI); + Push(DI); +ELSE (* OperandSize = 32, PUSHAD instruction *) + Temp  (ESP); + Push(EAX); + Push(ECX); + Push(EDX); + Push(EBX); + Push(Temp); + Push(EBP); + Push(ESI); + Push(EDI); +FI; + +Description + +PUSHA and PUSHAD save the 16-bit or 32-bit general registers, +respectively, on the 80386 stack. PUSHA decrements the stack pointer +(SP) by 16 to hold the eight word values. PUSHAD decrements the +stack pointer (ESP) by 32 to hold the eight doubleword values. Because +the registers are pushed onto the stack in the order in which they were +given, they appear in the 16 or 32 new stack bytes in reverse order. The +last register pushed is DI or EDI. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the starting or ending stack address is outside the stack segment +limit; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Before executing PUSHA or PUSHAD, the 80386 shuts down if SP or +ESP equals 1, 3, or 5; if SP or ESP equals 7, 9, 11, 13, or 15, exception +13 occurs + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +PUSHF/PUSHFD Push Flags Register onto the Stack + +Opcode Instruction Clocks Description + +9C PUSHF 4 Push FLAGS +9C PUSHFD 4 Push EFLAGS + + +Operation + +IF OperandSize = 32 +THEN push(EFLAGS); +ELSE push(FLAGS); +FI; + +Description + +PUSHF decrements the stack pointer by 2 and copies the FLAGS +register to the new top of stack; PUSHFD decrements the stack pointer by +4, and the 80386 EFLAGS register is copied to the new top of stack +which is pointed to by SS:eSP. Refer to Chapter 2 and Chapter 4 for +information on the EFLAGS register. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the new value of eSP is outside the stack segment boundaries + +Real Address Mode Exceptions + +None; the 80386 shuts down due to a lack of stack space + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, to permit emulation + + +RCL/RCR/ROL/ROR Rotate + + +Opcode Instruction Clocks Description + +D0 /2 RCL r/m8,1 9/10 Rotate 9 bits (CF,r/m byte) left + once +D2 /2 RCL r/m8,CL 9/10 Rotate 9 bits (CF,r/m byte) left CL + times +C0 /2 ib RCL r/m8,imm8 9/10 Rotate 9 bits (CF,r/m byte) left + imm8 times +D1 /2 RCL r/m16,1 9/10 Rotate 17 bits (CF,r/m word) left + once +D3 /2 RCL r/m16,CL 9/10 Rotate 17 bits (CF,r/m word) left + CL times +C1 /2 ib RCL r/m16,imm8 9/10 Rotate 17 bits (CF,r/m word) left + imm8 times +D1 /2 RCL r/m32,1 9/10 Rotate 33 bits (CF,r/m dword) left + once +D3 /2 RCL r/m32,CL 9/10 Rotate 33 bits (CF,r/m dword) left + CL times +C1 /2 ib RCL r/m32,imm8 9/10 Rotate 33 bits (CF,r/m dword) left + imm8 times +D0 /3 RCR r/m8,1 9/10 Rotate 9 bits (CF,r/m byte) right + once +D2 /3 RCR r/m8,CL 9/10 Rotate 9 bits (CF,r/m byte) right + CL times +C0 /3 ib RCR r/m8,imm8 9/10 Rotate 9 bits (CF,r/m byte) right + imm8 times +D1 /3 RCR r/m16,1 9/10 Rotate 17 bits (CF,r/m word) right + once +D3 /3 RCR r/m16,CL 9/10 Rotate 17 bits (CF,r/m word) right + CL times +C1 /3 ib RCR r/m16,imm8 9/10 Rotate 17 bits (CF,r/m word) right + imm8 times +D1 /3 RCR r/m32,1 9/10 Rotate 33 bits (CF,r/m dword) right + once +D3 /3 RCR r/m32,CL 9/10 Rotate 33 bits (CF,r/m dword) right + CL times +C1 /3 ib RCR r/m32,imm8 9/10 Rotate 33 bits (CF,r/m dword) right + imm8 times +D0 /0 ROL r/m8,1 3/7 Rotate 8 bits r/m byte left once +D2 /0 ROL r/m8,CL 3/7 Rotate 8 bits r/m byte left CL + times +C0 /0 ib ROL r/m8,imm8 3/7 Rotate 8 bits r/m byte left imm8 + times +D1 /0 ROL r/m16,1 3/7 Rotate 16 bits r/m word left once +D3 /0 ROL r/m16,CL 3/7 Rotate 16 bits r/m word left CL + times +C1 /0 ib ROL r/m16,imm8 3/7 Rotate 16 bits r/m word left imm8 + times +D1 /0 ROL r/m32,1 3/7 Rotate 32 bits r/m dword left once +D3 /0 ROL r/m32,CL 3/7 Rotate 32 bits r/m dword left CL + times +C1 /0 ib ROL r/m32,imm8 3/7 Rotate 32 bits r/m dword left imm8 + times +D0 /1 ROR r/m8,1 3/7 Rotate 8 bits r/m byte right once +D2 /1 ROR r/m8,CL 3/7 Rotate 8 bits r/m byte right CL + times +C0 /1 ib ROR r/m8,imm8 3/7 Rotate 8 bits r/m word right imm8 + times +D1 /1 ROR r/m16,1 3/7 Rotate 16 bits r/m word right once +D3 /1 ROR r/m16,CL 3/7 Rotate 16 bits r/m word right CL + times +C1 /1 ib ROR r/m16,imm8 3/7 Rotate 16 bits r/m word right imm8 + times +D1 /1 ROR r/m32,1 3/7 Rotate 32 bits r/m dword right once +D3 /1 ROR r/m32,CL 3/7 Rotate 32 bits r/m dword right CL + times +C1 /1 ib ROR r/m32,imm8 3/7 Rotate 32 bits r/m dword right imm8 + times + + +Operation + +(* ROL - Rotate Left *) +temp  COUNT; +WHILE (temp <> 0) +DO + tmpcf  high-order bit of (r/m); + r/m  r/m * 2 + (tmpcf); + temp  temp - 1; +OD; +IF COUNT = 1 +THEN + IF high-order bit of r/m <> CF + THEN OF  1; + ELSE OF  0; + FI; +ELSE OF  undefined; +FI; +(* ROR - Rotate Right *) +temp  COUNT; +WHILE (temp <> 0 ) +DO + tmpcf  low-order bit of (r/m); + r/m  r/m / 2 + (tmpcf * 2^(width(r/m))); + temp  temp - 1; +DO; +IF COUNT = 1 +THEN + IF (high-order bit of r/m) <> (bit next to high-order bit of r/m) + THEN OF  1; + ELSE OF  0; + FI; +ELSE OF  undefined; +FI; + +Description + +Each rotate instruction shifts the bits of the register or memory operand +given. The left rotate instructions shift all the bits upward, except for +the top bit, which is returned to the bottom. The right rotate instructions +do the reverse: the bits shift downward until the bottom bit arrives at +the top. + +For the RCL and RCR instructions, the carry flag is part of the rotated +quantity. RCL shifts the carry flag into the bottom bit and shifts the top +bit into the carry flag; RCR shifts the carry flag into the top bit and +shifts the bottom bit into the carry flag. For the ROL and ROR +instructions, the original value of the carry flag is not a part of the +result, but the carry flag receives a copy of the bit that was shifted from +one end to the other. + +The rotate is repeated the number of times indicated by the second +operand, which is either an immediate number or the contents of the CL +register. To reduce the maximum instruction execution time, the 80386 +does not allow rotation counts greater than 31. If a rotation count greater +than 31 is attempted, only the bottom five bits of the rotation are used. +The 8086 does not mask rotation counts. The 80386 in Virtual 8086 Mode does +mask rotation counts. + +The overflow flag is defined only for the single-rotate forms of the +instructions (second operand = 1). It is undefined in all other cases. For +left shifts/rotates, the CF bit after the shift is XORed with the +high-order result bit. For right shifts/rotates, the high-order two bits of +the result are XORed to get OF. + +Flags Affected + +OF only for single rotates; OF is undefined for multi-bit rotates; CF as +described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +REP/REPE/REPZ/REPNE/REPNZ Repeat Following String Operation + + +Opcode Instruction Clocks Description + +F3 6C REP INS r/m8, DX 13+6*(E)CX, + pm=7+6*(E)CX +If CPL IOPL/ + 27+6*(E)CX +If CPL > IOPL or if in virtual 8086 mode Input (E)CX bytes from port + DX into ES:[(E)DI] +F3 6D REP INS r/m16,DX 13+6*(E)CX, + pm=7+6*(E)CX +If CPL IOPL/ + 27+6*(E)CX +If CPL > IOPL or if in virtual 8086 mode Input (E)CX words from port + DX into ES:[(E)DI] +F3 6D REP INS r/m32,DX 13+6*(E)CX, + pm=7+6*(E)CX +If CPL IOPL/ + 27+6*(E)CX +If CPL > IOPL or if in virtual 8086 mode Input (E)CX dwords from port + DX into ES:[(E)DI] +F3 A4 REP MOVS m8,m8 5+4*(E)CX Move (E)CX bytes from + [(E)SI] to ES:[(E)DI] +F3 A5 REP MOVS m16,m16 5+4*(E)CX Move (E)CX words from + [(E)SI] to ES:[(E)DI] +F3 A5 REP MOVS m32,m32 5+4*(E)CX Move (E)CX dwords from + [(E)SI] to ES:[(E)DI] +F3 6E REP OUTS DX,r/m8 5+12*(E)CX, + pm=6+5*(E)CX +If CPL IOPL/ + 26+5*(E)CX +If CPL > IOPL or if in virtual 8086 mode Output (E)CX bytes from + [(E)SI] to port DX +F3 6F REP OUTS DX,r/m16 5+12*(E)CX, + pm=6+5*(E)CX +If CPL IOPL/ + 26+5*(E)CX +If CPL > IOPL or if in virtual 8086 mode Output (E)CX words from + [(E)SI] to port DX +F3 6F REP OUTS DX,r/m32 5+12*(E)CX, + pm=6+5*(E)CX +If CPL IOPL/ + 26+5*(E)CX +If CPL > IOPL or if in virtual 8086 mode Output (E)CX dwords from + [(E)SI] to port DX +F3 AA REP STOS m8 5+5*(E)CX Fill (E)CX bytes at + ES:[(E)DI] with AL +F3 AB REP STOS m16 5+5*(E)CX Fill (E)CX words at + ES:[(E)DI] with AX +F3 AB REP STOS m32 5+5*(E)CX Fill (E)CX dwords at + ES:[(E)DI] with EAX +F3 A6 REPE CMPS m8,m8 5+9*N Find nonmatching bytes in + ES:[(E)DI] and [(E)SI] +F3 A7 REPE CMPS m16,m16 5+9*N Find nonmatching words in + ES:[(E)DI] and [(E)SI] +F3 A7 REPE CMPS m32,m32 5+9*N Find nonmatching dwords in + ES:[(E)DI] and [(E)SI] +F3 AE REPE SCAS m8 5+8*N Find non-AL byte starting + at ES:[(E)DI] +F3 AF REPE SCAS m16 5+8*N Find non-AX word starting + at ES:[(E)DI] +F3 AF REPE SCAS m32 5+8*N Find non-EAX dword starting + at ES:[(E)DI] +F2 A6 REPNE CMPS m8,m8 5+9*N Find matching bytes in + ES:[(E)DI] and [(E)SI] +F2 A7 REPNE CMPS m16,m16 5+9*N Find matching words in + ES:[(E)DI] and [(E)SI] +F2 A7 REPNE CMPS m32,m32 5+9*N Find matching dwords in + ES:[(E)DI] and [(E)SI] +F2 AE REPNE SCAS m8 5+8*N Find AL, starting at + ES:[(E)DI] +F2 AF REPNE SCAS m16 5+8*N Find AX, starting at + ES:[(E)DI] +F2 AF REPNE SCAS m32 5+8*N Find EAX, starting at + ES:[(E)DI] + + +Operation + +IF AddressSize = 16 +THEN use CX for CountReg; +ELSE (* AddressSize = 32 *) use ECX for CountReg; +FI; +WHILE CountReg <> 0 +DO + service pending interrupts (if any); + perform primitive string instruction; + CountReg  CountReg - 1; + IF primitive operation is CMPB, CMPW, SCAB, or SCAW + THEN + IF (instruction is REP/REPE/REPZ) AND (ZF=1) + THEN exit WHILE loop + ELSE + IF (instruction is REPNZ or REPNE) AND (ZF=0) + THEN exit WHILE loop; + FI; + FI; + FI; +OD; + +Description + +REP, REPE (repeat while equal), and REPNE (repeat while not equal) +are prefix that are applied to string operation. Each prefix cause the +string instruction that follows to be repeated the number of times +indicated in the count register or (for REPE and REPNE) until the +indicated condition in the zero flag is no longer met. + +Synonymous forms of REPE and REPNE are REPZ and REPNZ, +respectively. + +The REP prefixes apply only to one string instruction at a time. To repeat +a block of instructions, use the LOOP instruction or another looping +construct. + +The precise action for each iteration is as follows: + + 1. If the address-size attribute is 16 bits, use CX for the count + register; if the address-size attribute is 32 bits, use ECX for the + count register. + + 2. Check CX. If it is zero, exit the iteration, and move to the next + instruction. + + 3. Acknowledge any pending interrupts. + + 4. Perform the string operation once. + + 5. Decrement CX or ECX by one; no flags are modified. + + 6. Check the zero flag if the string operation is SCAS or CMPS. If + the repeat condition does not hold, exit the iteration and move to + the next instruction. Exit the iteration if the prefix is REPE and ZF + is 0 (the last comparison was not equal), or if the prefix is REPNE + and ZF is one (the last comparison was equal). + + 7. Return to step 1 for the next iteration. + +Repeated CMPS and SCAS instructions can be exited if the count is +exhausted or if the zero flag fails the repeat condition. These two cases +can be distinguished by using either the JCXZ instruction, or by using +the conditional jumps that test the zero flag (JZ, JNZ, and JNE). + +Flags Affected + +ZF by REP CMPS and REP SCAS as described above + +Protected Mode Exceptions + +#UD if a repeat prefix is used before an instruction that is not in the +list above; further exceptions can be generated when the string operation is +executed; refer to the descriptions of the string instructions themselves + +Real Address Mode Exceptions + +Interrupt 6 if a repeat prefix is used before an instruction that is not in +the list above; further exceptions can be generated when the string +operation is executed; refer to the descriptions of the string instructions +themselves + +Virtual 8086 Mode Exceptions + +#UD if a repeat prefix is used before an instruction that is not in the +list above; further exceptions can be generated when the string operation is +executed; refer to the descriptions of the string instructions themselves + +Notes + +Not all input/output ports can handle the rate at which the REP INS +and REP OUTS instructions execute. + + +RET Return from Procedure + +Opcode Instruction Clocks Description + +C3 RET 10+m Return (near) to caller +CB RET 18+m,pm=32+m Return (far) to caller, same + privilege +CB RET pm=68 Return (far), lesser privilege, + switch stacks +C2 iw RET imm16 10+m Return (near), pop imm16 bytes of + parameters +CA iw RET imm16 18+m,pm=32+m Return (far), same privilege, pop + imm16 bytes +CA iw RET imm16 pm=68 Return (far), lesser privilege, pop + imm16 bytes + + +Operation + +IF instruction = near RET +THEN; + IF OperandSize = 16 + THEN + IP  Pop(); + EIP  EIP AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + EIP  Pop(); + FI; + IF instruction has immediate operand THEN eSP  eSP + imm16; FI; +FI; + +IF (PE = 0 OR (PE = 1 AND VM = 1)) + (* real mode or virtual 8086 mode *) + AND instruction = far RET +THEN; + IF OperandSize = 16 + THEN + IP  Pop(); + EIP  EIP AND 0000FFFFH; + CS  Pop(); (* 16-bit pop *) + ELSE (* OperandSize = 32 *) + EIP  Pop(); + CS  Pop(); (* 32-bit pop, high-order 16-bits discarded *) + FI; + IF instruction has immediate operand THEN eSP  eSP + imm16; FI; +FI; + +IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *) + AND instruction = far RET +THEN + IF OperandSize=32 + THEN Third word on stack must be within stack limits else #SS(0); + ELSE Second word on stack must be within stack limits else #SS(0); + FI; + Return selector RPL must be CPL ELSE #GP(return selector) + IF return selector RPL = CPL + THEN GOTO SAME-LEVEL; + ELSE GOTO OUTER-PRIVILEGE-LEVEL; + FI; +FI; + +SAME-LEVEL: + Return selector must be non-null ELSE #GP(0) + Selector index must be within its descriptor table limits ELSE + #GP(selector) + Descriptor AR byte must indicate code segment ELSE #GP(selector) + IF non-conforming + THEN code segment DPL must equal CPL; + ELSE #GP(selector); + FI; + IF conforming + THEN code segment DPL must be CPL; + ELSE #GP(selector); + FI; + Code segment must be present ELSE #NP(selector); + Top word on stack must be within stack limits ELSE #SS(0); + IP must be in code segment limit ELSE #GP(0); + IF OperandSize=32 + THEN + Load CS:EIP from stack + Load CS register with descriptor + Increment eSP by 8 plus the immediate offset if it exists + ELSE (* OperandSize=16 *) + Load CS:IP from stack + Load CS register with descriptor + Increment eSP by 4 plus the immediate offset if it exists + FI; + +OUTER-PRIVILEGE-LEVEL: + IF OperandSize=32 + THEN Top (16+immediate) bytes on stack must be within stack limits + ELSE #SS(0); + ELSE Top (8+immediate) bytes on stack must be within stack limits ELSE + #SS(0); + FI; + Examine return CS selector and associated descriptor: + Selector must be non-null ELSE #GP(0); + Selector index must be within its descriptor table limits ELSE + #GP(selector) + Descriptor AR byte must indicate code segment ELSE #GP(selector); + IF non-conforming + THEN code segment DPL must equal return selector RPL + ELSE #GP(selector); + FI; + IF conforming + THEN code segment DPL must be return selector RPL; + ELSE #GP(selector); + FI; + Segment must be present ELSE #NP(selector) + Examine return SS selector and associated descriptor: + Selector must be non-null ELSE #GP(0); + Selector index must be within its descriptor table limits + ELSE #GP(selector); + Selector RPL must equal the RPL of the return CS selector ELSE + #GP(selector); + Descriptor AR byte must indicate a writable data segment ELSE + #GP(selector); + Descriptor DPL must equal the RPL of the return CS selector ELSE + #GP(selector); + Segment must be present ELSE #NP(selector); + IP must be in code segment limit ELSE #GP(0); + Set CPL to the RPL of the return CS selector; + IF OperandMode=32 + THEN + Load CS:EIP from stack; + Set CS RPL to CPL; + Increment eSP by 8 plus the immediate offset if it exists; + Load SS:eSP from stack; + ELSE (* OperandMode=16 *) + Load CS:IP from stack; + Set CS RPL to CPL; + Increment eSP by 4 plus the immediate offset if it exists; + Load SS:eSP from stack; + FI; + Load the CS register with the return CS descriptor; + Load the SS register with the return SS descriptor; + For each of ES, FS, GS, and DS + DO + IF the current register setting is not valid for the outer level, + set the register to null (selector  AR  0); + To be valid, the register setting must satisfy the following + properties: + Selector index must be within descriptor table limits; + Descriptor AR byte must indicate data or readable code segment; + IF segment is data or non-conforming code, THEN + DPL must be CPL, or DPL must be RPL; + FI; + OD; + +Description + +RET transfers control to a return address located on the stack. The +address is usually placed on the stack by a CALL instruction, and the +return is made to the instruction that follows the CALL. + +The optional numeric parameter to RET gives the number of stack bytes +(OperandMode=16) or words (OperandMode=32) to be released after the return +address is popped. These items are typically used as input parameters to the +procedure called. + +For the intrasegment (near) return, the address on the stack is a segment +offset, which is popped into the instruction pointer. The CS register is +unchanged. For the intersegment (far) return, the address on the stack +is a long pointer. The offset is popped first, followed by the selector. + +In real mode, CS and IP are loaded directly. In Protected Mode, an +intersegment return causes the processor to check the descriptor +addressed by the return selector. The AR byte of the descriptor must +indicate a code segment of equal or lesser privilege (or greater or equal +numeric value) than the current privilege level. Returns to a lesser +privilege level cause the stack to be reloaded from the value saved beyond +the parameter block. + +The DS, ES, FS, and GS segment registers can be set to 0 by the RET +instruction during an interlevel transfer. If these registers refer to +segments that cannot be used by the new privilege level, they are set to +0 to prevent unauthorized access from the new privilege level. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #NP, or #SS, as described under "Operation" above; #PF(fault-code) for +a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would be outside the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SAHF Store AH into Flags + +Opcode Instruction Clocks Description + +9E SAHF 3 Store AH into flags SF ZF xx AF xx PF xx CF + + +Operation + +SF:ZF:xx:AF:xx:PF:xx:CF  AH; + +Description + +SAHF loads the flags listed above with values from the AH register, +from bits 7, 6, 4, 2, and 0, respectively. + +Flags Affected + +SF, ZF, AF, PF, and CF as described above + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +SAL/SAR/SHL/SHR Shift Instructions + + +Opcode Instruction Clocks Description + +D0 /4 SAL r/m8,1 3/7 Multiply r/m byte by 2, once +D2 /4 SAL r/m8,CL 3/7 Multiply r/m byte by 2, CL times +C0 /4 ib SAL r/m8,imm8 3/7 Multiply r/m byte by 2, imm8 + times +D1 /4 SAL r/m16,1 3/7 Multiply r/m word by 2, once +D3 /4 SAL r/m16,CL 3/7 Multiply r/m word by 2, CL times +C1 /4 ib SAL r/m16,imm8 3/7 Multiply r/m word by 2, imm8 + times +D1 /4 SAL r/m32,1 3/7 Multiply r/m dword by 2, once +D3 /4 SAL r/m32,CL 3/7 Multiply r/m dword by 2, CL + times +C1 /4 ib SAL r/m32,imm8 3/7 Multiply r/m dword by 2, imm8 + times +D0 /7 SAR r/m8,1 3/7 Signed divide^(1) r/m byte by 2, + once +D2 /7 SAR r/m8,CL 3/7 Signed divide^(1) r/m byte by 2, + CL times +C0 /7 ib SAR r/m8,imm8 3/7 Signed divide^(1) r/m byte by 2, + imm8 times +D1 /7 SAR r/m16,1 3/7 Signed divide^(1) r/m word by 2, + once +D3 /7 SAR r/m16,CL 3/7 Signed divide^(1) r/m word by 2, + CL times +C1 /7 ib SAR r/m16,imm8 3/7 Signed divide^(1) r/m word by 2, + imm8 times +D1 /7 SAR r/m32,1 3/7 Signed divide^(1) r/m dword by 2, + once +D3 /7 SAR r/m32,CL 3/7 Signed divide^(1) r/m dword by 2, + CL times +C1 /7 ib SAR r/m32,imm8 3/7 Signed divide^(1) r/m dword by 2, + imm8 times +D0 /4 SHL r/m8,1 3/7 Multiply r/m byte by 2, once +D2 /4 SHL r/m8,CL 3/7 Multiply r/m byte by 2, CL times +C0 /4 ib SHL r/m8,imm8 3/7 Multiply r/m byte by 2, imm8 + times +D1 /4 SHL r/m16,1 3/7 Multiply r/m word by 2, once +D3 /4 SHL r/m16,CL 3/7 Multiply r/m word by 2, CL times +C1 /4 ib SHL r/m16,imm8 3/7 Multiply r/m word by 2, imm8 + times +D1 /4 SHL r/m32,1 3/7 Multiply r/m dword by 2, once +D3 /4 SHL r/m32,CL 3/7 Multiply r/m dword by 2, CL + times +C1 /4 ib SHL r/m32,imm8 3/7 Multiply r/m dword by 2, imm8 + times +D0 /5 SHR r/m8,1 3/7 Unsigned divide r/m byte by 2, + once +D2 /5 SHR r/m8,CL 3/7 Unsigned divide r/m byte by 2, + CL times +C0 /5 ib SHR r/m8,imm8 3/7 Unsigned divide r/m byte by 2, + imm8 times +D1 /5 SHR r/m16,1 3/7 Unsigned divide r/m word by 2, + once +D3 /5 SHR r/m16,CL 3/7 Unsigned divide r/m word by 2, + CL times +C1 /5 ib SHR r/m16,imm8 3/7 Unsigned divide r/m word by 2, + imm8 times +D1 /5 SHR r/m32,1 3/7 Unsigned divide r/m dword by 2, + once +D3 /5 SHR r/m32,CL 3/7 Unsigned divide r/m dword by 2, + CL times +C1 /5 ib SHR r/m32,imm8 3/7 Unsigned divide r/m dword by 2, + imm8 times + + +Not the same division as IDIV; rounding is toward negative infinity. + +Operation + +(* COUNT is the second parameter *) +(temp)  COUNT; +WHILE (temp <> 0) +DO + IF instruction is SAL or SHL + THEN CF  high-order bit of r/m; + FI; + IF instruction is SAR or SHR + THEN CF  low-order bit of r/m; + FI; + IF instruction = SAL or SHL + THEN r/m  r/m * 2; + FI; + IF instruction = SAR + THEN r/m  r/m /2 (*Signed divide, rounding toward negative infinity*); + FI; + IF instruction = SHR + THEN r/m  r/m / 2; (* Unsigned divide *); + FI; + temp  temp - 1; +OD; +(* Determine overflow for the various instructions *) +IF COUNT = 1 +THEN + IF instruction is SAL or SHL + THEN OF  high-order bit of r/m <> (CF); + FI; + IF instruction is SAR + THEN OF  0; + FI; + IF instruction is SHR + THEN OF  high-order bit of operand; + FI; +ELSE OF  undefined; +FI; + +Description + +SAL (or its synonym, SHL) shifts the bits of the operand upward. The +high-order bit is shifted into the carry flag, and the low-order bit is set +to 0. + +SAR and SHR shift the bits of the operand downward. The low-order +bit is shifted into the carry flag. The effect is to divide the operand by +2. SAR performs a signed divide with rounding toward negative infinity (not +the same as IDIV); the high-order bit remains the same. SHR performs an +unsigned divide; the high-order bit is set to 0. + +The shift is repeated the number of times indicated by the second +operand, which is either an immediate number or the contents of the CL +register. To reduce the maximum execution time, the 80386 does not +allow shift counts greater than 31. If a shift count greater than 31 is +attempted, only the bottom five bits of the shift count are used. (The +8086 uses all eight bits of the shift count.) + +The overflow flag is set only if the single-shift forms of the instructions +are used. For left shifts, OF is set to 0 if the high bit of the answer is +the same as the result of the carry flag (i.e., the top two bits of the +original operand were the same); OF is set to 1 if they are different. For +SAR, OF is set to 0 for all single shifts. For SHR, OF is set to the +high-order bit of the original operand. + +Flags Affected + +OF for single shifts; OF is undefined for multiple shifts; CF, ZF, PF, +and SF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SBB Integer Subtraction with Borrow + + +Opcode Instruction Clocks Description + +1C ib SBB AL,imm8 2 Subtract with borrow immediate byte + from AL +1D iw SBB AX,imm16 2 Subtract with borrow immediate word + from AX +1D id SBB EAX,imm32 2 Subtract with borrow immediate + dword from EAX +80 /3 ib SBB r/m8,imm8 2/7 Subtract with borrow immediate byte + from r/m byte +81 /3 iw SBB r/m16,imm16 2/7 Subtract with borrow immediate word + from r/m word +81 /3 id SBB r/m32,imm32 2/7 Subtract with borrow immediate + dword from r/m dword +83 /3 ib SBB r/m16,imm8 2/7 Subtract with borrow sign-extended + immediate byte from r/m word +83 /3 ib SBB r/m32,imm8 2/7 Subtract with borrow sign-extended + immediate byte from r/m dword +18 /r SBB r/m8,r8 2/6 Subtract with borrow byte register + from r/m byte +19 /r SBB r/m16,r16 2/6 Subtract with borrow word register + from r/m word +19 /r SBB r/m32,r32 2/6 Subtract with borrow dword register + from r/m dword +1A /r SBB r8,r/m8 2/7 Subtract with borrow byte register + from r/m byte +1B /r SBB r16,r/m16 2/7 Subtract with borrow word register + from r/m word +1B /r SBB r32,r/m32 2/7 Subtract with borrow dword register + from r/m dword + + +Operation + +IF SRC is a byte and DEST is a word or dword +THEN DEST = DEST - (SignExtend(SRC) + CF) +ELSE DEST  DEST - (SRC + CF); + +Description + +SBB adds the second operand (DEST) to the carry flag (CF) and +subtracts the result from the first operand (SRC). The result of the +subtraction is assigned to the first operand (DEST), and the flags are +set accordingly. + +When an immediate byte value is subtracted from a word operand, the +immediate value is first sign-extended. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SCAS/SCASB/SCASW/SCASD Compare String Data + +Opcode Instruction Clocks Description + +AE SCAS m8 7 Compare bytes AL-ES:[DI], update (E)DI +AF SCAS m16 7 Compare words AX-ES:[DI], update (E)DI +AF SCAS m32 7 Compare dwords EAX-ES:[DI], update (E)DI +AE SCASB 7 Compare bytes AL-ES:[DI], update (E)DI +AF SCASW 7 Compare words AX-ES:[DI], update (E)DI +AF SCASD 7 Compare dwords EAX-ES:[DI], update (E)DI + + +Operation + +IF AddressSize = 16 +THEN use DI for dest-index; +ELSE (* AddressSize = 32 *) use EDI for dest-index; +FI; +IF byte type of instruction +THEN + AL - [dest-index]; (* Compare byte in AL and dest *) + IF DF = 0 THEN IndDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + AX - [dest-index]; (* compare word in AL and dest *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + EAX - [dest-index];(* compare dword in EAX & dest *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +dest-index = dest-index + IncDec + +Description + +SCAS subtracts the memory byte or word at the destination register from +the AL, AX or EAX register. The result is discarded; only the flags are set. +The operand must be addressable from the ES segment; no segment override is +possible. + +If the address-size attribute for this instruction is 16 bits, DI is used +as the destination register; otherwise, the address-size attribute is 32 +bits and EDI is used. + +The address of the memory data being compared is determined solely by the +contents of the destination register, not by the operand to SCAS. The +operand validates ES segment addressability and determines the data type. +Load the correct index value into DI or EDI before executing SCAS. + +After the comparison is made, the destination register is automatically +updated. If the direction flag is 0 (CLD was executed), the destination +register is incremented; if the direction flag is 1 (STD was executed), it +is decremented. The increments or decrements are by 1 if bytes are compared, +by 2 if words are compared, or by 4 if doublewords are compared. + +SCASB, SCASW, and SCASD are synonyms for the byte, word and +doubleword SCAS instructions that don't require operands. They are +simpler to code, but provide no type or segment checking. + +SCAS can be preceded by the REPE or REPNE prefix for a block search +of CX or ECX bytes or words. Refer to the REP instruction for further +details. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SETcc Byte Set on Condition + + +Opcode Instruction Clocks Description + +0F 97 SETA r/m8 4/5 Set byte if above (CF=0 and ZF=0) +0F 93 SETAE r/m8 4/5 Set byte if above or equal (CF=0) +0F 92 SETB r/m8 4/5 Set byte if below (CF=1) +0F 96 SETBE r/m8 4/5 Set byte if below or equal (CF=1 or (ZF=1) +0F 92 SETC r/m8 4/5 Set if carry (CF=1) +0F 94 SETE r/m8 4/5 Set byte if equal (ZF=1) +0F 9F SETG r/m8 4/5 Set byte if greater (ZF=0 or SF=OF) +0F 9D SETGE r/m8 4/5 Set byte if greater or equal (SF=OF) +0F 9C SETL r/m8 4/5 Set byte if less (SF<>OF) +0F 9E SETLE r/m8 4/5 Set byte if less or equal (ZF=1 and + SF<>OF) +0F 96 SETNA r/m8 4/5 Set byte if not above (CF=1) +0F 92 SETNAE r/m8 4/5 Set byte if not above or equal (CF=1) +0F 93 SETNB r/m8 4/5 Set byte if not below (CF=0) +0F 97 SETNBE r/m8 4/5 Set byte if not below or equal (CF=0 and + ZF=0) +0F 93 SETNC r/m8 4/5 Set byte if not carry (CF=0) +0F 95 SETNE r/m8 4/5 Set byte if not equal (ZF=0) +0F 9E SETNG r/m8 4/5 Set byte if not greater (ZF=1 or SF<>OF) +0F 9C SETNGE r/m8 4/5 Set if not greater or equal (SF<>OF) +0F 9D SETNL r/m8 4/5 Set byte if not less (SF=OF) +0F 9F SETNLE r/m8 4/5 Set byte if not less or equal (ZF=1 and + SF<>OF) +0F 91 SETNO r/m8 4/5 Set byte if not overflow (OF=0) +0F 9B SETNP r/m8 4/5 Set byte if not parity (PF=0) +0F 99 SETNS r/m8 4/5 Set byte if not sign (SF=0) +0F 95 SETNZ r/m8 4/5 Set byte if not zero (ZF=0) +0F 90 SETO r/m8 4/5 Set byte if overflow (OF=1) +0F 9A SETP r/m8 4/5 Set byte if parity (PF=1) +0F 9A SETPE r/m8 4/5 Set byte if parity even (PF=1) +0F 9B SETPO r/m8 4/5 Set byte if parity odd (PF=0) +0F 98 SETS r/m8 4/5 Set byte if sign (SF=1) +0F 94 SETZ r/m8 4/5 Set byte if zero (ZF=1) + + +Operation + +IF condition THEN r/m8  1 ELSE r/m8  0; FI; + +Description + +SETcc stores a byte at the destination specified by the effective address +or register if the condition is met, or a 0 byte if the condition is not +met. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a non-writable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SGDT/SIDT Store Global/Interrupt Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 01 /0 SGDT m 9 Store GDTR to m +0F 01 /1 SIDT m 9 Store IDTR to m + + +Operation + +DEST  48-bit BASE/LIMIT register contents; + +Description + +SGDT/SIDT copies the contents of the descriptor table register the six +bytes of memory indicated by the operand. The LIMIT field of the +register is assigned to the first word at the effective address. If the +operand-size attribute is 32 bits, the next three bytes are assigned the +BASE field of the register, and the fourth byte is written with zero. The +last byte is undefined. Otherwise, if the operand-size attribute is 16 +bits, the next four bytes are assigned the 32-bit BASE field of the +register. + +SGDT and SIDT are used only in operating system software; they are +not used in application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +Interrupt 6 if the destination operand is a register; #GP(0) if the +destination is in a nonwritable segment; #GP(0) for an illegal memory +operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for +an illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6 if the destination operand is a register; Interrupt 13 if any +part of the operand would lie outside of the effective address space from +0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + +Compatability Note + +The 16-bit forms of the SGDT/SIDT instructions are compatible with +the 80286, if the value in the upper eight bits is not referenced. The +80286 stores 1's in these upper bits, whereas the 80386 stores 0's if the +operand-size attribute is 16 bits. These bits were specified as undefined +by the SGDT/SIDT instructions in the iAPX 286 Programmer's +Reference Manual. + + +SHLD Double Precision Shift Left + +Opcode Instruction Clocks Description + +0F A4 SHLD r/m16,r16,imm8 3/7 r/m16 gets SHL of r/m16 concatenated + with r16 +0F A4 SHLD r/m32,r32,imm8 3/7 r/m32 gets SHL of r/m32 concatenated + with r32 +0F A5 SHLD r/m16,r16,CL 3/7 r/m16 gets SHL of r/m16 concatenated + with r16 +0F A5 SHLD r/m32,r32,CL 3/7 r/m32 gets SHL of r/m32 concatenated + with r32 + + +Operation + +(* count is an unsigned integer corresponding to the last operand of the +instruction, either an immediate byte or the byte in register CL *) +ShiftAmt  count MOD 32; +inBits  register; (* Allow overlapped operands *) +IF ShiftAmt = 0 +THEN no operation +ELSE + IF ShiftAmt OperandSize + THEN (* Bad parameters *) + r/m  UNDEFINED; + CF, OF, SF, ZF, AF, PF  UNDEFINED; + ELSE (* Perform the shift *) + CF  BIT[Base, OperandSize - ShiftAmt]; + (* Last bit shifted out on exit *) + FOR i  OperandSize - 1 DOWNTO ShiftAmt + DO + BIT[Base, i]  BIT[Base, i - ShiftAmt]; + OF; + FOR i  ShiftAmt - 1 DOWNTO 0 + DO + BIT[Base, i]  BIT[inBits, i - ShiftAmt + OperandSize]; + OD; + Set SF, ZF, PF (r/m); + (* SF, ZF, PF are set according to the value of the result *) + AF  UNDEFINED; + FI; +FI; + +Description + +SHLD shifts the first operand provided by the r/m field to the left as +many bits as specified by the count operand. The second operand (r16 or r32) +provides the bits to shift in from the right (starting with bit 0). The +result is stored back into the r/m operand. The register remains unaltered. + +The count operand is provided by either an immediate byte or the contents +of the CL register. These operands are taken MODULO 32 to provide a number +between 0 and 31 by which to shift. Because the bits to shift are provided +by the specified registers, the operation is useful for multiprecision +shifts (64 bits or more). The SF, ZF and PF flags are set according to the +value of the result. CS is set to the value of the last bit shifted out. OF +and AF are left undefined. + +Flags Affected + +OF, SF, ZF, PF, and CF as described above; AF and OF are undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +SHRD Double Precision Shift Right + +Opcode Instruction Clocks Description + +0F AC SHRD r/m16,r16,imm8 3/7 r/m16 gets SHR of r/m16 concatenated + with r16 +0F AC SHRD r/m32,r32,imm8 3/7 r/m32 gets SHR of r/m32 concatenated + with r32 +0F AD SHRD r/m16,r16,CL 3/7 r/m16 gets SHR of r/m16 concatenated + with r16 +0F AD SHRD r/m32,r32,CL 3/7 r/m32 gets SHR of r/m32 concatenated + with r32 + + +Operation + +(* count is an unsigned integer corresponding to the last operand of the +instruction, either an immediate byte or the byte in register CL *) +ShiftAmt  count MOD 32; +inBits  register; (* Allow overlapped operands *) +IF ShiftAmt = 0 +THEN no operation +ELSE + IF ShiftAmt OperandSize + THEN (* Bad parameters *) + r/m  UNDEFINED; + CF, OF, SF, ZF, AF, PF  UNDEFINED; + ELSE (* Perform the shift *) + CF  BIT[r/m, ShiftAmt - 1]; (* last bit shifted out on exit *) + FOR i  0 TO OperandSize - 1 - ShiftAmt + DO + BIT[r/m, i]  BIT[r/m, i - ShiftAmt]; + OD; + FOR i  OperandSize - ShiftAmt TO OperandSize - 1 + DO + BIT[r/m,i]  BIT[inBits,i+ShiftAmt - OperandSize]; + OD; + Set SF, ZF, PF (r/m); + (* SF, ZF, PF are set according to the value of the result *) + Set SF, ZF, PF (r/m); + AF  UNDEFINED; + FI; +FI; + +Description + +SHRD shifts the first operand provided by the r/m field to the right as many +bits as specified by the count operand. The second operand (r16 or r32) +provides the bits to shift in from the left (starting with bit 31). The +result is stored back into the r/m operand. The register remains unaltered. + +The count operand is provided by either an immediate byte or the contents +of the CL register. These operands are taken MODULO 32 to provide a number +between 0 and 31 by which to shift. Because the bits to shift are provided +by the specified register, the operation is useful for multi-precision +shifts (64 bits or more). The SF, ZF and PF flags are set according to the +value of the result. CS is set to the value of the last bit shifted out. OF +and AF are left undefined. + +Flags Affected + +OF, SF, ZF, PF, and CF as described above; AF and OF are undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SLDT Store Local Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 00 /0 SLDT r/m16 pm=2/2 Store LDTR to EA word + + +Operation + +r/m16  LDTR; + +Description + +SLDT stores the Local Descriptor Table Register (LDTR) in the two-byte +register or memory location indicated by the effective address operand. +This register is a selector that points into the Global Descriptor Table. + +SLDT is used only in operating system software. It is not used in +application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 6; SLDT is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The operand-size attribute has no effect on the operation of the +instruction. + + +SMSW Store Machine Status Word + +Opcode Instruction Clocks Description + +0F 01 /4 SMSW r/m16 2/3,pm=2/2 Store machine status word to EA + word + + +Operation + +r/m16  MSW; + +Description + +SMSW stores the machine status word (part of CR0) in the two-byte register +or memory location indicated by the effective address operand. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +This instruction is provided for compatibility with the 80286; 80386 +programs should use MOV ..., CR0. + + +STC Set Carry Flag + +Opcode Instruction Clocks Description + +F9 STC 2 Set carry flag + + +Operation + +CF  1; + +Description + +STC sets the carry flag to 1. + +Flags Affected + +CF = 1 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +STD Set Direction Flag + +Opcode Instruction Clocks Description + +FD STD 2 Set direction flag so (E)SI and/or (E)DI + decrement + + +Operation + +DF  1; + +Description + +STD sets the direction flag to 1, causing all subsequent string operations +to decrement the index registers, (E)SI and/or (E)DI, on which they +operate. + +Flags Affected + +DF = 1 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +STI Set Interrupt Flag + +Opcode Instruction Clocks Description + +F13 STI 3 Set interrupt flag; interrupts enabled at the + end of the next instruction + + +Operation + +IF  1 + +Description + +STI sets the interrupt flag to 1. The 80386 then responds to external +interrupts after executing the next instruction if the next instruction +allows the interrupt flag to remain enabled. If external interrupts are +disabled and you code STI, RET (such as at the end of a subroutine), +the RET is allowed to execute before external interrupts are recognized. +Also, if external interrupts are disabled and you code STI, CLI, then +external interrupts are not recognized because the CLI instruction clears +the interrupt flag during its execution. + +Flags Affected + +IF = 1 + +Protected Mode Exceptions + +#GP(0) if the current privilege level is greater (has less privilege) than +the I/O privilege level + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +STOS/STOSB/STOSW/STOSD Store String Data + +Opcode Instruction Clocks Description + +AA STOS m8 4 Store AL in byte ES:[(E)DI], update (E)DI +AB STOS m16 4 Store AX in word ES:[(E)DI], update (E)DI +AB STOS m32 4 Store EAX in dword ES:[(E)DI], update (E)DI +AA STOSB 4 Store AL in byte ES:[(E)DI], update (E)DI +AB STOSW 4 Store AX in word ES:[(E)DI], update (E)DI +AB STOSD 4 Store EAX in dword ES:[(E)DI], update (E)DI + + +Operation + +IF AddressSize = 16 +THEN use ES:DI for DestReg +ELSE (* AddressSize = 32 *) use ES:EDI for DestReg; +FI; +IF byte type of instruction +THEN + (ES:DestReg)  AL; + IF DF = 0 + THEN DestReg  DestReg + 1; + ELSE DestReg  DestReg - 1; + FI; +ELSE IF OperandSize = 16 + THEN + (ES:DestReg)  AX; + IF DF = 0 + THEN DestReg  DestReg + 2; + ELSE DestReg  DestReg - 2; + FI; + ELSE (* OperandSize = 32 *) + (ES:DestReg)  EAX; + IF DF = 0 + THEN DestReg  DestReg + 4; + ELSE DestReg  DestReg - 4; + FI; + FI; +FI; + +Description + +STOS transfers the contents of all AL, AX, or EAX register to the memory +byte or word given by the destination register relative to the ES segment. +The destination register is DI for an address-size attribute of 16 bits or +EDI for an address-size attribute of 32 bits. + +The destination operand must be addressable from the ES register. A segment +override is not possible. + +The address of the destination is determined by the contents of the +destination register, not by the explicit operand of STOS. This operand is +used only to validate ES segment addressability and to determine the data +type. Load the correct index value into the destination register before +executing STOS. + +After the transfer is made, DI is automatically updated. If the direction +flag is 0 (CLD was executed), DI is incremented; if the direction flag is +1 (STD was executed), DI is decremented. DI is incremented or decremented by +1 if a byte is stored, by 2 if a word is stored, or by 4 if a doubleword is +stored. + +STOSB, STOSW, and STOSD are synonyms for the byte, word, and doubleword STOS +instructions, that do not require an operand. They are simpler to use, but +provide no type or segment checking. + +STOS can be preceded by the REP prefix for a block fill of CX or ECX bytes, +words, or doublewords. Refer to the REP instruction for further details. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +STR Store Task Register + +Opcode Instruction Clocks Description + +0F 00 /1 STR r/m16 pm=23/27 Load EA word into task register + + +Operation + +r/m  task register; + +Description + +The contents of the task register are copied to the two-byte register or +memory location indicated by the effective address operand. + +STR is used only in operating system software. It is not used in application +programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 6; STR is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + +Notes + +The operand-size attribute has no effect on this instruction. + + +SUB Integer Subtraction + +Opcode Instruction Clocks Description + +2C ib SUB AL,imm8 2 Subtract immediate byte from AL +2D iw SUB AX,imm16 2 Subtract immediate word from AX +2D id SUB EAX,imm32 2 Subtract immediate dword from EAX +80 /5 ib SUB r/m8,imm8 2/7 Subtract immediate byte from r/m byte +81 /5 iw SUB r/m16,imm16 2/7 Subtract immediate word from r/m word +81 /5 id SUB r/m32,imm32 2/7 Subtract immediate dword from r/m + dword +83 /5 ib SUB r/m16,imm8 2/7 Subtract sign-extended immediate byte + from r/m word +83 /5 ib SUB r/m32,imm8 2/7 Subtract sign-extended immediate byte + from r/m dword +28 /r SUB r/m8,r8 2/6 Subtract byte register from r/m byte +29 /r SUB r/m16,r16 2/6 Subtract word register from r/m word +29 /r SUB r/m32,r32 2/6 Subtract dword register from r/m + dword +2A /r SUB r8,r/m8 2/7 Subtract byte register from r/m byte +2B /r SUB r16,r/m16 2/7 Subtract word register from r/m word +2B /r SUB r32,r/m32 2/7 Subtract dword register from r/m + dword + + +Operation + +IF SRC is a byte and DEST is a word or dword +THEN DEST = DEST - SignExtend(SRC); +ELSE DEST  DEST - SRC; +FI; + +Description + +SUB subtracts the second operand (SRC) from the first operand (DEST). The +first operand is assigned the result of the subtraction, and the flags are +set accordingly. + +When an immediate byte value is subtracted from a word operand, the +immediate value is first sign-extended to the size of the destination +operand. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +TEST Logical Compare + +Opcode Instruction Clocks Description + +A8 ib TEST AL,imm8 2 AND immediate byte with AL +A9 iw TEST AX,imm16 2 AND immediate word with AX +A9 id TEST EAX,imm32 2 AND immediate dword with EAX +F6 /0 ib TEST r/m8,imm8 2/5 AND immediate byte with r/m byte +F7 /0 iw TEST r/m16,imm16 2/5 AND immediate word with r/m word +F7 /0 id TEST r/m32,imm32 2/5 AND immediate dword with r/m dword +84 /r TEST r/m8,r8 2/5 AND byte register with r/m byte +85 /r TEST r/m16,r16 2/5 AND word register with r/m word +85 /r TEST r/m32,r32 2/5 AND dword register with r/m dword + + +Operation + +DEST : = LeftSRC AND RightSRC; +CF  0; +OF  0; + +Description + +TEST computes the bit-wise logical AND of its two operands. Each bit +of the result is 1 if both of the corresponding bits of the operands are 1; +otherwise, each bit is 0. The result of the operation is discarded and only +the flags are modified. + +Flags Affected + +OF = 0, CF = 0; SF, ZF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +VERR, VERW Verify a Segment for Reading or Writing + +Opcode Instruction Clocks Description + +0F 00 /4 VERR r/m16 pm=10/11 Set ZF=1 if segment can be read, + selector in r/m16 +0F 00 /5 VERW r/m16 pm=15/16 Set ZF=1 if segment can be written, + selector in r/m16 + + +Operation + +IF segment with selector at (r/m) is accessible + with current protection level + AND ((segment is readable for VERR) OR + (segment is writable for VERW)) +THEN ZF  0; +ELSE ZF  1; +FI; + +Description + +The two-byte register or memory operand of VERR and VERW contains +the value of a selector. VERR and VERW determine whether the +segment denoted by the selector is reachable from the current privilege +level and whether the segment is readable (VERR) or writable (VERW). +If the segment is accessible, the zero flag is set to 1; if the segment is +not accessible, the zero flag is set to 0. To set ZF, the following +conditions must be met: + + The selector must denote a descriptor within the bounds of the table + (GDT or LDT); the selector must be "defined." + + The selector must denote the descriptor of a code or data segment + (not that of a task state segment, LDT, or a gate). + + For VERR, the segment must be readable. For VERW, the segment + must be a writable data segment. + + If the code segment is readable and conforming, the descriptor + privilege level (DPL) can be any value for VERR. Otherwise, the + DPL must be greater than or equal to (have less or the same + privilege as) both the current privilege level and the selector's RPL. + +The validation performed is the same as if the segment were loaded into +DS, ES, FS, or GS, and the indicated access (read or write) were +performed. The zero flag receives the result of the validation. The +selector's value cannot result in a protection exception, enabling the +software to anticipate possible segment access problems. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +Faults generated by illegal addressing of the memory operand that +contains the selector, the selector is not loaded into any segment +register, and no faults attributable to the selector operand are generated + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; VERR and VERW are not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +WAIT Wait until BUSY# Pin is Inactive (HIGH) + +Opcode Instruction Clocks Description + +9B WAIT 6 min. Wait until BUSY pin is inactive (HIGH) + + +Description + +WAIT suspends execution of 80386 instructions until the BUSY# pin is +inactive (high). The BUSY# pin is driven by the 80287 numeric processor +extension. + +Flags Affected + +None + +Protected Mode Exceptions + +#NM if the task-switched flag in the machine status word (the lower 16 bits +of register CR0) is set; #MF if the ERROR# input pin is asserted (i.e., the +80287 has detected an unmasked numeric error) + +Real Address Mode Exceptions + +Same exceptions as in Protected Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Protected Mode + + +XCHG Exchange Register/Memory with Register + +Opcode Instruction Clocks Description + +90 + r XCHG AX,r16 3 Exchange word register with AX +90 + r XCHG r16,AX 3 Exchange word register with AX +90 + r XCHG EAX,r32 3 Exchange dword register with EAX +90 + r XCHG r32,EAX 3 Exchange dword register with EAX +86 /r XCHG r/m8,r8 3 Exchange byte register with EA byte +86 /r XCHG r8,r/m8 3/5 Exchange byte register with EA byte +87 /r XCHG r/m16,r16 3 Exchange word register with EA word +87 /r XCHG r16,r/m16 3/5 Exchange word register with EA word +87 /r XCHG r/m32,r32 3 Exchange dword register with EA dword +87 /r XCHG r32,r/m32 3/5 Exchange dword register with EA dword + + +Operation + +temp  DEST +DEST  SRC +SRC  temp + +Description + +XCHG exchanges two operands. The operands can be in either order. If a +memory operand is involved, BUS LOCK is asserted for the duration of the +exchange, regardless of the presence or absence of the LOCK prefix or of the +value of the IOPL. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if either operand is in a nonwritable segment; #GP(0) for an +illegal memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +XLAT/XLATB Table Look-up Translation + +D7 XLAT m8 5 Set AL to memory byte DS:[(E)BX + unsigned AL] +D7 XLATB 5 Set AL to memory byte DS:[(E)BX + unsigned AL] + + +Operation + +IF AddressSize = 16 +THEN + AL  (BX + ZeroExtend(AL)) +ELSE (* AddressSize = 32 *) + AL  (EBX + ZeroExtend(AL)); +FI; + +Description + +XLAT changes the AL register from the table index to the table entry. AL +should be the unsigned index into a table addressed by DS:BX (for an +address-size attribute of 16 bits) or DS:EBX (for an address-size attribute +of 32 bits). + +The operand to XLAT allows for the possibility of a segment override. XLAT +uses the contents of BX even if they differ from the offset of the operand. +The offset of the operand should have been moved intoBX/EBX with a previous +instruction. + +The no-operand form, XLATB, can be used if the BX/EBX table will always +reside in the DS segment. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +XOR Logical Exclusive OR + + +Opcode Instruction Clocks Description + +34 ib XOR AL,imm8 2 Exclusive-OR immediate byte to AL +35 iw XOR AX,imm16 2 Exclusive-OR immediate word to AX +35 id XOR EAX,imm32 2 Exclusive-OR immediate dword to EAX +80 /6 ib XOR r/m8,imm8 2/7 Exclusive-OR immediate byte to r/m + byte +81 /6 iw XOR r/m16,imm16 2/7 Exclusive-OR immediate word to r/m + word +81 /6 id XOR r/m32,imm32 2/7 Exclusive-OR immediate dword to r/m + dword +83 /6 ib XOR r/m16,imm8 2/7 XOR sign-extended immediate byte + with r/m word +83 /6 ib XOR r/m32,imm8 2/7 XOR sign-extended immediate byte + with r/m dword +30 /r XOR r/m8,r8 2/6 Exclusive-OR byte register to r/m + byte +31 /r XOR r/m16,r16 2/6 Exclusive-OR word register to r/m + word +31 /r XOR r/m32,r32 2/6 Exclusive-OR dword register to r/m + dword +32 /r XOR r8,r/m8 2/7 Exclusive-OR byte register to r/m + byte +33 /r XOR r16,r/m16 2/7 Exclusive-OR word register to r/m + word +33 /r XOR r32,r/m32 2/7 Exclusive-OR dword register to r/m + dword + + +Operation + +DEST  LeftSRC XOR RightSRC +CF  0 +OF  0 + +Description + +XOR computes the exclusive OR of the two operands. Each bit of the result +is 1 if the corresponding bits of the operands are different; each bit is 0 +if the corresponding bits are the same. The answer replaces the first +operand. + +Flags Affected + +CF = 0, OF = 0; SF, ZF, and PF as described in Appendix C; AF is undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +Appendix A Opcode Map + + + +The opcode tables that follow aid in interpreting 80386 object code. Use +the high-order four bits of the opcode as an index to a row of the opcode +table; use the low-order four bits as an index to a column of the table. If +the opcode is 0FH, refer to the two-byte opcode table and use the second +byte of the opcode to index the rows and columns of that table. + + +Key to Abbreviations + +Operands are identified by a two-character code of the form Zz. The first +character, an uppercase letter, specifies the addressing method; the second +character, a lowercase letter, specifies the type of operand. + + +Codes for Addressing Method + +A Direct address; the instruction has no modR/M byte; the address of the + operand is encoded in the instruction; no base register, index register, + or scaling factor can be applied; e.g., far JMP (EA). + +C The reg field of the modR/M byte selects a control register; e.g., MOV + (0F20, 0F22). + +D The reg field of the modR/M byte selects a debug register; e.g., MOV + (0F21,0F23). + +E A modR/M byte follows the opcode and specifies the operand. The operand + is either a general register or a memory address. If it is a memory + address, the address is computed from a segment register and any of the + following values: a base register, an index register, a scaling factor, + a displacement. + +F Flags Register. + +G The reg field of the modR/M byte selects a general register; e.g., ADD + (00). + +I Immediate data. The value of the operand is encoded in subsequent bytes + of the instruction. + +J The instruction contains a relative offset to be added to the + instruction pointer register; e.g., JMP short, LOOP. + +M The modR/M byte may refer only to memory; e.g., BOUND, LES, LDS, LSS, + LFS, LGS. + +O The instruction has no modR/M byte; the offset of the operand is coded as + a word or double word (depending on address size attribute) in the + instruction. No base register, index register, or scaling factor can be + applied; e.g., MOV (A0-A3). + +R The mod field of the modR/M byte may refer only to a general register; + e.g., MOV (0F20-0F24, 0F26). + +S The reg field of the modR/M byte selects a segment register; e.g., MOV + (8C,8E). + +T The reg field of the modR/M byte selects a test register; e.g., MOV + (0F24,0F26). + +X Memory addressed by DS:SI; e.g., MOVS, COMPS, OUTS, LODS, SCAS. + +Y Memory addressed by ES:DI; e.g., MOVS, CMPS, INS, STOS. + + +Codes for Operant Type + +a Two one-word operands in memory or two double-word operands in memory, + depending on operand size attribute (used only by BOUND). + +b Byte (regardless of operand size attribute) + +c Byte or word, depending on operand size attribute. + +d Double word (regardless of operand size attribute) + +p 32-bit or 48-bit pointer, depending on operand size attribute. + +s Six-byte pseudo-descriptor + +v Word or double word, depending on operand size attribute. + +w Word (regardless of operand size attribute) + + +Register Codes + +When an operand is a specific register encoded in the opcode, the register +is identified by its name; e.g., AX, CL, or ESI. The name of the register +indicates whether the register is 32-, 16-, or 8-bits wide. A register +identifier of the form eXX is used when the width of the register depends on +the operand size attribute; for example, eAX indicates that the AX register +is used when the operand size attribute is 16 and the EAX register is used +when the operand size attribute is 32. + + +One-Byte Opcode Map + + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + ͻ + ADD PUSH POP OR PUSH 2-byte +0Ĵ Ĵ + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv ES ES Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv CS escape + ͹ + ADC PUSH POP SBB PUSH POP +1Ĵ Ĵ + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv SS SS Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv DS DS + ͹ + AND SEG SUB SEG +2Ĵ DAA Ĵ DAS + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =ES Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =CS + ͹ + XOR SEG CMP SEG +3Ĵ AAA Ĵ AAS + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =SS Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =CS + ͹ + INC general register DEC general register +4Ķ + eAX eCX eDX eBX eSP eBP eSI eDI eAX eCX eDX eBX eSP eBP eSI eDI + ͹ + PUSH general register POP into general register +5Ķ + eAX eCX eDX eBX eSP eBP eSI eDI eAX eCX eDX eBX eSP eBP eSI eDI + ͹ + BOUND ARPL SEG SEG Operand Address PUSH IMUL PUSH IMUL INSB INSW/D OUTSB OUTSW/D +6 PUSHA POPA + Gv,Ma Ew,Rw =FS =GS Size Size Ib GvEvIv Ib GvEvIv Yb,DX Yb,DX Dx,Xb DX,Xv + ͹ + Short displacement jump of condition (Jb) Short-displacement jump on condition(Jb) +7Ķ + JO JNO JB JNB JZ JNZ JBE JNBE JS JNS JP JNP JL JNL JLE JNLE + ͹ + Immediate Grpl Grpl TEST XCNG MOV MOV LEA MOV POP +8Ĵ Ĵ + Eb,Ib Ev,Iv Ev,Iv Eb,Gb Ev,Gv Eb,Gb Ev,Gv Eb,Gb Ev,Gv Gb,Eb Gv,Ev Ew,Sw Gv,M Sw,Ew Ev + ͹ + XCHG word or double-word register with eAX CALL PUSHF POPF +9 NOP Ĵ CBW CWD WAIT SAHF LAHF + eCX eDX eBX eSP eBP eSI eDI Ap Fv Fv + ͹ + MOV MOVSB MOVSW/D CMPSB CMPSW/D TEST STOSB STOSW/D LODSB LODSW/D SCASB SCASW/D +AĴ Ĵ + AL,Ob eAX,Ov Ob,AL Ov,eAX Xb,Yb Xv,Yv Xb,Yb Xv,Yv AL,Ib eAX,Iv Yb,AL Yv,eAX AL,Xb eAX,Xv AL,Xb eAX,Xv + ͹ + MOV immediate byte into byte register MOV immediate word or double into word or double register +BĶ + AL CL DL BL AH CH DH BH eAX eCX eDX eBX eSP eBP eSI eDI + ͹ + Shift Grp2 RET near LES LDS MOV ENTER RET far INT INT +CĴ Ĵ LEAVE Ĵ INTO IRET + Eb,Ib Ev,Iv Iw Gv,Mp Gv,Mp Eb,Ib Ev,Iv Iw,Ib Iw 3 Ib + ͹ + Shift Grp2 +DĴ AAM AAD XLAT ESC(Escape to coprocessor instruction set) + Eb,1 Ev,1 Eb,CL Ev,CL + ͹ + LOOPNE LOOPE LOOP JCXZ IN OUT CALL JNP IN OUT +E Ĵ Ķ + Jb Jb Jb Jb AL,Ib eAX,Ib Ib,AL Ib,eAX Av Jv Ap Jb AL,DX eAX,DX DX,AL DX,eAX + ͹ + REP Unary Grp3 INC/DEC Indirct +F LOCK REPNE HLT CMC Ĵ CLC STC CLI STI CLD STD + REPE Eb Ev Grp4 Grp5 + ͼ + + +Two-Byte Opcode Map (first byte is 0FH) + + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + ͻ + LAR LSL +0 Grp6 Grp7 CLTS + Gw,Ew Gv,Ew + ͹ + +1 + + ͹ + MOV MOV MOV MOV MOV MOV +2 + Cd,Rd Dd,Rd Rd,Cd Rd,Dd Td,Rd Rd,Td + ͹ + +3 + + ͹ + +4 + + ͹ + +5 + + ͹ + +6 + + ͹ + +7 + + ͹ + Long-displacement jump on condition (Jv) Long-displacement jump on condition (Jv) +8Ķ + JO JNO JB JNB JZ JNZ JBE JNBE JS JNS JP JNP JL JNL JLE JNLE + ͹ + Byte Set on condition (Eb) +9Ĵ SETS SETNS SETP SETNP SETL SETNL SETLE SETNLE + SETO SETNO SETB SETNB SETZ SETNZ SETBE SETNBE + ͹ + PUSH POP BT SHLD SHLD PUSH POP BTS SHRD SHRD IMUL +A + FS FS Ev,Gv EvGvIb EvGvCL GS GS Ev,Gv EvGvIb EvGvCL Gv,Ev + ͹ + LSS BTR LFS LGS MOVZX Grp-8 BTC BSF BSR MOVSX +B Ĵ Ķ + Mp Ev,Gv Mp Mp Gv,Eb Gv,Ew Ev,Ib Ev,Gv Gv,Ev Gv,Ev Gv,Eb Gv,Ew + ͹ + +C + + ͹ + +D + + ͹ + +E + + ͹ + +F + + ͼ + + +Opcodes determined by bits 5,4,3 of modR/M byte: + + G Ŀ + r mod nnn R/M + o + u + p 000 001 010 011 100 101 110 111 + Ŀ + 1 ADD OR ADC SBB AND SUB XOR CMP + + Ĵ + 2 ROL ROR RCL RCR SHL SHR SAR + + Ĵ + 3 TEST NOT NEG MUL IMUL DIV IDIV + Ib/Iv AL/eAX AL/eAX AL/eAX AL/eAX + Ĵ + 4 INC DEC + Eb Eb + Ĵ + 5 INC DEC CALL CALL JMP JMP PUSH + Ev Ev Ev eP Ev Ep Ev + + + +Opcodes determined by bits 5,4,3 of modR/M byte: + + G Ŀ + r mod nnn R/M + o + u + p 000 001 010 011 100 101 110 111 + Ŀ + 6 SLDT STR LLDT LTR VERR VERW + Ew Ew Ew Ew Ew Ew + Ĵ + 7 SGDT SIDT LGDT LIDT SMSW LMSW + Ms Ms Ms Ms Ew Ew + Ĵ + 8 BT BTS BTR BTC + + + + +Appendix B Complete Flag Cross-Reference + + + +Key to Codes + +T = instruction tests flag + +M = instruction modifies flag + (either sets or resets depending on operands) + +0 = instruction resets flag + +1 = instruction sets flag + + = instruction's effect on flag is undefined + +R = instruction restores prior value of flag + +blank = instruction does not affect flag + + +Instruction OF SF ZF AF PF CF TF IF DF NT RF + +AAA TM M +AAD M M M +AAM M M M +AAS TM M +ADC M M M M M TM +ADD M M M M M M +AND 0 M M M 0 +ARPL M +BOUND +BSF/BSR M +BT/BTS/BTR/BTC M +CALL +CBW +CLC 0 +CLD 0 +CLI 0 +CLTS +CMC M +CMP M M M M M M +CMPS M M M M M M T +CWD +DAA M M TM M TM +DAS M M TM M TM +DEC M M M M M +DIV +ENTER +ESC +HLT +IDIV +IMUL M M +IN +INC M M M M M +INS T +INT 0 0 +INTO T 0 0 +IRET R R R R R R R R R T +Jcond T T T T T +JCXZ +JMP +LAHF +LAR M +LDS/LES/LSS/LFS/LGS +LEA +LEAVE +LGDT/LIDT/LLDT/LMSW +LOCK +LODS T +LOOP +LOOPE/LOOPNE T +LSL M +LTR +MOV +MOV control, debug +MOVS T +MOVSX/MOVZX +MUL M M +NEG M M M M M M +NOP +NOT +OR 0 M M M 0 +OUT +OUTS T +POP/POPA +POPF R R R R R R R R R R +PUSH/PUSHA/PUSHF +RCL/RCR 1 M TM +RCL/RCR count TM +REP/REPE/REPNE +RET +ROL/ROR 1 M M +ROL/ROR count M +SAHF R R R R R +SAL/SAR/SHL/SHR 1 M M M M M +SAL/SAR/SHL/SHR count M M M M +SBB M M M M M TM +SCAS M M M M M M T +SET cond T T T T T +SGDT/SIDT/SLDT/SMSW +SHLD/SHRD M M M M +STC 1 +STD 1 +STI 1 +STOS T +STR +SUB M M M M M M +TEST 0 M M M 0 +VERR/VERRW M +WAIT +XCHG +XLAT +XOR 0 M M M 0 + + +Appendix C Status Flag Summary + + + +Status Flags' Functions + +Bit Name Function + + 0 CF Carry Flag Set on high-order bit carry or borrow; cleared + otherwise. + 2 PF Parity Flag Set if low-order eight bits of result contain + an even number of 1 bits; cleared otherwise. + 4 AF Adjust flag Set on carry from or borrow to the low order + four bits of AL; cleared otherwise. Used for decimal + arithmetic. + 6 ZF Zero Flag Set if result is zero; cleared otherwise. + 7 SF Sign Flag Set equal to high-order bit of result (0 is + positive, 1 if negative). +11 OF Overflow Flag Set if result is too large a positive number + or too small a negative number (excluding sign-bit) to fit in + destination operand; cleared otherwise. + +Key to Codes + +T = instruction tests flag +M = instruction modifies flag + (either sets or resets depending on operands) +0 = instruction resets flag + = instruction's effect on flag is undefined +blank = instruction does not affect flag + + + +Instruction OF SF ZF AF PF CF +AAA TM M +AAS TM M +AAD M M M +AAM M M M +DAA M M TM M TM +DAS M M TM M TM +ADC M M M M M TM +ADD M M M M M M +SBB M M M M M TM +SUB M M M M M M +CMP M M M M M M +CMPS M M M M M M +SCAS M M M M M M +NEG M M M M M M +DEC M M M M M +INC M M M M M +IMUL M M +MUL M M +RCL/RCR 1 M TM +RCL/RCR count TM +ROL/ROR 1 M M +ROL/ROR count M +SAL/SAR/SHL/SHR 1 M M M M M +SAL/SAR/SHL/SHR count M M M M +SHLD/SHRD M M M M +BSF/BSR M +BT/BTS/BTR/BTC M +AND 0 M M M 0 +OR 0 M M M 0 +TEST 0 M M M 0 +XOR 0 M M M 0 + + +Appendix D Condition Codes + + + + +Note: + The terms "above" and "below" refer to the relation between two + unsigned values (neither SF nor OF is tested). The terms "greater" and + "less" refer to the relation between two signed values (SF and OF are + tested). + + +Definition of Conditions + +(For conditional instructions Jcond, and SETcond) + + + Instruction Condition +Mnemonic Meaning Subcode Tested + +O Overflow 0000 OF = 1 + +NO No overflow 0001 OF = 0 + +B Below +NAE Neither above nor equal 0010 CF = 1 + +NB Not below +AE Above or equal 0011 CF = 0 + +E Equal +Z Zero 0100 ZF = 1 + +NE Not equal +NZ Not zero 0101 ZF = 0 + +BE Below or equal +NA Not above 0110 (CF or ZF) = 1 + +NBE Neither below nor equal +NA Above 0111 (CF or ZF) = 0 + +S Sign 1000 SF = 1 + +NS No sign 1001 SF = 0 + +P Parity +PE Parity even 1010 PF = 1 + +NP No parity +PO Parity odd 1011 PF = 0 + +L Less +NGE Neither greater nor equal 1100 (SF xor OF) = 1 + +NL Not less +GE Greater or equal 1101 (SF xor OF) = 0 + +LE Less or equal +NG Not greater 1110 ((SF xor OF) or ZF) = 1 + +NLE Neither less nor equal +G Greater 1111 ((SF xor OF) or ZF) = 0 diff --git a/bench/data/sliceslice/i386.txt b/bench/data/sliceslice/i386.txt new file mode 100644 index 0000000..b4c9785 --- /dev/null +++ b/bench/data/sliceslice/i386.txt @@ -0,0 +1,20854 @@ +INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986 + +Intel Corporation makes no warranty for the use of its products and +assumes no responsibility for any errors which may appear in this document +nor does it make a commitment to update the information contained herein. + +Intel retains the right to make changes to these specifications at any +time, without notice. + +Contact your local sales office to obtain the latest specifications before +placing your order. + +The following are trademarks of Intel Corporation and may only be used to +identify Intel Products: + +Above, BITBUS, COMMputer, CREDIT, Data Pipeline, FASTPATH, Genius, i, , +ICE, iCEL, iCS, iDBP, iDIS, IICE, iLBX, im, iMDDX, iMMX, Inboard, +Insite, Intel, intel, intelBOS, Intel Certified, Intelevision, +inteligent Identifier, inteligent Programming, Intellec, Intellink, +iOSP, iPDS, iPSC, iRMK, iRMX, iSBC, iSBX, iSDM, iSXM, KEPROM, Library +Manager, MAPNET, MCS, Megachassis, MICROMAINFRAME, MULTIBUS, MULTICHANNEL, +MULTIMODULE, MultiSERVER, ONCE, OpenNET, OTP, PC BUBBLE, Plug-A-Bubble, +PROMPT, Promware, QUEST, QueX, Quick-Pulse Programming, Ripplemode, RMX/80, +RUPI, Seamless, SLD, SugarCube, SupportNET, UPI, and VLSiCEL, and the +combination of ICE, iCS, iRMX, iSBC, iSBX, iSXM, MCS, or UPI and a numerical +suffix, 4-SITE. + +MDS is an ordering code only and is not used as a product name or +trademark. MDS(R) is a registered trademark of Mohawk Data Sciences +Corporation. + +Additional copies of this manual or other Intel literature may be obtained +from: + +Intel Corporation +Literature Distribution +Mail Stop SC6-59 +3065 Bowers Avenue +Santa Clara, CA 95051 + +(c)INTEL CORPORATION 1987 CG-5/26/87 + + +Customer Support + + + +Customer Support is Intel's complete support service that provides Intel +customers with hardware support, software support, customer training, and +consulting services. For more information contact your local sales offices. + +After a customer purchases any system hardware or software product, +service and support become major factors in determining whether that +product will continue to meet a customer's expectations. Such support +requires an international support organization and a breadth of programs +to meet a variety of customer needs. As you might expect, Intel's customer +support is quite extensive. It includes factory repair services and +worldwide field service offices providing hardware repair services, +software support services, customer training classes, and consulting +services. + +Hardware Support Services + +Intel is committed to providing an international service support package +through a wide variety of service offerings available from Intel Hardware +Support. + +Software Support Services + +Intel's software support consists of two levels of contracts. Standard +support includes TIPS (Technical Information Phone Service), updates and +subscription service (product-specific troubleshooting guides and COMMENTS +Magazine). Basic support includes updates and the subscription service. +Contracts are sold in environments which represent product groupings +(i.e., iRMX environment). + +Consulting Services + +Intel provides field systems engineering services for any phase of your +development or support effort. You can use our systems engineers in a +variety of ways ranging from assistance in using a new product, developing +an application, personalizing training, and customizing or tailoring an +Intel product to providing technical and management consulting. Systems +Engineers are well versed in technical areas such as microcommunications, +real-time applications, embedded microcontrollers, and network services. +You know your application needs; we know our products. Working together we +can help you get a successful product to market in the least possible time. + +Customer Training + +Intel offers a wide range of instructional programs covering various +aspects of system design and implementation. In just three to ten days a +limited number of individuals learn more in a single workshop than in +weeks of self-study. For optimum convenience, workshops are scheduled +regularly at Training Centers woridwide or we can take our workshops to +you for on-site instruction. Covering a wide variety of topics, Intel's +major course categories include: architecture and assembly language, +programming and operating systems, bitbus and LAN applications. + +Training Center Locations + +To obtain a complete catalog of our workshops, call the nearest Training +Center in your area. + +Boston (617) 692-1000 +Chicago (312) 310-5700 +San Francisco (415) 940-7800 +Washington D.C. (301) 474-2878 +Isreal (972) 349-491-099 +Tokyo 03-437-6611 +Osaka (Call Tokyo) 03-437-6611 +Toronto, Canada (416) 675-2105 +London (0793) 696-000 +Munich (089) 5389-1 +Paris (01) 687-22-21 +Stockholm (468) 734-01-00 +Milan 39-2-82-44-071 +Benelux (Rotterdam) (10) 21-23-77 +Copenhagen (1) 198-033 +Hong Kong 5-215311-7 + + +Table of Contents + +Chapter 1 Introduction to the 80386 + +1.1 Organization of This Manual + 1.1.1 Part I Applications Programming + 1.1.2 Part II Systems Programming + 1.1.3 Part III Compatibility + 1.1.4 Part IV Instruction Set + 1.1.5 Appendices + +1.2 Related Literature +1.3 Notational Conventions + 1.3.1 Data-Structure Formats + 1.3.2 Undefined Bits and Software Compatibility + 1.3.3 Instruction Operands + 1.3.4 Hexadecimal Numbers + 1.3.5 Sub- and Super-Scripts + + PART I APPLICATIONS PROGRAMMING + +Chapter 2 Basic Programming Model + +2.1 Memory Organization and Segmentation + 2.1.1 The"Flat" Model + 2.1.2 The Segmented Model + +2.2 Data Types +2.3 Registers + 2.3.1 General Registers + 2.3.2 Segment Registers + 2.3.3 Stack Implementation + 2.3.4 Flags Register + 2.3.4.1 Status Flags + 2.3.4.2 Control Flag + 2.3.4.3 Instruction Pointer + +2.4 Instruction Format +2.5 Operand Selection + 2.5.1 Immediate Operands + 2.5.2 Register Operands + 2.5.3 Memory Operands + 2.5.3.1 Segment Selection + 2.5.3.2 Effective-Address Computation + +2.6 Interrupts and Exceptions + +Chapter 3 Applications Instruction Set + +3.1 Data Movement Instructions + 3.1.1 General-Purpose Data Movement Instructions + 3.1.2 Stack Manipulation Instructions + 3.1.3 Type Conversion Instructions + +3.2 Binary Arithmetic Instructions + 3.2.1 Addition and Subtraction Instructions + 3.2.2 Comparison and Sign Change Instruction + 3.2.3 Multiplication Instructions + 3.2.4 Division Instructions + +3.3 Decimal Arithmetic Instructions + 3.3.1 Packed BCD Adjustment Instructions + 3.3.2 Unpacked BCD Adjustment Instructions + +3.4 Logical Instructions + 3.4.1 Boolean Operation Instructions + 3.4.2 Bit Test and Modify Instructions + 3.4.3 Bit Scan Instructions + 3.4.4 Shift and Rotate Instructions + 3.4.4.1 Shift Instructions + 3.4.4.2 Double-Shift Instructions + 3.4.4.3 Rotate Instructions + 3.4.4.4 Fast"bit-blt" Using Double Shift + Instructions + 3.4.4.5 Fast Bit-String Insert and Extract + + 3.4.5 Byte-Set-On-Condition Instructions + 3.4.6 Test Instruction + +3.5 Control Transfer Instructions + 3.5.1 Unconditional Transfer Instructions + 3.5.1.1 Jump Instruction + 3.5.1.2 Call Instruction + 3.5.1.3 Return and Return-From-Interrupt Instruction + + 3.5.2 Conditional Transfer Instructions + 3.5.2.1 Conditional Jump Instructions + 3.5.2.2 Loop Instructions + 3.5.2.3 Executing a Loop or Repeat Zero Times + + 3.5.3 Software-Generated Interrupts + +3.6 String and Character Translation Instructions + 3.6.1 Repeat Prefixes + 3.6.2 Indexing and Direction Flag Control + 3.6.3 String Instructions + +3.7 Instructions for Block-Structured Languages +3.8 Flag Control Instructions + 3.8.1 Carry and Direction Flag Control Instructions + 3.8.2 Flag Transfer Instructions + +3.9 Coprocessor Interface Instructions +3.10 Segment Register Instructions + 3.10.1 Segment-Register Transfer Instructions + 3.10.2 Far Control Transfer Instructions + 3.10.3 Data Pointer Instructions + +3.11 Miscellaneous Instructions + 3.11.1 Address Calculation Instruction + 3.11.2 No-Operation Instruction + 3.11.3 Translate Instruction + + PART II SYSTEMS PROGRAMMING + +Chapter 4 Systems Architecture + +4.1 Systems Registers + 4.1.1 Systems Flags + 4.1.2 Memory-Management Registers + 4.1.3 Control Registers + 4.1.4 Debug Register + 4.1.5 Test Registers + +4.2 Systems Instructions + +Chapter 5 Memory Management + +5.1 Segment Translation + 5.1.1 Descriptors + 5.1.2 Descriptor Tables + 5.1.3 Selectors + 5.1.4 Segment Registers + +5.2 Page Translation + 5.2.1 Page Frame + 5.2.2 Linear Address + 5.2.3 Page Tables + 5.2.4 Page-Table Entries + 5.2.4.1 Page Frame Address + 5.2.4.2 Present Bit + 5.2.4.3 Accessed and Dirty Bits + 5.2.4.4 Read/Write and User/Supervisor Bits + + 5.2.5 Page Translation Cache + +5.3 Combining Segment and Page Translation + 5.3.1 "Flat" Architecture + 5.3.2 Segments Spanning Several Pages + 5.3.3 Pages Spanning Several Segments + 5.3.4 Non-Aligned Page and Segment Boundaries + 5.3.5 Aligned Page and Segment Boundaries + 5.3.6 Page-Table per Segment + +Chapter 6 Protection + +6.1 Why Protection? +6.2 Overview of 80386 Protection Mechanisms +6.3 Segment-Level Protection + 6.3.1 Descriptors Store Protection Parameters + 6.3.1.1 Type Checking + 6.3.1.2 Limit Checking + 6.3.1.3 Privilege Levels + + 6.3.2 Restricting Access to Data + 6.3.2.1 Accessing Data in Code Segments + + 6.3.3 Restricting Control Transfers + 6.3.4 Gate Descriptors Guard Procedure Entry Points + 6.3.4.1 Stack Switching + 6.3.4.2 Returning from a Procedure + + 6.3.5 Some Instructions are Reserved for Operating System + 6.3.5.1 Privileged Instructions + 6.3.5.2 Sensitive Instructions + + 6.3.6 Instructions for Pointer Validation + 6.3.6.1 Descriptor Validation + 6.3.6.2 Pointer Integrity and RPL + +6.4 Page-Level Protection + 6.4.1 Page-Table Entries Hold Protection Parameters + 6.4.1.1 Restricting Addressable Domain + 6.4.1.2 Type Checking + + 6.4.2 Combining Protection of Both Levels of Page Tables + 6.4.3 Overrides to Page Protection + +6.5 Combining Page and Segment Protection + +Chapter 7 Multitasking + +7.1 Task State Segment +7.2 TSS Descriptor +7.3 Task Register +7.4 Task Gate Descriptor +7.5 Task Switching +7.6 Task Linking + 7.6.1 Busy Bit Prevents Loops + 7.6.2 Modifying Task Linkages + +7.7 Task Address Space + 7.7.1 Task Linear-to-Physical Space Mapping + 7.7.2 Task Logical Address Space + +Chapter 8 Input/Output + +8.1 I/O Addressing + 8.1.1 I/O Address Space + 8.1.2 Memory-Mapped I/O + +8.2 I/O Instructions + 8.2.1 Register I/O Instructions + 8.2.2 Block I/O Instructions + +8.3 Protection and I/O + 8.3.1 I/O Privilege Level + 8.3.2 I/O Permission Bit Map + +Chapter 9 Exceptions and Interrupts + +9.1 Identifying Interrupts +9.2 Enabling and Disabling Interrupts + 9.2.1 NMI Masks Further NMls + 9.2.2 IF Masks INTR + 9.2.3 RF Masks Debug Faults + 9.2.4 MOV or POP to SS Masks Some Interrupts and Exceptions + +9.3 Priority Among Simultaneous Interrupts and Exceptions +9.4 Interrupt Descriptor Table +9.5 IDT Descriptors +9.6 Interrupt Tasks and Interrupt Procedures + 9.6.1 Interrupt Procedures + 9.6.1.1 Stack of Interrupt Procedure + 9.6.1.2 Returning from an Interrupt Procedure + 9.6.1.3 Flags Usage by Interrupt Procedure + 9.6.1.4 Protection in Interrupt Procedures + + 9.6.2 Interrupt Tasks + +9.7 Error Code +9.8 Exception Conditions + 9.8.1 Interrupt 0 Divide Error + 9.8.2 Interrupt 1 Debug Exceptions + 9.8.3 Interrupt 3 Breakpoint + 9.8.4 Interrupt 4 Overflow + 9.8.5 Interrupt 5 Bounds Check + 9.8.6 Interrupt 6 Invalid Opcode + 9.8.7 Interrupt 7 Coprocessor Not Available + 9.8.8 Interrupt 8 Double Fault + 9.8.9 Interrupt 9 Coprocessor Segment Overrun + 9.8.10 Interrupt 10 Invalid TSS + 9.8.11 Interrupt 11 Segment Not Present + 9.8.12 Interrupt 12 Stack Exception + 9.8.13 Interrupt 13 General Protection Exception + 9.8.14 Interrupt 14 Page Fault + 9.8.14.1 Page Fault during Task Switch + 9.8.14.2 Page Fault with Inconsistent Stack Pointer + + 9.8.15 Interrupt 16 Coprocessor Error + +9.9 Exception Summary + +9.10 Error Code Summary + +Chapter 10 Initialization + +10.1 Processor State after Reset +10.2 Software Initialization for Real-Address Mode + 10.2.1 Stack + 10.2.2 Interrupt Table + 10.2.3 First Instructions + +10.3 Switching to Protected Mode +10.4 Software Initialization for Protected Mode + 10.4.1 Interrupt Descriptor Table + 10.4.2 Stack + 10.4.3 Global Descriptor Table + 10.4.4 Page Tables + 10.4.5 First Task + +10.5 Initialization Example +10.6 TLB Testing + 10.6.1 Structure of the TLB + 10.6.2 Test Registers + 10.6.3 Test Operations + +Chapter 11 Coprocessing and Multiprocessing + +11.1 Coprocessing + 11.1.1 Coprocessor Identification + 11.1.2 ESC and WAIT Instructions + 11.1.3 EM and MP Flags + 11.1.4 The Task-Switched Flag + 11.1.5 Coprocessor Exceptions + 11.1.5.1 Interrupt 7 Coprocessor Not Available + 11.1.5.2 Interrupt 9 Coprocessor Segment Overrun + 11.1.5.3 Interrupt 16 Coprocessor Error + +11.2 General Multiprocessing + 11.2.1 LOCK and the LOCK# Signal + 11.2.2 Automatic Locking + 11.2.3 Cache Considerations + +Chapter 12 Debugging + +12.1 Debugging Features of the Architecture +12.2 Debug Registers + 12.2.1 Debug Address Registers (DRO-DR3) + 12.2.2 Debug Control Register (DR7) + 12.2.3 Debug Status Register (DR6) + 12.2.4 Breakpoint Field Recognition + +12.3 Debug Exceptions + 12.3.1 Interrupt 1 Debug Exceptions + 12.3.1.1 Instruction Address Breakpoint + 12.3.1.2 Data Address Breakpoint + 12.3.1.3 General Detect Fault + 12.3.1.4 Single-Step Trap + 12.3.1.5 Task Switch Breakpoint + + 12.3.2 Interrupt 3 Breakpoint Exception + + PART III COMPATIBILITY + +Chapter 13 Executing 80286 Protected-Mode Code + +13.1 80286 Code Executes as a Subset of the 80386 +13.2 Two Ways to Execute 80286 Tasks +13.3 Differences from 80286 + 13.3.1 Wraparound of 80286 24-Bit Physical Address Space + 13.3.2 Reserved Word of Descriptor + 13.3.3 New Descriptor Type Codes + 13.3.4 Restricted Semantics of LOCK + 13.3.5 Additional Exceptions + +Chapter 14 80386 Real-Address Mode + +14.1 Physical Address Formation +14.2 Registers and Instructions +14.3 Interrupt and Exception Handling +14.4 Entering and Leaving Real-Address Mode + 14.4.1 Switching to Protected Mode + +14.5 Switching Back to Real-Address Mode +14.6 Real-Address Mode Exceptions +14.7 Differences from 8086 +14.8 Differences from 80286 Real-Address Mode + 14.8.1 Bus Lock + 14.8.2 Location of First Instruction + 14.8.3 Initial Values of General Registers + 14.8.4 MSW Initialization + +Chapter 15 Virtual 8088 Mode + +15.1 Executing 8086 Code + 15.1.1 Registers and Instructions + 15.1.2 Linear Address Formation + +15.2 Structure of a V86 Task + 15.2.1 Using Paging for V86 Tasks + 15.2.2 Protection within a V86 Task + +15.3 Entering and Leaving V86 Mode + 15.3.1 Transitions Through Task Switches + 15.3.2 Transitions Through Trap Gates and Interrupt Gates + +15.4 Additional Sensitive Instructions + 15.4.1 Emulating 8086 Operating System Calls + 15.4.2 Virtualizing the Interrupt-Enable Flag + +15.5 Virtual I/O + 15.5.1 I/O-Mapped I/O + 15.5.2 Memory-Mapped I/O + 15.5.3 Special I/O Buffers + +15.6 Differences from 8086 +15.7 Differences from 80286 Real-Address Mode + +Chapter 16 Mixing 16-Bit and 32-Bit Code + +16.1 How the 80386 Implements 16-Bit and 32-Bit Features +16.2 Mixing 32-Bit and 16-Bit Operations +16.3 Sharing Data Segments among Mixed Code Segments +16.4 Transferring Control among Mixed Code Segments + 16.4.1 Size of Code-Segment Pointer + 16.4.2 Stack Management for Control Transfers + 16.4.2.1 Controlling the Operand-Size for a CALL + 16.4.2.2 Changing Size of Call + + 16.4.3 Interrupt Control Transfers + 16.4.4 Parameter Translation + 16.4.5 The Interface Procedure + + PART IV INSTRUCTION SET + +Chapter 17 80386 Instruction Set + +17.1 Operand-Size and Address-Size Attributes + 17.1.1 Default Segment Attribute + 17.1.2 Operand-Size and Address-Size Instruction Prefixes + 17.1.3 Address-Size Attribute for Stack + +17.2 Instruction Format + 17.2.1 ModR/M and SIB Bytes + 17.2.2 How to Read the Instruction Set Pages + 17.2.2.1 Opcode + 17.2.2.2 Instruction + 17.2.2.3 Clocks + 17.2.2.4 Description + 17.2.2.5 Operation + 17.2.2.6 Description + 17.2.2.7 Flags Affected + 17.2.2.8 Protected Mode Exceptions + 17.2.2.9 Real Address Mode Exceptions + 17.2.2.10 Virtual-8086 Mode Exceptions + +Instruction Sets + +AAA +AAD +AAM +AAS +ADC +ADD +AND +ARPL +BOUND +BSF +BSR +BT +BTC +BTR +BTS +CALL +CBW/CWDE +CLC +CLD +CLI +CLTS +CMC +CMP +CMPS/CMPSB/CMPSW/CMPSD +CWD/CDQ +DAA +DAS +DEC +DIV +ENTER +HLT +IDIV +IMUL +IN +INC +INS/INSB/INSW/INSD +INT/INTO +IRET/IRETD +Jcc +JMP +LAHF +LAR +LEA +LEAVE +LGDT/LIDT +LGS/LSS/LDS/LES/LFS +LLDT +LMSW +LOCK +LODS/LODSB/LODSW/LODSD +LOOP/LOOPcond +LSL +LTR +MOV +MOV +MOVS/MOVSB/MOVSW/MOVSD +MOVSX +MOVZX +MUL +NEG +NOP +NOT +OR +OUT +OUTS/OUTSB/OUTSW/OUTSD +POP +POPA/POPAD +POPF/POPFD +PUSH +PUSHA/PUSHAD +PUSHF/PUSHFD +RCL/RCR/ROL/ROR +REP/REPE/REPZ/REPNE/REPNZ +RET +SAHF +SAL/SAR/SHL/SHR +SBB +SCAS/SCASB/SCASW/SCASD +SETcc +SGDT/SIDT +SHLD +SHRD +SLDT +SMSW +STC +STD +STI +STOS/STOSB/STOSW/STOSD +STR +SUB +TEST +VERR,VERW +WAIT +XCHG +XLAT/XLATB +XOR + +Appendix A Opcode Map + +Appendix B Complete Flag Cross-Reference + +Appendix C Status Flag Summary + +Appendix D Condition Codes + + +Figures + +1-1 Example Data Structure + +2-1 Two-Component Pointer +2-2 Fundamental Data Types +2-3 Bytes, Words, and Doublewords in Memory +2-4 80386 Data Types +2-5 80386 Applications Register Set +2-6 Use of Memory Segmentation +2-7 80386 Stack +2-8 EFLAGS Register +2-9 Instruction Pointer Register +2-10 Effective Address Computation + +3-1 PUSH +3-2 PUSHA +3-3 POP +3-4 POPA +3-5 Sign Extension +3-6 SAL and SHL +3-7 SHR +3-8 SAR +3-9 Using SAR to Simulate IDIV +3-10 Shift Left Double +3-11 Shift Right Double +3-12 ROL +3-13 ROR +3-14 RCL +3-15 RCR +3-16 Formal Definition of the ENTER Instruction +3-17 Variable Access in Nested Procedures +3-18 Stack Frame for MAIN at Level 1 +3-19 Stack Frame for Prooedure A +3-20 Stack Frame for Procedure B at Level 3 Called from A +3-21 Stack Frame for Procedure C at Level 3 Called from B +3-22 LAHF and SAHF +3-23 Flag Format for PUSHF and POPF + +4-1 Systems Flags of EFLAGS Register +4-2 Control Registers + +5-1 Address Translation Overview +5-2 Segment Translation +5-3 General Segment-Descriptor Format +5-4 Format of Not-Present Descriptor +5-5 Descriptor Tables +5-6 Format of a Selector +5-7 Segment Registers +5-8 Format of a Linear Address +5-9 Page Translation +5-10 Format of a Page Table Entry +5-11 Invalid Page Table Entry +5-12 80386 Addressing Mechanism +5-13 Descriptor per Page Table + +6-1 Protection Fields of Segment Descriptors +6-2 Levels of Privilege +6-3 Privilege Check for Data Access +6-4 Privilege Check for Control Transfer without Gate +6-5 Format of 80386 Call Gate +6-6 Indirect Transfer via Call Gate +6-7 Privilege Check via Call Gate +6-8 Initial Stack Pointers of TSS +6-9 Stack Contents after an Interievel Call +6-10 Protection Fields of Page Table Entries + +7-1 80386 32-Bit Task State Segment +7-2 TSS Descriptor for 32-Bit TSS +7-3 Task Register +7-4 Task Gate Descriptor +7-5 Task Gate Indirectly Identifies Task +7-6 Partially-Overlapping Linear Spaces + +8-1 Memory-Mapped I/O +8-2 I/O Address Bit Map + +9-1 IDT Register and Table +9-2 Pseudo-Descriptor Format for LIDT and SIDT +9-3 80386 IDT Gate Descriptors +9-4 Interrupt Vectoring for Procedures +9-5 Stack Layout after Exception of Interrupt +9-6 Interrupt Vectoring for Tasks +9-7 Error Code Format +9-8 Page-Fault Error Code Format +9-9 CR2 Format + +10-1 Contents of EDX after RESET +10-2 Initial Contents of CRO +10-3 TLB Structure +10-4 Test Registers + +12-1 Debug Registers + +14-1 Real-Address Mode Address Formation + +15-1 V86 Mode Address Formation +15-2 Entering and Leaving an 8086 Program +15-3 PL 0 Stack after Interrupt in V86 Task + +16-1 Stack after Far 16-Bit and 32-Bit Calls + +17-1 80386 Instruction Format +17-2 ModR/M and SIB Byte Formats +17-3 Bit Offset for BIT[EAX, 21] +17-4 Memory Bit Indexing + + +Tables + +2-1 Default Segment Register Selection Rules +2-2 80386 Reserved Exceptions and Interrupts + +3-1 Bit Test and Modify Instructions +3-2 Interpretation of Conditional Transfers + +6-1 System and Gate Descriptor Types +6-2 Useful Combinations of E, G, and B Bits +6-3 Interievel Return Checks +6-4 Valid Descriptor Types for LSL +6-5 Combining Directory and Page Protection + +7-1 Checks Made during a Task Switch +7-2 Effect of Task Switch on BUSY, NT, and Back-Link + +9-1 Interrupt and Exception ID Assignments +9-2 Priority Among Simultaneous Interrupts and Exceptions +9-3 Double-Fault Detection Classes +9-4 Double-Fault Definition +9-5 Conditions That Invalidate the TSS +9-6 Exception Summary +9-7 Error-Code Summary + +10-1 Meaning of D, U, and W Bit Pairs + +12-1 Breakpeint Field Recognition Examples +12-2 Debug Exception Conditions + +14-1 80386 Real-Address Mode Exceptions +14-2 New 80386 Exceptions + +17-1 Effective Size Attributes +17-2 16-Bit Addressing Forms with the ModR/M Byte +17-3 32-Bit Addressing Forms with the ModR/M Byte +17-4 32-Bit Addressing Forms with the SIB Byte +17-5 Task Switch Times for Exceptions +17-6 80386 Exceptions + + +Chapter 1 Introduction to the 80386 + + + +The 80386 is an advanced 32-bit microprocessor optimized for multitasking +operating systems and designed for applications needing very high +performance. The 32-bit registers and data paths support 32-bit addresses +and data types. The processor can address up to four gigabytes of physical +memory and 64 terabytes (2^(46) bytes) of virtual memory. The on-chip +memory-management facilities include address translation registers, +advanced multitasking hardware, a protection mechanism, and paged virtual +memory. Special debugging registers provide data and code breakpoints even +in ROM-based software. + + +1.1 Organization of This Manual + +This book presents the architecture of the 80386 in five parts: + + Part I Applications Programming + Part II Systems Programming + Part III Compatibility + Part IV Instruction Set + Appendices + +These divisions are determined in part by the architecture itself and in +part by the different ways the book will be used. As the following table +indicates, the latter two parts are intended as reference material for +programmers actually engaged in the process of developing software for the +80386. The first three parts are explanatory, showing the purpose of +architectural features, developing terminology and concepts, and describing +instructions as they relate to specific purposes or to specific +architectural features. + +Explanation Part I Applications Programming + Part II Systems Programming + Part III Compatibility + +Reference Part IV Instruction Set + Appendices + +The first three parts follow the execution modes and protection features of +the 80386 CPU. The distinction between applications features and systems +features is determined by the protection mechanism of the 80386. One purpose +of protection is to prevent applications from interfering with the operating +system; therefore, the processor makes certain registers and instructions +inaccessible to applications programs. The features discussed in Part I are +those that are accessible to applications; the features in Part II are +available only to systems software that has been given special privileges or +in unprotected systems. + +The processing mode of the 80386 also determines the features that are +accessible. The 80386 has three processing modes: + + 1. Protected Mode. + 2. Real-Address Mode. + 3. Virtual 8086 Mode. + +Protected mode is the natural 32-bit environment of the 80386 processor. In +this mode all instructions and features are available. + +Real-address mode (often called just "real mode") is the mode of the +processor immediately after RESET. In real mode the 80386 appears to +programmers as a fast 8086 with some new instructions. Most applications of +the 80386 will use real mode for initialization only. + +Virtual 8086 mode (also called V86 mode) is a dynamic mode in the sense +that the processor can switch repeatedly and rapidly between V86 mode and +protected mode. The CPU enters V86 mode from protected mode to execute an +8086 program, then leaves V86 mode and enters protected mode to continue +executing a native 80386 program. + +The features that are available to applications programs in protected mode +and to all programs in V86 mode are the same. These features form the +content of Part I. The additional features that are available to systems +software in protected mode form Part II. Part III explains real-address +mode and V86 mode, as well as how to execute a mix of 32-bit and 16-bit +programs. + +Available in All Modes Part I Applications Programming + +Available in Protected Part II Systems Programming +Mode Only + +Compatibility Modes Part III Compatibility + + +1.1.1 Part I Applications Programming + +This part presents those aspects of the architecture that are customarily +used by applications programmers. + +Chapter 2 Basic Programming Model: Introduces the models of memory +organization. Defines the data types. Presents the register set used by +applications. Introduces the stack. Explains string operations. Defines the +parts of an instruction. Explains addressing calculations. Introduces +interrupts and exceptions as they may apply to applications programming. + +Chapter 3 Application Instruction Set: Surveys the instructions commonly +used for applications programming. Considers instructions in functionally +related groups; for example, string instructions are considered in one +section, while control-transfer instructions are considered in another. +Explains the concepts behind the instructions. Details of individual +instructions are deferred until Part IV, the instruction-set reference. + + +1.1.2 Part II Systems Programming + +This part presents those aspects of the architecture that are customarily +used by programmers who write operating systems, device drivers, debuggers, +and other software that supports applications programs in the protected mode +of the 80386. + +Chapter 4 Systems Architecture: Surveys the features of the 80386 that +are used by systems programmers. Introduces the remaining registers and data +structures of the 80386 that were not discussed in Part I. Introduces the +systems-oriented instructions in the context of the registers and data +structures they support. Points to the chapter where each register, data +structure, and instruction is considered in more detail. + +Chapter 5 Memory Management: Presents details of the data structures, +registers, and instructions that support virtual memory and the concepts of +segmentation and paging. Explains how systems designers can choose a model +of memory organization ranging from completely linear ("flat") to fully +paged and segmented. + +Chapter 6 Protection: Expands on the memory management features of the +80386 to include protection as it applies to both segments and pages. +Explains the implementation of privilege rules, stack switching, pointer +validation, user and supervisor modes. Protection aspects of multitasking +are deferred until the following chapter. + +Chapter 7 Multitasking: Explains how the hardware of the 80386 supports +multitasking with context-switching operations and intertask protection. + +Chapter 8 Input/Output: Reveals the I/O features of the 80386, including +I/O instructions, protection as it relates to I/O, and the I/O permission +map. + +Chapter 9 Exceptions and Interrupts: Explains the basic interrupt +mechanisms of the 80386. Shows how interrupts and exceptions relate to +protection. Discusses all possible exceptions, listing causes and including +information needed to handle and recover from the exception. + +Chapter 10 Initialization: Defines the condition of the processor after +RESET or power-up. Explains how to set up registers, flags, and data +structures for either real-address mode or protected mode. Contains an +example of an initialization program. + +Chapter 11 Coprocessing and Multiprocessing: Explains the instructions +and flags that support a numerics coprocessor and multiple CPUs with shared +memory. + +Chapter 12 Debugging: Tells how to use the debugging registers of the +80386. + + +1.1.3 Part III Compatibility + +Other parts of the book treat the processor primarily as a 32-bit machine, +omitting for simplicity its facilities for 16-bit operations. Indeed, the +80386 is a 32-bit machine, but its design fully supports 16-bit operands and +addressing, too. This part completes the picture of the 80386 by explaining +the features of the architecture that support 16-bit programs and 16-bit +operations in 32-bit programs. All three processor modes are used to +execute 16-bit programs: protected mode can directly execute 16-bit 80286 +protected mode programs, real mode executes 8086 programs and real-mode +80286 programs, and virtual 8086 mode executes 8086 programs in a +multitasking environment with other 80386 protected-mode programs. In +addition, 32-bit and 16-bit modules and individual 32-bit and 16-bit +operations can be mixed in protected mode. + +Chapter 13 Executing 80286 Protected-Mode Code: In its protected mode, +the 80386 can execute complete 80286 protected-mode systems, because 80286 +capabilities are a subset of 80386 capabilities. + +Chapter 14 80386 Real-Address Mode: Explains the real mode of the 80386 +CPU. In this mode the 80386 appears as a fast real-mode 80286 or fast 8086 +enhanced with additional instructions. + +Chapter 15 Virtual 8086 Mode: The 80386 can switch rapidly between its +protected mode and V86 mode, giving it the ability to multiprogram 8086 +programs along with "native mode" 32-bit programs. + +Chapter 16 Mixing 16-Bit and 32-Bit Code: Even within a program or task, +the 80386 can mix 16-bit and 32-bit modules. Furthermore, any given module +can utilize both 16-bit and 32-bit operands and addresses. + + +1.1.4 Part IV Instruction Set + +Parts I, II, and III present overviews of the instructions as they relate +to specific aspects of the architecture, but this part presents the +instructions in alphabetical order, providing the detail needed by +assembly-language programmers and programmers of debuggers, compilers, +operating systems, etc. Instruction descriptions include algorithmic +description of operation, effect of flag settings, effect on flag settings, +effect of operand- or address-size attributes, effect of processor modes, +and possible exceptions. + + +1.1.5 Appendices + +The appendices present tables of encodings and other details in a format +designed for quick reference by assembly-language and systems programmers. + + +1.2 Related Literature + +The following books contain additional material concerning the 80386 +microprocessor: + + Introduction to the 80386, order number 231252 + + 80386 Hardware Reference Manual, order number 231732 + + 80386 System Software Writer's Guide, order number 231499 + + 80386 High Performance 32-bit Microprocessor with Integrated Memory + Management (Data Sheet), order number 231630 + + +1.3 Notational Conventions + +This manual uses special notations for data-structure formats, for symbolic +representation of instructions, for hexadecimal numbers, and for super- and +sub-scripts. Subscript characters are surrounded by {curly brackets}, for +example 10{2} = 10 base 2. Superscript characters are preceeded by a caret +and enclosed within (parentheses), for example 10^(3) = 10 to the third +power. A review of these notations will make it easier to read the +manual. + +1.3.1 Data-Structure Formats + +In illustrations of data structures in memory, smaller addresses appear at +the lower-right part of the figure; addresses increase toward the left and +upwards. Bit positions are numbered from right to left. Figure 1-1 +illustrates this convention. + + +1.3.2 Undefined Bits and Software Compatibility + +In many register and memory layout descriptions, certain bits are marked as +undefined. When bits are marked as undefined (as illustrated in Figure +1-1), it is essential for compatibility with future processors that +software treat these bits as undefined. Software should follow these +guidelines in dealing with undefined bits: + + Do not depend on the states of any undefined bits when testing the + values of registers that contain such bits. Mask out the undefined bits + before testing. + + Do not depend on the states of any undefined bits when storing them in + memory or in another register. + + Do not depend on the ability to retain information written into any + undefined bits. + + When loading a register, always load the undefined bits as zeros or + reload them with values previously stored from the same register. + + +NOTE + Depending upon the values of undefined register bits will make software + dependent upon the unspecified manner in which the 80386 handles these + bits. Depending upon undefined values risks making software incompatible + with future processors that define usages for these bits. AVOID ANY + SOFTWARE DEPENDENCE UPON THE STATE OF UNDEFINED 80386 REGISTER BITS. + + + +Figure 1-1. Example Data Structure + + GREATEST DATA STRUCTURE + ADDRESS + 31 23 15 7 0 BIT + ͻ OFFSET + 28 + ͹ + 24 + ͹ + 20 + ͹ + 16 + ͹ + 12 + ͹ + 8 + ͹ + UNDEFINED 4 + ͹ SMALLEST + BYTE 3 BYTE 2 BYTE 1 BYTE 0 0 ADDRESS + ͼ + BYTE OFFSET + + +1.3.3 Instruction Operands + +When instructions are represented symbolically, a subset of the 80386 +Assembly Language is used. In this subset, an instruction has the following +format: + +label: prefix mnemonic argument1, argument2, argument3 + +where: + + A label is an identifier that is followed by a colon. + + A prefix is an optional reserved name for one of the instruction + prefixes. + + A mnemonic is a reserved name for a class of instruction opcodes that + have the same function. + + The operands argument1, argument2, and argument3 are optional. There + may be from zero to three operands, depending on the opcode. When + present, they take the form of either literals or identifiers for data + items. Operand identifiers are either reserved names of registers or + are assumed to be assigned to data items declared in another part of + the program (which may not be shown in the example). When two operands + are present in an instruction that modifies data, the right operand is + the source and the left operand is the destination. + +For example: + +LOADREG: MOV EAX, SUBTOTAL + +In this example LOADREG is a label, MOV is the mnemonic identifier of an +opcode, EAX is the destination operand, and SUBTOTAL is the source operand. + +1.3.4 Hexadecimal Numbers + +Base 16 numbers are represented by a string of hexadecimal digits followed +by the character H. A hexadecimal digit is a character from the set (0, 1, +2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). In some cases, especially in +examples of program syntax, a leading zero is added if the number would +otherwise begin with one of the digits A-F. For example, 0FH is equivalent +to the decimal number 15. + +1.3.5 Sub- and Super-Scripts + +This manual uses special notation to represent sub- and super-script +characters. Sub-script characters are surrounded by {curly brackets}, for +example 10{2} = 10 base 2. Super-script characters are preceeded by a +caret and enclosed within (parentheses), for example 10^(3) = 10 to the +third power. + + + PART I APPLICATIONS PROGRAMMING + + +Chapter 2 Basic Programming Model + + + +This chapter describes the 80386 application programming environment as +seen by assembly language programmers when the processor is executing in +protected mode. The chapter introduces programmers to those features of the +80386 architecture that directly affect the design and implementation of +80386 applications programs. Other chapters discuss 80386 features that +relate to systems programming or to compatibility with other processors of +the 8086 family. + +The basic programming model consists of these aspects: + + Memory organization and segmentation + Data types + Registers + Instruction format + Operand selection + Interrupts and exceptions + +Note that input/output is not included as part of the basic programming +model. Systems designers may choose to make I/O instructions available to +applications or may choose to reserve these functions for the operating +system. For this reason, the I/O features of the 80386 are discussed in Part +II. + +This chapter contains a section for each aspect of the architecture that is +normally visible to applications. + + +2.1 Memory Organization and Segmentation + +The physical memory of an 80386 system is organized as a sequence of 8-bit +bytes. Each byte is assigned a unique address that ranges from zero to a +maximum of 2^(32) -1 (4 gigabytes). + +80386 programs, however, are independent of the physical address space. +This means that programs can be written without knowledge of how much +physical memory is available and without knowledge of exactly where in +physical memory the instructions and data are located. + +The model of memory organization seen by applications programmers is +determined by systems-software designers. The architecture of the 80386 +gives designers the freedom to choose a model for each task. The model of +memory organization can range between the following extremes: + + A "flat" address space consisting of a single array of up to 4 + gigabytes. + + A segmented address space consisting of a collection of up to 16,383 + linear address spaces of up to 4 gigabytes each. + +Both models can provide memory protection. Different tasks may employ +different models of memory organization. The criteria that designers use to +determine a memory organization model and the means that systems programmers +use to implement that model are covered in Part IISystems Programming. + + +2.1.1 The "Flat" Model + +In a "flat" model of memory organization, the applications programmer sees +a single array of up to 2^(32) bytes (4 gigabytes). While the physical +memory can contain up to 4 gigabytes, it is usually much smaller; the +processor maps the 4 gigabyte flat space onto the physical address space by +the address translation mechanisms described in Chapter 5. Applications +programmers do not need to know the details of the mapping. + +A pointer into this flat address space is a 32-bit ordinal number that may +range from 0 to 2^(32) -1. Relocation of separately-compiled modules in this +space must be performed by systems software (e.g., linkers, locators, +binders, loaders). + + +2.1.2 The Segmented Model + +In a segmented model of memory organization, the address space as viewed by +an applications program (called the logical address space) is a much larger +space of up to 2^(46) bytes (64 terabytes). The processor maps the 64 +terabyte logical address space onto the physical address space (up to 4 +gigabytes) by the address translation mechanisms described in Chapter 5. +Applications programmers do not need to know the details of this mapping. + +Applications programmers view the logical address space of the 80386 as a +collection of up to 16,383 one-dimensional subspaces, each with a specified +length. Each of these linear subspaces is called a segment. A segment is a +unit of contiguous address space. Segment sizes may range from one byte up +to a maximum of 2^(32) bytes (4 gigabytes). + +A complete pointer in this address space consists of two parts (see Figure +2-1): + + 1. A segment selector, which is a 16-bit field that identifies a + segment. + + 2. An offset, which is a 32-bit ordinal that addresses to the byte level + within a segment. + +During execution of a program, the processor associates with a segment +selector the physical address of the beginning of the segment. Separately +compiled modules can be relocated at run time by changing the base address +of their segments. The size of a segment is variable; therefore, a segment +can be exactly the size of the module it contains. + + +2.2 Data Types + +Bytes, words, and doublewords are the fundamental data types (refer to +Figure 2-2). A byte is eight contiguous bits starting at any logical +address. The bits are numbered 0 through 7; bit zero is the least +significant bit. + +A word is two contiguous bytes starting at any byte address. A word thus +contains 16 bits. The bits of a word are numbered from 0 through 15; bit 0 +is the least significant bit. The byte containing bit 0 of the word is +called the low byte; the byte containing bit 15 is called the high byte. + +Each byte within a word has its own address, and the smaller of the +addresses is the address of the word. The byte at this lower address +contains the eight least significant bits of the word, while the byte at the +higher address contains the eight most significant bits. + +A doubleword is two contiguous words starting at any byte address. A +doubleword thus contains 32 bits. The bits of a doubleword are numbered from +0 through 31; bit 0 is the least significant bit. The word containing bit 0 +of the doubleword is called the low word; the word containing bit 31 is +called the high word. + +Each byte within a doubleword has its own address, and the smallest of the +addresses is the address of the doubleword. The byte at this lowest address +contains the eight least significant bits of the doubleword, while the byte +at the highest address contains the eight most significant bits. Figure 2-3 +illustrates the arrangement of bytes within words anddoublewords. + +Note that words need not be aligned at even-numbered addresses and +doublewords need not be aligned at addresses evenly divisible by four. This +allows maximum flexibility in data structures (e.g., records containing +mixed byte, word, and doubleword items) and efficiency in memory +utilization. When used in a configuration with a 32-bit bus, actual +transfers of data between processor and memory take place in units of +doublewords beginning at addresses evenly divisible by four; however, the +processor converts requests for misaligned words or doublewords into the +appropriate sequences of requests acceptable to the memory interface. Such +misaligned data transfers reduce performance by requiring extra memory +cycles. For maximum performance, data structures (including stacks) should +be designed in such a way that, whenever possible, word operands are aligned +at even addresses and doubleword operands are aligned at addresses evenly +divisible by four. Due to instruction prefetching and queuing within the +CPU, there is no requirement for instructions to be aligned on word or +doubleword boundaries. (However, a slight increase in speed results if the +target addresses of control transfers are evenly divisible by four.) + +Although bytes, words, and doublewords are the fundamental types of +operands, the processor also supports additional interpretations of these +operands. Depending on the instruction referring to the operand, the +following additional data types are recognized: + +Integer: +A signed binary numeric value contained in a 32-bit doubleword,16-bit word, +or 8-bit byte. All operations assume a 2's complement representation. The +sign bit is located in bit 7 in a byte, bit 15 in a word, and bit 31 in a +doubleword. The sign bit has the value zero for positive integers and one +for negative. Since the high-order bit is used for a sign, the range of an +8-bit integer is -128 through +127; 16-bit integers may range from -32,768 +through +32,767; 32-bit integers may range from -2^(31) through +2^(31) -1. +The value zero has a positive sign. + +Ordinal: +An unsigned binary numeric value contained in a 32-bit doubleword, +16-bit word, or 8-bit byte. All bits are considered in determining +magnitude of the number. The value range of an 8-bit ordinal number +is 0-255; 16 bits can represent values from 0 through 65,535; 32 bits +can represent values from 0 through 2^(32) -1. + +Near Pointer: +A 32-bit logical address. A near pointer is an offset within a segment. +Near pointers are used in either a flat or a segmented model of memory +organization. + +Far Pointer: +A 48-bit logical address of two components: a 16-bit segment selector +component and a 32-bit offset component. Far pointers are used by +applications programmers only when systems designers choose a +segmented memory organization. + +String: +A contiguous sequence of bytes, words, or doublewords. A string may +contain from zero bytes to 2^(32) -1 bytes (4 gigabytes). + +Bit field: +A contiguous sequence of bits. A bit field may begin at any bit position +of any byte and may contain up to 32 bits. + +Bit string: +A contiguous sequence of bits. A bit string may begin at any bit position +of any byte and may contain up to 2^(32) -1 bits. + +BCD: +A byte (unpacked) representation of a decimal digit in the range0 through +9. Unpacked decimal numbers are stored as unsigned byte quantities. One +digit is stored in each byte. The magnitude of the number is determined from +the low-order half-byte; hexadecimal values 0-9 are valid and are +interpreted as decimal numbers. The high-order half-byte must be zero for +multiplication and division; it may contain any value for addition and +subtraction. + +Packed BCD: +A byte (packed) representation of two decimal digits, each in the range +0 through 9. One digit is stored in each half-byte. The digit in the +high-order half-byte is the most significant. Values 0-9 are valid in each +half-byte. The range of a packed decimal byte is 0-99. + +Figure 2-4 graphically summarizes the data types supported by the 80386. + + +Figure 2-1. Two-Component Pointer + +   + + ͹Ŀ + 32 0 + ͻ ͻ ͹ + OFFSET Ķ +  OPERAND + ͼ ͼ ͹ SELECTED SEGMENT +  + 16 0 + ͻ + SEGMENT͹ + ͼ + + +   + + +Figure 2-2. Fundamental Data Types + + 7 0 + ͻ + BYTE BYTE + ͼ + + 15 7 0 + ͻ + HIGH BYTE LOW BYTE WORD + ͼ + address n+1 address n + + 31 23 15 7 0 + ͻ + HIGH WORD LOW WORD DOUBLEWORD + ͼ + address n+3 address n+2 address n+1 address n + + +Figure 2-3. Bytes, Words, and Doublewords in Memory + + MEMORY + BYTE VALUES +All values in hexadecimal + ADDRESS ͻ + E + ͹Ŀ + D 7A DOUBLE WORD AT ADDRESS A + ͹Ŀ CONTAINS 7AFE0636 + C FE + ͹ WORD AT ADDRESS B + B 06 CONTAINS FE06 + ͹ٳ + A 36 + ͹͵ + 9 1F WORD AT ADDRESS 9 + ͹ CONTAINS IF + 8 + ͹Ŀ + 7 23 + ͹ WORD AT ADDRESS 6 + 6 OB CONTAINS 23OB + ͹ + 5 + ͹ + 4 + ͹Ŀ + 3 74 + ͹Ŀ WORD AT ADDRESS 2 + 2 CB CONTAINS 74CB + ͹ + 1 31 WORD AT ADDRESS 1 + ͹ CONTAINS CB31 + 0 + ͼ + + +Figure 2-4. 80386 Data Types + + +1 0 + 7 0 7 0 15 14 8 7 0 + BYTE ѻ BYTE ѻ WORD ѻ + INTEGER ORDINAL INTEGER + ͼ ͼ ͼ + SIGN BIT SIGN BITMSB + MAGNITUDE MAGNITUDE + MAGNITUDE + + + +1 0 +3 +2 +1 0 + 15 0 31 16 15 0 + WORD ѻ DOUBLEWORD ѻ + ORDINAL INTEGER + ͼ ͼ + SIGN BITMSB + + MAGNITUDE MAGNITUDE + + + +3 +2 +1 0 + 31 0 + DOUBLEWORD ѻ + ORDINAL + ͼ + + MAGNITUDE + + +N +1 0 + 7 0 7 0 7 0 + BINARY CODED ѻ ѻ + DECIMAL (BCD)  + ͼ ͼ + BCD BCD BCD + DIGIT N DIGIT 1 DIGIT 0 + + +N +1 0 + 7 0 7 0 7 0 + PACKED ѻ ѻ + BCD  + ͼ ͼ + + MOST LEAST + SIGNIFICANT SIGNIFICANT + DIGIT DIGIT + + +N +1 0 + 7 0 7 0 7 0 + BYTE ѻ ѻ + STRING  + ͼ ͼ + + -2 GIGABYTES + +2 GIGABYTES 210 + BIT ѻ + STRING + ϼ + BIT 0 + + +3 +2 +1 0 + 31 0 +NEAR 32-BIT ѻ + POINTER + ͼ + + OFFSET + + +5 +4 +3 +2 +1 0 + 48 0 +FAR 48-BIT ѻ + POINTER + ͼ + + SELECTOR OFFSET + + +5 +4 +3 +2 +1 0 + 32-BIT ѻ + BIT FIELD + ͼ +  BIT FIELD  + 1 TO 32 BITS + + +2.3 Registers + +The 80386 contains a total of sixteen registers that are of interest to the +applications programmer. As Figure 2-5 shows, these registers may be +grouped into these basic categories: + + 1. General registers. These eight 32-bit general-purpose registers are + used primarily to contain operands for arithmetic and logical + operations. + + 2. Segment registers. These special-purpose registers permit systems + software designers to choose either a flat or segmented model of + memory organization. These six registers determine, at any given time, + which segments of memory are currently addressable. + + 3. Status and instruction registers. These special-purpose registers are + used to record and alter certain aspects of the 80386 processor state. + + +2.3.1 General Registers + +The general registers of the 80386 are the 32-bit registers EAX, EBX, ECX, +EDX, EBP, ESP, ESI, and EDI. These registers are used interchangeably to +contain the operands of logical and arithmetic operations. They may also be +used interchangeably for operands of address computations (except that ESP +cannot be used as an index operand). + +As Figure 2-5 shows, the low-order word of each of these eight registers +has a separate name and can be treated as a unit. This feature is useful for +handling 16-bit data items and for compatibility with the 8086 and 80286 +processors. The word registers are named AX, BX, CX, DX, BP, SP, SI, and DI. + +Figure 2-5 also illustrates that each byte of the 16-bit registers AX, BX, +CX, and DX has a separate name and can be treated as a unit. This feature is +useful for handling characters and other 8-bit data items. The byte +registers are named AH, BH, CH, and DH (high bytes); and AL, BL, CL, and DL +(low bytes). + +All of the general-purpose registers are available for addressing +calculations and for the results of most arithmetic and logical +calculations; however, a few functions are dedicated to certain registers. +By implicitly choosing registers for these functions, the 80386 architecture +can encode instructions more compactly. The instructions that use specific +registers include: double-precision multiply and divide, I/O, string +instructions, translate, loop, variable shift and rotate, and stack +operations. + + +2.3.2 Segment Registers + +The segment registers of the 80386 give systems software designers the +flexibility to choose among various models of memory organization. +Implementation of memory models is the subject of Part II Systems +Programming. Designers may choose a model in which applications programs do +not need to modify segment registers, in which case applications programmers +may skip this section. + +Complete programs generally consist of many different modules, each +consisting of instructions and data. However, at any given time during +program execution, only a small subset of a program's modules are actually +in use. The 80386 architecture takes advantage of this by providing +mechanisms to support direct access to the instructions and data of the +current module's environment, with access to additional segments on demand. + +At any given instant, six segments of memory may be immediately accessible +to an executing 80386 program. The segment registers CS, DS, SS, ES, FS, and +GS are used to identify these six current segments. Each of these registers +specifies a particular kind of segment, as characterized by the associated +mnemonics ("code," "data," or "stack") shown in Figure 2-6. Each register +uniquely determines one particular segment, from among the segments that +make up the program, that is to be immediately accessible at highest speed. + +The segment containing the currently executing sequence of instructions is +known as the current code segment; it is specified by means of the CS +register. The 80386 fetches all instructions from this code segment, using +as an offset the contents of the instruction pointer. CS is changed +implicitly as the result of intersegment control-transfer instructions (for +example, CALL and JMP), interrupts, and exceptions. + +Subroutine calls, parameters, and procedure activation records usually +require that a region of memory be allocated for a stack. All stack +operations use the SS register to locate the stack. Unlike CS, the SS +register can be loaded explicitly, thereby permitting programmers to define +stacks dynamically. + +The DS, ES, FS, and GS registers allow the specification of four data +segments, each addressable by the currently executing program. Accessibility +to four separate data areas helps programs efficiently access different +types of data structures; for example, one data segment register can point +to the data structures of the current module, another to the exported data +of a higher-level module, another to a dynamically created data structure, +and another to data shared with another task. An operand within a data +segment is addressed by specifying its offset either directly in an +instruction or indirectly via general registers. + +Depending on the structure of data (e.g., the way data is parceled into one +or more segments), a program may require access to more than four data +segments. To access additional segments, the DS, ES, FS, and GS registers +can be changed under program control during the course of a program's +execution. This simply requires that the program execute an instruction to +load the appropriate segment register prior to executing instructions that +access the data. + +The processor associates a base address with each segment selected by a +segment register. To address an element within a segment, a 32-bit offset is +added to the segment's base address. Once a segment is selected (by loading +the segment selector into a segment register), a data manipulation +instruction only needs to specify the offset. Simple rules define which +segment register is used to form an address when only an offset is +specified. + + +Figure 2-5. 80386 Applications Register Set + + GENERAL REGISTERS + + 31 23 15 7 0 + ͻ + EAX AH AX AL + ͹ + EDX DH DX DL + ͹ + ECX CH CX CL + ͹ + EBX BH BX BL + ͹ + EBP BP + ͹ + ESI SI + ͹ + EDI DI + ͹ + ESP SP + ͼ + + + 15 7 0 + ͻ + CS (CODE SEGMENT) + Ķ + SS (STACK SEGMENT) + SEGMENT Ķ + REGISTERS DS (DATA SEGMENT) + Ķ + ES (DATA SEGMENT) + Ķ + FS (DATA SEGMENT) + Ķ + GS (DATA SEGMENT) + ͼ + + + STATUS AND INSTRUCTION REGISTERS + + 31 23 15 7 0 + ͻ + EFLAGS + Ķ + EIP (INSTRUCTION POINTER) + ͼ + + +Figure 2-6. Use of Memory Segmentation + + ͻ ͻ + MODULE MODULE + A Ŀ  A + CODE DATA + ͼ ͻ ͼ + Ķ CS (CODE) + ͹ + ͻ Ķ SS (STACK) ͻ + ͹ DATA + STACK  DS (DATA)  STRUCTURE + ͹ 1 + ͼ ES (DATA) ͼ + ͹ + Ķ FS (DATA) + ͻ ͹ ͻ + DATA GS (DATA) Ŀ DATA + STRUCTURE  ͼ  STRUCTURE + 2 3 + ͼ ͼ + + +2.3.3 Stack Implementation + +Stack operations are facilitated by three registers: + + 1. The stack segment (SS) register. Stacks are implemented in memory. A + system may have a number of stacks that is limited only by the maximum + number of segments. A stack may be up to 4 gigabytes long, the maximum + length of a segment. One stack is directly addressable at a timethe + one located by SS. This is the current stack, often referred to simply + as "the" stack. SS is used automatically by the processor for all + stack operations. + + 2. The stack pointer (ESP) register. ESP points to the top of the + push-down stack (TOS). It is referenced implicitly by PUSH and POP + operations, subroutine calls and returns, and interrupt operations. + When an item is pushed onto the stack (see Figure 2-7), the processor + decrements ESP, then writes the item at the new TOS. When an item is + popped off the stack, the processor copies it from TOS, then + increments ESP. In other words, the stack grows down in memory toward + lesser addresses. + + 3. The stack-frame base pointer (EBP) register. The EBP is the best + choice of register for accessing data structures, variables and + dynamically allocated work space within the stack. EBP is often used + to access elements on the stack relative to a fixed point on the stack + rather than relative to the current TOS. It typically identifies the + base address of the current stack frame established for the current + procedure. When EBP is used as the base register in an offset + calculation, the offset is calculated automatically in the current + stack segment (i.e., the segment currently selected by SS). Because + SS does not have to be explicitly specified, instruction encoding in + such cases is more efficient. EBP can also be used to index into + segments addressable via other segment registers. + + +Figure 2-7. 80386 Stack + + 31 0 + ͻ BOTTOM OF STACK + (INITIAL ESP VALUE) + ͹ + + ͹  + POP + ͹ + + ͹ TOP OF ͻ + Ķ ESP + ͹ STACK ͼ + + + PUSH +  + + +2.3.4 Flags Register + +The flags register is a 32-bit register named EFLAGS. Figure 2-8 defines +the bits within this register. The flags control certain operations and +indicate the status of the 80386. + +The low-order 16 bits of EFLAGS is named FLAGS and can be treated as a +unit. This feature is useful when executing 8086 and 80286 code, because +this part of EFLAGS is identical to the FLAGS register of the 8086 and the +80286. + +The flags may be considered in three groups: the status flags, the control +flags, and the systems flags. Discussion of the systems flags is delayed +until Part II. + + +Figure 2-8. EFLAGS Register + + 16-BIT FLAGS REGISTER + A + Ŀ + 31 23 15 7 0 + ͻ + VR N IOODITSZ A P C + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 + MF T PLFFFFFF F F F + Ѽ + + VIRTUAL 8086 MODEX + RESUME FLAGX + NESTED TASK FLAGX + I/O PRIVILEGE LEVELX + OVERFLOWS + DIRECTION FLAGC + INTERRUPT ENABLEX + TRAP FLAGS + SIGN FLAGS + ZERO FLAGS + AUXILIARY CARRYS + PARITY FLAGS + CARRY FLAGS + + S = STATUS FLAG, C = CONTROL FLAG, X = SYSTEM FLAG + + NOTE: 0 OR 1 INDICATES INTEL RESERVED. DO NOT DEFINE + + +2.3.4.1 Status Flags + +The status flags of the EFLAGS register allow the results of one +instruction to influence later instructions. The arithmetic instructions use +OF, SF, ZF, AF, PF, and CF. The SCAS (Scan String), CMPS (Compare String), +and LOOP instructions use ZF to signal that their operations are complete. +There are instructions to set, clear, and complement CF before execution of +an arithmetic instruction. Refer to Appendix C for definition of each +status flag. + + +2.3.4.2 Control Flag + +The control flag DF of the EFLAGS register controls string instructions. + +DF (Direction Flag, bit 10) + + Setting DF causes string instructions to auto-decrement; that is, to + process strings from high addresses to low addresses. Clearing DF causes + string instructions to auto-increment, or to process strings from low + addresses to high addresses. + + +2.3.4.3 Instruction Pointer + +The instruction pointer register (EIP) contains the offset address, +relative to the start of the current code segment, of the next sequential +instruction to be executed. The instruction pointer is not directly visible +to the programmer; it is controlled implicitly by control-transfer +instructions, interrupts, and exceptions. + +As Figure 2-9 shows, the low-order 16 bits of EIP is named IP and can be +used by the processor as a unit. This feature is useful when executing +instructions designed for the 8086 and 80286 processors. + + +Figure 2-9. Instruction Pointer Register + + 16-BIT IP REGISTER + Ŀ + 31 23 15 7 0 + ͻ + EIP (INSTRUCTION POINTER) + ͼ + + +2.4 Instruction Format + +The information encoded in an 80386 instruction includes a specification of +the operation to be performed, the type of the operands to be manipulated, +and the location of these operands. If an operand is located in memory, the +instruction must also select, explicitly or implicitly, which of the +currently addressable segments contains the operand. + +80386 instructions are composed of various elements and have various +formats. The exact format of instructions is shown in Appendix B; the +elements of instructions are described below. Of these instruction elements, +only one, the opcode, is always present. The other elements may or may not +be present, depending on the particular operation involved and on the +location and type of the operands. The elements of an instruction, in order +of occurrence are as follows: + + Prefixes one or more bytes preceding an instruction that modify the + operation of the instruction. The following types of prefixes can be + used by applications programs: + + 1. Segment override explicitly specifies which segment register an + instruction should use, thereby overriding the default + segment-register selection used by the 80386 for that instruction. + + 2. Address size switches between 32-bit and 16-bit address + generation. + + 3. Operand size switches between 32-bit and 16-bit operands. + + 4. Repeat used with a string instruction to cause the instruction + to act on each element of the string. + + Opcode specifies the operation performed by the instruction. Some + operations have several different opcodes, each specifying a different + variant of the operation. + + Register specifier an instruction may specify one or two register + operands. Register specifiers may occur either in the same byte as the + opcode or in the same byte as the addressing-mode specifier. + + Addressing-mode specifier when present, specifies whether an operand + is a register or memory location; if in memory, specifies whether a + displacement, a base register, an index register, and scaling are to be + used. + + SIB (scale, index, base) byte when the addressing-mode specifier + indicates that an index register will be used to compute the address of + an operand, an SIB byte is included in the instruction to encode the + base register, the index register, and a scaling factor. + + Displacement when the addressing-mode specifier indicates that a + displacement will be used to compute the address of an operand, the + displacement is encoded in the instruction. A displacement is a signed + integer of 32, 16, or eight bits. The eight-bit form is used in the + common case when the displacement is sufficiently small. The processor + extends an eight-bit displacement to 16 or 32 bits, taking into + account the sign. + + Immediate operand when present, directly provides the value of an + operand of the instruction. Immediate operands may be 8, 16, or 32 bits + wide. In cases where an eight-bit immediate operand is combined in some + way with a 16- or 32-bit operand, the processor automatically extends + the size of the eight-bit operand, taking into account the sign. + + +2.5 Operand Selection + +An instruction can act on zero or more operands, which are the data +manipulated by the instruction. An example of a zero-operand instruction is +NOP (no operation). An operand can be in any of these locations: + + In the instruction itself (an immediate operand) + + In a register (EAX, EBX, ECX, EDX, ESI, EDI, ESP, or EBP in the case + of 32-bit operands; AX, BX, CX, DX, SI, DI, SP, or BP in the case of + 16-bit operands; AH, AL, BH, BL, CH, CL, DH, or DL in the case of 8-bit + operands; the segment registers; or the EFLAGS register for flag + operations) + + In memory + + At an I/O port + +Immediate operands and operands in registers can be accessed more rapidly +than operands in memory since memory operands must be fetched from memory. +Register operands are available in the CPU. Immediate operands are also +available in the CPU, because they are prefetched as part of the +instruction. + +Of the instructions that have operands, some specify operands implicitly; +others specify operands explicitly; still others use a combination of +implicit and explicit specification; for example: + +Implicit operand: AAM + + By definition, AAM (ASCII adjust for multiplication) operates on the + contents of the AX register. + +Explicit operand: XCHG EAX, EBX + + The operands to be exchanged are encoded in the instruction after the + opcode. + +Implicit and explicit operands: PUSH COUNTER + + The memory variable COUNTER (the explicit operand) is copied to the top of + the stack (the implicit operand). + +Note that most instructions have implicit operands. All arithmetic +instructions, for example, update the EFLAGS register. + +An 80386 instruction can explicitly reference one or two operands. +Two-operand instructions, such as MOV, ADD, XOR, etc., generally overwrite +one of the two participating operands with the result. A distinction can +thus be made between the source operand (the one unaffected by the +operation) and the destination operand (the one overwritten by the result). + +For most instructions, one of the two explicitly specified operandseither +the source or the destinationcan be either in a register or in memory. +The other operand must be in a register or be an immediate source operand. +Thus, the explicit two-operand instructions of the 80386 permit operations +of the following kinds: + + Register-to-register + Register-to-memory + Memory-to-register + Immediate-to-register + Immediate-to-memory + +Certain string instructions and stack manipulation instructions, however, +transfer data from memory to memory. Both operands of some string +instructions are in memory and are implicitly specified. Push and pop stack +operations allow transfer between memory operands and the memory-based +stack. + + +2.5.1 Immediate Operands + +Certain instructions use data from the instruction itself as one (and +sometimes two) of the operands. Such an operand is called an immediate +operand. The operand may be 32-, 16-, or 8-bits long. For example: + +SHR PATTERN, 2 + +One byte of the instruction holds the value 2, the number of bits by which +to shift the variable PATTERN. + +TEST PATTERN, 0FFFF00FFH + +A doubleword of the instruction holds the mask that is used to test the +variable PATTERN. + + +2.5.2 Register Operands + +Operands may be located in one of the 32-bit general registers (EAX, EBX, +ECX, EDX, ESI, EDI, ESP, or EBP), in one of the 16-bit general registers +(AX, BX, CX, DX, SI, DI, SP, or BP), or in one of the 8-bit general +registers (AH, BH, CH, DH, AL, BL, CL,or DL). + +The 80386 has instructions for referencing the segment registers (CS, DS, +ES, SS, FS, GS). These instructions are used by applications programs only +if systems designers have chosen a segmented memory model. + +The 80386 also has instructions for referring to the flag register. The +flags may be stored on the stack and restored from the stack. Certain +instructions change the commonly modified flags directly in the EFLAGS +register. Other flags that are seldom modified can be modified indirectly +via the flags image in the stack. + + +2.5.3 Memory Operands + +Data-manipulation instructions that address operands in memory must specify +(either directly or indirectly) the segment that contains the operand and +the offset of the operand within the segment. However, for speed and compact +instruction encoding, segment selectors are stored in the high speed segment +registers. Therefore, data-manipulation instructions need to specify only +the desired segment register and an offset in order to address a memory +operand. + +An 80386 data-manipulation instruction that accesses memory uses one of the +following methods for specifying the offset of a memory operand within its +segment: + + 1. Most data-manipulation instructions that access memory contain a byte + that explicitly specifies the addressing method for the operand. A + byte, known as the modR/M byte, follows the opcode and specifies + whether the operand is in a register or in memory. If the operand is + in memory, the address is computed from a segment register and any of + the following values: a base register, an index register, a scaling + factor, a displacement. When an index register is used, the modR/M + byte is also followed by another byte that identifies the index + register and scaling factor. This addressing method is the + mostflexible. + + 2. A few data-manipulation instructions implicitly use specialized + addressing methods: + + For a few short forms of MOV that implicitly use the EAX register, + the offset of the operand is coded as a doubleword in the + instruction. No base register, index register, or scaling factor + are used. + + String operations implicitly address memory via DS:ESI, (MOVS, + CMPS, OUTS, LODS, SCAS) or via ES:EDI (MOVS, CMPS, INS, STOS). + + Stack operations implicitly address operands via SS:ESP + registers; e.g., PUSH, POP, PUSHA, PUSHAD, POPA, POPAD, PUSHF, + PUSHFD, POPF, POPFD, CALL, RET, IRET, IRETD, exceptions, and + interrupts. + + +2.5.3.1 Segment Selection + +Data-manipulation instructions need not explicitly specify which segment +register is used. For all of these instructions, specification of a segment +register is optional. For all memory accesses, if a segment is not +explicitly specified by the instruction, the processor automatically chooses +a segment register according to the rules of Table 2-1. (If systems +designers have chosen a flat model of memory organization, the segment +registers and the rules that the processor uses in choosing them are not +apparent to applications programs.) + +There is a close connection between the kind of memory reference and the +segment in which that operand resides. As a rule, a memory reference implies +the current data segment (i.e., the implicit segment selector is in DS). +However, ESP and EBP are used to access items on the stack; therefore, when +the ESP or EBP register is used as a base register, the current stack +segment is implied (i.e., SS contains the selector). + +Special instruction prefix elements may be used to override the default +segment selection. Segment-override prefixes allow an explicit segment +selection. The 80386 has a segment-override prefix for each of the segment +registers. Only in the following special cases is there an implied segment +selection that a segment prefix cannot override: + + The use of ES for destination strings in string instructions. + The use of SS in stack instructions. + The use of CS for instruction fetches. + + +Table 2-1. Default Segment Register Selection Rules + +Memory Reference Needed Segment Implicit Segment Selection Rule + Register + Used + +Instructions Code (CS) Automatic with instruction prefetch +Stack Stack (SS) All stack pushes and pops. Any + memory reference that uses ESP or + EBP as a base register. +Local Data Data (DS) All data references except when + relative to stack or string + destination. +Destination Strings Extra (ES) Destination of string instructions. + + +2.5.3.2 Effective-Address Computation + +The modR/M byte provides the most flexible of the addressing methods, and +instructions that require a modR/M byte as the second byte of the +instruction are the most common in the 80386 instruction set. For memory +operands defined by modR/M, the offset within the desired segment is +calculated by taking the sum of up to three components: + + A displacement element in the instruction. + + A base register. + + An index register. The index register may be automatically multiplied + by a scaling factor of 2, 4, or 8. + +The offset that results from adding these components is called an effective +address. Each of these components of an effective address may have either a +positive or negative value. If the sum of all the components exceeds 2^(32), +the effective address is truncated to 32 bits.Figure 2-10 illustrates the +full set of possibilities for modR/M addressing. + +The displacement component, because it is encoded in the instruction, is +useful for fixed aspects of addressing; for example: + + Location of simple scalar operands. + Beginning of a statically allocated array. + Offset of an item within a record. + +The base and index components have similar functions. Both utilize the same +set of general registers. Both can be used for aspects of addressing that +are determined dynamically; for example: + + Location of procedure parameters and local variables in stack. + + The beginning of one record among several occurrences of the same + record type or in an array of records. + + The beginning of one dimension of multiple dimension array. + + The beginning of a dynamically allocated array. + +The uses of general registers as base or index components differ in the +following respects: + + ESP cannot be used as an index register. + + When ESP or EBP is used as the base register, the default segment is + the one selected by SS. In all other cases the default segment is DS. + +The scaling factor permits efficient indexing into an array in the common +cases when array elements are 2, 4, or 8 bytes wide. The shifting of the +index register is done by the processor at the time the address is evaluated +with no performance loss. This eliminates the need for a separate shift or +multiply instruction. + +The base, index, and displacement components may be used in any +combination; any of these components may be null. A scale factor can be used +only when an index is also used. Each possible combination is useful for +data structures commonly used by programmers in high-level languages and +assembly languages. Following are possible uses for some of the various +combinations of address components. + +DISPLACEMENT + + The displacement alone indicates the offset of the operand. This + combination is used to directly address a statically allocated scalar + operand. An 8-bit, 16-bit, or 32-bit displacement can be used. + +BASE + + The offset of the operand is specified indirectly in one of the general + registers, as for "based" variables. + +BASE + DISPLACEMENT + + A register and a displacement can be used together for two distinct + purposes: + + 1. Index into static array when element size is not 2, 4, or 8 bytes. + The displacement component encodes the offset of the beginning of + the array. The register holds the results of a calculation to + determine the offset of a specific element within the array. + + 2. Access item of a record. The displacement component locates an + item within record. The base register selects one of several + occurrences of record, thereby providing a compact encoding for + this common function. + + An important special case of this combination, is to access parameters + in the procedure activation record in the stack. In this case, EBP is + the best choice for the base register, because when EBP is used as a + base register, the processor automatically uses the stack segment + register (SS) to locate the operand, thereby providing a compact + encoding for this common function. + +(INDEX * SCALE) + DISPLACEMENT + + This combination provides efficient indexing into a static array when + the element size is 2, 4, or 8 bytes. The displacement addresses the + beginning of the array, the index register holds the subscript of the + desired array element, and the processor automatically converts the + subscript into an index by applying the scaling factor. + +BASE + INDEX + DISPLACEMENT + + Two registers used together support either a two-dimensional array (the + displacement determining the beginning of the array) or one of several + instances of an array of records (the displacement indicating an item + in the record). + +BASE + (INDEX * SCALE) + DISPLACEMENT + + This combination provides efficient indexing of a two-dimensional array + when the elements of the array are 2, 4, or 8 bytes wide. + + +Figure 2-10. Effective Address Computation + + SEGMENT + BASE + (INDEX * SCALE) + DISPLACEMENT + + + --- + EAX EAX 1 + CS ECX ECX + SS EDX EDX 2 NO DISPLACEMENT + Ĵ DS + Ĵ EBX + Ĵ EBX * Ĵ + Ĵ 8-BIT DISPLACEMENT + ES ESP --- 4 32-BIT DISPLACEMENT + FS EBP EBP + GS ESI ESI 6 + EDI EDI + + + +2.6 Interrupts and Exceptions + +The 80386 has two mechanisms for interrupting program execution: + + 1. Exceptions are synchronous events that are the responses of the CPU + to certain conditions detected during the execution of an instruction. + + 2. Interrupts are asynchronous events typically triggered by external + devices needing attention. + +Interrupts and exceptions are alike in that both cause the processor to +temporarily suspend its present program execution in order to execute a +program of higher priority. The major distinction between these two kinds of +interrupts is their origin. An exception is always reproducible by +re-executing with the program and data that caused the exception, whereas an +interrupt is generally independent of the currently executing program. + +Application programmers are not normally concerned with servicing +interrupts. More information on interrupts for systems programmers may be +found in Chapter 9. Certain exceptions, however, are of interest to +applications programmers, and many operating systems give applications +programs the opportunity to service these exceptions. However, the operating +system itself defines the interface between the applications programs and +the exception mechanism of the 80386. + +Table 2-2 highlights the exceptions that may be of interest to applications +programmers. + + A divide error exception results when the instruction DIV or IDIV is + executed with a zero denominator or when the quotient is too large for + the destination operand. (Refer to Chapter 3 for a discussion of DIV + and IDIV.) + + The debug exception may be reflected back to an applications program + if it results from the trap flag (TF). + + A breakpoint exception results when the instruction INT 3 is executed. + This instruction is used by some debuggers to stop program execution at + specific points. + + An overflow exception results when the INTO instruction is executed + and the OF (overflow) flag is set (after an arithmetic operation that + set the OF flag). (Refer to Chapter 3 for a discussion of INTO). + + A bounds check exception results when the BOUND instruction is + executed and the array index it checks falls outside the bounds of the + array. (Refer to Chapter 3 for a discussion of the BOUND instruction.) + + Invalid opcodes may be used by some applications to extend the + instruction set. In such a case, the invalid opcode exception presents + an opportunity to emulate the opcode. + + The "coprocessor not available" exception occurs if the program + contains instructions for a coprocessor, but no coprocessor is present + in the system. + + A coprocessor error is generated when a coprocessor detects an illegal + operation. + +The instruction INT generates an interrupt whenever it is executed; the +processor treats this interrupt as an exception. The effects of this +interrupt (and the effects of all other exceptions) are determined by +exception handler routines provided by the application program or as part of +the systems software (provided by systems programmers). The INT instruction +itself is discussed in Chapter 3. Refer to Chapter 9 for a more complete +description of exceptions. + + +Table 2-2. 80386 Reserved Exceptions and Interrupts + +Vector Number Description + +0 Divide Error +1 Debug Exceptions +2 NMI Interrupt +3 Breakpoint +4 INTO Detected Overflow +5 BOUND Range Exceeded +6 Invalid Opcode +7 Coprocessor Not Available +8 Double Exception +9 Coprocessor Segment Overrun +10 Invalid Task State Segment +11 Segment Not Present +12 Stack Fault +13 General Protection +14 Page Fault +15 (reserved) +16 Coprocessor Error +17-32 (reserved) + + +Chapter 3 Applications Instruction Set + + + +This chapter presents an overview of the instructions which programmers can +use to write application software for the 80386 executing in protected +virtual-address mode. The instructions are grouped by categories of related +functions. + +The instructions not discussed in this chapter are those that are normally +used only by operating-system programmers. Part II describes the operation +of these instructions. + +The descriptions in this chapter assume that the 80386 is operating in +protected mode with 32-bit addressing in effect; however, all instructions +discussed are also available when 16-bit addressing is in effect in +protected mode, real mode, or virtual 8086 mode. For any differences of +operation that exist in the various modes, refer to Chapter 13, +Chapter 14, or Chapter 15. + +The instruction dictionary in Chapter 17 contains more detailed +descriptions of all instructions, including encoding, operation, timing, +effect on flags, and exceptions. + + +3.1 Data Movement Instructions + +These instructions provide convenient methods for moving bytes, words, or +doublewords of data between memory and the registers of the base +architecture. They fall into the following classes: + + 1. General-purpose data movement instructions. + 2. Stack manipulation instructions. + 3. Type-conversion instructions. + + +3.1.1 General-Purpose Data Movement Instructions + +MOV (Move) transfers a byte, word, or doubleword from the source operand to +the destination operand. The MOV instruction is useful for transferring data +along any of these paths +There are also variants of MOV that operate on segment registers. These +are covered in a later section of this chapter.: + + To a register from memory + To memory from a register + Between general registers + Immediate data to a register + Immediate data to a memory + +The MOV instruction cannot move from memory to memory or from segment +register to segment register are not allowed. Memory-to-memory moves can be +performed, however, by the string move instruction MOVS. + +XCHG (Exchange) swaps the contents of two operands. This instruction takes +the place of three MOV instructions. It does not require a temporary +location to save the contents of one operand while load the other is being +loaded. XCHG is especially useful for implementing semaphores or similar +data structures for process synchronization. + +The XCHG instruction can swap two byte operands, two word operands, or two +doubleword operands. The operands for the XCHG instruction may be two +register operands, or a register operand with a memory operand. When used +with a memory operand, XCHG automatically activates the LOCK signal. (Refer +to Chapter 11 for more information on the bus lock.) + + +3.1.2 Stack Manipulation Instructions + +PUSH (Push) decrements the stack pointer (ESP), then transfers the source +operand to the top of stack indicated by ESP (see Figure 3-1). PUSH is +often used to place parameters on the stack before calling a procedure; it +is also the basic means of storing temporary variables on the stack. The +PUSH instruction operates on memory operands, immediate operands, and +register operands (including segment registers). + +PUSHA (Push All Registers) saves the contents of the eight general +registers on the stack (see Figure 3-2). This instruction simplifies +procedure calls by reducing the number of instructions required to retain +the contents of the general registers for use in a procedure. The processor +pushes the general registers on the stack in the following order: EAX, ECX, +EDX, EBX, the initial value of ESP before EAX was pushed, EBP, ESI, and +EDI. PUSHA is complemented by the POPA instruction. + +POP (Pop) transfers the word or doubleword at the current top of stack +(indicated by ESP) to the destination operand, and then increments ESP to +point to the new top of stack. See Figure 3-3. POP moves information from +the stack to a general register, or to memory +There are also a variant of POP that operates on segment registers. This +is covered in a later section of this chapter.. + +POPA (Pop All Registers) restores the registers saved on the stack by +PUSHA, except that it ignores the saved value of ESP. See Figure 3-4. + + +Figure 3-1. PUSH + + D O BEFORE PUSH AFTER PUSH + I F  31 0   31 0  + R + E E ͹ ͹ + C X + T P ͹ ͹ + I A + O N ͹ESP ͹ + N S OPERAND + I ͹ ͹ESP + O + N ͹ ͹ + +  ͹ ͹ + +     + + +Figure 3-2. PUSHA + + BEFORE PUSHA AFTER PUSHA +  31 0   31 0  + D O + I F ͹ ͹ + R + E E ͹ ͹ + C X + T P ͹ESP ͹ + I A EAX + O N ͹ ͹ + N S ECX + I ͹ ͹ + O EDX + N ͹ ͹ + EBX +  ͹ ͹ + OLD ESP + ͹ ͹ + EBP + ͹ ͹ + ESI + ͹ ͹ + EDI + ͹ ͹ESP + + ͹ ͹ + +     + + +3.1.3 Type Conversion Instructions + +The type conversion instructions convert bytes into words, words into +doublewords, and doublewords into 64-bit items (quad-words). These +instructions are especially useful for converting signed integers, because +they automatically fill the extra bits of the larger item with the value of +the sign bit of the smaller item. This kind of conversion, illustrated by +Figure 3-5, is called sign extension. + +There are two classes of type conversion instructions: + + 1. The forms CWD, CDQ, CBW, and CWDE which operate only on data in the + EAX register. + + 2. The forms MOVSX and MOVZX, which permit one operand to be in any + general register while permitting the other operand to be in memory or + in a register. + +CWD (Convert Word to Doubleword) and CDQ (Convert Doubleword to Quad-Word) +double the size of the source operand. CWD extends the sign of the +word in register AX throughout register DX. CDQ extends the sign of the +doubleword in EAX throughout EDX. CWD can be used to produce a doubleword +dividend from a word before a word division, and CDQ can be used to produce +a quad-word dividend from a doubleword before doubleword division. + +CBW (Convert Byte to Word) extends the sign of the byte in register AL +throughout AX. + +CWDE (Convert Word to Doubleword Extended) extends the sign of the word in +register AX throughout EAX. + +MOVSX (Move with Sign Extension) sign-extends an 8-bit value to a 16-bit +value and a 8- or 16-bit value to 32-bit value. + +MOVZX (Move with Zero Extension) extends an 8-bit value to a 16-bit value +and an 8- or 16-bit value to 32-bit value by inserting high-order zeros. + + +Figure 3-3. POP + + D O BEFORE POP AFTER POP + I F  31 0   31 0  + R + E E ͹ ͹ + C X + T P ͹ ͹ + I A + O N ͹ ͹ESP + N S OPERAND + I ͹ESP ͹ + O + N ͹ ͹ + +  ͹ ͹ + +     + + +Figure 3-4. POPA + + BEFORE POPA AFTER POPA +  31 0   31 0  + D O + I F ͹ ͹ + R + E E ͹ ͹ + C X + T P ͹ ͹ESP + I A EAX + O N ͹ ͹ + N S ECX + I ͹ ͹ + O EDX + N ͹ ͹ + EBX +  ͹ ͹ + ESP + ͹ ͹ + EPB + ͹ ͹ + ESI + ͹ ͹ + EDI + ͹ESP ͹ + + ͹ ͹ + +     + + +Figure 3-5. Sign Extension + + 15 7 0 + ͻ + BEFORE SIGN EXTENSIONS N N N N N N N N N N N N N N N + ͼ + AFTER SIGN EXTENSIONĿ + + 31 23  15 7 0 + ͻ + SS S S S S S S S S S S S S S S S N N N N N N N N N N N N N N N + ͼ + + +3.2 Binary Arithmetic Instructions + +The arithmetic instructions of the 80386 processor simplify the +manipulation of numeric data that is encoded in binary. Operations include +the standard add, subtract, multiply, and divide as well as increment, +decrement, compare, and change sign. Both signed and unsigned binary +integers are supported. The binary arithmetic instructions may also be used +as one step in the process of performing arithmetic on decimal integers. + +Many of the arithmetic instructions operate on both signed and unsigned +integers. These instructions update the flags ZF, CF, SF, and OF in such a +manner that subsequent instructions can interpret the results of the +arithmetic as either signed or unsigned. CF contains information relevant to +unsigned integers; SF and OF contain information relevant to signed +integers. ZF is relevant to both signed and unsigned integers; ZF is set +when all bits of the result are zero. + +If the integer is unsigned, CF may be tested after one of these arithmetic +operations to determine whether the operation required a carry or borrow of +a one-bit in the high-order position of the destination operand. CF is set +if a one-bit was carried out of the high-order position (addition +instructions ADD, ADC, AAA, and DAA) or if a one-bit was carried (i.e. +borrowed) into the high-order bit (subtraction instructions SUB, SBB, AAS, +DAS, CMP, and NEG). + +If the integer is signed, both SF and OF should be tested. SF always has +the same value as the sign bit of the result. The most significant bit (MSB) +of a signed integer is the bit next to the signbit 6 of a byte, bit 14 of +a word, or bit 30 of a doubleword. OF is set in either of these cases: + + A one-bit was carried out of the MSB into the sign bit but no one bit + was carried out of the sign bit (addition instructions ADD, ADC, INC, + AAA, and DAA). In other words, the result was greater than the greatest + positive number that could be contained in the destination operand. + + A one-bit was carried from the sign bit into the MSB but no one bit + was carried into the sign bit (subtraction instructions SUB, SBB, DEC, + AAS, DAS, CMP, and NEG). In other words, the result was smaller that + the smallest negative number that could be contained in the destination + operand. + +These status flags are tested by executing one of the two families of +conditional instructions: Jcc (jump on condition cc) or SETcc (byte set on +condition). + + +3.2.1 Addition and Subtraction Instructions + +ADD (Add Integers) replaces the destination operand with the sum of the +source and destination operands. Sets CF if overflow. + +ADC (Add Integers with Carry) sums the operands, adds one if CF is set, and +replaces the destination operand with the result. If CF is cleared, ADC +performs the same operation as the ADD instruction. An ADD followed by +multiple ADC instructions can be used to add numbers longer than 32 bits. + +INC (Increment) adds one to the destination operand. INC does not affect +CF. Use ADD with an immediate value of 1 if an increment that updates carry +(CF) is needed. + +SUB (Subtract Integers) subtracts the source operand from the destination +operand and replaces the destination operand with the result. If a borrow is +required, the CF is set. The operands may be signed or unsigned bytes, +words, or doublewords. + +SBB (Subtract Integers with Borrow) subtracts the source operand from the +destination operand, subtracts 1 if CF is set, and returns the result to the +destination operand. If CF is cleared, SBB performs the same operation as +SUB. SUB followed by multiple SBB instructions may be used to subtract +numbers longer than 32 bits. If CF is cleared, SBB performs the same +operation as SUB. + +DEC (Decrement) subtracts 1 from the destination operand. DEC does not +update CF. Use SUB with an immediate value of 1 to perform a decrement that +affects carry. + + +3.2.2 Comparison and Sign Change Instruction + +CMP (Compare) subtracts the source operand from the destination operand. It +updates OF, SF, ZF, AF, PF, and CF but does not alter the source and +destination operands. A subsequent Jcc or SETcc instruction can test the +appropriate flags. + +NEG (Negate) subtracts a signed integer operand from zero. The effect of +NEG is to reverse the sign of the operand from positive to negative or from +negative to positive. + + +3.2.3 Multiplication Instructions + +The 80386 has separate multiply instructions for unsigned and signed +operands. MUL operates on unsigned numbers, while IMUL operates on signed +integers as well as unsigned. + +MUL (Unsigned Integer Multiply) performs an unsigned multiplication of the +source operand and the accumulator. If the source is a byte, the processor +multiplies it by the contents of AL and returns the double-length result to +AH and AL. If the source operand is a word, the processor multiplies it by +the contents of AX and returns the double-length result to DX and AX. If the +source operand is a doubleword, the processor multiplies it by the contents +of EAX and returns the 64-bit result in EDX and EAX. MUL sets CF and OF +when the upper half of the result is nonzero; otherwise, they are cleared. + +IMUL (Signed Integer Multiply) performs a signed multiplication operation. +IMUL has three variations: + + 1. A one-operand form. The operand may be a byte, word, or doubleword + located in memory or in a general register. This instruction uses EAX + and EDX as implicit operands in the same way as the MUL instruction. + + 2. A two-operand form. One of the source operands may be in any general + register while the other may be either in memory or in a general + register. The product replaces the general-register operand. + + 3. A three-operand form; two are source and one is the destination + operand. One of the source operands is an immediate value stored in + the instruction; the second may be in memory or in any general + register. The product may be stored in any general register. The + immediate operand is treated as signed. If the immediate operand is a + byte, the processor automatically sign-extends it to the size of the + second operand before performing the multiplication. + +The three forms are similar in most respects: + + The length of the product is calculated to twice the length of the + operands. + + The CF and OF flags are set when significant bits are carried into the + high-order half of the result. CF and OF are cleared when the + high-order half of the result is the sign-extension of the low-order + half. + +However, forms 2 and 3 differ in that the product is truncated to the +length of the operands before it is stored in the destination register. +Because of this truncation, OF should be tested to ensure that no +significant bits are lost. (For ways to test OF, refer to the INTO and PUSHF +instructions.) + +Forms 2 and 3 of IMUL may also be used with unsigned operands because, +whether the operands are signed or unsigned, the low-order half of the +product is the same. + + +3.2.4 Division Instructions + +The 80386 has separate division instructions for unsigned and signed +operands. DIV operates on unsigned numbers, while IDIV operates on signed +integers as well as unsigned. In either case, an exception (interrupt zero) +occurs if the divisor is zero or if the quotient is too large for AL, AX, or +EAX. + +DIV (Unsigned Integer Divide) performs an unsigned division of the +accumulator by the source operand. The dividend (the accumulator) is twice +the size of the divisor (the source operand); the quotient and remainder +have the same size as the divisor, as the following table shows. + +Size of Source Operand + (divisor) Dividend Quotient Remainder + +Byte AX AL AH +Word DX:AX AX DX +Doubleword EDX:EAX EAX EDX + +Non-integral quotients are truncated to integers toward 0. The remainder is +always less than the divisor. For unsigned byte division, the largest +quotient is 255. For unsigned word division, the largest quotient is 65,535. +For unsigned doubleword division the largest quotient is 2^(32) -1. + +IDIV (Signed Integer Divide) performs a signed division of the accumulator +by the source operand. IDIV uses the same registers as the DIV instruction. + +For signed byte division, the maximum positive quotient is +127, and the +minimum negative quotient is -128. For signed word division, the maximum +positive quotient is +32,767, and the minimum negative quotient is -32,768. +For signed doubleword division the maximum positive quotient is 2^(31) -1, +the minimum negative quotient is -2^(31). Non-integral results are truncated +towards 0. The remainder always has the same sign as the dividend and is +less than the divisor in magnitude. + + +3.3 Decimal Arithmetic Instructions + +Decimal arithmetic is performed by combining the binary arithmetic +instructions (already discussed in the prior section) with the decimal +arithmetic instructions. The decimal arithmetic instructions are used in one +of the following ways: + + To adjust the results of a previous binary arithmetic operation to + produce a valid packed or unpacked decimal result. + + To adjust the inputs to a subsequent binary arithmetic operation so + that the operation will produce a valid packed or unpacked decimal + result. + +These instructions operate only on the AL or AH registers. Most utilize the +AF flag. + + +3.3.1 Packed BCD Adjustment Instructions + +DAA (Decimal Adjust after Addition) adjusts the result of adding two valid +packed decimal operands in AL. DAA must always follow the addition of two +pairs of packed decimal numbers (one digit in each half-byte) to obtain a +pair of valid packed decimal digits as results. The carry flag is set if +carry was needed. + +DAS (Decimal Adjust after Subtraction) adjusts the result of subtracting +two valid packed decimal operands in AL. DAS must always follow the +subtraction of one pair of packed decimal numbers (one digit in each half- +byte) from another to obtain a pair of valid packed decimal digits as +results. The carry flag is set if a borrow was needed. + + +3.3.2 Unpacked BCD Adjustment Instructions + +AAA (ASCII Adjust after Addition) changes the contents of register AL to a +valid unpacked decimal number, and zeros the top 4 bits. AAA must always +follow the addition of two unpacked decimal operands in AL. The carry flag +is set and AH is incremented if a carry is necessary. + +AAS (ASCII Adjust after Subtraction) changes the contents of register AL to +a valid unpacked decimal number, and zeros the top 4 bits. AAS must always +follow the subtraction of one unpacked decimal operand from another in AL. +The carry flag is set and AH decremented if a borrow is necessary. + +AAM (ASCII Adjust after Multiplication) corrects the result of a +multiplication of two valid unpacked decimal numbers. AAM must always follow +the multiplication of two decimal numbers to produce a valid decimal result. +The high order digit is left in AH, the low order digit in AL. + +AAD (ASCII Adjust before Division) modifies the numerator in AH and AL to +prepare for the division of two valid unpacked decimal operands so that the +quotient produced by the division will be a valid unpacked decimal number. +AH should contain the high-order digit and AL the low-order digit. This +instruction adjusts the value and places the result in AL. AH will contain +zero. + + +3.4 Logical Instructions + +The group of logical instructions includes: + + The Boolean operation instructions + Bit test and modify instructions + Bit scan instructions + Rotate and shift instructions + Byte set on condition + + +3.4.1 Boolean Operation Instructions + +The logical operations are AND, OR, XOR, and NOT. + +NOT (Not) inverts the bits in the specified operand to form a one's +complement of the operand. The NOT instruction is a unary operation that +uses a single operand in a register or memory. NOT has no effect on the +flags. + +The AND, OR, and XOR instructions perform the standard logical operations +"and", "(inclusive) or", and "exclusive or". These instructions can use the +following combinations of operands: + + Two register operands + + A general register operand with a memory operand + + An immediate operand with either a general register operand or a + memory operand. + +AND, OR, and XOR clear OF and CF, leave AF undefined, and update SF, ZF, +and PF. + + +3.4.2 Bit Test and Modify Instructions + +This group of instructions operates on a single bit which can be in memory +or in a general register. The location of the bit is specified as an offset +from the low-order end of the operand. The value of the offset either may be +given by an immediate byte in the instruction or may be contained in a +general register. + +These instructions first assign the value of the selected bit to CF, the +carry flag. Then a new value is assigned to the selected bit, as determined +by the operation. OF, SF, ZF, AF, PF are left in an undefined state. Table +3-1 defines these instructions. + + +Table 3-1. Bit Test and Modify Instructions + +Instruction Effect on CF Effect on + Selected Bit + +Bit (Bit Test) CF  BIT (none) +BTS (Bit Test and Set) CF  BIT BIT  1 +BTR (Bit Test and Reset) CF  BIT BIT  0 +BTC (Bit Test and Complement) CF  BIT BIT  NOT(BIT) + + +3.4.3 Bit Scan Instructions + +These instructions scan a word or doubleword for a one-bit and store the +index of the first set bit into a register. The bit string being scanned +may be either in a register or in memory. The ZF flag is set if the entire +word is zero (no set bits are found); ZF is cleared if a one-bit is found. +If no set bit is found, the value of the destination register is undefined. + +BSF (Bit Scan Forward) scans from low-order to high-order (starting from +bit index zero). + +BSR (Bit Scan Reverse) scans from high-order to low-order (starting from +bit index 15 of a word or index 31 of a doubleword). + + +3.4.4 Shift and Rotate Instructions + +The shift and rotate instructions reposition the bits within the specified +operand. + +These instructions fall into the following classes: + + Shift instructions + Double shift instructions + Rotate instructions + + +3.4.4.1 Shift Instructions + +The bits in bytes, words, and doublewords may be shifted arithmetically or +logically. Depending on the value of a specified count, bits can be shifted +up to 31 places. + +A shift instruction can specify the count in one of three ways. One form of +shift instruction implicitly specifies the count as a single shift. The +second form specifies the count as an immediate value. The third form +specifies the count as the value contained in CL. This last form allows the +shift count to be a variable that the program supplies during execution. +Only the low order 5 bits of CL are used. + +CF always contains the value of the last bit shifted out of the destination +operand. In a single-bit shift, OF is set if the value of the high-order +(sign) bit was changed by the operation. Otherwise, OF is cleared. Following +a multibit shift, however, the content of OF is always undefined. + +The shift instructions provide a convenient way to accomplish division or +multiplication by binary power. Note however that division of signed numbers +by shifting right is not the same kind of division performed by the IDIV +instruction. + +SAL (Shift Arithmetic Left) shifts the destination byte, word, or +doubleword operand left by one or by the number of bits specified in the +count operand (an immediate value or the value contained in CL). The +processor shifts zeros in from the right (low-order) side of the operand as +bits exit from the left (high-order) side. See Figure 3-6. + +SHL (Shift Logical Left) is a synonym for SAL (refer to SAL). + +SHR (Shift Logical Right) shifts the destination byte, word, or doubleword +operand right by one or by the number of bits specified in the count operand +(an immediate value or the value contained in CL). The processor shifts +zeros in from the left side of the operand as bits exit from the right side. +See Figure 3-7. + +SAR (Shift Arithmetic Right) shifts the destination byte, word, or +doubleword operand to the right by one or by the number of bits specified in +the count operand (an immediate value or the value contained in CL). The +processor preserves the sign of the operand by shifting in zeros on the left +(high-order) side if the value is positive or by shifting by ones if the +value is negative. See Figure 3-8. + +Even though this instruction can be used to divide integers by a power of +two, the type of division is not the same as that produced by the IDIV +instruction. The quotient of IDIV is rounded toward zero, whereas the +"quotient" of SAR is rounded toward negative infinity. This difference is +apparent only for negative numbers. For example, when IDIV is used to divide +-9 by 4, the result is -2 with a remainder of -1. If SAR is used to shift +-9 right by two bits, the result is -3. The "remainder" of this kind of +division is +3; however, the SAR instruction stores only the high-order bit +of the remainder (in CF). + +The code sequence in Figure 3-9 produces the same result as IDIV for any M += 2^(N), where 0 < N < 32. This sequence takes about 12 to 18 clocks, +depending on whether the jump is taken; if ECX contains M, the corresponding +IDIV ECX instruction will take about 43 clocks. + + +Figure 3-6. SAL and SHL + + OF CF OPERAND + + BEFORE SHL X X 10001000100010001000100010001111 + OR SAL + + AFTER SHL 1 1  00010001000100010001000100011110  0 + OR SAL BY 1 + + AFTER SHL X 0  00100010001000100011110000000000  0 + OR SAL BY 10 + +SHL (WHICH HAS THE SYNONYM SAL) SHIFTS THE BITS IN THE REGISTER OR MEMORY +OPERAND TO THE LEFT BY THE SPECIFIED NUMBER OF BIT POSITIONS. CF RECEIVES +THE LAST BIT SHIFTED OUT OF THE LEFT OF THE OPERAND. SHL SHIFTS IN ZEROS +TO FILL THE VACATED BIT LOCATIONS. THESE INSTRUCTIONS OPERATE ON BYTE, +WORD, AND DOUBLEWORD OPERANDS. + + +Figure 3-7. SHR + + OPERAND CF + + BEFORE SHR 10001000100010001000100010001111 X + + AFTER SHR 0010001000100010001000100010001111 + BY 1 + + AFTER SHR 000000000001000100010001000100010O + BY 10 + +SHR SHIFTS THE BITS OF THE REGISTER OR MEMORY OPERAND TO THE RIGHT BY THE +SPECIFIED NUMBER OF BIT POSITIONS. CF RECEIVES THE LAST BIT SHIFTED OUT OF +THE RIGHT OF THE OPERAND. SHR SHIFTS IN ZEROS TO FILL THE VACATED BIT +LOCATIONS. + + +Figure 3-8. SAR + + POSITIVE OPERAND CF + + BEFORE SAR 01000100010001000100010001000111 X + + AFTER SAR 0001000100010001000100010001000111 + BY 1 + + NEGATIVE OPERAND CF + + BEFORE SAR 11000100010001000100010001000111 X + + AFTER SAR 0111000100010001000100010001000111 + BY 1 + +SAR PRESERVES THE SIGN OF THE REGISTER OR MEMORY OPERAND AS IT SHIFTS THE +OPERAND TO THE RIGHT BY THE SPECIFIED NUMBER OF BIT POSITIONS. CF RECIEVES +THE LAST BIT SHIFTED OUT OF THE RIGHT OF THE OPERAND. + + +Figure 3-9. Using SAR to Simulate IDIV + + ; assuming N is in ECX, and the dividend is in EAX + ; CLOCKS + CMP EAX, 0 ; to set sign flag 2 + JGE NoAdjust ; jump if sign is zero 3 or 9 + ADD EAX, ECX ; 2 + DEC EAX ; EAX := EAX + (N-1) 2 +NoAdjust: + SAR EAX, CL ; 3 + ; TOTAL CLOCKS 12 or 18] + + +3.4.4.2 Double-Shift Instructions + +These instructions provide the basic operations needed to implement +operations on long unaligned bit strings. The double shifts operate either +on word or doubleword operands, as follows: + + 1. Taking two word operands as input and producing a one-word output. + + 2. Taking two doubleword operands as input and producing a doubleword + output. + +Of the two input operands, one may either be in a general register or in +memory, while the other may only be in a general register. The results +replace the memory or register operand. The number of bits to be shifted is +specified either in the CL register or in an immediate byte of the +instruction. + +Bits are shifted from the register operand into the memory or register +operand. CF is set to the value of the last bit shifted out of the +destination operand. SF, ZF, and PF are set according to the value of the +result. OF and AF are left undefined. + +SHLD (Shift Left Double) shifts bits of the R/M field to the left, while +shifting high-order bits from the Reg field into the R/M field on the right +(see Figure 3-10). The result is stored back into the R/M operand. The Reg +field is not modified. + +SHRD (Shift Right Double) shifts bits of the R/M field to the right, while +shifting low-order bits from the Reg field into the R/M field on the left +(see Figure 3-11). The result is stored back into the R/M operand. The Reg +field is not modified. + + +3.4.4.3 Rotate Instructions + +Rotate instructions allow bits in bytes, words, and doublewords to be +rotated. Bits rotated out of an operand are not lost as in a shift, but are +"circled" back into the other "end" of the operand. + +Rotates affect only the carry and overflow flags. CF may act as an +extension of the operand in two of the rotate instructions, allowing a bit +to be isolated and then tested by a conditional jump instruction (JC or +JNC). CF always contains the value of the last bit rotated out, even if the +instruction does not use this bit as an extension of the rotated operand. + +In single-bit rotates, OF is set if the operation changes the high-order +(sign) bit of the destination operand. If the sign bit retains its original +value, OF is cleared. On multibit rotates, the value of OF is always +undefined. + +ROL (Rotate Left) rotates the byte, word, or doubleword destination operand +left by one or by the number of bits specified in the count operand (an +immediate value or the value contained in CL). For each rotation specified, +the high-order bit that exits from the left of the operand returns at the +right to become the new low-order bit of the operand. See Figure 3-12. + +ROR (Rotate Right) rotates the byte, word, or doubleword destination +operand right by one or by the number of bits specified in the count operand +(an immediate value or the value contained in CL). For each rotation +specified, the low-order bit that exits from the right of the operand +returns at the left to become the new high-order bit of the operand. +See Figure 3-13. + +RCL (Rotate Through Carry Left) rotates bits in the byte, word, or +doubleword destination operand left by one or by the number of bits +specified in the count operand (an immediate value or the value contained in +CL). + +This instruction differs from ROL in that it treats CF as a high-order +one-bit extension of the destination operand. Each high-order bit that exits +from the left side of the operand moves to CF before it returns to the +operand as the low-order bit on the next rotation cycle. See Figure 3-14. + +RCR (Rotate Through Carry Right) rotates bits in the byte, word, or +doubleword destination operand right by one or by the number of bits +specified in the count operand (an immediate value or the value contained in +CL). + +This instruction differs from ROR in that it treats CF as a low-order +one-bit extension of the destination operand. Each low-order bit that exits +from the right side of the operand moves to CF before it returns to the +operand as the high-order bit on the next rotation cycle. See Figure 3-15. + + +Figure 3-10. Shift Left Double + + 31 DESTINATION 0 + ͻ ͻ + CF Ķ MEMORY OF REGISTER Ŀ + ͼ ͼ + + 31 SOURCE 0 + ͻ + Ķ REGISTER + ͼ + + +Figure 3-11. Shift Right Double + + 31 SOURCE 0 + ͻ + REGISTER Ŀ + ͼ + + 31 DESTINATION 0 + ͻ ͻ +  MEMORY OF REGISTER  CF + ͼ ͼ + + +Figure 3-12. ROL + + 31 DESTINATION 0 + ͻ ͻ + CF Ķ MEMORY OF REGISTER Ŀ + ͼ ͼ + + + +Figure 3-13. ROR + + Ŀ + 31 DESTINATION 0 + ͻ ͻ +  MEMORY OF REGISTER  CF + ͼ ͼ + + +Figure 3-14. RCL + + 31 DESTINATION 0 + ͻ ͻ + Ķ CF Ķ MEMORY OF REGISTER Ŀ + ͼ ͼ + + + +Figure 3-15. RCR + + Ŀ + 31 DESTINATION 0 + ͻ ͻ +  MEMORY OF REGISTER  CF + ͼ ͼ + + +3.4.4.4 Fast "BIT BLT" Using Double Shift Instructions + +One purpose of the double shifts is to implement a bit string move, with +arbitrary misalignment of the bit strings. This is called a "bit blt" (BIT +BLock Transfer.) A simple example is to move a bit string from an arbitrary +offset into a doubleword-aligned byte string. A left-to-right string is +moved 32 bits at a time if a double shift is used inside the move loop. + + MOV ESI,ScrAddr + MOV EDI,DestAddr + MOV EBX,WordCnt + MOV CL,RelOffset ; relative offset Dest-Src + MOV EDX,[ESI] ; load first word of source + ADD ESI,4 ; bump source address +BltLoop: + LODS ; new low order part + SHLD EDX,EAX,CL ; EDX overwritten with aligned stuff + XCHG EDX,EAS ; Swap high/low order parts + STOS ; Write out next aligned chunk + DEC EBX + JA BltLoop + +This loop is simple yet allows the data to be moved in 32-bit pieces for +the highest possible performance. Without a double shift, the best that can +be achieved is 16 bits per loop iteration by using a 32-bit shift and +replacing the XCHG with a ROR by 16 to swap high and low order parts of +registers. A more general loop than shown above would require some extra +masking on the first doubleword moved (before the main loop), and on the +last doubleword moved (after the main loop), but would have the same basic +32-bits per loop iteration as the code above. + + +3.4.4.5 Fast Bit-String Insert and Extract + +The double shift instructions also enable: + + Fast insertion of a bit string from a register into an arbitrary bit + location in a larger bit string in memory without disturbing the bits + on either side of the inserted bits. + + Fast extraction of a bits string into a register from an arbitrary bit + location in a larger bit string in memory without disturbing the bits + on either side of the extracted bits. + +The following coded examples illustrate bit insertion and extraction under +variousconditions: + + 1. Bit String Insert into Memory (when bit string is 1-25 bits long, + i.e., spans four bytes or less): + + ; Insert a right-justified bit string from register into + ; memory bit string. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate value + ; but the bit offset is held in a register. + ; + ; Register ESI holds the right-justified bit string + ; to be inserted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX and ECX are also used by this + ; "insert" operation. + ; + MOV ECX,EDI ; preserve original offset for later use + SHR EDI,3 ; signed divide offset by 8 (byte address) + AND CL,7H ; isolate low three bits of offset in CL + MOV EAX,[EDI]strg_base ; move string dword into EAX + ROR EAX,CL ; right justify old bit field + SHRD EAX,ESI,length ; bring in new bits + ROL EAX,length ; right justify new bit field + ROL EAX,CL ; bring to final position + MOV [EDI]strg_base,EAX ; replace dword in memory + + 2. Bit String Insert into Memory (when bit string is 1-31 bits long, i.e. + spans five bytes or less): + + ; Insert a right-justified bit string from register into + ; memory bit string. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate value + ; but the bit offset is held in a register. + ; + ; Register ESI holds the right-justified bit string + ; to be inserted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX, EBX, ECX, and EDI are also used by + ; this "insert" operation. + ; + MOV ECX,EDI ; temp storage for offset + SHR EDI,5 ; signed divide offset by 32 (dword address) + SHL EDI,2 ; multiply by 4 (in byte address format) + AND CL,1FH ; isolate low five bits of offset in CL + MOV EAX,[EDI]strg_base ; move low string dword into EAX + MOV EDX,[EDI]strg_base+4 ; other string dword into EDX + MOV EBX,EAX ; temp storage for part of string rotate + SHRD EAX,EDX,CL ; double shift by offset within dword EDX:EAX + SHRD EAX,EBX,CL ; double shift by offset within dword right + SHRD EAX,ESI,length ; bring in new bits + ROL EAX,length ; right justify new bit field + MOV EBX,EAX ; temp storage for part of string rotate + SHLD EAX,EDX,CL ; double shift back by offset within word EDX:EAX + SHLD EDX,EBX,CL ; double shift back by offset within word left + MOV [EDI]strg_base,EAX ; replace dword in memory + MOV [EDI]strg_base+4,EDX ; replace dword in memory + + 3. Bit String Insert into Memory (when bit string is exactly 32 bits + long, i.e., spans five or four types of memory): + + ; Insert right-justified bit string from register into + ; memory bit string. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is 32 + ; but the bit offset is held in a register. + ; + ; Register ESI holds the 32-bit string to be inserted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX, EBX, ECX, and EDI are also used by + ; this "insert" operation. + ; + MOV EDX,EDI ; preserve original offset for later use + SHR EDI,5 ; signed divide offset by 32 (dword address) + SHL EDI,2 ; multiply by 4 (in byte address format) + AND CL,1FH ; isolate low five bits of offset in CL + MOV EAX,[EDI]strg_base ; move low string dword into EAX + MOV EDX,[EDI]strg_base+4 ; other string dword into EDX + MOV EBX,EAX ; temp storage for part of string rotate + SHRD EAX,EDX ; double shift by offset within dword EDX:EAX + SHRD EDX,EBX ; double shift by offset within dword right + MOV EAX,ESI ; move 32-bit bit field into position + MOV EBX,EAX ; temp storage for part of string rotate + SHLD EAX,EDX ; double shift back by offset within word EDX:EAX + SHLD EDX,EBX ; double shift back by offset within word left + MOV [EDI]strg_base,EAX ; replace dword in memory + MOV [EDI]strg_base,+4,EDX ; replace dword in memory + + 4. Bit String Extract from Memory (when bit string is 1-25 bits long, + i.e., spans four bytes or less): + + ; Extract a right-justified bit string from memory bit + ; string into register + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate value + ; but the bit offset is held in a register. + ; + ; Register EAX holds the right-justified, zero-padded + ; bit string that was extracted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EDI, and ECX are also used by this "extract." + ; + MOV ECX,EDI ; temp storage for offset + SHR EDI,3 ; signed divide offset by 8 (byte address) + AND CL,7H ; isolate low three bits of offset + MOV EAX,[EDI]strg_base ; move string dword into EAX + SHR EAX,CL ; shift by offset within dword + AND EAX,mask ; extracted bit field in EAX + + 5. Bit String Extract from Memory (when bit string is 1-32 bits long, + i.e., spans five bytes or less): + + ; Extract a right-justified bit string from memory bit + ; string into register. + ; + ; Assumptions: + ; 1) The base of the string array is dword aligned, and + ; 2) the length of the bit string is an immediate + ; value but the bit offset is held in a register. + ; + ; Register EAX holds the right-justified, zero-padded + ; bit string that was extracted. + ; Register EDI holds the bit offset of the start of the + ; substring. + ; Registers EAX, EBX, and ECX are also used by this "extract." + MOV ECX,EDI ; temp storage for offset + SHR EDI,5 ; signed divide offset by 32 (dword address) + SHL EDI,2 ; multiply by 4 (in byte address format) + AND CL,1FH ; isolate low five bits of offset in CL + MOV EAX,[EDI]strg_base ; move low string dword into EAX + MOV EDX,[EDI]strg_base+4 ; other string dword into EDX + SHRD EAX,EDX,CL ; double shift right by offset within dword + AND EAX,mask ; extracted bit field in EAX + + +3.4.5 Byte-Set-On-Condition Instructions + +This group of instructions sets a byte to zero or one depending on any of +the 16 conditions defined by the status flags. The byte may be in memory or +may be a one-byte general register. These instructions are especially useful +for implementing Boolean expressions in high-level languages such as Pascal. + +SETcc (Set Byte on Condition cc) set a byte to one if condition cc is true; +sets the byte to zero otherwise. Refer to Appendix D for a definition of +the possible conditions. + + +3.4.6 Test Instruction + +TEST (Test) performs the logical "and" of the two operands, clears OF and +CF, leaves AF undefined, and updates SF, ZF, and PF. The flags can be tested +by conditional control transfer instructions or by the byte-set-on-condition +instructions. The operands may be doublewords, words, or bytes. + +The difference between TEST and AND is that TEST does not alter the +destination operand. TEST differs from BT in that TEST is useful for testing +the value of multiple bits in one operations, whereas BT tests a single bit. + + +3.5 Control Transfer Instructions + +The 80386 provides both conditional and unconditional control transfer +instructions to direct the flow of execution. Conditional control transfers +depend on the results of operations that affect the flag register. +Unconditional control transfers are always executed. + + +3.5.1 Unconditional Transfer Instructions + +JMP, CALL, RET, INT and IRET instructions transfer control from one code +segment location to another. These locations can be within the same code +segment (near control transfers) or in different code segments (far control +transfers). The variants of these instructions that transfer control to +other segments are discussed in a later section of this chapter. If the +model of memory organization used in a particular 80386 application does +not make segments visible to applications programmers, intersegment control +transfers will not be used. + + +3.5.1.1 Jump Instruction + +JMP (Jump) unconditionally transfers control to the target location. JMP is +a one-way transfer of execution; it does not save a return address on the +stack. + +The JMP instruction always performs the same basic function of transferring +control from the current location to a new location. Its implementation +varies depending on whether the address is specified directly within the +instruction or indirectly through a register or memory. + +A direct JMP instruction includes the destination address as part of the +instruction. An indirect JMP instruction obtains the destination address +indirectly through a register or a pointer variable. + +Direct near JMP. A direct JMP uses a relative displacement value contained +in the instruction. The displacement is signed and the size of the +displacement may be a byte, word, or doubleword. The processor forms an +effective address by adding this relative displacement to the address +contained in EIP. When the additions have been performed, EIP refers to the +next instruction to be executed. + +Indirect near JMP. Indirect JMP instructions specify an absolute address in +one of several ways: + + 1. The program can JMP to a location specified by a general register + (any of EAX, EDX, ECX, EBX, EBP, ESI, or EDI). The processor moves + this 32-bit value into EIP and resumes execution. + + 2. The processor can obtain the destination address from a memory + operand specified in the instruction. + + 3. A register can modify the address of the memory pointer to select a + destination address. + + +3.5.1.2 Call Instruction + +CALL (Call Procedure) activates an out-of-line procedure, saving on the +stack the address of the instruction following the CALL for later use by a +RET (Return) instruction. CALL places the current value of EIP on the stack. +The RET instruction in the called procedure uses this address to transfer +control back to the calling program. + +CALL instructions, like JMP instructions have relative, direct, and +indirect versions. + +Indirect CALL instructions specify an absolute address in one of these +ways: + + 1. The program can CALL a location specified by a general register (any + of EAX, EDX, ECX, EBX, EBP, ESI, or EDI). The processor moves this + 32-bit value into EIP. + + 2. The processor can obtain the destination address from a memory + operand specified in the instruction. + + +3.5.1.3 Return and Return-From-Interrupt Instruction + +RET (Return From Procedure) terminates the execution of a procedure and +transfers control through a back-link on the stack to the program that +originally invoked the procedure. RET restores the value of EIP that was +saved on the stack by the previous CALL instruction. + +RET instructions may optionally specify an immediate operand. By adding +this constant to the new top-of-stack pointer, RET effectively removes any +arguments that the calling program pushed on the stack before the execution +of the CALL instruction. + +IRET (Return From Interrupt) returns control to an interrupted procedure. +IRET differs from RET in that it also pops the flags from the stack into the +flags register. The flags are stored on the stack by the interrupt +mechanism. + + +3.5.2 Conditional Transfer Instructions + +The conditional transfer instructions are jumps that may or may not +transfer control, depending on the state of the CPU flags when the +instruction executes. + + +3.5.2.1 Conditional Jump Instructions + +Table 3-2 shows the conditional transfer mnemonics and their +interpretations. The conditional jumps that are listed as pairs are actually +the same instruction. The assembler provides the alternate mnemonics for +greater clarity within a program listing. + +Conditional jump instructions contain a displacement which is added to the +EIP register if the condition is true. The displacement may be a byte, a +word, or a doubleword. The displacement is signed; therefore, it can be used +to jump forward or backward. + + +Table 3-2. Interpretation of Conditional Transfers + +Unsigned Conditional Transfers + +Mnemonic Condition Tested "Jump If..." + +JA/JNBE (CF or ZF) = 0 above/not below nor equal +JAE/JNB CF = 0 above or equal/not below +JB/JNAE CF = 1 below/not above nor equal +JBE/JNA (CF or ZF) = 1 below or equal/not above +JC CF = 1 carry +JE/JZ ZF = 1 equal/zero +JNC CF = 0 not carry +JNE/JNZ ZF = 0 not equal/not zero +JNP/JPO PF = 0 not parity/parity odd +JP/JPE PF = 1 parity/parity even + +Signed Conditional Transfers + +Mnemonic Condition Tested "Jump If..." +JG/JNLE ((SF xor OF) or ZF) = 0 greater/not less nor equal +JGE/JNL (SF xor OF) = 0 greater or equal/not less +JL/JNGE (SF xor OF) = 1 less/not greater nor equal +JLE/JNG ((SF xor OF) or ZF) = 1 less or equal/not greater +JNO OF = 0 not overflow +JNS SF = 0 not sign (positive, including 0) +JO OF = 1 overflow +JS SF = 1 sign (negative) + + +3.5.2.2 Loop Instructions + +The loop instructions are conditional jumps that use a value placed in ECX +to specify the number of repetitions of a software loop. All loop +instructions automatically decrement ECX and terminate the loop when ECX=0. +Four of the five loop instructions specify a condition involving ZF that +terminates the loop before ECX reaches zero. + +LOOP (Loop While ECX Not Zero) is a conditional transfer that automatically +decrements the ECX register before testing ECX for the branch condition. If +ECX is non-zero, the program branches to the target label specified in the +instruction. The LOOP instruction causes the repetition of a code section +until the operation of the LOOP instruction decrements ECX to a value of +zero. If LOOP finds ECX=0, control transfers to the instruction immediately +following the LOOP instruction. If the value of ECX is initially zero, then +the LOOP executes 2^(32) times. + +LOOPE (Loop While Equal) and LOOPZ (Loop While Zero) are synonyms for the +same instruction. These instructions automatically decrement the ECX +register before testing ECX and ZF for the branch conditions. If ECX is +non-zero and ZF=1, the program branches to the target label specified in the +instruction. If LOOPE or LOOPZ finds that ECX=0 or ZF=0, control transfers +to the instruction immediately following the LOOPE or LOOPZ instruction. + +LOOPNE (Loop While Not Equal) and LOOPNZ (Loop While Not Zero) are synonyms +for the same instruction. These instructions automatically decrement the ECX +register before testing ECX and ZF for the branch conditions. If ECX is +non-zero and ZF=0, the program branches to the target label specified in the +instruction. If LOOPNE or LOOPNZ finds that ECX=0 or ZF=1, control transfers +to the instruction immediately following the LOOPNE or LOOPNZ instruction. + + +3.5.2.3 Executing a Loop or Repeat Zero Times + +JCXZ (Jump if ECX Zero) branches to the label specified in the instruction +if it finds a value of zero in ECX. JCXZ is useful in combination with the +LOOP instruction and with the string scan and compare instructions, all of +which decrement ECX. Sometimes, it is desirable to design a loop that +executes zero times if the count variable in ECX is initialized to zero. +Because the LOOP instructions (and repeat prefixes) decrement ECX before +they test it, a loop will execute 2^(32) times if the program enters the +loop with a zero value in ECX. A programmer may conveniently overcome this +problem with JCXZ, which enables the program to branch around the code +within the loop if ECX is zero when JCXZ executes. When used with repeated +string scan and compare instructions, JCXZ can determine whether the +repetitions terminated due to zero in ECX or due to satisfaction of the +scan or compare conditions. + + +3.5.3 Software-Generated Interrupts + +The INT n, INTO, and BOUND instructions allow the programmer to specify a +transfer to an interrupt service routine from within a program. + +INT n (Software Interrupt) activates the interrupt service routine that +corresponds to the number coded within the instruction. The INT instruction +may specify any interrupt type. Programmers may use this flexibility to +implement multiple types of internal interrupts or to test the operation of +interrupt service routines. (Interrupts 0-31 are reserved by Intel.) The +interrupt service routine terminates with an IRET instruction that returns +control to the instruction that follows INT. + +INTO (Interrupt on Overflow) invokes interrupt 4 if OF is set. Interrupt 4 +is reserved for this purpose. OF is set by several arithmetic, logical, and +string instructions. + +BOUND (Detect Value Out of Range) verifies that the signed value contained +in the specified register lies within specified limits. An interrupt (INT 5) +occurs if the value contained in the register is less than the lower bound +or greater than the upper bound. + +The BOUND instruction includes two operands. The first operand specifies +the register being tested. The second operand contains the effective +relative address of the two signed BOUND limit values. The BOUND instruction +assumes that the upper limit and lower limit are in adjacent memory +locations. These limit values cannot be register operands; if they are, an +invalid opcode exception occurs. + +BOUND is useful for checking array bounds before using a new index value to +access an element within the array. BOUND provides a simple way to check the +value of an index register before the program overwrites information in a +location beyond the limit of the array. + +The block of memory that specifies the lower and upper limits of an array +might typically reside just before the array itself. This makes the array +bounds accessible at a constant offset from the beginning of the array. +Because the address of the array will already be present in a register, this +practice avoids extra calculations to obtain the effective address of the +array bounds. + +The upper and lower limit values may each be a word or a doubleword. + + +3.6 String and Character Translation Instructions + +The instructions in this category operate on strings rather than on logical +or numeric values. Refer also to the section on I/O for information about +the string I/O instructions (also known as block I/O). + +The power of 80386 string operations derives from the following features of +the architecture: + +1. A set of primitive string operations + + MOVS Move String + CMPS Compare string + SCAS Scan string + LODS Load string + STOS Store string + +2. Indirect, indexed addressing, with automatic incrementing or + decrementing of the indexes. + + Indexes: + + ESI Source index register + EDI Destination index register + + Control flag: + + DF Direction flag + + Control flag instructions: + + CLD Clear direction flag instruction + STD Set direction flag instruction + +3. Repeat prefixes + + REP Repeat while ECX not xero + REPE/REPZ Repeat while equal or zero + REPNE/REPNZ Repeat while not equal or not zero + +The primitive string operations operate on one element of a string. A +string element may be a byte, a word, or a doubleword. The string elements +are addressed by the registers ESI and EDI. After every primitive operation +ESI and/or EDI are automatically updated to point to the next element of the +string. If the direction flag is zero, the index registers are incremented; +if one, they are decremented. The amount of the increment or decrement is +1, 2, or 4 depending on the size of the string element. + + +3.6.1 Repeat Prefixes + +The repeat prefixes REP (Repeat While ECX Not Zero), REPE/REPZ (Repeat +While Equal/Zero), and REPNE/REPNZ (Repeat While Not Equal/Not Zero) specify +repeated operation of a string primitive. This form of iteration allows the +CPU to process strings much faster than would be possible with a regular +software loop. + +When a primitive string operation has a repeat prefix, the operation is +executed repeatedly, each time using a different element of the string. The +repetition terminates when one of the conditions specified by the prefix is +satisfied. + +At each repetition of the primitive instruction, the string operation may +be suspended temporarily in order to handle an exception or external +interrupt. After the interruption, the string operation can be restarted +again where it left off. This method of handling strings allows operations +on strings of arbitrary length, without affecting interrupt response. + +All three prefixes causes the hardware to automatically repeat the +associated string primitive until ECX=0. The differences among the repeat +prefixes have to do with the second termination condition. REPE/REPZ and +REPNE/REPNZ are used exclusively with the SCAS (Scan String) and CMPS +(Compare String) primitives. When these prefixes are used, repetition of the +next instruction depends on the zero flag (ZF) as well as the ECX register. +ZF does not require initialization before execution of a repeated string +instruction, because both SCAS and CMPS set ZF according to the results of +the comparisons they make. The differences are summarized in the +accompanying table. + +Prefix Termination Termination + Condition 1 Condition 2 + +REP ECX = 0 (none) +REPE/REPZ ECX = 0 ZF = 0 +REPNE/REPNZ ECX = 0 ZF = 1 + + +3.6.2 Indexing and Direction Flag Control + +The addresses of the operands of string primitives are determined by the +ESI and EDI registers. ESI points to source operands. By default, ESI refers +to a location in the segment indicated by the DS segment register. A +segment-override prefix may be used, however, to cause ESI to refer to CS, +SS, ES, FS, or GS. EDI points to destination operands in the segment +indicated by ES; no segment override is possible. The use of two different +segment registers in one instruction allows movement of strings between +different segments. + +This use of ESI and DSI has led to the descriptive names source index and +destination index for the ESI and EDI registers, respectively. In all +cases other than string instructions, however, the ESI and EDI registers may +be used as general-purpose registers. + +When ESI and EDI are used in string primitives, they are automatically +incremented or decremented after to operation. The direction flag determines +whether they are incremented or decremented. The instruction CLD puts zero +in DF, causing the index registers to be incremented; the instruction STD +puts one in DF, causing the index registers to be decremented. Programmers +should always put a known value in DF before using string instructions in a +procedure. + + +3.6.3 String Instructions + +MOVS (Move String) moves the string element pointed to by ESI to the +location pointed to by EDI. MOVSB operates on byte elements, MOVSW operates +on word elements, and MOVSD operates on doublewords. The destination segment +register cannot be overridden by a segment override prefix, but the source +segment register can be overridden. + +The MOVS instruction, when accompanied by the REP prefix, operates as a +memory-to-memory block transfer. To set up for this operation, the program +must initialize ECX and the register pairs ESI and EDI. ECX specifies the +number of bytes, words, or doublewords in the block. + +If DF=0, the program must point ESI to the first element of the source +string and point EDI to the destination address for the first element. If +DF=1, the program must point these two registers to the last element of the +source string and to the destination address for the last element, +respectively. + +CMPS (Compare Strings) subtracts the destination string element (at ES:EDI) +from the source string element (at ESI) and updates the flags AF, SF, PF, CF +and OF. If the string elements are equal, ZF=1; otherwise, ZF=0. If DF=0, +the processor increments the memory pointers (ESI and EDI) for the two +strings. CMPSB compares bytes, CMPSW compares words, and CMPSD compares +doublewords. The segment register used for the source address can be changed +with a segment override prefix while the destination segment register +cannot be overridden. + +SCAS (Scan String) subtracts the destination string element at ES:EDI from +EAX, AX, or AL and updates the flags AF, SF, ZF, PF, CF and OF. If the +values are equal, ZF=1; otherwise, ZF=0. If DF=0, the processor increments +the memory pointer (EDI) for the string. SCASB scans bytes; SCASW scans +words; SCASD scans doublewords. The destination segment register (ES) cannot +be overridden. + +When either the REPE or REPNE prefix modifies either the SCAS or CMPS +primitives, the processor compares the value of the current string element +with the value in EAX for doubleword elements, in AX for word elements, or +in AL for byte elements. Termination of the repeated operation depends on +the resulting state of ZF as well as on the value in ECX. + +LODS (Load String) places the source string element at ESI into EAX for +doubleword strings, into AX for word strings, or into AL for byte strings. +LODS increments or decrements ESI according to DF. + +STOS (Store String) places the source string element from EAX, AX, or AL +into the string at ES:DSI. STOS increments or decrements EDI according to +DF. + + +3.7 Instructions for Block-Structured Languages + +The instructions in this section provide machine-language support for +functions normally found in high-level languages. These instructions include +ENTER and LEAVE, which simplify the programming of procedures. + +ENTER (Enter Procedure) creates a stack frame that may be used to implement +the scope rules of block-structured high-level languages. A LEAVE +instruction at the end of a procedure complements an ENTER at the beginning +of the procedure to simplify stack management and to control access to +variables for nested procedures. + +The ENTER instruction includes two parameters. The first parameter +specifies the number of bytes of dynamic storage to be allocated on the +stack for the routine being entered. The second parameter corresponds to the +lexical nesting level (0-31) of the routine. (Note that the lexical level +has no relationship to either the protection privilege levels or to the I/O +privilege level.) + +The specified lexical level determines how many sets of stack frame +pointers the CPU copies into the new stack frame from the preceding frame. +This list of stack frame pointers is sometimes called the display. The first +word of the display is a pointer to the last stack frame. This pointer +enables a LEAVE instruction to reverse the action of the previous ENTER +instruction by effectively discarding the last stack frame. + + Example: ENTER 2048,3 + + Allocates 2048 bytes of dynamic storage on the stack and sets up pointers + to two previous stack frames in the stack frame that ENTER creates for + this procedure. + +After ENTER creates the new display for a procedure, it allocates the +dynamic storage space for that procedure by decrementing ESP by the number +of bytes specified in the first parameter. This new value of ESP serves as a +starting point for all PUSH and POP operations within that procedure. + +To enable a procedure to address its display, ENTER leaves EBP pointing to +the beginning of the new stack frame. Data manipulation instructions that +specify EBP as a base register implicitly address locations within the stack +segment instead of the data segment. + +The ENTER instruction can be used in two ways: nested and non-nested. If +the lexical level is 0, the non-nested form is used. Since the second +operand is 0, ENTER pushes EBP, copies ESP to EBP and then subtracts the +first operand from ESP. The nested form of ENTER occurs when the second +parameter (lexical level) is not 0. + +Figure 3-16 gives the formal definition of ENTER. + +The main procedure (with other procedures nested within) operates at the +highest lexical level, level 1. The first procedure it calls operates at the +next deeper lexical level, level 2. A level 2 procedure can access the +variables of the main program which are at fixed locations specified by the +compiler. In the case of level 1, ENTER allocates only the requested +dynamic storage on the stack because there is no previous display to copy. + +A program operating at a higher lexical level calling a program at a lower +lexical level requires that the called procedure should have access to the +variables of the calling program. ENTER provides this access through a +display that provides addressability to the calling program's stack frame. + +A procedure calling another procedure at the same lexical level implies +that they are parallel procedures and that the called procedure should not +have access to the variables of the calling procedure. In this case, ENTER +copies only that portion of the display from the calling procedure which +refers to previously nested procedures operating at higher lexical levels. +The new stack frame does not include the pointer for addressing the calling +procedure's stack frame. + +ENTER treats a reentrant procedure as a procedure calling another procedure +at the same lexical level. In this case, each succeeding iteration of the +reentrant procedure can address only its own variables and the variables of +the calling procedures at higher lexical levels. A reentrant procedure can +always address its own variables; it does not require pointers to the stack +frames of previous iterations. + +By copying only the stack frame pointers of procedures at higher lexical +levels, ENTER makes sure that procedures access only those variables of +higher lexical levels, not those at parallel lexical levels (see Figure +3-17). Figures 3-18 through 3-21 demonstrate the actions of the ENTER +instruction if the modules shown in Figure 3-17 were to call one another in +alphabetic order. + +Block-structured high-level languages can use the lexical levels defined by +ENTER to control access to the variables of previously nested procedures. +Referring to Figure 3-17 for example, if PROCEDURE A calls PROCEDURE B +which, in turn, calls PROCEDURE C, then PROCEDURE C will have access to the +variables of MAIN and PROCEDURE A, but not PROCEDURE B because they operate +at the same lexical level. Following is the complete definition of access to +variables for Figure 3-17. + + 1. MAIN PROGRAM has variables at fixed locations. + + 2. PROCEDURE A can access only the fixed variables of MAIN. + + 3. PROCEDURE B can access only the variables of PROCEDURE A and MAIN. + PROCEDURE B cannot access the variables of PROCEDURE C or PROCEDURE D. + + 4. PROCEDURE C can access only the variables of PROCEDURE A and MAIN. + PROCEDURE C cannot access the variables of PROCEDURE B or PROCEDURE D. + + 5. PROCEDURE D can access the variables of PROCEDURE C, PROCEDURE A, and + MAIN. PROCEDURE D cannot access the variables of PROCEDURE B. + +ENTER at the beginning of the MAIN PROGRAM creates dynamic storage space +for MAIN but copies no pointers. The first and only word in the display +points to itself because there is no previous value for LEAVE to return to +EBP. See Figure 3-18. + +After MAIN calls PROCEDURE A, ENTER creates a new display for PROCEDURE A +with the first word pointing to the previous value of EBP (BPM for LEAVE to +return to the MAIN stack frame) and the second word pointing to the current +value of EBP. Procedure A can access variables in MAIN since MAIN is at +level 1. Therefore the base for the dynamic storage for MAIN is at [EBP-2]. +All dynamic variables for MAIN are at a fixed offset from this value. See +Figure 3-19. + +After PROCEDURE A calls PROCEDURE B, ENTER creates a new display for +PROCEDURE B with the first word pointing to the previous value of EBP, the +second word pointing to the value of EBP for MAIN, and the third word +pointing to the value of EBP for A and the last word pointing to the current +EBP. B can access variables in A and MAIN by fetching from the display the +base addresses of the respective dynamic storage areas. See Figure 3-20. + +After PROCEDURE B calls PROCEDURE C, ENTER creates a new display for +PROCEDURE C with the first word pointing to the previous value of EBP, the +second word pointing to the value of EBP for MAIN, and the third word +pointing to the EBP value for A and the third word pointing to the current +value of EBP. Because PROCEDURE B and PROCEDURE C have the same lexical +level, PROCEDURE C is not allowed access to variables in B and therefore +does not receive a pointer to the beginning of PROCEDURE B's stack frame. +See Figure 3-21. + +LEAVE (Leave Procedure) reverses the action of the previous ENTER +instruction. The LEAVE instruction does not include any operands. LEAVE +copies EBP to ESP to release all stack space allocated to the procedure by +the most recent ENTER instruction. Then LEAVE pops the old value of EBP from +the stack. A subsequent RET instruction can then remove any arguments that +were pushed on the stack by the calling program for use by the called +procedure. + + +Figure 3-16. Formal Definition of the ENTER Instruction + +The formal definition of the ENTER instruction for all cases is given by the +following listing. LEVEL denotes the value of the second operand. + +Push EBP +Set a temporary value FRAME_PTR := ESP +If LEVEL > 0 then + Repeat (LEVEL-1) times: + EBP :=EBP - 4 + Push the doubleword pointed to by EBP + End repeat + Push FRAME_PTR +End if +EBP := FRAME_PTR +ESP := ESP - first operand. + + +Figure 3-17. Variable Access in Nested Procedures + + ͻ + MAIN PROCEDURE (LEXICAL LEVEL 1) + ͻ + PROCEDURE A (LEXICAL LEVEL 2) + ͻ + PROCEDURE B (LEXICAL LEVEL 3) + ͼ + + ͻ + PROCEDURE C (LEXICAL LEVEL 3) + ͻ + PROCEDURE D (LEXICAL LEVEL 4) + ͼ + + ͼ + + ͼ + + ͼ + + +Figure 3-18. Stack Frame for MAIN at Level 1 + +  31 0  + D O + I F ͹ + R OLD ESP + E E DISPLAY Ĵ ͹EBP FOR + C X EBPM +EBPM = EBP VALUE FOR MAIN MAIN + T P ͹ + I A + O N ͹ + N S DYNAMIC Ĵ + I STORAGE ͹ + O + N ͹ESP + +    + + +Figure 3-19. Stack Frame for Procedure A + +  31 0  + D O + I F ͹ + R OLD ESP + E E ͹ + C X EBPM +EBPM = EBP VALUE FOR MAIN + T P ͹ + I A + O N ͹ + N S + I ͹ + O + N ͹ + EBPM +  ͹EBP FOR A + DISPLAY Ĵ EBPM + ͹ + EBPA +EBPA = EBP VALUE FOR PROCEDURE A + ͹ + + ͹ + DYNAMIC Ĵ + STORAGE ͹ + + ͹ESP + +   + + +Figure 3-20. Stack Frame for Procedure B at Level 3 Called from A + +  31 0  + D O + I F ͹ + R OLD ESP + E E ͹ + C X EBPM +EBPM = EBP VALUE FOR MAIN + T P ͹ + I A + O N ͹ + N S + I ͹ + O + N ͹ + EBPM +  ͹ + EBPM + ͹ + EBPA + ͹ + + ͹ + + ͹ + + ͹ + EBPA + ͹EBP + EBPM + DISPLAY Ĵ ͹ + EBPA + ͹ + EBPB +EBPB = EBP VALUE FOR PROCEDURE B + ͹ + + ͹ + DYNAMIC Ĵ + STORAGE ͹ + + ͹ESP + +   + + +Figure 3-21. Stack Frame for Procedure C at Level 3 Called from B + +  31 0  + D O + I F ͹ + R OLD ESP + E E ͹ + C X EBPM +EBPM = EBP VALUE FOR MAIN + T P ͹ + I A + O N ͹ + N S + I ͹ + O + N ͹ + EBPM +  ͹ + EBPM + ͹ + EBPA +EBPA = EBP VALUE FOR PROCEDURE A + ͹ + + ͹ + + ͹ + + ͹ + EBPA + ͹EBP + EBPM + DISPLAY Ĵ ͹ + EBPA + ͹ + EBPB +EBPB = EBP VALUE FOR PROCEDURE B + ͹ + + ͹ + DYNAMIC Ĵ + STORAGE ͹ + + ͹ESP + +   + + +3.8 Flag Control Instructions + +The flag control instructions provide a method for directly changing the +state of bits in the flag register. + + +3.8.1 Carry and Direction Flag Control Instructions + +The carry flag instructions are useful in conjunction with +rotate-with-carry instructions RCL and RCR. They can initialize the carry +flag, CF, to a known state before execution of a rotate that moves the carry +bit into one end of the rotated operand. + +The direction flag control instructions are specifically included to set or +clear the direction flag, DF, which controls the left-to-right or +right-to-left direction of string processing. If DF=0, the processor +automatically increments the string index registers, ESI and EDI, after each +execution of a string primitive. If DF=1, the processor decrements these +index registers. Programmers should use one of these instructions before any +procedure that uses string instructions to insure that DF is set properly. + +Flag Control Instruction Effect + +STC (Set Carry Flag) CF  1 +CLC (Clear Carry Flag) CF  0 +CMC (Complement Carry Flag) CF  NOT (CF) +CLD (Clear Direction Flag) DF  0 +STD (Set Direction Flag) DF  1 + + +3.8.2 Flag Transfer Instructions + +Though specific instructions exist to alter CF and DF, there is no direct +method of altering the other applications-oriented flags. The flag transfer +instructions allow a program to alter the other flag bits with the bit +manipulation instructions after transferring these flags to the stack or the +AH register. + +The instructions LAHF and SAHF deal with five of the status flags, which +are used primarily by the arithmetic and logical instructions. + +LAHF (Load AH from Flags) copies SF, ZF, AF, PF, and CF to AH bits 7, 6, 4, +2, and 0, respectively (see Figure 3-22). The contents of the remaining bits +(5, 3, and 1) are undefined. The flags remain unaffected. + +SAHF (Store AH into Flags) transfers bits 7, 6, 4, 2, and 0 from AH into +SF, ZF, AF, PF, and CF, respectively (see Figure 3-22). + +The PUSHF and POPF instructions are not only useful for storing the flags +in memory where they can be examined and modified but are also useful for +preserving the state of the flags register while executing a procedure. + +PUSHF (Push Flags) decrements ESP by two and then transfers the low-order +word of the flags register to the word at the top of stack pointed to by ESP +(see Figure 3-23). The variant PUSHFD decrements ESP by four, then +transfers both words of the extended flags register to the top of the stack +pointed to by ESP (the VM and RF flags are not moved, however). + +POPF (Pop Flags) transfers specific bits from the word at the top of stack +into the low-order byte of the flag register (see Figure 3-23), then +increments ESP by two. The variant POPFD transfers specific bits from the +doubleword at the top of the stack into the extended flags register (the RF +and VM flags are not changed, however), then increments ESP by four. + + +Figure 3-22. LAHF and SAHF + + 7 6 5 4 3 2 1 0 + ͻ + SF ZF UU AF UU PF UU CF + ͼ + + LAHF LOADS FIVE FLAGS FROM THE FLAG REGISTER INTO REGISTER AH. SAHF + STORES THESE SAME FIVE FLAGS FROM AH INTO THE FLAG REGISTER. THE BIT + POSITION OF EACH FLAG IS THE SAME IN AH AS IT IS IN THE FLAG REGISTER. + THE REMAINING BITS (MARKED UU) ARE RESERVED; DO NOT DEFINE. + + +3.9 Coprocessor Interface Instructions + +A numerics coprocessor (e.g., the 80387 or 80287) provides an extension to +the instruction set of the base architecture. The coprocessor extends the +instruction set of the base architecture to support high-precision integer +and floating-point calculations. This extended instruction set includes +arithmetic, comparison, transcendental, and data transfer instructions. The +coprocessor also contains a set of useful constants to enhance the speed of +numeric calculations. + +A program contains instructions for the coprocessor in line with the +instructions for the CPU. The system executes these instructions in the same +order as they appear in the instruction stream. The coprocessor operates +concurrently with the CPU to provide maximum throughput for numeric +calculations. + +The 80386 also has features to support emulation of the numerics +coprocessor when the coprocessor is absent. The software emulation of the +coprocessor is transparent to application software but requires more time +for execution. Refer to Chapter 11 for more information on coprocessor +emulation. + +ESC (Escape) is a 5-bit sequence that begins the opcodes that identify +floating point numeric instructions. The ESC pattern tells the 80386 to send +the opcode and addresses of operands to the numerics coprocessor. The +numerics coprocessor uses the escape instructions to perform +high-performance, high-precision floating point arithmetic that conforms to +the IEEE floating point standard 754. + +WAIT (Wait) is an 80386 instruction that suspends program execution until +the 80386 CPU detects that the BUSY pin is inactive. This condition +indicates that the coprocessor has completed its processing task and that +the CPU may obtain the results. + + +Figure 3-23. Flag Format for PUSHF and POPF + + PUSHFD/POPFD + Ŀ + PUSHF/POPF + Ŀ + 31 23 15 7 0 + ͻ + VR NID ODITSZ A P C + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 + MF T PLFFFFFF F F F + ͼ + + BITS MARKED 0 AND 1 ARE RESERVED BY INTEL. DO NOT DEFINE. + + SYSTEMS FLAGS (INCLUDING THE IOPL FIELD, AND THE VM, RF, AND IF FLAGS) + ARE PUSHED AND ARE VISIBLE TO APPLICATIONS PROGRAMS. HOWEVER, WHEN AN + APPLICATIONS PROGRAM POPS THE FLAGS, THESE ITEMS ARE NOT CHANGED, + REGARDLESS OF THE VALUES POPPED INTO THEM. + + +3.10 Segment Register Instructions + +This category actually includes several distinct types of instructions. +These various types are grouped together here because, if systems designers +choose an unsegmented model of memory organization, none of these +instructions is used by applications programmers. The instructions that deal +with segment registers are: + +1. Segment-register transfer instructions. + + MOV SegReg, ... + MOV ..., SegReg + PUSH SegReg + POP SegReg + +2. Control transfers to another executable segment. + + JMP far ; direct and indirect + CALL far + RET far + +3. Data pointer instructions. + + LDS + LES + LFS + LGS + LSS + +Note that the following interrupt-related instructions are different; all +are capable of transferring control to another segment, but the use of +segmentation is not apparent to the applications programmer. + +INT n +INTO +BOUND +IRET + + +3.10.1 Segment-Register Transfer Instructions + +The MOV, POP, and PUSH instructions also serve to load and store segment +registers. These variants operate similarly to their general-register +counterparts except that one operand can be a segment register. MOV cannot +move segment register to a segment register. Neither POP nor MOV can place a +value in the code-segment register CS; only the far control-transfer +instructions can change CS. + + +3.10.2 Far Control Transfer Instructions + +The far control-transfer instructions transfer control to a location in +another segment by changing the content of the CS register. + +Direct far JMP. Direct JMP instructions that specify a target location +outside the current code segment contain a far pointer. This pointer +consists of a selector for the new code segment and an offset within the new +segment. + +Indirect far JMP. Indirect JMP instructions that specify a target location +outside the current code segment use a 48-bit variable to specify the far +pointer. + +Far CALL. An intersegment CALL places both the value of EIP and CS on the +stack. + +Far RET. An intersegment RET restores the values of both CS and EIP which +were saved on the stack by the previous intersegment CALL instruction. + + +3.10.3 Data Pointer Instructions + +The data pointer instructions load a pointer (consisting of a segment +selector and an offset) to a segment register and a general register. + +LDS (Load Pointer Using DS) transfers a pointer variable from the source +operand to DS and the destination register. The source operand must be a +memory operand, and the destination operand must be a general register. DS +receives the segment-selector of the pointer. The destination register +receives the offset part of the pointer, which points to a specific location +within the segment. + +Example: LDS ESI, STRING_X + +Loads DS with the selector identifying the segment pointed to by a +STRING_X, and loads the offset of STRING_X into ESI. Specifying ESI as the +destination operand is a convenient way to prepare for a string operation on +a source string that is not in the current data segment. + +LES (Load Pointer Using ES) operates identically to LDS except that ES +receives the segment selector rather than DS. + +Example: LES EDI, DESTINATION_X + +Loads ES with the selector identifying the segment pointed to by +DESTINATION_X, and loads the offset of DESTINATION_X into EDI. This +instruction provides a convenient way to select a destination for a string +operation if the desired location is not in the current extra segment. + +LFS (Load Pointer Using FS) operates identically to LDS except that FS +receives the segment selector rather than DS. + +LGS (Load Pointer Using GS) operates identically to LDS except that GS +receives the segment selector rather than DS. + +LSS (Load Pointer Using SS) operates identically to LDS except that SS +receives the segment selector rather than DS. This instruction is +especially important, because it allows the two registers that identify the +stack (SS:ESP) to be changed in one uninterruptible operation. Unlike the +other instructions which load SS, interrupts are not inhibited at the end +of the LSS instruction. The other instructions (e.g., POP SS) inhibit +interrupts to permit the following instruction to load ESP, thereby forming +an indivisible load of SS:ESP. Since both SS and ESP can be loaded by LSS, +there is no need to inhibit interrupts. + + +3.11 Miscellaneous Instructions + +The following instructions do not fit in any of the previous categories, +but are nonetheless useful. + + +3.11.1 Address Calculation Instruction + +LEA (Load Effective Address) transfers the offset of the source operand +(rather than its value) to the destination operand. The source operand must +be a memory operand, and the destination operand must be a general register. +This instruction is especially useful for initializing registers before the +execution of the string primitives (ESI, EDI) or the XLAT instruction (EBX). +The LEA can perform any indexing or scaling that may be needed. + +Example: LEA EBX, EBCDIC_TABLE + +Causes the processor to place the address of the starting location of the +table labeled EBCDIC_TABLE into EBX. + + +3.11.2 No-Operation Instruction + +NOP (No Operation) occupies a byte of storage but affects nothing but the +instruction pointer, EIP. + + +3.11.3 Translate Instruction + +XLAT (Translate) replaced a byte in the AL register with a byte from a +user-coded translation table. When XLAT is executed, AL should have the +unsigned index to the table addressed by EBX. XLAT changes the contents of +AL from table index to table entry. EBX is unchanged. The XLAT instruction +is useful for translating from one coding system to another such as from +ASCII to EBCDIC. The translate table may be up to 256 bytes long. The +value placed in the AL register serves as an index to the location of the +corresponding translation value. + + + PART II SYSTEMS PROGRAMMING + + +Chapter 4 Systems Architecture + + + +Many of the architectural features of the 80386 are used only by systems +programmers. This chapter presents an overview of these aspects of the +architecture. + +The systems-level features of the 80386 architecture include: + + Memory Management + Protection + Multitasking + Input/Output + Exceptions and Interrupts + Initialization + Coprocessing and Multiprocessing + Debugging + +These features are implemented by registers and instructions, all of which +are introduced in the following sections. The purpose of this chapter is not +to explain each feature in detail, but rather to place the remaining +chapters of Part II in perspective. Each mention in this chapter of a +register or instruction is either accompanied by an explanation or a +reference to a following chapter where detailed information can be obtained. + + +4.1 Systems Registers + +The registers designed for use by systems programmers fall into these +classes: + + EFLAGS + Memory-Management Registers + Control Registers + Debug Registers + Test Registers + + +4.1.1 Systems Flags + +The systems flags of the EFLAGS register control I/O, maskable interrupts, +debugging, task switching, and enabling of virtual 8086 execution in a +protected, multitasking environment. These flags are highlighted in Figure +4-1. + +IF (Interrupt-Enable Flag, bit 9) + + Setting IF allows the CPU to recognize external (maskable) interrupt + requests. Clearing IF disables these interrupts. IF has no effect on + either exceptions or nonmaskable external interrupts. Refer to Chapter + 9 for more details about interrupts. + +NT (Nested Task, bit 14) + + The processor uses the nested task flag to control chaining of + interrupted and called tasks. NT influences the operation of the IRET + instruction. Refer to Chapter 7 and Chapter 9 for more information on + nested tasks. + +RF (Resume Flag, bit 16) + + The RF flag temporarily disables debug exceptions so that an instruction + can be restarted after a debug exception without immediately causing + another debug exception. Refer to Chapter 12 for details. + +TF (Trap Flag, bit 8) + + Setting TF puts the processor into single-step mode for debugging. In + this mode, the CPU automatically generates an exception after each + instruction, allowing a program to be inspected as it executes each + instruction. Single-stepping is just one of several debugging features of + the 80386. Refer to Chapter 12 for additional information. + +VM (Virtual 8086 Mode, bit 17) + + When set, the VM flag indicates that the task is executing an 8086 + program. Refer to Chapter 14 for a detailed discussion of how the 80386 + executes 8086 tasks in a protected, multitasking environment. + + +Figure 4-1. System Flags of EFLAGS Register + + 31 23 15 7 0 + ͻ + VRNID ODITSZAPC + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 001 + MFT PLFFFFFFFFF + ͼ + + VIRTUAL 8086 MODE + RESUME FLAG + NESTED TASK FLAG + I/O PRIVILEGE LEVEL + INTERRUPT ENABLE + + +NOTE + 0 OR 1 INDICATES INTEL RESERVED. DO NOT DEFINE. + + + +4.1.2 Memory-Management Registers + +Four registers of the 80386 locate the data structures that control +segmented memory management: + +GDTR Global Descriptor Table Register +LDTR Local Descriptor Table Register + + These registers point to the segment descriptor tables GDT and LDT. + Refer to Chapter 5 for an explanation of addressing via descriptor + tables. + +IDTR Interrupt Descriptor Table Register + + This register points to a table of entry points for interrupt handlers + (the IDT). Refer to Chapter 9 for details of the interrupt mechanism. + +TR Task Register + + This register points to the information needed by the processor to define + the current task. Refer to Chapter 7 for a description of the + multitasking features of the 80386. + + +4.1.3 Control Registers + +Figure 4-2 shows the format of the 80386 control registers CR0, CR2, and +CR3. These registers are accessible to systems programmers only via variants +of the MOV instruction, which allow them to be loaded from or stored in +general registers; for example: + +MOV EAX, CR0 +MOV CR3, EBX + +CR0 contains system control flags, which control or indicate conditions +that apply to the system as a whole, not to an individual task. + +EM (Emulation, bit 2) + + EM indicates whether coprocessor functions are to be emulated. Refer to + Chapter 11 for details. + +ET (Extension Type, bit 4) + + ET indicates the type of coprocessor present in the system (80287 or + 80387). Refer to Chapter 11 and Chapter 10 for details. + +MP (Math Present, bit 1) + + MP controls the function of the WAIT instruction, which is used to + coordinate a coprocessor. Refer to Chapter 11 for details. + +PE (Protection Enable, bit 0) + + Setting PE causes the processor to begin executing in protected mode. + Resetting PE returns to real-address mode. Refer to Chapter 14 and + Chapter 10 for more information on changing processor modes. + +PG (Paging, bit 31) + + PG indicates whether the processor uses page tables to translate linear + addresses into physical addresses. Refer to Chapter 5 for a description + of page translation; refer to Chapter 10 for a discussion of how to set + PG. + +TS (Task Switched, bit 3) + + The processor sets TS with every task switch and tests TS when + interpreting coprocessor instructions. Refer to Chapter 11 for details. + +CR2 is used for handling page faults when PG is set. The processor stores +in CR2 the linear address that triggers the fault. Refer to Chapter 9 for a +description of page-fault handling. + +CR3 is used when PG is set. CR3 enables the processor to locate the page +table directory for the current task. Refer to Chapter 5 for a description +of page tables and page translation. + + +Figure 4-2. Control Registers + + 31 23 15 7 0 +ͻ + + PAGE DIRECTORY BASE REGISTER (PDBR) RESERVED CR3 +Ķ + + PAGE FAULT LINEAR ADDRESS CR2 +Ķ + + RESERVED CR1 +Ķ +P ETEMP +G RESERVED TSMPECR0 +ͼ + + +4.1.4 Debug Register + +The debug registers bring advanced debugging abilities to the 80386, +including data breakpoints and the ability to set instruction breakpoints +without modifying code segments. Refer to Chapter 12 for a complete +description of formats and usage. + + +4.1.5 Test Registers + +The test registers are not a standard part of the 80386 architecture. They +are provided solely to enable confidence testing of the translation +lookaside buffer (TLB), the cache used for storing information from page +tables. Chapter 12 explains how to use these registers. + + +4.2 Systems Instructions + +Systems instructions deal with such functions as: + + 1. Verification of pointer parameters (refer to Chapter 6): + + ARPL Adjust RPL + LAR Load Access Rights + LSL Load Segment Limit + VERR Verify for Reading + VERW Verify for Writing + + 2. Addressing descriptor tables (refer to Chaper 5): + + LLDT Load LDT Register + SLDT Store LDT Register + LGDT Load GDT Register + SGDT Store GDT Register + + 3. Multitasking (refer to Chapter 7): + + LTR Load Task Register + STR Store Task Register + + 4. Coprocessing and Multiprocessing (refer to Chapter 11): + + CLTS Clear Task-Switched Flag + ESC Escape instructions + WAIT Wait until Coprocessor not Busy + LOCK Assert Bus-Lock Signal + + 5. Input and Output (refer to Chapter 8): + + IN Input + OUT Output + INS Input String + OUTS Output String + + 6. Interrupt control (refer to Chapter 9): + + CLI Clear Interrupt-Enable Flag + STI Set Interrupt-Enable Flag + LIDT Load IDT Register + SIDT Store IDT Register + + 7. Debugging (refer to Chapter 12): + + MOV Move to and from debug registers + + 8. TLB testing (refer to Chapter 10): + + MOV Move to and from test registers + + 9. System Control: + + SMSW Set MSW + LMSW Load MSW + HLT Halt Processor + MOV Move to and from control registers + +The instructions SMSW and LMSW are provided for compatibility with the +80286 processor. 80386 programs access the MSW in CR0 via variants of the +MOV instruction. HLT stops the processor until receipt of an INTR or RESET +signal. + +In addition to the chapters cited above, detailed information about each of +these instructions can be found in the instruction reference chapter, +Chapter 17. + + +Chapter 5 Memory Management + + + +The 80386 transforms logical addresses (i.e., addresses as viewed by +programmers) into physical address (i.e., actual addresses in physical +memory) in two steps: + + Segment translation, in which a logical address (consisting of a + segment selector and segment offset) are converted to a linear address. + + Page translation, in which a linear address is converted to a physical + address. This step is optional, at the discretion of systems-software + designers. + +These translations are performed in a way that is not visible to +applications programmers. Figure 5-1 illustrates the two translations at a +high level of abstraction. + +Figure 5-1 and the remainder of this chapter present a simplified view of +the 80386 addressing mechanism. In reality, the addressing mechanism also +includes memory protection features. For the sake of simplicity, however, +the subject of protection is taken up in another chapter, Chapter 6. + + +Figure 5-1. Address Translation Overview + + 15 0 31 0 + LOGICAL ͻ ͻ + ADDRESS SELECTOR OFFSET + ͼ ͼ +  + ͻ + SEGMENT TRANSLATION + ͼ + ͻ PAGING ENABLED + PG ?Ŀ + ͼ + 31 PAGING  DISABLED 0 + LINEAR ͻ + ADDRESS DIR PAGE OFFSET + ͼ +  + ͻ + PAGE TRANSLATION + ͼ +  + 31  0 + PHYSICAL ͻ + ADDRESS + ͼ + + +5.1 Segment Translation + +Figure 5-2 shows in more detail how the processor converts a logical +address into a linear address. + +To perform this translation, the processor uses the following data +structures: + + Descriptors + Descriptor tables + Selectors + Segment Registers + + +5.1.1 Descriptors + +The segment descriptor provides the processor with the data it needs to map +a logical address into a linear address. Descriptors are created by +compilers, linkers, loaders, or the operating system, not by applications +programmers. Figure 5-3 illustrates the two general descriptor formats. All +types of segment descriptors take one of these formats. Segment-descriptor +fields are: + +BASE: Defines the location of the segment within the 4 gigabyte linear +address space. The processor concatenates the three fragments of the base +address to form a single 32-bit value. + +LIMIT: Defines the size of the segment. When the processor concatenates the +two parts of the limit field, a 20-bit value results. The processor +interprets the limit field in one of two ways, depending on the setting of +the granularity bit: + + 1. In units of one byte, to define a limit of up to 1 megabyte. + + 2. In units of 4 Kilobytes, to define a limit of up to 4 gigabytes. The + limit is shifted left by 12 bits when loaded, and low-order one-bits + are inserted. + +Granularity bit: Specifies the units with which the LIMIT field is +interpreted. When thebit is clear, the limit is interpreted in units of one +byte; when set, the limit is interpreted in units of 4 Kilobytes. + +TYPE: Distinguishes between various kinds of descriptors. + +DPL (Descriptor Privilege Level): Used by the protection mechanism (refer +to Chapter 6). + +Segment-Present bit: If this bit is zero, the descriptor is not valid for +use in address transformation; the processor will signal an exception when a +selector for the descriptor is loaded into a segment register. Figure 5-4 +shows the format of a descriptor when the present-bit is zero. The operating +system is free to use the locations marked AVAILABLE. Operating systems that +implement segment-based virtual memory clear the present bit in either of +these cases: + + When the linear space spanned by the segment is not mapped by the + paging mechanism. + + When the segment is not present in memory. + +Accessed bit: The processor sets this bit when the segment is accessed; +i.e., a selector for the descriptor is loaded into a segment register or +used by a selector test instruction. Operating systems that implement +virtual memory at the segment level may, by periodically testing and +clearing this bit, monitor frequency of segment usage. + +Creation and maintenance of descriptors is the responsibility of systems +software, usually requiring the cooperation of compilers, program loaders or +system builders, and therating system. + + +Figure 5-2. Segment Translation + + 15 0 31 0 + LOGICAL ͻ ͻ + ADDRESS SELECTOR OFFSET + ͼ ͼ +  + DESCRIPTOR TABLE + ͻ + + + + + ͹ + SEGMENT BASE ͻ +  DESCRIPTOR  +  + ͹ ADDRESS ͼ + + ͼ +  + LINEAR ͻ + ADDRESS DIR PAGE OFFSET + ͼ + + +Figure 5-3. General Segment-Descriptor Format + + DESCRIPTORS USED FOR APPLICATIONS CODE AND DATA SEGMENTS + + 31 23 15 7 0 + ͻ + A + BASE 31..24 GXOV LIMIT P DPL 1 TYPEA BASE 23..16 4 + L 19..16 + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + DESCRIPTORS USED FOR SPECIAL SYSTEM SEGMENTS + + 31 23 15 7 0 + ͻ + A + BASE 31..24 GXOV LIMIT P DPL 0 TYPE BASE 23..16 4 + L 19..16 + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + A - ACCESSED + AVL - AVAILABLE FOR USE BY SYSTEMS PROGRAMMERS + DPL - DESCRIPTOR PRIVILEGE LEVEL + G - GRANULARITY + P - SEGMENT PRESENT + + +5.1.2 Descriptor Tables + +Segment descriptors are stored in either of two kinds of descriptor table: + + The global descriptor table (GDT) + A local descriptor table (LDT) + +A descriptor table is simply a memory array of 8-byte entries that contain +descriptors, as Figure 5-5 shows. A descriptor table is variable in length +and may contain up to 8192 (2^(13)) descriptors. The first entry of the GDT +(INDEX=0) is not used by the processor, however. + +The processor locates the GDT and the current LDT in memory by means of the +GDTR and LDTR registers. These registers store the base addresses of the +tables in the linear address space and store the segment limits. The +instructions LGDT and SGDT give access to the GDTR; the instructions LLDT +and SLDT give access to the LDTR. + + +Figure 5-4. Format of Not-Present Descriptor + + 31 23 15 7 0 + ͻ + + AVAILABLE O DPL S TYPE AVAILABLE 4 + + Ķ + + AVAILABLE 0 + + ͼ + + +Figure 5-5. Descriptor Tables + + GLOBAL DESCRIPTOR TABLE LOCAL DESCRIPTOR TABLE + ͻ ͻ + + Ķ Ķ + M M + ͼ ͼ + | | | | + | | | | + ͻ ͻ + + Ķ Ķ + N + 3 N + 3 + ͹ ͹ + + Ķ Ķ + N + 2 N + 2 + ͹ ͹ + + Ķ Ķ + N + 1 N + 1 + ͹ ͹ + + Ķ Ķ + N N + ͼ ͼ + | | | | + | | | | + ͻ ͻ + + (UNUSED)Ķ Ķ + + ͼ ͼ +   + ͻ ͻ + GDTR LDTR + ͼ ͼ + + +5.1.3 Selectors + +The selector portion of a logical address identifies a descriptor by +specifying a descriptor table and indexing a descriptor within that table. +Selectors may be visible to applications programs as a field within a +pointer variable, but the values of selectors are usually assigned (fixed +up) by linkers or linking loaders. Figure 5-6 shows the format of a +selector. + +Index: Selects one of 8192 descriptors in a descriptor table. The processor +simply multiplies this index value by 8 (the length of a descriptor), and +adds the result to the base address of the descriptor table in order to +access the appropriate segment descriptor in the table. + +Table Indicator: Specifies to which descriptor table the selector refers. A +zero indicates the GDT; a one indicates the current LDT. + +Requested Privilege Level: Used by the protection mechanism. (Refer to +Chapter 6.) + +Because the first entry of the GDT is not used by the processor, a selector +that has an index of zero and a table indicator of zero (i.e., a selector +that points to the first entry of the GDT), can be used as a null selector. +The processor does not cause an exception when a segment register (other +than CS or SS) is loaded with a null selector. It will, however, cause an +exception when the segment register is used to access memory. This feature +is useful for initializing unused segment registers so as to trap accidental +references. + + +Figure 5-6. Format of a Selector + + 15 4 3 0 + ͻ + T + INDEX RPL + I + ͼ + + TI - TABLE INDICATOR + RPL - REQUESTOR'S PRIVILEGE LEVEL + + +Figure 5-7. Segment Registers + + 16-BIT VISIBLE + SELECTOR HIDDEN DESCRIPTOR + ͻ + CS + Ķ + SS + Ķ + DS + Ķ + ES + Ķ + FS + Ķ + GS + ͼ + + +5.1.4 Segment Registers + +The 80386 stores information from descriptors in segment registers, thereby +avoiding the need to consult a descriptor table every time it accesses +memory. + +Every segment register has a "visible" portion and an "invisible" portion, +as Figure 5-7 illustrates. The visible portions of these segment address +registers are manipulated by programs as if they were simply 16-bit +registers. The invisible portions are manipulated by the processor. + +The operations that load these registers are normal program instructions +(previously described in Chapter 3). These instructions are of two classes: + + 1. Direct load instructions; for example, MOV, POP, LDS, LSS, LGS, LFS. + These instructions explicitly reference the segment registers. + + 2. Implied load instructions; for example, far CALL and JMP. These + instructions implicitly reference the CS register, and load it with a + new value. + +Using these instructions, a program loads the visible part of the segment +register with a 16-bit selector. The processor automatically fetches the +base address, limit, type, and other information from a descriptor table and +loads them into the invisible part of the segment register. + +Because most instructions refer to data in segments whose selectors have +already been loaded into segment registers, the processor can add the +segment-relative offset supplied by the instruction to the segment base +address with no additional overhead. + + +5.2 Page Translation + +In the second phase of address transformation, the 80386 transforms a +linear address into a physical address. This phase of address transformation +implements the basic features needed for page-oriented virtual-memory +systems and page-level protection. + +The page-translation step is optional. Page translation is in effect only +when the PG bit of CR0 is set. This bit is typically set by the operating +system during software initialization. The PG bit must be set if the +operating system is to implement multiple virtual 8086 tasks, page-oriented +protection, or page-oriented virtual memory. + + +5.2.1 Page Frame + +A page frame is a 4K-byte unit of contiguous addresses of physical memory. +Pages begin onbyte boundaries and are fixed in size. + + +5.2.2 Linear Address + +A linear address refers indirectly to a physical address by specifying a +page table, a page within that table, and an offset within that page. Figure +5-8 shows the format of a linear address. + +Figure 5-9 shows how the processor converts the DIR, PAGE, and OFFSET +fields of a linear address into the physical address by consulting two +levels of page tables. The addressing mechanism uses the DIR field as an +index into a page directory, uses the PAGE field as an index into the page +table determined by the page directory, and uses the OFFSET field to address +a byte within the page determined by the page table. + + +Figure 5-8. Format of a Linear Address + + 31 22 21 12 11 0 + ͻ + + DIR PAGE OFFSET + + ͼ + + +Figure 5-9. Page Translation + + PAGE FRAME + ͻ ͻ + DIR PAGE OFFSET + ͼ + +  PHYSICAL + ADDRESS + PAGE DIRECTORY PAGE TABLE + ͻ ͻ + ͼ + ͹  +  PG TBL ENTRY + ͹ ͹ +  DIR ENTRY Ŀ + ͹ + + ͼ ͼ +   +ͻ + CR3 +ͼ + + +5.2.3 Page Tables + +A page table is simply an array of 32-bit page specifiers. A page table is +itself a page, and therefore contains 4 Kilobytes of memory or at most 1K +32-bit entries. + +Two levels of tables are used to address a page of memory. At the higher +level is a page directory. The page directory addresses up to 1K page tables +of the second level. A page table of the second level addresses up to 1K +pages. All the tables addressed by one page directory, therefore, can +address 1M pages (2^(20)). Because each page contains 4K bytes 2^(12) +bytes), the tables of one page directory can span the entire physical +address space of the 80386 (2^(20) times 2^(12) = 2^(32)). + +The physical address of the current page directory is stored in the CPU +register CR3, also called the page directory base register (PDBR). Memory +management software has the option of using one page directory for all +tasks, one page directory for each task, or some combination of the two. +Refer to Chapter 10 for information on initialization of CR3. Refer to +Chapter 7 to see how CR3 can change for each task. + + +5.2.4 Page-Table Entries + +Entries in either level of page tables have the same format. Figure 5-10 +illustrates this format. + + +5.2.4.1 Page Frame Address + +The page frame address specifies the physical starting address of a page. +Because pages are located on 4K boundaries, the low-order 12 bits are always +zero. In a page directory, the page frame address is the address of a page +table. In a second-level page table, the page frame address is the address +of the page frame that contains the desired memory operand. + + +5.2.4.2 Present Bit + +The Present bit indicates whether a page table entry can be used in address +translation. P=1 indicates that the entry can be used. + +When P=0 in either level of page tables, the entry is not valid for address +translation, and the rest of the entry is available for software use; none +of the other bits in the entry is tested by the hardware. Figure 5-11 +illustrates the format of a page-table entry when P=0. + +If P=0 in either level of page tables when an attempt is made to use a +page-table entry for address translation, the processor signals a page +exception. In software systems that support paged virtual memory, the +page-not-present exception handler can bring the required page into physical +memory. The instruction that caused the exception can then be reexecuted. +Refer to Chapter 9 for more information on exception handlers. + +Note that there is no present bit for the page directory itself. The page +directory may be not-present while the associated task is suspended, but the +operating system must ensure that the page directory indicated by the CR3 +image in the TSS is present in physical memory before the task is +dispatched. Refer to Chapter 7 for an explanation of the TSS and task +dispatching. + + +Figure 5-10. Format of a Page Table Entry + + 31 12 11 0 + ͻ + UR + PAGE FRAME ADDRESS 31..12 AVAIL 0 0DA0 0//P + SW + ͼ + + P - PRESENT + R/W - READ/WRITE + U/S - USER/SUPERVISOR + D - DIRTY + AVAIL - AVAILABLE FOR SYSTEMS PROGRAMMER USE + + NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. + + +Figure 5-11. Invalid Page Table Entry + + 31 1 0 + ͻ + + AVAILABLE 0 + + ͼ + + +5.2.4.3 Accessed and Dirty Bits + +These bits provide data about page usage in both levels of the page tables. +With the exception of the dirty bit in a page directory entry, these bits +are set by the hardware; however, the processor does not clear any of these +bits. + +The processor sets the corresponding accessed bits in both levels of page +tables to one before a read or write operation to a page. + +The processor sets the dirty bit in the second-level page table to one +before a write to an address covered by that page table entry. The dirty bit +in directory entries is undefined. + +An operating system that supports paged virtual memory can use these bits +to determine what pages to eliminate from physical memory when the demand +for memory exceeds the physical memory available. The operating system is +responsible for testing and clearing these bits. + +Refer to Chapter 11 for how the 80386 coordinates updates to the accessed +and dirty bits in multiprocessor systems. + + +5.2.4.4 Read/Write and User/Supervisor Bits + +These bits are not used for address translation, but are used for +page-level protection, which the processor performs at the same time as +address translation. Refer to Chapter 6 where protection is discussed in +detail. + + +5.2.5 Page Translation Cache + +For greatest efficiency in address translation, the processor stores the +most recently used page-table data in an on-chip cache. Only if the +necessary paging information is not in the cache must both levels of page +tables be referenced. + +The existence of the page-translation cache is invisible to applications +programmers but not to systems programmers; operating-system programmers +must flush the cache whenever the page tables are changed. The +page-translation cache can be flushed by either of two methods: + + 1. By reloading CR3 with a MOV instruction; for example: + + MOV CR3, EAX + + 2. By performing a task switch to a TSS that has a different CR3 image + than the current TSS. (Refer to Chapter 7 for more information on + task switching.) + + +5.3 Combining Segment and Page Translation + +Figure 5-12 combines Figure 5-2 and Figure 5-9 to summarize both phases +of the transformation from a logical address to a physical address when +paging is enabled. By appropriate choice of options and parameters to both +phases, memory-management software can implement several different styles of +memory management. + + +5.3.1 "Flat" Architecture + +When the 80386 is used to execute software designed for architectures that +don't have segments, it may be expedient to effectively "turn off" the +segmentation features of the 80386. The 80386 does not have a mode that +disables segmentation, but the same effect can be achieved by initially +loading the segment registers with selectors for descriptors that encompass +the entire 32-bit linear address space. Once loaded, the segment registers +don't need to be changed. The 32-bit offsets used by 80386 instructions are +adequate to address the entire linear-address space. + + +5.3.2 Segments Spanning Several Pages + +The architecture of the 80386 permits segments to be larger or smaller than +the size of a page (4 Kilobytes). For example, suppose a segment is used to +address and protect a large data structure that spans 132 Kilobytes. In a +software system that supports paged virtual memory, it is not necessary for +the entire structure to be in physical memory at once. The structure is +divided into 33 pages, any number of which may not be present. The +applications programmer does not need to be aware that the virtual memory +subsystem is paging the structure in this manner. + + +Figure 5-12. 80306 Addressing Machanism + + 16 0 32 0 + ͻ LOGICAL + SELECTOR OFFSET ADDRESS + ͼ +  + DESCRIPTOR TABLE + ͻ + + + + + ͹ + SEGMENT ͻ +  DESCRIPTOR  +  + ͹ ͼ + + ͼ +  PAGE FRAME + LINEAR ͻ ͻ + ADDRESS DIR PAGE OFFSET + ͼ + +  PHYSICAL + ADDRESS + PAGE DIRECTORY PAGE TABLE + ͻ ͻ + + ͼ + ͹  +  PG TBL ENTRY + ͹ ͹ +  DIR ENTRY Ŀ + ͹ + + ͼ ͼ +   +ͻ + CR3 +ͼ + + +5.3.3 Pages Spanning Several Segments + +On the other hand, segments may be smaller than the size of a page. For +example, consider a small data structure such as a semaphore. Because of the +protection and sharing provided by segments (refer to Chapter 6), it may be +useful to create a separate segment for each semaphore. But, because a +system may need many semaphores, it is not efficient to allocate a page for +each. Therefore, it may be useful to cluster many related segments within a +page. + + +5.3.4 Non-Aligned Page and Segment Boundaries + +The architecture of the 80386 does not enforce any correspondence between +the boundaries of pages and segments. It is perfectly permissible for a page +to contain the end of one segment and the beginning of another. Likewise, a +segment may contain the end of one page and the beginning of another. + + +5.3.5 Aligned Page and Segment Boundaries + +Memory-management software may be simpler, however, if it enforces some +correspondence between page and segment boundaries. For example, if segments +are allocated only in units of one page, the logic for segment and page +allocation can be combined. There is no need for logic to account for +partially used pages. + + +5.3.6 Page-Table per Segment + +An approach to space management that provides even further simplification +of space-management software is to maintain a one-to-one correspondence +between segment descriptors and page-directory entries, as Figure 5-13 +illustrates. Each descriptor has a base address in which the low-order 22 +bits are zero; in other words, the base address is mapped by the first entry +of a page table. A segment may have any limit from 1 to 4 megabytes. +Depending on the limit, the segment is contained in from 1 to 1K page +frames. A task is thus limited to 1K segments (a sufficient number for many +applications), each containing up to 4 Mbytes. The descriptor, the +corresponding page-directory entry, and the corresponding page table can be +allocated and deallocated simultaneously. + + +Figure 5-13. Descriptor per Page Table + + PAGE FRAMES + ͻ + LDT PAGE DIRECTORY PAGE TABLES + ͻ ͻ ͻ + ͼ + ͹ ͹ ͹ + PTE ͻ + ͹ ͹ ͹ + PTE Ŀ + ͹ ͹ ͹ ͼ + PTE Ŀ + ͹ ͹ ͼ ͻ + DESCRIPTOR PDE + ͹ ͹ + DESCRIPTOR PDE Ŀ ͼ + ͹ ͹ ͻ + ͻ + ͹ ͹ ͹ + + ͹ ͹ ͹ ͼ + PTE + ͹ ͹ ͹ ͻ + PTE Ŀ + ͼ ͼ ͼ + LDT PAGE DIRECTORY PAGE TABLES ͼ + PAGE FRAMES + + +Chapter 6 Protection + + + +6.1 Why Protection? + +The purpose of the protection features of the 80386 is to help detect and +identify bugs. The 80386 supports sophisticated applications that may +consist of hundreds or thousands of program modules. In such applications, +the question is how bugs can be found and eliminated as quickly as possible +and how their damage can be tightly confined. To help debug applications +faster and make them more robust in production, the 80386 contains +mechanisms to verify memory accesses and instruction execution for +conformance to protection criteria. These mechanisms may be used or ignored, +according to system design objectives. + + +6.2 Overview of 80386 Protection Mechanisms + +Protection in the 80386 has five aspects: + + 1. Type checking + 2. Limit checking + 3. Restriction of addressable domain + 4. Restriction of procedure entry points + 5. Restriction of instruction set + +The protection hardware of the 80386 is an integral part of the memory +management hardware. Protection applies both to segment translation and to +page translation. + +Each reference to memory is checked by the hardware to verify that it +satisfies the protection criteria. All these checks are made before the +memory cycle is started; any violation prevents that cycle from starting and +results in an exception. Since the checks are performed concurrently with +address formation, there is no performance penalty. + +Invalid attempts to access memory result in an exception. Refer to +Chapter 9 for an explanation of the exception mechanism. The present +chapter defines the protection violations that lead to exceptions. + +The concept of "privilege" is central to several aspects of protection +(numbers 3, 4, and 5 in the preceeding list). Applied to procedures, +privilege is the degree to which the procedure can be trusted not to make a +mistake that might affect other procedures or data. Applied to data, +privilege is the degree of protection that a data structure should have +from less trusted procedures. + +The concept of privilege applies both to segment protection and to page +protection. + + +6.3 Segment-Level Protection + +All five aspects of protection apply to segment translation: + + 1. Type checking + 2. Limit checking + 3. Restriction of addressable domain + 4. Restriction of procedure entry points + 5. Restriction of instruction set + +The segment is the unit of protection, and segment descriptors store +protection parameters. Protection checks are performed automatically by the +CPU when the selector of a segment descriptor is loaded into a segment +register and with every segment access. Segment registers hold the +protection parameters of the currently addressable segments. + + +6.3.1 Descriptors Store Protection Parameters + +Figure 6-1 highlights the protection-related fields of segment descriptors. + +The protection parameters are placed in the descriptor by systems software +at the time a descriptor is created. In general, applications programmers do +not need to be concerned about protection parameters. + +When a program loads a selector into a segment register, the processor +loads not only the base address of the segment but also protection +information. Each segment register has bits in the invisible portion for +storing base, limit, type, and privilege level; therefore, subsequent +protection checks on the same segment do not consume additional clock +cycles. + + +Figure 6-1. Protection Fields of Segment Descriptors + + DATA SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24GB0V 19..16 P DPL BASE 23..16 4 + L 10EWA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + EXECUTABLE SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24GD0V 19..16 P DPL BASE 23..16 4 + L 10CRA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + SYSTEM SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT + BASE 31..24GX0V 19..16 P DPL 0 TYPE BASE 23..16 4 + L + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + + A - ACCESSED E - EXPAND-DOWN + AVL - AVAILABLE FOR PROGRAMMERS USE G - GRANULARITY + B - BIG P - SEGMENT PRESENT + C - CONFORMING R - READABLE + D - DEFAULT W - WRITABLE + DPL - DESCRIPTOR PRIVILEGE LEVEL + + +6.3.1.1 Type Checking + +The TYPE field of a descriptor has two functions: + + 1. It distinguishes among different descriptor formats. + 2. It specifies the intended usage of a segment. + +Besides the descriptors for data and executable segments commonly used by +applications programs, the 80386 has descriptors for special segments used +by the operating system and for gates. Table 6-1 lists all the types defined +for system segments and gates. Note that not all descriptors define +segments; gate descriptors have a different purpose that is discussed later +in this chapter. + +The type fields of data and executable segment descriptors include bits +which further define the purpose of the segment (refer to Figure 6-1): + + The writable bit in a data-segment descriptor specifies whether + instructions can write into the segment. + + The readable bit in an executable-segment descriptor specifies + whether instructions are allowed to read from the segment (for example, + to access constants that are stored with instructions). A readable, + executable segment may be read in two ways: + + 1. Via the CS register, by using a CS override prefix. + + 2. By loading a selector of the descriptor into a data-segment register + (DS, ES, FS,or GS). + +Type checking can be used to detect programming errors that would attempt +to use segments in ways not intended by the programmer. The processor +examines type information on two kinds of occasions: + + 1. When a selector of a descriptor is loaded into a segment register. + Certain segment registers can contain only certain descriptor types; + for example: + + The CS register can be loaded only with a selector of an executable + segment. + + Selectors of executable segments that are not readable cannot be + loaded into data-segment registers. + + Only selectors of writable data segments can be loaded into SS. + + 2. When an instruction refers (implicitly or explicitly) to a segment + register. Certain segments can be used by instructions only in certain + predefined ways; for example: + + No instruction may write into an executable segment. + + No instruction may write into a data segment if the writable bit is + not set. + + No instruction may read an executable segment unless the readable bit + is set. + + +Table 6-1. System and Gate Descriptor Types + +Code Type of Segment or Gate + + 0 -reserved + 1 Available 286 TSS + 2 LDT + 3 Busy 286 TSS + 4 Call Gate + 5 Task Gate + 6 286 Interrupt Gate + 7 286 Trap Gate + 8 -reserved + 9 Available 386 TSS + A -reserved + B Busy 386 TSS + C 386 Call Gate + D -reserved + E 386 Interrupt Gate + F 386 Trap Gate + + +6.3.1.2 Limit Checking + +The limit field of a segment descriptor is used by the processor to prevent +programs from addressing outside the segment. The processor's interpretation +of the limit depends on the setting of the G (granularity) bit. For data +segments, the processor's interpretation of the limit depends also on the +E-bit (expansion-direction bit) and the B-bit (big bit) (refer to Table +6-2). + +When G=0, the actual limit is the value of the 20-bit limit field as it +appears in the descriptor. In this case, the limit may range from 0 to +0FFFFFH (2^(20) - 1 or 1 megabyte). When G=1, the processor appends 12 +low-order one-bits to the value in the limit field. In this case the actual +limit may range from 0FFFH (2^(12) - 1 or 4 kilobytes) to 0FFFFFFFFH(2^(32) +- 1 or 4 gigabytes). + +For all types of segments except expand-down data segments, the value of +the limit is one less than the size (expressed in bytes) of the segment. The +processor causes a general-protection exception in any of these cases: + + Attempt to access a memory byte at an address > limit. + Attempt to access a memory word at an address limit. + Attempt to access a memory doubleword at an address (limit-2). + +For expand-down data segments, the limit has the same function but is +interpreted differently. In these cases the range of valid addresses is from +limit + 1 to either 64K or 2^(32) - 1 (4 Gbytes) depending on the B-bit. An +expand-down segment has maximum size when the limit is zero. + +The expand-down feature makes it possible to expand the size of a stack by +copying it to a larger segment without needing also to update intrastack +pointers. + +The limit field of descriptors for descriptor tables is used by the +processor to prevent programs from selecting a table entry outside the +descriptor table. The limit of a descriptor table identifies the last valid +byte of the last descriptor in the table. Since each descriptor is eight +bytes long, the limit value is N * 8 - 1 for a table that can contain up to +N descriptors. + +Limit checking catches programming errors such as runaway subscripts and +invalid pointer calculations. Such errors are detected when they occur, so +that identification of the cause is easier. Without limit checking, such +errors could corrupt other modules; the existence of such errors would not +be discovered until later, when the corrupted module behaves incorrectly, +and when identification of the cause is difficult. + + +Table 6-2. Useful Combinations of E, G, and B Bits + + +Case: 1 2 3 4 + +Expansion Direction U U D D +G-bit 0 1 0 1 +B-bit X X 0 1 + +Lower bound is: + 0 X X + LIMIT+1 X +shl(LIMIT,12,1)+1 X + +Upper bound is: + LIMIT X + shl(LIMIT,12,1) X + 64K-1 X + 4G-1 X + +Max seg size is: + 64K X + 64K-1 X + 4G-4K X + 4G X + +Min seg size is: + 0 X X + 4K X X + +shl (X, 12, 1) = shift X left by 12 bits inserting one-bits on the right + + +6.3.1.3 Privilege Levels + +The concept of privilege is implemented by assigning a value from zero to +three to key objects recognized by the processor. This value is called the +privilege level. The value zero represents the greatest privilege, the +value three represents the least privilege. The following +processor-recognized objects contain privilege levels: + + Descriptors contain a field called the descriptor privilege level + (DPL). + + Selectors contain a field called the requestor's privilege level + (RPL). The RPL is intended to represent the privilege level of + the procedure that originates a selector. + + An internal processor register records the current privilege level + (CPL). Normally the CPL is equal to the DPL of the segment that + the processor is currently executing. CPL changes as control is + transferred to segments with differing DPLs. + +The processor automatically evaluates the right of a procedure to access +another segment by comparing the CPL to one or more other privilege levels. +The evaluation is performed at the time the selector of a descriptor is +loaded into a segment register. The criteria used for evaluating access to +data differs from that for evaluating transfers of control to executable +segments; therefore, the two types of access are considered separately in +the following sections. + +Figure 6-2 shows how these levels of privilege can be interpreted as rings +of protection. The center is for the segments containing the most critical +software, usually the kernel of the operating system. Outer rings are for +the segments of less critical software. + +It is not necessary to use all four privilege levels. Existing software +that was designed to use only one or two levels of privilege can simply +ignore the other levels offered by the 80386. A one-level system should use +privilege level zero; a two-level system should use privilege levels zero +and three. + + +Figure 6-2. Levels of Privilege + + TASK C + Ŀ + ͻ + APPLICATIONS + ͻ + CUSTOM EXTENSIONS + ͻ + SYSTEM SERVICES + ͻ + KERNAL + Ķ͵ + LEVELLEVELLEVELLEVEL + 0 1 2 3 + ͼ + + ͼ + + ͼ + + TASK B ͼ TASK A + + + +6.3.2 Restricting Access to Data + +To address operands in memory, an 80386 program must load the selector of a +data segment into a data-segment register (DS, ES, FS, GS, SS). The +processor automatically evaluates access to a data segment by comparing +privilege levels. The evaluation is performed at the time a selector for the +descriptor of the target segment is loaded into the data-segment register. +As Figure 6-3 shows, three different privilege levels enter into this type +of privilege check: + + 1. The CPL (current privilege level). + + 2. The RPL (requestor's privilege level) of the selector used to specify + the target segment. + + 3. The DPL of the descriptor of the target segment. + +Instructions may load a data-segment register (and subsequently use the +target segment) only if the DPL of the target segment is numerically greater +than or equal to the maximum of the CPL and the selector's RPL. In other +words, a procedure can only access data that is at the same or less +privileged level. + +The addressable domain of a task varies as CPL changes. When CPL is zero, +data segments at all privilege levels are accessible; when CPL is one, only +data segments at privilege levels one through three are accessible; when CPL +is three, only data segments at privilege level three are accessible. This +property of the 80386 can be used, for example, to prevent applications +procedures from reading or changing tables of the operating system. + + +Figure 6-3. Privilege Check for Data Access + + 16-BIT VISIBLE + SELECTOR INVISIBLE DESCRIPTOR + ͻ + CS CPL + ͼ + + TARGET SEGMENT SELECTOR ͻ + ͻ  PRIVILEGE + INDEX RPL CHECK + ͼ  BY CPU + ͼ + DATA SEGMENT DESCRIPTOR + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24 GB0V P DPL BASE 23..16 4 + L 19..16 10EWA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + + CPL - CURRENT PRIVILEGE LEVEL + RPL - REQUESTOR'S PRIVILEGE LEVEL + DPL - DESCRIPTOR PRIVILEGE LEVEL + + +6.3.2.1 Accessing Data in Code Segments + +Less common than the use of data segments is the use of code segments to +store data. Code segments may legitimately hold constants; it is not +possible to write to a segment described as a code segment. The following +methods of accessing data in code segments are possible: + + 1. Load a data-segment register with a selector of a nonconforming, + readable, executable segment. + + 2. Load a data-segment register with a selector of a conforming, + readable, executable segment. + + 3. Use a CS override prefix to read a readable, executable segment whose + selector is already loaded in the CS register. + +The same rules as for access to data segments apply to case 1. Case 2 is +always valid because the privilege level of a segment whose conforming bit +is set is effectively the same as CPL regardless of its DPL. Case 3 always +valid because the DPL of the code segment in CS is, by definition, equal to +CPL. + + +6.3.3 Restricting Control Transfers + +With the 80386, control transfers are accomplished by the instructions JMP, +CALL, RET, INT, and IRET, as well as by the exception and interrupt +mechanisms. Exceptions and interrupts are special cases that Chapter 9 +covers. This chapter discusses only JMP, CALL, and RET instructions. + +The "near" forms of JMP, CALL, and RET transfer within the current code +segment, and therefore are subject only to limit checking. The processor +ensures that the destination of the JMP, CALL, or RET instruction does not +exceed the limit of the current executable segment. This limit is cached in +the CS register; therefore, protection checks for near transfers require no +extra clock cycles. + +The operands of the "far" forms of JMP and CALL refer to other segments; +therefore, the processor performs privilege checking. There are two ways a +JMP or CALL can refer to another segment: + + 1. The operand selects the descriptor of another executable segment. + + 2. The operand selects a call gate descriptor. This gated form of + transfer is discussed in a later section on call gates. + +As Figure 6-4 shows, two different privilege levels enter into a privilege +check for a control transfer that does not use a call gate: + + 1. The CPL (current privilege level). + 2. The DPL of the descriptor of the target segment. + +Normally the CPL is equal to the DPL of the segment that the processor is +currently executing. CPL may, however, be greater than DPL if the conforming +bit is set in the descriptor of the current executable segment. The +processor keeps a record of the CPL cached in the CS register; this value +can be different from the DPL in the descriptor of the code segment. + +The processor permits a JMP or CALL directly to another segment only if one +of the following privilege rules is satisfied: + + DPL of the target is equal to CPL. + + The conforming bit of the target code-segment descriptor is set, and + the DPL of the target is less than or equal to CPL. + +An executable segment whose descriptor has the conforming bit set is called +a conforming segment. The conforming-segment mechanism permits sharing of +procedures that may be called from various privilege levels but should +execute at the privilege level of the calling procedure. Examples of such +procedures include math libraries and some exception handlers. When control +is transferred to a conforming segment, the CPL does not change. This is +the only case when CPL may be unequal to the DPL of the current executable +segment. + +Most code segments are not conforming. The basic rules of privilege above +mean that, for nonconforming segments, control can be transferred without a +gate only to executable segments at the same level of privilege. There is a +need, however, to transfer control to (numerically) smaller privilege +levels; this need is met by the CALL instruction when used with call-gate +descriptors, which are explained in the next section. The JMP instruction +may never transfer control to a nonconforming segment whose DPL does not +equal CPL. + + +Figure 6-4. Privilege Check for Control Transfer without Gate + + 16-BIT VISIBLE + SELECTOR INVISIBLE PART + ͻ + CPL CS + ͼ + + ͻ +  PRIVILEGE +  CHECK +  BY CPU + CODE-SEGMENT DESCRIPTOR ͼ + + 31 23 15 7 0 + ͻ + A LIMIT + BASE 31..24 GD0V P DPL BASE 23..16 4 + L 19..16 11CRA + Ķ + + SEGMENT BASE 15..0 SEGMENT LIMIT 15..0 0 + + ͼ + + CPL - CURRENT PRIVILEGE LEVEL + DPL - DESCRIPTOR PRIVILEGE LEVEL + C - CONFORMING BIT + + +6.3.4 Gate Descriptors Guard Procedure Entry Points + +To provide protection for control transfers among executable segments +at different privilege levels, the 80386 uses gate descriptors. There are +four kinds of gate descriptors: + + Call gates + Trap gates + Interrupt gates + Task gates + +This chapter is concerned only with call gates. Task gates are used for +task switching, and therefore are discussed in Chapter 7. Chapter 9 +explains how trap gates and interrupt gates are used by exceptions and +interrupts. Figure 6-5 illustrates the format of a call gate. A call gate +descriptor may reside in the GDT or in an LDT, but not in the IDT. + +A call gate has two primary functions: + + 1. To define an entry point of a procedure. + 2. To specify the privilege level of the entry point. + +Call gate descriptors are used by call and jump instructions in the same +manner as code segment descriptors. When the hardware recognizes that the +destination selector refers to a gate descriptor, the operation of the +instruction is expanded as determined by the contents of the call gate. + +The selector and offset fields of a gate form a pointer to the entry point +of a procedure. A call gate guarantees that all transitions to another +segment go to a valid entry point, rather than possibly into the middle of a +procedure (or worse, into the middle of an instruction). The far pointer +operand of the control transfer instruction does not point to the segment +and offset of the target instruction; rather, the selector part of the +pointer selects a gate, and the offset is not used. Figure 6-6 illustrates +this style of addressing. + +As Figure 6-7 shows, four different privilege levels are used to check the +validity of a control transfer via a call gate: + + 1. The CPL (current privilege level). + + 2. The RPL (requestor's privilege level) of the selector used to specify + the call gate. + + 3. The DPL of the gate descriptor. + + 4. The DPL of the descriptor of the target executable segment. + +The DPL field of the gate descriptor determines what privilege levels can +use the gate. One code segment can have several procedures that are intended +for use by different privilege levels. For example, an operating system may +have some services that are intended to be used by applications, whereas +others may be intended only for use by other systems software. + +Gates can be used for control transfers to numerically smaller privilege +levels or to the same privilege level (though they are not necessary for +transfers to the same level). Only CALL instructions can use gates to +transfer to smaller privilege levels. A gate may be used by a JMP +instruction only to transfer to an executable segment with the same +privilege level or to a conforming segment. + +For a JMP instruction to a nonconforming segment, both of the following +privilege rules must be satisfied; otherwise, a general protection exception +results. + + MAX (CPL,RPL) gate DPL + target segment DPL = CPL + +For a CALL instruction (or for a JMP instruction to a conforming segment), +both of the following privilege rules must be satisfied; otherwise, a +general protection exception results. + + MAX (CPL,RPL) gate DPL + target segment DPL CPL + + +Figure 6-5. Format of 80386 Call Gate + + 31 23 15 7 0 + ͻ + TYPE DWORD + OFFSET 31..16 P DPL 0 0 0 4 + 0 1 1 0 0 COUNT + Ķ + + SELECTOR OFFSET 15..0 0 + + ͼ + + +Figure 6-6. Indirect Transfer via Call Gate + + OPCODE OFFSET SELECTOR + ͻ + CALL (NOT USED) INDEX RPL + ͼ + + DESCRIPTOR TABLE + ͻ + + Ķ + + ͼ +   +   +   + ͻ + GATE OFFSET DPL COUNT  EXECUTABLE + DESCRIPTOR Ķ SEGMENT + Ķ SELECTOR OFFSET Ŀ ͻ + ͹ + + Ķ + + ͹ +  PROCEDURE + Ķ + +  ͹ + EXECUTABLE BASE DPL BASE + SEGMENT Ķ ͼ + DESCRIPTOR BASE + ͼ +   +   +   + ͻ + + Ķ + + ͼ + + +Figure 6-7. Privilege Check via Call Gate + + 16-BIT VISIBLE + SELECTOR INVISIBLE DESCRIPTOR + ͻ + CS CPL + ͼ + + TARGET SELECTOR ͻ + ͻ  PRIVILEGE + INDEX RPL CHECK + ͼ  BY +  CPU + ͼ + + GATE DESCRIPTOR  + ͻ + OFFSET DPL COUNT + ͹ + SELECTOR OFFSET + ͼ + + + ͻ + EXECUTABLE BASE LIMIT DPL BASE + SEGMENT ͹ + DESCRIPTOR BASE LIMIT + ͼ + + CPL - CURRENT PRIVILEGE LEVEL + RPL - REQUESTOR'S PRIVILEGE LEVEL + DPL - DESCRIPTOR PRIVILEGE LEVEL + + +6.3.4.1 Stack Switching + +If the destination code segment of the call gate is at a different +privilege level than the CPL, an interlevel transfer is being requested. + +To maintain system integrity, each privilege level has a separate stack. +These stacks assure sufficient stack space to process calls from less +privileged levels. Without them, a trusted procedure would not work +correctly if the calling procedure did not provide sufficient space on the +caller's stack. + +The processor locates these stacks via the task state segment (see Figure +6-8). Each task has a separate TSS, thereby permitting tasks to have +separate stacks. Systems software is responsible for creating TSSs and +placing correct stack pointers in them. The initial stack pointers in the +TSS are strictly read-only values. The processor never changes them during +the course of execution. + +When a call gate is used to change privilege levels, a new stack is +selected by loading a pointer value from the Task State Segment (TSS). The +processor uses the DPL of the target code segment (the new CPL) to index the +initial stack pointer for PL 0, PL 1, or PL 2. + +The DPL of the new stack data segment must equal the new CPL; if it does +not, a stack exception occurs. It is the responsibility of systems software +to create stacks and stack-segment descriptors for all privilege levels that +are used. Each stack must contain enough space to hold the old SS:ESP, the +return address, and all parameters and local variables that may be required +to process a call. + +As with intralevel calls, parameters for the subroutine are placed on the +stack. To make privilege transitions transparent to the called procedure, +the processor copies the parameters to the new stack. The count field of a +call gate tells the processor how many doublewords (up to 31) to copy from +the caller's stack to the new stack. If the count is zero, no parameters are +copied. + +The processor performs the following stack-related steps in executing an +interlevel CALL. + + 1. The new stack is checked to assure that it is large enough to hold + the parameters and linkages; if it is not, a stack fault occurs with + an error code of 0. + + 2. The old value of the stack registers SS:ESP is pushed onto the new + stack as two doublewords. + + 3. The parameters are copied. + + 4. A pointer to the instruction after the CALL instruction (the former + value of CS:EIP) is pushed onto the new stack. The final value of + SS:ESP points to this return pointer on the new stack. + +Figure 6-9 illustrates the stack contents after a successful interlevel +call. + +The TSS does not have a stack pointer for a privilege level 3 stack, +because privilege level 3 cannot be called by any procedure at any other +privilege level. + +Procedures that may be called from another privilege level and that require +more than the 31 doublewords for parameters must use the saved SS:ESP link +to access all parameters beyond the last doubleword copied. + +A call via a call gate does not check the values of the words copied onto +the new stack. The called procedure should check each parameter for +validity. A later section discusses how the ARPL, VERR, VERW, LSL, and LAR +instructions can be used to check pointer values. + + +Figure 6-8. Initial Stack Pointers of TSS + + 31 23 15 7 0 + ͻ64 +   +   +   + + ͹ + EFLAGS 24 + ͹ + INSTRUCTION POINTER (EIP) 20 + ͹ + CR3 (PDBR) 1C + ͹ Ŀ + 00000000 00000000 SS2 1018 + ͹ + ESP2 14 + ͹ + 00000000 00000000 SS1 0110 INITIAL + ͹ STACK + ESP1 0C POINTERS + ͹ + 00000000 00000000 SS0 008 + ͹ + ESP0 4 + ͹ + 00000000 00000000 TSS BACK LINK 0 + ͼ + + +Figure 6-9. Stack Contents after an Interlevel Call + + 31 0 SS:ESP + ͻFROM TSS + 31 0 OLD SS + ͻ ͹ + D O OLD ESP + I F ͹ + R PARM 3 + E E ͹ + C X PARM 2 + T P ͹ ͹ + I A PARM 3 PARM 1 + O N ͹ ͹ + N S PARM 2 OLD CS NEW + I ͹ OLD ͹ SS:ESP + O PARM 1 SS:ESP OLD EIP + N ͹ ͹ + +  + ͼ ͼ + OLD STACK NEW STACK + + +6.3.4.2 Returning from a Procedure + +The "near" forms of the RET instruction transfer control within the current +code segment and therefore are subject only to limit checking. The offset of +the instruction following the corresponding CALL, is popped from the stack. +The processor ensures that this offset does not exceed the limit of the +current executable segment. + +The "far" form of the RET instruction pops the return pointer that was +pushed onto the stack by a prior far CALL instruction. Under normal +conditions, the return pointer is valid, because of its relation to the +prior CALL or INT. Nevertheless, the processor performs privilege checking +because of the possibility that the current procedure altered the pointer or +failed to properly maintain the stack. The RPL of the CS selector popped +off the stack by the return instruction identifies the privilege level of +the calling procedure. + +An intersegment return instruction can change privilege levels, but only +toward procedures of lesser privilege. When the RET instruction encounters a +saved CS value whose RPL is numerically greater than the CPL, an interlevel +return occurs. Such a return follows these steps: + + 1. The checks shown in Table 6-3 are made, and CS:EIP and SS:ESP are + loaded with their former values that were saved on the stack. + + 2. The old SS:ESP (from the top of the current stack) value is adjusted + by the number of bytes indicated in the RET instruction. The resulting + ESP value is not compared to the limit of the stack segment. If ESP is + beyond the limit, that fact is not recognized until the next stack + operation. (The SS:ESP value of the returning procedure is not + preserved; normally, this value is the same as that contained in the + TSS.) + + 3. The contents of the DS, ES, FS, and GS segment registers are checked. + If any of these registers refer to segments whose DPL is greater than + the new CPL (excluding conforming code segments), the segment register + is loaded with the null selector (INDEX = 0, TI = 0). The RET + instruction itself does not signal exceptions in these cases; + however, any subsequent memory reference that attempts to use a + segment register that contains the null selector will cause a general + protection exception. This prevents less privileged code from + accessing more privileged segments using selectors left in the + segment registers by the more privileged procedure. + + +6.3.5 Some Instructions are Reserved for Operating System + +Instructions that have the power to affect the protection mechanism or to +influence general system performance can only be executed by trusted +procedures. The 80386 has two classes of such instructions: + + 1. Privileged instructions those used for system control. + + 2. Sensitive instructions those used for I/O and I/O related + activities. + + +Table 6-3. Interlevel Return Checks + + +Type of Check Exception +SF Stack Fault +GP General Protection Exception +NP Segment-Not-Present Exception Error Code + +ESP is within current SS segment SF 0 +ESP + 7 is within current SS segment SF 0 +RPL of return CS is greater than CPL GP Return CS +Return CS selector is not null GP Return CS +Return CS segment is within descriptor +table limit GP Return CS +Return CS descriptor is a code segment GP Return CS +Return CS segment is present NP Return CS +DPL of return nonconforming code +segment = RPL of return CS, or DPL of +return conforming code segment RPL +of return CS GP Return CS +ESP + N + 15 is within SS segment +N Immediate Operand of RET N Instruction SF Return SS +SS selector at ESP + N + 12 is not null GP Return SS +SS selector at ESP + N + 12 is within +descriptor table limit GP Return SS +SS descriptor is writable data segment GP Return SS +SS segment is present SF Return SS +Saved SS segment DPL = RPL of saved +CS GP Return SS +Saved SS selector RPL = Saved SS +segment DPL GP Return SS + + +6.3.5.1 Privileged Instructions + +The instructions that affect system data structures can only be executed +when CPL is zero. If the CPU encounters one of these instructions when CPL +is greater than zero, it signals a general protection exception. These +instructions include: + + CLTS Clear TaskSwitched Flag + HLT Halt Processor + LGDT Load GDL Register + LIDT Load IDT Register + LLDT Load LDT Register + LMSW Load Machine Status Word + LTR Load Task Register + MOV to/from CRn Move to Control Register n + MOV to /from DRn Move to Debug Register n + MOV to/from TRn Move to Test Register n + + +6.3.5.2 Sensitive Instructions + +Instructions that deal with I/O need to be restricted but also need to be +executed by procedures executing at privilege levels other than zero. The +mechanisms for restriction of I/O operations are covered in detail in +Chapter 8, "Input/Output". + + +6.3.6 Instructions for Pointer Validation + +Pointer validation is an important part of locating programming errors. +Pointer validation is necessary for maintaining isolation between the +privilege levels. Pointer validation consists of the following steps: + + 1. Check if the supplier of the pointer is entitled to access the + segment. + + 2. Check if the segment type is appropriate to its intended use. + + 3. Check if the pointer violates the segment limit. + +Although the 80386 processor automatically performs checks 2 and 3 during +instruction execution, software must assist in performing the first check. +The unprivileged instruction ARPL is provided for this purpose. Software can +also explicitly perform steps 2 and 3 to check for potential violations +(rather than waiting for an exception). The unprivileged instructions LAR, +LSL, VERR, and VERW are provided for this purpose. + +LAR (Load Access Rights) is used to verify that a pointer refers to a +segment of the proper privilege level and type. LAR has one operanda +selector for a descriptor whose access rights are to be examined. The +descriptor must be visible at the privilege level which is the maximum of +the CPL and the selector's RPL. If the descriptor is visible, LAR obtains a +masked form of the second doubleword of the descriptor, masks this value +with 00FxFF00H, stores the result into the specified 32-bit destination +register, and sets the zero flag. (The x indicates that the corresponding +four bits of the stored value are undefined.) Once loaded, the access-rights +bits can be tested. All valid descriptor types can be tested by the LAR +instruction. If the RPL or CPL is greater than DPL, or if the selector is +outside the table limit, no access-rights value is returned, and the zero +flag is cleared. Conforming code segments may be accessed from any privilege +level. + +LSL (Load Segment Limit) allows software to test the limit of a descriptor. +If the descriptor denoted by the given selector (in memory or a register) is +visible at the CPL, LSL loads the specified 32-bit register with a 32-bit, +byte granular, unscrambled limit that is calculated from fragmented limit +fields and the G-bit of that descriptor. This can only be done for segments +(data, code, task state, and local descriptor tables); gate descriptors are +inaccessible. (Table 6-4 lists in detail which types are valid and which +are not.) Interpreting the limit is a function of the segment type. For +example, downward expandable data segments treat the limit differently than +code segments do. For both LAR and LSL, the zero flag (ZF) is set if the +loading was performed; otherwise, the ZF is cleared. + + +Table 6-4. Valid Descriptor Types for LSL + + Type Descriptor Type Valid? + Code + + 0 (invalid) NO + 1 Available 286 TSS YES + 2 LDT YES + 3 Busy 286 TSS YES + 4 286 Call Gate NO + 5 Task Gate NO + 6 286 Trap Gate NO + 7 286 Interrupt Gate NO + 8 (invalid) NO + 9 Available 386 TSS YES + A (invalid) NO + B Busy 386 TSS YES + C 386 Call Gate NO + D (invalid) NO + E 386 Trap Gate NO + F 386 Interrupt Gate NO + + +6.3.6.1 Descriptor Validation + +The 80386 has two instructions, VERR and VERW, which determine whether a +selector points to a segment that can be read or written at the current +privilege level. Neither instruction causes a protection fault if the result +is negative. + +VERR (Verify for Reading) verifies a segment for reading and loads ZF with +1 if that segment is readable from the current privilege level. VERR checks +that: + + The selector points to a descriptor within the bounds of the GDT or + LDT. + + It denotes a code or data segment descriptor. + + The segment is readable and of appropriate privilege level. + +The privilege check for data segments and nonconforming code segments is +that the DPL must be numerically greater than or equal to both the CPL and +the selector's RPL. Conforming segments are not checked for privilege level. + +VERW (Verify for Writing) provides the same capability as VERR for +verifying writability. Like the VERR instruction, VERW loads ZF if the +result of the writability check is positive. The instruction checks that the +descriptor is within bounds, is a segment descriptor, is writable, and that +its DPL is numerically greater or equal to both the CPL and the selector's +RPL. Code segments are never writable, conforming or not. + + +6.3.6.2 Pointer Integrity and RPL + +The Requestor's Privilege Level (RPL) feature can prevent inappropriate use +of pointers that could corrupt the operation of more privileged code or data +from a less privileged level. + +A common example is a file system procedure, FREAD (file_id, n_bytes, +buffer_ptr). This hypothetical procedure reads data from a file into a +buffer, overwriting whatever is there. Normally, FREAD would be available at +the user level, supplying only pointers to the file system procedures and +data located and operating at a privileged level. Normally, such a procedure +prevents user-level procedures from directly changing the file tables. +However, in the absence of a standard protocol for checking pointer +validity, a user-level procedure could supply a pointer into the file tables +in place of its buffer pointer, causing the FREAD procedure to corrupt them +unwittingly. + +Use of RPL can avoid such problems. The RPL field allows a privilege +attribute to be assigned to a selector. This privilege attribute would +normally indicate the privilege level of the code which generated the +selector. The 80386 processor automatically checks the RPL of any selector +loaded into a segment register to determine whether the RPL allows access. + +To take advantage of the processor's checking of RPL, the called procedure +need only ensure that all selectors passed to it have an RPL at least as +high (numerically) as the original caller's CPL. This action guarantees that +selectors are not more trusted than their supplier. If one of the selectors +is used to access a segment that the caller would not be able to access +directly, i.e., the RPL is numerically greater than the DPL, then a +protection fault will result when that selector is loaded into a segment +register. + +ARPL (Adjust Requestor's Privilege Level) adjusts the RPL field of a +selector to become the larger of its original value and the value of the RPL +field in a specified register. The latter is normally loaded from the image +of the caller's CS register which is on the stack. If the adjustment changes +the selector's RPL, ZF (the zero flag) is set; otherwise, ZF is cleared. + + +6.4 Page-Level Protection + +Two kinds of protection are related to pages: + + 1. Restriction of addressable domain. + 2. Type checking. + + +6.4.1 Page-Table Entries Hold Protection Parameters + +Figure 6-10 highlights the fields of PDEs and PTEs that control access to +pages. + + +Figure 6-10. Protection Fields of Page Table Entries + + 31 12 11 7 0 + ͻ + UR + PAGE FRAME ADDRESS 31..12AVAIL00DA00//P + SW + ͼ + R/W - READ/WRITE + U/S - USER/SUPERVISOR + + +6.4.1.1 Restricting Addressable Domain + +The concept of privilege for pages is implemented by assigning each page to +one of two levels: + + 1. Supervisor level (U/S=0) for the operating system and other systems + software and related data. + + 2. User level (U/S=1) for applications procedures and data. + +The current level (U or S) is related to CPL. If CPL is 0, 1, or 2, the +processor is executing at supervisor level. If CPL is 3, the processor is +executing at user level. + +When the processor is executing at supervisor level, all pages are +addressable, but, when the processor is executing at user level, only pages +that belong to the user level are addressable. + + +6.4.1.2 Type Checking + +At the level of page addressing, two types are defined: + + 1. Read-only access (R/W=0) + 2. Read/write access (R/W=1) + +When the processor is executing at supervisor level, all pages are both +readable and writable. When the processor is executing at user level, only +pages that belong to user level and are marked for read/write access are +writable; pages that belong to supervisor level are neither readable nor +writable from user level. + + +6.4.2 Combining Protection of Both Levels of Page Tables + +For any one page, the protection attributes of its page directory entry may +differ from those of its page table entry. The 80386 computes the effective +protection attributes for a page by examining the protection attributes in +both the directory and the page table. Table 6-5 shows the effective +protection provided by the possible combinations of protection attributes. + + +6.4.3 Overrides to Page Protection + +Certain accesses are checked as if they are privilege-level 0 references, +even if CPL = 3: + + LDT, GDT, TSS, IDT references. + Access to inner stack during ring-crossing CALL/INT. + + +6.5 Combining Page and Segment Protection + +When paging is enabled, the 80386 first evaluates segment protection, then +evaluates page protection. If the processor detects a protection violation +at either the segment or the page level, the requested operation cannot +proceed; a protection exception occurs instead. + +For example, it is possible to define a large data segment which has some +subunits that are read-only and other subunits that are read-write. In this +case, the page directory (or page table) entries for the read-only subunits +would have the U/S and R/W bits set to x0, indicating no write rights for +all the pages described by that directory entry (or for individual pages). +This technique might be used, for example, in a UNIX-like system to define +a large data segment, part of which is read only (for shared data or ROMmed +constants). This enables UNIX-like systems to define a "flat" data space as +one large segment, use "flat" pointers to address within this "flat" space, +yet be able to protect shared data, shared files mapped into the virtual +space, and supervisor areas. + + +Table 6-5. Combining Directory and Page Protection + +Page Directory Entry Page Table Entry Combined Protection + U/S R/W U/S R/W U/S R/W + + S-0 R-0 S-0 R-0 S x + S-0 R-0 S-0 W-1 S x + S-0 R-0 U-1 R-0 S x + S-0 R-0 U-1 W-1 S x + S-0 W-1 S-0 R-0 S x + S-0 W-1 S-0 W-1 S x + S-0 W-1 U-1 R-0 S x + S-0 W-1 U-1 W-1 S x + U-1 R-0 S-0 R-0 S x + U-1 R-0 S-0 W-1 S x + U-1 R-0 U-1 R-0 U R + U-1 R-0 U-1 W-1 U R + U-1 W-1 S-0 R-0 S x + U-1 W-1 S-0 W-1 S x + U-1 W-1 U-1 R-0 U R + U-1 W-1 U-1 W-1 U W + + +NOTE + S Supervisor + R Read only + U User + W Read and Write + x indicates that when the combined U/S attribute is S, the R/W attribute + is not checked. + + + +Chapter 7 Multitasking + + + +To provide efficient, protected multitasking, the 80386 employs several +special data structures. It does not, however, use special instructions to +control multitasking; instead, it interprets ordinary control-transfer +instructions differently when they refer to the special data structures. The +registers and data structures that support multitasking are: + + Task state segment + Task state segment descriptor + Task register + Task gate descriptor + +With these structures the 80386 can rapidly switch execution from one task +to another, saving the context of the original task so that the task can be +restarted later. In addition to the simple task switch, the 80386 offers two +other task-management features: + + 1. Interrupts and exceptions can cause task switches (if needed in the + system design). The processor not only switches automatically to the + task that handles the interrupt or exception, but it automatically + switches back to the interrupted task when the interrupt or exception + has been serviced. Interrupt tasks may interrupt lower-priority + interrupt tasks to any depth. + + 2. With each switch to another task, the 80386 can also switch to + another LDT and to another page directory. Thus each task can have a + different logical-to-linear mapping and a different linear-to-physical + mapping. This is yet another protection feature, because tasks can be + isolated and prevented from interfering with one another. + + +7.1 Task State Segment + +All the information the processor needs in order to manage a task is stored +in a special type of segment, a task state segment (TSS). Figure 7-1 shows +the format of a TSS for executing 80386 tasks. (Another format is used for +executing 80286 tasks; refer to Chapter 13.) + +The fields of a TSS belong to two classes: + + 1. A dynamic set that the processor updates with each switch from the + task. This set includes the fields that store: + + The general registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI). + + The segment registers (ES, CS, SS, DS, FS, GS). + + The flags register (EFLAGS). + + The instruction pointer (EIP). + + The selector of the TSS of the previously executing task (updated + only when a return is expected). + + 2. A static set that the processor reads but does not change. This set + includes the fields that store: + + The selector of the task's LDT. + + The register (PDBR) that contains the base address of the task's + page directory (read only when paging is enabled). + + Pointers to the stacks for privilege levels 0-2. + + The T-bit (debug trap bit) which causes the processor to raise a + debug exception when a task switch occurs. (Refer to Chapter 12 + for more information on debugging.) + + The I/O map base (refer to Chapter 8 for more information on the + use of the I/O map). + +Task state segments may reside anywhere in the linear space. The only case +that requires caution is when the TSS spans a page boundary and the +higher-addressed page is not present. In this case, the processor raises an +exception if it encounters the not-present page while reading the TSS during +a task switch. Such an exception can be avoided by either of two strategies: + + 1. By allocating the TSS so that it does not cross a page boundary. + + 2. By ensuring that both pages are either both present or both + not-present at the time of a task switch. If both pages are + not-present, then the page-fault handler must make both pages present + before restarting the instruction that caused the task switch. + + +Figure 7-1. 80386 32-Bit Task State Segment + + 31 23 15 7 0 + ͻ + I/O MAP BASE 0 0 0 0 0 0 0 0 0 0 0 0 0 T64 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 LDT 60 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GS 5C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FS 58 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DS 54 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS 50 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 CS 4C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ES 48 + Ķ + EDI 44 + Ķ + ESI 40 + Ķ + EBP 3C + Ķ + ESP 38 + Ķ + EBX 34 + Ķ + EDX 30 + ͹ + ECX 2C + Ķ + EAX 28 + Ķ + EFLAGS 24 + Ķ + INSTRUCTION POINTER (EIP) 20 + Ķ + CR3 (PDPR) 1C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS2 18 + Ķ + ESP2 14 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS1 10 + Ķ + ESP1 0C + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 SS0 8 + Ķ + ESP0 4 + Ķ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 BACK LINK TO PREVIOUS TSS 0 + ͼ + + +NOTE + 0 MEANS INTEL RESERVED. DO NOT DEFINE. + + + +7.2 TSS Descriptor + +The task state segment, like all other segments, is defined by a +descriptor. Figure 7-2 shows the format of a TSS descriptor. + +The B-bit in the type field indicates whether the task is busy. A type code +of 9 indicates a non-busy task; a type code of 11 indicates a busy task. +Tasks are not reentrant. The B-bit allows the processor to detect an attempt +to switch to a task that is already busy. + +The BASE, LIMIT, and DPL fields and the G-bit and P-bit have functions +similar to their counterparts in data-segment descriptors. The LIMIT field, +however, must have a value equal to or greater than 103. An attempt to +switch to a task whose TSS descriptor has a limit less that 103 causes an +exception. A larger limit is permissible, and a larger limit is required if +an I/O permission map is present. A larger limit may also be convenient for +systems software if additional data is stored in the same segment as the +TSS. + +A procedure that has access to a TSS descriptor can cause a task switch. In +most systems the DPL fields of TSS descriptors should be set to zero, so +that only trusted software has the right to perform task switching. + +Having access to a TSS-descriptor does not give a procedure the right to +read or modify a TSS. Reading and modification can be accomplished only with +another descriptor that redefines the TSS as a data segment. An attempt to +load a TSS descriptor into any of the segment registers (CS, SS, DS, ES, FS, +GS) causes an exception. + +TSS descriptors may reside only in the GDT. An attempt to identify a TSS +with a selector that has TI=1 (indicating the current LDT) results in an +exception. + + +Figure 7-2. TSS Descriptor for 32-bit TSS + + 31 23 15 7 0 + ͻ + A LIMIT TYPE + BASE 31..24 G00V P DPL BASE 23..16 4 + L 19..16 010B1 + Ķ + + BASE 15..0 LIMIT 15..0 0 + + ͼ + + +7.3 Task Register + +The task register (TR) identifies the currently executing task by pointing +to the TSS. Figure 7-3 shows the path by which the processor accesses the +current TSS. + +The task register has both a "visible" portion (i.e., can be read and +changed by instructions) and an "invisible" portion (maintained by the +processor to correspond to the visible portion; cannot be read by any +instruction). The selector in the visible portion selects a TSS descriptor +in the GDT. The processor uses the invisible portion to cache the base and +limit values from the TSS descriptor. Holding the base and limit in a +register makes execution of the task more efficient, because the processor +does not need to repeatedly fetch these values from memory when it +references the TSS of the current task. + +The instructions LTR and STR are used to modify and read the visible +portion of the task register. Both instructions take one operand, a 16-bit +selector located in memory or in a general register. + +LTR (Load task register) loads the visible portion of the task register +with the selector operand, which must select a TSS descriptor in the GDT. +LTR also loads the invisible portion with information from the TSS +descriptor selected by the operand. LTR is a privileged instruction; it may +be executed only when CPL is zero. LTR is generally used during system +initialization to give an initial value to the task register; thereafter, +the contents of TR are changed by task switch operations. + +STR (Store task register) stores the visible portion of the task register +in a general register or memory word. STR is not privileged. + + +Figure 7-3. Task Register + + ͻ + + + TASK STATE + SEGMENT Ŀ + + + ͼ + 16-BIT VISIBLE  + REGISTER HIDDEN REGISTER + ͻ + TR SELECTOR (BASE) (LIMT) + ͼ +   + Ŀ + GLOBAL DESCRIPTOR TABLE + ͸ + | TSS DESCRIPTOR | + ͻ + + ͹ +  + ͼ + | | + ; + + +7.4 Task Gate Descriptor + +A task gate descriptor provides an indirect, protected reference to a TSS. +Figure 7-4 illustrates the format of a task gate. + +The SELECTOR field of a task gate must refer to a TSS descriptor. The value +of the RPL in this selector is not used by the processor. + +The DPL field of a task gate controls the right to use the descriptor to +cause a task switch. A procedure may not select a task gate descriptor +unless the maximum of the selector's RPL and the CPL of the procedure is +numerically less than or equal to the DPL of the descriptor. This constraint +prevents untrusted procedures from causing a task switch. (Note that when a +task gate is used, the DPL of the target TSS descriptor is not used for +privilege checking.) + +A procedure that has access to a task gate has the power to cause a task +switch, just as a procedure that has access to a TSS descriptor. The 80386 +has task gates in addition to TSS descriptors to satisfy three needs: + + 1. The need for a task to have a single busy bit. Because the busy-bit + is stored in the TSS descriptor, each task should have only one such + descriptor. There may, however, be several task gates that select the + single TSS descriptor. + + 2. The need to provide selective access to tasks. Task gates fulfill + this need, because they can reside in LDTs and can have a DPL that is + different from the TSS descriptor's DPL. A procedure that does not + have sufficient privilege to use the TSS descriptor in the GDT (which + usually has a DPL of 0) can still switch to another task if it has + access to a task gate for that task in its LDT. With task gates, + systems software can limit the right to cause task switches to + specific tasks. + + 3. The need for an interrupt or exception to cause a task switch. Task + gates may also reside in the IDT, making it possible for interrupts + and exceptions to cause task switching. When interrupt or exception + vectors to an IDT entry that contains a task gate, the 80386 switches + to the indicated task. Thus, all tasks in the system can benefit from + the protection afforded by isolation from interrupt tasks. + +Figure 7-5 illustrates how both a task gate in an LDT and a task gate in +the IDT can identify the same task. + + +Figure 7-4. Task Gate Descriptor + + 31 23 15 7 0 + ͻ + + (NOT USED)P DPL 0 0 1 0 1(NOT USED) 4 + + Ķ + + SELECTOR (NOT USED) 0 + + ͼ + + +Figure 7-5. Task Gate Indirectly Identifies Task + + LOCAL DESCRIPTOR TABLE INTERRUPT DESCRIPTOR TABLE + ͸ ͸ + | | | | + | TASK GATE | | TASK GATE | + ͻ ͻ + + Ķ Ķ + Ķ Ķ + ͼ ͼ + | | | | + | | | | + ; ; + Ŀ + GLOBAL DESCRIPTOR TABLE + ͸ + | | + | TASK DESCRIPTOR | + ͻ + + Ķ +  Ŀ + ͼ + | | + | | + ; + + ͻ + + + + TASK STATE + SEGMENT + + + + ͼ + + +7.5 Task Switching + +The 80386 switches execution to another task in any of four cases: + + 1. The current task executes a JMP or CALL that refers to a TSS + descriptor. + + 2. The current task executes a JMP or CALL that refers to a task gate. + + 3. An interrupt or exception vectors to a task gate in the IDT. + + 4. The current task executes an IRET when the NT flag is set. + +JMP, CALL, IRET, interrupts, and exceptions are all ordinary mechanisms of +the 80386 that can be used in circumstances that do not require a task +switch. Either the type of descriptor referenced or the NT (nested task) bit +in the flag word distinguishes between the standard mechanism and the +variant that causes a task switch. + +To cause a task switch, a JMP or CALL instruction can refer either to a TSS +descriptor or to a task gate. The effect is the same in either case: the +80386 switches to the indicated task. + +An exception or interrupt causes a task switch when it vectors to a task +gate in the IDT. If it vectors to an interrupt or trap gate in the IDT, a +task switch does not occur. Refer to Chapter 9 for more information on the +interrupt mechanism. + +Whether invoked as a task or as a procedure of the interrupted task, an +interrupt handler always returns control to the interrupted procedure in the +interrupted task. If the NT flag is set, however, the handler is an +interrupt task, and the IRET switches back to the interrupted task. + +A task switching operation involves these steps: + + 1. Checking that the current task is allowed to switch to the designated + task. Data-access privilege rules apply in the case of JMP or CALL + instructions. The DPL of the TSS descriptor or task gate must be less + than or equal to the maximum of CPL and the RPL of the gate selector. + Exceptions, interrupts, and IRETs are permitted to switch tasks + regardless of the DPL of the target task gate or TSS descriptor. + + 2. Checking that the TSS descriptor of the new task is marked present + and has a valid limit. Any errors up to this point occur in the + context of the outgoing task. Errors are restartable and can be + handled in a way that is transparent to applications procedures. + + 3. Saving the state of the current task. The processor finds the base + address of the current TSS cached in the task register. It copies the + registers into the current TSS (EAX, ECX, EDX, EBX, ESP, EBP, ESI, + EDI, ES, CS, SS, DS, FS, GS, and the flag register). The EIP field of + the TSS points to the instruction after the one that caused the task + switch. + + 4. Loading the task register with the selector of the incoming task's + TSS descriptor, marking the incoming task's TSS descriptor as busy, + and setting the TS (task switched) bit of the MSW. The selector is + either the operand of a control transfer instruction or is taken from + a task gate. + + 5. Loading the incoming task's state from its TSS and resuming + execution. The registers loaded are the LDT register; the flag + register; the general registers EIP, EAX, ECX, EDX, EBX, ESP, EBP, + ESI, EDI; the segment registers ES, CS, SS, DS, FS, and GS; and PDBR. + Any errors detected in this step occur in the context of the incoming + task. To an exception handler, it appears that the first instruction + of the new task has not yet executed. + +Note that the state of the outgoing task is always saved when a task switch +occurs. If execution of that task is resumed, it starts after the +instruction that caused the task switch. The registers are restored to the +values they held when the task stopped executing. + +Every task switch sets the TS (task switched) bit in the MSW (machine +status word). The TS flag is useful to systems software when a coprocessor +(such as a numerics coprocessor) is present. The TS bit signals that the +context of the coprocessor may not correspond to the current 80386 task. +Chapter 11 discusses the TS bit and coprocessors in more detail. + +Exception handlers that field task-switch exceptions in the incoming task +(exceptions due to tests 4 thru 16 of Table 7-1) should be cautious about +taking any action that might load the selector that caused the exception. +Such an action will probably cause another exception, unless the exception +handler first examines the selector and fixes any potential problem. + +The privilege level at which execution resumes in the incoming task is +neither restricted nor affected by the privilege level at which the outgoing +task was executing. Because the tasks are isolated by their separate address +spaces and TSSs and because privilege rules can be used to prevent improper +access to a TSS, no privilege rules are needed to constrain the relation +between the CPLs of the tasks. The new task begins executing at the +privilege level indicated by the RPL of the CS selector value that is loaded +from the TSS. + + +Table 7-1. Checks Made during a Task Switch + + +Test Test Description Exception +NP = Segment-not-present exception, GP = General protection fault, TS = +Invalid TSS, SF = Stack fault Error Code Selects + + 1 Incoming TSS descriptor is NP Incoming TSS + present + 2 Incoming TSS descriptor is GP Incoming TSS + marked not-busy + 3 Limit of incoming TSS is TS Incoming TSS + greater than or equal to 103 + + All register and selector values are loaded + + 4 LDT selector of incoming TS Incoming TSS + task is valid + 5 LDT of incoming task is TS Incoming TSS + present + 6 CS selector is valid +Validity tests of a selector check that the selector is in the proper +table (eg., the LDT selector refers to the GDT), lies within the bounds of +the table, and refers to the proper type of descriptor (e.g., the LDT +selector refers to an LDT descriptor). TS Code segment + 7 Code segment is present NP Code segment + 8 Code segment DPL matches TS Code segment + CS RPL + 9 Stack segment is valid +Validity tests of a selector check that the selector is in the proper +table (eg., the LDT selector refers to the GDT), lies within the bounds of +the table, and refers to the proper type of descriptor (e.g., the LDT +selector refers to an LDT descriptor). GP Stack segment + 10 Stack segment is present SF Stack segment + 11 Stack segment DPL = CPL SF Stack segment + 12 Stack-selector RPL = CPL GP Stack segment + 13 DS, ES, FS, GS selectors are GP Segment + valid +Validity tests of a selector check that the selector is in the proper +table (eg., the LDT selector refers to the GDT), lies within the bounds of +the table, and refers to the proper type of descriptor (e.g., the LDT +selector refers to an LDT descriptor). + + + 14 DS, ES, FS, GS segments GP Segment + are readable + 15 DS, ES, FS, GS segments NP Segment + are present + 16 DS, ES, FS, GS segment DPL GP Segment + CPL (unless these are + conforming segments) + + +7.6 Task Linking + +The back-link field of the TSS and the NT (nested task) bit of the flag +word together allow the 80386 to automatically return to a task that CALLed +another task or was interrupted by another task. When a CALL instruction, an +interrupt instruction, an external interrupt, or an exception causes a +switch to a new task, the 80386 automatically fills the back-link of the new +TSS with the selector of the outgoing task's TSS and, at the same time, +sets the NT bit in the new task's flag register. The NT flag indicates +whether the back-link field is valid. The new task releases control by +executing an IRET instruction. When interpreting an IRET, the 80386 examines +the NT flag. If NT is set, the 80386 switches back to the task selected by +the back-link field. Table 7-2 summarizes the uses of these fields. + + +Table 7-2. Effect of Task Switch on BUSY, NT, and Back-Link + +Affected Field Effect of JMP Effect of Effect of + Instruction CALL Instruction IRET Instruction + +Busy bit of Set, must be Set, must be 0 Unchanged, +incoming task 0 before before must be set + +Busy bit of Cleared Unchanged Cleared +outgoing task (already set) + +NT bit of Cleared Set Unchanged +incoming task + +NT bit of Unchanged Unchanged Cleared +outgoing task + +Back-link of Unchanged Set to outgoing Unchanged +incoming task TSS selector + +Back-link of Unchanged Unchanged Unchanged +outgoing task + + +7.6.1 Busy Bit Prevents Loops + +The B-bit (busy bit) of the TSS descriptor ensures the integrity of the +back-link. A chain of back-links may grow to any length as interrupt tasks +interrupt other interrupt tasks or as called tasks call other tasks. The +busy bit ensures that the CPU can detect any attempt to create a loop. A +loop would indicate an attempt to reenter a task that is already busy; +however, the TSS is not a reentrable resource. + +The processor uses the busy bit as follows: + + 1. When switching to a task, the processor automatically sets the busy + bit of the new task. + + 2. When switching from a task, the processor automatically clears the + busy bit of the old task if that task is not to be placed on the + back-link chain (i.e., the instruction causing the task switch is JMP + or IRET). If the task is placed on the back-link chain, its busy bit + remains set. + + 3. When switching to a task, the processor signals an exception if the + busy bit of the new task is already set. + +By these actions, the processor prevents a task from switching to itself or +to any task that is on a back-link chain, thereby preventing invalid reentry +into a task. + +The busy bit is effective even in multiprocessor configurations, because +the processor automatically asserts a bus lock when it sets or clears the +busy bit. This action ensures that two processors do not invoke the same +task at the same time. (Refer to Chapter 11 for more on multiprocessing.) + + +7.6.2 Modifying Task Linkages + +Any modification of the linkage order of tasks should be accomplished only +by software that can be trusted to correctly update the back-link and the +busy-bit. Such changes may be needed to resume an interrupted task before +the task that interrupted it. Trusted software that removes a task from the +back-link chain must follow one of the following policies: + + 1. First change the back-link field in the TSS of the interrupting task, + then clear the busy-bit in the TSS descriptor of the task removed from + the list. + + 2. Ensure that no interrupts occur between updating the back-link chain + and the busy bit. + + +7.7 Task Address Space + +The LDT selector and PDBR fields of the TSS give software systems designers +flexibility in utilization of segment and page mapping features of the +80386. By appropriate choice of the segment and page mappings for each task, +tasks may share address spaces, may have address spaces that are largely +distinct from one another, or may have any degree of sharing between these +two extremes. + +The ability for tasks to have distinct address spaces is an important +aspect of 80386 protection. A module in one task cannot interfere with a +module in another task if the modules do not have access to the same address +spaces. The flexible memory management features of the 80386 allow systems +designers to assign areas of shared address space to those modules of +different tasks that are designed to cooperate with each other. + + +7.7.1 Task Linear-to-Physical Space Mapping + +The choices for arranging the linear-to-physical mappings of tasks fall +into two general classes: + + 1. One linear-to-physical mapping shared among all tasks. + + When paging is not enabled, this is the only possibility. Without page + tables, all linear addresses map to the same physical addresses. + + When paging is enabled, this style of linear-to-physical mapping + results from using one page directory for all tasks. The linear space + utilized may exceed the physical space available if the operating + system also implements page-level virtual memory. + + 2. Several partially overlapping linear-to-physical mappings. + + This style is implemented by using a different page directory for each + task. Because the PDBR (page directory base register) is loaded from + the TSS with each task switch, each task may have a different page + directory. + +In theory, the linear address spaces of different tasks may map to +completely distinct physical addresses. If the entries of different page +directories point to different page tables and the page tables point to +different pages of physical memory, then the tasks do not share any physical +addresses. + +In practice, some portion of the linear address spaces of all tasks must +map to the same physical addresses. The task state segments must lie in a +common space so that the mapping of TSS addresses does not change while the +processor is reading and updating the TSSs during a task switch. The linear +space mapped by the GDT should also be mapped to a common physical space; +otherwise, the purpose of the GDT is defeated. Figure 7-6 shows how the +linear spaces of two tasks can overlap in the physical space by sharing +page tables. + + +7.7.2 Task Logical Address Space + +By itself, a common linear-to-physical space mapping does not enable +sharing of data among tasks. To share data, tasks must also have a common +logical-to-linear space mapping; i.e., they must also have access to +descriptors that point into a shared linear address space. There are three +ways to create common logical-to-physical address-space mappings: + + 1. Via the GDT. All tasks have access to the descriptors in the GDT. If + those descriptors point into a linear-address space that is mapped to + a common physical-address space for all tasks, then the tasks can + share data and instructions. + + 2. By sharing LDTs. Two or more tasks can use the same LDT if the LDT + selectors in their TSSs select the same LDT segment. Those + LDT-resident descriptors that point into a linear space that is mapped + to a common physical space permit the tasks to share physical memory. + This method of sharing is more selective than sharing by the GDT; the + sharing can be limited to specific tasks. Other tasks in the system + may have different LDTs that do not give them access to the shared + areas. + + 3. By descriptor aliases in LDTs. It is possible for certain descriptors + of different LDTs to point to the same linear address space. If that + linear address space is mapped to the same physical space by the page + mapping of the tasks involved, these descriptors permit the tasks to + share the common space. Such descriptors are commonly called + "aliases". This method of sharing is even more selective than the + prior two; other descriptors in the LDTs may point to distinct linear + addresses or to linear addresses that are not shared. + + +Figure 7-6. Partially-Overlapping Linear Spaces + + TSSs PAGE FRAMES + ͻ + TASK A TSS PAGE DIRECTORIES PAGE TABLES TASK A + ͻ ͻ ͻ  PAGE + ͼ + ͹ ͹ ͻ + PTE TASK A + ͹ ͹  PAGE + PTE ͼ + ͹ ͹ ͹ ͻ + PDBR  PDE  PTE Ŀ TASK A + ͹ ͹ ͼ  PAGE + PDE Ŀ SHARED PT ͼ + ͼ ͼ ͻ ͻ + SHARED + ͹  PAGE + ͼ + ͹ ͻ + PTE SHARED + ͹  PAGE +  PTE ͼ + TASK B TSS ͼ ͻ + ͻ ͻ TASK B +  PAGE + ͹ ͻ ͼ + ͻ + ͹ ͹ TASK B +  PAGE + ͹ ͹ ͹ ͼ + PDBR  PDE PTE PAGE FRAMES + ͹ ͹ ͹ + PDE  PTE + ͼ ͼ ͼ + TSSs PAGE DIRECTORIES PAGE TABLES + + +Chapter 8 Input/Output + + + +This chapter presents the I/O features of the 80386 from the following +perspectives: + + Methods of addressing I/O ports + + Instructions that cause I/O operations + + Protection as it applies to the use of I/O instructions and I/O port + addresses. + + +8.1 I/O Addressing + +The 80386 allows input/output to be performed in either of two ways: + + By means of a separate I/O address space (using specific I/O + instructions) + + By means of memory-mapped I/O (using general-purpose operand + manipulationinstructions). + + +8.1.1 I/O Address Space + +The 80386 provides a separate I/O address space, distinct from physical +memory, that can be used to address the input/output ports that are used for +external 16 devices. The I/O address space consists of 2^(16) (64K) +individually addressable 8-bit ports; any two consecutive 8-bit ports can be +treated as a 16-bit port; and four consecutive 8-bit ports can be treated +as a 32-bit port. Thus, the I/O address space can accommodate up to 64K +8-bit ports, up to 32K 16-bit ports, or up to 16K 32-bit ports. + +The program can specify the address of the port in two ways. Using an +immediate byte constant, the program can specify: + + 256 8-bit ports numbered 0 through 255. + 128 16-bit ports numbered 0, 2, 4, . . . , 252, 254. + 64 32-bit ports numbered 0, 4, 8, . . . , 248, 252. + +Using a value in DX, the program can specify: + + 8-bit ports numbered 0 through 65535 + 16-bit ports numbered 0, 2, 4, . . . , 65532, 65534 + 32-bit ports numbered 0, 4, 8, . . . , 65528, 65532 + +The 80386 can transfer 32, 16, or 8 bits at a time to a device located in +the I/O space. Like doublewords in memory, 32-bit ports should be aligned at +addresses evenly divisible by four so that the 32 bits can be transferred in +a single bus access. Like words in memory, 16-bit ports should be aligned at +even-numbered addresses so that the 16 bits can be transferred in a single +bus access. An 8-bit port may be located at either an even or odd address. + +The instructions IN and OUT move data between a register and a port in the +I/O address space. The instructions INS and OUTS move strings of data +between the memory address space and ports in the I/O address space. + + +8.1.2 Memory-Mapped I/O + +I/O devices also may be placed in the 80386 memory address space. As long +as the devices respond like memory components, they are indistinguishable to +the processor. + +Memory-mapped I/O provides additional programming flexibility. Any +instruction that references memory may be used to access an I/O port located +in the memory space. For example, the MOV instruction can transfer data +between any register and a port; and the AND, OR, and TEST instructions may +be used to manipulate bits in the internal registers of a device (see Figure +8-1). Memory-mapped I/O performed via the full instruction set maintains +the full complement of addressing modes for selecting the desired I/O +device (e.g., direct address, indirect address, base register, index +register, scaling). + +Memory-mapped I/O, like any other memory reference, is subject to access +protection and control when executing in protected mode. Refer to Chapter 6 +for a discussion of memory protection. + + +8.2 I/O Instructions + +The I/O instructions of the 80386 provide access to the processor's I/O +ports for the transfer of data to and from peripheral devices. These +instructions have as one operand the address of a port in the I/O address +space. There are two classes of I/O instruction: + + 1. Those that transfer a single item (byte, word, or doubleword) located + in a register. + + 2. Those that transfer strings of items (strings of bytes, words, or + doublewords) located in memory. These are known as "string I/O + instructions" or "block I/O instructions". + + +8.2.1 Register I/O Instructions + +The I/O instructions IN and OUT are provided to move data between I/O ports +and the EAX (32-bit I/O), the AX (16-bit I/O), or AL (8-bit I/O) general +registers. IN and OUT instructions address I/O ports either directly, with +the address of one of up to 256 port addresses coded in the instruction, or +indirectly via the DX register to one of up to 64K port addresses. + +IN (Input from Port) transfers a byte, word, or doubleword from an input +port to AL, AX, or EAX. If a program specifies AL with the IN instruction, +the processor transfers 8 bits from the selected port to AL. If a program +specifies AX with the IN instruction, the processor transfers 16 bits from +the port to AX. If a program specifies EAX with the IN instruction, the +processor transfers 32 bits from the port to EAX. + +OUT (Output to Port) transfers a byte, word, or doubleword to an output +port from AL, AX, or EAX. The program can specify the number of the port +using the same methods as the IN instruction. + + +Figure 8-1. Memory-Mapped I/O + + MEMORY + ADDRESS SPACE I/O DEVICE 1 + ͻ ͻ + INTERNAL REGISTER + Ķ ĺͻ + + Ķ ĺͼ + ͼ + + + + I/O DEVICE 2 + ͻ + INTERNAL REGISTER + Ķ ĺͻ + + Ķ ĺͼ + ͼ + ͼ + + +8.2.2 Block I/O Instructions + +The block (or string) I/O instructions INS and OUTS move blocks of data +between I/O ports and memory space. Block I/O instructions use the DX +register to specify the address of a port in the I/O address space. INS and +OUTS use DX to specify: + + 8-bit ports numbered 0 through 65535 + 16-bit ports numbered 0, 2, 4, . . . , 65532, 65534 + 32-bit ports numbered 0, 4, 8, . . . , 65528, 65532 + +Block I/O instructions use either SI or DI to designate the source or +destination memory address. For each transfer, SI or DI are automatically +either incremented or decremented as specified by the direction bit in the +flags register. + +INS and OUTS, when used with repeat prefixes, cause block input or output +operations. REP, the repeat prefix, modifies INS and OUTS to provide a means +of transferring blocks of data between an I/O port and memory. These block +I/O instructions are string primitives (refer also to Chapter 3 for more on +string primitives). They simplify programming and increase the speed of data +transfer by eliminating the need to use a separate LOOP instruction or an +intermediate register to hold the data. + +The string I/O primitives can operate on byte strings, word strings, or +doubleword strings. After each transfer, the memory address in ESI or EDI is +updated by 1 for byte operands, by 2 for word operands, or by 4 for +doubleword operands. The value in the direction flag (DF) determines whether +the processor automatically increments ESI or EDI (DF=0) or whether it +automatically decrements these registers (DF=1). + +INS (Input String from Port) transfers a byte or a word string element from +an input port to memory. The mnemonics INSB, INSW, and INSD are variants +that explicitly specify the size of the operand. If a program specifies +INSB, the processor transfers 8 bits from the selected port to the memory +location indicated by ES:EDI. If a program specifies INSW, the processor +transfers 16 bits from the port to the memory location indicated by ES:EDI. +If a program specifies INSD, the processor transfers 32 bits from the port +to the memory location indicated by ES:EDI. The destination segment register +choice (ES) cannot be changed for the INS instruction. Combined with the REP +prefix, INS moves a block of information from an input port to a series of +consecutive memory locations. + +OUTS (Output String to Port) transfers a byte, word, or doubleword string +element to an output port from memory. The mnemonics OUTSB, OUTSW, and OUTSD +are variants that explicitly specify the size of the operand. If a program +specifies OUTSB, the processor transfers 8 bits from the memory location +indicated by ES:EDI to the the selected port. If a program specifies OUTSW, +the processor transfers 16 bits from the memory location indicated by ES:EDI +to the the selected port. If a program specifies OUTSD, the processor +transfers 32 bits from the memory location indicated by ES:EDI to the the +selected port. Combined with the REP prefix, OUTS moves a block of +information from a series of consecutive memory locations indicated by +DS:ESI to an output port. + + +8.3 Protection and I/O + +Two mechanisms provide protection for I/O functions: + + 1. The IOPL field in the EFLAGS register defines the right to use + I/O-related instructions. + + 2. The I/O permission bit map of a 80386 TSS segment defines the right + to use ports in the I/O address space. + +These mechanisms operate only in protected mode, including virtual 8086 +mode; they do not operate in real mode. In real mode, there is no protection +of the I/O space; any procedure can execute I/O instructions, and any I/O +port can be addressed by the I/O instructions. + + +8.3.1 I/O Privilege Level + +Instructions that deal with I/O need to be restricted but also need to be +executed by procedures executing at privilege levels other than zero. For +this reason, the processor uses two bits of the flags register to store the +I/O privilege level (IOPL). The IOPL defines the privilege level +needed to execute I/O-related instructions. + +The following instructions can be executed only if CPL IOPL: + +IN Input +INS Input String +OUT Output +OUTS Output String +CLI Clear Interrupt-Enable Flag +STI Set Interrupt-Enable + +These instructions are called "sensitive" instructions, because they are +sensitive to IOPL. + +To use sensitive instructions, a procedure must execute at a privilege +level at least as privileged as that specified by the IOPL (CPL IOPL). Any +attempt by a less privileged procedure to use a sensitive instruction +results in a general protection exception. + +Because each task has its own unique copy of the flags register, each task +can have a different IOPL. A task whose primary function is to perform I/O +(a device driver) can benefit from having an IOPL of three, thereby +permitting all procedures of the task to performI/O. Other tasks typically +have IOPL set to zero or one, reserving the right to perform I/O +instructions for the most privileged procedures. + +A task can change IOPL only with the POPF instruction; however, such +changes are privileged. No procedure may alter IOPL (the I/O privilege level +in the flag register) unless the procedure is executing at privilege level +0. An attempt by a less privileged procedure to alter IOPL does not result +in an exception; IOPL simply remains unaltered. + +The POPF instruction may be used in addition to CLI and STI to alter the +interrupt-enable flag (IF); however, changes to IF by POPF are +IOPL-sensitive. A procedure may alter IF with a POPF instruction only when +executing at a level that is at least as privileged as IOPL. An attempt by a +less privileged procedure to alter IF in this manner does not result in an +exception; IF simply remains unaltered. + + +8.3.2 I/O Permission Bit Map + +The I/O instructions that directly refer to addresses in the processor's +I/O space are IN, INS, OUT, OUTS. The 80386 has the ability to selectively +trap references to specific I/O addresses. The structure that enables +selective trapping is the I/O Permission Bit Map in the TSS segment (see +Figure 8-2). The I/O permission map is a bit vector. The size of the map +and its location in the TSS segment are variable. The processor locates the +I/O permission map by means of the I/O map base field in the fixed portion +of the TSS. The I/O map base field is 16 bits wide and contains the offset +of the beginning of the I/O permission map. The upper limit of the I/O +permission map is the same as the limit of the TSS segment. + +In protected mode, when it encounters an I/O instruction (IN, INS, OUT, or +OUTS), the processor first checks whether CPL IOPL. If this condition is +true, the I/O operation may proceed. If not true, the processor checks the +I/O permission map. (In virtual 8086 mode, the processor consults the map +without regard for IOPL. Refer to Chapter 15.) + +Each bit in the map corresponds to an I/O port byte address; for example, +the bit for port 41 is found at I/O map base + 5, bit offset 1. The +processor tests all the bits that correspond to the I/O addresses spanned by +an I/O operation; for example, a doubleword operation tests four bits +corresponding to four adjacent byte addresses. If any tested bit is set, +the processor signals a general protection exception. If all the tested bits +are zero, the I/O operation may proceed. + +It is not necessary for the I/O permission map to represent all the I/O +addresses. I/O addresses not spanned by the map are treated as if they had +one bits in the map. For example, if TSS limit is equal to I/O map base + +31, the first 256 I/O ports are mapped; I/O operations on any port greater +than 255 cause an exception. + +If I/O map base is greater than or equal to TSS limit, the TSS segment has +no I/O permission map, and all I/O instructions in the 80386 program cause +exceptions when CPL > IOPL. + +Because the I/O permission map is in the TSS segment, different tasks can +have different maps. Thus, the operating system can allocate ports to a task +by changing the I/O permission map in the task's TSS. + + +Figure 8-2. I/O Address Bit Map + + TSS SEGMEMT + + 31 23 15 7 0 + ͻ + LIMIT + +   +  I/O PERMISSION BIT MAP  +   + +  + Ķ +   +   +   + Ķ + Ķ I/O MAP BASE uuuuuuuu uuuuuuuT64 + Ķ + 00000000 00000000 LOT 60 + Ķ + 00000000 00000000 GS 5C + Ķ + 58 +   +   +   + 4 + Ķ + 00000000 00000000 TSS BACK LINK 0 + ͼ + + +Chapter 9 Exceptions and Interrupts + + + +Interrupts and exceptions are special kinds of control transfer; they work +somewhat like unprogrammed CALLs. They alter the normal program flow to +handle external events or to report errors or exceptional conditions. The +difference between interrupts and exceptions is that interrupts are used to +handle asynchronous events external to the processor, but exceptions handle +conditions detected by the processor itself in the course of executing +instructions. + +There are two sources for external interrupts and two sources for +exceptions: + + 1. Interrupts + + Maskable interrupts, which are signalled via the INTR pin. + + Nonmaskable interrupts, which are signalled via the NMI + (Non-Maskable Interrupt) pin. + + 2. Exceptions + + Processor detected. These are further classified as faults, traps, + and aborts. + + Programmed. The instructions INTO, INT 3, INT n, and BOUND can + trigger exceptions. These instructions are often called "software + interrupts", but the processor handles them as exceptions. + +This chapter explains the features that the 80386 offers for controlling +and responding to interrupts when it is executing in protected mode. + + +9.1 Identifying Interrupts + +The processor associates an identifying number with each different type of +interrupt or exception. + +The NMI and the exceptions recognized by the processor are assigned +predetermined identifiers in the range 0 through 31. Not all of these +numbers are currently used by the 80386; unassigned identifiers in this +range are reserved by Intel for possible future expansion. + +The identifiers of the maskable interrupts are determined by external +interrupt controllers (such as Intel's 8259A Programmable Interrupt +Controller) and communicated to the processor during the processor's +interrupt-acknowledge sequence. The numbers assigned by an 8259A PIC can be +specified by software. Any numbers in the range 32 through 255 can be used. +Table 9-1 shows the assignment of interrupt and exception identifiers. + +Exceptions are classified as faults, traps, or aborts depending on the way +they are reported and whether restart of the instruction that caused the +exception is supported. + +Faults Faults are exceptions that are reported "before" the + instruction causingthe exception. Faults are either detected before + the instruction begins to execute, or during execution of the + instruction. If detected during the instruction, the fault is + reported with the machine restored to a state that permits the + instruction to be restarted. + +Traps A trap is an exception that is reported at the instruction + boundary immediately after the instruction in which the + exception was detected. + +Aborts An abort is an exception that permits neither precise location + of the instruction causing the exception nor restart of the program + that caused the exception. Aborts are used to report severe errors, + such as hardware errors and inconsistent or illegal values in system + tables. + + +Table 9-1. Interrupt and Exception ID Assignments + +Identifier Description + +0 Divide error +1 Debug exceptions +2 Nonmaskable interrupt +3 Breakpoint (one-byte INT 3 instruction) +4 Overflow (INTO instruction) +5 Bounds check (BOUND instruction) +6 Invalid opcode +7 Coprocessor not available +8 Double fault +9 (reserved) +10 Invalid TSS +11 Segment not present +12 Stack exception +13 General protection +14 Page fault +15 (reserved) +16 Coprecessor error +17-31 (reserved) +32-255 Available for external interrupts via INTR pin + + +9.2 Enabling and Disabling Interrupts + +The processor services interrupts and exceptions only between the end of +one instruction and the beginning of the next. When the repeat prefix is +used to repeat a string instruction, interrupts and exceptions may occur +between repetitions. Thus, operations on long strings do not delay interrupt +response. + +Certain conditions and flag settings cause the processor to inhibit certain +interrupts and exceptions at instruction boundaries. + + +9.2.1 NMI Masks Further NMIs + +While an NMI handler is executing, the processor ignores further interrupt +signals at the NMI pin until the next IRET instruction is executed. + + +9.2.2 IF Masks INTR + +The IF (interrupt-enable flag) controls the acceptance of external +interrupts signalled via the INTR pin. When IF=0, INTR interrupts are +inhibited; when IF=1, INTR interrupts are enabled. As with the other flag +bits, the processor clears IF in response to a RESET signal. The +instructions CLI and STI alter the setting of IF. + +CLI (Clear Interrupt-Enable Flag) and STI (Set Interrupt-Enable Flag) +explicitly alter IF (bit 9 in the flag register). These instructions may be +executed only if CPL IOPL. A protection exception occurs if they are +executed when CPL > IOPL. + +The IF is also affected implicitly by the following operations: + + The instruction PUSHF stores all flags, including IF, in the stack + where they can be examined. + + Task switches and the instructions POPF and IRET load the flags + register; therefore, they can be used to modify IF. + + Interrupts through interrupt gates automatically reset IF, disabling + interrupts. (Interrupt gates are explained later in this chapter.) + + +9.2.3 RF Masks Debug Faults + +The RF bit in EFLAGS controls the recognition of debug faults. This permits +debug faults to be raised for a given instruction at most once, no matter +how many times the instruction is restarted. (Refer to Chapter 12 for more +information on debugging.) + + +9.2.4 MOV or POP to SS Masks Some Interrupts and Exceptions + +Software that needs to change stack segments often uses a pair of +instructions; for example: + + MOV SS, AX + MOV ESP, StackTop + +If an interrupt or exception is processed after SS has been changed but +before ESP has received the corresponding change, the two parts of the stack +pointer SS:ESP are inconsistent for the duration of the interrupt handler or +exception handler. + +To prevent this situation, the 80386, after both a MOV to SS and a POP to +SS instruction, inhibits NMI, INTR, debug exceptions, and single-step traps +at the instruction boundary following the instruction that changes SS. Some +exceptions may still occur; namely, page fault and general protection fault. +Always use the 80386 LSS instruction, and the problem will not occur. + + +9.3 Priority Among Simultaneous Interrupts and Exceptions + +If more than one interrupt or exception is pending at an instruction +boundary, the processor services one of them at a time. The priority among +classes of interrupt and exception sources is shown in Table 9-2. The +processor first services a pending interrupt or exception from the class +that has the highest priority, transferring control to the first +instruction of the interrupt handler. Lower priority exceptions are +discarded; lower priority interrupts are held pending. Discarded exceptions +will be rediscovered when the interrupt handler returns control to the point +of interruption. + + +9.4 Interrupt Descriptor Table + +The interrupt descriptor table (IDT) associates each interrupt or exception +identifier with a descriptor for the instructions that service the +associated event. Like the GDT and LDTs, the IDT is an array of 8-byte +descriptors. Unlike the GDT and LDTs, the first entry of the IDT may contain +a descriptor. To form an index into the IDT, the processor multiplies the +interrupt or exception identifier by eight. Because there are only 256 +identifiers, the IDT need not contain more than 256 descriptors. It can +contain fewer than 256 entries; entries are required only for interrupt +identifiers that are actually used. + +The IDT may reside anywhere in physical memory. As Figure 9-1 shows, the +processor locates the IDT by means of the IDT register (IDTR). The +instructions LIDT and SIDT operate on the IDTR. Both instructions have one +explicit operand: the address in memory of a 6-byte area. Figure 9-2 shows +the format of this area. + +LIDT (Load IDT register) loads the IDT register with the linear base +address and limit values contained in the memory operand. This instruction +can be executed only when the CPL is zero. It is normally used by the +initialization logic of an operating system when creating an IDT. An +operating system may also use it to change from one IDT to another. + +SIDT (Store IDT register) copies the base and limit value stored in IDTR +to a memory location. This instruction can be executed at any privilege +level. + + +Table 9-2. Priority Among Simultaneous Interrupts and Exceptions + +Priority Class of Interrupt or Exception + +HIGHEST Faults except debug faults + Trap instructions INTO, INT n, INT 3 + Debug traps for this instruction + Debug faults for next instruction + NMI interrupt +LOWEST INTR interrupt + + +Figure 9-1. IDT Register and Table + + INTERRUPT DESCRIPTOR TABLE + ͻ +  + GATE FOR INTERRUPT #N Ķ + + ͼ +   +   +   + ͻ + + GATE FOR INTERRUPT #2 Ķ + + ͹ + IDT REGISTER + GATE FOR INTERRUPT #1 Ķ + 15 0 + ͻ ͹ + IDT LIMIT + ͹ GATE FOR INTERRUPT #0 Ķ + IDT BASE  + ͼ ͼ + 31 0 + + +Figure 9-2. Pseudo-Descriptor Format for LIDT and SIDT + + 31 23 15 7 0 + ͻ + BASE 2 + ͹ + LIMIT 0 + ͼ + + +9.5 IDT Descriptors + +The IDT may contain any of three kinds of descriptor: + + Task gates + Interrupt gates + Trap gates + +Figure 9-3 illustrates the format of task gates and 80386 interrupt gates +and trap gates. (The task gate in an IDT is the same as the task gate +already discussed in Chapter 7.) + + +Figure 9-3. 80306 IDT Gate Descriptors + + 80386 TASK GATE + 31 23 15 7 0 + ͻ + (NOT USED) P DPL0 0 1 0 1(NOT USED)4 + Ķ + SELECTOR (NOT USED)0 + ͼ + + 80386 INTERRUPT GATE + 31 23 15 7 0 + ͻ + OFFSET 31..16 P DPL0 1 1 1 00 0 0(NOT USED) 4 + Ķ + SELECTOR OFFSET 15..0 0 + ͼ + + 80386 TRAP GATE + 31 23 15 7 0 + ͻ + OFFSET 31..16 P DPL0 1 1 1 10 0 0(NOT USED) 4 + Ķ + SELECTOR OFFSET 15..0 0 + ͼ + + +9.6 Interrupt Tasks and Interrupt Procedures + +Just as a CALL instruction can call either a procedure or a task, so an +interrupt or exception can "call" an interrupt handler that is either a +procedure or a task. When responding to an interrupt or exception, the +processor uses the interrupt or exception identifier to index a descriptor +in the IDT. If the processor indexes to an interrupt gate or trap gate, it +invokes the handler in a manner similar to a CALL to a call gate. If the +processor finds a task gate, it causes a task switch in a manner similar to +a CALL to a task gate. + + +9.6.1 Interrupt Procedures + +An interrupt gate or trap gate points indirectly to a procedure which will +execute in the context of the currently executing task as illustrated by +Figure 9-4. The selector of the gate points to an executable-segment +descriptor in either the GDT or the current LDT. The offset field of the +gate points to the beginning of the interrupt or exception handling +procedure. + +The 80386 invokes an interrupt or exception handling procedure in much the +same manner as it CALLs a procedure; the differences are explained in the +following sections. + + +Figure 9-4. Interrupt Vectoring for Procedures + + IDT EXECUTABLE SEGMENT + ͻ ͻ + OFFSET + ͹  ENTRY POINT + LDT OR GDT + ͹ ͻ + +INTERRUPT ͹ ͹ + ID TRAP GATE OR + INTERRUPT GATE Ŀ ͹ + ͹ + ͹ + ͹  SEGMENT Ŀ + DESCRIPTOR + ͹ ͹ + + ͹ ͹ + BASE + ͼ ͹ ͼ + + + + ͼ + + +9.6.1.1 Stack of Interrupt Procedure + +Just as with a control transfer due to a CALL instruction, a control +transfer to an interrupt or exception handling procedure uses the stack to +store the information needed for returning to the original procedure. As +Figure 9-5 shows, an interrupt pushes the EFLAGS register onto the stack +before the pointer to the interrupted instruction. + +Certain types of exceptions also cause an error code to be pushed on the +stack. An exception handler can use the error code to help diagnose the +exception. + + +9.6.1.2 Returning from an Interrupt Procedure + +An interrupt procedure also differs from a normal procedure in the method +of leaving the procedure. The IRET instruction is used to exit from an +interrupt procedure. IRET is similar to RET except that IRET increments EIP +by an extra four bytes (because of the flags on the stack) and moves the +saved flags into the EFLAGS register. The IOPL field of EFLAGS is changed +only if the CPL is zero. The IF flag is changed only if CPL IOPL. + + +Figure 9-5. Stack Layout after Exception of Interrupt + + WITHOUT PRIVILEGE TRANSITION + + D O 31 0 31 0 + I F ͹ ͹ + R OLD OLD + E E ͹ SS:ESP ͹ SS:ESP + C X + T P ͹ ͹ + I A OLD EFLAGS OLD EFLAGS + O N ͹ ͹ + N S OLD CS NEW OLD CS + I ͹ SS:ESP ͹ + O OLD EIP OLD EIP NEW + N ͹ ͹ SS:ESP + ERROR CODE +    ͹ +   +   + WITHOUT ERROR CODE WITH ERROR CODE + + WITH PRIVILEGE TRANSITION + + D O 31 0 31 0 + I F ͻĿ ͻĿ + R OLD SS OLD SS + E E ͹ SS:ESP ͹ SS:ESP + C X OLD ESP FROM TSS OLD ESP FROM TSS + T P ͹ ͹ + I A OLD EFLAGS OLD EFLAGS + O N ͹ ͹ + N S OLD CS NEW OLD CS + I ͹ SS:EIP ͹ + O OLD EIP OLD EIP NEW + N ͹ ͹ SS:ESP + ERROR CODE +    ͹ +   +   + WITHOUT ERROR CODE WITH ERROR CODE + + +9.6.1.3 Flags Usage by Interrupt Procedure + +Interrupts that vector through either interrupt gates or trap gates cause +TF (the trap flag) to be reset after the current value of TF is saved on the +stack as part of EFLAGS. By this action the processor prevents debugging +activity that uses single-stepping from affecting interrupt response. A +subsequent IRET instruction restores TF to the value in the EFLAGS image on +the stack. + +The difference between an interrupt gate and a trap gate is in the effect +on IF (the interrupt-enable flag). An interrupt that vectors through an +interrupt gate resets IF, thereby preventing other interrupts from +interfering with the current interrupt handler. A subsequent IRET +instruction restores IF to the value in the EFLAGS image on the stack. An +interrupt through a trap gate does not change IF. + + +9.6.1.4 Protection in Interrupt Procedures + +The privilege rule that governs interrupt procedures is similar to that for +procedure calls: the CPU does not permit an interrupt to transfer control to +a procedure in a segment of lesser privilege (numerically greater privilege +level) than the current privilege level. An attempt to violate this rule +results in a general protection exception. + +Because occurrence of interrupts is not generally predictable, this +privilege rule effectively imposes restrictions on the privilege levels at +which interrupt and exception handling procedures can execute. Either of the +following strategies can be employed to ensure that the privilege rule is +never violated. + + Place the handler in a conforming segment. This strategy suits the + handlers for certain exceptions (divide error, for example). Such a + handler must use only the data available to it from the stack. If it + needed data from a data segment, the data segment would have to have + privilege level three, thereby making it unprotected. + + Place the handler procedure in a privilege level zero segment. + + +9.6.2 Interrupt Tasks + +A task gate in the IDT points indirectly to a task, as Figure 9-6 +illustrates. The selector of the gate points to a TSS descriptor in the GDT. + +When an interrupt or exception vectors to a task gate in the IDT, a task +switch results. Handling an interrupt with a separate task offers two +advantages: + + The entire context is saved automatically. + + The interrupt handler can be isolated from other tasks by giving it a + separate address space, either via its LDT or via its page directory. + +The actions that the processor takes to perform a task switch are discussed +in Chapter 7. The interrupt task returns to the interrupted task by +executing an IRET instruction. + +If the task switch is caused by an exception that has an error code, the +processor automatically pushes the error code onto the stack that +corresponds to the privilege level of the first instruction to be executed +in the interrupt task. + +When interrupt tasks are used in an operating system for the 80386, there +are actually two schedulers: the software scheduler (part of the operating +system) and the hardware scheduler (part of the processor's interrupt +mechanism). The design of the software scheduler should account for the fact +that the hardware scheduler may dispatch an interrupt task whenever +interrupts are enabled. + + +Figure 9-6. Interrupt Vectoring for Tasks + + IDT GDT + ͻ ͻ + TSS + Ķ Ķ ͻ + + Ķ Ķ + + Ķ Ķ +  TASK GATE Ŀ + Ķ Ķ +  TSS DESCRIPTOR Ŀ + Ķ Ķ + + Ķ Ķ ͼ + + Ķ Ķ + + ͼ ͼ + + INTERRUPT ID + + +9.7 Error Code + +With exceptions that relate to a specific segment, the processor pushes an +error code onto the stack of the exception handler (whether procedure or +task). The error code has the format shown in Figure 9-7. The format of the +error code resembles that of a selector; however, instead of an RPL field, +the error code contains two one-bit items: + + 1. The processor sets the EXT bit if an event external to the program + caused the exception. + + 2. The processor sets the I-bit (IDT-bit) if the index portion of the + error code refers to a gate descriptor in the IDT. + +If the I-bit is not set, the TI bit indicates whether the error code refers +to the GDT (value 0) or to the LDT (value 1). The remaining 14 bits are the +upper 14 bits of the segment selector involved. In some cases the error code +on the stack is null, i.e., all bits in the low-order word are zero. + + +Figure 9-7. Error Code Format + + 31 15 2 1 0 + ͻ + T E + UNDEFINED SELECTOR INDEX I + I X + ͼ + + +9.8 Exception Conditions + +The following sections describe each of the possible exception conditions +in detail. Each description classifies the exception as a fault, trap, or +abort. This classification provides information needed by systems +programmers for restarting the procedure in which the exception occurred: + +Faults The CS and EIP values saved when a fault is reported point to the + instruction causing the fault. + +Traps The CS and EIP values stored when the trap is reported point to the + instruction dynamically after the instruction causing the trap. If + a trap is detected during an instruction that alters program flow, + the reported values of CS and EIP reflect the alteration of program + flow. For example, if a trap is detected in a JMP instruction, the + CS and EIP values pushed onto the stack point to the target of the + JMP, not to the instruction after the JMP. + +Aborts An abort is an exception that permits neither precise location of + the instruction causing the exception nor restart of the program + that caused the exception. Aborts are used to report severe errors, + such as hardware errors and inconsistent or illegal values in + system tables. + + +9.8.1 Interrupt 0 Divide Error + +The divide-error fault occurs during a DIV or an IDIV instruction when the +divisor is zero. + + +9.8.2 Interrupt 1 Debug Exceptions + +The processor triggers this interrupt for any of a number of conditions; +whether the exception is a fault or a trap depends on the condition: + + Instruction address breakpoint fault. + Data address breakpoint trap. + General detect fault. + Single-step trap. + Task-switch breakpoint trap. + +The processor does not push an error code for this exception. An exception +handler can examine the debug registers to determine which condition caused +the exception. Refer to Chapter 12 for more detailed information about +debugging and the debug registers. + + +9.8.3 Interrupt 3 Breakpoint + +The INT 3 instruction causes this trap. The INT 3 instruction is one byte +long, which makes it easy to replace an opcode in an executable segment with +the breakpoint opcode. The operating system or a debugging subsystem can use +a data-segment alias for an executable segment to place an INT 3 anywhere it +is convenient to arrest normal execution so that some sort of special +processing can be performed. Debuggers typically use breakpoints as a way of +displaying registers, variables, etc., at crucial points in a task. + +The saved CS:EIP value points to the byte following the breakpoint. If a +debugger replaces a planted breakpoint with a valid opcode, it must subtract +one from the saved EIP value before returning. Refer also to Chapter 12 for +more information on debugging. + + +9.8.4 Interrupt 4 Overflow + +This trap occurs when the processor encounters an INTO instruction and the +OF (overflow) flag is set. Since signed arithmetic and unsigned arithmetic +both use the same arithmetic instructions, the processor cannot determine +which is intended and therefore does not cause overflow exceptions +automatically. Instead it merely sets OF when the results, if interpreted as +signed numbers, would be out of range. When doing arithmetic on signed +operands, careful programmers and compilers either test OF directly or use +the INTO instruction. + + +9.8.5 Interrupt 5 Bounds Check + +This fault occurs when the processor, while executing a BOUND instruction, +finds that the operand exceeds the specified limits. A program can use the +BOUND instruction to check a signed array index against signed limits +defined in a block of memory. + + +9.8.6 Interrupt 6 Invalid Opcode + +This fault occurs when an invalid opcode is detected by the execution unit. +(The exception is not detected until an attempt is made to execute the +invalid opcode; i.e., prefetching an invalid opcode does not cause this +exception.) No error code is pushed on the stack. The exception can be +handled within the same task. + +This exception also occurs when the type of operand is invalid for the +given opcode. Examples include an intersegment JMP referencing a register +operand, or an LES instruction with a register source operand. + + +9.8.7 Interrupt 7 Coprocessor Not Available + +This exception occurs in either of two conditions: + + The processor encounters an ESC (escape) instruction, and the EM + (emulate) bit ofCR0 (control register zero) is set. + + The processor encounters either the WAIT instruction or an ESC + instruction, and both the MP (monitor coprocessor) and TS (task + switched) bits of CR0 are set. + +Refer to Chapter 11 for information about the coprocessor interface. + + +9.8.8 Interrupt 8 Double Fault + +Normally, when the processor detects an exception while trying to invoke +the handler for a prior exception, the two exceptions can be handled +serially. If, however, the processor cannot handle them serially, it signals +the double-fault exception instead. To determine when two faults are to be +signalled as a double fault, the 80386 divides the exceptions into three +classes: benign exceptions, contributory exceptions, and page faults. Table +9-3 shows this classification. + +Table 9-4 shows which combinations of exceptions cause a double fault and +which do not. + +The processor always pushes an error code onto the stack of the +double-fault handler; however, the error code is always zero. The faulting +instruction may not be restarted. If any other exception occurs while +attempting to invoke the double-fault handler, the processor shuts down. + + +Table 9-3. Double-Fault Detection Classes + +Class ID Description + + 1 Debug exceptions + 2 NMI + 3 Breakpoint +Benign 4 Overflow +Exceptions 5 Bounds check + 6 Invalid opcode + 7 Coprocessor not available + 16 Coprocessor error + + 0 Divide error + 9 Coprocessor Segment Overrun +Contributory 10 Invalid TSS +Exceptions 11 Segment not present + 12 Stack exception + 13 General protection + +Page Faults 14 Page fault + + +Table 9-4. Double-Fault Definition + + SECOND EXCEPTION + + Benign Contributory Page + Exception Exception Fault + + + Benign OK OK OK + Exception + +FIRST Contributory OK DOUBLE OK +EXCEPTION Exception + + Page + Fault OK DOUBLE DOUBLE + + +9.8.9 Interrupt 9 Coprocessor Segment Overrun + +This exception is raised in protected mode if the 80386 detects a page or +segment violation while transferring the middle portion of a coprocessor +operand to the NPX. This exception is avoidable. Refer to Chapter 11 for +more information about the coprocessor interface. + + +9.8.10 Interrupt 10 Invalid TSS + +Interrupt 10 occurs if during a task switch the new TSS is invalid. A TSS +is considered invalid in the cases shown in Table 9-5. An error code is +pushed onto the stack to help identify the cause of the fault. The EXT bit +indicates whether the exception was caused by a condition outside the +control of the program; e.g., an external interrupt via a task gate +triggered a switch to an invalid TSS. + +This fault can occur either in the context of the original task or in the +context of the new task. Until the processor has completely verified the +presence of the new TSS, the exception occurs in the context of the original +task. Once the existence of the new TSS is verified, the task switch is +considered complete; i.e., TR is updated and, if the switch is due to a +CALL or interrupt, the backlink of the new TSS is set to the old TSS. Any +errors discovered by the processor after this point are handled in the +context of the new task. + +To insure a proper TSS to process it, the handler for exception 10 must be +a task invoked via a task gate. + + +Table 9-5. Conditions That Invalidate the TSS + +Error Code Condition + +TSS id + EXT The limit in the TSS descriptor is less than 103 +LTD id + EXT Invalid LDT selector or LDT not present +SS id + EXT Stack segment selector is outside table limit +SS id + EXT Stack segment is not a writable segment +SS id + EXT Stack segment DPL does not match new CPL +SS id + EXT Stack segment selector RPL < > CPL +CS id + EXT Code segment selector is outside table limit +CS id + EXT Code segment selector does not refer to code + segment +CS id + EXT DPL of non-conforming code segment < > new CPL +CS id + EXT DPL of conforming code segment > new CPL +DS/ES/FS/GS id + EXT DS, ES, FS, or GS segment selector is outside + table limits +DS/ES/FS/GS id + EXT DS, ES, FS, or GS is not readable segment + + +9.8.11 Interrupt 11 Segment Not Present + +Exception 11 occurs when the processor detects that the present bit of a +descriptor is zero. The processor can trigger this fault in any of these +cases: + + While attempting to load the CS, DS, ES, FS, or GS registers; loading + the SS register, however, causes a stack fault. + + While attempting loading the LDT register with an LLDT instruction; + loading the LDT register during a task switch operation, however, + causes the "invalid TSS" exception. + + While attempting to use a gate descriptor that is marked not-present. + +This fault is restartable. If the exception handler makes the segment +present and returns, the interrupted program will resume execution. + +If a not-present exception occurs during a task switch, not all the steps +of the task switch are complete. During a task switch, the processor first +loads all the segment registers, then checks their contents for validity. If +a not-present exception is discovered, the remaining segment registers have +not been checked and therefore may not be usable for referencing memory. The +not-present handler should not rely on being able to use the values found +in CS, SS, DS, ES, FS, and GS without causing another exception. The +exception handler should check all segment registers before trying to resume +the new task; otherwise, general protection faults may result later under +conditions that make diagnosis more difficult. There are three ways to +handle this case: + + 1. Handle the not-present fault with a task. The task switch back to the + interrupted task will cause the processor to check the registers as it + loads them from the TSS. + + 2. PUSH and POP all segment registers. Each POP causes the processor to + check the new contents of the segment register. + + 3. Scrutinize the contents of each segment-register image in the TSS, + simulating the test that the processor makes when it loads a segment + register. + +This exception pushes an error code onto the stack. The EXT bit of the +error code is set if an event external to the program caused an interrupt +that subsequently referenced a not-present segment. The I-bit is set if the +error code refers to an IDT entry, e.g., an INT instruction referencing a +not-present gate. + +An operating system typically uses the "segment not present" exception to +implement virtual memory at the segment level. A not-present indication in a +gate descriptor, however, usually does not indicate that a segment is not +present (because gates do not necessarily correspond to segments). +Not-present gates may be used by an operating system to trigger exceptions +of special significance to the operating system. + + +9.8.12 Interrupt 12 Stack Exception + +A stack fault occurs in either of two general conditions: + + As a result of a limit violation in any operation that refers to the + SS register. This includes stack-oriented instructions such as POP, + PUSH, ENTER, and LEAVE, as well as other memory references that + implicitly use SS (for example, MOV AX, [BP+6]). ENTER causes this + exception when the stack is too small for the indicated local-variable + space. + + When attempting to load the SS register with a descriptor that is + marked not-present but is otherwise valid. This can occur in a task + switch, an interlevel CALL, an interlevel return, an LSS instruction, + or a MOV or POP instruction to SS. + +When the processor detects a stack exception, it pushes an error code onto +the stack of the exception handler. If the exception is due to a not-present +stack segment or to overflow of the new stack during an interlevel CALL, the +error code contains a selector to the segment in question (the exception +handler can test the present bit in the descriptor to determine which +exception occurred); otherwise the error code is zero. + +An instruction that causes this fault is restartable in all cases. The +return pointer pushed onto the exception handler's stack points to the +instruction that needs to be restarted. This instruction is usually the one +that caused the exception; however, in the case of a stack exception due to +loading of a not-present stack-segment descriptor during a task switch, the +indicated instruction is the first instruction of the new task. + +When a stack fault occurs during a task switch, the segment registers may +not be usable for referencing memory. During a task switch, the selector +values are loaded before the descriptors are checked. If a stack fault is +discovered, the remaining segment registers have not been checked and +therefore may not be usable for referencing memory. The stack fault handler +should not rely on being able to use the values found in CS, SS, DS, ES, +FS, and GS without causing another exception. The exception handler should +check all segment registers before trying to resume the new task; otherwise, +general protection faults may result later under conditions that make +diagnosis more difficult. + + +9.8.13 Interrupt 13 General Protection Exception + +All protection violations that do not cause another exception cause a +general protection exception. This includes (but is not limited to): + + 1. Exceeding segment limit when using CS, DS, ES, FS, or GS + + 2. Exceeding segment limit when referencing a descriptor table + + 3. Transferring control to a segment that is not executable + + 4. Writing into a read-only data segment or into a code segment + + 5. Reading from an execute-only segment + + 6. Loading the SS register with a read-only descriptor (unless the + selector comes from the TSS during a task switch, in which case a TSS + exception occurs + + 7. Loading SS, DS, ES, FS, or GS with the descriptor of a system segment + + 8. Loading DS, ES, FS, or GS with the descriptor of an executable + segment that is not also readable + + 9. Loading SS with the descriptor of an executable segment + + 10. Accessing memory via DS, ES, FS, or GS when the segment register + contains a null selector + + 11. Switching to a busy task + + 12. Violating privilege rules + + 13. Loading CR0 with PG=1 and PE=0. + + 14. Interrupt or exception via trap or interrupt gate from V86 mode to + privilege level other than zero. + + 15. Exceeding the instruction length limit of 15 bytes (this can occur + only if redundant prefixes are placed before an instruction) + +The general protection exception is a fault. In response to a general +protection exception, the processor pushes an error code onto the exception +handler's stack. If loading a descriptor causes the exception, the error +code contains a selector to the descriptor; otherwise, the error code is +null. The source of the selector in an error code may be any of the +following: + + 1. An operand of the instruction. + 2. A selector from a gate that is the operand of the instruction. + 3. A selector from a TSS involved in a task switch. + + +9.8.14 Interrupt 14 Page Fault + +This exception occurs when paging is enabled (PG=1) and the processor +detects one of the following conditions while translating a linear address +to a physical address: + + The page-directory or page-table entry needed for the address + translation has zero in its present bit. + + The current procedure does not have sufficient privilege to access the + indicated page. + +The processor makes available to the page fault handler two items of +information that aid in diagnosing the exception and recovering from it: + + An error code on the stack. The error code for a page fault has a + format different from that for other exceptions (see Figure 9-8). The + error code tells the exception handler three things: + + 1. Whether the exception was due to a not present page or to an access + rights violation. + + 2. Whether the processor was executing at user or supervisor level at + the time of the exception. + + 3. Whether the memory access that caused the exception was a read or + write. + + CR2 (control register two). The processor stores in CR2 the linear + address used in the access that caused the exception (see Figure 9-9). + The exception handler can use this address to locate the corresponding + page directory and page table entries. If another page fault can occur + during execution of the page fault handler, the handler should push CR2 + onto the stack. + + +Figure 9-8. Page-Fault Error Code Format + + ͻ + FieldValue Description + Ķ + U/S 0 The access causing the fault originated when the processor + was executing in supervisor mode. + + 1 The access causing the fault originated when the processor + was executing in user mode. + + W/R 0 The access causing the fault was a read. + + 1 The access causing the fault was a write. + + P 0 The fault was caused by a not-present page. + + 1 The fault was caused by a page-level protection violation. + ͼ + + 31 15 7 3 2 1 0 + ͻ + UW + UNDEFINED//P + SR + ͼ + + +9.8.14.1 Page Fault During Task Switch + +The processor may access any of four segments during a task switch: + + 1. Writes the state of the original task in the TSS of that task. + + 2. Reads the GDT to locate the TSS descriptor of the new task. + + 3. Reads the TSS of the new task to check the types of segment + descriptors from the TSS. + + 4. May read the LDT of the new task in order to verify the segment + registers stored in the new TSS. + +A page fault can result from accessing any of these segments. In the latter +two cases the exception occurs in the context of the new task. The +instruction pointer refers to the next instruction of the new task, not to +the instruction that caused the task switch. If the design of the operating +system permits page faults to occur during task-switches, the page-fault +handler should be invoked via a task gate. + + +Figure 9-9. CR2 Format + + 31 23 15 7 0 + ͻ + + PAGE FAULT LINEAR ADDRESS + + ͼ + + +9.8.14.2 Page Fault with Inconsistent Stack Pointer + +Special care should be taken to ensure that a page fault does not cause the +processor to use an invalid stack pointer (SS:ESP). Software written for +earlier processors in the 8086 family often uses a pair of instructions to +change to a new stack; for example: + +MOV SS, AX +MOV SP, StackTop + +With the 80386, because the second instruction accesses memory, it is +possible to get a page fault after SS has been changed but before SP has +received the corresponding change. At this point, the two parts of the stack +pointer SS:SP (or, for 32-bit programs, SS:ESP) are inconsistent. + +The processor does not use the inconsistent stack pointer if the handling +of the page fault causes a stack switch to a well defined stack (i.e., the +handler is a task or a more privileged procedure). However, if the page +fault handler is invoked by a trap or interrupt gate and the page fault +occurs at the same privilege level as the page fault handler, the processor +will attempt to use the stack indicated by the current (invalid) stack +pointer. + +In systems that implement paging and that handle page faults within the +faulting task (with trap or interrupt gates), software that executes at the +same privilege level as the page fault handler should initialize a new stack +by using the new LSS instruction rather than an instruction pair shown +above. When the page fault handler executes at privilege level zero (the +normal case), the scope of the problem is limited to privilege-level zero +code, typically the kernel of the operating system. + + +9.8.15 Interrupt 16 Coprocessor Error + +The 80386 reports this exception when it detects a signal from the 80287 or +80387 on the 80386's ERROR# input pin. The 80386 tests this pin only at the +beginning of certain ESC instructions and when it encounters a WAIT +instruction while the EM bit of the MSW is zero (no emulation). Refer to +Chapter 11 for more information on the coprocessor interface. + + +9.9 Exception Summary + + +Table 9-6 summarizes the exceptions recognized by the 386. + +Table 9-6. Exception Summary + + +Description Interrupt Return Address Exception Function That Can Generate + Number Points to Type the Exception + Faulting + Instruction + +Divide error 0 YES FAULT DIV, IDIV +Debug exceptions 1 +Some debug exceptions are traps and some are faults. The exception +handler can determine which has occurred by examining DR6. (Refer to +Chapter 12.) +Some debug exceptions are traps and some are faults. The exception +handler can determine which has occurred by examining DR6. (Refer to +Chapter 12.) Any instruction +Breakpoint 3 NO TRAP One-byte INT 3 +Overflow 4 NO TRAP INTO +Bounds check 5 YES FAULT BOUND +Invalid opcode 6 YES FAULT Any illegal instruction +Coprocessor not available 7 YES FAULT ESC, WAIT +Double fault 8 YES ABORT Any instruction that can + generate an exception +Coprocessor Segment +Overrun 9 NO ABORT Any operand of an ESC + instruction that wraps around + the end of a segment. +Invalid TSS 10 YES FAULT +An invalid-TSS fault is not restartable if it occurs during the +processing of an external interrupt. JMP, CALL, IRET, any interrupt +Segment not present 11 YES FAULT Any segment-register modifier +Stack exception 12 YES FAULT Any memory reference thru SS +General Protection 13 YES FAULT/ABORT +All GP faults are restartable. If the fault occurs while attempting to +vector to the handler for an external interrupt, the interrupted program is +restartable, but the interrupt may be lost. Any memory reference or code + fetch +Page fault 14 YES FAULT Any memory reference or code + fetch +Coprocessor error 16 YES FAULT +Coprocessor errors are reported as a fault on the first ESC or WAIT +instruction executed after the ESC instruction that caused the error. ESC, WAIT +Two-byte SW Interrupt 0-255 NO TRAP INT n + + +9.10 Error Code Summary + +Table 9-7 summarizes the error information that is available with each +exception. + + +Table 9-7. Error-Code Summary + +Description Interrupt Error Code + Number + +Divide error 0 No +Debug exceptions 1 No +Breakpoint 3 No +Overflow 4 No +Bounds check 5 No +Invalid opcode 6 No +Coprocessor not available 7 No +System error 8 Yes (always 0) +Coprocessor Segment Overrun 9 No +Invalid TSS 10 Yes +Segment not present 11 Yes +Stack exception 12 Yes +General protection fault 13 Yes +Page fault 14 Yes +Coprocessor error 16 No +Two-byte SW interrupt 0-255 No + + +Chapter 10 Initialization + + + +After a signal on the RESET pin, certain registers of the 80386 are set to +predefined values. These values are adequate to enable execution of a +bootstrap program, but additional initialization must be performed by +software before all the features of the processor can be utilized. + + +10.1 Processor State After Reset + +The contents of EAX depend upon the results of the power-up self test. The +self-test may be requested externally by assertion of BUSY# at the end of +RESET. The EAX register holds zero if the 80386 passed the test. A nonzero +value in EAX after self-test indicates that the particular 80386 unit is +faulty. If the self-test is not requested, the contents of EAX after RESET +is undefined. + +DX holds a component identifier and revision number after RESET as Figure +10-1 illustrates. DH contains 3, which indicates an 80386 component. DL +contains a unique identifier of the revision level. + +Control register zero (CR0) contains the values shown in Figure 10-2. The +ET bit of CR0 is set if an 80387 is present in the configuration (according +to the state of the ERROR# pin after RESET). If ET is reset, the +configuration either contains an 80287 or does not contain a coprocessor. A +software test is required to distinguish between these latter two +possibilities. + +The remaining registers and flags are set as follows: + + EFLAGS =00000002H + IP =0000FFF0H + CS selector =000H + DS selector =0000H + ES selector =0000H + SS selector =0000H + FS selector =0000H + GS selector =0000H + IDTR: + base =0 + limit =03FFH + +All registers not mentioned above are undefined. + +These settings imply that the processor begins in real-address mode with +interrupts disabled. + + +Figure 10-1. Contents of EDX after RESET + + EDX REGISTER + + 31 23 15 7 0 + ͻ + DH DL + UNDEFINED DEVICE ID STEPPING ID + 3 (UNIQUE) + ͼ + + +Figure 10-2. Initial Contents of CR0 + + CONTROL REGISTER ZERO + + 31 23 15 7 4 3 1 0 + ͻ + P ETEMP + UNDEFINED + G TSMPE + Ѽ + + 0 - PAGING DISABLED + * - INDICATES PRESENCE OF 80387 + 0 - NO TASK SWITCH + 0 - DO NOT MONITOR COPROCESSOR + 0 - COPROCESSOR NOT PRESENT + 0 - PROTECTION NOT ENABLED (REAL ADDRESS MODE) + + +10.2 Software Initialization for Real-Address Mode + +In real-address mode a few structures must be initialized before a program +can take advantage of all the features available in this mode. + + +10.2.1 Stack + +No instructions that use the stack can be used until the stack-segment +register (SS) has been loaded. SS must point to an area in RAM. + + +10.2.2 Interrupt Table + +The initial state of the 80386 leaves interrupts disabled; however, the +processor will still attempt to access the interrupt table if an exception +or nonmaskable interrupt (NMI) occurs. Initialization software should take +one of the following actions: + + Change the limit value in the IDTR to zero. This will cause a shutdown + if an exception or nonmaskable interrupt occurs. (Refer to the 80386 + Hardware Reference Manual to see how shutdown is signalled externally.) + + Put pointers to valid interrupt handlers in all positions of the + interrupt table that might be used by exceptions or interrupts. + + Change the IDTR to point to a valid interrupt table. + + +10.2.3 First Instructions + +After RESET, address lines A{31-20} are automatically asserted for +instruction fetches. This fact, together with the initial values of CS:IP, +causes instruction execution to begin at physical address FFFFFFF0H. Near +(intrasegment) forms of control transfer instructions may be used to pass +control to other addresses in the upper 64K bytes of the address space. The +first far (intersegment) JMP or CALL instruction causes A{31-20} to drop +low, and the 80386 continues executing instructions in the lower one +megabyte of physical memory. This automatic assertion of address lines +A{31-20} allows systems designers to use a ROM at the high end of +the address space to initialize the system. + + +10.3 Switching to Protected Mode + +Setting the PE bit of the MSW in CR0 causes the 80386 to begin executing in +protected mode. The current privilege level (CPL) starts at zero. The +segment registers continue to point to the same linear addresses as in real +address mode (in real address mode, linear addresses are the same physical +addresses). + +Immediately after setting the PE flag, the initialization code must flush +the processor's instruction prefetch queue by executing a JMP instruction. +The 80386 fetches and decodes instructions and addresses before they are +used; however, after a change into protected mode, the prefetched +instruction information (which pertains to real-address mode) is no longer +valid. A JMP forces the processor to discard the invalid information. + + +10.4 Software Initialization for Protected Mode + +Most of the initialization needed for protected mode can be done either +before or after switching to protected mode. If done in protected mode, +however, the initialization procedures must not use protected-mode features +that are not yet initialized. + + +10.4.1 Interrupt Descriptor Table + +The IDTR may be loaded in either real-address or protected mode. However, +the format of the interrupt table for protected mode is different than that +for real-address mode. It is not possible to change to protected mode and +change interrupt table formats at the same time; therefore, it is inevitable +that, if IDTR selects an interrupt table, it will have the wrong format at +some time. An interrupt or exception that occurs at this time will have +unpredictable results. To avoid this unpredictability, interrupts should +remain disabled until interrupt handlers are in place and a valid IDT has +been created in protected mode. + + +10.4.2 Stack + +The SS register may be loaded in either real-address mode or protected +mode. If loaded in real-address mode, SS continues to point to the same +linear base-address after the switch to protected mode. + + +10.4.3 Global Descriptor Table + +Before any segment register is changed in protected mode, the GDT register +must point to a valid GDT. Initialization of the GDT and GDTR may be done in +real-address mode. The GDT (as well as LDTs) should reside in RAM, because +the processor modifies the accessed bit of descriptors. + + +10.4.4 Page Tables + +Page tables and the PDBR in CR3 can be initialized in either real-address +mode or in protected mode; however, the paging enabled (PG) bit of CR0 +cannot be set until the processor is in protected mode. PG may be set +simultaneously with PE, or later. When PG is set, the PDBR in CR3 should +already be initialized with a physical address that points to a valid page +directory. The initialization procedure should adopt one of the following +strategies to ensure consistent addressing before and after paging is +enabled: + + The page that is currently being executed should map to the same + physical addresses both before and after PG is set. + + A JMP instruction should immediately follow the setting of PG. + + +10.4.5 First Task + +The initialization procedure can run awhile in protected mode without +initializing the task register; however, before the first task switch, the +following conditions must prevail: + + There must be a valid task state segment (TSS) for the new task. The + stack pointers in the TSS for privilege levels numerically less than or + equal to the initial CPL must point to valid stack segments. + + The task register must point to an area in which to save the current + task state. After the first task switch, the information dumped in this + area is not needed, and the area can be used for other purposes. + + +10.5 Initialization Example + +$TITLE ('Initial Task') + + NAME INIT + +init_stack SEGMENT RW + DW 20 DUP(?) +tos LABEL WORD +init_stack ENDS + +init_data SEGMENT RW PUBLIC + DW 20 DUP(?) +init_data ENDS + +init_code SEGMENT ER PUBLIC + +ASSUME DS:init_data + + nop + nop + nop +init_start: + ; set up stack + mov ax, init_stack + mov ss, ax + mov esp, offset tos + + mov a1,1 +blink: + xor a1,1 + out 0e4h,a1 + mov cx,3FFFh +here: + dec cx + jnz here + + jmp SHORT blink + + hlt +init_code ends + + END init_start, SS:init_stack, DS:init_data + +$TITLE('Protected Mode Transition -- 386 initialization') +NAME RESET + +;***************************************************************** +; Upon reset the 386 starts executing at address 0FFFFFFF0H. The +; upper 12 address bits remain high until a FAR call or jump is +; executed. +; +; Assume the following: +; +; +; - a short jump at address 0FFFFFFF0H (placed there by the +; system builder) causes execution to begin at START in segment +; RESET_CODE. +; +; +; - segment RESET_CODE is based at physical address 0FFFF0000H, +; i.e. at the start of the last 64K in the 4G address space. +; Note that this is the base of the CS register at reset. If +; you locate ROMcode above this address, you will need to +; figure out an adjustment factor to address things within this +; segment. +; +;***************************************************************** +$EJECT ; + +; Define addresses to locate GDT and IDT in RAM. +; These addresses are also used in the BLD386 file that defines +; the GDT and IDT. If you change these addresses, make sure you +; change the base addresses specified in the build file. + +GDTbase EQU 00001000H ; physical address for GDT base +IDTbase EQU 00000400H ; physical address for IDT base + +PUBLIC GDT_EPROM +PUBLIC IDT_EPROM +PUBLIC START + +DUMMY segment rw ; ONLY for ASM386 main module stack init + DW 0 +DUMMY ends + +;***************************************************************** +; +; Note: RESET CODE must be USEl6 because the 386 initally executes +; in real mode. +; + +RESET_CODE segment er PUBLIC USE16 + +ASSUME DS:nothing, ES:nothing + +; +; 386 Descriptor template + +DESC STRUC + lim_0_15 DW 0 ; limit bits (0..15) + bas_0_15 DW 0 ; base bits (0..15) + bas_16_23 DB 0 ; base bits (16..23) + access DB 0 ; access byte + gran DB 0 ; granularity byte + bas_24_31 DB 0 ; base bits (24..31) +DESC ENDS + +; The following is the layout of the real GDT created by BLD386. +; It is located in EPROM and will be copied to RAM. +; +; GDT[O] ... NULL +; GDT[1] ... Alias for RAM GDT +; GDT[2] ... Alias for RAM IDT +; GDT[2] ... initial task TSS +; GDT[3] ... initial task TSS alias +; GDT[4] ... initial task LDT +; GDT[5] ... initial task LDT alias + +; +; define entries in GDT and IDT. + +GDT_ENTRIES EQU 8 +IDT_ENTRIES EQU 32 + +; define some constants to index into the real GDT + +GDT_ALIAS EQU 1*SIZE DESC +IDT_ALIAS EQU 2*SIZE DESC +INIT_TSS EQU 3*SIZE DESC +INIT_TSS_A EQU 4*SIZE DESC +INIT_LDT EQU 5*SIZE DESC +INIT_LDT_A EQU 6*SIZE DESC + +; +; location of alias in INIT_LDT + +INIT_LDT_ALIAS EQU 1*SIZE DESC + +; +; access rights byte for DATA and TSS descriptors + +DS_ACCESS EQU 010010010B +TSS_ACCESS EQU 010001001B + + +; +; This temporary GDT will be used to set up the real GDT in RAM. + +Temp_GDT LABEL BYTE ; tag for begin of scratch GDT + +NULL_DES DESC <> ; NULL descriptor + + ; 32-Gigabyte data segment based at 0 +FLAT_DES DESC <0FFFFH,0,0,92h,0CFh,0> + +GDT_eprom DP ? ; Builder places GDT address and limit + ; in this 6 byte area. + +IDT_eprom DP ? ; Builder places IDT address and limit + ; in this 6 byte area. + +; +; Prepare operand for loadings GDTR and LDTR. + + +TGDT_pword LABEL PWORD ; for temp GDT + DW end_Temp_GDT_Temp_GDT -1 + DD 0 + +GDT_pword LABEL PWORD ; for GDT in RAM + DW GDT_ENTRIES * SIZE DESC -1 + DD GDTbase + +IDT_pword LABEL PWORD ; for IDT in RAM + DW IDT_ENTRIES * SIZE DESC -1 + DD IDTbase + + +end_Temp_GDT LABEL BYTE + +; +; Define equates for addressing convenience. + +GDT_DES_FLAT EQU DS:GDT_ALIAS +GDTbase +IDT_DES_FLAT EQU DS:IDT_ALIAS +GDTbase + +INIT_TSS_A_OFFSET EQU DS:INIT_TSS_A +INIT_TSS_OFFSET EQU DS:INIT_TSS + +INIT_LDT_A_OFFSET EQU DS:INIT_LDT_A +INIT_LDT_OFFSET EQU DS:INIT_LDT + + +; define pointer for first task switch + +ENTRY POINTER LABEL DWORD + DW 0, INIT_TSS + +;****************************************************************** +; +; Jump from reset vector to here. + +START: + + CLI ;disable interrupts + CLD ;clear direction flag + + LIDT NULL_des ;force shutdown on errors + +; +; move scratch GDT to RAM at physical 0 + + XOR DI,DI + MOV ES,DI ;point ES:DI to physical location 0 + + + MOV SI,OFFSET Temp_GDT + MOV CX,end_Temp_GDT-Temp_GDT ;set byte count + INC CX +; +; move table + + REP MOVS BYTE PTR ES:[DI],BYTE PTR CS:[SI] + + LGDT tGDT_pword ;load GDTR for Temp. GDT + ;(located at 0) + +; switch to protected mode + + MOV EAX,CR0 ;get current CRO + MOV EAX,1 ;set PE bit + MOV CRO,EAX ;begin protected mode +; +; clear prefetch queue + + JMP SHORT flush +flush: + +; set DS,ES,SS to address flat linear space (0 ... 4GB) + + MOV BX,FLAT_DES-Temp_GDT + MOV US,BX + MOV ES,BX + MOV SS,BX +; +; initialize stack pointer to some (arbitrary) RAM location + + MOV ESP, OFFSET end_Temp_GDT + +; +; copy eprom GDT to RAM + + MOV ESI,DWORD PTR GDT_eprom +2 ; get base of eprom GDT + ; (put here by builder). + + MOV EDI,GDTbase ; point ES:EDI to GDT base in RAM. + + MOV CX,WORD PTR gdt_eprom +0 ; limit of eprom GDT + INC CX + SHR CX,1 ; easier to move words + CLD + REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] + +; +; copy eprom IDT to RAM +; + MOV ESI,DWORD PTR IDT_eprom +2 ; get base of eprom IDT + ; (put here by builder) + + MOV EDI,IDTbase ; point ES:EDI to IDT base in RAM. + + MOV CX,WORD PTR idt_eprom +0 ; limit of eprom IDT + INC CX + SHR CX,1 + CLD + REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] + +; switch to RAM GDT and IDT +; + LIDT IDT_pword + LGDT GDT_pword + +; + MOV BX,GDT_ALIAS ; point DS to GDT alias + MOV DS,BX +; +; copy eprom TSS to RAM +; + MOV BX,INIT_TSS_A ; INIT TSS A descriptor base + ; has RAM location of INIT TSS. + + MOV ES,BX ; ES points to TSS in RAM + + MOV BX,INIT_TSS ; get inital task selector + LAR DX,BX ; save access byte + MOV [BX].access,DS_ACCESS ; set access as data segment + MOV FS,BX ; FS points to eprom TSS + + XOR si,si ; FS:si points to eprom TSS + XOR di,di ; ES:di points to RAM TSS + + MOV CX,[BX].lim_0_15 ; get count to move + INC CX + +; +; move INIT_TSS to RAM. + + REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si] + + MOV [BX].access,DH ; restore access byte + +; +; change base of INIT TSS descriptor to point to RAM. + + MOV AX,INIT_TSS_A_OFFSET.bas_0_15 + MOV INIT_TSS_OFFSET.bas_0_15,AX + MOV AL,INIT_TSS_A_OFFSET.bas_16_23 + MOV INIT_TSS_OFFSET.bas_16_23,AL + MOV AL,INIT_TSS_A_OFFSET.bas_24_31 + MOV INIT_TSS_OFFSET.bas_24_31,AL + +; +; change INIT TSS A to form a save area for TSS on first task +; switch. Use RAM at location 0. + + MOV BX,INIT_TSS_A + MOV WORD PTR [BX].bas_0_15,0 + MOV [BX].bas_16_23,0 + MOV [BX].bas_24_31,0 + MOV [BX].access,TSS_ACCESS + MOV [BX].gran,O + LTR BX ; defines save area for TSS + +; +; copy eprom LDT to RAM + + MOV BX,INIT_LDT_A ; INIT_LDT_A descriptor has + ; base address in RAM for INIT_LDT. + + MOV ES,BX ; ES points LDT location in RAM. + + MOV AH,[BX].bas_24_31 + MOV AL,[BX].bas_16_23 + SHL EAX,16 + MOV AX,[BX].bas_0_15 ; save INIT_LDT base (ram) in EAX + + MOV BX,INIT_LDT ; get inital LDT selector + LAR DX,BX ; save access rights + MOV [BX].access,DS_ACCESS ; set access as data segment + MOV FS,BX ; FS points to eprom LDT + + XOR si,si ; FS:SI points to eprom LDT + XOR di,di ; ES:DI points to RAM LDT + + MOV CX,[BX].lim_0_15 ; get count to move + INC CX +; +; move initial LDT to RAM + + REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si] + + MOV [BX].access,DH ; restore access rights in + ; INIT_LDT descriptor + +; +; change base of alias (of INIT_LDT) to point to location in RAM. + + MOV ES:[INIT_LDT_ALIAS].bas_0_15,AX + SHR EAX,16 + MOV ES:[INIT_LDT_ALIAS].bas_16_23,AL + MOV ES:[INIT_LDT_ALIAS].bas_24_31,AH + +; +; now set the base value in INIT_LDT descriptor + + MOV AX,INIT_LDT_A_OFFSET.bas_0_15 + MOV INIT_LDT_OFFSET.bas_0_15,AX + MOV AL,INIT_LDT_A_OFFSET.bas_16_23 + MOV INIT_LDT_OFFSET.bas_16_23,AL + MOV AL,INIT_LDT_A_OFFSET.bas_24_31 + MOV INIT_LDT_OFFSET.bas_24_31,AL + +; +; Now GDT, IDT, initial TSS and initial LDT are all set up. +; +; Start the first task! +' + JMP ENTRY_POINTER + +RESET_CODE ends + END START, SS:DUMMY,DS:DUMMY + + +10.6 TLB Testing + +The 80386 provides a mechanism for testing the Translation Lookaside Buffer +(TLB), the cache used for translating linear addresses to physical +addresses. Although failure of the TLB hardware is extremely unlikely, users +may wish to include TLB confidence tests among other power-up confidence +tests for the 80386. + + +NOTE + This TLB testing mechanism is unique to the 80386 and may not be + continued in the same way in future processors. Sortware that uses + this mechanism may be incompatible with future processors. + + +When testing the TLB it is recommended that paging be turned off (PG=0 in +CR0) to avoid interference with the test data being written to the TLB. + + +10.6.1 Structure of the TLB + +The TLB is a four-way set-associative memory. Figure 10-3 illustrates the +structure of the TLB. There are four sets of eight entries each. Each entry +consists of a tag and data. Tags are 24-bits wide. They contain the +high-order 20 bits of the linear address, the valid bit, and three attribute +bits. The data portion of each entry contains the high-order 20 bits of the +physical address. + + +10.6.2 Test Registers + +Two test registers, shown in Figure 10-4, are provided for the purpose of +testing. TR6 is the test command register, and TR7 is the test data +register. These registers are accessed by variants of the MOV +instruction. A test register may be either the source operand or destination +operand. The MOV instructions are defined in both real-address mode and +protected mode. The test registers are privileged resources; in protected +mode, the MOV instructions that access them can only be executed at +privilege level 0. An attempt to read or write the test registers when +executing at any other privilege level causes a general +protection exception. + +The test command register (TR6) contains a command and an address tag to +use in performing the command: + +C This is the command bit. There are two TLB testing commands: + write entries into the TLB, and perform TLB lookups. To cause an + immediate write into the TLB entry, move a doubleword into TR6 + that contains a 0 in this bit. To cause an immediate TLB lookup, + move a doubleword into TR6 that contains a 1 in this bit. + +Linear On a TLB write, a TLB entry is allocated to this linear address; +Address the rest of that TLB entry is set per the value of TR7 and the + value just written into TR6. On a TLB lookup, the TLB is + interrogated per this value; if one and only one TLB entry + matches, the rest of the fields of TR6 and TR7 are set from the + matching TLB entry. + +V The valid bit for this TLB entry. The TLB uses the valid bit to + identify entries that contain valid data. Entries of the TLB + that have not been assigned values have zero in the valid bit. + All valid bits can be cleared by writing to CR3. + +D, D# The dirty bit (and its complement) for/from the TLB entry. + +U, U# The U/S bit (and its complement) for/from the TLB entry. + +W, W# The R/W bit (and its complement) for/from the TLB entry. + + The meaning of these pairs of bits is given by Table 10-1, + where X represents D, U, or W. + +The test data register (TR7) holds data read from or data to be written to +the TLB. + +Physical This is the data field of the TLB. On a write to the TLB, the +Address TLB entry allocated to the linear address in TR6 is set to this + value. On a TLB lookup, if HT is set, the data field (physical + address) from the TLB is read out to this field. If HT is not + set, this field is undefined. + +HT For a TLB lookup, the HT bit indicates whether the lookup was a + hit (HT  1) or a miss (HT  0). For a TLB write, HT must be set + to 1. + +REP For a TLB write, selects which of four associative blocks of the + TLB is to be written. For a TLB read, if HT is set, REP reports + in which of the four associative blocks the tag was found; if HT + is not set, REP is undefined. + + +Table 10-1. Meaning of D, U, and W Bit Pairs + +X X# Effect during Value of bit X + TLB Lookup after TLB Write + +0 0 (undefined) (undefined) +0 1 Match if X=0 Bit X becomes 0 +1 0 Match if X=1 Bit X becomes 1 +1 1 (undefined) (undefined) + + +Figure 10-3. TLB Structure + + ͻ + 7 TAG DATA + ͹ +    +    + SET 11    + ͹ + 1 TAG DATA + ͹ + 0 TAG DATA + ͼ + + ͻ + 7 TAG DATA + ͹ +    +    + SET 10    + ͹ + 1 TAG DATA + D ͹ + A 0 TAG DATA + T ͼ + A + Ŀ ͻ + B 7 TAG DATA + U ͹ + S    +    + SET 01    + ͹ + 1 TAG DATA + ͹ + 0 TAG DATA + ͼ + + ͻ + 7 TAG DATA + ͹ +    +    + SET 00    + ͹ + 1 TAG DATA + ͹ + 0 TAG DATA + ͼ + + +Figure 10-4. Test Registers + + 31 23 15 11 7 0 + ͻ + H + PHYSICAL ADDRESS 0 0 0 0 0 0 0 REP0 0 TR7 + T + Ķ + D U W + LINEAR ADDRESS VD U 0 0 0 0C TR8 + # # # + ͼ + + NOTE: 0 INDICATES INTEL RESERVED. NO NOT DEFINE + + +10.6.3 Test Operations + +To write a TLB entry: + + 1. Move a doubleword to TR7 that contains the desired physical address, + HT, and REP values. HT must contain 1. REP must point to the + associative block in which to place the entry. + + 2. Move a doubleword to TR6 that contains the appropriate linear + address, and values for V, D, U, and W. Be sure C=0 for "write" + command. + +Be careful not to write duplicate tags; the results of doing so are +undefined. + +To look up (read) a TLB entry: + + 1. Move a doubleword to TR6 that contains the appropriate linear address + and attributes. Be sure C=1 for "lookup" command. + + 2. Store TR7. If the HT bit in TR7 indicates a hit, then the other + values reveal the TLB contents. If HT indicates a miss, then the other + values in TR7 are indeterminate. + +For the purposes of testing, the V bit functions as another bit of +addresss. The V bit for a lookup request should usually be set, so that +uninitialized tags do not match. Lookups with V=0 are unpredictable if any +tags are uninitialized. + + +Chapter 11 Coprocessing and Multiprocessing + + + +The 80386 has two levels of support for multiple parallel processing units: + + A highly specialized interface for very closely coupled processors of + a type known as coprocessors. + + A more general interface for more loosely coupled processors of + unspecified type. + + +11.1 Coprocessing + +The components of the coprocessor interface include: + + ET bit of control register zero (CR0) + The EM, and MP bits of CR0 + The ESC instructions + The WAIT instruction + The TS bit of CR0 + Exceptions + + +11.1.1 Coprocessor Identification + +The 80386 is designed to operate with either an 80287 or 80387 math +coprocessor. The ET bit of CR0 indicates which type of coprocessor is +present. ET is set automatically by the 80386 after RESET according to the +level detected on the ERROR# input. If desired, ET may also be set or reset +by loading CR0 with a MOV instruction. If ET is set, the 80386 uses the +32-bit protocol of the 80387; if reset, the 80386 uses the 16-bit protocol +of the 80287. + + +11.1.2 ESC and WAIT Instructions + +The 80386 interprets the pattern 11011B in the first five bits of an +instruction as an opcode intended for a coprocessor. Instructions thus +marked are called ESCAPE or ESC instructions. The CPU performs the following +functions upon encountering an ESC instruction before sending the +instruction to the coprocessor: + + Tests the emulation mode (EM) flag to determine whether coprocessor + functions are being emulated by software. + + Tests the TS flag to determine whether there has been a context change + since the last ESC instruction. + + For some ESC instructions, tests the ERROR# pin to determine whether + the coprocessor detected an error in the previous ESC instruction. + +The WAIT instruction is not an ESC instruction, but WAIT causes the CPU to +perform some of the same tests that it performs upon encountering an ESC +instruction. The processor performs the following actions for a WAIT +instruction: + + Waits until the coprocessor no longer asserts the BUSY# pin. + + Tests the ERROR# pin (after BUSY# goes inactive). If ERROR# is active, + the 80386 signals exception 16, which indicates that the coprocessor + encountered an error in the previous ESC instruction. + + WAIT can therefore be used to cause exception 16 if an error is + pending from a previous ESC instruction. Note that, if no coprocessor + is present, the ERROR# and BUSY# pins should be tied inactive to + prevent WAIT from waiting forever or causing spurious exceptions. + + +11.1.3 EM and MP Flags + +The EM and MP flags of CR0 control how the processor reacts to coprocessor +instructions. + +The EM bit indicates whether coprocessor functions are to be emulated. If +the processor finds EM set when executing an ESC instruction, it signals +exception 7, giving the exception handler an opportunity to emulate the ESC +instruction. + +The MP (monitor coprocessor) bit indicates whether a coprocessor is +actually attached. The MP flag controls the function of the WAIT +instruction. If, when executing a WAIT instruction, the CPU finds MP set, +then it tests the TS flag; it does not otherwise test TS during a WAIT +instruction. If it finds TS set under these conditions, the CPU signals +exception 7. + +The EM and MP flags can be changed with the aid of a MOV instruction using +CR0 as the destination operand and read with the aid of a MOV instruction +with CR0 as the source operand. These forms of the MOV instruction can be +executed only at privilege level zero. + + +11.1.4 The Task-Switched Flag + +The TS bit of CR0 helps to determine when the context of the coprocessor +does not match that of the task being executed by the 80386 CPU. The 80386 +sets TS each time it performs a task switch (whether triggered by software +or by hardware interrupt). If, when interpreting one of the ESC +instructions, the CPU finds TS already set, it causes exception 7. The WAIT +instruction also causes exception 7 if both TS and MP are set. Operating +systems can use this exception to switch the context of the coprocessor to +correspond to the current task. Refer to the 80386 System Software Writer's +Guide for an example. + +The CLTS instruction (legal only at privilege level zero) resets the TS +flag. + + +11.1.5 Coprocessor Exceptions + +Three exceptions aid in interfacing to a coprocessor: interrupt 7 +(coprocessor not available), interrupt 9 (coprocessor segment overrun), and +interrupt 16 (coprocessor error). + + +11.1.5.1 Interrupt 7 Coprocessor Not Available + +This exception occurs in either of two conditions: + + 1. The CPU encounters an ESC instruction and EM is set. In this case, + the exception handler should emulate the instruction that caused the + exception. TS may also be set. + + 2. The CPU encounters either the WAIT instruction or an ESC instruction + when both MP and TS are set. In this case, the exception handler + should update the state of the coprocessor, if necessary. + + +11.1.5.2 Interrupt 9 Coprocessor Segment Overrun + +This exception occurs in protected mode under the following conditions: + + An operand of a coprocessor instruction wraps around an addressing + limit (0FFFFH for small segments, 0FFFFFFFFH for big segments, zero for + expand-down segments). An operand may wrap around an addressing limit + when the segment limit is near an addressing limit and the operand is + near the largest valid address in the segment. Because of the + wrap-around, the beginning and ending addresses of such an operand + will be near opposite ends of the segment. + + Both the first byte and the last byte of the operand (considering + wrap-around) are at addresses located in the segment and in present and + accessible pages. + + The operand spans inaccessible addresses. There are two ways that such + an operand may also span inaccessible addresses: + + 1. The segment limit is not equal to the addressing limit (e.g., + addressing limit is FFFFH and segment limit is FFFDH); therefore, + the operand will span addresses that are not within the segment + (e.g., an 8-byte operand that starts at valid offset FFFC will span + addresses FFFC-FFFF and 0000-0003; however, addresses FFFE and FFFF + are not valid, because they exceed the limit); + + 2. The operand begins and ends in present and accessible pages but + intermediate bytes of the operand fall either in a not-present page + or in a page to which the current procedure does not have access + rights. + +The address of the failing numerics instruction and data operand may be +lost; an FSTENV does not return reliable addresses. As with the 80286/80287, +the segment overrun exception should be handled by executing an FNINIT +instruction (i.e., an FINIT without a preceding WAIT). The return address on +the stack does not necessarily point to the failing instruction nor to the +following instruction. The failing numerics instruction is not restartable. + +Case 2 can be avoided by either aligning all segments on page boundaries or +by not starting them within 108 bytes of the start or end of a page. (The +maximum size of a coprocessor operand is 108 bytes.) Case 1 can be avoided +by making sure that the gap between the last valid offset and the first +valid offset of a segment is either no less than 108 bytes or is zero (i.e., +the segment is of full size). If neither software system design constraint +is acceptable, the exception handler should execute FNINIT and should +probably terminate the task. + + +11.1.5.3 Interrupt 16 Coprocessor Error + +The numerics coprocessors can detect six different exception conditions +during instruction execution. If the detected exception is not masked by a +bit in the control word, the coprocessor communicates the fact that an error +occurred to the CPU by a signal at the ERROR# pin. The CPU causes interrupt +16 the next time it checks the ERROR# pin, which is only at the beginning of +a subsequent WAIT or certain ESC instructions. If the exception is masked, +the numerics coprocessor handles the exception according to on-board logic; +it does not assert the ERROR# pin in this case. + + +11.2 General Multiprocessing + +The components of the general multiprocessing interface include: + + The LOCK# signal + + The LOCK instruction prefix, which gives programmed control of the + LOCK# signal. + + Automatic assertion of the LOCK# signal with implicit memory updates + by the processor + + +11.2.1 LOCK and the LOCK# Signal + +The LOCK instruction prefix and its corresponding output signal LOCK# can +be used to prevent other bus masters from interrupting a data movement +operation. LOCK may only be used with the following 80386 instructions when +they modify memory. An undefined-opcode exception results from using LOCK +before any instruction other than: + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + +A locked instruction is only guaranteed to lock the area of memory defined +by the destination operand, but it may lock a larger memory area. For +example, typical 8086 and 80286 configurations lock the entire physical +memory space. The area of memory defined by the destination operand is +guaranteed to be locked against access by a processor executing a locked +instruction on exactly the same memory area, i.e., an operand with +identical starting address and identical length. + +The integrity of the lock is not affected by the alignment of the memory +field. The LOCK signal is asserted for as many bus cycles as necessary to +update the entire operand. + + +11.2.2 Automatic Locking + +In several instances, the processor itself initiates activity on the data +bus. To help ensure that such activities function correctly in +multiprocessor configurations, the processor automatically asserts the LOCK# +signal. These instances include: + + Acknowledging interrupts. + + After an interrupt request, the interrupt controller uses the data bus + to send the interrupt ID of the interrupt source to the CPU. The CPU + asserts LOCK# to ensure that no other data appears on the data bus + during this time. + + Setting busy bit of TSS descriptor. + + The processor tests and sets the busy-bit in the type field of the TSS + descriptor when switching to a task. To ensure that two different + processors cannot simultaneously switch to the same task, the processor + asserts LOCK# while testing and setting this bit. + + Loading of descriptors. + + While copying the contents of a descriptor from a descriptor table into + a segment register, the processor asserts LOCK# so that the descriptor + cannot be modified by another processor while it is being loaded. For + this action to be effective, operating-system procedures that update + descriptors should adhere to the following steps: + + Use a locked update to the access-rights byte to mark the + descriptor not-present. + + Update the fields of the descriptor. (This may require several + memory accesses; therefore, LOCK cannot be used.) + + Use a locked update to the access-rights byte to mark the + descriptor present again. + + Updating page-table A and D bits. + + The processor exerts LOCK# while updating the A (accessed) and D + (dirty) bits of page-table entries. Also the processor bypasses the + page-table cache and directly updates these bits in memory. + + Executing XCHG instruction. + + The 80386 always asserts LOCK during an XCHG instruction that + references memory (even if the LOCK prefix is not used). + + +11.2.3 Cache Considerations + +Systems programmers must take care when updating shared data that may also +be stored in on-chip registers and caches. With the 80386, such shared +data includes: + + Descriptors, which may be held in segment registers. + + A change to a descriptor that is shared among processors should be + broadcast to all processors. Segment registers are effectively + "descriptor caches". A change to a descriptor will not be utilized by + another processor if that processor already has a copy of the old + version of the descriptor in a segment register. + + Page tables, which may be held in the page-table cache. + + A change to a page table that is shared among processors should be + broadcast to all processors, so that others can flush their page-table + caches and reload them with up-to-date page tables from memory. + +Systems designers can employ an interprocessor interrupt to handle the +above cases. When one processor changes data that may be cached by other +processors, it can send an interrupt signal to all other processors that may +be affected by the change. If the interrupt is serviced by an interrupt +task, the task switch automatically flushes the segment registers. The task +switch also flushes the page-table cache if the PDBR (the contents of CR3) +of the interrupt task is different from the PDBR of every other task. + +In multiprocessor systems that need a cacheability signal from the CPU, it +is recommended that physical address pin A31 be used to indicate +cacheability. Such a system can then possess up to 2 Gbytes of physical +memory. The virtual address range available to the programmer is not +affected by this convention. + + +Chapter 12 Debugging + + + +The 80386 brings to Intel's line of microprocessors significant advances in +debugging power. The single-step exception and breakpoint exception of +previous processors are still available in the 80386, but the principal +debugging support takes the form of debug registers. The debug registers +support both instruction breakpoints and data breakpoints. Data breakpoints +are an important innovation that can save hours of debugging time by +pinpointing, for example, exactly when a data structure is being +overwritten. The breakpoint registers also eliminate the complexities +associated with writing a breakpoint instruction into a code segment +(requires a data-segment alias for the code segment) or a code segment +shared by multiple tasks (the breakpoint exception can occur in the context +of any of the tasks). Breakpoints can even be set in code contained in ROM. + + +12.1 Debugging Features of the Architecture + +The features of the 80386 architecture that support debugging include: + +Reserved debug interrupt vector + +Permits processor to automatically invoke a debugger task or procedure when +an event occurs that is of interest to the debugger. + +Four debug address registers + +Permit programmers to specify up to four addresses that the CPU will +automatically monitor. + +Debug control register + +Allows programmers to selectively enable various debug conditions +associated with the four debug addresses. + +Debug status register + +Helps debugger identify condition that caused debug exception. + +Trap bit of TSS (T-bit) + +Permits monitoring of task switches. + +Resume flag (RF) of flags register + +Allows an instruction to be restarted after a debug exception without +immediately causing another debug exception due to the same condition. + +Single-step flag (TF) + +Allows complete monitoring of program flow by specifying whether the CPU +should cause a debug exception with the execution of every instruction. + +Breakpoint instruction + +Permits debugger intervention at any point in program execution and aids +debugging of debugger programs. + +Reserved interrupt vector for breakpoint exception + +Permits processor to automatically invoke a handler task or procedure upon +encountering a breakpoint instruction. + +These features make it possible to invoke a debugger that is either a +separate task or a procedure in the context of the current task. The +debugger can be invoked under any of the following kinds of conditions: + + Task switch to a specific task. + Execution of the breakpoint instruction. + Execution of every instruction. + Execution of any instruction at a given address. + Read or write of a byte, word, or doubleword at any specified address. + Write to a byte, word, or doubleword at any specified address. + Attempt to change a debug register. + + +12.2 Debug Registers + +Six 80386 registers are used to control debug features. These registers are +accessed by variants of the MOV instruction. A debug register may be either +the source operand or destination operand. The debug registers are +privileged resources; the MOV instructions that access them can only be +executed at privilege level zero. An attempt to read or write the debug +registers when executing at any other privilege level causes a general +protection exception. Figure 12-1 shows the format of the debug registers. + + +Figure 12-1. Debug Registers + + 31 23 15 7 0 + ͻ + LENR/WLENR/WLENR/WLENR/W GLGLGLGLGL + 0 000 0 0 DR7 + 3 3 2 2 1 1 0 0 EE33221100 + Ķ + BBB BBBB + 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 DR6 + TSD 3210 + Ķ + + RESERVED DR5 + + Ķ + + RESERVED DR4 + + Ķ + + BREAKPOINT 3 LINEAR ADDRESS DR3 + + Ķ + + BREAKPOINT 2 LINEAR ADDRESS DR2 + + Ķ + + BREAKPOINT 1 LINEAR ADDRESS DR1 + + Ķ + + BREAKPOINT 0 LINEAR ADDRESS DR0 + + ͼ + + +NOTE + 0 MEANS INTEL RESERVED. DO NOT DEFINE. + + + +12.2.1 Debug Address Registers (DR0-DR3) + +Each of these registers contains the linear address associated with one of +four breakpoint conditions. Each breakpoint condition is further defined by +bits in DR7. + +The debug address registers are effective whether or not paging is enabled. +The addresses in these registers are linear addresses. If paging is enabled, +the linear addresses are translated into physical addresses by the +processor's paging mechanism (as explained in Chapter 5). If paging is not +enabled, these linear addresses are the same as physical addresses. + +Note that when paging is enabled, different tasks may have different +linear-to-physical address mappings. When this is the case, an address in a +debug address register may be relevant to one task but not to another. For +this reason the 80386 has both global and local enable bits in DR7. These +bits indicate whether a given debug address has a global (all tasks) or +local (current task only) relevance. + + +12.2.2 Debug Control Register (DR7) + +The debug control register shown in Figure 12-1 both helps to define the +debug conditions and selectively enables and disables those conditions. + +For each address in registers DR0-DR3, the corresponding fields R/W0 +through R/W3 specify the type of action that should cause a breakpoint. The +processor interprets these bits as follows: + + 00 Break on instruction execution only + 01 Break on data writes only + 10 undefined + 11 Break on data reads or writes but not instruction fetches + +Fields LEN0 through LEN3 specify the length of data item to be monitored. A +length of 1, 2, or 4 bytes may be specified. The values of the length fields +are interpreted as follows: + + 00 one-byte length + 01 two-byte length + 10 undefined + 11 four-byte length + +If RWn is 00 (instruction execution), then LENn should also be 00. Any other +length is undefined. + +The low-order eight bits of DR7 (L0 through L3 and G0 through G3) +selectively enable the four address breakpoint conditions. There are two +levels of enabling: the local (L0 through L3) and global (G0 through G3) +levels. The local enable bits are automatically reset by the processor at +every task switch to avoid unwanted breakpoint conditions in the new task. +The global enable bits are not reset by a task switch; therefore, they can +be used for conditions that are global to all tasks. + +The LE and GE bits control the "exact data breakpoint match" feature of the +processor. If either LE or GE is set, the processor slows execution so that +data breakpoints are reported on the instruction that causes them. It is +recommended that one of these bits be set whenever data breakpoints are +armed. The processor clears LE at a task switch but does not clear GE. + + +12.2.3 Debug Status Register (DR6) + +The debug status register shown in Figure 12-1 permits the debugger to +determine which debug conditions have occurred. + +When the processor detects an enabled debug exception, it sets the +low-order bits of this register (B0 thru B3) before entering the debug +exception handler. Bn is set if the condition described by DRn, LENn, and +R/Wn occurs. (Note that the processor sets Bn regardless of whether Gn or +Ln is set. If more than one breakpoint condition occurs at one time and if +the breakpoint trap occurs due to an enabled condition other than n, Bn may +be set, even though neither Gn nor Ln is set.) + +The BT bit is associated with the T-bit (debug trap bit) of the TSS (refer +to 7 for the location of the T-bit). The processor sets the BT bit before +entering the debug handler if a task switch has occurred and the T-bit of +the new TSS is set. There is no corresponding bit in DR7 that enables and +disables this trap; the T-bit of the TSS is the sole enabling bit. + +The BS bit is associated with the TF (trap flag) bit of the EFLAGS +register. The BS bit is set if the debug handler is entered due to the +occurrence of a single-step exception. The single-step trap is the +highest-priority debug exception; therefore, when BS is set, any of the +other debug status bits may also be set. + +The BD bit is set if the next instruction will read or write one of the +eight debug registers and ICE-386 is also using the debug registers at the +same time. + +Note that the bits of DR6 are never cleared by the processor. To avoid any +confusion in identifying the next debug exception, the debug handler should +move zeros to DR6 immediately before returning. + + +12.2.4 Breakpoint Field Recognition + +The linear address and LEN field for each of the four breakpoint conditions +define a range of sequential byte addresses for a data breakpoint. The LEN +field permits specification of a one-, two-, or four-byte field. Two-byte +fields must be aligned on word boundaries (addresses that are multiples of +two) and four-byte fields must be aligned on doubleword boundaries +(addresses that are multiples of four). These requirements are enforced by +the processor; it uses the LEN bits to mask the low-order bits of the +addresses in the debug address registers. Improperly aligned code or data +breakpoint addresses will not yield the expected results. + +A data read or write breakpoint is triggered if any of the bytes +participating in a memory access is within the field defined by a breakpoint +address register and the corresponding LEN field. Table 12-1 gives some +examples of breakpoint fields with memory references that both do and do not +cause traps. + +To set a data breakpoint for a misaligned field longer than one byte, it +may be desirable to put two sets of entries in the breakpoint register such +that each entry is properly aligned and the two entries together span the +length of the field. + +Instruction breakpoint addresses must have a length specification of one +byte (LEN = 00); other values are undefined. The processor recognizes an +instruction breakpoint address only when it points to the first byte of an +instruction. If the instruction has any prefixes, the breakpoint address +must point to the first prefix. + + +Table 12-1. Breakpoint Field Recognition Examples + + Address (hex) Length + + DR0 0A0001 1 (LEN0 = 00) +Register Contents DR1 0A0002 1 (LEN1 = 00) + DR2 0B0002 2 (LEN2 = 01) + DR3 0C0000 4 (LEN3 = 11) + +Some Examples of Memory 0A0001 1 +References That Cause Traps 0A0002 1 + 0A0001 2 + 0A0002 2 + 0B0002 2 + 0B0001 4 + 0C0000 4 + 0C0001 2 + 0C0003 1 + +Some Examples of Memory 0A0000 1 +References That Don't Cause Traps 0A0003 4 + 0B0000 2 + 0C0004 4 + + +12.3 Debug Exceptions + +Two of the interrupt vectors of the 80386 are reserved for exceptions that +relate to debugging. Interrupt 1 is the primary means of invoking debuggers +designed expressly for the 80386; interrupt 3 is intended for debugging +debuggers and for compatibility with prior processors in Intel's 8086 +processor family. + + +12.3.1 Interrupt 1 Debug Exceptions + +The handler for this exception is usually a debugger or part of a debugging +system. The processor causes interrupt 1 for any of several conditions. The +debugger can check flags in DR6 and DR7 to determine what condition caused +the exception and what other conditions might be in effect at the same time. +Table 12-2 associates with each breakpoint condition the combination of +bits that indicate when that condition has caused the debug exception. + +Instruction address breakpoint conditions are faults, while other debug +conditions are traps. The debug exception may report either or both at one +time. The following paragraphs present details for each class of debug +exception. + + +Table 12-2. Debug Exception Conditions + +Flags to Test Condition + +BS=1 Single-step trap +B0=1 AND (GE0=1 OR LE0=1) Breakpoint DR0, LEN0, R/W0 +B1=1 AND (GE1=1 OR LE1=1) Breakpoint DR1, LEN1, R/W1 +B2=1 AND (GE2=1 OR LE2=1) Breakpoint DR2, LEN2, R/W2 +B3=1 AND (GE3=1 OR LE3=1) Breakpoint DR3, LEN3, R/W3 +BD=1 Debug registers not available; in use by ICE-386. +BT=1 Task switch + + +12.3.1.1 Instruction Addrees Breakpoint + +The processor reports an instruction-address breakpoint before it executes +the instruction that begins at the given address; i.e., an instruction- +address breakpoint exception is a fault. + +The RF (restart flag) permits the debug handler to retry instructions that +cause other kinds of faults in addition to debug faults. When it detects a +fault, the processor automatically sets RF in the flags image that it pushes +onto the stack. (It does not, however, set RF for traps and aborts.) + +When RF is set, it causes any debug fault to be ignored during the next +instruction. (Note, however, that RF does not cause breakpoint traps to be +ignored, nor other kinds of faults.) + +The processor automatically clears RF at the successful completion of every +instruction except after the IRET instruction, after the POPF instruction, +and after a JMP, CALL, or INT instruction that causes a task switch. These +instructions set RF to the value specified by the memory image of the EFLAGS +register. + +The processor automatically sets RF in the EFLAGS image on the stack before +entry into any fault handler. Upon entry into the fault handler for +instruction address breakpoints, for example, RF is set in the EFLAGS image +on the stack; therefore, the IRET instruction at the end of the handler will +set RF in the EFLAGS register, and execution will resume at the breakpoint +address without generating another breakpoint fault at the same address. + +If, after a debug fault, RF is set and the debug handler retries the +faulting instruction, it is possible that retrying the instruction will +raise other faults. The retry of the instruction after these faults will +also be done with RF=1, with the result that debug faults continue to be +ignored. The processor clears RF only after successful completion of the +instruction. + +Real-mode debuggers can control the RF flag by using a 32-bit IRET. A +16-bit IRET instruction does not affect the RF bit (which is in the +high-order 16 bits of EFLAGS). To use a 32-bit IRET, the debugger must +rearrange the stack so that it holds appropriate values for the 32-bit EIP, +CS, and EFLAGS (with RF set in the EFLAGS image). Then executing an IRET +with an operand size prefix causes a 32-bit return, popping the RF flag +into EFLAGS. + + +12.3.1.2 Data Address Breakpoint + +A data-address breakpoint exception is a trap; i.e., the processor reports +a data-address breakpoint after executing the instruction that accesses the +given memory item. + +When using data breakpoints it is recommended that either the LE or GE bit +of DR7 be set also. If either LE or GE is set, any data breakpoint trap is +reported exactly after completion of the instruction that accessed the +specified memory item. This exact reporting is accomplished by forcing the +80386 execution unit to wait for completion of data operand transfers before +beginning execution of the next instruction. If neither GE nor LE is set, +data breakpoints may not be reported until one instruction after the data is +accessed or may not be reported at all. This is due to the fact that, +normally, instruction execution is overlapped with memory transfers to such +a degree that execution of the next instruction may begin before memory +transfers for the prior instruction are completed. + +If a debugger needs to preserve the contents of a write breakpoint +location, it should save the original contents before setting a write +breakpoint. Because data breakpoints are traps, a write into a breakpoint +location will complete before the trap condition is reported. The handler +can report the saved value after the breakpoint is triggered. The data in +the debug registers can be used to address the new value stored by the +instruction that triggered the breakpoint. + + +12.3.1.3 General Detect Fault + +This exception occurs when an attempt is made to use the debug registers at +the same time that ICE-386 is using them. This additional protection feature +is provided to guarantee that ICE-386 can have full control over the +debug-register resources when required. ICE-386 uses the debug-registers; +therefore, a software debugger that also uses these registers cannot run +while ICE-386 is in use. The exception handler can detect this condition by +examining the BD bit of DR6. + + +12.3.1.4 Single-Step Trap + +This debug condition occurs at the end of an instruction if the trap flag +(TF) of the flags register held the value one at the beginning of that +instruction. Note that the exception does not occur at the end of an +instruction that sets TF. For example, if POPF is used to set TF, a +single-step trap does not occur until after the instruction that follows +POPF. + +The processor clears the TF bit before invoking the handler. If TF=1 in +the flags image of a TSS at the time of a task switch, the exception occurs +after the first instruction is executed in the new task. + +The single-step flag is normally not cleared by privilege changes inside a +task. INT instructions, however, do clear TF. Therefore, software +debuggers that single-step code must recognize and emulate INT n or INTO +rather than executing them directly. + +To maintain protection, system software should check the current execution +privilege level after any single step interrupt to see whether single +stepping should continue at the current privilege level. + +The interrupt priorities in hardware guarantee that if an external +interrupt occurs, single stepping stops. When both an external interrupt and +a single step interrupt occur together, the single step interrupt is +processed first. This clears the TF bit. After saving the return address or +switching tasks, the external interrupt input is examined before the first +instruction of the single step handler executes. If the external interrupt +is still pending, it is then serviced. The external interrupt handler is not +single-stepped. To single step an interrupt handler, just single step an INT +n instruction that refers to the interrupt handler. + + +12.3.1.5 Task Switch Breakpoint + +The debug exception also occurs after a switch to an 80386 task if the +T-bit of the new TSS is set. The exception occurs after control has passed +to the new task, but before the first instruction of that task is executed. +The exception handler can detect this condition by examining the BT bit of +the debug status register DR6. + +Note that if the debug exception handler is a task, the T-bit of its TSS +should not be set. Failure to observe this rule will cause the processor to +enter an infinite loop. + + +12.3.2 Interrupt 3 Breakpoint Exception + +This exception is caused by execution of the breakpoint instruction INT 3. +Typically, a debugger prepares a breakpoint by substituting the opcode of +the one-byte breakpoint instruction in place of the first opcode byte of the +instruction to be trapped. When execution of the INT 3 instruction causes +the exception handler to be invoked, the saved value of ES:EIP points to the +byte following the INT 3 instruction. + +With prior generations of processors, this feature is used extensively for +trapping execution of specific instructions. With the 80386, the needs +formerly filled by this feature are more conveniently solved via the debug +registers and interrupt 1. However, the breakpoint exception is still +useful for debugging debuggers, because the breakpoint exception can vector +to a different exception handler than that used by the debugger. The +breakpoint exception can also be useful when it is necessary to set a +greater number of breakpoints than permitted by the debug registers. + + + PART III COMPATIBILITY + + +Chapter 13 Executing 80286 Protected-Mode Code + + + +13.1 80286 Code Executes as a Subset of the 80386 + +In general, programs designed for execution in protected mode on an 80286 +execute without modification on the 80386, because the features of the 80286 +are a subset of those of the 80386. + +All the descriptors used by the 80286 are supported by the 80386 as long as +the Intel-reserved word (last word) of the 80286 descriptor is zero. + +The descriptors for data segments, executable segments, local descriptor +tables, and task gates are common to both the 80286 and the 80386. Other +80286 descriptorsTSS segment, call gate, interrupt gate, and trap +gateare supported by the 80386. The 80386 also has new versions of +descriptors for TSS segment, call gate, interrupt gate, and trap gate that +support the 32-bit nature of the 80386. Both sets of descriptors can be +used simultaneously in the same system. + +For those descriptors that are common to both the 80286 and the 80386, the +presence of zeros in the final word causes the 80386 to interpret these +descriptors exactly as 80286 does; for example: + +Base Address The high-order eight bits of the 32-bit base address are + zero, limiting base addresses to 24 bits. + +Limit The high-order four bits of the limit field are zero, + restricting the value of the limit field to 64K. + +Granularity bit The granularity bit is zero, which implies that the value + of the 16-bit limit is interpreted in units of one byte. + +B-bit In a data-segment descriptor, the B-bit is zero, implying + that the segment is no larger than 64 Kbytes. + +D-bit In an executable-segment descriptor, the D-bit is zero, + implying that 16-bit addressing and operands are the + default. + +For formats of these descriptors and documentation of their use refer to +the iAPX 286 Programmer's Reference Manual. + + +13.2 Two ways to Execute 80286 Tasks + +When porting 80286 programs to the 80386, there are two cases to consider: + + 1. Porting an entire 80286 system to the 80386, complete with 80286 + operating system, loader, and system builder. + + In this case, all tasks will have 80286 TSSs. The 80386 is being used + as a faster 286. + + 2. Porting selected 80286 applications to run in an 80386 environment + with an 80386 operating system, loader, and system builder. + + In this case, the TSSs used to represent 80286 tasks should be + changed to 80386 TSSs. It is theoretically possible to mix 80286 and + 80386 TSSs, but the benefits are slight and the problems are great. It + is recommended that all tasks in a 80386 software system have 80386 + TSSs. It is not necessary to change the 80286 object modules + themselves; TSSs are usually constructed by the operating system, by + the loader, or by the system builder. Refer to Chapter 16 for further + discussion of the interface between 16-bit and 32-bit code. + + +13.3 Differences From 80286 + +The few differences that do exist primarily affect operating system code. + + +13.3.1 Wraparound of 80286 24-Bit Physical Address Space + +With the 80286, any base and offset combination that addresses beyond 16M +bytes wraps around to the first megabyte of the 80286 address space. With +the 80386, since it has a greater physical address space, any such address +falls into the 17th megabyte. In the unlikely event that any software +depends on this anomaly, the same effect can be simulated on the 80386 by +using paging to map the first 64K bytes of the 17th megabyte of logical +addresses to physical addresses in the first megabyte. + + +13.3.2 Reserved Word of Descriptor + +Because the 80386 uses the contents of the reserved word (last word) of +every descriptor, 80286 programs that place values in this word may not +execute correctly on the 80386. + + +13.3.3 New Descriptor Type Codes + +Operating-system code that manages space in descriptor tables often uses an +invalid value in the access-rights field of descriptor-table entries to +identify unused entries. Access rights values of 80H and 00H remain invalid +for both the 80286 and 80386. Other values that were invalid on for the +80286 may be valid for the 80386 because of the additional descriptor types +defined by the 80386. + + +13.3.4 Restricted Semantics of LOCK + +The 80286 processor implements the bus lock function differently than the +80386. Programs that use forms of memory locking specific to the 80286 may +not execute properly when transported to a specific application of the +80386. + +The LOCK prefix and its corresponding output signal should only be used to +prevent other bus masters from interrupting a data movement operation. LOCK +may only be used with the following 80386 instructions when they modify +memory. An undefined-opcode exception results from using LOCK before any +other instruction. + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + +A locked instruction is guaranteed to lock only the area of memory defined +by the destination operand, but may lock a larger memory area. For example, +typical 8086 and 80286 configurations lock the entire physical memory space. +With the 80386, the defined area of memory is guaranteed to be locked +against access by a processor executing a locked instruction on exactly the +same memory area, i.e., an operand with identical starting address and +identical length. + + +13.3.5 Additional Exceptions + +The 80386 defines new exceptions that can occur even in systems designed +for the 80286. + + Exception #6 invalid opcode + + This exception can result from improper use of the LOCK instruction. + + Exception #14 page fault + + This exception may occur in an 80286 program if the operating system + enables paging. Paging can be used in a system with 80286 tasks as long + as all tasks use the same page directory. Because there is no place in + an 80286 TSS to store the PDBR, switching to an 80286 task does not + change the value of PDBR. Tasks ported from the 80286 should be given + 80386 TSSs so they can take full advantage of paging. + + +Chapter 14 80386 Real-Address Mode + + + +The real-address mode of the 80386 executes object code designed for +execution on 8086, 8088, 80186, or 80188 processors, or for execution in the +real-address mode of an 80286: + +In effect, the architecture of the 80386 in this mode is almost identical +to that of the 8086, 8088, 80186, and 80188. To a programmer, an 80386 in +real-address mode appears as a high-speed 8086 with extensions to the +instruction set and registers. The principal features of this architecture +are defined in Chapters 2 and 3. + +This chapter discusses certain additional topics that complete the system +programmer's view of the 80386 in real-address mode: + + Address formation. + Extensions to registers and instructions. + Interrupt and exception handling. + Entering and leaving real-address mode. + Real-address-mode exceptions. + Differences from 8086. + Differences from 80286 real-address mode. + + +14.1 Physical Address Formation + +The 80386 provides a one Mbyte + 64 Kbyte memory space for an 8086 program. +Segment relocation is performed as in the 8086: the 16-bit value in a +segment selector is shifted left by four bits to form the base address of a +segment. The effective address is extended with four high order zeros and +added to the base to form a linear address as Figure 14-1 illustrates. (The +linear address is equivalent to the physical address, because paging is not +used in real-address mode.) Unlike the 8086, the resulting linear address +may have up to 21 significant bits. There is a possibility of a carry when +the base address is added to the effective address. On the 8086, the carried +bit is truncated, whereas on the 80386 the carried bit is stored in bit +position 20 of the linear address. + +Unlike the 8086 and 80286, 32-bit effective addresses can be generated (via +the address-size prefix); however, the value of a 32-bit address may not +exceed 65535 without causing an exception. For full compatibility with 80286 +real-address mode, pseudo-protection faults (interrupt 12 or 13 with no +error code) occur if an effective address is generated outside the range 0 +through 65535. + + +Figure 14-1. Real-Address Mode Address Formation + + 19 3 0 + ͻ + BASE 16-BIT SEGMENT SELECTOR 0 0 0 0 + ͼ + + + + 19 15 0 + ͻ + OFFSET 0 0 0 0 16-BIT EFFECTIVE ADDRESS + ͼ + + = + 20 0 + LINEAR ͻ + ADDRESS X X X X X X X X X X X X X X X X X X X X X X + ͼ + + +14.2 Registers and Instructions + +The register set available in real-address mode includes all the registers +defined for the 8086 plus the new registers introduced by the 80386: FS, GS, +debug registers, control registers, and test registers. New instructions +that explicitly operate on the segment registers FS and GS are available, +and the new segment-override prefixes can be used to cause instructions to +utilize FS and GS for address calculations. Instructions can utilize 32-bit +operands through the use of the operand size prefix. + +The instruction codes that cause undefined opcode traps (interrupt 6) +include instructions of the protected mode that manipulate or interrogate +80386 selectors and descriptors; namely, VERR, VERW, LAR, LSL, LTR, STR, +LLDT, and SLDT. Programs executing in real-address mode are able to take +advantage of the new applications-oriented instructions added to the +architecture by the introduction of the 80186/80188, 80286 and 80386: + + New instructions introduced by 80186/80188 and 80286. + + PUSH immediate data + Push all and pop all (PUSHA and POPA) + Multiply immediate data + Shift and rotate by immediate count + String I/O + ENTER and LEAVE + BOUND + + New instructions introduced by 80386. + + LSS, LFS, LGS instructions + Long-displacement conditional jumps + Single-bit instructions + Bit scan + Double-shift instructions + Byte set on condition + Move with sign/zero extension + Generalized multiply + MOV to and from control registers + MOV to and from test registers + MOV to and from debug registers + + +14.3 Interrupt and Exception Handling + +Interrupts and exceptions in 80386 real-address mode work as much as they +do on an 8086. Interrupts and exceptions vector to interrupt procedures via +an interrupt table. The processor multiplies the interrupt or exception +identifier by four to obtain an index into the interrupt table. The entries +of the interrupt table are far pointers to the entry points of interrupt or +exception handler procedures. When an interrupt occurs, the processor +pushes the current values of CS:IP onto the stack, disables interrupts, +clears TF (the single-step flag), then transfers control to the location +specified in the interrupt table. An IRET instruction at the end of the +handler procedure reverses these steps before returning control to the +interrupted procedure. + +The primary difference in the interrupt handling of the 80386 compared to +the 8086 is that the location and size of the interrupt table depend on the +contents of the IDTR (IDT register). Ordinarily, this fact is not apparent +to programmers, because, after RESET, the IDTR contains a base address of 0 +and a limit of 3FFH, which is compatible with the 8086. However, the LIDT +instruction can be used in real-address mode to change the base and limit +values in the IDTR. Refer to Chapter 9 for details on the IDTR, and the +LIDT and SIDT instructions. If an interrupt occurs and the corresponding +entry of the interrupt table is beyond the limit stored in the IDTR, the +processor raises exception 8. + + +14.4 Entering and Leaving Real-Address Mode + +Real-address mode is in effect after a signal on the RESET pin. Even if the +system is going to be used in protected mode, the start-up program will +execute in real-address mode temporarily while initializing for protected +mode. + + +14.4.1 Switching to Protected Mode + +The only way to leave real-address mode is to switch to protected mode. The +processor enters protected mode when a MOV to CR0 instruction sets the PE +(protection enable) bit in CR0. (For compatibility with the 80286, the LMSW +instruction may also be used to set the PE bit.) + +Refer to Chapter 10 "Initialization" for other aspects of switching to +protected mode. + + +14.5 Switching Back to Real-Address Mode + +The processor reenters real-address mode if software clears the PE bit in +CR0 with a MOV to CR0 instruction. A procedure that attempts to do this, +however, should proceed as follows: + + 1. If paging is enabled, perform the following sequence: + + Transfer control to linear addresses that have an identity mapping; + i.e., linear addresses equal physical addresses. + + Clear the PG bit in CR0. + + Move zeros to CR3 to clear out the paging cache. + + 2. Transfer control to a segment that has a limit of 64K (FFFFH). This + loads the CS register with the limit it needs to have in real mode. + + 3. Load segment registers SS, DS, ES, FS, and GS with a selector that + points to a descriptor containing the following values, which are + appropriate to real mode: + + Limit = 64K (FFFFH) + Byte granular (G = 0) + Expand up (E = 0) + Writable (W = 1) + Present (P = 1) + Base = any value + + 4. Disable interrupts. A CLI instruction disables INTR interrupts. NMIs + can be disabled with external circuitry. + + 5. Clear the PE bit. + + 6. Jump to the real mode code to be executed using a far JMP. This + action flushes the instruction queue and puts appropriate values in + the access rights of the CS register. + + 7. Use the LIDT instruction to load the base and limit of the real-mode + interrupt vector table. + + 8. Enable interrupts. + + 9. Load the segment registers as needed by the real-mode code. + + +14.6 Real-Address Mode Exceptions + +The 80386 reports some exceptions differently when executing in +real-address mode than when executing in protected mode. Table 14-1 details +the real-address-mode exceptions. + + +14.7 Differences From 8086 + +In general, the 80386 in real-address mode will correctly execute ROM-based +software designed for the 8086, 8088, 80186, and 80188. Following is a list +of the minor differences between 8086 execution on the 80386 and on an 8086. + + 1. Instruction clock counts. + + The 80386 takes fewer clocks for most instructions than the 8086/8088. + The areas most likely to be affected are: + + Delays required by I/O devices between I/O operations. + + Assumed delays with 8086/8088 operating in parallel with an 8087. + + 2. Divide Exceptions Point to the DIV instruction. + + Divide exceptions on the 80386 always leave the saved CS:IP value + pointing to the instruction that failed. On the 8086/8088, the CS:IP + value points to the next instruction. + + 3. Undefined 8086/8088 opcodes. + + Opcodes that were not defined for the 8086/8088 will cause exception + 6 or will execute one of the new instructions defined for the 80386. + + 4. Value written by PUSH SP. + + The 80386 pushes a different value on the stack for PUSH SP than the + 8086/8088. The 80386 pushes the value of SP before SP is incremented + as part of the push operation; the 8086/8088 pushes the value of SP + after it is incremented. If the value pushed is important, replace + PUSH SP instructions with the following three instructions: + + PUSH BP + MOV BP, SP + XCHG BP, [BP] + + This code functions as the 8086/8088 PUSH SP instruction on the 80386. + + 5. Shift or rotate by more than 31 bits. + + The 80386 masks all shift and rotate counts to the low-order five + bits. This MOD 32 operation limits the count to a maximum of 31 bits, + thereby limiting the time that interrupt response is delayed while + the instruction is executing. + + 6. Redundant prefixes. + + The 80386 sets a limit of 15 bytes on instruction length. The only + way to violate this limit is by putting redundant prefixes before an + instruction. Exception 13 occurs if the limit on instruction length + is violated. The 8086/8088 has no instruction length limit. + + 7. Operand crossing offset 0 or 65,535. + + On the 8086, an attempt to access a memory operand that crosses + offset 65,535 (e.g., MOV a word to offset 65,535) or offset 0 (e.g., + PUSH a word when SP = 1) causes the offset to wrap around modulo + 65,536. The 80386 raises an exception in these casesexception 13 if + the segment is a data segment (i.e., if CS, DS, ES, FS, or GS is being + used to address the segment), exception 12 if the segment is a stack + segment (i.e., if SS is being used). + + 8. Sequential execution across offset 65,535. + + On the 8086, if sequential execution of instructions proceeds past + offset 65,535, the processor fetches the next instruction byte from + offset 0 of the same segment. On the 80386, the processor raises + exception 13 in such a case. + + 9. LOCK is restricted to certain instructions. + + The LOCK prefix and its corresponding output signal should only be + used to prevent other bus masters from interrupting a data movement + operation. The 80386 always asserts the LOCK signal during an XCHG + instruction with memory (even if the LOCK prefix is not used). LOCK + may only be used with the following 80386 instructions when they + update memory: BTS, BTR, BTC, XCHG, ADD, ADC, SUB, SBB, INC, DEC, + AND, OR, XOR, NOT, and NEG. An undefined-opcode exception + (interrupt 6) results from using LOCK before any other instruction. + + 10. Single-stepping external interrupt handlers. + + The priority of the 80386 single-step exception is different from that + of the 8086/8088. The change prevents an external interrupt handler + from being single-stepped if the interrupt occurs while a program is + being single-stepped. The 80386 single-step exception has higher + priority that any external interrupt. The 80386 will still single-step + through an interrupt handler invoked by the INT instructions or by an + exception. + + 11. IDIV exceptions for quotients of 80H or 8000H. + + The 80386 can generate the largest negative number as a quotient for + the IDIV instruction. The 8086/8088 causes exception zero instead. + + 12. Flags in stack. + + The setting of the flags stored by PUSHF, by interrupts, and by + exceptions is different from that stored by the 8086 in bit positions + 12 through 15. On the 8086 these bits are stored as ones, but in + 80386 real-address mode bit 15 is always zero, and bits 14 through 12 + reflect the last value loaded into them. + + 13. NMI interrupting NMI handlers. + + After an NMI is recognized on the 80386, the NMI interrupt is masked + until an IRET instruction is executed. + + 14. Coprocessor errors vector to interrupt 16. + + Any 80386 system with a coprocessor must use interrupt vector 16 for + the coprocessor error exception. If an 8086/8088 system uses another + vector for the 8087 interrupt, both vectors should point to the + coprocessor-error exception handler. + + 15. Numeric exception handlers should allow prefixes. + + On the 80386, the value of CS:IP saved for coprocessor exceptions + points at any prefixes before an ESC instruction. On 8086/8088 + systems, the saved CS:IP points to the ESC instruction. + + 16. Coprocessor does not use interrupt controller. + + The coprocessor error signal to the 80386 does not pass through an + interrupt controller (an 8087 INT signal does). Some instructions in + a coprocessor error handler may need to be deleted if they deal with + the interrupt controller. + + 17. Six new interrupt vectors. + + The 80386 adds six exceptions that arise only if the 8086 program has + a hidden bug. It is recommended that exception handlers be added that + treat these exceptions as invalid operations. This additional + software does not significantly affect the existing 8086 software + because the interrupts do not normally occur. These interrupt + identifiers should not already have been used by the 8086 software, + because they are in the range reserved by Intel. Table 14-2 describes + the new 80386 exceptions. + + 18. One megabyte wraparound. + + The 80386 does not wrap addresses at 1 megabyte in real-address mode. + On members of the 8086 family, it possible to specify addresses + greater than one megabyte. For example, with a selector value 0FFFFH + and an offset of 0FFFFH, the effective address would be 10FFEFH (1 + Mbyte + 65519). The 8086, which can form adresses only up to 20 bits + long, truncates the high-order bit, thereby "wrapping" this address + to 0FFEFH. However, the 80386, which can form addresses up to 32 + bits long does not truncate such an address. + + +Table 14-1. 80386 Real-Address Mode Exceptions + + +Description Interrupt Function that Can Return Address + Number Generate the Exception Points to Faulting + Instruction +Divide error 0 DIV, IDIV YES +Debug exceptions 1 All +Some debug exceptions point to the faulting instruction, others to the +next instruction. The exception handler can determine which has occurred by +examining DR6. + + + + + +Breakpoint 3 INT NO +Overflow 4 INTO NO +Bounds check 5 BOUND YES +Invalid opcode 6 Any undefined opcode or LOCK YES + used with wrong instruction +Coprocessor not available 7 ESC or WAIT YES +Interrupt table limit too small 8 INT vector is not within IDTR YES + limit +Reserved 9-12 +Stack fault 12 Memory operand crosses offset YES + 0 or 0FFFFH +Pseudo-protection exception 13 Memory operand crosses offset YES + 0FFFFH or attempt to execute + past offset 0FFFFH or + instruction longer than 15 + bytes +Reserved 14,15 +Coprocessor error 16 ESC or WAIT YES +Coprocessor errors are reported on the first ESC or WAIT instruction +after the ESC instruction that caused the error. + + + + + +Two-byte SW interrupt 0-255 INT n NO + + +Table 14-2. New 80386 Exceptions + +Interrupt Function +Identifier + + 5 A BOUND instruction was executed with a register value outside + the limit values. + + 6 An undefined opcode was encountered or LOCK was used improperly + before an instruction to which it does not apply. + + 7 The EM bit in the MSW is set when an ESC instruction was + encountered. This exception also occurs on a WAIT instruction + if TS is set. + + 8 An exception or interrupt has vectored to an interrupt table + entry beyond the interrupt table limit in IDTR. This can occur + only if the LIDT instruction has changed the limit from the + default value of 3FFH, which is enough for all 256 interrupt + IDs. + + 12 Operand crosses extremes of stack segment, e.g., MOV operation + at offset 0FFFFH or push with SP=1 during PUSH, CALL, or INT. + + 13 Operand crosses extremes of a segment other than a stack + segment; or sequential instruction execution attempts to + proceed beyond offset 0FFFFH; or an instruction is longer than + 15 bytes (including prefixes). + + +14.8 Differences From 80286 Real-Address Mode + +The few differences that exist between 80386 real-address mode and 80286 +real-address mode are not likely to affect any existing 80286 programs +except possibly the system initialization procedures. + + +14.8.1 Bus Lock + +The 80286 processor implements the bus lock function differently than the +80386. Programs that use forms of memory locking specific to the 80286 may +not execute properly if transported to a specific application of the 80386. + +The LOCK prefix and its corresponding output signal should only be used to +prevent other bus masters from interrupting a data movement operation. LOCK +may only be used with the following 80386 instructions when they modify +memory. An undefined-opcode exception results from using LOCK before any +other instruction. + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + +A locked instruction is guaranteed to lock only the area of memory defined +by the destination operand, but may lock a larger memory area. For example, +typical 8086 and 80286 configurations lock the entire physical memory space. +With the 80386, the defined area of memory is guranteed to be locked against +access by a processor executing a locked instruction on exactly the same +memory area, i.e., an operand with identical starting address and identical +length. + + +14.8.2 Location of First Instruction + +The starting location is 0FFFFFFF0H (sixteen bytes from end of 32-bit +address space) on the 80386 rather than 0FFFFF0H (sixteen bytes from end of +24-bit address space) as on the 80286. Many 80286 ROM initialization +programs will work correctly in this new environment. Others can be made to +work correctly with external hardware that redefines the signals on +A{31-20}. + + +14.8.3 Initial Values of General Registers + +On the 80386, certain general registers may contain different values after +RESET than on the 80286. This should not cause compatibility problems, +because the content of 8086 registers after RESET is undefined. If +self-test is requested during the reset sequence and errors are detected in +the 80386 unit, EAX will contain a nonzero value. EDX contains the component +and revision identifier. Refer to Chapter 10 for more information. + + +14.8.4 MSW Initialization + +The 80286 initializes the MSW register to FFF0H, but the 80386 initializes +this register to 0000H. This difference should have no effect, because the +bits that are different are undefined on the 80286. Programs that read the +value of the MSW will behave differently on the 80386 only if they depend on +the setting of the undefined, high-order bits. + + +Chapter 15 Virtual 8086 Mode + + + +The 80386 supports execution of one or more 8086, 8088, 80186, or 80188 +programs in an 80386 protected-mode environment. An 8086 program runs in +this environment as part of a V86 (virtual 8086) task. V86 tasks take +advantage of the hardware support of multitasking offered by the protected +mode. Not only can there be multiple V86 tasks, each one executing an 8086 +program, but V86 tasks can be multiprogrammed with other 80386 tasks. + +The purpose of a V86 task is to form a "virtual machine" with which to +execute an 8086 program. A complete virtual machine consists not only of +80386 hardware but also of systems software. Thus, the emulation of an 8086 +is the result of cooperation between hardware and software: + + The hardware provides a virtual set of registers (via the TSS), a + virtual memory space (the first megabyte of the linear address space of + the task), and directly executes all instructions that deal with these + registers and with this address space. + + The software controls the external interfaces of the virtual machine + (I/O, interrupts, and exceptions) in a manner consistent with the + larger environment in which it executes. In the case of I/O, software + can choose either to emulate I/O instructions or to let the hardware + execute them directly without software intervention. + +Software that helps implement virtual 8086 machines is called a V86 +monitor. + + +15.1 Executing 8086 Code + +The processor executes in V86 mode when the VM (virtual machine) bit in the +EFLAGS register is set. The processor tests this flag under two general +conditions: + + 1. When loading segment registers to know whether to use 8086-style + address formation. + + 2. When decoding instructions to determine which instructions are + sensitive to IOPL. + +Except for these two modifications to its normal operations, the 80386 in +V86 mode operated much as in protected mode. + + +15.1.1 Registers and Instructions + +The register set available in V86 mode includes all the registers defined +for the 8086 plus the new registers introduced by the 80386: FS, GS, debug +registers, control registers, and test registers. New instructions that +explicitly operate on the segment registers FS and GS are available, and the +new segment-override prefixes can be used to cause instructions to utilize +FS and GS for address calculations. Instructions can utilize 32-bit +operands through the use of the operand size prefix. + +8086 programs running as V86 tasks are able to take advantage of the new +applications-oriented instructions added to the architecture by the +introduction of the 80186/80188, 80286 and 80386: + + New instructions introduced by 80186/80188 and 80286. + PUSH immediate data + Push all and pop all (PUSHA and POPA) + Multiply immediate data + Shift and rotate by immediate count + String I/O + ENTER and LEAVE + BOUND + + New instructions introduced by 80386. + LSS, LFS, LGS instructions + Long-displacement conditional jumps + Single-bit instructions + Bit scan + Double-shift instructions + Byte set on condition + Move with sign/zero extension + Generalized multiply + + +15.1.2 Linear Address Formation + +In V86 mode, the 80386 processor does not interpret 8086 selectors by +referring to descriptors; instead, it forms linear addresses as an 8086 +would. It shifts the selector left by four bits to form a 20-bit base +address. The effective address is extended with four high-order zeros and +added to the base address to create a linear address as Figure 15-1 +illustrates. + +Because of the possibility of a carry, the resulting linear address may +contain up to 21 significant bits. An 8086 program may generate linear +addresses anywhere in the range 0 to 10FFEFH (one megabyte plus +approximately 64 Kbytes) of the task's linear address space. + +V86 tasks generate 32-bit linear addresses. While an 8086 program can only +utilize the low-order 21 bits of a linear address, the linear address can be +mapped via page tables to any 32-bit physical address. + +Unlike the 8086 and 80286, 32-bit effective addresses can be generated (via +the address-size prefix); however, the value of a 32-bit address may not +exceed 65,535 without causing an exception. For full compatibility with +80286 real-address mode, pseudo-protection faults (interrupt 12 or 13 with +no error code) occur if an address is generated outside the range 0 through +65,535. + + +Figure 15-1. V86 Mode Address Formation + + 19 3 0 + ͻ + BASE 16-BIT SEGMENT SELECTOR 0 0 0 0 + ͼ + + + + 19 15 0 + ͻ + OFFSET 0 0 0 0 16-BIT EFFECTIVE ADDRESS + ͼ + + = + 20 0 + LINEAR ͻ + ADDRESS X X X X X X X X X X X X X X X X X X X X X X + ͼ + + +15.2 Structure of a V86 Task + +A V86 task consists partly of the 8086 program to be executed and partly of +80386 "native mode" code that serves as the virtual-machine monitor. The +task must be represented by an 80386 TSS (not an 80286 TSS). The processor +enters V86 mode to execute the 8086 program and returns to protected mode to +execute the monitor or other 80386 tasks. + +To run successfully in V86 mode, an existing 8086 program needs the +following: + + A V86 monitor. + Operating-system services. + +The V86 monitor is 80386 protected-mode code that executes at +privilege-level zero. The monitor consists primarily of initialization and +exception-handling procedures. As for any other 80386 program, +executable-segment descriptors for the monitor must exist in the GDT or in +the task's LDT. The linear addresses above 10FFEFH are available for the +V86 monitor, the operating system, and other systems software. The monitor +may also need data-segment descriptors so that it can examine the interrupt +vector table or other parts of the 8086 program in the first megabyte of the +address space. + +In general, there are two options for implementing the 8086 operating +system: + + 1. The 8086 operating system may run as part of the 8086 code. This + approach is desirable for any of the following reasons: + + The 8086 applications code modifies the operating system. + + There is not sufficient development time to reimplement the 8086 + operating system as 80386 code. + + 2. The 8086 operating system may be implemented or emulated in the V86 + monitor. This approach is desirable for any of the following reasons: + + Operating system functions can be more easily coordinated among + several V86 tasks. + + The functions of the 8086 operating system can be easily emulated + by calls to the 80386 operating system. + +Note that, regardless of the approach chosen for implementing the 8086 +operating system, different V86 tasks may use different 8086 operating +systems. + + +15.2.1 Using Paging for V86 Tasks + +Paging is not necessary for a single V86 task, but paging is useful or +necessary for any of the following reasons: + + To create multiple V86 tasks. Each task must map the lower megabyte of + linear addresses to different physical locations. + + To emulate the megabyte wrap. On members of the 8086 family, it is + possible to specify addresses larger than one megabyte. For example, + with a selector value of 0FFFFH and an offset of 0FFFFH, the effective + address would be 10FFEFH (one megabyte + 65519). The 8086, which can + form addresses only up to 20 bits long, truncates the high-order bit, + thereby "wrapping" this address to 0FFEFH. The 80386, however, which + can form addresses up to 32 bits long does not truncate such an + address. If any 8086 programs depend on this addressing anomaly, the + same effect can be achieved in a V86 task by mapping linear addresses + between 100000H and 110000H and linear addresses between 0 and 10000H + to the same physical addresses. + + To create a virtual address space larger than the physical address + space. + + To share 8086 OS code or ROM code that is common to several 8086 + programs that are executing simultaneously. + + To redirect or trap references to memory-mapped I/O devices. + + +15.2.2 Protection within a V86 Task + +Because it does not refer to descriptors while executing 8086 programs, the +processor also does not utilize the protection mechanisms offered by +descriptors. To protect the systems software that runs in a V86 task from +the 8086 program, software designers may follow either of these approaches: + + Reserve the first megabyte (plus 64 kilobytes) of each task's linear + address space for the 8086 program. An 8086 task cannot generate + addresses outside this range. + + Use the U/S bit of page-table entries to protect the virtual-machine + monitor and other systems software in each virtual 8086 task's space. + When the processor is in V86 mode, CPL is 3. Therefore, an 8086 program + has only user privileges. If the pages of the virtual-machine monitor + have supervisor privilege, they cannot be accessed by the 8086 program. + + +15.3 Entering and Leaving V86 Mode + +Figure 15-2 summarizes the ways that the processor can enter and leave an +8086 program. The processor can enter V86 by either of two means: + + 1. A task switch to an 80386 task loads the image of EFLAGS from the new + TSS. The TSS of the new task must be an 80386 TSS, not an 80286 TSS, + because the 80286 TSS does not store the high-order word of EFLAGS, + which contains the VM flag. A value of one in the VM bit of the new + EFLAGS indicates that the new task is executing 8086 instructions; + therefore, while loading the segment registers from the TSS, the + processor forms base addresses as the 8086 would. + + 2. An IRET from a procedure of an 80386 task loads the image of EFLAGS + from the stack. A value of one in VM in this case indicates that the + procedure to which control is being returned is an 8086 procedure. The + CPL at the time the IRET is executed must be zero, else the processor + does not change VM. + +The processor leaves V86 mode when an interrupt or exception occurs. There +are two cases: + + 1. The interrupt or exception causes a task switch. A task switch from a + V86 task to any other task loads EFLAGS from the TSS of the new task. + If the new TSS is an 80386 TSS and the VM bit in the EFLAGS image is + zero or if the new TSS is an 80286 TSS, then the processor clears the + VM bit of EFLAGS, loads the segment registers from the new TSS using + 80386-style address formation, and begins executing the instructions + of the new task according to 80386 protected-mode semantics. + + 2. The interrupt or exception vectors to a privilege-level zero + procedure. The processor stores the current setting of EFLAGS on the + stack, then clears the VM bit. The interrupt or exception handler, + therefore, executes as "native" 80386 protected-mode code. If an + interrupt or exception vectors to a conforming segment or to a + privilege level other than three, the processor causes a + general-protection exception; the error code is the selector of the + executable segment to which transfer was attempted. + +Systems software does not manipulate the VM flag directly, but rather +manipulates the image of the EFLAGS register that is stored on the stack or +in the TSS. The V86 monitor sets the VM flag in the EFLAGS image on the +stack or in the TSS when first creating a V86 task. Exception and interrupt +handlers can examine the VM flag on the stack. If the interrupted procedure +was executing in V86 mode, the handler may need to invoke the V86 monitor. + + +Figure 15-2. Entering and Leaving the 8086 Program + + MODE TRANSITION DIAGRAM + + ͻ + TASK SWITCH INITIAL + Ķ ENTRY + OR IRET ͼ + +  + ͻ INTERRUPT, EXCEPTION ͻ + 8086 PROGRAM  V86 MONITOR + (V86 MODE) Ķ (PROTECTED + ͼ IRET MODE) +  ͼ +  + + + TASK SWITCH ͻ TASK SWITCH +  OTHER 80386 TASKS  + Ķ (PROTECTED MODE) + TASK SWITCH ͼ TASK SWITCH + + +15.3.1 Transitions Through Task Switches + +A task switch to or from a V86 task may be due to any of three causes: + + 1. An interrupt that vectors to a task gate. + 2. An action of the scheduler of the 80386 operating system. + 3. An IRET when the NT flag is set. + +In any of these cases, the processor changes the VM bit in EFLAGS according +to the image of EFLAGS in the new TSS. If the new TSS is an 80286 TSS, the +high-order word of EFLAGS is not in the TSS; the processor clears VM in this +case. The processor updates VM prior to loading the segment registers from +the images in the new TSS. The new setting of VM determines whether the +processor interprets the new segment-register images as 8086 selectors or +80386/80286 selectors. + + +15.3.2 Transitions Through Trap Gates and Interrupt Gates + +The processor leaves V86 mode as the result of an exception or interrupt +that vectors via a trap or interrupt gate to a privilege-level zero +procedure. The exception or interrupt handler returns to the 8086 code by +executing an IRET. + +Because it was designed for execution by an 8086 processor, an 8086 program +in a V86 task will have an 8086-style interrupt table starting at linear +address zero. However, the 80386 does not use this table directly. For all +exceptions and interrupts that occur in V86 mode, the processor vectors +through the IDT. The IDT entry for an interrupt or exception that occurs in +a V86 task must contain either: + + A task gate. + + An 80386 trap gate (type 14) or an 80386 interrupt gate (type 15), + which must point to a nonconforming, privilege-level zero, code + segment. + +Interrupts and exceptions that have 80386 trap or interrupt gates in the +IDT vector to the appropriate handler procedure at privilege-level zero. The +contents of all the 8086 segment registers are stored on the PL 0 stack. +Figure 15-3 shows the format of the PL 0 stack after an exception or +interrupt that occurs while a V86 task is executing an 8086 program. + +After the processor stores all the 8086 segment registers on the PL 0 +stack, it loads all the segment registers with zeros before starting to +execute the handler procedure. This permits the interrupt handler to safely +save and restore the DS, ES, FS, and GS registers as 80386 selectors. +Interrupt handlers that may be invoked in the context of either a regular +task or a V86 task, can use the same prolog and epilog code for register +saving regardless of the kind of task. Restoring zeros to these registers +before execution of the IRET does not cause a trap in the interrupt handler. +Interrupt procedures that expect values in the segment registers or that +return values via segment registers have to use the register images stored +on the PL 0 stack. Interrupt handlers that need to know whether the +interrupt occurred in V86 mode can examine the VM bit in the stored EFLAGS +image. + +An interrupt handler passes control to the V86 monitor if the VM bit is set +in the EFLAGS image stored on the stack and the interrupt or exception is +one that the monitor needs to handle. The V86 monitor may either: + + Handle the interrupt completely within the V86 monitor. + Invoke the 8086 program's interrupt handler. + +Reflecting an interrupt or exception back to the 8086 code involves the +following steps: + + 1. Refer to the 8086 interrupt vector to locate the appropriate handler + procedure. + + 2. Store the state of the 8086 program on the privilege-level three + stack. + + 3. Change the return link on the privilege-level zero stack to point to + the privilege-level three handler procedure. + + 4. Execute an IRET so as to pass control to the handler. + + 5. When the IRET by the privilege-level three handler again traps to the + V86 monitor, restore the return link on the privilege-level zero stack + to point to the originally interrupted, privilege-level three + procedure. + + 6. Execute an IRET so as to pass control back to the interrupted + procedure. + + +Figure 15-3. PL 0 Stack after Interrupt in V86 Task + + + WITHOUT ERROR CODE WITH ERROR CODE + 31 0 31 0 + ͻĿ ͻĿ + OLD GS OLD GS + ͹ SS:ESP ͹ SS:ESP + D O OLD FS FROM TSS OLD FS FROM TSS + I F ͹ ͹ + R OLD DS OLD DS + E E ͹ ͹ + C X OLD ES OLD ES + T P ͹ ͹ + I A OLD SS OLD SS + O N ͹ ͹ + N S OLD ESP OLD ESP + I ͹ ͹ + O OLD EFLAGS OLD EFLAGS + N ͹ ͹ + OLD CS NEW OLD CS +  ͹ SS:EIP ͹ + OLD EIP OLD EIP NEW + ͹ ͹ SS:EIP + ERROR CODE +   ͹ +   +     + + +15.4 Additional Sensitive Instructions + +When the 80386 is executing in V86 mode, the instructions PUSHF, POPF, +INT n, and IRET are sensitive to IOPL. The instructions IN, INS, OUT, and +OUTS, which are ordinarily sensitive in protected mode, are not sensitive +in V86 mode. Following is a complete list of instructions that are sensitive +in V86 mode: + + CLI Clear Interrupt-Enable Flag + STI Set Interrupt-Enable Flag + LOCK Assert Bus-Lock Signal + PUSHF Push Flags + POPF Pop Flags + INT n Software Interrupt + RET Interrupt Return + +CPL is always three in V86 mode; therefore, if IOPL < 3, these instructions +will trigger a general-protection exceptions. These instructions are made +sensitive so that their functions can be simulated by the V86 monitor. + + +15.4.1 Emulating 8086 Operating System Calls + +INT n is sensitive so that the V86 monitor can intercept calls to the +8086 OS. Many 8086 operating systems are called by pushing parameters onto +the stack, then executing an INT n instruction. If IOPL < 3, INT n +instructions will be intercepted by the V86 monitor. The V86 monitor can +then emulate the function of the 8086 operating system or reflect the +interrupt back to the 8086 operating system in V86 mode. + + +15.4.2 Virtualizing the Interrupt-Enable Flag + +When the processor is executing 8086 code in a V86 task, the instructions +PUSHF, POPF, and IRET are sensitive to IOPL so that the V86 monitor can +control changes to the interrupt-enable flag (IF). Other instructions that +affect IF (STI and CLI) are IOPL sensitive both in 8086 code and in +80386/80386 code. + +Many 8086 programs that were designed to execute on single-task systems set +and clear IF to control interrupts. However, when these same programs are +executed in a multitasking environment, such control of IF can be +disruptive. If IOPL is less than three, all instructions that change or +interrogate IF will trap to the V86 monitor. The V86 monitor can then +control IF in a manner that both suits the needs of the larger environment +and is transparent to the 8086 program. + + +15.5 Virtual I/O + +Many 8086 programs that were designed to execute on single-task systems use +I/O devices directly. However, when these same programs are executed in a +multitasking environment, such use of devices can be disruptive. The 80386 +provides sufficient flexibility to control I/O in a manner that both suits +the needs of the new environment and is transparent to the 8086 program. +Designers may take any of several possible approaches to controlling I/O: + + Implement or emulate the 8086 operating system as an 80386 program and + require the 8086 application to do I/O via software interrupts to the + operating system, trapping all attempts to do I/O directly. + + Let the 8086 program take complete control of all I/O. + + Selectively trap and emulate references that a task makes to specific + I/O ports. + + Trap or redirect references to memory-mapped I/O addresses. + +The method of controlling I/O depends upon whether I/O ports are I/O mapped +or memory mapped. + + +15.5.1 I/O-Mapped I/O + +I/O-mapped I/O in V86 mode differs from protected mode only in that the +protection mechanism does not consult IOPL when executing the I/O +instructions IN, INS, OUT, OUTS. Only the I/O permission bit map controls +the right for V86 tasks to execute these I/O instructions. + +The I/O permission map traps I/O instructions selectively depending on the +I/O addresses to which they refer. The I/O permission bit map of each V86 +task determines which I/O addresses are trapped for that task. Because each +task may have a different I/O permission bit map, the addresses trapped for +one task may be different from those trapped for others. Refer to Chapter 8 +for more information about the I/O permission map. + + +15.5.2 Memory-Mapped I/O + +In hardware designs that utilize memory-mapped I/O, the paging facilities +of the 80386 can be used to trap or redirect I/O operations. Each task that +executes memory-mapped I/O must have a page (or pages) for the memory-mapped +address space. The V86 monitor may control memory-mapped I/O by any of +these means: + + Assign the memory-mapped page to appropriate physical addresses. + Different tasks may have different physical addresses, thereby + preventing the tasks from interfering with each other. + + Cause a trap to the monitor by forcing a page fault on the + memory-mapped page. Read-only pages trap writes. Not-present pages trap + both reads and writes. + +Intervention for every I/O might be excessive for some kinds of I/O +devices. A page fault can still be used in this case to cause intervention +on the first I/O operation. The monitor can then at least make sure that the +task has exclusive access to the device. Then the monitor can change the +page status to present and read/write, allowing subsequent I/O to proceed at +full speed. + + +15.5.3 Special I/O Buffers + +Buffers of intelligent controllers (for example, a bit-mapped graphics +buffer) can also be virtualized via page mapping. The linear space for the +buffer can be mapped to a different physical space for each virtual 8086 +task. The V86 monitor can then assume responsibility for spooling the data +or assigning the virtual buffer to the real buffer at appropriate times. + + +15.6 Differences From 8086 + +In general, V86 mode will correctly execute software designed for the 8086, +8088, 80186, and 80188. Following is a list of the minor differences between +8086 execution on the 80386 and on an 8086. + + 1. Instruction clock counts. + + The 80386 takes fewer clocks for most instructions than the + 8086/8088. The areas most likely to be affected are: + + Delays required by I/O devices between I/O operations. + + Assumed delays with 8086/8088 operating in parallel with an 8087. + + 2. Divide exceptions point to the DIV instruction. + + Divide exceptions on the 80386 always leave the saved CS:IP value + pointing to the instruction that failed. On the 8086/8088, the CS:IP + value points to the next instruction. + + 3. Undefined 8086/8088 opcodes. + + Opcodes that were not defined for the 8086/8088 will cause exception + 6 or will execute one of the new instructions defined for the 80386. + + 4. Value written by PUSH SP. + + The 80386 pushes a different value on the stack for PUSH SP than the + 8086/8088. The 80386 pushes the value of SP before SP is incremented + as part of the push operation; the 8086/8088 pushes the value of SP + after it is incremented. If the value pushed is important, replace + PUSH SP instructions with the following three instructions: + + PUSH BP + MOV BP, SP + XCHG BP, [BP] + + This code functions as the 8086/8088 PUSH SP instruction on the + 80386. + + 5. Shift or rotate by more than 31 bits. + + The 80386 masks all shift and rotate counts to the low-order five + bits. This MOD 32 operation limits the count to a maximum of 31 bits, + thereby limiting the time that interrupt response is delayed while + the instruction is executing. + + 6. Redundant prefixes. + + The 80386 sets a limit of 15 bytes on instruction length. The only + way to violate this limit is by putting redundant prefixes before an + instruction. Exception 13 occurs if the limit on instruction length + is violated. The 8086/8088 has no instruction length limit. + + 7. Operand crossing offset 0 or 65,535. + + On the 8086, an attempt to access a memory operand that crosses + offset 65,535 (e.g., MOV a word to offset 65,535) or offset 0 (e.g., + PUSH a word when SP = 1) causes the offset to wrap around modulo + 65,536. The 80386 raises an exception in these casesexception 13 if + the segment is a data segment (i.e., if CS, DS, ES, FS, or GS is + being used to address the segment), exception 12 if the segment is a + stack segment (i.e., if SS is being used). + + 8. Sequential execution across offset 65,535. + + On the 8086, if sequential execution of instructions proceeds past + offset 65,535, the processor fetches the next instruction byte from + offset 0 of the same segment. On the 80386, the processor raises + exception 13 in such a case. + + 9. LOCK is restricted to certain instructions. + + The LOCK prefix and its corresponding output signal should only be + used to prevent other bus masters from interrupting a data movement + operation. The 80386 always asserts the LOCK signal during an XCHG + instruction with memory (even if the LOCK prefix is not used). LOCK + may only be used with the following 80386 instructions when they + update memory: BTS, BTR, BTC, XCHG, ADD, ADC, SUB, SBB, INC, DEC, + AND, OR, XOR, NOT, and NEG. An undefined-opcode exception (interrupt + 6) results from using LOCK before any other instruction. + + 10. Single-stepping external interrupt handlers. + + The priority of the 80386 single-step exception is different from + that of the 8086/8088. The change prevents an external interrupt + handler from being single-stepped if the interrupt occurs while a + program is being single-stepped. The 80386 single-step exception has + higher priority that any external interrupt. The 80386 will still + single-step through an interrupt handler invoked by the INT + instructions or by an exception. + + 11. IDIV exceptions for quotients of 80H or 8000H. + + The 80386 can generate the largest negative number as a quotient for + the IDIV instruction. The 8086/8088 causes exception zero instead. + + 12. Flags in stack. + + The setting of the flags stored by PUSHF, by interrupts, and by + exceptions is different from that stored by the 8086 in bit positions + 12 through 15. On the 8086 these bits are stored as ones, but in V86 + mode bit 15 is always zero, and bits 14 through 12 reflect the last + value loaded into them. + + 13. NMI interrupting NMI handlers. + + After an NMI is recognized on the 80386, the NMI interrupt is masked + until an IRET instruction is executed. + + 14. Coprocessor errors vector to interrupt 16. + + Any 80386 system with a coprocessor must use interrupt vector 16 for + the coprocessor error exception. If an 8086/8088 system uses another + vector for the 8087 interrupt, both vectors should point to the + coprocessor-error exception handler. + + 15. Numeric exception handlers should allow prefixes. + + On the 80386, the value of CS:IP saved for coprocessor exceptions + points at any prefixes before an ESC instruction. On 8086/8088 + systems, the saved CS:IP points to the ESC instruction itself. + + 16. Coprocessor does not use interrupt controller. + + The coprocessor error signal to the 80386 does not pass through an + interrupt controller (an 8087 INT signal does). Some instructions in + a coprocessor error handler may need to be deleted if they deal with + the interrupt controller. + + +15.7 Differences From 80286 Real-Address Mode + +The 80286 processor implements the bus lock function differently than the +80386. This fact may or may not be apparent to 8086 programs, depending on +how the V86 monitor handles the LOCK prefix. LOCKed instructions are +sensitive to IOPL; therefore, software designers can choose to emulate its +function. If, however, 8086 programs are allowed to execute LOCK directly, +programs that use forms of memory locking specific to the 8086 may not +execute properly when transported to a specific application of the 80386. + +The LOCK prefix and its corresponding output signal should only be used to +prevent other bus masters from interrupting a data movement operation. LOCK +may only be used with the following 80386 instructions when they modify +memory. An undefined-opcode exception results from using LOCK before any +other instruction. + + Bit test and change: BTS, BTR, BTC. + Exchange: XCHG. + One-operand arithmetic and logical: INC, DEC, NOT, and NEG. + Two-operand arithmetic and logical: ADD, ADC, SUB, SBB, AND, OR, XOR. + +A locked instruction is guaranteed to lock only the area of memory defined +by the destination operand, but may lock a larger memory area. For example, +typical 8086 and 80286 configurations lock the entire physical memory space. +With the 80386, the defined area of memory is guaranteed to be locked +against access by a processor executing a locked instruction on exactly the +same memory area, i.e., an operand with identical starting address and +identical length. + + +Chapter 16 Mixing 16-Bit and 32 Bit Code + + + +The 80386 running in protected mode is a 32-bit microprocessor, but it is +designed to support 16-bit processing at three levels: + + 1. Executing 8086/80286 16-bit programs efficiently with complete + compatibility. + + 2. Mixing 16-bit modules with 32-bit modules. + + 3. Mixing 16-bit and 32-bit addresses and operands within one module. + +The first level of support for 16-bit programs has already been discussed +in Chapter 13, Chapter 14, and Chapter 15. This chapter shows how 16-bit +and 32-bit modules can cooperate with one another, and how one module can +utilize both 16-bit and 32-bit operands and addressing. + +The 80386 functions most efficiently when it is possible to distinguish +between pure 16-bit modules and pure 32-bit modules. A pure 16-bit module +has these characteristics: + + All segments occupy 64 Kilobytes or less. + Data items are either 8 bits or 16 bits wide. + Pointers to code and data have 16-bit offsets. + Control is transferred only among 16-bit segments. + +A pure 32-bit module has these characteristics: + + Segments may occupy more than 64 Kilobytes (zero bytes to 4 + gigabytes). + + Data items are either 8 bits or 32 bits wide. + + Pointers to code and data have 32-bit offsets. + + Control is transferred only among 32-bit segments. + +Pure 16-bit modules do exist; they are the modules designed for 16-bit +microprocessors. Pure 32-bit modules may exist in new programs designed +explicitly for the 80386. However, as systems designers move applications +from 16-bit processors to the 32-bit 80386, it will not always be possible +to maintain these ideals of pure 16-bit or 32-bit modules. It may be +expedient to execute old 16-bit modules in a new 32-bit environment without +making source-code changes to the old modules if any of the following +conditions is true: + + Modules will be converted one-by-one from 16-bit environments to + 32-bit environments. + + Older, 16-bit compilers and software-development tools will be + utilized in the new32-bit operating environment until new 32-bit + versions can be created. + + The source code of 16-bit modules is not available for modification. + + The specific data structures used by a given module inherently utilize + 16-bit words. + + The native word size of the source language is 16 bits. + +On the 80386, 16-bit modules can be mixed with 32-bit modules. To design a +system that mixes 16- and 32-bit code requires an understanding of the +mechanisms that the 80386 uses to invoke and control its 32-bit and 16-bit +features. + + +16.1 How the 80386 Implements 16-Bit and 32-Bit Features + +The features of the architecture that permit the 80386 to work equally well +with 32-bit and 16-bit address and operand sizes include: + + The D-bit (default bit) of code-segment descriptors, which determines + the default choice of operand-size and address-size for the + instructions of a code segment. (In real-address mode and V86 mode, + which do not use descriptors, the default is 16 bits.) A code segment + whose D-bit is set is known as a USE32 segment; a code segment whose + D-bit is zero is a USE16 segment. The D-bit eliminates the need to + encode the operand size and address size in instructions when all + instructions use operands and effective addresses of the same size. + + Instruction prefixes that explicitly override the default choice of + operand size and address size (available in protected mode as well as + in real-address mode and V86 mode). + + Separate 32-bit and 16-bit gates for intersegment control transfers + (including call gates, interrupt gates, and trap gates). The operand + size for the control transfer is determined by the type of gate, not by + the D-bit or prefix of the transfer instruction. + + Registers that can be used both for 32-bit and 16-bit operands and + effective-address calculations. + + The B-bit (big bit) of data-segment descriptors, which determines the + size of stack pointer (32-bit ESP or 16-bit SP) used by the CPU for + implicit stack references. + + +16.2 Mixing 32-Bit and 16-Bit Operations + +The 80386 has two instruction prefixes that allow mixing of 32-bit and +16-bit operations within one segment: + + The operand-size prefix (66H) + The address-size prefix (67H) + +These prefixes reverse the default size selected by the D-bit. For example, +the processor can interpret the word-move instruction MOV mem, reg in any of +four ways: + + In a USE32 segment: + + 1. Normally moves 32 bits from a 32-bit register to a 32-bit + effective address in memory. + + 2. If preceded by an operand-size prefix, moves 16 bits from a 16-bit + register to 32-bit effective address in memory. + + 3. If preceded by an address-size prefix, moves 32 bits from a 32-bit + register to a16-bit effective address in memory. + + 4. If preceded by both an address-size prefix and an operand-size + prefix, moves 16 bits from a 16-bit register to a 16-bit effective + address in memory. + + In a USE16 segment: + + 1. Normally moves 16 bits from a 16-bit register to a 16-bit + effective address in memory. + + 2. If preceded by an operand-size prefix, moves 32 bits from a 32-bit + register to 16-bit effective address in memory. + + 3. If preceded by an address-size prefix, moves 16 bits from a 16-bit + register to a32-bit effective address in memory. + + 4. If preceded by both an address-size prefix and an operand-size + prefix, moves 32 bits from a 32-bit register to a 32-bit effective + address in memory. + +These examples illustrate that any instruction can generate any combination +of operand size and address size regardless of whether the instruction is in +a USE16 or USE32 segment. The choice of the USE16 or USE32 attribute for a +code segment is based upon these criteria: + + 1. The need to address instructions or data in segments that are larger + than 64 Kilobytes. + + 2. The predominant size of operands. + + 3. The addressing modes desired. (Refer to Chapter 17 for an explanation + of the additional addressing modes that are available when 32-bit + addressing is used.) + +Choosing a setting of the D-bit that is contrary to the predominant size of +operands requires the generation of an excessive number of operand-size +prefixes. + + +16.3 Sharing Data Segments Among Mixed Code Segments + +Because the choice of operand size and address size is defined in code +segments and their descriptors, data segments can be shared freely among +both USE16 and USE32 code segments. The only limitation is the one imposed +by pointers with 16-bit offsets, which can only point to the first 64 +Kilobytes of a segment. When a data segment that contains more than 64 +Kilobytes is to be shared among USE32 and USE16 segments, the data that is +to be accessed by the USE16 segments must be located within the first 64 +Kilobytes. + +A stack that spans addresses less than 64K can be shared by both USE16 and +USE32 code segments. This class of stacks includes: + + Stacks in expand-up segments with G=0 and B=0. + + Stacks in expand-down segments with G=0 and B=0. + + Stacks in expand-up segments with G=1 and B=0, in which the stack is + contained completely within the lower 64 Kilobytes. (Offsets greater + than 64K can be used for data, other than the stack, that is not + shared.) + +The B-bit of a stack segment cannot, in general, be used to change the size +of stack used by a USE16 code segment. The size of stack pointer used by the +processor for implicit stack references is controlled by the B-bit of the +data-segment descriptor for the stack. Implicit references are those caused +by interrupts, exceptions, and instructions such as PUSH, POP, CALL, and +RET. One might be tempted, therefore, to try to increase beyond 64K the +size of the stack used by 16-bit code simply by supplying a larger stack +segment with the B-bit set. However, the B-bit does not control explicit +stack references, such as accesses to parameters or local variables. A USE16 +code segment can utilize a "big" stack only if the code is modified so that +all explicit references to the stack are preceded by the address-size +prefix, causing those references to use 32-bit addressing. + +In big, expand-down segments (B=1, G=1, and E=1), all offsets are greater +than 64K, therefore USE16 code cannot utilize such a stack segment unless +the code segment is modified to employ 32-bit addressing. (Refer to Chapter +6 for a review of the B, G, and E bits.) + + +16.4 Transferring Control Among Mixed Code Segments + +When transferring control among procedures in USE16 and USE32 code +segments, programmers must be aware of three points: + + Addressing limitations imposed by pointers with 16-bit offsets. + + Matching of operand-size attribute in effect for the CALL/RET pair and + theInterrupt/IRET pair so as to manage the stack correctly. + + Translation of parameters, especially pointer parameters. + +Clearly, 16-bit effective addresses cannot be used to address data or code +located beyond 64K in a 32-bit segment, nor can large 32-bit parameters be +squeezed into a 16-bit word; however, except for these obvious limits, most +interfacing problems between 16-bit and 32-bit modules can be solved. Some +solutions involve inserting interface procedures between the procedures in +question. + + +16.4.1 Size of Code-Segment Pointer + +For control-transfer instructions that use a pointer to identify the next +instruction (i.e., those that do not use gates), the size of the offset +portion of the pointer is determined by the operand-size attribute. The +implications of the use of two different sizes of code-segment pointer are: + + JMP, CALL, or RET from 32-bit segment to 16-bit segment is always + possible using a 32-bit operand size. + + JMP, CALL, or RET from 16-bit segment using a 16-bit operand size + cannot address the target in a 32-bit segment if the address of the + target is greater than 64K. + +An interface procedure can enable transfers from USE16 segments to 32-bit +addresses beyond 64K without requiring modifications any more extensive than +relinking or rebinding the old programs. The requirements for such an +interface procedure are discussed later in this chapter. + + +16.4.2 Stack Management for Control Transfers + +Because stack management is different for 16-bit CALL/RET than for 32-bit +CALL/RET, the operand size of RET must match that of CALL. (Refer to Figure +16-1.) A 16-bit CALL pushes the 16-bit IP and (for calls between privilege +levels) the 16-bit SP register. The corresponding RET must also use a 16-bit +operand size to POP these 16-bit values from the stack into the 16-bit +registers. A 32-bit CALL pushes the 32-bit EIP and (for interlevel calls) +the 32-bit ESP register. The corresponding RET must also use a 32-bit +operand size to POP these 32-bit values from the stack into the 32-bit +registers. If the two halves of a CALL/RET pair do not have matching operand +sizes, the stack will not be managed correctly and the values of the +instruction pointer and stack pointer will not be restored to correct +values. + +When the CALL and its corresponding RET are in segments that have D-bits +with the same values (i.e., both have 32-bit defaults or both have 16-bit +defaults), there is no problem. When the CALL and its corresponding RET are +in segments that have different D-bit values, however, programmers (or +program development software) must ensure that the CALL and RET match. + +There are three ways to cause a 16-bit procedure to execute a 32-bit call: + + 1. Use a 16-bit call to a 32-bit interface procedure that then uses a + 32-bit call to invoke the intended target. + + 2. Bind the 16-bit call to a 32-bit call gate. + + 3. Modify the 16-bit procedure, inserting an operand-size prefix before + the call, thereby changing it to a 32-bit call. + +Likewise, there are three ways to cause a 32-bit procedure to execute a +16-bit call: + + 1. Use a 32-bit call to a 32-bit interface procedure that then uses a + 16-bit call to invoke the intended target. + + 2. Bind the 32-bit call to a 16-bit call gate. + + 3. Modify the 32-bit procedure, inserting an operand-size prefix before + the call, thereby changing it to a 16-bit call. (Be certain that the + return offset does not exceed 64K.) + +Programmers can utilize any of the preceding methods to make a CALL in a +USE16 segment match the corresponding RET in a USE32 segment, or to make a +CALL in a USE32 segment match the corresponding RET in a USE16 segment. + + +Figure 16-1. Stack after Far 16-Bit and 32-Bit Calls + + WITHOUT PRIVILEGE TRANSITION + + AFTER 16-BIT CALL AFTER 32-BIT CALL + + 31 0 31 0 + D O + I F ͹ ͹ + R + E E ͹ ͹ + C X PARM2 PARM1 PARM2 + T P ͹ ͹ + I A CS IP SP PARM1 + O N ͹ ͹ + N S CS + I ͹ ͹ + O EIP ESP + N ͹ ͹ + +      + + WITH PRIVILEGE TRANSITION + + AFTER 16-BIT CALL AFTER 32-BIT CALL + + D O 31 0 31 0 + I F ͻ ͻ + R SS SP SS + E E ͹ ͹ + C X PARM2 PARM1 ESP + T P ͹ ͹ + I A CS IP SP PARM2 + O N ͹ ͹ + N S PARM1 + I ͹ ͹ + O CS + N ͹ ͹ + EIP ESP +  ͹ ͹ + +     + + +16.4.2.1 Controlling the Operand-Size for a Call + +When the selector of the pointer referenced by a CALL instruction selects a +segment descriptor, the operand-size attribute in effect for the CALL +instruction is determined by the D-bit in the segment descriptor and by any +operand-size instruction prefix. + +When the selector of the pointer referenced by a CALL instruction selects a +gate descriptor, the type of call is determined by the type of call gate. A +call via an 80286 call gate (descriptor type 4) always has a 16-bit +operand-size attribute; a call via an 80386 call gate (descriptor type 12) +always has a 32-bit operand-size attribute. The offset of the target +procedure is taken from the gate descriptor; therefore, even a 16-bit +procedure can call a procedure that is located more than 64 kilobytes from +the base of a 32-bit segment, because a 32-bit call gate contains a 32-bit +target offset. + +An unmodified 16-bit code segment that has run successfully on an 8086 or +real-mode 80286 will always have a D-bit of zero and will not use +operand-size override prefixes; therefore, it will always execute 16-bit +versions of CALL. The only modification needed to make a16-bit procedure +effect a 32-bit call is to relink the call to an 80386 call gate. + + +16.4.2.2 Changing Size of Call + +When adding 32-bit gates to 16-bit procedures, it is important to consider +the number of parameters. The count field of the gate descriptor specifies +the size of the parameter string to copy from the current stack to the stack +of the more privileged procedure. The count field of a 16-bit gate specifies +the number of words to be copied, whereas the count field of a 32-bit gate +specifies the number of doublewords to be copied; therefore, the 16-bit +procedure must use an even number of words as parameters. + + +16.4.3 Interrupt Control Transfers + +With a control transfer due to an interrupt or exception, a gate is always +involved. The operand-size attribute for the interrupt is determined by the +type of IDT gate. + +A 386 interrupt or trap gate (descriptor type 14 or 15) to a 32-bit +interrupt procedure can be used to interrupt either 32-bit or 16-bit +procedures. However, it is not generally feasible to permit an interrupt or +exception to invoke a 16-bit handler procedure when 32-bit code is +executing, because a 16-bit interrupt procedure has a return offset of only +16-bits on its stack. If the 32-bit procedure is executing at an address +greater than 64K, the 16-bit interrupt procedure cannot return correctly. + + +16.4.4 Parameter Translation + +When segment offsets or pointers (which contain segment offsets) are passed +as parameters between 16-bit and 32-bit procedures, some translation is +required. Clearly, if a 32-bit procedure passes a pointer to data located +beyond 64K to a 16-bit procedure, the 16-bit procedure cannot utilize it. +Beyond this natural limitation, an interface procedure can perform any +format conversion between 32-bit and 16-bit pointers that may be needed. + +Parameters passed by value between 32-bit and 16-bit code may also require +translation between 32-bit and 16-bit formats. Such translation requirements +are application dependent. Systems designers should take care to limit the +range of values passed so that such translations are possible. + + +16.4.5 The Interface Procedure + +Interposing an interface procedure between 32-bit and 16-bit procedures can +be the solution to any of several interface requirements: + + Allowing procedures in 16-bit segments to transfer control to + instructions located beyond 64K in 32-bit segments. + + Matching of operand size for CALL/RET. + + Parameter translation. + +Interface procedures between USE32 and USE16 segments can be constructed +with these properties: + + The procedures reside in a code segment whose D-bit is set, indicating + a default operand size of 32-bits. + + All entry points that may be called by 16-bit procedures have offsets + that are actually less than 64K. + + All points to which called 16-bit procedures may return also lie + within 64K. + +The interface procedures do little more than call corresponding procedures +in other segments. There may be two kinds of procedures: + + Those that are called by 16-bit procedures and call 32-bit procedures. + These interface procedures are called by 16-bit CALLs and use the + operand-size prefix before RET instructions to cause a 16-bit RET. + CALLs to 32-bit segments are 32-bit calls (by default, because the + D-bit is set), and the 32-bit code returns with 32-bit RET + instructions. + + Those that are called by 32-bit procedures and call 16-bit procedures. + These interface procedures are called by 32-bit CALL instructions, and + return with 32-bit RET instructions (by default, because the D-bit is + set). CALLs to 16-bit procedures use the operand-size prefix; + procedures in the 16-bit code return with 16-bit RET instructions. + + + PART IV INSTRUCTION SET + + +Chapter 17 80386 Instruction Set + + + +This chapter presents instructions for the 80386 in alphabetical order. For +each instruction, the forms are given for each operand combination, +including object code produced, operands required, execution time, and a +description. For each instruction, there is an operational description and a +summary of exceptions generated. + + +17.1 Operand-Size and Address-Size Attributes + +When executing an instruction, the 80386 can address memory using either 16 +or 32-bit addresses. Consequently, each instruction that uses memory +addresses has associated with it an address-size attribute of either 16 or +32 bits. 16-bit addresses imply both the use of a 16-bit displacement in +the instruction and the generation of a 16-bit address offset (segment +relative address) as the result of the effective address calculation. +32-bit addresses imply the use of a 32-bit displacement and the generation +of a 32-bit address offset. Similarly, an instruction that accesses words +(16 bits) or doublewords (32 bits) has an operand-size attribute of either +16 or 32 bits. + +The attributes are determined by a combination of defaults, instruction +prefixes, and (for programs executing in protected mode) size-specification +bits in segment descriptors. + + +17.1.1 Default Segment Attribute + +For programs executed in protected mode, the D-bit in executable-segment +descriptors determines the default attribute for both address size and +operand size. These default attributes apply to the execution of all +instructions in the segment. A value of zero in the D-bit sets the default +address size and operand size to 16 bits; a value of one, to 32 bits. + +Programs that execute in real mode or virtual-8086 mode have 16-bit +addresses and operands by default. + + +17.1.2 Operand-Size and Address-Size Instruction Prefixes + +The internal encoding of an instruction can include two byte-long prefixes: +the address-size prefix, 67H, and the operand-size prefix, 66H. (A later +section, "Instruction Format," shows the position of the prefixes in an +instruction's encoding.) These prefixes override the default segment +attributes for the instruction that follows. Table 17-1 shows the effect of +each possible combination of defaults and overrides. + + +17.1.3 Address-Size Attribute for Stack + +Instructions that use the stack implicitly (for example: POP EAX also have +a stack address-size attribute of either 16 or 32 bits. Instructions with a +stack address-size attribute of 16 use the 16-bit SP stack pointer register; +instructions with a stack address-size attribute of 32 bits use the 32-bit +ESP register to form the address of the top of the stack. + +The stack address-size attribute is controlled by the B-bit of the +data-segment descriptor in the SS register. A value of zero in the B-bit +selects a stack address-size attribute of 16; a value of one selects a stack +address-size attribute of 32. + + +Table 17-1. Effective Size Attributes + +Segment Default D = ... 0 0 0 0 1 1 1 1 +Operand-Size Prefix 66H N N Y Y N N Y Y +Address-Size Prefix 67H N Y N Y N Y N Y + +Effective Operand Size 16 16 32 32 32 32 16 16 +Effective Address Size 16 32 16 32 32 16 32 16 + +Y = Yes, this instruction prefix is present +N = No, this instruction prefix is not present + + +17.2 Instruction Format + +All instruction encodings are subsets of the general instruction format +shown in Figure 17-1. Instructions consist of optional instruction +prefixes, one or two primary opcode bytes, possibly an address specifier +consisting of the ModR/M byte and the SIB (Scale Index Base) byte, a +displacement, if required, and an immediate data field, if required. + +Smaller encoding fields can be defined within the primary opcode or +opcodes. These fields define the direction of the operation, the size of the +displacements, the register encoding, or sign extension; encoding fields +vary depending on the class of operation. + +Most instructions that can refer to an operand in memory have an addressing +form byte following the primary opcode byte(s). This byte, called the ModR/M +byte, specifies the address form to be used. Certain encodings of the ModR/M +byte indicate a second addressing byte, the SIB (Scale Index Base) byte, +which follows the ModR/M byte and is required to fully specify the +addressing form. + +Addressing forms can include a displacement immediately following either +the ModR/M or SIB byte. If a displacement is present, it can be 8-, 16- or +32-bits. + +If the instruction specifies an immediate operand, the immediate operand +always follows any displacement bytes. The immediate operand, if specified, +is always the last field of the instruction. + +The following are the allowable instruction prefix codes: + + F3H REP prefix (used only with string instructions) + F3H REPE/REPZ prefix (used only with string instructions + F2H REPNE/REPNZ prefix (used only with string instructions) + F0H LOCK prefix + +The following are the segment override prefixes: + + 2EH CS segment override prefix + 36H SS segment override prefix + 3EH DS segment override prefix + 26H ES segment override prefix + 64H FS segment override prefix + 65H GS segment override prefix + 66H Operand-size override + 67H Address-size override + + +Figure 17-1. 80386 Instruction Format + + ͻ + INSTRUCTION ADDRESS- OPERAND- SEGMENT + PREFIX SIZE PREFIX SIZE PREFIX OVERRIDE + ͹ + 0 OR 1 0 OR 1 0 OR 1 0 OR 1 + Ķ + NUMBER OF BYTES + ͼ + + ͻ + OPCODE MODR/M SIB DISPLACEMENT IMMEDIATE + + ͹ + 1 OR 2 0 OR 1 0 OR 1 0,1,2 OR 4 0,1,2 OR 4 + Ķ + NUMBER OF BYTES + ͼ + + +17.2.1 ModR/M and SIB Bytes + +The ModR/M and SIB bytes follow the opcode byte(s) in many of the 80386 +instructions. They contain the following information: + + The indexing type or register number to be used in the instruction + The register to be used, or more information to select the instruction + The base, index, and scale information + +The ModR/M byte contains three fields of information: + + The mod field, which occupies the two most significant bits of the + byte, combines with the r/m field to form 32 possible values: eight + registers and 24 indexing modes + + The reg field, which occupies the next three bits following the mod + field, specifies either a register number or three more bits of opcode + information. The meaning of the reg field is determined by the first + (opcode) byte of the instruction. + + The r/m field, which occupies the three least significant bits of the + byte, can specify a register as the location of an operand, or can form + part of the addressing-mode encoding in combination with the field as + described above + +The based indexed and scaled indexed forms of 32-bit addressing require the +SIB byte. The presence of the SIB byte is indicated by certain encodings of +the ModR/M byte. The SIB byte then includes the following fields: + + The ss field, which occupies the two most significant bits of the + byte, specifies the scale factor + + The index field, which occupies the next three bits following the ss + field and specifies the register number of the index register + + The base field, which occupies the three least significant bits of the + byte, specifies the register number of the base register + +Figure 17-2 shows the formats of the ModR/M and SIB bytes. + +The values and the corresponding addressing forms of the ModR/M and SIB +bytes are shown in Tables 17-2, 17-3, and 17-4. The 16-bit addressing +forms specified by the ModR/M byte are in Table 17-2. The 32-bit addressing +forms specified by ModR/M are in Table 17-3. Table 17-4 shows the 32-bit +addressing forms specified by the SIB byte + + +Figure 17-2. ModR/M and SIB Byte Formats + + MODR/M BYTE + + 7 6 5 4 3 2 1 0 + ͻ + MOD REG/OPCODE R/M + ͼ + + SIB (SCALE INDEX BASE) BYTE + + 7 6 5 4 3 2 1 0 + ͻ + SS INDEX BASE + ͼ + + +Table 17-2. 16-Bit Addressing Forms with the ModR/M Byte + + +r8(/r) AL CL DL BL AH CH DH BH +r16(/r) AX CX DX BX SP BP SI DI +r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI +/digit (Opcode) 0 1 2 3 4 5 6 7 +REG = 000 001 010 011 100 101 110 111 + + Effective +Address +disp8 denotes an 8-bit displacement following the ModR/M byte, to be +sign-extended and added to the index. disp16 denotes a 16-bit displacement +following the ModR/M byte, to be added to the index. Default segment +register is SS for the effective addresses containing a BP index, DS for +other effective addresses.Ŀ Mod R/M ModR/M Values in HexadecimalĿ + +[BX + SI] 000 00 08 10 18 20 28 30 38 +[BX + DI] 001 01 09 11 19 21 29 31 39 +[BP + SI] 010 02 0A 12 1A 22 2A 32 3A +[BP + DI] 011 03 0B 13 1B 23 2B 33 3B +[SI] 00 100 04 0C 14 1C 24 2C 34 3C +[DI] 101 05 0D 15 1D 25 2D 35 3D +disp16 110 06 0E 16 1E 26 2E 36 3E +[BX] 111 07 0F 17 1F 27 2F 37 3F + +[BX+SI]+disp8 000 40 48 50 58 60 68 70 78 +[BX+DI]+disp8 001 41 49 51 59 61 69 71 79 +[BP+SI]+disp8 010 42 4A 52 5A 62 6A 72 7A +[BP+DI]+disp8 011 43 4B 53 5B 63 6B 73 7B +[SI]+disp8 01 100 44 4C 54 5C 64 6C 74 7C +[DI]+disp8 101 45 4D 55 5D 65 6D 75 7D +[BP]+disp8 110 46 4E 56 5E 66 6E 76 7E +[BX]+disp8 111 47 4F 57 5F 67 6F 77 7F + +[BX+SI]+disp16 000 80 88 90 98 A0 A8 B0 B8 +[BX+DI]+disp16 001 81 89 91 99 A1 A9 B1 B9 +[BX+SI]+disp16 010 82 8A 92 9A A2 AA B2 BA +[BX+DI]+disp16 011 83 8B 93 9B A3 AB B3 BB +[SI]+disp16 10 100 84 8C 94 9C A4 AC B4 BC +[DI]+disp16 101 85 8D 95 9D A5 AD B5 BD +[BP]+disp16 110 86 8E 96 9E A6 AE B6 BE +[BX]+disp16 111 87 8F 97 9F A7 AF B7 BF + +EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 +ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 +EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA +EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB +ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC +EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD +ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE +EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF + + + +NOTES: + disp8 denotes an 8-bit displacement following the ModR/M byte, to be + sign-extended and added to the index. disp16 denotes a 16-bit displacement + following the ModR/M byte, to be added to the index. Default segment + register is SS for the effective addresses containing a BP index, DS for + other effective addresses. + + + +Table 17-3. 32-Bit Addressing Forms with the ModR/M Byte + + +r8(/r) AL CL DL BL AH CH DH BH +r16(/r) AX CX DX BX SP BP SI DI +r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI +/digit (Opcode) 0 1 2 3 4 5 6 7 +REG = 000 001 010 011 100 101 110 111 + + Effective +Address +[--] [--] means a SIB follows the ModR/M byte. disp8 denotes an 8-bit +displacement following the SIB byte, to be sign-extended and added to the +index. disp32 denotes a 32-bit displacement following the ModR/M byte, to +be added to the index.Ŀ Mod R/M ModR/M Values in HexadecimalĿ + +[EAX] 000 00 08 10 18 20 28 30 38 +[ECX] 001 01 09 11 19 21 29 31 39 +[EDX] 010 02 0A 12 1A 22 2A 32 3A +[EBX] 011 03 0B 13 1B 23 2B 33 3B +[--] [--] 00 100 04 0C 14 1C 24 2C 34 3C +disp32 101 05 0D 15 1D 25 2D 35 3D +[ESI] 110 06 0E 16 1E 26 2E 36 3E +[EDI] 111 07 0F 17 1F 27 2F 37 3F + +disp8[EAX] 000 40 48 50 58 60 68 70 78 +disp8[ECX] 001 41 49 51 59 61 69 71 79 +disp8[EDX] 010 42 4A 52 5A 62 6A 72 7A +disp8[EPX]; 011 43 4B 53 5B 63 6B 73 7B +disp8[--] [--] 01 100 44 4C 54 5C 64 6C 74 7C +disp8[ebp] 101 45 4D 55 5D 65 6D 75 7D +disp8[ESI] 110 46 4E 56 5E 66 6E 76 7E +disp8[EDI] 111 47 4F 57 5F 67 6F 77 7F + +disp32[EAX] 000 80 88 90 98 A0 A8 B0 B8 +disp32[ECX] 001 81 89 91 99 A1 A9 B1 B9 +disp32[EDX] 010 82 8A 92 9A A2 AA B2 BA +disp32[EBX] 011 83 8B 93 9B A3 AB B3 BB +disp32[--] [--] 10 100 84 8C 94 9C A4 AC B4 BC +disp32[EBP] 101 85 8D 95 9D A5 AD B5 BD +disp32[ESI] 110 86 8E 96 9E A6 AE B6 BE +disp32[EDI] 111 87 8F 97 9F A7 AF B7 BF + +EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 +ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 +EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA +EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB +ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC +EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD +ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE +EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF + + + +NOTES: + [--] [--] means a SIB follows the ModR/M byte. disp8 denotes an 8-bit + displacement following the SIB byte, to be sign-extended and added to the + index. disp32 denotes a 32-bit displacement following the ModR/M byte, to + be added to the index. + + + +Table 17-4. 32-Bit Addressing Forms with the SIB Byte + + + r32 EAX ECX EDX EBX ESP [*] +[*] means a disp32 with no base if MOD is 00, [ESP] otherwise. This provides +the following addressing modes: + disp32[index] (MOD=00) + disp8[EBP][index] (MOD=01) + disp32[EBP][index] (MOD=10) ESI EDI + Base = 0 1 2 3 4 5 6 7 + Base = 000 001 010 011 100 101 110 111 + +Scaled Index +[*] means a disp32 with no base if MOD is 00, [ESP] otherwise. This provides +the following addressing modes: + disp32[index] (MOD=00) + disp8[EBP][index] (MOD=01) + disp32[EBP][index] (MOD=10)SS Index ModR/M Values in HexadecimalĿ + +[EAX] 000 00 01 02 03 04 05 06 07 +[ECX] 001 08 09 0A 0B 0C 0D 0E 0F +[EDX] 010 10 11 12 13 14 15 16 17 +[EBX] 011 18 19 1A 1B 1C 1D 1E 1F +none 00 100 20 21 22 23 24 25 26 27 +[EBP] 101 28 29 2A 2B 2C 2D 2E 2F +[ESI] 110 30 31 32 33 34 35 36 37 +[EDI] 111 38 39 3A 3B 3C 3D 3E 3F + +[EAX*2] 000 40 41 42 43 44 45 46 47 +[ECX*2] 001 48 49 4A 4B 4C 4D 4E 4F +[ECX*2] 010 50 51 52 53 54 55 56 57 +[EBX*2] 011 58 59 5A 5B 5C 5D 5E 5F +none 01 100 60 61 62 63 64 65 66 67 +[EBP*2] 101 68 69 6A 6B 6C 6D 6E 6F +[ESI*2] 110 70 71 72 73 74 75 76 77 +[EDI*2] 111 78 79 7A 7B 7C 7D 7E 7F + +[EAX*4] 000 80 81 82 83 84 85 86 87 +[ECX*4] 001 88 89 8A 8B 8C 8D 8E 8F +[EDX*4] 010 90 91 92 93 94 95 96 97 +[EBX*4] 011 98 89 9A 9B 9C 9D 9E 9F +none 10 100 A0 A1 A2 A3 A4 A5 A6 A7 +[EBP*4] 101 A8 A9 AA AB AC AD AE AF +[ESI*4] 110 B0 B1 B2 B3 B4 B5 B6 B7 +[EDI*4] 111 B8 B9 BA BB BC BD BE BF + +[EAX*8] 000 C0 C1 C2 C3 C4 C5 C6 C7 +[ECX*8] 001 C8 C9 CA CB CC CD CE CF +[EDX*8] 010 D0 D1 D2 D3 D4 D5 D6 D7 +[EBX*8] 011 D8 D9 DA DB DC DD DE DF +none 11 100 E0 E1 E2 E3 E4 E5 E6 E7 +[EBP*8] 101 E8 E9 EA EB EC ED EE EF +[ESI*8] 110 F0 F1 F2 F3 F4 F5 F6 F7 +[EDI*8] 111 F8 F9 FA FB FC FD FE FF + + + +NOTES: + [*] means a disp32 with no base if MOD is 00, [ESP] otherwise. This + provides the following addressing modes: + disp32[index] (MOD=00) + disp8[EBP][index] (MOD=01) + disp32[EBP][index] (MOD=10) + + + +17.2.2 How to Read the Instruction Set Pages + +The following is an example of the format used for each 80386 instruction +description in this chapter: + +CMC Complement Carry Flag + +Opcode Instruction Clocks Description + +F5 CMC 2 Complement carry flag + +The above table is followed by paragraphs labelled "Operation," +"Description," "Flags Affected," "Protected Mode Exceptions," "Real +Address Mode Exceptions," and, optionally, "Notes." The following sections +explain the notational conventions and abbreviations used in these +paragraphs of the instruction descriptions. + + +17.2.2.1 Opcode + +The "Opcode" column gives the complete object code produced for each form +of the instruction. When possible, the codes are given as hexadecimal bytes, +in the same order in which they appear in memory. Definitions of entries +other than hexadecimal bytes are as follows: + +/digit: (digit is between 0 and 7) indicates that the ModR/M byte of the +instruction uses only the r/m (register or memory) operand. The reg field +contains the digit that provides an extension to the instruction's opcode. + +/r: indicates that the ModR/M byte of the instruction contains both a +register operand and an r/m operand. + +cb, cw, cd, cp: a 1-byte (cb), 2-byte (cw), 4-byte (cd) or 6-byte (cp) +value following the opcode that is used to specify a code offset and +possibly a new value for the code segment register. + +ib, iw, id: a 1-byte (ib), 2-byte (iw), or 4-byte (id) immediate operand to +the instruction that follows the opcode, ModR/M bytes or scale-indexing +bytes. The opcode determines if the operand is a signed value. All words and +doublewords are given with the low-order byte first. + ++rb, +rw, +rd: a register code, from 0 through 7, added to the hexadecimal +byte given at the left of the plus sign to form a single opcode byte. The +codes are + + rb rw rd + AL = 0 AX = 0 EAX = 0 + CL = 1 CX = 1 ECX = 1 + DL = 2 DX = 2 EDX = 2 + BL = 3 BX = 3 EBX = 3 + AH = 4 SP = 4 ESP = 4 + CH = 5 BP = 5 EBP = 5 + DH = 6 SI = 6 ESI = 6 + BH = 7 DI = 7 EDI = 7 + + +17.2.2.2 Instruction + +The "Instruction" column gives the syntax of the instruction statement as +it would appear in an ASM386 program. The following is a list of the symbols +used to represent operands in the instruction statements: + +rel8: a relative address in the range from 128 bytes before the end of the +instruction to 127 bytes after the end of the instruction. + +rel16, rel32: a relative address within the same code segment as the +instruction assembled. rel16 applies to instructions with an operand-size +attribute of 16 bits; rel32 applies to instructions with an operand-size +attribute of 32 bits. + +ptr16:16, ptr16:32: a FAR pointer, typically in a code segment different +from that of the instruction. The notation 16:16 indicates that the value of +the pointer has two parts. The value to the right of the colon is a 16-bit +selector or value destined for the code segment register. The value to the +left corresponds to the offset within the destination segment. ptr16:16 is +used when the instruction's operand-size attribute is 16 bits; ptr16:32 is +used with the 32-bit attribute. + +r8: one of the byte registers AL, CL, DL, BL, AH, CH, DH, or BH. + +r16: one of the word registers AX, CX, DX, BX, SP, BP, SI, or DI. + +r32: one of the doubleword registers EAX, ECX, EDX, EBX, ESP, EBP, ESI, or +EDI. + +imm8: an immediate byte value. imm8 is a signed number between -128 and ++127 inclusive. For instructions in which imm8 is combined with a word or +doubleword operand, the immediate value is sign-extended to form a word or +doubleword. The upper byte of the word is filled with the topmost bit of the +immediate value. + +imm16: an immediate word value used for instructions whose operand-size +attribute is 16 bits. This is a number between -32768 and +32767 inclusive. + +imm32: an immediate doubleword value used for instructions whose +operand-size attribute is 32-bits. It allows the use of a number between ++2147483647 and -2147483648. + +r/m8: a one-byte operand that is either the contents of a byte register +(AL, BL, CL, DL, AH, BH, CH, DH), or a byte from memory. + +r/m16: a word register or memory operand used for instructions whose +operand-size attribute is 16 bits. The word registers are: AX, BX, CX, DX, +SP, BP, SI, DI. The contents of memory are found at the address provided by +the effective address computation. + +r/m32: a doubleword register or memory operand used for instructions whose +operand-size attribute is 32-bits. The doubleword registers are: EAX, EBX, +ECX, EDX, ESP, EBP, ESI, EDI. The contents of memory are found at the +address provided by the effective address computation. + +m8: a memory byte addressed by DS:SI or ES:DI (used only by string +instructions). + +m16: a memory word addressed by DS:SI or ES:DI (used only by string +instructions). + +m32: a memory doubleword addressed by DS:SI or ES:DI (used only by string +instructions). + +m16:16, M16:32: a memory operand containing a far pointer composed of two +numbers. The number to the left of the colon corresponds to the pointer's +segment selector. The number to the right corresponds to its offset. + +m16 & 32, m16 & 16, m32 & 32: a memory operand consisting of data item pairs +whose sizes are indicated on the left and the right side of the ampersand. +All memory addressing modes are allowed. m16 & 16 and m32 & 32 operands are +used by the BOUND instruction to provide an operand containing an upper and +lower bounds for array indices. m16 & 32 is used by LIDT and LGDT to +provide a word with which to load the limit field, and a doubleword with +which to load the base field of the corresponding Global and Interrupt +Descriptor Table Registers. + +moffs8, moffs16, moffs32: (memory offset) a simple memory variable of type +BYTE, WORD, or DWORD used by some variants of the MOV instruction. The +actual address is given by a simple offset relative to the segment base. No +ModR/M byte is used in the instruction. The number shown with moffs +indicates its size, which is determined by the address-size attribute of the +instruction. + +Sreg: a segment register. The segment register bit assignments are ES=0, +CS=1, SS=2, DS=3, FS=4, and GS=5. + + +17.2.2.3 Clocks + +The "Clocks" column gives the number of clock cycles the instruction takes +to execute. The clock count calculations makes the following assumptions: + + The instruction has been prefetched and decoded and is ready for + execution. + + Bus cycles do not require wait states. + + There are no local bus HOLD requests delaying processor access to the + bus. + + No exceptions are detected during instruction execution. + + Memory operands are aligned. + +Clock counts for instructions that have an r/m (register or memory) operand +are separated by a slash. The count to the left is used for a register +operand; the count to the right is used for a memory operand. + +The following symbols are used in the clock count specifications: + + n, which represents a number of repetitions. + + m, which represents the number of components in the next instruction + executed, where the entire displacement (if any) counts as one + component, the entire immediate data (if any) counts as one component, + and every other byte of the instruction and prefix(es) each counts as + one component. + + pm=, a clock count that applies when the instruction executes in + Protected Mode. pm= is not given when the clock counts are the same for + Protected and Real Address Modes. + +When an exception occurs during the execution of an instruction and the +exception handler is in another task, the instruction execution time is +increased by the number of clocks to effect a task switch. This parameter +depends on several factors: + + The type of TSS used to represent the current task (386 TSS or 286 + TSS). + + The type of TSS used to represent the new task. + + Whether the current task is in V86 mode. + + Whether the new task is in V86 mode. + +Table 17-5 summarizes the task switch times for exceptions. + + +Table 17-5. Task Switch Times for Exceptions + + New Task + +Old 386 TSS 286 TSS +Task VM = 0 + +386 VM = 0 309 282 +TSS + +386 VM = 1 314 231 +TSS + +286 307 282 +TSS + + +17.2.2.4 Description + +The "Description" column following the "Clocks" column briefly explains the +various forms of the instruction. The "Operation" and "Description" sections +contain more details of the instruction's operation. + + +17.2.2.5 Operation + +The "Operation" section contains an algorithmic description of the +instruction which uses a notation similar to the Algol or Pascal language. +The algorithms are composed of the following elements: + +Comments are enclosed within the symbol pairs "(*" and "*)". + +Compound statements are enclosed between the keywords of the "if" statement +(IF, THEN, ELSE, FI) or of the "do" statement (DO, OD), or of the "case" +statement (CASE ... OF, ESAC). + +A register name implies the contents of the register. A register name +enclosed in brackets implies the contents of the location whose address is +contained in that register. For example, ES:[DI] indicates the contents of +the location whose ES segment relative address is in register DI. [SI] +indicates the contents of the address contained in register SI relative to +SI's default segment (DS) or overridden segment. + +Brackets also used for memory operands, where they mean that the contents +of the memory location is a segment-relative offset. For example, [SRC] +indicates that the contents of the source operand is a segment-relative +offset. + +A  B; indicates that the value of B is assigned to A. + +The symbols =, <>, , and are relational operators used to compare two +values, meaning equal, not equal, greater or equal, less or equal, +respectively. A relational expression such as A = B is TRUE if the value of +A is equal to B; otherwise it is FALSE. + +The following identifiers are used in the algorithmic descriptions: + + OperandSize represents the operand-size attribute of the instruction, + which is either 16 or 32 bits. AddressSize represents the address-size + attribute, which is either 16 or 32 bits. For example, + + IF instruction = CMPSW + THEN OperandSize  16; + ELSE + IF instruction = CMPSD + THEN OperandSize  32; + FI; + FI; + +indicates that the operand-size attribute depends on the form of the CMPS +instruction used. Refer to the explanation of address-size and operand-size +attributes at the beginning of this chapter for general guidelines on how +these attributes are determined. + + StackAddrSize represents the stack address-size attribute associated + with the instruction, which has a value of 16 or 32 bits, as explained + earlier in the chapter. + + SRC represents the source operand. When there are two operands, SRC is + the one on the right. + + DEST represents the destination operand. When there are two operands, + DEST is the one on the left. + + LeftSRC, RightSRC distinguishes between two operands when both are + source operands. + + eSP represents either the SP register or the ESP register depending on + the setting of the B-bit for the current stack segment. + +The following functions are used in the algorithmic descriptions: + + Truncate to 16 bits(value) reduces the size of the value to fit in 16 + bits by discarding the uppermost bits as needed. + + Addr(operand) returns the effective address of the operand (the result + of the effective address calculation prior to adding the segment base). + + ZeroExtend(value) returns a value zero-extended to the operand-size + attribute of the instruction. For example, if OperandSize = 32, + ZeroExtend of a byte value of -10 converts the byte from F6H to + doubleword with hexadecimal value 000000F6H. If the value passed to + ZeroExtend and the operand-size attribute are the same size, + ZeroExtend returns the value unaltered. + + SignExtend(value) returns a value sign-extended to the operand-size + attribute of the instruction. For example, if OperandSize = 32, + SignExtend of a byte containing the value -10 converts the byte from + F6H to a doubleword with hexadecimal value FFFFFFF6H. If the value + passed to SignExtend and the operand-size attribute are the same size, + SignExtend returns the value unaltered. + + Push(value) pushes a value onto the stack. The number of bytes pushed + is determined by the operand-size attribute of the instruction. The + action of Push is as follows: + + IF StackAddrSize = 16 + THEN + IF OperandSize = 16 + THEN + SP  SP - 2; + SS:[SP]  value; (* 2 bytes assigned starting at + byte address in SP *) + ELSE (* OperandSize = 32 *) + SP  SP - 4; + SS:[SP]  value; (* 4 bytes assigned starting at + byte address in SP *) + FI; + ELSE (* StackAddrSize = 32 *) + IF OperandSize = 16 + THEN + ESP  ESP - 2; + SS:[ESP]  value; (* 2 bytes assigned starting at + byte address in ESP*) + ELSE (* OperandSize = 32 *) + ESP  ESP - 4; + SS:[ESP]  value; (* 4 bytes assigned starting at + byte address in ESP*) + FI; + FI; + + Pop(value) removes the value from the top of the stack and returns it. + The statement EAX  Pop( ); assigns to EAX the 32-bit value that Pop + took from the top of the stack. Pop will return either a word or a + doubleword depending on the operand-size attribute. The action of Pop + is as follows: + + IF StackAddrSize = 16 + THEN + IF OperandSize = 16 + THEN + ret val  SS:[SP]; (* 2-byte value *) + SP  SP + 2; + ELSE (* OperandSize = 32 *) + ret val  SS:[SP]; (* 4-byte value *) + SP  SP + 4; + FI; + ELSE (* StackAddrSize = 32 *) + IF OperandSize = 16 + THEN + ret val  SS:[ESP]; (* 2 bytes value *) + ESP  ESP + 2; + ELSE (* OperandSize = 32 *) + ret val  SS:[ESP]; (* 4 bytes value *) + ESP  ESP + 4; + FI; + FI; + RETURN(ret val); (*returns a word or doubleword*) + + Bit[BitBase, BitOffset] returns the address of a bit within a bit + string, which is a sequence of bits in memory or a register. Bits are + numbered from low-order to high-order within registers and within + memory bytes. In memory, the two bytes of a word are stored with the + low-order byte at the lower address. + + If the base operand is a register, the offset can be in the range 0..31. + This offset addresses a bit within the indicated register. An example, + "BIT[EAX, 21]," is illustrated in Figure 17-3. + + If BitBase is a memory address, BitOffset can range from -2 gigabits to 2 + gigabits. The addressed bit is numbered (Offset MOD 8) within the byte at + address (BitBase + (BitOffset DIV 8)), where DIV is signed division with + rounding towards negative infinity, and MOD returns a positive number. + This is illustrated in Figure 17-4. + + I-O-Permission(I-O-Address, width) returns TRUE or FALSE depending on + the I/O permission bitmap and other factors. This function is defined as + follows: + + IF TSS type is 286 THEN RETURN FALSE; FI; + Ptr  [TSS + 66]; (* fetch bitmap pointer *) + BitStringAddr  SHR (I-O-Address, 3) + Ptr; + MaskShift  I-O-Address AND 7; + CASE width OF: + BYTE: nBitMask  1; + WORD: nBitMask  3; + DWORD: nBitMask  15; + ESAC; + mask  SHL (nBitMask, MaskShift); + CheckString  [BitStringAddr] AND mask; + IF CheckString = 0 + THEN RETURN (TRUE); + ELSE RETURN (FALSE); + FI; + + Switch-Tasks is the task switching function described in Chapter 7. + + +17.2.2.6 Description + +The "Description" section contains further explanation of the instruction's +operation. + + +Figure 17-3. Bit Offset for BIT[EAX, 21] + + 31 21 0 + ͻ + + ͼ +   + BITOFFSET = 21 + + +Figure 17-4. Memory Bit Indexing + + BIT INDEXING (POSITIVE OFFSET) + + 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + ͻ + + ͼ + BITBASE + 1 BITBASE BITBASE - 1 +  + OFFSET = 13 + + BIT INDEXING (NEGATIVE OFFSET) + + 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + ͻ + + ͼ + BITBASE BITBASE - 1 BITBASE - 2 +  + OFFSET = -11 + + +17.2.2.7 Flags Affected + +The "Flags Affected" section lists the flags that are affected by the +instruction, as follows: + + If a flag is always cleared or always set by the instruction, the + value is given (0 or 1) after the flag name. Arithmetic and logical + instructions usually assign values to the status flags in the uniform + manner described in Appendix C. Nonconventional assignments are + described in the "Operation" section. + + The values of flags listed as "undefined" may be changed by the + instruction in an indeterminate manner. + +All flags not listed are unchanged by the instruction. + + +17.2.2.8 Protected Mode Exceptions + +This section lists the exceptions that can occur when the instruction is +executed in 80386 Protected Mode. The exception names are a pound sign (#) +followed by two letters and an optional error code in parentheses. For +example, #GP(0) denotes a general protection exception with an error code of +0. Table 17-6 associates each two-letter name with the corresponding +interrupt number. + +Chapter 9 describes the exceptions and the 80386 state upon entry to the +exception. + +Application programmers should consult the documentation provided with +their operating systems to determine the actions taken when exceptions +occur. + + +Table 17-6. 80386 Exceptions + +Mnemonic Interrupt Description + +#UD 6 Invalid opcode +#NM 7 Coprocessor not available +#DF 8 Double fault +#TS 10 Invalid TSS +#NP 11 Segment or gate not present +#SS 12 Stack fault +#GP 13 General protection fault +#PF 14 Page fault +#MF 16 Math (coprocessor) fault + + +17.2.2.9 Real Address Mode Exceptions + +Because less error checking is performed by the 80386 in Real Address Mode, +this mode has fewer exception conditions. Refer to Chapter 14 for further +information on these exceptions. + + +17.2.2.10 Virtual-8086 Mode Exceptions + +Virtual 8086 tasks provide the ability to simulate Virtual 8086 machines. +Virtual 8086 Mode exceptions are similar to those for the 8086 processor, +but there are some differences. Refer to Chapter 15 for details. + + +AAA ASCII Adjust after Addition + +Opcode Instruction Clocks Description + +37 AAA 4 ASCII adjust AL after addition + + +Operation + +IF ((AL AND 0FH) > 9) OR (AF = 1) +THEN + AL  (AL + 6) AND 0FH; + AH  AH + 1; + AF  1; + CF  1; +ELSE + CF  0; + AF  0; +FI; + +Description + +Execute AAA only following an ADD instruction that leaves a byte result +in the AL register. The lower nibbles of the operands of the ADD instruction +should be in the range 0 through 9 (BCD digits). In this case, AAA adjusts +AL to contain the correct decimal digit result. If the addition produced a +decimal carry, the AH register is incremented, and the carry and auxiliary +carry flags are set to 1. If there was no decimal carry, the carry and +auxiliary flags are set to 0 and AH is unchanged. In either case, AL is left +with its top nibble set to 0. To convert AL to an ASCII result, follow the +AAA instruction with OR AL, 30H. + +Flags Affected + +AF and CF as described above; OF, SF, ZF, and PF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +AAD ASCII Adjust AX before Division + +Opcode Instruction Clocks Description + +D5 0A AAD 19 ASCII adjust AX before division + + +Operation + +AL  AH * 10 + AL; +AH  0; + +Description + +AAD is used to prepare two unpacked BCD digits (the least-significant +digit in AL, the most-significant digit in AH) for a division operation that +will yield an unpacked result. This is accomplished by setting AL to +AL + (10 * AH), and then setting AH to 0. AX is then equal to the binary +equivalent of the original unpacked two-digit number. + +Flags Affected + +SF, ZF, and PF as described in Appendix C; OF, AF, and CF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +AAM ASCII Adjust AX after Multiply + +Opcode Instruction Clocks Description + +D4 0A AAM 17 ASCII adjust AX after multiply + + +Operation + +AH  AL / 10; +AL  AL MOD 10; + +Description + +Execute AAM only after executing a MUL instruction between two unpacked +BCD digits that leaves the result in the AX register. Because the result is +less than 100, it is contained entirely in the AL register. AAM unpacks the +AL result by dividing AL by 10, leaving the quotient (most-significant +digit) in AH and the remainder (least-significant digit) in AL. + +Flags Affected + +SF, ZF, and PF as described in Appendix C; OF, AF, and CF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +AAS ASCII Adjust AL after Subtraction + +Opcode Instruction Clocks Description + +3F AAS 4 ASCII adjust AL after subtraction + + +Operation + +IF (AL AND 0FH) > 9 OR AF = 1 +THEN + AL  AL - 6; + AL  AL AND 0FH; + AH  AH - 1; + AF  1; + CF  1; +ELSE + CF  0; + AF  0; +FI; + +Description + +Execute AAS only after a SUB instruction that leaves the byte result in the +AL register. The lower nibbles of the operands of the SUB instruction must +have been in the range 0 through 9 (BCD digits). In this case, AAS adjusts +AL so it contains the correct decimal digit result. If the subtraction +produced a decimal carry, the AH register is decremented, and the carry and +auxiliary carry flags are set to 1. If no decimal carry occurred, the carry +and auxiliary carry flags are set to 0, and AH is unchanged. In either case, +AL is left with its top nibble set to 0. To convert AL to an ASCII result, +follow the AAS with OR AL, 30H. + +Flags Affected + +AF and CF as described above; OF, SF, ZF, and PF are undefined + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +ADC Add with Carry + + +Opcode Instruction Clocks Description + +14 ib ADC AL,imm8 2 Add with carry immediate byte to AL +15 iw ADC AX,imm16 2 Add with carry immediate word to AX +15 id ADC EAX,imm32 2 Add with carry immediate dword to EAX +80 /2 ib ADC r/m8,imm8 2/7 Add with carry immediate byte to r/m + byte +81 /2 iw ADC r/m16,imm16 2/7 Add with carry immediate word to r/m + word +81 /2 id ADC r/m32,imm32 2/7 Add with CF immediate dword to r/m + dword +83 /2 ib ADC r/m16,imm8 2/7 Add with CF sign-extended immediate + byte to r/m word +83 /2 ib ADC r/m32,imm8 2/7 Add with CF sign-extended immediate + byte into r/m dword +10 /r ADC r/m8,r8 2/7 Add with carry byte register to r/m + byte +11 /r ADC r/m16,r16 2/7 Add with carry word register to r/m + word +11 /r ADC r/m32,r32 2/7 Add with CF dword register to r/m dword +12 /r ADC r8,r/m8 2/6 Add with carry r/m byte to byte + register +13 /r ADC r16,r/m16 2/6 Add with carry r/m word to word + register +13 /r ADC r32,r/m32 2/6 Add with CF r/m dword to dword register + + +Operation + +DEST  DEST + SRC + CF; + +Description + +ADC performs an integer addition of the two operands DEST and SRC and the +carry flag, CF. The result of the addition is assigned to the first operand +(DEST), and the flags are set accordingly. ADC is usually executed as part +of a multi-byte or multi-word addition operation. When an immediate byte +value is added to a word or doubleword operand, the immediate value is first +sign-extended to the size of the word or doubleword operand. + +Flags Affected + +OF, SF, ZF, AF, CF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) if page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +ADD Add + +Opcode Instruction Clocks Description + +04 ib ADD AL,imm8 2 Add immediate byte to AL +05 iw ADD AX,imm16 2 Add immediate word to AX +05 id ADD EAX,imm32 2 Add immediate dword to EAX +80 /0 ib ADD r/m8,imm8 2/7 Add immediate byte to r/m byte +81 /0 iw ADD r/m16,imm16 2/7 Add immediate word to r/m word +81 /0 id ADD r/m32,imm32 2/7 Add immediate dword to r/m dword +83 /0 ib ADD r/m16,imm8 2/7 Add sign-extended immediate byte + to r/m word +83 /0 ib ADD r/m32,imm8 2/7 Add sign-extended immediate byte + to r/m dword +00 /r ADD r/m8,r8 2/7 Add byte register to r/m byte +01 /r ADD r/m16,r16 2/7 Add word register to r/m word +01 /r ADD r/m32,r32 2/7 Add dword register to r/m dword +02 /r ADD r8,r/m8 2/6 Add r/m byte to byte register +03 /r ADD r16,r/m16 2/6 Add r/m word to word register +03 /r ADD r32,r/m32 2/6 Add r/m dword to dword register + + +Operation + +DEST  DEST + SRC; + +Description + +ADD performs an integer addition of the two operands (DEST and SRC). The +result of the addition is assigned to the first operand (DEST), and the +flags are set accordingly. + +When an immediate byte is added to a word or doubleword operand, the +immediate value is sign-extended to the size of the word or doubleword +operand. + +Flags Affected + +OF, SF, ZF, AF, CF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +AND Logical AND + +Opcode Instruction Clocks Description + +24 ib AND AL,imm8 2 AND immediate byte to AL +25 iw AND AX,imm16 2 AND immediate word to AX +25 id AND EAX,imm32 2 AND immediate dword to EAX +80 /4 ib AND r/m8,imm8 2/7 AND immediate byte to r/m byte +81 /4 iw AND r/m16,imm16 2/7 AND immediate word to r/m word +81 /4 id AND r/m32,imm32 2/7 AND immediate dword to r/m dword +83 /4 ib AND r/m16,imm8 2/7 AND sign-extended immediate byte + with r/m word +83 /4 ib AND r/m32,imm8 2/7 AND sign-extended immediate byte + with r/m dword +20 /r AND r/m8,r8 2/7 AND byte register to r/m byte +21 /r AND r/m16,r16 2/7 AND word register to r/m word +21 /r AND r/m32,r32 2/7 AND dword register to r/m dword +22 /r AND r8,r/m8 2/6 AND r/m byte to byte register +23 /r AND r16,r/m16 2/6 AND r/m word to word register +23 /r AND r32,r/m32 2/6 AND r/m dword to dword register + + +Operation + +DEST  DEST AND SRC; +CF  0; +OF  0; + +Description + +Each bit of the result of the AND instruction is a 1 if both corresponding +bits of the operands are 1; otherwise, it becomes a 0. + +Flags Affected + +CF = 0, OF = 0; PF, SF, and ZF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +ARPL Adjust RPL Field of Selector + +Opcode Instruction Clocks Description + +63 /r ARPL r/m16,r16 pm=20/21 Adjust RPL of r/m16 to not + less than RPL of r16 + + +Operation + +IF RPL bits(0,1) of DEST < RPL bits(0,1) of SRC +THEN + ZF  1; + RPL bits(0,1) of DEST  RPL bits(0,1) of SRC; +ELSE + ZF  0; +FI; + +Description + +The ARPL instruction has two operands. The first operand is a 16-bit +memory variable or word register that contains the value of a selector. The +second operand is a word register. If the RPL field ("requested privilege +level"bottom two bits) of the first operand is less than the RPL field of +the second operand, the zero flag is set to 1 and the RPL field of the +first operand is increased to match the second operand. Otherwise, the zero +flag is set to 0 and no change is made to the first operand. + +ARPL appears in operating system software, not in application programs. It +is used to guarantee that a selector parameter to a subroutine does not +request more privilege than the caller is allowed. The second operand of +ARPL is normally a register that contains the CS selector value of the +caller. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 6; ARPL is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BOUND Check Array Index Against Bounds + +Opcode Instruction Clocks Description + +62 /r BOUND r16,m16&16 10 Check if r16 is within bounds + (passes test) +62 /r BOUND r32,m32&32 10 Check if r32 is within bounds + (passes test) + + +Operation + +IF (LeftSRC < [RightSRC] OR LeftSRC > [RightSRC + OperandSize/8]) + (* Under lower bound or over upper bound *) +THEN Interrupt 5; +FI; + +Description + +BOUND ensures that a signed array index is within the limits specified by a +block of memory consisting of an upper and a lower bound. Each bound uses +one word for an operand-size attribute of 16 bits and a doubleword for an +operand-size attribute of 32 bits. The first operand (a register) must be +greater than or equal to the first bound in memory (lower bound), and less +than or equal to the second bound in memory (upper bound). If the register +is not within bounds, an Interrupt 5 occurs; the return EIP points to the +BOUND instruction. + +The bounds limit data structure is usually placed just before the array +itself, making the limits addressable via a constant offset from the +beginning of the array. + +Flags Affected + +None + +Protected Mode Exceptions + +Interrupt 5 if the bounds test fails, as described above; #GP(0) for an +illegal memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +The second operand must be a memory operand, not a register. If BOUND is +executed with a ModRM byte representing a register as the second operand, +#UD occurs. + +Real Address Mode Exceptions + +Interrupt 5 if the bounds test fails; Interrupt 13 if any part of the +operand would lie outside of the effective address space from 0 to 0FFFFH; +Interrupt 6 if the second operand is a register + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BSF Bit Scan Forward + +Opcode Instruction Clocks Description + +0F BC BSF r16,r/m16 10+3n Bit scan forward on r/m word +0F BC BSF r32,r/m32 10+3n Bit scan forward on r/m dword + + +Notes + + is the number of leading zero bits. + +Operation + +IF r/m = 0 +THEN + ZF  1; + register  UNDEFINED; +ELSE + temp  0; + ZF  0; + WHILE BIT[r/m, temp = 0] + DO + temp  temp + 1; + register  temp; + OD; +FI; + +Description + +BSF scans the bits in the second word or doubleword operand starting with +bit 0. The ZF flag is cleared if the bits are all 0; otherwise, the ZF flag +is set and the destination register is loaded with the bit index of the +first set bit. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BSR Bit Scan Reverse + +Opcode Instruction Clocks Description + +0F BD BSR r16,r/m16 10+3n Bit scan reverse on r/m word +0F BD BSR r32,r/m32 10+3n Bit scan reverse on r/m dword + + +Operation + +IF r/m = 0 +THEN + ZF  1; + register  UNDEFINED; +ELSE + temp  OperandSize - 1; + ZF  0; + WHILE BIT[r/m, temp] = 0 + DO + temp  temp - 1; + register  temp; + OD; +FI; + +Description + +BSR scans the bits in the second word or doubleword operand from the most +significant bit to the least significant bit. The ZF flag is cleared if the +bits are all 0; otherwise, ZF is set and the destination register is loaded +with the bit index of the first set bit found when scanning in the reverse +direction. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +BT Bit Test + +Opcode Instruction Clocks Description + +0F A3 BT r/m16,r16 3/12 Save bit in carry flag +0F A3 BT r/m32,r32 3/12 Save bit in carry flag +0F BA /4 ib BT r/m16,imm8 3/6 Save bit in carry flag +0F BA /4 ib BT r/m32,imm8 3/6 Save bit in carry flag + + +Operation + +CF  BIT[LeftSRC, RightSRC]; + +Description + +BT saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 are supported by using the immediate bit offset field in +combination with the displacement field of the memory operand. The low-order +3 to 5 bits of the immediate bit offset are stored in the immediate bit +offset field, and the high-order 27 to 29 bits are shifted and combined with +the byte displacement in the addressing mode. + +When accessing a bit in memory, the 80386 may access four bytes starting +from the memory address given by: + + Effective Address + (4 * (BitOffset DIV 32)) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + (2 * (BitOffset DIV 16)) + +for a 16-bit operand size. It may do so even when only a single byte needs +to be accessed in order to reach the given bit. You must therefore avoid +referencing areas of memory close to address space holes. In particular, +avoid references to memory-mapped I/O registers. Instead, use the MOV +instructions to load from or store to these addresses, and use the register +form of these instructions to manipulate the data. + + +BTC Bit Test and Complement + +Opcode Instruction Clocks Description + +0F BB BTC r/m16,r16 6/13 Save bit in carry flag and complement +0F BB BTC r/m32,r32 6/13 Save bit in carry flag and complement +0F BA /7 ib BTC r/m16,imm8 6/8 Save bit in carry flag and complement +0F BA /7 ib BTC r/m32,imm8 6/8 Save bit in carry flag and complement + + +Operation + +CF  BIT[LeftSRC, RightSRC]; +BIT[LeftSRC, RightSRC]  NOT BIT[LeftSRC, RightSRC]; + +Description + +BTC saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag and then complements the +bit. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 are supported by using the immediate bit offset field in +combination with the displacement field of the memory operand. The low-order +3 to 5 bits of the immediate bit offset are stored in the immediate bit +offset field, and the high-order 27 to 29 bits are shifted and combined with +the byte displacement in the addressing mode. + +When accessing a bit in memory, the 80386 may access four bytes starting +from the memory address given by: + + Effective Address + (4 * (BitOffset DIV 32)) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + (2 * (BitOffset DIV 16)) + +for a 16-bit operand size. It may do so even when only a single byte needs +to be accessed in order to reach the given bit. You must therefore avoid +referencing areas of memory close to address space holes. In particular, +avoid references to memory-mapped I/O registers. Instead, use the MOV +instructions to load from or store to these addresses, and use the register +form of these instructions to manipulate the data. + + +BTR Bit Test and Reset + +Opcode Instruction Clocks Description + +0F B3 BTR r/m16,r16 6/13 Save bit in carry flag and reset +0F B3 BTR r/m32,r32 6/13 Save bit in carry flag and reset +0F BA /6 ib BTR r/m16,imm8 6/8 Save bit in carry flag and reset +0F BA /6 ib BTR r/m32,imm8 6/8 Save bit in carry flag and reset + + +Operation + +CF  BIT[LeftSRC, RightSRC]; +BIT[LeftSRC, RightSRC]  0; + +Description + +BTR saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag and then stores 0 in the +bit. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 (or 15) are supported by using the immediate bit offset field +in combination with the displacement field of the memory operand. The +low-order 3 to 5 bits of the immediate bit offset are stored in the +immediate bit offset field, and the high-order 27 to 29 bits are shifted and +combined with the byte displacement in the addressing mode. + +When accessing a bit in memory, the 80386 may access four bytes starting +from the memory address given by: + + Effective Address + 4 * (BitOffset DIV 32) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + 2 * (BitOffset DIV 16) + +for a 16-bit operand size. It may do so even when only a single byte needs +to be accessed in order to reach the given bit. You must therefore avoid +referencing areas of memory close to address space holes. In particular, +avoid references to memory-mapped I/O registers. Instead, use the MOV +instructions to load from or store to these addresses, and use the register +form of these instructions to manipulate the data. + + +BTS Bit Test and Set + +Opcode Instruction Clocks Description + +0F AB BTS r/m16,r16 6/13 Save bit in carry flag and set +0F AB BTS r/m32,r32 6/13 Save bit in carry flag and set +0F BA /5 ib BTS r/m16,imm8 6/8 Save bit in carry flag and set +0F BA /5 ib BTS r/m32,imm8 6/8 Save bit in carry flag and set + + +Operation + +CF  BIT[LeftSRC, RightSRC]; +BIT[LeftSRC, RightSRC]  1; + +Description + +BTS saves the value of the bit indicated by the base (first operand) and the +bit offset (second operand) into the carry flag and then stores 1 in the +bit. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The index of the selected bit can be given by the immediate constant in the +instruction or by a value in a general register. Only an 8-bit immediate +value is used in the instruction. This operand is taken modulo 32, so the +range of immediate bit offsets is 0..31. This allows any bit within a +register to be selected. For memory bit strings, this immediate field gives +only the bit offset within a word or doubleword. Immediate bit offsets +larger than 31 are supported by using the immediate bit offset field in +combination with the displacement field of the memory operand. The +low-order 3 to 5 bits of the immediate bit offset are stored in the +immediate bit offset field, and the high order 27 to 29 bits are shifted and +combined with the byte displacement in the addressing mode. + +When accessing a bit in memory, the processor may access four bytes starting +from the memory address given by: + + Effective Address + (4 * (BitOffset DIV 32)) + +for a 32-bit operand size, or two bytes starting from the memory address +given by: + + Effective Address + (2 * (BitOffset DIV 16)) + +for a 16-bit operand size. It may do this even when only a single byte needs +to be accessed in order to get at the given bit. Thus the programmer must be +careful to avoid referencing areas of memory close to address space holes. +In particular, avoid references to memory-mapped I/O registers. Instead, use +the MOV instructions to load from or store to these addresses, and use the +register form of these instructions to manipulate the data. + + +CALL Call Procedure + + +Opcode Instruction Clocks + Values of ts are given by the following table: + + New Task + 386 TSS 386 TSS 286 TSS + Old VM = 0 VM = 1 + Task Via Task Gate? + + N Y N Y N Y + +386 300 309 217 226 273 282 +TSS VM=0 + +286 298 307 217 226 273 282 +TSS Description + +E8 cw CALL rel16 7+m Call near, displacement relative + to next instruction +FF /2 CALL r/m16 7+m/10+m Call near, register + indirect/memory indirect +9A cd CALL ptr16:16 17+m,pm=34+m Call intersegment, to full + pointer given +9A cd CALL ptr16:16 pm=52+m Call gate, same privilege +9A cd CALL ptr16:16 pm=86+m Call gate, more privilege, no + parameters +9A cd CALL ptr16:16 pm=94+4x+m Call gate, more privilege, x + parameters +9A cd CALL ptr16:16 ts Call to task +FF /3 CALL m16:16 22+m,pm=38+m Call intersegment, address at + r/m dword +FF /3 CALL m16:16 pm=56+m Call gate, same privilege +FF /3 CALL m16:16 pm=90+m Call gate, more privilege, no + parameters +FF /3 CALL m16:16 pm=98+4x+m Call gate, more privilege, x + parameters +FF /3 CALL m16:16 5 + ts Call to task +E8 cd CALL rel32 7+m Call near, displacement relative + to next instruction +FF /2 CALL r/m32 7+m/10+m Call near, indirect +9A cp CALL ptr16:32 17+m,pm=34+m Call intersegment, to full + pointer given +9A cp CALL ptr16:32 pm=52+m Call gate, same privilege +9A cp CALL ptr16:32 pm=86+m Call gate, more privilege, no + parameters +9A cp CALL ptr32:32 pm=94+4x+m Call gate, more privilege, x + parameters +9A cp CALL ptr16:32 ts Call to task +FF /3 CALL m16:32 22+m,pm=38+m Call intersegment, address at + r/m dword +FF /3 CALL m16:32 pm=56+m Call gate, same privilege +FF /3 CALL m16:32 pm=90+m Call gate, more privilege, no + parameters +FF /3 CALL m16:32 pm=98+4x+m Call gate, more privilege, x + parameters +FF /3 CALL m16:32 5 + ts Call to task + + + +NOTE: + Values of ts are given by the following table: + + New Task + 386 TSS 386 TSS 286 TSS + Old VM = 0 VM = 1 + Task Via Task Gate? + + N Y N Y N Y + +386 300 309 217 226 273 282 +TSS VM=0 + +286 298 307 217 226 273 282 +TSS + + +Operation + +IF rel16 or rel32 type of call +THEN (* near relative call *) + IF OperandSize = 16 + THEN + Push(IP); + EIP  (EIP + rel16) AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + Push(EIP); + EIP  EIP + rel32; + FI; +FI; + +IF r/m16 or r/m32 type of call +THEN (* near absolute call *) + IF OperandSize = 16 + THEN + Push(IP); + EIP  [r/m16] AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + Push(EIP); + EIP  [r/m32]; + FI; +FI; + +IF (PE = 0 OR (PE = 1 AND VM = 1)) +(* real mode or virtual 8086 mode *) + AND instruction = far CALL + (* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *) +THEN + IF OperandSize = 16 + THEN + Push(CS); + Push(IP); (* address of next instruction; 16 bits *) + ELSE + Push(CS); (* padded with 16 high-order bits *) + Push(EIP); (* address of next instruction; 32 bits *) + FI; + IF operand type is m16:16 or m16:32 + THEN (* indirect far call *) + IF OperandSize = 16 + THEN + CS:IP  [m16:16]; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  [m16:32]; + FI; + FI; + IF operand type is ptr16:16 or ptr16:32 + THEN (* direct far call *) + IF OperandSize = 16 + THEN + CS:IP  ptr16:16; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  ptr16:32; + FI; + FI; +FI; + +IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *) + AND instruction = far CALL +THEN + If indirect, then check access of EA doubleword; + #GP(0) if limit violation; + New CS selector must not be null else #GP(0); + Check that new CS selector index is within its + descriptor table limits; else #GP(new CS selector); + Examine AR byte of selected descriptor for various legal values; + depending on value: + go to CONFORMING-CODE-SEGMENT; + go to NONCONFORMING-CODE-SEGMENT; + go to CALL-GATE; + go to TASK-GATE; + go to TASK-STATE-SEGMENT; + ELSE #GP(code segment selector); +FI; + +CONFORMING-CODE-SEGMENT: + DPL must be CPL ELSE #GP(code segment selector); + Segment must be present ELSE #NP(code segment selector); + Stack must be big enough for return address ELSE #SS(0); + Instruction pointer must be in code segment limit ELSE #GP(0); + Load code segment descriptor into CS register; + Load CS with new code segment selector; + Load EIP with zero-extend(new offset); + IF OperandSize=16 THEN EIP  EIP AND 0000FFFFH; FI; + +NONCONFORMING-CODE-SEGMENT: + RPL must be CPL ELSE #GP(code segment selector) + DPL must be = CPL ELSE #GP(code segment selector) + Segment must be present ELSE #NP(code segment selector) + Stack must be big enough for return address ELSE #SS(0) + Instruction pointer must be in code segment limit ELSE #GP(0) + Load code segment descriptor into CS register + Load CS with new code segment selector + Set RPL of CS to CPL + Load EIP with zero-extend(new offset); + IF OperandSize=16 THEN EIP  EIP AND 0000FFFFH; FI; + +CALL-GATE: + Call gate DPL must be CPL ELSE #GP(call gate selector) + Call gate DPL must be RPL ELSE #GP(call gate selector) + Call gate must be present ELSE #NP(call gate selector) + Examine code segment selector in call gate descriptor: + Selector must not be null ELSE #GP(0) + Selector must be within its descriptor table + limits ELSE #GP(code segment selector) + AR byte of selected descriptor must indicate code + segment ELSE #GP(code segment selector) + DPL of selected descriptor must be CPL ELSE + #GP(code segment selector) + IF non-conforming code segment AND DPL < CPL + THEN go to MORE-PRIVILEGE + ELSE go to SAME-PRIVILEGE + FI; + +MORE-PRIVILEGE: + Get new SS selector for new privilege level from TSS + Check selector and descriptor for new SS: + Selector must not be null ELSE #TS(0) + Selector index must be within its descriptor + table limits ELSE #TS(SS selector) + Selector's RPL must equal DPL of code segment + ELSE #TS(SS selector) + Stack segment DPL must equal DPL of code + segment ELSE #TS(SS selector) + Descriptor must indicate writable data segment + ELSE #TS(SS selector) + Segment present ELSE #SS(SS selector) + IF OperandSize=32 + THEN + New stack must have room for parameters plus 16 bytes + ELSE #SS(0) + EIP must be in code segment limit ELSE #GP(0) + Load new SS:eSP value from TSS + Load new CS:EIP value from gate + ELSE + New stack must have room for parameters plus 8 bytes ELSE #SS(0) + IP must be in code segment limit ELSE #GP(0) + Load new SS:eSP value from TSS + Load new CS:IP value from gate + FI; + Load CS descriptor + Load SS descriptor + Push long pointer of old stack onto new stack + Get word count from call gate, mask to 5 bits + Copy parameters from old stack onto new stack + Push return address onto new stack + Set CPL to stack segment DPL + Set RPL of CS to CPL + +SAME-PRIVILEGE: + IF OperandSize=32 + THEN + Stack must have room for 6-byte return address (padded to 8 bytes) + ELSE #SS(0) + EIP must be within code segment limit ELSE #GP(0) + Load CS:EIP from gate + ELSE + Stack must have room for 4-byte return address ELSE #SS(0) + IP must be within code segment limit ELSE #GP(0) + Load CS:IP from gate + FI; + Push return address onto stack + Load code segment descriptor into CS register + Set RPL of CS to CPL + +TASK-GATE: + Task gate DPL must be CPL ELSE #TS(gate selector) + Task gate DPL must be RPL ELSE #TS(gate selector) + Task Gate must be present ELSE #NP(gate selector) + Examine selector to TSS, given in Task Gate descriptor: + Must specify global in the local/global bit ELSE #TS(TSS selector) + Index must be within GDT limits ELSE #TS(TSS selector) + TSS descriptor AR byte must specify nonbusy TSS + ELSE #TS(TSS selector) + Task State Segment must be present ELSE #NP(TSS selector) + SWITCH-TASKS (with nesting) to TSS + IP must be in code segment limit ELSE #TS(0) + +TASK-STATE-SEGMENT: + TSS DPL must be CPL else #TS(TSS selector) + TSS DPL must be RPL ELSE #TS(TSS selector) + TSS descriptor AR byte must specify available TSS + ELSE #TS(TSS selector) + Task State Segment must be present ELSE #NP(TSS selector) + SWITCH-TASKS (with nesting) to TSS + IP must be in code segment limit ELSE #TS(0) + +Description + +The CALL instruction causes the procedure named in the operand to be +executed. When the procedure is complete (a return instruction is executed +within the procedure), execution continues at the instruction that follows +the CALL instruction. + +The action of the different forms of the instruction are described below. + +Near calls are those with destinations of type r/m16, r/m32, rel16, rel32; +changing or saving the segment register value is not necessary. The CALL +rel16 and CALL rel32 forms add a signed offset to the address of the +instruction following CALL to determine the destination. The rel16 form is +used when the instruction's operand-size attribute is 16 bits; rel32 is used +when the operand-size attribute is 32 bits. The result is stored in the +32-bit EIP register. With rel16, the upper 16 bits of EIP are cleared, +resulting in an offset whose value does not exceed 16 bits. CALL r/m16 and +CALL r/m32 specify a register or memory location from which the absolute +segment offset is fetched. The offset fetched from r/m is 32 bits for an +operand-size attribute of 32 (r/m32), or 16 bits for an operand-size of 16 +(r/m16). The offset of the instruction following CALL is pushed onto the +stack. It will be popped by a near RET instruction within the procedure. The +CS register is not changed by this form of CALL. + +The far calls, CALL ptr16:16 and CALL ptr16:32, use a four-byte or six-byte +operand as a long pointer to the procedure called. The CALL m16:16 and +m16:32 forms fetch the long pointer from the memory location +specified (indirection). In Real Address Mode or Virtual 8086 Mode, the long +pointer provides 16 bits for the CS register and 16 or 32 bits for the EIP +register (depending on the operand-size attribute). These forms of the +instruction push both CS and IP or EIP as a return address. + +In Protected Mode, both long pointer forms consult the AR byte in the +descriptor indexed by the selector part of the long pointer. Depending on +the value of the AR byte, the call will perform one of the following types +of control transfers: + + A far call to the same protection level + An inter-protection level far call + A task switch + +For more information on Protected Mode control transfers, refer to +Chapter 6 and Chapter 7. + +Flags Affected + +All flags are affected if a task switch occurs; no flags are affected if a +task switch does not occur + +Protected Mode Exceptions + +For far calls: #GP, #NP, #SS, and #TS, as indicated in the list above + +For near direct calls: #GP(0) if procedure location is beyond the code +segment limits; #SS(0) if pushing the return address exceeds the bounds of +the stack segment; #PF (fault-code) for a page fault + +For a near indirect call: #GP(0) for an illegal memory operand effective +address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address +in the SS segment; #GP(0) if the indirect offset obtained is beyond the code +segment limits; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +Any far call from a 32-bit code segment to 16-bit code segments should be +made from the first 64K bytes of the 32-bit code segment, since the +operand-size attribute of the instruction is set to 16, thus allowing only a +16-bit return address offset to be saved. + + +CBW/CWDE Convert Byte to Word/Convert Word to Doubleword + +Opcode Instruction Clocks Description + +98 CBW 3 AX  sign-extend of AL +98 CWDE 3 EAX  sign-extend of AX + + +Operation + +IF OperandSize = 16 (* instruction = CBW *) +THEN AX  SignExtend(AL); +ELSE (* OperandSize = 32, instruction = CWDE *) + EAX  SignExtend(AX); +FI; + +Description + +CBW converts the signed byte in AL to a signed word in AX by extending the +most significant bit of AL (the sign bit) into all of the bits of AH. CWDE +converts the signed word in AX to a doubleword in EAX by extending the most +significant bit of AX into the two most significant bytes of EAX. Note that +CWDE is different from CWD. CWD uses DX:AX rather than EAX as a destination. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CLC Clear Carry Flag + +Opcode Instruction Clocks Description + +F8 CLC 2 Clear carry flag + + +Operation + +CF  0; + +Description + +CLC sets the carry flag to zero. It does not affect other flags or +registers. + +Flags Affected + +CF = 0 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CLD Clear Direction Flag + +Opcode Instruction Clocks Description + +FC CLD 2 Clear direction flag; SI and DI + will increment during string + instructions + + +Operation + +DF  0; + +Description + +CLD clears the direction flag. No other flags or registers are affected. +After CLD is executed, string operations will increment the index registers +(SI and/or DI) that they use. + +Flags Affected + +DF = 0 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CLI Clear Interrupt Flag + +Opcode Instruction Clocks Description + +FA CLI 3 Clear interrupt flag; interrupts disabled + + +Operation + +IF  0; + +Description + +CLI clears the interrupt flag if the current privilege level is at least as +privileged as IOPL. No other flags are affected. External interrupts are not +recognized at the end of the CLI instruction or from that point on until the +interrupt flag is set. + +Flags Affected + +IF = 0 + +Protected Mode Exceptions + +#GP(0) if the current privilege level is greater (has less privilege) than +the IOPL in the flags register. IOPL specifies the least privileged level at +which I/O can be performed. + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) as for Protected Mode + + +CLTS Clear Task-Switched Flag in CR0 + +Opcode Instruction Clocks Description + +OF 06 CLTS 5 Clear task-switched flag + + +Operation + +TS Flag in CR0  0; + +Description + +CLTS clears the task-switched (TS) flag in register CR0. This flag is set by +the 80386 every time a task switch occurs. The TS flag is used to manage +processor extensions as follows: + + Every execution of an ESC instruction is trapped if the TS flag is set. + + Execution of a WAIT instruction is trapped if the MP flag and the TS + flag are both set. + +Thus, if a task switch was made after an ESC instruction was begun, the +processor extension's context may need to be saved before a new ESC +instruction can be issued. The fault handler saves the context and resets +the TS flag. + +CLTS appears in operating system software, not in application programs. It +is a privileged instruction that can only be executed at privilege level 0. + +Flags Affected + +TS = 0 (TS is in CR0, not the flag register) + +Protected Mode Exceptions + +#GP(0) if CLTS is executed with a current privilege level other than 0 + +Real Address Mode Exceptions + +None (valid in Real Address Mode to allow initialization for Protected +Mode) + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +CMC Complement Carry Flag + +Opcode Instruction Clocks Description + +F5 CMC 2 Complement carry flag + + +Operation + +CF  NOT CF; + +Description + +CMC reverses the setting of the carry flag. No other flags are affected. + +Flags Affected + +CF as described above + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +CMP Compare Two Operands + + +Opcode Instruction Clocks Description + +3C ib CMP AL,imm8 2 Compare immediate byte to AL +3D iw CMP AX,imm16 2 Compare immediate word to AX +3D id CMP EAX,imm32 2 Compare immediate dword to EAX +80 /7 ib CMP r/m8,imm8 2/5 Compare immediate byte to r/m + byte +81 /7 iw CMP r/m16,imm16 2/5 Compare immediate word to r/m + word +81 /7 id CMP r/m32,imm32 2/5 Compare immediate dword to r/m + dword +83 /7 ib CMP r/m16,imm8 2/5 Compare sign extended immediate + byte to r/m word +83 /7 ib CMP r/m32,imm8 2/5 Compare sign extended immediate + byte to r/m dword +38 /r CMP r/m8,r8 2/5 Compare byte register to r/m + byte +39 /r CMP r/m16,r16 2/5 Compare word register to r/m + word +39 /r CMP r/m32,r32 2/5 Compare dword register to r/m + dword +3A /r CMP r8,r/m8 2/6 Compare r/m byte to byte + register +3B /r CMP r16,r/m16 2/6 Compare r/m word to word + register +3B /r CMP r32,r/m32 2/6 Compare r/m dword to dword + register + + +Operation + +LeftSRC - SignExtend(RightSRC); +(* CMP does not store a result; its purpose is to set the flags *) + +Description + +CMP subtracts the second operand from the first but, unlike the SUB +instruction, does not store the result; only the flags are changed. CMP is +typically used in conjunction with conditional jumps and the SETcc +instruction. (Refer to Appendix D for the list of signed and unsigned flag +tests provided.) If an operand greater than one byte is compared to an +immediate byte, the byte value is first sign-extended. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +CMPS/CMPSB/CMPSW/CMPSD Compare String Operands + +Opcode Instruction Clocks Description + +A6 CMPS m8,m8 10 Compare bytes ES:[(E)DI] (second + operand) with [(E)SI] (first + operand) +A7 CMPS m16,m16 10 Compare words ES:[(E)DI] (second + operand) with [(E)SI] (first + operand) +A7 CMPS m32,m32 10 Compare dwords ES:[(E)DI] + (second operand) with [(E)SI] + (first operand) +A6 CMPSB 10 Compare bytes ES:[(E)DI] with + DS:[SI] +A7 CMPSW 10 Compare words ES:[(E)DI] with + DS:[SI] +A7 CMPSD 10 Compare dwords ES:[(E)DI] with + DS:[SI] + + +Operation + +IF (instruction = CMPSD) OR + (instruction has operands of type DWORD) +THEN OperandSize  32; +ELSE OperandSize  16; +FI; +IF AddressSize = 16 +THEN + use SI for source-index and DI for destination-index +ELSE (* AddressSize = 32 *) + use ESI for source-index and EDI for destination-index; +FI; +IF byte type of instruction +THEN + [source-index] - [destination-index]; (* byte comparison *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + [source-index] - [destination-index]; (* word comparison *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + [source-index] - [destination-index]; (* dword comparison *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index = source-index + IncDec; +destination-index = destination-index + IncDec; + +Description + +CMPS compares the byte, word, or doubleword pointed to by the source-index +register with the byte, word, or doubleword pointed to by the +destination-index register. + +If the address-size attribute of this instruction is 16 bits, SI and DI +will be used for source- and destination-index registers; otherwise ESI and +EDI will be used. Load the correct index values into SI and DI (or ESI and +EDI) before executing CMPS. + +The comparison is done by subtracting the operand indexed by +the destination-index register from the operand indexed by the source-index +register. + +Note that the direction of subtraction for CMPS is [SI] - [DI] or +[ESI] - [EDI]. The left operand (SI or ESI) is the source and the right +operand (DI or EDI) is the destination. This is the reverse of the usual +Intel convention in which the left operand is the destination and the right +operand is the source. + +The result of the subtraction is not stored; only the flags reflect the +change. The types of the operands determine whether bytes, words, or +doublewords are compared. For the first operand (SI or ESI), the DS register +is used, unless a segment override byte is present. The second operand (DI +or EDI) must be addressable from the ES register; no segment override is +possible. + +After the comparison is made, both the source-index register and +destination-index register are automatically advanced. If the direction flag +is 0 (CLD was executed), the registers increment; if the direction flag is 1 +(STD was executed), the registers decrement. The registers increment or +decrement by 1 if a byte is compared, by 2 if a word is compared, or by 4 if +a doubleword is compared. + +CMPSB, CMPSW and CMPSD are synonyms for the byte, word, and +doubleword CMPS instructions, respectively. + +CMPS can be preceded by the REPE or REPNE prefix for block comparison of CX +or ECX bytes, words, or doublewords. Refer to the description of the REP +instruction for more information on this operation. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF (fault-code) for a page fault + + +CWD/CDQ Convert Word to Doubleword/Convert Doubleword to + Quadword + +Opcode Instruction Clocks Description + +99 CWD 2 DX:AX  sign-extend of AX +99 CDQ 2 EDX:EAX  sign-extend of EAX + + +Operation + +IF OperandSize = 16 (* CWD instruction *) +THEN + IF AX < 0 THEN DX  0FFFFH; ELSE DX  0; FI; +ELSE (* OperandSize = 32, CDQ instruction *) + IF EAX < 0 THEN EDX  0FFFFFFFFH; ELSE EDX  0; FI; +FI; + +Description + +CWD converts the signed word in AX to a signed doubleword in DX:AX +by extending the most significant bit of AX into all the bits of DX. CDQ +converts the signed doubleword in EAX to a signed 64-bit integer in the +register pair EDX:EAX by extending the most significant bit of EAX +(the sign bit) into all the bits of EDX. Note that CWD is different from +CWDE. CWDE uses EAX as a destination, instead of DX:AX. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +DAA Decimal Adjust AL after Addition + +Opcode Instruction Clocks Description + +27 DAA 4 Decimal adjust AL after addition + + +Operation + +IF ((AL AND 0FH) > 9) OR (AF = 1) +THEN + AL  AL + 6; + AF  1; +ELSE + AF  0; +FI; +IF (AL > 9FH) OR (CF = 1) +THEN + AL  AL + 60H; + CF  1; +ELSE CF  0; +FI; + +Description + +Execute DAA only after executing an ADD instruction that leaves a +two-BCD-digit byte result in the AL register. The ADD operands should +consist of two packed BCD digits. The DAA instruction adjusts AL to +contain the correct two-digit packed decimal result. + +Flags Affected + +AF and CF as described above; SF, ZF, PF, and CF as described in +Appendix C. + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +DAS Decimal Adjust AL after Subtraction + +Opcode Instruction Clocks Description + +2F DAS 4 Decimal adjust AL after subtraction + + +Operation + +IF (AL AND 0FH) > 9 OR AF = 1 +THEN + AL  AL - 6; + AF  1; +ELSE + AF  0; +FI; +IF (AL > 9FH) OR (CF = 1) +THEN + AL  AL - 60H; + CF  1; +ELSE CF  0; +FI; + +Description + +Execute DAS only after a subtraction instruction that leaves a +two-BCD-digit byte result in the AL register. The operands should consist +of two packed BCD digits. DAS adjusts AL to contain the correct packed +two-digit decimal result. + +Flags Affected + +AF and CF as described above; SF, ZF, and PF as described in Appendix C. + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +DEC Decrement by 1 + +Opcode Instruction Clocks Description + +FE /1 DEC r/m8 2/6 Decrement r/m byte by 1 +FF /1 DEC r/m16 2/6 Decrement r/m word by 1 + DEC r/m32 2/6 Decrement r/m dword by 1 +48+rw DEC r16 2 Decrement word register by 1 +48+rw DEC r32 2 Decrement dword register by 1 + + +Operation + +DEST  DEST - 1; + +Description + +DEC subtracts 1 from the operand. DEC does not change the carry flag. +To affect the carry flag, use the SUB instruction with an immediate +operand of 1. + +Flags Affected + +OF, SF, ZF, AF, and PF as described in Appendix C. + +Protected Mode Exceptions + +#GP(0) if the result is a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +DIV Unsigned Divide + +Opcode Instruction Clocks Description + +F6 /6 DIV AL,r/m8 14/17 Unsigned divide AX by r/m byte + (AL=Quo, AH=Rem) +F7 /6 DIV AX,r/m16 22/25 Unsigned divide DX:AX by r/m + word (AX=Quo, DX=Rem) +F7 /6 DIV EAX,r/m32 38/41 Unsigned divide EDX:EAX by r/m + dword (EAX=Quo, EDX=Rem) + + +Operation + +temp  dividend / divisor; +IF temp does not fit in quotient +THEN Interrupt 0; +ELSE + quotient  temp; + remainder  dividend MOD (r/m); +FI; + + +Note: + Divisions are unsigned. The divisor is given by the r/m operand. + The dividend, quotient, and remainder use implicit registers. Refer to + the table under "Description." + + +Description + +DIV performs an unsigned division. The dividend is implicit; only the +divisor is given as an operand. The remainder is always less than the +divisor. The type of the divisor determines which registers to use as +follows: + + Size Dividend Divisor Quotient Remainder + byte AX r/m8 AL AH + word DX:AX r/m16 AX DX + dword EDX:EAX r/m32 EAX EDX + +Flags Affected + +OF, SF, ZF, AR, PF, CF are undefined. + +Protected Mode Exceptions + +Interrupt 0 if the quotient is too large to fit in the designated register +(AL, AX, or EAX), or if the divisor is 0; #GP(0) for an illegal memory +operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) +for an illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 0 if the quotient is too big to fit in the designated register +(AL, AX, or EAX), or if the divisor is 0; Interrupt 13 if any part of the +operand would lie outside of the effective address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +ENTER Make Stack Frame for Procedure Parameters + +Opcode Instruction Clocks Description + +C8 iw 00 ENTER imm16,0 10 Make procedure stack frame +C8 iw 01 ENTER imm16,1 12 Make stack frame for procedure + parameters +C8 iw ib ENTER imm16,imm8 15+4(n-1) Make stack frame for + procedure parameters + + +Operation + +level  level MOD 32 +IF OperandSize = 16 THEN Push(BP) ELSE Push (EBP) FI; + (* Save stack pointer *) +frame-ptr  eSP +IF level > 0 +THEN (* level is rightmost parameter *) + FOR i  1 TO level - 1 + DO + IF OperandSize = 16 + THEN + BP  BP - 2; + Push[BP] + ELSE (* OperandSize = 32 *) + EBP  EBP - 4; + Push[EBP]; + FI; + OD; + Push(frame-ptr) +FI; +IF OperandSize = 16 THEN BP  frame-ptr ELSE EBP  frame-ptr; FI; +IF StackAddrSize = 16 +THEN SP  SP - First operand; +ELSE ESP  ESP - ZeroExtend(First operand); +FI; + +Description + +ENTER creates the stack frame required by most block-structured +high-level languages. The first operand specifies the number of bytes of +dynamic storage allocated on the stack for the routine being entered. +The second operand gives the lexical nesting level (0 to 31) of the routine +within the high-level language source code. It determines the number of +stack frame pointers copied into the new stack frame from the preceding +frame. BP (or EBP, if the operand-size attribute is 32 bits) is the current +stack frame pointer. + +If the operand-size attribute is 16 bits, the processor uses BP as the +frame pointer and SP as the stack pointer. If the operand-size attribute is +32 bits, the processor uses EBP for the frame pointer and ESP for the stack +pointer. + +If the second operand is 0, ENTER pushes the frame pointer (BP or +EBP) onto the stack; ENTER then subtracts the first operand from the +stack pointer and sets the frame pointer to the current stack-pointer +value. + +For example, a procedure with 12 bytes of local variables would have an +ENTER 12,0 instruction at its entry point and a LEAVE instruction +before every RET. The 12 local bytes would be addressed as negative +offsets from the frame pointer. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if SP or ESP would exceed the stack limit at any point during +instruction execution; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +HLT Halt + +Opcode Instruction Clocks Description + +F4 HLT 5 Halt + + +Operation + +Enter Halt state; + +Description + +HALT stops instruction execution and places the 80386 in a HALT state. +An enabled interrupt, NMI, or a reset will resume execution. If an +interrupt (including NMI) is used to resume execution after HLT, the saved +CS:IP (or CS:EIP) value points to the instruction following HLT. + +Flags Affected + +None + +Protected Mode Exceptions + +HLT is a privileged instruction; #GP(0) if the current privilege level is +not 0 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0); HLT is a privileged instruction + + +IDIV Signed Divide + +Opcode Instruction Clocks Description + +F6 /7 IDIV r/m8 19 Signed divide AX by r/m byte + (AL=Quo, AH=Rem) +F7 /7 IDIV AX,r/m16 27 Signed divide DX:AX by EA word + (AX=Quo, DX=Rem) +F7 /7 IDIV EAX,r/m32 43 Signed divide EDX:EAX by DWORD + byte (EAX=Quo, EDX=Rem) + + +Operation + +temp  dividend / divisor; +IF temp does not fit in quotient +THEN Interrupt 0; +ELSE + quotient  temp; + remainder  dividend MOD (r/m); +FI; + + +Notes: + Divisions are signed. The divisor is given by the r/m operand. The + dividend, quotient, and remainder use implicit registers. Refer to the + table under "Description." + + +Description + +IDIV performs a signed division. The dividend, quotient, and remainder +are implicitly allocated to fixed registers. Only the divisor is given as +an explicit r/m operand. The type of the divisor determines which registers +to use as follows: + +Size Divisor Quotient Remainder Dividend +byte r/m8 AL AH AX +word r/m16 AX DX DX:AX +dword r/m32 EAX EDX EDX:EAX + +If the resulting quotient is too large to fit in the destination, or if the +division is 0, an Interrupt 0 is generated. Nonintegral quotients are +truncated toward 0. The remainder has the same sign as the dividend +and the absolute value of the remainder is always less than the absolute +value of the divisor. + +Flags Affected + +OF, SF, ZF, AR, PF, CF are undefined. + +Protected Mode Exceptions + +Interrupt 0 if the quotient is too large to fit in the designated register +(AL or AX), or if the divisor is 0; #GP (0) for an illegal memory operand +effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an +illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 0 if the quotient is too large to fit in the designated register +(AL or AX), or if the divisor is 0; Interrupt 13 if any part of the operand +would lie outside of the effective address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +IMUL Signed Multiply + + +Opcode Instruction Clocks Description + +F6 /5 IMUL r/m8 9-14/12-17 AX AL * r/m byte +F7 /5 IMUL r/m16 9-22/12-25 DX:AX  AX * r/m word +F7 /5 IMUL r/m32 9-38/12-41 EDX:EAX  EAX * r/m dword +0F AF /r IMUL r16,r/m16 9-22/12-25 word register  word + register * r/m word +0F AF /r IMUL r32,r/m32 9-38/12-41 dword register  dword + register * r/m dword +6B /r ib IMUL r16,r/m16,imm8 9-14/12-17 word register  r/m16 * + sign-extended immediate byte +6B /r ib IMUL r32,r/m32,imm8 9-14/12-17 dword register  r/m32 * + sign-extended immediate byte +6B /r ib IMUL r16,imm8 9-14/12-17 word register  word + register * sign-extended + immediate byte +6B /r ib IMUL r32,imm8 9-14/12-17 dword register  dword + register * sign-extended + immediate byte +69 /r iw IMUL r16,r/m16,imm16 9-22/12-25 word register  r/m16 * + immediate word +69 /r id IMUL r32,r/m32,imm32 9-38/12-41 dword register  r/m32 * + immediate dword +69 /r iw IMUL r16,imm16 9-22/12-25 word register  r/m16 * + immediate word +69 /r id IMUL r32,imm32 9-38/12-41 dword register  r/m32 * + immediate dword + + + +NOTES: + The 80386 uses an early-out multiply algorithm. The actual number of + clocks depends on the position of the most significant bit in the + optimizing multiplier, shown underlined above. The optimization occurs for + positive and negative values. Because of the early-out algorithm, clock + counts given are minimum to maximum. To calculate the actual clocks, use + the following formula: + + + Actual clock = if m <> 0 then max(ceiling(log{2} m), 3) + 6 clocks + Actual clock = if m = 0 then 9 clocks + (where m is the multiplier) + +Add three clocks if the multiplier is a memory operand. + +Operation + +result  multiplicand * multiplier; + +Description + +IMUL performs signed multiplication. Some forms of the instruction +use implicit register operands. The operand combinations for all forms +of the instruction are shown in the "Description" column above. + +IMUL clears the overflow and carry flags under the following conditions: + + Instruction Form Condition for Clearing CF and OF + r/m8 AL = sign-extend of AL to 16 bits + r/m16 AX = sign-extend of AX to 32 bits + r/m32 EDX:EAX = sign-extend of EAX to 32 bits + r16,r/m16 Result exactly fits within r16 + r/32,r/m32 Result exactly fits within r32 + r16,r/m16,imm16 Result exactly fits within r16 + r32,r/m32,imm32 Result exactly fits within r32 + +Flags Affected + +OF and CF as described above; SF, ZF, AF, and PF are undefined + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exeptions as in Real Address Mode; #PF(fault-code) for a page +fault + +Notes + +When using the accumulator forms (IMUL r/m8, IMUL r/m16, or IMUL +r/m32), the result of the multiplication is available even if the overflow +flag is set because the result is two times the size of the multiplicand +and multiplier. This is large enough to handle any possible result. + + +IN Input from Port + +Opcode Instruction Clocks Description + +E4 ib IN AL,imm8 12,pm=6*/26** Input byte from immediate port + into AL +E5 ib IN AX,imm8 12,pm=6*/26** Input word from immediate port + into AX +E5 ib IN EAX,imm8 12,pm=6*/26** Input dword from immediate port + into EAX +EC IN AL,DX 13,pm=7*/27** Input byte from port DX into AL +ED IN AX,DX 13,pm=7*/27** Input word from port DX into AX +ED IN EAX,DX 13,pm=7*/27** Input dword from port DX into + EAX + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (SRC, width(SRC)) + THEN #GP(0); + FI; +FI; +DEST  [SRC]; (* Reads from I/O address space *) + +Description + +IN transfers a data byte or data word from the port numbered by the +second operand into the register (AL, AX, or EAX) specified by the first +operand. Access any port from 0 to 65535 by placing the port number +in the DX register and using an IN instruction with DX as the second +parameter. These I/O instructions can be shortened by using an 8-bit +port I/O in the instruction. The upper eight bits of the port address will +be 0 when 8-bit port I/O is used. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is larger (has less privilege) than +IOPL and any of the corresponding I/O permission bits in TSS equals 1 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1 + + +INC Increment by 1 + +Opcode Instruction Clocks Description + +FE /0 INC r/m8 Increment r/m byte by 1 +FF /0 INC r/m16 Increment r/m word by 1 +FF /6 INC r/m32 Increment r/m dword by 1 +40 + rw INC r16 Increment word register by 1 +40 + rd INC r32 Increment dword register by 1 + + +Operation + +DEST  DEST + 1; + +Description + +INC adds 1 to the operand. It does not change the carry flag. To affect +the carry flag, use the ADD instruction with a second operand of 1. + +Flags Affected + +OF, SF, ZF, AF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the operand is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +INS/INSB/INSW/INSD Input from Port to String + +Opcode Instruction Clocks Description + +6C INS r/m8,DX 15,pm=9*/29** Input byte from port DX into ES:(E)DI +6D INS r/m16,DX 15,pm=9*/29** Input word from port DX into ES:(E)DI +6D INS r/m32,DX 15,pm=9*/29** Input dword from port DX into ES:(E)DI +6C INSB 15,pm=9*/29** Input byte from port DX into ES:(E)DI +6D INSW 15,pm=9*/29** Input word from port DX into ES:(E)DI +6D INSD 15,pm=9*/29** Input dword from port DX into ES:(E)DI + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF AddressSize = 16 +THEN use DI for dest-index; +ELSE (* AddressSize = 32 *) + use EDI for dest-index; +FI; +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (SRC, width(SRC)) + THEN #GP(0); + FI; +FI; +IF byte type of instruction +THEN + ES:[dest-index]  [DX]; (* Reads byte at DX from I/O address space *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +FI; +IF OperandSize = 16 +THEN + ES:[dest-index]  [DX]; (* Reads word at DX from I/O address space *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; +FI; +IF OperandSize = 32 +THEN + ES:[dest-index]  [DX]; (* Reads dword at DX from I/O address space *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; +FI; +dest-index  dest-index + IncDec; + +Description + +INS transfers data from the input port numbered by the DX register to +the memory byte or word at ES:dest-index. The memory operand must +be addressable from ES; no segment override is possible. The destination +register is DI if the address-size attribute of the instruction is 16 bits, +or EDI if the address-size attribute is 32 bits. + +INS does not allow the specification of the port number as an immediate +value. The port must be addressed through the DX register value. Load +the correct value into DX before executing the INS instruction. + +The destination address is determined by the contents of the destination +index register. Load the correct index into the destination index register +before executing INS. + +After the transfer is made, DI or EDI advances automatically. If the +direction flag is 0 (CLD was executed), DI or EDI increments; if the +direction flag is 1 (STD was executed), DI or EDI decrements. DI +increments or decrements by 1 if a byte is input, by 2 if a word is input, +or by 4 if a doubleword is input. + +INSB, INSW and INSD are synonyms of the byte, word, and doubleword +INS instructions. INS can be preceded by the REP prefix for block input of +CX bytes or words. Refer to the REP instruction for details of this +operation. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if CPL is numerically greater than IOPL and any of the +corresponding I/O permission bits in TSS equals 1; #GP(0) if the +destination is in a nonwritable segment; #GP(0) for an illegal memory +operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for +an illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1; #PF(fault-code) for a page fault + + +INT/INTO Call to Interrupt Procedure + + +Opcode Instruction Clocks Description + +CC INT 3 33 Interrupt 3--trap to debugger +CC INT 3 pm=59 Interrupt 3--Protected Mode, same + privilege +CC INT 3 pm=99 Interrupt 3--Protected Mode, more + privilege +CC INT 3 pm=119 Interrupt 3--from V86 mode to PL 0 +CC INT 3 ts Interrupt 3--Protected Mode, via + task gate +CD ib INT imm8 37 Interrupt numbered by immediate + byte +CD ib INT imm8 pm=59 Interrupt--Protected Mode, same + privilege +CD ib INT imm8 pm=99 Interrupt--Protected Mode, more + privilege +CD ib INT imm8 pm=119 Interrupt--from V86 mode to PL 0 +CD ib INT imm8 ts Interrupt--Protected Mode, via task + gate +CE INTO Fail:3,pm=3; + Pass:35 Interrupt 4--if overflow flag is 1 +CE INTO pm=59 Interrupt 4--Protected Mode, same + privilege +CE INTO pm=99 Interrupt 4--Protected Mode, more + privilege +CE INTO pm=119 Interrupt 4--from V86 mode to PL 0 +CE INTO ts Interrupt 4--Protected Mode, via + task gate + + + +NOTE: + Approximate values of ts are given by the following table: + + New Task + +Old Task 386 TSS 386 TSS 286 TSS + VM = 0 VM = 1 + +386 +TSS VM=0 309 226 282 + +386 +TSS VM=1 314 231 287 + +286 +TSS 307 224 280 + + +Operation + + +NOTE: + The following operational description applies not only to the + above instructions but also to external interrupts and exceptions. + + +IF PE = 0 +THEN GOTO REAL-ADDRESS-MODE; +ELSE GOTO PROTECTED-MODE; +FI; + +REAL-ADDRESS-MODE: + Push (FLAGS); + IF  0; (* Clear interrupt flag *) + TF  0; (* Clear trap flag *) + Push(CS); + Push(IP); + (* No error codes are pushed *) + CS  IDT[Interrupt number * 4].selector; + IP  IDT[Interrupt number * 4].offset; + +PROTECTED-MODE: + Interrupt vector must be within IDT table limits, + else #GP(vector number * 8+2+EXT); + Descriptor AR byte must indicate interrupt gate, trap gate, or task gate, + else #GP(vector number * 8+2+EXT); + IF software interrupt (* i.e. caused by INT n, INT 3, or INTO *) + THEN + IF gate descriptor DPL < CPL + THEN #GP(vector number * 8+2+EXT); + FI; + FI; + Gate must be present, else #NP(vector number * 8+2+EXT); + IF trap gate OR interrupt gate + THEN GOTO TRAP-GATE-OR-INTERRUPT-GATE; + ELSE GOTO TASK-GATE; + FI; + +TRAP-GATE-OR-INTERRUPT-GATE: + Examine CS selector and descriptor given in the gate descriptor; + Selector must be non-null, else #GP (EXT); + Selector must be within its descriptor table limits + ELSE #GP(selector+EXT); + Descriptor AR byte must indicate code segment + ELSE #GP(selector + EXT); + Segment must be present, else #NP(selector+EXT); + IF code segment is non-conforming AND DPL < CPL + THEN GOTO INTERRUPT-TO-INNER-PRIVILEGE; + ELSE + IF code segment is conforming OR code segment DPL = CPL + THEN GOTO INTERRUPT-TO-SAME-PRIVILEGE-LEVEL; + ELSE #GP(CS selector + EXT); + FI; + FI; + +INTERRUPT-TO-INNER-PRIVILEGE: + Check selector and descriptor for new stack in current TSS; + Selector must be non-null, else #GP(EXT); + Selector index must be within its descriptor table limits + ELSE #TS(SS selector+EXT); + Selector's RPL must equal DPL of code segment, else #TS(SS + selector+EXT); + Stack segment DPL must equal DPL of code segment, else #TS(SS + selector+EXT); + Descriptor must indicate writable data segment, else #TS(SS + selector+EXT); + Segment must be present, else #SS(SS selector+EXT); + IF 32-bit gate + THEN New stack must have room for 20 bytes else #SS(0) + ELSE New stack must have room for 10 bytes else #SS(0) + FI; + Instruction pointer must be within CS segment boundaries else #GP(0); + Load new SS and eSP value from TSS; + IF 32-bit gate + THEN CS:EIP  selector:offset from gate; + ELSE CS:IP  selector:offset from gate; + FI; + Load CS descriptor into invisible portion of CS register; + Load SS descriptor into invisible portion of SS register; + IF 32-bit gate + THEN + Push (long pointer to old stack) (* 3 words padded to 4 *); + Push (EFLAGS); + Push (long pointer to return location) (* 3 words padded to 4*); + ELSE + Push (long pointer to old stack) (* 2 words *); + Push (FLAGS); + Push (long pointer to return location) (* 2 words *); + FI; + Set CPL to new code segment DPL; + Set RPL of CS to CPL; + IF interrupt gate THEN IF  0 (* interrupt flag to 0 (disabled) *); FI; + TF  0; + NT  0; + +INTERRUPT-FROM-V86-MODE: + TempEFlags  EFLAGS; + VM  0; + TF  0; + IF service through Interrupt Gate THEN IF  0; + TempSS  SS; + TempESP  ESP; + SS  TSS.SS0; (* Change to level 0 stack segment *) + ESP  TSS.ESP0; (* Change to level 0 stack pointer *) + Push(GS); (* padded to two words *) + Push(FS); (* padded to two words *) + Push(DS); (* padded to two words *) + Push(ES); (* padded to two words *) + GS  0; + FS  0; + DS  0; + ES  0; + Push(TempSS); (* padded to two words *) + Push(TempESP); + Push(TempEFlags); + Push(CS); (* padded to two words *) + Push(EIP); + CS:EIP  selector:offset from interrupt gate; + (* Starts execution of new routine in 80386 Protected Mode *) + +INTERRUPT-TO-SAME-PRIVILEGE-LEVEL: + IF 32-bit gate + THEN Current stack limits must allow pushing 10 bytes, else #SS(0); + ELSE Current stack limits must allow pushing 6 bytes, else #SS(0); + FI; + IF interrupt was caused by exception with error code + THEN Stack limits must allow push of two more bytes; + ELSE #SS(0); + FI; + Instruction pointer must be in CS limit, else #GP(0); + IF 32-bit gate + THEN + Push (EFLAGS); + Push (long pointer to return location); (* 3 words padded to 4 *) + CS:EIP  selector:offset from gate; + ELSE (* 16-bit gate *) + Push (FLAGS); + Push (long pointer to return location); (* 2 words *) + CS:IP  selector:offset from gate; + FI; + Load CS descriptor into invisible portion of CS register; + Set the RPL field of CS to CPL; + Push (error code); (* if any *) + IF interrupt gate THEN IF  0; FI; + TF  0; + NT  0; + +TASK-GATE: + Examine selector to TSS, given in task gate descriptor; + Must specify global in the local/global bit, else #TS(TSS selector); + Index must be within GDT limits, else #TS(TSS selector); + AR byte must specify available TSS (bottom bits 00001), + else #TS(TSS selector; + TSS must be present, else #NP(TSS selector); + SWITCH-TASKS with nesting to TSS; + IF interrupt was caused by fault with error code + THEN + Stack limits must allow push of two more bytes, else #SS(0); + Push error code onto stack; + FI; + Instruction pointer must be in CS limit, else #GP(0); + +Description + +The INT instruction generates via software a call to an interrupt +handler. The immediate operand, from 0 to 255, gives the index number +into the Interrupt Descriptor Table (IDT) of the interrupt routine to be +called. In Protected Mode, the IDT consists of an array of eight-byte +descriptors; the descriptor for the interrupt invoked must indicate an +interrupt, trap, or task gate. In Real Address Mode, the IDT is an array +of four byte-long pointers. In Protected and Real Address Modes, the +base linear address of the IDT is defined by the contents of the IDTR. + +The INTO conditional software instruction is identical to the INT +interrupt instruction except that the interrupt number is implicitly 4, +and the interrupt is made only if the 80386 overflow flag is set. + +The first 32 interrupts are reserved by Intel for system use. Some of +these interrupts are use for internally generated exceptions. + +INT n generally behaves like a far call except that the flags register is +pushed onto the stack before the return address. Interrupt procedures +return via the IRET instruction, which pops the flags and return address +from the stack. + +In Real Address Mode, INT n pushes the flags, CS, and the return IP +onto the stack, in that order, then jumps to the long pointer indexed by +the interrupt number. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #NP, #SS, and #TS as indicated under "Operation" above + +Real Address Mode Exceptions + +None; if the SP or ESP = 1, 3, or 5 before executing INT or INTO, +the 80386 will shut down due to insufficient stack space + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, for INT only, to permit emulation; +Interrupt 3 (0CCH) generates Interrupt 3; INTO generates Interrupt 4 +if the overflow flag equals 1 + + +IRET/IRETD Interrupt Return + +Opcode Instruction Clocks Description + +CF IRET 22,pm=38 Interrupt return (far return and pop + flags) +CF IRET pm=82 Interrupt return to lesser privilege +CF IRET ts Interrupt return, different task (NT = 1) +CF IRETD 22,pm=38 Interrupt return (far return and pop + flags) +CF IRETD pm=82 Interrupt return to lesser privilege +CF IRETD pm=60 Interrupt return to V86 mode +CF IRETD ts Interrupt return, different task (NT = 1) + + + +NOTE: + Values of ts are given by the following table: + + New Task + +Old Task 386 TSS 386 TSS 286 TSS + VM = 0 VM = 1 + +386 +TSS VM=0 275 224 271 + +286 +TSS 265 214 232 + + +Operation + +IF PE = 0 +THEN (* Real-address mode *) + IF OperandSize = 32 (* Instruction = IRETD *) + THEN EIP  Pop(); + ELSE (* Instruction = IRET *) + IP  Pop(); + FI; + CS  Pop(); + IF OperandSize = 32 (* Instruction = IRETD *) + THEN EFLAGS  Pop(); + ELSE (* Instruction = IRET *) + FLAGS  Pop(); + FI; +ELSE (* Protected mode *) + IF VM = 1 + THEN #GP(0); + ELSE + IF NT = 1 + THEN GOTO TASK-RETURN; + ELSE + IF VM = 1 in flags image on stack + THEN GO TO STACK-RETURN-TO-V86; + ELSE GOTO STACK-RETURN; + FI; + FI; + FI; +FI;STACK-RETURN-TO-V86: (* Interrupted procedure was in V86 mode *) + IF return CS selector RPL < > 3 + THEN #GP(Return selector); + FI; + IF top 36 bytes of stack not within limits + THEN #SS(0); + FI; + Examine return CS selector and associated descriptor: + IF selector is null, THEN #GP(0); FI; + IF selector index not within its descriptor table limits; + THEN #GP(Return selector); + FI; + IF AR byte does not indicate code segment + THEN #GP(Return selector); + FI; + IF code segment DPL not = 3; + THEN #GP(Return selector); + FI; + IF code segment not present + THEN #NP(Return selector); + FI; + + Examine return SS selector and associated descriptor: + IF selector is null THEN #GP(0); FI; + IF selector index not within its descriptor table limits + THEN #GP(SS selector); + FI; + IF selector RPL not = RPL of return CS selector + THEN #GP(SS selector); + FI; + IF AR byte does not indicate a writable data segment + THEN #GP(SS selector); + FI; + IF stack segment DPL not = RPL of return CS selector + THEN #GP(SS selector); + FI; + IF SS not present + THEN #NP(SS selector); + FI; + + IF instruction pointer not within code segment limit THEN #GP(0); + FI; + EFLAGS  SS:[eSP + 8]; (* Sets VM in interrupted routine *) + EIP  Pop(); + CS  Pop(); (* CS behaves as in 8086, due to VM = 1 *) + throwaway  Pop(); (* pop away EFLAGS already read *) + ES  Pop(); (* pop 2 words; throw away high-order word *) + DS  Pop(); (* pop 2 words; throw away high-order word *) + FS  Pop(); (* pop 2 words; throw away high-order word *) + GS  Pop(); (* pop 2 words; throw away high-order word *) + IF CS.RPL > CPL + THEN + TempESP  Pop(); + TempSS  Pop(); + SS:ESP  TempSS:TempESP; + FI; + + (* Resume execution in Virtual 8086 mode *) + +TASK-RETURN: + Examine Back Link Selector in TSS addressed by the current task + register: + Must specify global in the local/global bit, else #TS(new TSS + selector); + Index must be within GDT limits, else #TS(new TSS selector); + AR byte must specify TSS, else #TS(new TSS selector); + New TSS must be busy, else #TS(new TSS selector); + TSS must be present, else #NP(new TSS selector); + SWITCH-TASKS without nesting to TSS specified by back link selector; + Mark the task just abandoned as NOT BUSY; + Instruction pointer must be within code segment limit ELSE #GP(0); + +STACK-RETURN: + IF OperandSize=32 + THEN Third word on stack must be within stack limits, else #SS(0); + ELSE Second word on stack must be within stack limits, else #SS(0); + FI; + Return CS selector RPL must be CPL, else #GP(Return selector); + IF return selector RPL = CPL + THEN GOTO RETURN-SAME-LEVEL; + ELSE GOTO RETURN-OUTER-LEVEL; + FI; + +RETURN-SAME-LEVEL: + IF OperandSize=32 + THEN + Top 12 bytes on stack must be within limits, else #SS(0); + Return CS selector (at eSP+4) must be non-null, else #GP(0); + ELSE + Top 6 bytes on stack must be within limits, else #SS(0); + Return CS selector (at eSP+2) must be non-null, else #GP(0); + FI; + Selector index must be within its descriptor table limits, else #GP + (Return selector); + AR byte must indicate code segment, else #GP(Return selector); + IF non-conforming + THEN code segment DPL must = CPL; + ELSE #GP(Return selector); + FI; + IF conforming + THEN code segment DPL must be CPL, else #GP(Return selector); + Segment must be present, else #NP(Return selector); + Instruction pointer must be within code segment boundaries, else #GP(0); + FI; + IF OperandSize=32 + THEN + Load CS:EIP from stack; + Load CS-register with new code segment descriptor; + Load EFLAGS with third doubleword from stack; + Increment eSP by 12; + ELSE + Load CS-register with new code segment descriptor; + Load FLAGS with third word on stack; + Increment eSP by 6; + FI; + +RETURN-OUTER-LEVEL: + IF OperandSize=32 + THEN Top 20 bytes on stack must be within limits, else #SS(0); + ELSE Top 10 bytes on stack must be within limits, else #SS(0); + FI; + Examine return CS selector and associated descriptor: + Selector must be non-null, else #GP(0); + Selector index must be within its descriptor table limits; + ELSE #GP(Return selector); + AR byte must indicate code segment, else #GP(Return selector); + IF non-conforming + THEN code segment DPL must = CS selector RPL; + ELSE #GP(Return selector); + FI; + IF conforming + THEN code segment DPL must be > CPL; + ELSE #GP(Return selector); + FI; + Segment must be present, else #NP(Return selector); + Examine return SS selector and associated descriptor: + Selector must be non-null, else #GP(0); + Selector index must be within its descriptor table limits + ELSE #GP(SS selector); + Selector RPL must equal the RPL of the return CS selector + ELSE #GP(SS selector); + AR byte must indicate a writable data segment, else #GP(SS selector); + Stack segment DPL must equal the RPL of the return CS selector + ELSE #GP(SS selector); + SS must be present, else #NP(SS selector); + + Instruction pointer must be within code segment limit ELSE #GP(0); + IF OperandSize=32 + THEN + Load CS:EIP from stack; + Load EFLAGS with values at (eSP+8); + ELSE + Load CS:IP from stack; + Load FLAGS with values at (eSP+4); + FI; + Load SS:eSP from stack; + Set CPL to the RPL of the return CS selector; + Load the CS register with the CS descriptor; + Load the SS register with the SS descriptor; + FOR each of ES, FS, GS, and DS + DO; + IF the current value of the register is not valid for the outer level; + THEN zero the register and clear the valid flag; + FI; + To be valid, the register setting must satisfy the following + properties: + Selector index must be within descriptor table limits; + AR byte must indicate data or readable code segment; + IF segment is data or non-conforming code, + THEN DPL must be CPL, or DPL must be RPL; + OD; + +Description + +In Real Address Mode, IRET pops the instruction pointer, CS, and the +flags register from the stack and resumes the interrupted routine. + +In Protected Mode, the action of IRET depends on the setting of the +nested task flag (NT) bit in the flag register. When popping the new +flag image from the stack, the IOPL bits in the flag register are changed +only when CPL equals 0. + +If NT equals 0, IRET returns from an interrupt procedure without a +task switch. The code returned to must be equally or less privileged than +the interrupt routine (as indicated by the RPL bits of the CS selector +popped from the stack). If the destination code is less privileged, IRET +also pops the stack pointer and SS from the stack. + +If NT equals 1, IRET reverses the operation of a CALL or INT that +caused a task switch. The updated state of the task executing IRET is +saved in its task state segment. If the task is reentered later, the code +that follows IRET is executed. + +Flags Affected + +All; the flags register is popped from stack + +Protected Mode Exceptions + +#GP, #NP, or #SS, as indicated under "Operation" above + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand being popped lies beyond address +0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, to permit emulation + + +Jcc Jump if Condition is Met + + +Opcode Instruction Clocks Description + +77 cb JA rel8 7+m,3 Jump short if above (CF=0 and + ZF=0) +73 cb JAE rel8 7+m,3 Jump short if above or equal + (CF=0) +72 cb JB rel8 7+m,3 Jump short if below (CF=1) +76 cb JBE rel8 7+m,3 Jump short if below or equal + (CF=1 or ZF=1) +72 cb JC rel8 7+m,3 Jump short if carry (CF=1) +E3 cb JCXZ rel8 9+m,5 Jump short if CX register is 0 +E3 cb JECXZ rel8 9+m,5 Jump short if ECX register is 0 +74 cb JE rel8 7+m,3 Jump short if equal (ZF=1) +74 cb JZ rel8 7+m,3 Jump short if 0 (ZF=1) +7F cb JG rel8 7+m,3 Jump short if greater (ZF=0 and + SF=OF) +7D cb JGE rel8 7+m,3 Jump short if greater or equal + (SF=OF) +7C cb JL rel8 7+m,3 Jump short if less (SF<>OF) +7E cb JLE rel8 7+m,3 Jump short if less or equal + (ZF=1 and SF<>OF) +76 cb JNA rel8 7+m,3 Jump short if not above (CF=1 or + ZF=1) +72 cb JNAE rel8 7+m,3 Jump short if not above or equal + (CF=1) +73 cb JNB rel8 7+m,3 Jump short if not below (CF=0) +77 cb JNBE rel8 7+m,3 Jump short if not below or equal + (CF=0 and ZF=0) +73 cb JNC rel8 7+m,3 Jump short if not carry (CF=0) +75 cb JNE rel8 7+m,3 Jump short if not equal (ZF=0) +7E cb JNG rel8 7+m,3 Jump short if not greater (ZF=1 + or SF<>OF) +7C cb JNGE rel8 7+m,3 Jump short if not greater or + equal (SF<>OF) +7D cb JNL rel8 7+m,3 Jump short if not less (SF=OF) +7F cb JNLE rel8 7+m,3 Jump short if not less or equal + (ZF=0 and SF=OF) +71 cb JNO rel8 7+m,3 Jump short if not overflow + (OF=0) +7B cb JNP rel8 7+m,3 Jump short if not parity (PF=0) +79 cb JNS rel8 7+m,3 Jump short if not sign (SF=0) +75 cb JNZ rel8 7+m,3 Jump short if not zero (ZF=0) +70 cb JO rel8 7+m,3 Jump short if overflow (OF=1) +7A cb JP rel8 7+m,3 Jump short if parity (PF=1) +7A cb JPE rel8 7+m,3 Jump short if parity even (PF=1) +7B cb JPO rel8 7+m,3 Jump short if parity odd (PF=0) +78 cb JS rel8 7+m,3 Jump short if sign (SF=1) +74 cb JZ rel8 7+m,3 Jump short if zero (ZF = 1) +0F 87 cw/cd JA rel16/32 7+m,3 Jump near if above (CF=0 and + ZF=0) +0F 83 cw/cd JAE rel16/32 7+m,3 Jump near if above or equal + (CF=0) +0F 82 cw/cd JB rel16/32 7+m,3 Jump near if below (CF=1) +0F 86 cw/cd JBE rel16/32 7+m,3 Jump near if below or equal + (CF=1 or ZF=1) +0F 82 cw/cd JC rel16/32 7+m,3 Jump near if carry (CF=1) +0F 84 cw/cd JE rel16/32 7+m,3 Jump near if equal (ZF=1) +0F 84 cw/cd JZ rel16/32 7+m,3 Jump near if 0 (ZF=1) +0F 8F cw/cd JG rel16/32 7+m,3 Jump near if greater (ZF=0 and + SF=OF) +0F 8D cw/cd JGE rel16/32 7+m,3 Jump near if greater or equal + (SF=OF) +0F 8C cw/cd JL rel16/32 7+m,3 Jump near if less (SF<>OF) +0F 8E cw/cd JLE rel16/32 7+m,3 Jump near if less or equal (ZF=1 + and SF<>OF) +0F 86 cw/cd JNA rel16/32 7+m,3 Jump near if not above (CF=1 or + ZF=1) +0F 82 cw/cd JNAE rel16/32 7+m,3 Jump near if not above or equal + (CF=1) +0F 83 cw/cd JNB rel16/32 7+m,3 Jump near if not below (CF=0) +0F 87 cw/cd JNBE rel16/32 7+m,3 Jump near if not below or equal + (CF=0 and ZF=0) +0F 83 cw/cd JNC rel16/32 7+m,3 Jump near if not carry (CF=0) +0F 85 cw/cd JNE rel16/32 7+m,3 Jump near if not equal (ZF=0) +0F 8E cw/cd JNG rel16/32 7+m,3 Jump near if not greater (ZF=1 + or SF<>OF) +0F 8C cw/cd JNGE rel16/32 7+m,3 Jump near if not greater or + equal (SF<>OF) +0F 8D cw/cd JNL rel16/32 7+m,3 Jump near if not less (SF=OF) +0F 8F cw/cd JNLE rel16/32 7+m,3 Jump near if not less or equal + (ZF=0 and SF=OF) +0F 81 cw/cd JNO rel16/32 7+m,3 Jump near if not overflow (OF=0) +0F 8B cw/cd JNP rel16/32 7+m,3 Jump near if not parity (PF=0) +0F 89 cw/cd JNS rel16/32 7+m,3 Jump near if not sign (SF=0) +0F 85 cw/cd JNZ rel16/32 7+m,3 Jump near if not zero (ZF=0) +0F 80 cw/cd JO rel16/32 7+m,3 Jump near if overflow (OF=1) +0F 8A cw/cd JP rel16/32 7+m,3 Jump near if parity (PF=1) +0F 8A cw/cd JPE rel16/32 7+m,3 Jump near if parity even (PF=1) +0F 8B cw/cd JPO rel16/32 7+m,3 Jump near if parity odd (PF=0) +0F 88 cw/cd JS rel16/32 7+m,3 Jump near if sign (SF=1) +0F 84 cw/cd JZ rel16/32 7+m,3 Jump near if 0 (ZF=1) + + + +NOTES: + The first clock count is for the true condition (branch taken); the + second clock count is for the false condition (branch not taken). rel16/32 + indicates that these instructions map to two; one with a 16-bit relative + displacement, the other with a 32-bit relative displacement, depending on + the operand-size attribute of the instruction. + + +Operation + +IF condition +THEN + EIP  EIP + SignExtend(rel8/16/32); + IF OperandSize = 16 + THEN EIP  EIP AND 0000FFFFH; + FI; +FI; + +Description + +Conditional jumps (except JCXZ) test the flags which have been set by +a previous instruction. The conditions for each mnemonic are given in +parentheses after each description above. The terms "less" and "greater" +are used for comparisons of signed integers; "above" and "below" are +used for unsigned integers. + +If the given condition is true, a jump is made to the location provided as +the operand. Instruction coding is most efficient when the target for the +conditional jump is in the current code segment and within -128 to ++127 bytes of the next instruction's first byte. The jump can also target +-32768 thru +32767 (segment size attribute 16) or -2^(31) thru +2^(31) -1 +(segment size attribute 32) relative to the next instruction's first byte. +When the target for the conditional jump is in a different segment, use +the opposite case of the jump instruction (i.e., JE and JNE), and then +access the target with an unconditional far jump to the other segment. +For example, you cannot code + +JZ FARLABEL; + +You must instead code + + JNZ BEYOND; + JMP FARLABEL; +BEYOND: + +Because there can be several ways to interpret a particular state of the +flags, ASM386 provides more than one mnemonic for most of the +conditional jump opcodes. For example, if you compared two characters in +AX and want to jump if they are equal, use JE; or, if you ANDed AX +with a bit field mask and only want to jump if the result is 0, use JZ, a +synonym for JE. + +JCXZ differs from other conditional jumps because it tests the contents of +the CX or ECX register for 0, not the flags. JCXZ is useful at the beginning +of a conditional loop that terminates with a conditional loop instruction +(such as LOOPNE TARGET LABEL. The JCXZ prevents entering the loop with CX or +ECX equal to zero, which would cause the loop to execute 64K or 32G times +instead of zero times. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the offset jumped to is beyond the limits of the code segment + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +JMP Jump + + +Opcode Instruction Clocks Description + +EB cb JMP rel8 7+m Jump short +E9 cw JMP rel16 7+m Jump near, displacement relative + to next instruction +FF /4 JMP r/m16 7+m/10+m Jump near indirect +EA cd JMP ptr16:16 12+m,pm=27+m Jump intersegment, 4-byte + immediate address +EA cd JMP ptr16:16 pm=45+m Jump to call gate, same + privilege +EA cd JMP ptr16:16 ts Jump via task state segment +EA cd JMP ptr16:16 ts Jump via task gate +FF /5 JMP m16:16 43+m,pm=31+m Jump r/m16:16 indirect and + intersegment +FF /5 JMP m16:16 pm=49+m Jump to call gate, same + privilege +FF /5 JMP m16:16 5 + ts Jump via task state segment +FF /5 JMP m16:16 5 + ts Jump via task gate +E9 cd JMP rel32 7+m Jump near, displacement relative + to next instruction +FF /4 JMP r/m32 7+m,10+m Jump near, indirect +EA cp JMP ptr16:32 12+m,pm=27+m Jump intersegment, 6-byte + immediate address +EA cp JMP ptr16:32 pm=45+m Jump to call gate, same + privilege +EA cp JMP ptr16:32 ts Jump via task state segment +EA cp JMP ptr16:32 ts Jump via task gate +FF /5 JMP m16:32 43+m,pm=31+m Jump intersegment, address at + r/m dword +FF /5 JMP m16:32 pm=49+m Jump to call gate, same + privilege +FF /5 JMP m16:32 5 + ts Jump via task state segment +FF /5 JMP m16:32 5 + ts Jump via task gate + + + +NOTE: +Values of ts are given by the following table: + + New Task + + 386 TSS 386 TASK 286 TSS + VM = 0 VM = 1 + +Old Task Via Task Gate? + + N Y N Y N Y +386 +TSS VM=0 303 312 220 229 276 285 + +286 +TSS 301 310 218 227 274 283 + + +Operation + +IF instruction = relative JMP + (* i.e. operand is rel8, rel16, or rel32 *) +THEN + EIP  EIP + rel8/16/32; + IF OperandSize = 16 + THEN EIP  EIP AND 0000FFFFH; + FI; +FI; +IF instruction = near indirect JMP + (* i.e. operand is r/m16 or r/m32 *) +THEN + IF OperandSize = 16 + THEN + EIP  [r/m16] AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + EIP  [r/m32]; + FI; +FI; + +IF (PE = 0 OR (PE = 1 AND VM = 1)) (* real mode or V86 mode *) + AND instruction = far JMP + (* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *) +THEN GOTO REAL-OR-V86-MODE; + IF operand type = m16:16 or m16:32 + THEN (* indirect *) + IF OperandSize = 16 + THEN + CS:IP  [m16:16]; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  [m16:32]; + FI; + FI; + IF operand type = ptr16:16 or ptr16:32 + THEN + IF OperandSize = 16 + THEN + CS:IP  ptr16:16; + EIP  EIP AND 0000FFFFH; (* clear upper 16 bits *) + ELSE (* OperandSize = 32 *) + CS:EIP  ptr16:32; + FI; + FI; +FI; + +IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *) + AND instruction = far JMP +THEN + IF operand type = m16:16 or m16:32 + THEN (* indirect *) + check access of EA dword; + #GP(0) or #SS(0) IF limit violation; + FI; + Destination selector is not null ELSE #GP(0) + Destination selector index is within its descriptor table limits ELSE +#GP(selector) + Depending on AR byte of destination descriptor: + GOTO CONFORMING-CODE-SEGMENT; + GOTO NONCONFORMING-CODE-SEGMENT; + GOTO CALL-GATE; + GOTO TASK-GATE; + GOTO TASK-STATE-SEGMENT; + ELSE #GP(selector); (* illegal AR byte in descriptor *) +FI; + +CONFORMING-CODE-SEGMENT: + Descriptor DPL must be CPL ELSE #GP(selector); + Segment must be present ELSE #NP(selector); + Instruction pointer must be within code-segment limit ELSE #GP(0); + IF OperandSize = 32 + THEN Load CS:EIP from destination pointer; + ELSE Load CS:IP from destination pointer; + FI; + Load CS register with new segment descriptor; + +NONCONFORMING-CODE-SEGMENT: + RPL of destination selector must be CPL ELSE #GP(selector); + Descriptor DPL must be = CPL ELSE #GP(selector); + Segment must be present ELSE # NP(selector); + Instruction pointer must be within code-segment limit ELSE #GP(0); + IF OperandSize = 32 + THEN Load CS:EIP from destination pointer; + ELSE Load CS:IP from destination pointer; + FI; + Load CS register with new segment descriptor; + Set RPL field of CS register to CPL; + +CALL-GATE: + Descriptor DPL must be CPL ELSE #GP(gate selector); + Descriptor DPL must be gate selector RPL ELSE #GP(gate selector); + Gate must be present ELSE #NP(gate selector); + Examine selector to code segment given in call gate descriptor: + Selector must not be null ELSE #GP(0); + Selector must be within its descriptor table limits ELSE + #GP(CS selector); + Descriptor AR byte must indicate code segment + ELSE #GP(CS selector); + IF non-conforming + THEN code-segment descriptor, DPL must = CPL + ELSE #GP(CS selector); + FI; + IF conforming + THEN code-segment descriptor DPL must be CPL; + ELSE #GP(CS selector); + Code segment must be present ELSE #NP(CS selector); + Instruction pointer must be within code-segment limit ELSE #GP(0); + IF OperandSize = 32 + THEN Load CS:EIP from call gate; + ELSE Load CS:IP from call gate; + FI; + Load CS register with new code-segment descriptor; + Set RPL of CS to CPL + +TASK-GATE: + Gate descriptor DPL must be CPL ELSE #GP(gate selector); + Gate descriptor DPL must be gate selector RPL ELSE #GP(gate + selector); + Task Gate must be present ELSE #NP(gate selector); + Examine selector to TSS, given in Task Gate descriptor: + Must specify global in the local/global bit ELSE #GP(TSS selector); + Index must be within GDT limits ELSE #GP(TSS selector); + Descriptor AR byte must specify available TSS (bottom bits 00001); + ELSE #GP(TSS selector); + Task State Segment must be present ELSE #NP(TSS selector); +SWITCH-TASKS (without nesting) to TSS; +Instruction pointer must be within code-segment limit ELSE #GP(0); + +TASK-STATE-SEGMENT: + TSS DPL must be CPL ELSE #GP(TSS selector); + TSS DPL must be TSS selector RPL ELSE #GP(TSS selector); + Descriptor AR byte must specify available TSS (bottom bits 00001) + ELSE #GP(TSS selector); + Task State Segment must be present ELSE #NP(TSS selector); + SWITCH-TASKS (without nesting) to TSS; + Instruction pointer must be within code-segment limit ELSE #GP(0); + +Description + +The JMP instruction transfers control to a different point in the +instruction stream without recording return information. + +The action of the various forms of the instruction are shown below. + +Jumps with destinations of type r/m16, r/m32, rel16, and rel32 are near +jumps and do not involve changing the segment register value. + +The JMP rel16 and JMP rel32 forms of the instruction add an offset to +the address of the instruction following the JMP to determine the +destination. The rel16 form is used when the instruction's operand-size +attribute is 16 bits (segment size attribute 16 only); rel32 is used when +the operand-size attribute is 32 bits (segment size attribute 32 only). The +result is stored in the 32-bit EIP register. With rel16, the upper 16 bits +of EIP are cleared, which results in an offset whose value does not exceed +16 bits. + +JMP r/m16 and JMP r/m32 specifies a register or memory location from which +the absolute offset from the procedure is fetched. The offset fetched from +r/m is 32 bits for an operand-size attribute of 32 bits (r/m32), or 16 bits +for an operand-size attribute of 16 bits (r/m16). + +The JMP ptr16:16 and ptr16:32 forms of the instruction use a four-byte +or six-byte operand as a long pointer to the destination. The JMP +and forms fetch the long pointer from the memory location +specified (indirection). In Real Address Mode or Virtual 8086 Mode, +the long pointer provides 16 bits for the CS register and 16 or 32 bits +for the EIP register (depending on the operand-size attribute). In +Protected Mode, both long pointer forms consult the Access Rights (AR) +byte in the descriptor indexed by the selector part of the long pointer. + +Depending on the value of the AR byte, the jump will perform one of +the following types of control transfers: + + A jump to a code segment at the same privilege level + A task switch + +For more information on protected mode control transfers, refer to +Chapter 6 and Chapter 7. + +Flags Affected + +All if a task switch takes place; none if no task switch occurs + +Protected Mode Exceptions + +Far jumps: #GP, #NP, #SS, and #TS, as indicated in the list above. + +Near direct jumps: #GP(0) if procedure location is beyond the code +segment limits. + +Near indirect jumps: #GP(0) for an illegal memory operand effective +address in the CS, DS, ES, FS, or GS segments: #SS(0) for an illegal +address in the SS segment; #GP if the indirect offset obtained is beyond +the code segment limits; #PF(fault-code) for a page fault. + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would be outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as under Real Address Mode; #PF(fault-code) for a +page fault + + +LAHF Load Flags into AH Register + +Opcode Instruction Clocks Description + +9F LAHF 2 Load: AH = flags SF ZF xx AF xx PF xx CF + + +Operation + +AH  SF:ZF:xx:AF:xx:PF:xx:CF; + +Description + +LAHF transfers the low byte of the flags word to AH. The bits, from +MSB to LSB, are sign, zero, indeterminate, auxiliary, carry, +indeterminate, parity, indeterminate, and carry. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +LAR Load Access Rights Byte + +Opcode Instruction Clocks Description + +0F 02 /r LAR r16,r/m16 pm=15/16 r16  r/m16 masked by FF00 +0F 02 /r LAR r32,r/m32 pm=15/16 r32  r/m32 masked by 00FxFF00 + + +Description + +The LAR instruction stores a marked form of the second doubleword of +the descriptor for the source selector if the selector is visible at the +CPL (modified by the selector's RPL) and is a valid descriptor type. The +destination register is loaded with the high-order doubleword of the +descriptor masked by 00FxFF00, and ZF is set to 1. The x indicates that the +four bits corresponding to the upper four bits of the limit are undefined in +the value loaded by LAR. If the selector is invisible or of the wrong type, +ZF is cleared. + +If the 32-bit operand size is specified, the entire 32-bit value is loaded +into the 32-bit destination register. If the 16-bit operand size is +specified, the lower 16-bits of this value are stored in the 16-bit +destination register. + +All code and data segment descriptors are valid for LAR. + +The valid special segment and gate descriptor types for LAR are given +in the following table: + +Type Name Valid/Invalid + + 0 Invalid Invalid + 1 Available 80286 TSS Valid + 2 LDT Valid + 3 Busy 80286 TSS Valid + 4 80286 call gate Valid + 5 80286/80386 task gate Valid + 6 80286 trap gate Valid + 7 80286 interrupt gate Valid + 8 Invalid Invalid + 9 Available 80386 TSS Valid + A Invalid Invalid + B Busy 80386 TSS Valid + C 80386 call gate Valid + D Invalid Invalid + E 80386 trap gate Valid + F 80386 interrupt gate Valid + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; LAR is unrecognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LEA Load Effective Address + +Opcode Instruction Clocks Description + +8D /r LEA r16,m 2 Store effective address for m in register r16 +8D /r LEA r32,m 2 Store effective address for m in register r32 +8D /r LEA r16,m 2 Store effective address for m in register r16 +8D /r LEA r32,m 2 Store effective address for m in register r32 + + +Operation + +IF OperandSize = 16 AND AddressSize = 16 +THEN r16  Addr(m); +ELSE + IF OperandSize = 16 AND AddressSize = 32 + THEN + r16  Truncate_to_16bits(Addr(m)); (* 32-bit address *) + ELSE + IF OperandSize = 32 AND AddressSize = 16 + THEN + r32  Truncate_to_16bits(Addr(m)); + ELSE + IF OperandSize = 32 AND AddressSize = 32 + THEN r32  Addr(m); + FI; + FI; + FI; +FI; + +Description + +LEA calculates the effective address (offset part) and stores it in the +specified register. The operand-size attribute of the instruction +(represented by OperandSize in the algorithm under "Operation" above) is +determined by the chosen register. The address-size attribute (represented +by AddressSize) is determined by the USE attribute of the segment containing +the second operand. The address-size and operand-size attributes affect the +action performed by LEA, as follows: + +Operand Size Address Size Action Performed + + 16 16 16-bit effective address is calculated and + stored in requested 16-bit register + destination. + + 16 32 32-bit effective address is calculated. The + lower 16 bits of the address are stored in + the requested 16-bit register destination. + + 32 16 16-bit effective address is calculated. The + 16-bit address is zero-extended and stored + in the requested 32-bit register destination. + + 32 32 32-bit effective address is calculated and + stored in the requested 32-bit register + destination. + +Flags Affected + +None + +Protected Mode Exceptions + +#UD if the second operand is a register + +Real Address Mode Exceptions + +Interrupt 6 if the second operand is a register + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LEAVE High Level Procedure Exit + +Opcode Instruction Clocks Description + +C9 LEAVE 4 Set SP to BP, then pop BP +C9 LEAVE 4 Set ESP to EBP, then pop EBP + + +Operation + +IF StackAddrSize = 16 +THEN + SP  BP; +ELSE (* StackAddrSize = 32 *) + ESP  EBP; +FI; +IF OperandSize = 16 +THEN + BP  Pop(); +ELSE (* OperandSize = 32 *) + EBP  Pop(); +FI; + +Description + +LEAVE reverses the actions of the ENTER instruction. By copying the +frame pointer to the stack pointer, LEAVE releases the stack space used +by a procedure for its local variables. The old frame pointer is popped +into BP or EBP, restoring the caller's frame. A subsequent RET +instruction removes any arguments pushed onto the stack of the exiting +procedure. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if BP does not point to a location within the limits of the current +stack segment + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LGDT/LIDT Load Global/Interrupt Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 01 /2 LGDT m16&32 11 Load m into GDTR +0F 01 /3 LIDT m16&32 11 Load m into IDTR + + +Operation + +IF instruction = LIDT +THEN + IF OperandSize = 16 + THEN IDTR.Limit:Base  m16:24 (* 24 bits of base loaded *) + ELSE IDTR.Limit:Base  m16:32 + FI; +ELSE (* instruction = LGDT *) + IF OperandSize = 16 + THEN GDTR.Limit:Base  m16:24 (* 24 bits of base loaded *) + ELSE GDTR.Limit:Base  m16:32; + FI; +FI; + +Description + +The LGDT and LIDT instructions load a linear base address and limit +value from a six-byte data operand in memory into the GDTR or IDTR, +respectively. If a 16-bit operand is used with LGDT or LIDT, the +register is loaded with a 16-bit limit and a 24-bit base, and the +high-order eight bits of the six-byte data operand are not used. If a 32-bit +operand is used, a 16-bit limit and a 32-bit base is loaded; the high-order +eight bits of the six-byte operand are used as high-order base address bits. + +The SGDT and SIDT instructions always store into all 48 bits of the +six-byte data operand. With the 80286, the upper eight bits are undefined +after SGDT or SIDT is executed. With the 80386, the upper eight bits +are written with the high-order eight address bits, for both a 16-bit +operand and a 32-bit operand. If LGDT or LIDT is used with a 16-bit +operand to load the register stored by SGDT or SIDT, the upper eight +bits are stored as zeros. + +LGDT and LIDT appear in operating system software; they are not used +in application programs. They are the only instructions that directly load +a linear address (i.e., not a segment relative address) in 80386 Protected +Mode. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0; #UD if the source operand +is a register; #GP(0) for an illegal memory operand effective address in +the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address in +the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH; Interrupt 6 if the source operand is a +register + + +Note: + These instructions are valid in Real Address Mode to allow + power-up initialization for Protected Mode + + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +LGS/LSS/LDS/LES/LFS Load Full Pointer + +Opcode Instruction Clocks Description + +C5 /r LDS r16,m16:16 7,p=22 Load DS:r16 with pointer from memory +C5 /r LDS r32,m16:32 7,p=22 Load DS:r32 with pointer from memory +0F B2 /r LSS r16,m16:16 7,p=22 Load SS:r16 with pointer from memory +0F B2 /r LSS r32,m16:32 7,p=22 Load SS:r32 with pointer from memory +C4 /r LES r16,m16:16 7,p=22 Load ES:r16 with pointer from memory +C4 /r LES r32,m16:32 7,p=22 Load ES:r32 with pointer from memory +0F B4 /r LFS r16,m16:16 7,p=25 Load FS:r16 with pointer from memory +0F B4 /r LFS r32,m16:32 7,p=25 Load FS:r32 with pointer from memory +0F B5 /r LGS r16,m16:16 7,p=25 Load GS:r16 with pointer from memory +0F B5 /r LGS r32,m16:32 7,p=25 Load GS:r32 with pointer from memory + + +Operation + +CASE instruction OF + LSS: Sreg is SS; (* Load SS register *) + LDS: Sreg is DS; (* Load DS register *) + LES: Sreg is ES; (* Load ES register *) + LFS: Sreg is FS; (* Load FS register *) + LGS: Sreg is DS; (* Load GS register *) +ESAC; +IF (OperandSize = 16) +THEN + r16  [Effective Address]; (* 16-bit transfer *) + Sreg  [Effective Address + 2]; (* 16-bit transfer *) + (* In Protected Mode, load the descriptor into the segment register *) +ELSE (* OperandSize = 32 *) + r32  [Effective Address]; (* 32-bit transfer *) + Sreg  [Effective Address + 4]; (* 16-bit transfer *) + (* In Protected Mode, load the descriptor into the segment register *) +FI; + +Description + +These instructions read a full pointer from memory and store it in the +selected segment register:register pair. The full pointer loads 16 bits +into the segment register SS, DS, ES, FS, or GS. The other register loads 32 +bits if the operand-size attribute is 32 bits, or loads 16 bits if the +operand-size attribute is 16 bits. The other 16- or 32-bit register to be +loaded is determined by the r16 or r32 register operand specified. + +When an assignment is made to one of the segment registers, the +descriptor is also loaded into the segment register. The data for the +register is obtained from the descriptor table entry for the selector +given. + +A null selector (values 0000-0003) can be loaded into DS, ES, FS, or +GS registers without causing a protection exception. (Any subsequent +reference to a segment whose corresponding segment register is loaded +with a null selector to address memory causes a #GP(0) exception. No +memory reference to the segment occurs.) + +The following is a listing of the Protected Mode checks and actions taken in +the loading of a segment register: + +IF SS is loaded: + IF selector is null THEN #GP(0); FI; + Selector index must be within its descriptor table limits ELSE + #GP(selector); + Selector's RPL must equal CPL ELSE #GP(selector); + AR byte must indicate a writable data segment ELSE #GP(selector); + DPL in the AR byte must equal CPL ELSE #GP(selector); + Segment must be marked present ELSE #SS(selector); + Load SS with selector; + Load SS with descriptor; +IF DS, ES, FS, or GS is loaded with non-null selector: + Selector index must be within its descriptor table limits ELSE + #GP(selector); + AR byte must indicate data or readable code segment ELSE + #GP(selector); + IF data or nonconforming code + THEN both the RPL and the CPL must be less than or equal to DPL in + AR byte; + ELSE #GP(selector); + Segment must be marked present ELSE #NP(selector); +Load segment register with selector and RPL bits; +Load segment register with descriptor; +IF DS, ES, FS or GS is loaded with a null selector: + Clear descriptor valid bit; + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +the second operand must be a memory operand, not a register; #GP(0) +if a null selector is loaded into SS; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +The second operand must be a memory operand, not a register; Interrupt +13 if any part of the operand would lie outside of the effective address +space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +LLDT Load Local Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 00 /2 LLDT r/m16 20 Load selector r/m16 into LDTR + + +Operation + +LDTR  SRC; + +Description + +LLDT loads the Local Descriptor Table register (LDTR). The word +operand (memory or register) to LLDT should contain a selector to the +Global Descriptor Table (GDT). The GDT entry should be a Local Descriptor +Table. If so, then the LDTR is loaded from the entry. The descriptor +registers DS, ES, SS, FS, GS, and CS are not affected. The LDT field in the +task state segment does not change. + +The selector operand can be 0; if so, the LDTR is marked invalid. All +descriptor references (except by the LAR, VERR, VERW or LSL +instructions) cause a #GP fault. + +LLDT is used in operating system software; it is not used in application +programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0; #GP(selector) if the +selector operand does not point into the Global Descriptor Table, or if the +entry in the GDT is not a Local Descriptor Table; #NP(selector) if the +LDT descriptor is not present; #GP(0) for an illegal memory operand +effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an +illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; LLDT is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode (because the instruction is +not recognized, it will not execute or perform a memory reference) + +Note + +The operand-size attribute has no effect on this instruction. + + +LMSW Load Machine Status Word + +Opcode Instruction Clocks Description + +0F 01 /6 LMSW r/m16 10/13 Load r/m16 in machine status word + + +Operation + +MSW  r/m16; (* 16 bits is stored in the machine status word *) + +Description + +LMSW loads the machine status word (part of CR0) from the source +operand. This instruction can be used to switch to Protected Mode; if so, +it must be followed by an intrasegment jump to flush the instruction +queue. LMSW will not switch back to Real Address Mode. + +LMSW is used only in operating system software. It is not used in +application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + +Notes + +The operand-size attribute has no effect on this instruction. This +instruction is provided for compatibility with the 80286; 80386 programs +should use MOV CR0, ... instead. + + +LOCK Assert LOCK# Signal Prefix + +Opcode Instruction Clocks Description + +F0 LOCK 0 Assert LOCK# signal for the next instruction + + +Description + +The LOCK prefix causes the LOCK# signal of the 80386 to be asserted +during execution of the instruction that follows it. In a multiprocessor +environment, this signal can be used to ensure that the 80386 has +exclusive use of any shared memory while LOCK# is asserted. The +read-modify-write sequence typically used to implement test-and-set on the +80386 is the BTS instruction. + +The LOCK prefix functions only with the following instructions: + +BT, BTS, BTR, BTC mem, reg/imm +XCHG reg, mem +XCHG mem, reg +ADD, OR, ADC, SBB, AND, SUB, XOR mem, reg/imm +NOT, NEG, INC, DEC mem + +An undefined opcode trap will be generated if a LOCK prefix is used +with any instruction not listed above. + +XCHG always asserts LOCK# regardless of the presence or absence of +the LOCK prefix. + +The integrity of the LOCK is not affected by the alignment of the +memory field. Memory locking is observed for arbitrarily misaligned +fields. + +Locked access is not assured if another 80386 processor is executing an +instruction concurrently that has one of the following characteristics: + + Is not preceded by a LOCK prefix + + Is not one of the instructions in the preceding list + + Specifies a memory operand that does not exactly overlap the + destination operand. Locking is not guaranteed for partial overlap, + even if one memory operand is wholly contained within another. + +Flags Affected + +None + +Protected Mode Exceptions + +#UD if LOCK is used with an instruction not listed in the "Description" +section above; other exceptions can be generated by the subsequent +(locked) instruction + +Real Address Mode Exceptions + +Interrupt 6 if LOCK is used with an instruction not listed in the +"Description" section above; exceptions can still be generated by the +subsequent (locked) instruction + +Virtual 8086 Mode Exceptions + +#UD if LOCK is used with an instruction not listed in the "Description" +section above; exceptions can still be generated by the subsequent (locked) +instruction + + +LODS/LODSB/LODSW/LODSD Load String Operand + +Opcode Instruction Clocks Description + +AC LODS m8 5 Load byte [(E)SI] into AL +AD LODS m16 5 Load word [(E)SI] into AX +AD LODS m32 5 Load dword [(E)SI] into EAX +AC LODSB 5 Load byte DS:[(E)SI] into AL +AD LODSW 5 Load word DS:[(E)SI] into AX +AD LODSD 5 Load dword DS:[(E)SI] into EAX + + +Operation + +IF AddressSize = 16 +THEN use SI for source-index +ELSE (* AddressSize = 32 *) + use ESI for source-index; +FI; +IF byte type of instruction +THEN + AL  [source-index]; (* byte load *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + AX  [source-index]; (* word load *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + EAX  [source-index]; (* dword load *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index  source-index + IncDec + +Description + +LODS loads the AL, AX, or EAX register with the memory byte, word, +or doubleword at the location pointed to by the source-index register. +After the transfer is made, the source-index register is automatically +advanced. If the direction flag is 0 (CLD was executed), the source index +increments; if the direction flag is 1 (STD was executed), it decrements. +The increment or decrement is 1 if a byte is loaded, 2 if a word is loaded, +or 4 if a doubleword is loaded. + +If the address-size attribute for this instruction is 16 bits, SI is used +for the source-index register; otherwise the address-size attribute is 32 +bits, and the ESI register is used. The address of the source data is +determined solely by the contents of ESI/SI. Load the correct index value +into SI before executing the LODS instruction. LODSB, LODSW, LODSD are +synonyms for the byte, word, and doubleword LODS instructions. + +LODS can be preceded by the REP prefix; however, LODS is used more typically +within a LOOP construct, because further processing of the data moved into +EAX, AX, or AL is usually necessary. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +LOOP/LOOPcond Loop Control with CX Counter + +Opcode Instruction Clocks Description + +E2 cb LOOP rel8 11+m DEC count; jump short if count <> 0 +E1 cb LOOPE rel8 11+m DEC count; jump short if count <> 0 and ZF=1 +E1 cb LOOPZ rel8 11+m DEC count; jump short if count <> 0 and ZF=1 +E0 cb LOOPNE rel8 11+m DEC count; jump short if count <> 0 and ZF=0 +E0 cb LOOPNZ rel8 11+m DEC count; jump short if count <> 0 and ZF=0 + + +Operation + +IF AddressSize = 16 THEN CountReg is CX ELSE CountReg is ECX; FI; +CountReg  CountReg - 1; +IF instruction <> LOOP +THEN + IF (instruction = LOOPE) OR (instruction = LOOPZ) + THEN BranchCond  (ZF = 1) AND (CountReg <> 0); + FI; + IF (instruction = LOOPNE) OR (instruction = LOOPNZ) + THEN BranchCond  (ZF = 0) AND (CountReg <> 0); + FI; +FI; + +IF BranchCond +THEN + IF OperandSize = 16 + THEN + IP  IP + SignExtend(rel8); + ELSE (* OperandSize = 32 *) + EIP  EIP + SignExtend(rel8); + FI; +FI; + +Description + +LOOP decrements the count register without changing any of the flags. +Conditions are then checked for the form of LOOP being used. If the +conditions are met, a short jump is made to the label given by the operand +to LOOP. If the address-size attribute is 16 bits, the CX register is used +as the count register; otherwise the ECX register is used. The operand +of LOOP must be in the range from 128 (decimal) bytes before the +instruction to 127 bytes ahead of the instruction. + +The LOOP instructions provide iteration control and combine loop index +management with conditional branching. Use the LOOP instruction by +loading an unsigned iteration count into the count register, then code the +LOOP at the end of a series of instructions to be iterated. The +destination of LOOP is a label that points to the beginning of the +iteration. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the offset jumped to is beyond the limits of the current code +segment + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +LSL Load Segment Limit + +Opcode Instruction Clocks Description + +0F 03 /r LSL r16,r/m16 pm=20/21 Load: r16  segment limit, + selector r/m16 (byte granular) +0F 03 /r LSL r32,r/m32 pm=20/21 Load: r32  segment limit, + selector r/m32 (byte granular) +0F 03 /r LSL r16,r/m16 pm=25/26 Load: r16  segment limit, + selector r/m16 (page granular) +0F 03 /r LSL r32,r/m32 pm=25/26 Load: r32  segment limit, + selector r/m32 (page granular) + + +Description + +The LSL instruction loads a register with an unscrambled segment limit, +and sets ZF to 1, provided that the source selector is visible at the CPL +weakened by RPL, and that the descriptor is a type accepted by LSL. +Otherwise, ZF is cleared to 0, and the destination register is unchanged. +The segment limit is loaded as a byte granular value. If the descriptor +has a page granular segment limit, LSL will translate it to a byte limit +before loading it in the destination register (shift left 12 the 20-bit +"raw" limit from descriptor, then OR with 00000FFFH). + +The 32-bit forms of this instruction store the 32-bit byte granular limit +in the 16-bit destination register. + +Code and data segment descriptors are valid for LSL. + +The valid special segment and gate descriptor types for LSL are given +in the following table: + +Type Name Valid/Invalid + + 0 Invalid Invalid + 1 Available 80286 TSS Valid + 2 LDT Valid + 3 Busy 80286 TSS Valid + 4 80286 call gate Invalid + 5 80286/80386 task gate Invalid + 6 80286 trap gate Invalid + 7 80286 interrupt gate Invalid + 8 Invalid Valid + 9 Available 80386 TSS Valid + A Invalid Invalid + B Busy 80386 TSS Valid + C 80386 call gate Invalid + D Invalid Invalid + E 80386 trap gate Invalid + F 80386 interrupt gate Invalid + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; LSL is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + + +LTR Load Task Register + +Opcode Instruction Clocks Description + +0F 00 /3 LTR r/m16 pm=23/27 Load EA word into task register + + +Description + +LTR loads the task register from the source register or memory location +specified by the operand. The loaded task state segment is marked busy. +A task switch does not occur. + +LTR is used only in operating system software; it is not used in +application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#GP(0) if the current privilege level is not 0; #GP(selector) if the object +named by the source selector is not a TSS or is already busy; +#NP(selector) if the TSS is marked "not present"; #PF(fault-code) for +a page fault + +Real Address Mode Exceptions + +Interrupt 6; LTR is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + +Notes + +The operand-size attribute has no effect on this instruction. + + +MOV Move Data + + +Opcode Instruction Clocks Description + +88 /r MOV r/m8,r8 2/2 Move byte register to r/m byte +89 /r MOV r/m16,r16 2/2 Move word register to r/m word +89 /r MOV r/m32,r32 2/2 Move dword register to r/m dword +8A /r MOV r8,r/m8 2/4 Move r/m byte to byte register +8B /r MOV r16,r/m16 2/4 Move r/m word to word register +8B /r MOV r32,r/m32 2/4 Move r/m dword to dword register +8C /r MOV r/m16,Sreg 2/2 Move segment register to r/m word +8D /r MOV Sreg,r/m16 2/5,pm=18/19 Move r/m word to segment register +A0 MOV AL,moffs8 4 Move byte at (seg:offset) to AL +A1 MOV AX,moffs16 4 Move word at (seg:offset) to AX +A1 MOV EAX,moffs32 4 Move dword at (seg:offset) to EAX +A2 MOV moffs8,AL 2 Move AL to (seg:offset) +A3 MOV moffs16,AX 2 Move AX to (seg:offset) +A3 MOV moffs32,EAX 2 Move EAX to (seg:offset) +B0 + rb MOV reg8,imm8 2 Move immediate byte to register +B8 + rw MOV reg16,imm16 2 Move immediate word to register +B8 + rd MOV reg32,imm32 2 Move immediate dword to register +C6 MOV r/m8,imm8 2/2 Move immediate byte to r/m byte +C7 MOV r/m16,imm16 2/2 Move immediate word to r/m word +C7 MOV r/m32,imm32 2/2 Move immediate dword to r/m dword + + + +NOTES: + moffs8, moffs16, and moffs32 all consist of a simple offset relative + to the segment base. The 8, 16, and 32 refer to the size of the data. The + address-size attribute of the instruction determines the size of the + offset, either 16 or 32 bits. + + +Operation + +DEST  SRC; + +Description + +MOV copies the second operand to the first operand. + +If the destination operand is a segment register (DS, ES, SS, etc.), then +data from a descriptor is also loaded into the register. The data for the +register is obtained from the descriptor table entry for the selector +given. A null selector (values 0000-0003) can be loaded into DS and ES +registers without causing an exception; however, use of DS or ES causes a +#GP(0), and no memory reference occurs. + +A MOV into SS inhibits all interrupts until after the execution of the +next instruction (which is presumably a MOV into eSP). + +Loading a segment register under 80386 Protected Mode results in special +checks and actions, as described in the following listing: + +IF SS is loaded; +THEN + IF selector is null THEN #GP(0); +FI; + Selector index must be within its descriptor table limits else + #GP(selector); + Selector's RPL must equal CPL else #GP(selector); +AR byte must indicate a writable data segment else #GP(selector); + DPL in the AR byte must equal CPL else #GP(selector); + Segment must be marked present else #SS(selector); + Load SS with selector; + Load SS with descriptor. +FI; +IF DS, ES, FS or GS is loaded with non-null selector; +THEN + Selector index must be within its descriptor table limits + else #GP(selector); + AR byte must indicate data or readable code segment else + #GP(selector); + IF data or nonconforming code segment + THEN both the RPL and the CPL must be less than or equal to DPL in + AR byte; + ELSE #GP(selector); + FI; + Segment must be marked present else #NP(selector); + Load segment register with selector; + Load segment register with descriptor; +FI; +IF DS, ES, FS or GS is loaded with a null selector; +THEN + Load segment register with selector; + Clear descriptor valid bit; +FI; + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #SS, and #NP if a segment register is being loaded; otherwise, +#GP(0) if the destination is in a nonwritable segment; #GP(0) for an +illegal memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MOV Move to/from Special Registers + +Opcode Instruction Clocks Description + +0F 20 /r MOV r32,CR0/CR2/CR3 6 Move (control register) to + (register) +0F 22 /r MOV CR0/CR2/CR3,r32 10/4/5 Move (register) to (control + register) +0F 21 /r MOV r32,DR0 -- 3 22 Move (debug register) to + (register) +0F 21 /r MOV r32,DR6/DR7 14 Move (debug register) to + (register) +0F 23 /r MOV DR0 -- 3,r32 22 Move (register) to (debug + register) +0F 23 /r MOV DR6/DR7,r32 16 Move (register) to (debug + register) +0F 24 /r MOV r32,TR6/TR7 12 Move (test register) to + (register) +0F 26 /r MOV TR6/TR7,r32 12 Move (register) to (test + register) + + +Operation + +DEST  SRC; + +Description + +The above forms of MOV store or load the following special registers in +or from a general purpose register: + + Control registers CR0, CR2, and CR3 + Debug Registers DR0, DR1, DR2, DR3, DR6, and DR7 + Test Registers TR6 and TR7 + +32-bit operands are always used with these instructions, regardless of the +operand-size attribute. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF are undefined + +Protected Mode Exceptions + +#GP(0) if the current privilege level is not 0 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) if instruction execution is attempted + +Notes + +The instructions must be executed at privilege level 0 or in real-address +mode; otherwise, a protection exception will be raised. + +The reg field within the ModRM byte specifies which of the special +registers in each category is involved. The two bits in the field are +always 11. The r/m field specifies the general register involved. + + +MOVS/MOVSB/MOVSW/MOVSD Move Data from String to String + +Opcode Instruction Clocks Description + +A4 MOVS m8,m8 7 Move byte [(E)SI] to ES:[(E)DI] +A5 MOVS m16,m16 7 Move word [(E)SI] to ES:[(E)DI] +A5 MOVS m32,m32 7 Move dword [(E)SI] to ES:[(E)DI] +A4 MOVSB 7 Move byte DS:[(E)SI] to ES:[(E)DI] +A5 MOVSW 7 Move word DS:[(E)SI] to ES:[(E)DI] +A5 MOVSD 7 Move dword DS:[(E)SI] to ES:[(E)DI] + + +Operation + +IF (instruction = MOVSD) OR (instruction has doubleword operands) +THEN OperandSize  32; +ELSE OperandSize  16; +IF AddressSize = 16 +THEN use SI for source-index and DI for destination-index; +ELSE (* AddressSize = 32 *) + use ESI for source-index and EDI for destination-index; +FI; +IF byte type of instruction +THEN + [destination-index]  [source-index]; (* byte assignment *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + [destination-index]  [source-index]; (* word assignment *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + [destination-index]  [source-index]; (* doubleword assignment *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index  source-index + IncDec; +destination-index  destination-index + IncDec; + +Description + +MOVS copies the byte or word at [(E)SI] to the byte or word at +ES:[(E)DI]. The destination operand must be addressable from the ES +register; no segment override is possible for the destination. A segment +override can be used for the source operand; the default is DS. + +The addresses of the source and destination are determined solely by the +contents of (E)SI and (E)DI. Load the correct index values into (E)SI +and (E)DI before executing the MOVS instruction. MOVSB, MOVSW, +and MOVSD are synonyms for the byte, word, and doubleword MOVS +instructions. + +After the data is moved, both (E)SI and (E)DI are advanced +automatically. If the direction flag is 0 (CLD was executed), the registers +are incremented; if the direction flag is 1 (STD was executed), the +registers are decremented. The registers are incremented or decremented by 1 +if a byte was moved, 2 if a word was moved, or 4 if a doubleword was moved. + +MOVS can be preceded by the REP prefix for block movement of CX +bytes or words. Refer to the REP instruction for details of this operation. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MOVSX Move with Sign-Extend + +Opcode Instruction Clocks Description + +0F BE /r MOVSX r16,r/m8 3/6 Move byte to word with sign-extend +0F BE /r MOVSX r32,r/m8 3/6 Move byte to dword, sign-extend +0F BF /r MOVSX r32,r/m16 3/6 Move word to dword, sign-extend + + +Operation + +DEST  SignExtend(SRC); + +Description + +MOVSX reads the contents of the effective address or register as a byte +or a word, sign-extends the value to the operand-size attribute of the +instruction (16 or 32 bits), and stores the result in the destination +register. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MOVZX Move with Zero-Extend + +Opcode Instruction Clocks Description + +0F B6 /r MOVZX r16,r/m8 3/6 Move byte to word with zero-extend +0F B6 /r MOVZX r32,r/m8 3/6 Move byte to dword, zero-extend +0F B7 /r MOVZX r32,r/m16 3/6 Move word to dword, zero-extend + + +Operation + +DEST  ZeroExtend(SRC); + +Description + +MOVZX reads the contents of the effective address or register as a byte +or a word, zero extends the value to the operand-size attribute of the +instruction (16 or 32 bits), and stores the result in the destination +register. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +MUL Unsigned Multiplication of AL or AX + +Opcode Instruction Clocks Description + +F6 /4 MUL AL,r/m8 9-14/12-17 Unsigned multiply (AX  AL * r/m byte) +F7 /4 MUL AX,r/m16 9-22/12-25 Unsigned multiply (DX:AX  AX * r/m + word) +F7 /4 MUL EAX,r/m32 9-38/12-41 Unsigned multiply (EDX:EAX  EAX * r/m + dword) + + + +NOTES: + The 80386 uses an early-out multiply algorithm. The actual number of + clocks depends on the position of the most significant bit in the + optimizing multiplier, shown underlined above. The optimization occurs + for positive and negative multiplier values. Because of the early-out + algorithm, clock counts given are minimum to maximum. To calculate the + actual clocks, use the following formula: + + Actual clock = if <> 0 then max(ceiling(log{2} m), 3) + 6 clocks; + + Actual clock = if = 0 then 9 clocks + + where m is the multiplier. + + +Operation + +IF byte-size operation +THEN AX  AL * r/m8 +ELSE (* word or doubleword operation *) + IF OperandSize = 16 + THEN DX:AX  AX * r/m16 + ELSE (* OperandSize = 32 *) + EDX:EAX  EAX * r/m32 + FI; +FI; + +Description + +MUL performs unsigned multiplication. Its actions depend on the size +of its operand, as follows: + + A byte operand is multiplied by AL; the result is left in AX. The + carry and overflow flags are set to 0 if AH is 0; otherwise, they are + set to 1. + + A word operand is multiplied by AX; the result is left in DX:AX. + DX contains the high-order 16 bits of the product. The carry and + overflow flags are set to 0 if DX is 0; otherwise, they are set to 1. + + A doubleword operand is multiplied by EAX and the result is left in + EDX:EAX. EDX contains the high-order 32 bits of the product. The + carry and overflow flags are set to 0 if EDX is 0; otherwise, they are + set to 1. + +Flags Affected + +OF and CF as described above; SF, ZF, AF, PF, and CF are undefined + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +NEG Two's Complement Negation + +Opcode Instruction Clocks Description + +F6 /3 NEG r/m8 2/6 Two's complement negate r/m byte +F7 /3 NEG r/m16 2/6 Two's complement negate r/m word +F7 /3 NEG r/m32 2/6 Two's complement negate r/m dword + + +Operation + +IF r/m = 0 THEN CF  0 ELSE CF  1; FI; +r/m  - r/m; + +Description + +NEG replaces the value of a register or memory operand with its two's +complement. The operand is subtracted from zero, and the result is placed +in the operand. + +The carry flag is set to 1, unless the operand is zero, in which case the +carry flag is cleared to 0. + +Flags Affected + +CF as described above; OF, SF, ZF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +NOP No Operation + +Opcode Instruction Clocks Description + +90 NOP 3 No operation + + +Description + +NOP performs no operation. NOP is a one-byte instruction that takes +up space but affects none of the machine context except (E)IP. + +NOP is an alias mnemonic for the XCHG (E)AX, (E)AX instruction. + +Flags Affected + +None + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +NOT One's Complement Negation + +Opcode Instruction Clocks Description + +F6 /2 NOT r/m8 2/6 Reverse each bit of r/m byte +F7 /2 NOT r/m16 2/6 Reverse each bit of r/m word +F7 /2 NOT r/m32 2/6 Reverse each bit of r/m dword + + +Operation + +r/m  NOT r/m; + +Description + +NOT inverts the operand; every 1 becomes a 0, and vice versa. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +OR Logical Inclusive OR + +Opcode Instruction Clocks Description + +0C ib OR AL,imm8 2 OR immediate byte to AL +0D iw OR AX,imm16 2 OR immediate word to AX +0D id OR EAX,imm32 2 OR immediate dword to EAX +80 /1 ib OR r/m8,imm8 2/7 OR immediate byte to r/m byte +81 /1 iw OR r/m16,imm16 2/7 OR immediate word to r/m word +81 /1 id OR r/m32,imm32 2/7 OR immediate dword to r/m dword +83 /1 ib OR r/m16,imm8 2/7 OR sign-extended immediate byte + with r/m word +83 /1 ib OR r/m32,imm8 2/7 OR sign-extended immediate byte + with r/m dword +08 /r OR r/m8,r8 2/6 OR byte register to r/m byte +09 /r OR r/m16,r16 2/6 OR word register to r/m word +09 /r OR r/m32,r32 2/6 OR dword register to r/m dword +0A /r OR r8,r/m8 2/7 OR byte register to r/m byte +0B /r OR r16,r/m16 2/7 OR word register to r/m word +0B /r OR r32,r/m32 2/7 OR dword register to r/m dword + + +Operation + +DEST  DEST OR SRC; +CF  0; +OF  0 + +Description + +OR computes the inclusive OR of its two operands and places the result +in the first operand. Each bit of the result is 0 if both corresponding +bits of the operands are 0; otherwise, each bit is 1. + +Flags Affected + +OF  0, CF  0; SF, ZF, and PF as described in Appendix C; AF is +undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +OUT Output to Port + +Opcode Instruction Clocks Description + +E6 ib OUT imm8,AL 10,pm=4*/24** Output byte AL to immediate port + number +E7 ib OUT imm8,AX 10,pm=4*/24** Output word AL to immediate port + number +E7 ib OUT imm8,EAX 10,pm=4*/24** Output dword AL to immediate + port number +EE OUT DX,AL 11,pm=5*/25** Output byte AL to port number in +DX +EF OUT DX,AX 11,pm=5*/25** Output word AL to port number in +DX +EF OUT DX,EAX 11,pm=5*/25** Output dword AL to port number + in DX + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (DEST, width(DEST)) + THEN #GP(0); + FI; +FI; +[DEST]  SRC; (* I/O address space used *) + +Description + +OUT transfers a data byte or data word from the register (AL, AX, or +EAX) given as the second operand to the output port numbered by the +first operand. Output to any port from 0 to 65535 is performed by placing +the port number in the DX register and then using an OUT instruction +with DX as the first operand. If the instruction contains an eight-bit port +ID, that value is zero-extended to 16 bits. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the current privilege level is higher (has less privilege) than +IOPL and any of the corresponding I/O permission bits in TSS equals 1 + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1 + + +OUTS/OUTSB/OUTSW/OUTSD Output String to Port + +Opcode Instruction Clocks Description + +6E OUTS DX,r/m8 14,pm=8*/28** Output byte [(E)SI] to port in DX +6F OUTS DX,r/m16 14,pm=8*/28** Output word [(E)SI] to port in DX +6F OUTS DX,r/m32 14,pm=8*/28** Output dword [(E)SI] to port in DX +6E OUTSB 14,pm=8*/28** Output byte DS:[(E)SI] to port in + DX +6F OUTSW 14,pm=8*/28** Output word DS:[(E)SI] to port in + DX +6F OUTSD 14,pm=8*/28** Output dword DS:[(E)SI] to port in + DX + + + +NOTES: + *If CPL IOPL + **If CPL > IOPL or if in virtual 8086 mode + + +Operation + +IF AddressSize = 16 +THEN use SI for source-index; +ELSE (* AddressSize = 32 *) + use ESI for source-index; +FI; + +IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) +THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) + IF NOT I-O-Permission (DEST, width(DEST)) + THEN #GP(0); + FI; +FI; +IF byte type of instruction +THEN + [DX]  [source-index]; (* Write byte at DX I/O address *) + IF DF = 0 THEN IncDec  1 ELSE IncDec  -1; FI; +FI; +IF OperandSize = 16 +THEN + [DX]  [source-index]; (* Write word at DX I/O address *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; +FI; +IF OperandSize = 32 +THEN + [DX]  [source-index]; (* Write dword at DX I/O address *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +source-index  source-index + IncDec; + +Description + +OUTS transfers data from the memory byte, word, or doubleword at the +source-index register to the output port addressed by the DX register. If +the address-size attribute for this instruction is 16 bits, SI is used for +the source-index register; otherwise, the address-size attribute is 32 bits, +and ESI is used for the source-index register. + +OUTS does not allow specification of the port number as an immediate value. +The port must be addressed through the DX register value. Load the correct +value into DX before executing the OUTS instruction. + +The address of the source data is determined by the contents of +source-index register. Load the correct index value into SI or ESI before +executing the OUTS instruction. + +After the transfer, source-index register is advanced automatically. If +the direction flag is 0 (CLD was executed), the source-index register is +incremented; if the direction flag is 1 (STD was executed), it is +decremented. The amount of the increment or decrement is 1 if a byte is +output, 2 if a word is output, or 4 if a doubleword is output. + +OUTSB, OUTSW, and OUTSD are synonyms for the byte, word, and +doubleword OUTS instructions. OUTS can be preceded by the REP +prefix for block output of CX bytes or words. Refer to the REP +instruction for details on this operation. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if CPL is greater than IOPL and any of the corresponding I/O +permission bits in TSS equals 1; #GP(0) for an illegal memory operand +effective address in the CS, DS, or ES segments; #SS(0) for an illegal +address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if any of the corresponding I/O permission bits in TSS +equals 1; #PF(fault-code) for a page fault + + +POP Pop a Word from the Stack + +Opcode Instruction Clocks Description + +8F /0 POP m16 5 Pop top of stack into memory word +8F /0 POP m32 5 Pop top of stack into memory dword +58 + rw POP r16 4 Pop top of stack into word register +58 + rd POP r32 4 Pop top of stack into dword register +1F POP DS 7,pm=21 Pop top of stack into DS +07 POP ES 7,pm=21 Pop top of stack into ES +17 POP SS 7,pm=21 Pop top of stack into SS +0F A1 POP FS 7,pm=21 Pop top of stack into FS +0F A9 POP GS 7,pm=21 Pop top of stack into GS + + +Operation + +IF StackAddrSize = 16 +THEN + IF OperandSize = 16 + THEN + DEST  (SS:SP); (* copy a word *) + SP  SP + 2; + ELSE (* OperandSize = 32 *) + DEST  (SS:SP); (* copy a dword *) + SP  SP + 4; + FI; +ELSE (* StackAddrSize = 32 * ) + IF OperandSize = 16 + THEN + DEST  (SS:ESP); (* copy a word *) + ESP  ESP + 2; + ELSE (* OperandSize = 32 *) + DEST  (SS:ESP); (* copy a dword *) + ESP  ESP + 4; + FI; +FI; + +Description + +POP replaces the previous contents of the memory, the register, or the +segment register operand with the word on the top of the 80386 stack, +addressed by SS:SP (address-size attribute of 16 bits) or SS:ESP +(addresssize attribute of 32 bits). The stack pointer SP is incremented +by 2 for an operand-size of 16 bits or by 4 for an operand-size of 32 bits. +It then points to the new top of stack. + +POP CS is not an 80386 instruction. Popping from the stack into the CS +register is accomplished with a RET instruction. + +If the destination operand is a segment register (DS, ES, FS, GS, or +SS), the value popped must be a selector. In protected mode, loading the +selector initiates automatic loading of the descriptor information +associated with that selector into the hidden part of the segment register; +loading also initiates validation of both the selector and the descriptor +information. + +A null value (0000-0003) may be popped into the DS, ES, FS, or GS +register without causing a protection exception. An attempt to reference +a segment whose corresponding segment register is loaded with a null +value causes a #GP(0) exception. No memory reference occurs. The saved +value of the segment register is null. + +A POP SS instruction inhibits all interrupts, including NMI, until after +execution of the next instruction. This allows sequential execution of POP +SS and POP eSP instructions without danger of having an invalid stack +during an interrupt. However, use of the LSS instruction is the preferred +method of loading the SS and eSP registers. + +Loading a segment register while in protected mode results in special +checks and actions, as described in the following listing: + +IF SS is loaded: + IF selector is null THEN #GP(0); + Selector index must be within its descriptor table limits ELSE + #GP(selector); + Selector's RPL must equal CPL ELSE #GP(selector); + AR byte must indicate a writable data segment ELSE #GP(selector); + DPL in the AR byte must equal CPL ELSE #GP(selector); + Segment must be marked present ELSE #SS(selector); + Load SS register with selector; + Load SS register with descriptor; + +IF DS, ES, FS or GS is loaded with non-null selector: + AR byte must indicate data or readable code segment ELSE + #GP(selector); + IF data or nonconforming code + THEN both the RPL and the CPL must be less than or equal to DPL in + AR byte + ELSE #GP(selector); + FI; + Segment must be marked present ELSE #NP(selector); + Load segment register with selector; + Load segment register with descriptor; + +IF DS, ES, FS, or GS is loaded with a null selector: + Load segment register with selector + Clear valid bit in invisible portion of register + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #SS, and #NP if a segment register is being loaded; #SS(0) if the +current top of stack is not within the stack segment; #GP(0) if the result +is in a nonwritable segment; #GP(0) for an illegal memory operand +effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an +illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +POPA/POPAD Pop all General Registers + +Opcode Instruction Clocks Description + +61 POPA 24 Pop DI, SI, BP, SP, BX, DX, CX, and AX +61 POPAD 24 Pop EDI, ESI, EBP, ESP, EDX, ECX, and EAX + + +Operation + +IF OperandSize = 16 (* instruction = POPA *) +THEN + DI  Pop(); + SI  Pop(); + BP  Pop(); + throwaway  Pop (); (* Skip SP *) + BX  Pop(); + DX  Pop(); + CX  Pop(); + AX  Pop(); +ELSE (* OperandSize = 32, instruction = POPAD *) + EDI  Pop(); + ESI  Pop(); + EBP  Pop(); + throwaway  Pop (); (* Skip ESP *) + EBX  Pop(); + EDX  Pop(); + ECX  Pop(); + EAX  Pop(); +FI; + +Description + +POPA pops the eight 16-bit general registers. However, the SP value is +discarded instead of loaded into SP. POPA reverses a previous PUSHA, +restoring the general registers to their values before PUSHA was +executed. The first register popped is DI. + +POPAD pops the eight 32-bit general registers. The ESP value is +discarded instead of loaded into ESP. POPAD reverses the previous +PUSHAD, restoring the general registers to their values before PUSHAD +was executed. The first register popped is EDI. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the starting or ending stack address is not within the stack +segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +POPF/POPFD Pop Stack into FLAGS or EFLAGS Register + +Opcode Instruction Clocks Description + +9D POPF 5 Pop top of stack FLAGS +9D POPFD 5 Pop top of stack into EFLAGS + + +Operation + +Flags  Pop(); + +Description + +POPF/POPFD pops the word or doubleword on the top of the stack and +stores the value in the flags register. If the operand-size attribute of +the instruction is 16 bits, then a word is popped and the value is stored in +FLAGS. If the operand-size attribute is 32 bits, then a doubleword is popped +and the value is stored in EFLAGS. + +Refer to Chapter 2 and Chapter 4 for information about the FLAGS +and EFLAGS registers. Note that bits 16 and 17 of EFLAGS, called +VM and RF, respectively, are not affected by POPF or POPFD. + +The I/O privilege level is altered only when executing at privilege level +0. The interrupt flag is altered only when executing at a level at least as +privileged as the I/O privilege level. (Real-address mode is equivalent to +privilege level 0.) If a POPF instruction is executed with insufficient +privilege, an exception does not occur, but the privileged bits do not +change. + +Flags Affected + +All flags except VM and RF + +Protected Mode Exceptions + +#SS(0) if the top of stack is not within the stack segment + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, to permit emulation + + +PUSH Push Operand onto the Stack + +Opcode Instruction Clocks Description + +FF /6 PUSH m16 5 Push memory word +FF /6 PUSH m32 5 Push memory dword +50 + /r PUSH r16 2 Push register word +50 + /r PUSH r32 2 Push register dword +6A PUSH imm8 2 Push immediate byte +68 PUSH imm16 2 Push immediate word +68 PUSH imm32 2 Push immediate dword +0E PUSH CS 2 Push CS +16 PUSH SS 2 Push SS +1E PUSH DS 2 Push DS +06 PUSH ES 2 Push ES +0F A0 PUSH FS 2 Push FS +OF A8 PUSH GS 2 Push GS + + +Operation + +IF StackAddrSize = 16 +THEN + IF OperandSize = 16 THEN + SP  SP - 2; + (SS:SP)  (SOURCE); (* word assignment *) + ELSE + SP  SP - 4; + (SS:SP)  (SOURCE); (* dword assignment *) + FI; +ELSE (* StackAddrSize = 32 *) + IF OperandSize = 16 + THEN + ESP  ESP - 2; + (SS:ESP)  (SOURCE); (* word assignment *) + ELSE + ESP  ESP - 4; + (SS:ESP)  (SOURCE); (* dword assignment *) + FI; +FI; + +Description + +PUSH decrements the stack pointer by 2 if the operand-size attribute of +the instruction is 16 bits; otherwise, it decrements the stack pointer by +4. PUSH then places the operand on the new top of stack, which is +pointed to by the stack pointer. + +The 80386 PUSH eSP instruction pushes the value of eSP as it existed +before the instruction. This differs from the 8086, where PUSH SP +pushes the new value (decremented by 2). + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the new value of SP or ESP is outside the stack segment limit; +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +None; if SP or ESP is 1, the 80386 shuts down due to a lack of stack +space + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +PUSHA/PUSHAD Push all General Registers + +Opcode Instruction Clocks Description + +60 PUSHA 18 Push AX, CX, DX, BX, original SP, BP, SI, and + DI +60 PUSHAD 18 Push EAX, ECX, EDX, EBX, original ESP, EBP, + ESI, and EDI + + +Operation + +IF OperandSize = 16 (* PUSHA instruction *) +THEN + Temp  (SP); + Push(AX); + Push(CX); + Push(DX); + Push(BX); + Push(Temp); + Push(BP); + Push(SI); + Push(DI); +ELSE (* OperandSize = 32, PUSHAD instruction *) + Temp  (ESP); + Push(EAX); + Push(ECX); + Push(EDX); + Push(EBX); + Push(Temp); + Push(EBP); + Push(ESI); + Push(EDI); +FI; + +Description + +PUSHA and PUSHAD save the 16-bit or 32-bit general registers, +respectively, on the 80386 stack. PUSHA decrements the stack pointer +(SP) by 16 to hold the eight word values. PUSHAD decrements the +stack pointer (ESP) by 32 to hold the eight doubleword values. Because +the registers are pushed onto the stack in the order in which they were +given, they appear in the 16 or 32 new stack bytes in reverse order. The +last register pushed is DI or EDI. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the starting or ending stack address is outside the stack segment +limit; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Before executing PUSHA or PUSHAD, the 80386 shuts down if SP or +ESP equals 1, 3, or 5; if SP or ESP equals 7, 9, 11, 13, or 15, exception +13 occurs + +Virtual 8086 Mode Exceptions + +Same exceptions as in real-address mode; #PF(fault-code) for a page +fault + + +PUSHF/PUSHFD Push Flags Register onto the Stack + +Opcode Instruction Clocks Description + +9C PUSHF 4 Push FLAGS +9C PUSHFD 4 Push EFLAGS + + +Operation + +IF OperandSize = 32 +THEN push(EFLAGS); +ELSE push(FLAGS); +FI; + +Description + +PUSHF decrements the stack pointer by 2 and copies the FLAGS +register to the new top of stack; PUSHFD decrements the stack pointer by +4, and the 80386 EFLAGS register is copied to the new top of stack +which is pointed to by SS:eSP. Refer to Chapter 2 and Chapter 4 for +information on the EFLAGS register. + +Flags Affected + +None + +Protected Mode Exceptions + +#SS(0) if the new value of eSP is outside the stack segment boundaries + +Real Address Mode Exceptions + +None; the 80386 shuts down due to a lack of stack space + +Virtual 8086 Mode Exceptions + +#GP(0) fault if IOPL is less than 3, to permit emulation + + +RCL/RCR/ROL/ROR Rotate + + +Opcode Instruction Clocks Description + +D0 /2 RCL r/m8,1 9/10 Rotate 9 bits (CF,r/m byte) left + once +D2 /2 RCL r/m8,CL 9/10 Rotate 9 bits (CF,r/m byte) left CL + times +C0 /2 ib RCL r/m8,imm8 9/10 Rotate 9 bits (CF,r/m byte) left + imm8 times +D1 /2 RCL r/m16,1 9/10 Rotate 17 bits (CF,r/m word) left + once +D3 /2 RCL r/m16,CL 9/10 Rotate 17 bits (CF,r/m word) left + CL times +C1 /2 ib RCL r/m16,imm8 9/10 Rotate 17 bits (CF,r/m word) left + imm8 times +D1 /2 RCL r/m32,1 9/10 Rotate 33 bits (CF,r/m dword) left + once +D3 /2 RCL r/m32,CL 9/10 Rotate 33 bits (CF,r/m dword) left + CL times +C1 /2 ib RCL r/m32,imm8 9/10 Rotate 33 bits (CF,r/m dword) left + imm8 times +D0 /3 RCR r/m8,1 9/10 Rotate 9 bits (CF,r/m byte) right + once +D2 /3 RCR r/m8,CL 9/10 Rotate 9 bits (CF,r/m byte) right + CL times +C0 /3 ib RCR r/m8,imm8 9/10 Rotate 9 bits (CF,r/m byte) right + imm8 times +D1 /3 RCR r/m16,1 9/10 Rotate 17 bits (CF,r/m word) right + once +D3 /3 RCR r/m16,CL 9/10 Rotate 17 bits (CF,r/m word) right + CL times +C1 /3 ib RCR r/m16,imm8 9/10 Rotate 17 bits (CF,r/m word) right + imm8 times +D1 /3 RCR r/m32,1 9/10 Rotate 33 bits (CF,r/m dword) right + once +D3 /3 RCR r/m32,CL 9/10 Rotate 33 bits (CF,r/m dword) right + CL times +C1 /3 ib RCR r/m32,imm8 9/10 Rotate 33 bits (CF,r/m dword) right + imm8 times +D0 /0 ROL r/m8,1 3/7 Rotate 8 bits r/m byte left once +D2 /0 ROL r/m8,CL 3/7 Rotate 8 bits r/m byte left CL + times +C0 /0 ib ROL r/m8,imm8 3/7 Rotate 8 bits r/m byte left imm8 + times +D1 /0 ROL r/m16,1 3/7 Rotate 16 bits r/m word left once +D3 /0 ROL r/m16,CL 3/7 Rotate 16 bits r/m word left CL + times +C1 /0 ib ROL r/m16,imm8 3/7 Rotate 16 bits r/m word left imm8 + times +D1 /0 ROL r/m32,1 3/7 Rotate 32 bits r/m dword left once +D3 /0 ROL r/m32,CL 3/7 Rotate 32 bits r/m dword left CL + times +C1 /0 ib ROL r/m32,imm8 3/7 Rotate 32 bits r/m dword left imm8 + times +D0 /1 ROR r/m8,1 3/7 Rotate 8 bits r/m byte right once +D2 /1 ROR r/m8,CL 3/7 Rotate 8 bits r/m byte right CL + times +C0 /1 ib ROR r/m8,imm8 3/7 Rotate 8 bits r/m word right imm8 + times +D1 /1 ROR r/m16,1 3/7 Rotate 16 bits r/m word right once +D3 /1 ROR r/m16,CL 3/7 Rotate 16 bits r/m word right CL + times +C1 /1 ib ROR r/m16,imm8 3/7 Rotate 16 bits r/m word right imm8 + times +D1 /1 ROR r/m32,1 3/7 Rotate 32 bits r/m dword right once +D3 /1 ROR r/m32,CL 3/7 Rotate 32 bits r/m dword right CL + times +C1 /1 ib ROR r/m32,imm8 3/7 Rotate 32 bits r/m dword right imm8 + times + + +Operation + +(* ROL - Rotate Left *) +temp  COUNT; +WHILE (temp <> 0) +DO + tmpcf  high-order bit of (r/m); + r/m  r/m * 2 + (tmpcf); + temp  temp - 1; +OD; +IF COUNT = 1 +THEN + IF high-order bit of r/m <> CF + THEN OF  1; + ELSE OF  0; + FI; +ELSE OF  undefined; +FI; +(* ROR - Rotate Right *) +temp  COUNT; +WHILE (temp <> 0 ) +DO + tmpcf  low-order bit of (r/m); + r/m  r/m / 2 + (tmpcf * 2^(width(r/m))); + temp  temp - 1; +DO; +IF COUNT = 1 +THEN + IF (high-order bit of r/m) <> (bit next to high-order bit of r/m) + THEN OF  1; + ELSE OF  0; + FI; +ELSE OF  undefined; +FI; + +Description + +Each rotate instruction shifts the bits of the register or memory operand +given. The left rotate instructions shift all the bits upward, except for +the top bit, which is returned to the bottom. The right rotate instructions +do the reverse: the bits shift downward until the bottom bit arrives at +the top. + +For the RCL and RCR instructions, the carry flag is part of the rotated +quantity. RCL shifts the carry flag into the bottom bit and shifts the top +bit into the carry flag; RCR shifts the carry flag into the top bit and +shifts the bottom bit into the carry flag. For the ROL and ROR +instructions, the original value of the carry flag is not a part of the +result, but the carry flag receives a copy of the bit that was shifted from +one end to the other. + +The rotate is repeated the number of times indicated by the second +operand, which is either an immediate number or the contents of the CL +register. To reduce the maximum instruction execution time, the 80386 +does not allow rotation counts greater than 31. If a rotation count greater +than 31 is attempted, only the bottom five bits of the rotation are used. +The 8086 does not mask rotation counts. The 80386 in Virtual 8086 Mode does +mask rotation counts. + +The overflow flag is defined only for the single-rotate forms of the +instructions (second operand = 1). It is undefined in all other cases. For +left shifts/rotates, the CF bit after the shift is XORed with the +high-order result bit. For right shifts/rotates, the high-order two bits of +the result are XORed to get OF. + +Flags Affected + +OF only for single rotates; OF is undefined for multi-bit rotates; CF as +described above + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +REP/REPE/REPZ/REPNE/REPNZ Repeat Following String Operation + + +Opcode Instruction Clocks Description + +F3 6C REP INS r/m8, DX 13+6*(E)CX, + pm=7+6*(E)CX +If CPL IOPL/ + 27+6*(E)CX +If CPL > IOPL or if in virtual 8086 mode Input (E)CX bytes from port + DX into ES:[(E)DI] +F3 6D REP INS r/m16,DX 13+6*(E)CX, + pm=7+6*(E)CX +If CPL IOPL/ + 27+6*(E)CX +If CPL > IOPL or if in virtual 8086 mode Input (E)CX words from port + DX into ES:[(E)DI] +F3 6D REP INS r/m32,DX 13+6*(E)CX, + pm=7+6*(E)CX +If CPL IOPL/ + 27+6*(E)CX +If CPL > IOPL or if in virtual 8086 mode Input (E)CX dwords from port + DX into ES:[(E)DI] +F3 A4 REP MOVS m8,m8 5+4*(E)CX Move (E)CX bytes from + [(E)SI] to ES:[(E)DI] +F3 A5 REP MOVS m16,m16 5+4*(E)CX Move (E)CX words from + [(E)SI] to ES:[(E)DI] +F3 A5 REP MOVS m32,m32 5+4*(E)CX Move (E)CX dwords from + [(E)SI] to ES:[(E)DI] +F3 6E REP OUTS DX,r/m8 5+12*(E)CX, + pm=6+5*(E)CX +If CPL IOPL/ + 26+5*(E)CX +If CPL > IOPL or if in virtual 8086 mode Output (E)CX bytes from + [(E)SI] to port DX +F3 6F REP OUTS DX,r/m16 5+12*(E)CX, + pm=6+5*(E)CX +If CPL IOPL/ + 26+5*(E)CX +If CPL > IOPL or if in virtual 8086 mode Output (E)CX words from + [(E)SI] to port DX +F3 6F REP OUTS DX,r/m32 5+12*(E)CX, + pm=6+5*(E)CX +If CPL IOPL/ + 26+5*(E)CX +If CPL > IOPL or if in virtual 8086 mode Output (E)CX dwords from + [(E)SI] to port DX +F3 AA REP STOS m8 5+5*(E)CX Fill (E)CX bytes at + ES:[(E)DI] with AL +F3 AB REP STOS m16 5+5*(E)CX Fill (E)CX words at + ES:[(E)DI] with AX +F3 AB REP STOS m32 5+5*(E)CX Fill (E)CX dwords at + ES:[(E)DI] with EAX +F3 A6 REPE CMPS m8,m8 5+9*N Find nonmatching bytes in + ES:[(E)DI] and [(E)SI] +F3 A7 REPE CMPS m16,m16 5+9*N Find nonmatching words in + ES:[(E)DI] and [(E)SI] +F3 A7 REPE CMPS m32,m32 5+9*N Find nonmatching dwords in + ES:[(E)DI] and [(E)SI] +F3 AE REPE SCAS m8 5+8*N Find non-AL byte starting + at ES:[(E)DI] +F3 AF REPE SCAS m16 5+8*N Find non-AX word starting + at ES:[(E)DI] +F3 AF REPE SCAS m32 5+8*N Find non-EAX dword starting + at ES:[(E)DI] +F2 A6 REPNE CMPS m8,m8 5+9*N Find matching bytes in + ES:[(E)DI] and [(E)SI] +F2 A7 REPNE CMPS m16,m16 5+9*N Find matching words in + ES:[(E)DI] and [(E)SI] +F2 A7 REPNE CMPS m32,m32 5+9*N Find matching dwords in + ES:[(E)DI] and [(E)SI] +F2 AE REPNE SCAS m8 5+8*N Find AL, starting at + ES:[(E)DI] +F2 AF REPNE SCAS m16 5+8*N Find AX, starting at + ES:[(E)DI] +F2 AF REPNE SCAS m32 5+8*N Find EAX, starting at + ES:[(E)DI] + + +Operation + +IF AddressSize = 16 +THEN use CX for CountReg; +ELSE (* AddressSize = 32 *) use ECX for CountReg; +FI; +WHILE CountReg <> 0 +DO + service pending interrupts (if any); + perform primitive string instruction; + CountReg  CountReg - 1; + IF primitive operation is CMPB, CMPW, SCAB, or SCAW + THEN + IF (instruction is REP/REPE/REPZ) AND (ZF=1) + THEN exit WHILE loop + ELSE + IF (instruction is REPNZ or REPNE) AND (ZF=0) + THEN exit WHILE loop; + FI; + FI; + FI; +OD; + +Description + +REP, REPE (repeat while equal), and REPNE (repeat while not equal) +are prefix that are applied to string operation. Each prefix cause the +string instruction that follows to be repeated the number of times +indicated in the count register or (for REPE and REPNE) until the +indicated condition in the zero flag is no longer met. + +Synonymous forms of REPE and REPNE are REPZ and REPNZ, +respectively. + +The REP prefixes apply only to one string instruction at a time. To repeat +a block of instructions, use the LOOP instruction or another looping +construct. + +The precise action for each iteration is as follows: + + 1. If the address-size attribute is 16 bits, use CX for the count + register; if the address-size attribute is 32 bits, use ECX for the + count register. + + 2. Check CX. If it is zero, exit the iteration, and move to the next + instruction. + + 3. Acknowledge any pending interrupts. + + 4. Perform the string operation once. + + 5. Decrement CX or ECX by one; no flags are modified. + + 6. Check the zero flag if the string operation is SCAS or CMPS. If + the repeat condition does not hold, exit the iteration and move to + the next instruction. Exit the iteration if the prefix is REPE and ZF + is 0 (the last comparison was not equal), or if the prefix is REPNE + and ZF is one (the last comparison was equal). + + 7. Return to step 1 for the next iteration. + +Repeated CMPS and SCAS instructions can be exited if the count is +exhausted or if the zero flag fails the repeat condition. These two cases +can be distinguished by using either the JCXZ instruction, or by using +the conditional jumps that test the zero flag (JZ, JNZ, and JNE). + +Flags Affected + +ZF by REP CMPS and REP SCAS as described above + +Protected Mode Exceptions + +#UD if a repeat prefix is used before an instruction that is not in the +list above; further exceptions can be generated when the string operation is +executed; refer to the descriptions of the string instructions themselves + +Real Address Mode Exceptions + +Interrupt 6 if a repeat prefix is used before an instruction that is not in +the list above; further exceptions can be generated when the string +operation is executed; refer to the descriptions of the string instructions +themselves + +Virtual 8086 Mode Exceptions + +#UD if a repeat prefix is used before an instruction that is not in the +list above; further exceptions can be generated when the string operation is +executed; refer to the descriptions of the string instructions themselves + +Notes + +Not all input/output ports can handle the rate at which the REP INS +and REP OUTS instructions execute. + + +RET Return from Procedure + +Opcode Instruction Clocks Description + +C3 RET 10+m Return (near) to caller +CB RET 18+m,pm=32+m Return (far) to caller, same + privilege +CB RET pm=68 Return (far), lesser privilege, + switch stacks +C2 iw RET imm16 10+m Return (near), pop imm16 bytes of + parameters +CA iw RET imm16 18+m,pm=32+m Return (far), same privilege, pop + imm16 bytes +CA iw RET imm16 pm=68 Return (far), lesser privilege, pop + imm16 bytes + + +Operation + +IF instruction = near RET +THEN; + IF OperandSize = 16 + THEN + IP  Pop(); + EIP  EIP AND 0000FFFFH; + ELSE (* OperandSize = 32 *) + EIP  Pop(); + FI; + IF instruction has immediate operand THEN eSP  eSP + imm16; FI; +FI; + +IF (PE = 0 OR (PE = 1 AND VM = 1)) + (* real mode or virtual 8086 mode *) + AND instruction = far RET +THEN; + IF OperandSize = 16 + THEN + IP  Pop(); + EIP  EIP AND 0000FFFFH; + CS  Pop(); (* 16-bit pop *) + ELSE (* OperandSize = 32 *) + EIP  Pop(); + CS  Pop(); (* 32-bit pop, high-order 16-bits discarded *) + FI; + IF instruction has immediate operand THEN eSP  eSP + imm16; FI; +FI; + +IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *) + AND instruction = far RET +THEN + IF OperandSize=32 + THEN Third word on stack must be within stack limits else #SS(0); + ELSE Second word on stack must be within stack limits else #SS(0); + FI; + Return selector RPL must be CPL ELSE #GP(return selector) + IF return selector RPL = CPL + THEN GOTO SAME-LEVEL; + ELSE GOTO OUTER-PRIVILEGE-LEVEL; + FI; +FI; + +SAME-LEVEL: + Return selector must be non-null ELSE #GP(0) + Selector index must be within its descriptor table limits ELSE + #GP(selector) + Descriptor AR byte must indicate code segment ELSE #GP(selector) + IF non-conforming + THEN code segment DPL must equal CPL; + ELSE #GP(selector); + FI; + IF conforming + THEN code segment DPL must be CPL; + ELSE #GP(selector); + FI; + Code segment must be present ELSE #NP(selector); + Top word on stack must be within stack limits ELSE #SS(0); + IP must be in code segment limit ELSE #GP(0); + IF OperandSize=32 + THEN + Load CS:EIP from stack + Load CS register with descriptor + Increment eSP by 8 plus the immediate offset if it exists + ELSE (* OperandSize=16 *) + Load CS:IP from stack + Load CS register with descriptor + Increment eSP by 4 plus the immediate offset if it exists + FI; + +OUTER-PRIVILEGE-LEVEL: + IF OperandSize=32 + THEN Top (16+immediate) bytes on stack must be within stack limits + ELSE #SS(0); + ELSE Top (8+immediate) bytes on stack must be within stack limits ELSE + #SS(0); + FI; + Examine return CS selector and associated descriptor: + Selector must be non-null ELSE #GP(0); + Selector index must be within its descriptor table limits ELSE + #GP(selector) + Descriptor AR byte must indicate code segment ELSE #GP(selector); + IF non-conforming + THEN code segment DPL must equal return selector RPL + ELSE #GP(selector); + FI; + IF conforming + THEN code segment DPL must be return selector RPL; + ELSE #GP(selector); + FI; + Segment must be present ELSE #NP(selector) + Examine return SS selector and associated descriptor: + Selector must be non-null ELSE #GP(0); + Selector index must be within its descriptor table limits + ELSE #GP(selector); + Selector RPL must equal the RPL of the return CS selector ELSE + #GP(selector); + Descriptor AR byte must indicate a writable data segment ELSE + #GP(selector); + Descriptor DPL must equal the RPL of the return CS selector ELSE + #GP(selector); + Segment must be present ELSE #NP(selector); + IP must be in code segment limit ELSE #GP(0); + Set CPL to the RPL of the return CS selector; + IF OperandMode=32 + THEN + Load CS:EIP from stack; + Set CS RPL to CPL; + Increment eSP by 8 plus the immediate offset if it exists; + Load SS:eSP from stack; + ELSE (* OperandMode=16 *) + Load CS:IP from stack; + Set CS RPL to CPL; + Increment eSP by 4 plus the immediate offset if it exists; + Load SS:eSP from stack; + FI; + Load the CS register with the return CS descriptor; + Load the SS register with the return SS descriptor; + For each of ES, FS, GS, and DS + DO + IF the current register setting is not valid for the outer level, + set the register to null (selector  AR  0); + To be valid, the register setting must satisfy the following + properties: + Selector index must be within descriptor table limits; + Descriptor AR byte must indicate data or readable code segment; + IF segment is data or non-conforming code, THEN + DPL must be CPL, or DPL must be RPL; + FI; + OD; + +Description + +RET transfers control to a return address located on the stack. The +address is usually placed on the stack by a CALL instruction, and the +return is made to the instruction that follows the CALL. + +The optional numeric parameter to RET gives the number of stack bytes +(OperandMode=16) or words (OperandMode=32) to be released after the return +address is popped. These items are typically used as input parameters to the +procedure called. + +For the intrasegment (near) return, the address on the stack is a segment +offset, which is popped into the instruction pointer. The CS register is +unchanged. For the intersegment (far) return, the address on the stack +is a long pointer. The offset is popped first, followed by the selector. + +In real mode, CS and IP are loaded directly. In Protected Mode, an +intersegment return causes the processor to check the descriptor +addressed by the return selector. The AR byte of the descriptor must +indicate a code segment of equal or lesser privilege (or greater or equal +numeric value) than the current privilege level. Returns to a lesser +privilege level cause the stack to be reloaded from the value saved beyond +the parameter block. + +The DS, ES, FS, and GS segment registers can be set to 0 by the RET +instruction during an interlevel transfer. If these registers refer to +segments that cannot be used by the new privilege level, they are set to +0 to prevent unauthorized access from the new privilege level. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP, #NP, or #SS, as described under "Operation" above; #PF(fault-code) for +a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would be outside the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SAHF Store AH into Flags + +Opcode Instruction Clocks Description + +9E SAHF 3 Store AH into flags SF ZF xx AF xx PF xx CF + + +Operation + +SF:ZF:xx:AF:xx:PF:xx:CF  AH; + +Description + +SAHF loads the flags listed above with values from the AH register, +from bits 7, 6, 4, 2, and 0, respectively. + +Flags Affected + +SF, ZF, AF, PF, and CF as described above + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +SAL/SAR/SHL/SHR Shift Instructions + + +Opcode Instruction Clocks Description + +D0 /4 SAL r/m8,1 3/7 Multiply r/m byte by 2, once +D2 /4 SAL r/m8,CL 3/7 Multiply r/m byte by 2, CL times +C0 /4 ib SAL r/m8,imm8 3/7 Multiply r/m byte by 2, imm8 + times +D1 /4 SAL r/m16,1 3/7 Multiply r/m word by 2, once +D3 /4 SAL r/m16,CL 3/7 Multiply r/m word by 2, CL times +C1 /4 ib SAL r/m16,imm8 3/7 Multiply r/m word by 2, imm8 + times +D1 /4 SAL r/m32,1 3/7 Multiply r/m dword by 2, once +D3 /4 SAL r/m32,CL 3/7 Multiply r/m dword by 2, CL + times +C1 /4 ib SAL r/m32,imm8 3/7 Multiply r/m dword by 2, imm8 + times +D0 /7 SAR r/m8,1 3/7 Signed divide^(1) r/m byte by 2, + once +D2 /7 SAR r/m8,CL 3/7 Signed divide^(1) r/m byte by 2, + CL times +C0 /7 ib SAR r/m8,imm8 3/7 Signed divide^(1) r/m byte by 2, + imm8 times +D1 /7 SAR r/m16,1 3/7 Signed divide^(1) r/m word by 2, + once +D3 /7 SAR r/m16,CL 3/7 Signed divide^(1) r/m word by 2, + CL times +C1 /7 ib SAR r/m16,imm8 3/7 Signed divide^(1) r/m word by 2, + imm8 times +D1 /7 SAR r/m32,1 3/7 Signed divide^(1) r/m dword by 2, + once +D3 /7 SAR r/m32,CL 3/7 Signed divide^(1) r/m dword by 2, + CL times +C1 /7 ib SAR r/m32,imm8 3/7 Signed divide^(1) r/m dword by 2, + imm8 times +D0 /4 SHL r/m8,1 3/7 Multiply r/m byte by 2, once +D2 /4 SHL r/m8,CL 3/7 Multiply r/m byte by 2, CL times +C0 /4 ib SHL r/m8,imm8 3/7 Multiply r/m byte by 2, imm8 + times +D1 /4 SHL r/m16,1 3/7 Multiply r/m word by 2, once +D3 /4 SHL r/m16,CL 3/7 Multiply r/m word by 2, CL times +C1 /4 ib SHL r/m16,imm8 3/7 Multiply r/m word by 2, imm8 + times +D1 /4 SHL r/m32,1 3/7 Multiply r/m dword by 2, once +D3 /4 SHL r/m32,CL 3/7 Multiply r/m dword by 2, CL + times +C1 /4 ib SHL r/m32,imm8 3/7 Multiply r/m dword by 2, imm8 + times +D0 /5 SHR r/m8,1 3/7 Unsigned divide r/m byte by 2, + once +D2 /5 SHR r/m8,CL 3/7 Unsigned divide r/m byte by 2, + CL times +C0 /5 ib SHR r/m8,imm8 3/7 Unsigned divide r/m byte by 2, + imm8 times +D1 /5 SHR r/m16,1 3/7 Unsigned divide r/m word by 2, + once +D3 /5 SHR r/m16,CL 3/7 Unsigned divide r/m word by 2, + CL times +C1 /5 ib SHR r/m16,imm8 3/7 Unsigned divide r/m word by 2, + imm8 times +D1 /5 SHR r/m32,1 3/7 Unsigned divide r/m dword by 2, + once +D3 /5 SHR r/m32,CL 3/7 Unsigned divide r/m dword by 2, + CL times +C1 /5 ib SHR r/m32,imm8 3/7 Unsigned divide r/m dword by 2, + imm8 times + + +Not the same division as IDIV; rounding is toward negative infinity. + +Operation + +(* COUNT is the second parameter *) +(temp)  COUNT; +WHILE (temp <> 0) +DO + IF instruction is SAL or SHL + THEN CF  high-order bit of r/m; + FI; + IF instruction is SAR or SHR + THEN CF  low-order bit of r/m; + FI; + IF instruction = SAL or SHL + THEN r/m  r/m * 2; + FI; + IF instruction = SAR + THEN r/m  r/m /2 (*Signed divide, rounding toward negative infinity*); + FI; + IF instruction = SHR + THEN r/m  r/m / 2; (* Unsigned divide *); + FI; + temp  temp - 1; +OD; +(* Determine overflow for the various instructions *) +IF COUNT = 1 +THEN + IF instruction is SAL or SHL + THEN OF  high-order bit of r/m <> (CF); + FI; + IF instruction is SAR + THEN OF  0; + FI; + IF instruction is SHR + THEN OF  high-order bit of operand; + FI; +ELSE OF  undefined; +FI; + +Description + +SAL (or its synonym, SHL) shifts the bits of the operand upward. The +high-order bit is shifted into the carry flag, and the low-order bit is set +to 0. + +SAR and SHR shift the bits of the operand downward. The low-order +bit is shifted into the carry flag. The effect is to divide the operand by +2. SAR performs a signed divide with rounding toward negative infinity (not +the same as IDIV); the high-order bit remains the same. SHR performs an +unsigned divide; the high-order bit is set to 0. + +The shift is repeated the number of times indicated by the second +operand, which is either an immediate number or the contents of the CL +register. To reduce the maximum execution time, the 80386 does not +allow shift counts greater than 31. If a shift count greater than 31 is +attempted, only the bottom five bits of the shift count are used. (The +8086 uses all eight bits of the shift count.) + +The overflow flag is set only if the single-shift forms of the instructions +are used. For left shifts, OF is set to 0 if the high bit of the answer is +the same as the result of the carry flag (i.e., the top two bits of the +original operand were the same); OF is set to 1 if they are different. For +SAR, OF is set to 0 for all single shifts. For SHR, OF is set to the +high-order bit of the original operand. + +Flags Affected + +OF for single shifts; OF is undefined for multiple shifts; CF, ZF, PF, +and SF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SBB Integer Subtraction with Borrow + + +Opcode Instruction Clocks Description + +1C ib SBB AL,imm8 2 Subtract with borrow immediate byte + from AL +1D iw SBB AX,imm16 2 Subtract with borrow immediate word + from AX +1D id SBB EAX,imm32 2 Subtract with borrow immediate + dword from EAX +80 /3 ib SBB r/m8,imm8 2/7 Subtract with borrow immediate byte + from r/m byte +81 /3 iw SBB r/m16,imm16 2/7 Subtract with borrow immediate word + from r/m word +81 /3 id SBB r/m32,imm32 2/7 Subtract with borrow immediate + dword from r/m dword +83 /3 ib SBB r/m16,imm8 2/7 Subtract with borrow sign-extended + immediate byte from r/m word +83 /3 ib SBB r/m32,imm8 2/7 Subtract with borrow sign-extended + immediate byte from r/m dword +18 /r SBB r/m8,r8 2/6 Subtract with borrow byte register + from r/m byte +19 /r SBB r/m16,r16 2/6 Subtract with borrow word register + from r/m word +19 /r SBB r/m32,r32 2/6 Subtract with borrow dword register + from r/m dword +1A /r SBB r8,r/m8 2/7 Subtract with borrow byte register + from r/m byte +1B /r SBB r16,r/m16 2/7 Subtract with borrow word register + from r/m word +1B /r SBB r32,r/m32 2/7 Subtract with borrow dword register + from r/m dword + + +Operation + +IF SRC is a byte and DEST is a word or dword +THEN DEST = DEST - (SignExtend(SRC) + CF) +ELSE DEST  DEST - (SRC + CF); + +Description + +SBB adds the second operand (DEST) to the carry flag (CF) and +subtracts the result from the first operand (SRC). The result of the +subtraction is assigned to the first operand (DEST), and the flags are +set accordingly. + +When an immediate byte value is subtracted from a word operand, the +immediate value is first sign-extended. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SCAS/SCASB/SCASW/SCASD Compare String Data + +Opcode Instruction Clocks Description + +AE SCAS m8 7 Compare bytes AL-ES:[DI], update (E)DI +AF SCAS m16 7 Compare words AX-ES:[DI], update (E)DI +AF SCAS m32 7 Compare dwords EAX-ES:[DI], update (E)DI +AE SCASB 7 Compare bytes AL-ES:[DI], update (E)DI +AF SCASW 7 Compare words AX-ES:[DI], update (E)DI +AF SCASD 7 Compare dwords EAX-ES:[DI], update (E)DI + + +Operation + +IF AddressSize = 16 +THEN use DI for dest-index; +ELSE (* AddressSize = 32 *) use EDI for dest-index; +FI; +IF byte type of instruction +THEN + AL - [dest-index]; (* Compare byte in AL and dest *) + IF DF = 0 THEN IndDec  1 ELSE IncDec  -1; FI; +ELSE + IF OperandSize = 16 + THEN + AX - [dest-index]; (* compare word in AL and dest *) + IF DF = 0 THEN IncDec  2 ELSE IncDec  -2; FI; + ELSE (* OperandSize = 32 *) + EAX - [dest-index];(* compare dword in EAX & dest *) + IF DF = 0 THEN IncDec  4 ELSE IncDec  -4; FI; + FI; +FI; +dest-index = dest-index + IncDec + +Description + +SCAS subtracts the memory byte or word at the destination register from +the AL, AX or EAX register. The result is discarded; only the flags are set. +The operand must be addressable from the ES segment; no segment override is +possible. + +If the address-size attribute for this instruction is 16 bits, DI is used +as the destination register; otherwise, the address-size attribute is 32 +bits and EDI is used. + +The address of the memory data being compared is determined solely by the +contents of the destination register, not by the operand to SCAS. The +operand validates ES segment addressability and determines the data type. +Load the correct index value into DI or EDI before executing SCAS. + +After the comparison is made, the destination register is automatically +updated. If the direction flag is 0 (CLD was executed), the destination +register is incremented; if the direction flag is 1 (STD was executed), it +is decremented. The increments or decrements are by 1 if bytes are compared, +by 2 if words are compared, or by 4 if doublewords are compared. + +SCASB, SCASW, and SCASD are synonyms for the byte, word and +doubleword SCAS instructions that don't require operands. They are +simpler to code, but provide no type or segment checking. + +SCAS can be preceded by the REPE or REPNE prefix for a block search +of CX or ECX bytes or words. Refer to the REP instruction for further +details. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SETcc Byte Set on Condition + + +Opcode Instruction Clocks Description + +0F 97 SETA r/m8 4/5 Set byte if above (CF=0 and ZF=0) +0F 93 SETAE r/m8 4/5 Set byte if above or equal (CF=0) +0F 92 SETB r/m8 4/5 Set byte if below (CF=1) +0F 96 SETBE r/m8 4/5 Set byte if below or equal (CF=1 or (ZF=1) +0F 92 SETC r/m8 4/5 Set if carry (CF=1) +0F 94 SETE r/m8 4/5 Set byte if equal (ZF=1) +0F 9F SETG r/m8 4/5 Set byte if greater (ZF=0 or SF=OF) +0F 9D SETGE r/m8 4/5 Set byte if greater or equal (SF=OF) +0F 9C SETL r/m8 4/5 Set byte if less (SF<>OF) +0F 9E SETLE r/m8 4/5 Set byte if less or equal (ZF=1 and + SF<>OF) +0F 96 SETNA r/m8 4/5 Set byte if not above (CF=1) +0F 92 SETNAE r/m8 4/5 Set byte if not above or equal (CF=1) +0F 93 SETNB r/m8 4/5 Set byte if not below (CF=0) +0F 97 SETNBE r/m8 4/5 Set byte if not below or equal (CF=0 and + ZF=0) +0F 93 SETNC r/m8 4/5 Set byte if not carry (CF=0) +0F 95 SETNE r/m8 4/5 Set byte if not equal (ZF=0) +0F 9E SETNG r/m8 4/5 Set byte if not greater (ZF=1 or SF<>OF) +0F 9C SETNGE r/m8 4/5 Set if not greater or equal (SF<>OF) +0F 9D SETNL r/m8 4/5 Set byte if not less (SF=OF) +0F 9F SETNLE r/m8 4/5 Set byte if not less or equal (ZF=1 and + SF<>OF) +0F 91 SETNO r/m8 4/5 Set byte if not overflow (OF=0) +0F 9B SETNP r/m8 4/5 Set byte if not parity (PF=0) +0F 99 SETNS r/m8 4/5 Set byte if not sign (SF=0) +0F 95 SETNZ r/m8 4/5 Set byte if not zero (ZF=0) +0F 90 SETO r/m8 4/5 Set byte if overflow (OF=1) +0F 9A SETP r/m8 4/5 Set byte if parity (PF=1) +0F 9A SETPE r/m8 4/5 Set byte if parity even (PF=1) +0F 9B SETPO r/m8 4/5 Set byte if parity odd (PF=0) +0F 98 SETS r/m8 4/5 Set byte if sign (SF=1) +0F 94 SETZ r/m8 4/5 Set byte if zero (ZF=1) + + +Operation + +IF condition THEN r/m8  1 ELSE r/m8  0; FI; + +Description + +SETcc stores a byte at the destination specified by the effective address +or register if the condition is met, or a 0 byte if the condition is not +met. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a non-writable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SGDT/SIDT Store Global/Interrupt Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 01 /0 SGDT m 9 Store GDTR to m +0F 01 /1 SIDT m 9 Store IDTR to m + + +Operation + +DEST  48-bit BASE/LIMIT register contents; + +Description + +SGDT/SIDT copies the contents of the descriptor table register the six +bytes of memory indicated by the operand. The LIMIT field of the +register is assigned to the first word at the effective address. If the +operand-size attribute is 32 bits, the next three bytes are assigned the +BASE field of the register, and the fourth byte is written with zero. The +last byte is undefined. Otherwise, if the operand-size attribute is 16 +bits, the next four bytes are assigned the 32-bit BASE field of the +register. + +SGDT and SIDT are used only in operating system software; they are +not used in application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +Interrupt 6 if the destination operand is a register; #GP(0) if the +destination is in a nonwritable segment; #GP(0) for an illegal memory +operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for +an illegal address in the SS segment; #PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6 if the destination operand is a register; Interrupt 13 if any +part of the operand would lie outside of the effective address space from +0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + +Compatability Note + +The 16-bit forms of the SGDT/SIDT instructions are compatible with +the 80286, if the value in the upper eight bits is not referenced. The +80286 stores 1's in these upper bits, whereas the 80386 stores 0's if the +operand-size attribute is 16 bits. These bits were specified as undefined +by the SGDT/SIDT instructions in the iAPX 286 Programmer's +Reference Manual. + + +SHLD Double Precision Shift Left + +Opcode Instruction Clocks Description + +0F A4 SHLD r/m16,r16,imm8 3/7 r/m16 gets SHL of r/m16 concatenated + with r16 +0F A4 SHLD r/m32,r32,imm8 3/7 r/m32 gets SHL of r/m32 concatenated + with r32 +0F A5 SHLD r/m16,r16,CL 3/7 r/m16 gets SHL of r/m16 concatenated + with r16 +0F A5 SHLD r/m32,r32,CL 3/7 r/m32 gets SHL of r/m32 concatenated + with r32 + + +Operation + +(* count is an unsigned integer corresponding to the last operand of the +instruction, either an immediate byte or the byte in register CL *) +ShiftAmt  count MOD 32; +inBits  register; (* Allow overlapped operands *) +IF ShiftAmt = 0 +THEN no operation +ELSE + IF ShiftAmt OperandSize + THEN (* Bad parameters *) + r/m  UNDEFINED; + CF, OF, SF, ZF, AF, PF  UNDEFINED; + ELSE (* Perform the shift *) + CF  BIT[Base, OperandSize - ShiftAmt]; + (* Last bit shifted out on exit *) + FOR i  OperandSize - 1 DOWNTO ShiftAmt + DO + BIT[Base, i]  BIT[Base, i - ShiftAmt]; + OF; + FOR i  ShiftAmt - 1 DOWNTO 0 + DO + BIT[Base, i]  BIT[inBits, i - ShiftAmt + OperandSize]; + OD; + Set SF, ZF, PF (r/m); + (* SF, ZF, PF are set according to the value of the result *) + AF  UNDEFINED; + FI; +FI; + +Description + +SHLD shifts the first operand provided by the r/m field to the left as +many bits as specified by the count operand. The second operand (r16 or r32) +provides the bits to shift in from the right (starting with bit 0). The +result is stored back into the r/m operand. The register remains unaltered. + +The count operand is provided by either an immediate byte or the contents +of the CL register. These operands are taken MODULO 32 to provide a number +between 0 and 31 by which to shift. Because the bits to shift are provided +by the specified registers, the operation is useful for multiprecision +shifts (64 bits or more). The SF, ZF and PF flags are set according to the +value of the result. CS is set to the value of the last bit shifted out. OF +and AF are left undefined. + +Flags Affected + +OF, SF, ZF, PF, and CF as described above; AF and OF are undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +SHRD Double Precision Shift Right + +Opcode Instruction Clocks Description + +0F AC SHRD r/m16,r16,imm8 3/7 r/m16 gets SHR of r/m16 concatenated + with r16 +0F AC SHRD r/m32,r32,imm8 3/7 r/m32 gets SHR of r/m32 concatenated + with r32 +0F AD SHRD r/m16,r16,CL 3/7 r/m16 gets SHR of r/m16 concatenated + with r16 +0F AD SHRD r/m32,r32,CL 3/7 r/m32 gets SHR of r/m32 concatenated + with r32 + + +Operation + +(* count is an unsigned integer corresponding to the last operand of the +instruction, either an immediate byte or the byte in register CL *) +ShiftAmt  count MOD 32; +inBits  register; (* Allow overlapped operands *) +IF ShiftAmt = 0 +THEN no operation +ELSE + IF ShiftAmt OperandSize + THEN (* Bad parameters *) + r/m  UNDEFINED; + CF, OF, SF, ZF, AF, PF  UNDEFINED; + ELSE (* Perform the shift *) + CF  BIT[r/m, ShiftAmt - 1]; (* last bit shifted out on exit *) + FOR i  0 TO OperandSize - 1 - ShiftAmt + DO + BIT[r/m, i]  BIT[r/m, i - ShiftAmt]; + OD; + FOR i  OperandSize - ShiftAmt TO OperandSize - 1 + DO + BIT[r/m,i]  BIT[inBits,i+ShiftAmt - OperandSize]; + OD; + Set SF, ZF, PF (r/m); + (* SF, ZF, PF are set according to the value of the result *) + Set SF, ZF, PF (r/m); + AF  UNDEFINED; + FI; +FI; + +Description + +SHRD shifts the first operand provided by the r/m field to the right as many +bits as specified by the count operand. The second operand (r16 or r32) +provides the bits to shift in from the left (starting with bit 31). The +result is stored back into the r/m operand. The register remains unaltered. + +The count operand is provided by either an immediate byte or the contents +of the CL register. These operands are taken MODULO 32 to provide a number +between 0 and 31 by which to shift. Because the bits to shift are provided +by the specified register, the operation is useful for multi-precision +shifts (64 bits or more). The SF, ZF and PF flags are set according to the +value of the result. CS is set to the value of the last bit shifted out. OF +and AF are left undefined. + +Flags Affected + +OF, SF, ZF, PF, and CF as described above; AF and OF are undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +SLDT Store Local Descriptor Table Register + +Opcode Instruction Clocks Description + +0F 00 /0 SLDT r/m16 pm=2/2 Store LDTR to EA word + + +Operation + +r/m16  LDTR; + +Description + +SLDT stores the Local Descriptor Table Register (LDTR) in the two-byte +register or memory location indicated by the effective address operand. +This register is a selector that points into the Global Descriptor Table. + +SLDT is used only in operating system software. It is not used in +application programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 6; SLDT is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +The operand-size attribute has no effect on the operation of the +instruction. + + +SMSW Store Machine Status Word + +Opcode Instruction Clocks Description + +0F 01 /4 SMSW r/m16 2/3,pm=2/2 Store machine status word to EA + word + + +Operation + +r/m16  MSW; + +Description + +SMSW stores the machine status word (part of CR0) in the two-byte register +or memory location indicated by the effective address operand. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + +Notes + +This instruction is provided for compatibility with the 80286; 80386 +programs should use MOV ..., CR0. + + +STC Set Carry Flag + +Opcode Instruction Clocks Description + +F9 STC 2 Set carry flag + + +Operation + +CF  1; + +Description + +STC sets the carry flag to 1. + +Flags Affected + +CF = 1 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +STD Set Direction Flag + +Opcode Instruction Clocks Description + +FD STD 2 Set direction flag so (E)SI and/or (E)DI + decrement + + +Operation + +DF  1; + +Description + +STD sets the direction flag to 1, causing all subsequent string operations +to decrement the index registers, (E)SI and/or (E)DI, on which they +operate. + +Flags Affected + +DF = 1 + +Protected Mode Exceptions + +None + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +STI Set Interrupt Flag + +Opcode Instruction Clocks Description + +F13 STI 3 Set interrupt flag; interrupts enabled at the + end of the next instruction + + +Operation + +IF  1 + +Description + +STI sets the interrupt flag to 1. The 80386 then responds to external +interrupts after executing the next instruction if the next instruction +allows the interrupt flag to remain enabled. If external interrupts are +disabled and you code STI, RET (such as at the end of a subroutine), +the RET is allowed to execute before external interrupts are recognized. +Also, if external interrupts are disabled and you code STI, CLI, then +external interrupts are not recognized because the CLI instruction clears +the interrupt flag during its execution. + +Flags Affected + +IF = 1 + +Protected Mode Exceptions + +#GP(0) if the current privilege level is greater (has less privilege) than +the I/O privilege level + +Real Address Mode Exceptions + +None + +Virtual 8086 Mode Exceptions + +None + + +STOS/STOSB/STOSW/STOSD Store String Data + +Opcode Instruction Clocks Description + +AA STOS m8 4 Store AL in byte ES:[(E)DI], update (E)DI +AB STOS m16 4 Store AX in word ES:[(E)DI], update (E)DI +AB STOS m32 4 Store EAX in dword ES:[(E)DI], update (E)DI +AA STOSB 4 Store AL in byte ES:[(E)DI], update (E)DI +AB STOSW 4 Store AX in word ES:[(E)DI], update (E)DI +AB STOSD 4 Store EAX in dword ES:[(E)DI], update (E)DI + + +Operation + +IF AddressSize = 16 +THEN use ES:DI for DestReg +ELSE (* AddressSize = 32 *) use ES:EDI for DestReg; +FI; +IF byte type of instruction +THEN + (ES:DestReg)  AL; + IF DF = 0 + THEN DestReg  DestReg + 1; + ELSE DestReg  DestReg - 1; + FI; +ELSE IF OperandSize = 16 + THEN + (ES:DestReg)  AX; + IF DF = 0 + THEN DestReg  DestReg + 2; + ELSE DestReg  DestReg - 2; + FI; + ELSE (* OperandSize = 32 *) + (ES:DestReg)  EAX; + IF DF = 0 + THEN DestReg  DestReg + 4; + ELSE DestReg  DestReg - 4; + FI; + FI; +FI; + +Description + +STOS transfers the contents of all AL, AX, or EAX register to the memory +byte or word given by the destination register relative to the ES segment. +The destination register is DI for an address-size attribute of 16 bits or +EDI for an address-size attribute of 32 bits. + +The destination operand must be addressable from the ES register. A segment +override is not possible. + +The address of the destination is determined by the contents of the +destination register, not by the explicit operand of STOS. This operand is +used only to validate ES segment addressability and to determine the data +type. Load the correct index value into the destination register before +executing STOS. + +After the transfer is made, DI is automatically updated. If the direction +flag is 0 (CLD was executed), DI is incremented; if the direction flag is +1 (STD was executed), DI is decremented. DI is incremented or decremented by +1 if a byte is stored, by 2 if a word is stored, or by 4 if a doubleword is +stored. + +STOSB, STOSW, and STOSD are synonyms for the byte, word, and doubleword STOS +instructions, that do not require an operand. They are simpler to use, but +provide no type or segment checking. + +STOS can be preceded by the REP prefix for a block fill of CX or ECX bytes, +words, or doublewords. Refer to the REP instruction for further details. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +STR Store Task Register + +Opcode Instruction Clocks Description + +0F 00 /1 STR r/m16 pm=23/27 Load EA word into task register + + +Operation + +r/m  task register; + +Description + +The contents of the task register are copied to the two-byte register or +memory location indicated by the effective address operand. + +STR is used only in operating system software. It is not used in application +programs. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 6; STR is not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode + +Notes + +The operand-size attribute has no effect on this instruction. + + +SUB Integer Subtraction + +Opcode Instruction Clocks Description + +2C ib SUB AL,imm8 2 Subtract immediate byte from AL +2D iw SUB AX,imm16 2 Subtract immediate word from AX +2D id SUB EAX,imm32 2 Subtract immediate dword from EAX +80 /5 ib SUB r/m8,imm8 2/7 Subtract immediate byte from r/m byte +81 /5 iw SUB r/m16,imm16 2/7 Subtract immediate word from r/m word +81 /5 id SUB r/m32,imm32 2/7 Subtract immediate dword from r/m + dword +83 /5 ib SUB r/m16,imm8 2/7 Subtract sign-extended immediate byte + from r/m word +83 /5 ib SUB r/m32,imm8 2/7 Subtract sign-extended immediate byte + from r/m dword +28 /r SUB r/m8,r8 2/6 Subtract byte register from r/m byte +29 /r SUB r/m16,r16 2/6 Subtract word register from r/m word +29 /r SUB r/m32,r32 2/6 Subtract dword register from r/m + dword +2A /r SUB r8,r/m8 2/7 Subtract byte register from r/m byte +2B /r SUB r16,r/m16 2/7 Subtract word register from r/m word +2B /r SUB r32,r/m32 2/7 Subtract dword register from r/m + dword + + +Operation + +IF SRC is a byte and DEST is a word or dword +THEN DEST = DEST - SignExtend(SRC); +ELSE DEST  DEST - SRC; +FI; + +Description + +SUB subtracts the second operand (SRC) from the first operand (DEST). The +first operand is assigned the result of the subtraction, and the flags are +set accordingly. + +When an immediate byte value is subtracted from a word operand, the +immediate value is first sign-extended to the size of the destination +operand. + +Flags Affected + +OF, SF, ZF, AF, PF, and CF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +TEST Logical Compare + +Opcode Instruction Clocks Description + +A8 ib TEST AL,imm8 2 AND immediate byte with AL +A9 iw TEST AX,imm16 2 AND immediate word with AX +A9 id TEST EAX,imm32 2 AND immediate dword with EAX +F6 /0 ib TEST r/m8,imm8 2/5 AND immediate byte with r/m byte +F7 /0 iw TEST r/m16,imm16 2/5 AND immediate word with r/m word +F7 /0 id TEST r/m32,imm32 2/5 AND immediate dword with r/m dword +84 /r TEST r/m8,r8 2/5 AND byte register with r/m byte +85 /r TEST r/m16,r16 2/5 AND word register with r/m word +85 /r TEST r/m32,r32 2/5 AND dword register with r/m dword + + +Operation + +DEST : = LeftSRC AND RightSRC; +CF  0; +OF  0; + +Description + +TEST computes the bit-wise logical AND of its two operands. Each bit +of the result is 1 if both of the corresponding bits of the operands are 1; +otherwise, each bit is 0. The result of the operation is discarded and only +the flags are modified. + +Flags Affected + +OF = 0, CF = 0; SF, ZF, and PF as described in Appendix C + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +VERR, VERW Verify a Segment for Reading or Writing + +Opcode Instruction Clocks Description + +0F 00 /4 VERR r/m16 pm=10/11 Set ZF=1 if segment can be read, + selector in r/m16 +0F 00 /5 VERW r/m16 pm=15/16 Set ZF=1 if segment can be written, + selector in r/m16 + + +Operation + +IF segment with selector at (r/m) is accessible + with current protection level + AND ((segment is readable for VERR) OR + (segment is writable for VERW)) +THEN ZF  0; +ELSE ZF  1; +FI; + +Description + +The two-byte register or memory operand of VERR and VERW contains +the value of a selector. VERR and VERW determine whether the +segment denoted by the selector is reachable from the current privilege +level and whether the segment is readable (VERR) or writable (VERW). +If the segment is accessible, the zero flag is set to 1; if the segment is +not accessible, the zero flag is set to 0. To set ZF, the following +conditions must be met: + + The selector must denote a descriptor within the bounds of the table + (GDT or LDT); the selector must be "defined." + + The selector must denote the descriptor of a code or data segment + (not that of a task state segment, LDT, or a gate). + + For VERR, the segment must be readable. For VERW, the segment + must be a writable data segment. + + If the code segment is readable and conforming, the descriptor + privilege level (DPL) can be any value for VERR. Otherwise, the + DPL must be greater than or equal to (have less or the same + privilege as) both the current privilege level and the selector's RPL. + +The validation performed is the same as if the segment were loaded into +DS, ES, FS, or GS, and the indicated access (read or write) were +performed. The zero flag receives the result of the validation. The +selector's value cannot result in a protection exception, enabling the +software to anticipate possible segment access problems. + +Flags Affected + +ZF as described above + +Protected Mode Exceptions + +Faults generated by illegal addressing of the memory operand that +contains the selector, the selector is not loaded into any segment +register, and no faults attributable to the selector operand are generated + +#GP(0) for an illegal memory operand effective address in the CS, DS, +ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 6; VERR and VERW are not recognized in Real Address Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +WAIT Wait until BUSY# Pin is Inactive (HIGH) + +Opcode Instruction Clocks Description + +9B WAIT 6 min. Wait until BUSY pin is inactive (HIGH) + + +Description + +WAIT suspends execution of 80386 instructions until the BUSY# pin is +inactive (high). The BUSY# pin is driven by the 80287 numeric processor +extension. + +Flags Affected + +None + +Protected Mode Exceptions + +#NM if the task-switched flag in the machine status word (the lower 16 bits +of register CR0) is set; #MF if the ERROR# input pin is asserted (i.e., the +80287 has detected an unmasked numeric error) + +Real Address Mode Exceptions + +Same exceptions as in Protected Mode + +Virtual 8086 Mode Exceptions + +Same exceptions as in Protected Mode + + +XCHG Exchange Register/Memory with Register + +Opcode Instruction Clocks Description + +90 + r XCHG AX,r16 3 Exchange word register with AX +90 + r XCHG r16,AX 3 Exchange word register with AX +90 + r XCHG EAX,r32 3 Exchange dword register with EAX +90 + r XCHG r32,EAX 3 Exchange dword register with EAX +86 /r XCHG r/m8,r8 3 Exchange byte register with EA byte +86 /r XCHG r8,r/m8 3/5 Exchange byte register with EA byte +87 /r XCHG r/m16,r16 3 Exchange word register with EA word +87 /r XCHG r16,r/m16 3/5 Exchange word register with EA word +87 /r XCHG r/m32,r32 3 Exchange dword register with EA dword +87 /r XCHG r32,r/m32 3/5 Exchange dword register with EA dword + + +Operation + +temp  DEST +DEST  SRC +SRC  temp + +Description + +XCHG exchanges two operands. The operands can be in either order. If a +memory operand is involved, BUS LOCK is asserted for the duration of the +exchange, regardless of the presence or absence of the LOCK prefix or of the +value of the IOPL. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) if either operand is in a nonwritable segment; #GP(0) for an +illegal memory operand effective address in the CS, DS, ES, FS, or GS +segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) +for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +XLAT/XLATB Table Look-up Translation + +D7 XLAT m8 5 Set AL to memory byte DS:[(E)BX + unsigned AL] +D7 XLATB 5 Set AL to memory byte DS:[(E)BX + unsigned AL] + + +Operation + +IF AddressSize = 16 +THEN + AL  (BX + ZeroExtend(AL)) +ELSE (* AddressSize = 32 *) + AL  (EBX + ZeroExtend(AL)); +FI; + +Description + +XLAT changes the AL register from the table index to the table entry. AL +should be the unsigned index into a table addressed by DS:BX (for an +address-size attribute of 16 bits) or DS:EBX (for an address-size attribute +of 32 bits). + +The operand to XLAT allows for the possibility of a segment override. XLAT +uses the contents of BX even if they differ from the offset of the operand. +The offset of the operand should have been moved intoBX/EBX with a previous +instruction. + +The no-operand form, XLATB, can be used if the BX/EBX table will always +reside in the DS segment. + +Flags Affected + +None + +Protected Mode Exceptions + +#GP(0) for an illegal memory operand effective address in the CS, DS, ES, +FS, or GS segments; #SS(0) for an illegal address in the SS segment; +#PF(fault-code) for a page fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault + + +XOR Logical Exclusive OR + + +Opcode Instruction Clocks Description + +34 ib XOR AL,imm8 2 Exclusive-OR immediate byte to AL +35 iw XOR AX,imm16 2 Exclusive-OR immediate word to AX +35 id XOR EAX,imm32 2 Exclusive-OR immediate dword to EAX +80 /6 ib XOR r/m8,imm8 2/7 Exclusive-OR immediate byte to r/m + byte +81 /6 iw XOR r/m16,imm16 2/7 Exclusive-OR immediate word to r/m + word +81 /6 id XOR r/m32,imm32 2/7 Exclusive-OR immediate dword to r/m + dword +83 /6 ib XOR r/m16,imm8 2/7 XOR sign-extended immediate byte + with r/m word +83 /6 ib XOR r/m32,imm8 2/7 XOR sign-extended immediate byte + with r/m dword +30 /r XOR r/m8,r8 2/6 Exclusive-OR byte register to r/m + byte +31 /r XOR r/m16,r16 2/6 Exclusive-OR word register to r/m + word +31 /r XOR r/m32,r32 2/6 Exclusive-OR dword register to r/m + dword +32 /r XOR r8,r/m8 2/7 Exclusive-OR byte register to r/m + byte +33 /r XOR r16,r/m16 2/7 Exclusive-OR word register to r/m + word +33 /r XOR r32,r/m32 2/7 Exclusive-OR dword register to r/m + dword + + +Operation + +DEST  LeftSRC XOR RightSRC +CF  0 +OF  0 + +Description + +XOR computes the exclusive OR of the two operands. Each bit of the result +is 1 if the corresponding bits of the operands are different; each bit is 0 +if the corresponding bits are the same. The answer replaces the first +operand. + +Flags Affected + +CF = 0, OF = 0; SF, ZF, and PF as described in Appendix C; AF is undefined + +Protected Mode Exceptions + +#GP(0) if the result is in a nonwritable segment; #GP(0) for an illegal +memory operand effective address in the CS, DS, ES, FS, or GS segments; +#SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page +fault + +Real Address Mode Exceptions + +Interrupt 13 if any part of the operand would lie outside of the effective +address space from 0 to 0FFFFH + +Virtual 8086 Mode Exceptions + +Same exceptions as in Real Address Mode; #PF(fault-code) for a page +fault + + +Appendix A Opcode Map + + + +The opcode tables that follow aid in interpreting 80386 object code. Use +the high-order four bits of the opcode as an index to a row of the opcode +table; use the low-order four bits as an index to a column of the table. If +the opcode is 0FH, refer to the two-byte opcode table and use the second +byte of the opcode to index the rows and columns of that table. + + +Key to Abbreviations + +Operands are identified by a two-character code of the form Zz. The first +character, an uppercase letter, specifies the addressing method; the second +character, a lowercase letter, specifies the type of operand. + + +Codes for Addressing Method + +A Direct address; the instruction has no modR/M byte; the address of the + operand is encoded in the instruction; no base register, index register, + or scaling factor can be applied; e.g., far JMP (EA). + +C The reg field of the modR/M byte selects a control register; e.g., MOV + (0F20, 0F22). + +D The reg field of the modR/M byte selects a debug register; e.g., MOV + (0F21,0F23). + +E A modR/M byte follows the opcode and specifies the operand. The operand + is either a general register or a memory address. If it is a memory + address, the address is computed from a segment register and any of the + following values: a base register, an index register, a scaling factor, + a displacement. + +F Flags Register. + +G The reg field of the modR/M byte selects a general register; e.g., ADD + (00). + +I Immediate data. The value of the operand is encoded in subsequent bytes + of the instruction. + +J The instruction contains a relative offset to be added to the + instruction pointer register; e.g., JMP short, LOOP. + +M The modR/M byte may refer only to memory; e.g., BOUND, LES, LDS, LSS, + LFS, LGS. + +O The instruction has no modR/M byte; the offset of the operand is coded as + a word or double word (depending on address size attribute) in the + instruction. No base register, index register, or scaling factor can be + applied; e.g., MOV (A0-A3). + +R The mod field of the modR/M byte may refer only to a general register; + e.g., MOV (0F20-0F24, 0F26). + +S The reg field of the modR/M byte selects a segment register; e.g., MOV + (8C,8E). + +T The reg field of the modR/M byte selects a test register; e.g., MOV + (0F24,0F26). + +X Memory addressed by DS:SI; e.g., MOVS, COMPS, OUTS, LODS, SCAS. + +Y Memory addressed by ES:DI; e.g., MOVS, CMPS, INS, STOS. + + +Codes for Operant Type + +a Two one-word operands in memory or two double-word operands in memory, + depending on operand size attribute (used only by BOUND). + +b Byte (regardless of operand size attribute) + +c Byte or word, depending on operand size attribute. + +d Double word (regardless of operand size attribute) + +p 32-bit or 48-bit pointer, depending on operand size attribute. + +s Six-byte pseudo-descriptor + +v Word or double word, depending on operand size attribute. + +w Word (regardless of operand size attribute) + + +Register Codes + +When an operand is a specific register encoded in the opcode, the register +is identified by its name; e.g., AX, CL, or ESI. The name of the register +indicates whether the register is 32-, 16-, or 8-bits wide. A register +identifier of the form eXX is used when the width of the register depends on +the operand size attribute; for example, eAX indicates that the AX register +is used when the operand size attribute is 16 and the EAX register is used +when the operand size attribute is 32. + + +One-Byte Opcode Map + + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + ͻ + ADD PUSH POP OR PUSH 2-byte +0Ĵ Ĵ + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv ES ES Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv CS escape + ͹ + ADC PUSH POP SBB PUSH POP +1Ĵ Ĵ + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv SS SS Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv DS DS + ͹ + AND SEG SUB SEG +2Ĵ DAA Ĵ DAS + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =ES Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =CS + ͹ + XOR SEG CMP SEG +3Ĵ AAA Ĵ AAS + Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =SS Eb,Gb Ev,Gv Gb,Eb Gv,Ev AL,Ib eAX,Iv =CS + ͹ + INC general register DEC general register +4Ķ + eAX eCX eDX eBX eSP eBP eSI eDI eAX eCX eDX eBX eSP eBP eSI eDI + ͹ + PUSH general register POP into general register +5Ķ + eAX eCX eDX eBX eSP eBP eSI eDI eAX eCX eDX eBX eSP eBP eSI eDI + ͹ + BOUND ARPL SEG SEG Operand Address PUSH IMUL PUSH IMUL INSB INSW/D OUTSB OUTSW/D +6 PUSHA POPA + Gv,Ma Ew,Rw =FS =GS Size Size Ib GvEvIv Ib GvEvIv Yb,DX Yb,DX Dx,Xb DX,Xv + ͹ + Short displacement jump of condition (Jb) Short-displacement jump on condition(Jb) +7Ķ + JO JNO JB JNB JZ JNZ JBE JNBE JS JNS JP JNP JL JNL JLE JNLE + ͹ + Immediate Grpl Grpl TEST XCNG MOV MOV LEA MOV POP +8Ĵ Ĵ + Eb,Ib Ev,Iv Ev,Iv Eb,Gb Ev,Gv Eb,Gb Ev,Gv Eb,Gb Ev,Gv Gb,Eb Gv,Ev Ew,Sw Gv,M Sw,Ew Ev + ͹ + XCHG word or double-word register with eAX CALL PUSHF POPF +9 NOP Ĵ CBW CWD WAIT SAHF LAHF + eCX eDX eBX eSP eBP eSI eDI Ap Fv Fv + ͹ + MOV MOVSB MOVSW/D CMPSB CMPSW/D TEST STOSB STOSW/D LODSB LODSW/D SCASB SCASW/D +AĴ Ĵ + AL,Ob eAX,Ov Ob,AL Ov,eAX Xb,Yb Xv,Yv Xb,Yb Xv,Yv AL,Ib eAX,Iv Yb,AL Yv,eAX AL,Xb eAX,Xv AL,Xb eAX,Xv + ͹ + MOV immediate byte into byte register MOV immediate word or double into word or double register +BĶ + AL CL DL BL AH CH DH BH eAX eCX eDX eBX eSP eBP eSI eDI + ͹ + Shift Grp2 RET near LES LDS MOV ENTER RET far INT INT +CĴ Ĵ LEAVE Ĵ INTO IRET + Eb,Ib Ev,Iv Iw Gv,Mp Gv,Mp Eb,Ib Ev,Iv Iw,Ib Iw 3 Ib + ͹ + Shift Grp2 +DĴ AAM AAD XLAT ESC(Escape to coprocessor instruction set) + Eb,1 Ev,1 Eb,CL Ev,CL + ͹ + LOOPNE LOOPE LOOP JCXZ IN OUT CALL JNP IN OUT +E Ĵ Ķ + Jb Jb Jb Jb AL,Ib eAX,Ib Ib,AL Ib,eAX Av Jv Ap Jb AL,DX eAX,DX DX,AL DX,eAX + ͹ + REP Unary Grp3 INC/DEC Indirct +F LOCK REPNE HLT CMC Ĵ CLC STC CLI STI CLD STD + REPE Eb Ev Grp4 Grp5 + ͼ + + +Two-Byte Opcode Map (first byte is 0FH) + + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + ͻ + LAR LSL +0 Grp6 Grp7 CLTS + Gw,Ew Gv,Ew + ͹ + +1 + + ͹ + MOV MOV MOV MOV MOV MOV +2 + Cd,Rd Dd,Rd Rd,Cd Rd,Dd Td,Rd Rd,Td + ͹ + +3 + + ͹ + +4 + + ͹ + +5 + + ͹ + +6 + + ͹ + +7 + + ͹ + Long-displacement jump on condition (Jv) Long-displacement jump on condition (Jv) +8Ķ + JO JNO JB JNB JZ JNZ JBE JNBE JS JNS JP JNP JL JNL JLE JNLE + ͹ + Byte Set on condition (Eb) +9Ĵ SETS SETNS SETP SETNP SETL SETNL SETLE SETNLE + SETO SETNO SETB SETNB SETZ SETNZ SETBE SETNBE + ͹ + PUSH POP BT SHLD SHLD PUSH POP BTS SHRD SHRD IMUL +A + FS FS Ev,Gv EvGvIb EvGvCL GS GS Ev,Gv EvGvIb EvGvCL Gv,Ev + ͹ + LSS BTR LFS LGS MOVZX Grp-8 BTC BSF BSR MOVSX +B Ĵ Ķ + Mp Ev,Gv Mp Mp Gv,Eb Gv,Ew Ev,Ib Ev,Gv Gv,Ev Gv,Ev Gv,Eb Gv,Ew + ͹ + +C + + ͹ + +D + + ͹ + +E + + ͹ + +F + + ͼ + + +Opcodes determined by bits 5,4,3 of modR/M byte: + + G Ŀ + r mod nnn R/M + o + u + p 000 001 010 011 100 101 110 111 + Ŀ + 1 ADD OR ADC SBB AND SUB XOR CMP + + Ĵ + 2 ROL ROR RCL RCR SHL SHR SAR + + Ĵ + 3 TEST NOT NEG MUL IMUL DIV IDIV + Ib/Iv AL/eAX AL/eAX AL/eAX AL/eAX + Ĵ + 4 INC DEC + Eb Eb + Ĵ + 5 INC DEC CALL CALL JMP JMP PUSH + Ev Ev Ev eP Ev Ep Ev + + + +Opcodes determined by bits 5,4,3 of modR/M byte: + + G Ŀ + r mod nnn R/M + o + u + p 000 001 010 011 100 101 110 111 + Ŀ + 6 SLDT STR LLDT LTR VERR VERW + Ew Ew Ew Ew Ew Ew + Ĵ + 7 SGDT SIDT LGDT LIDT SMSW LMSW + Ms Ms Ms Ms Ew Ew + Ĵ + 8 BT BTS BTR BTC + + + + +Appendix B Complete Flag Cross-Reference + + + +Key to Codes + +T = instruction tests flag + +M = instruction modifies flag + (either sets or resets depending on operands) + +0 = instruction resets flag + +1 = instruction sets flag + + = instruction's effect on flag is undefined + +R = instruction restores prior value of flag + +blank = instruction does not affect flag + + +Instruction OF SF ZF AF PF CF TF IF DF NT RF + +AAA TM M +AAD M M M +AAM M M M +AAS TM M +ADC M M M M M TM +ADD M M M M M M +AND 0 M M M 0 +ARPL M +BOUND +BSF/BSR M +BT/BTS/BTR/BTC M +CALL +CBW +CLC 0 +CLD 0 +CLI 0 +CLTS +CMC M +CMP M M M M M M +CMPS M M M M M M T +CWD +DAA M M TM M TM +DAS M M TM M TM +DEC M M M M M +DIV +ENTER +ESC +HLT +IDIV +IMUL M M +IN +INC M M M M M +INS T +INT 0 0 +INTO T 0 0 +IRET R R R R R R R R R T +Jcond T T T T T +JCXZ +JMP +LAHF +LAR M +LDS/LES/LSS/LFS/LGS +LEA +LEAVE +LGDT/LIDT/LLDT/LMSW +LOCK +LODS T +LOOP +LOOPE/LOOPNE T +LSL M +LTR +MOV +MOV control, debug +MOVS T +MOVSX/MOVZX +MUL M M +NEG M M M M M M +NOP +NOT +OR 0 M M M 0 +OUT +OUTS T +POP/POPA +POPF R R R R R R R R R R +PUSH/PUSHA/PUSHF +RCL/RCR 1 M TM +RCL/RCR count TM +REP/REPE/REPNE +RET +ROL/ROR 1 M M +ROL/ROR count M +SAHF R R R R R +SAL/SAR/SHL/SHR 1 M M M M M +SAL/SAR/SHL/SHR count M M M M +SBB M M M M M TM +SCAS M M M M M M T +SET cond T T T T T +SGDT/SIDT/SLDT/SMSW +SHLD/SHRD M M M M +STC 1 +STD 1 +STI 1 +STOS T +STR +SUB M M M M M M +TEST 0 M M M 0 +VERR/VERRW M +WAIT +XCHG +XLAT +XOR 0 M M M 0 + + +Appendix C Status Flag Summary + + + +Status Flags' Functions + +Bit Name Function + + 0 CF Carry Flag Set on high-order bit carry or borrow; cleared + otherwise. + 2 PF Parity Flag Set if low-order eight bits of result contain + an even number of 1 bits; cleared otherwise. + 4 AF Adjust flag Set on carry from or borrow to the low order + four bits of AL; cleared otherwise. Used for decimal + arithmetic. + 6 ZF Zero Flag Set if result is zero; cleared otherwise. + 7 SF Sign Flag Set equal to high-order bit of result (0 is + positive, 1 if negative). +11 OF Overflow Flag Set if result is too large a positive number + or too small a negative number (excluding sign-bit) to fit in + destination operand; cleared otherwise. + +Key to Codes + +T = instruction tests flag +M = instruction modifies flag + (either sets or resets depending on operands) +0 = instruction resets flag + = instruction's effect on flag is undefined +blank = instruction does not affect flag + + + +Instruction OF SF ZF AF PF CF +AAA TM M +AAS TM M +AAD M M M +AAM M M M +DAA M M TM M TM +DAS M M TM M TM +ADC M M M M M TM +ADD M M M M M M +SBB M M M M M TM +SUB M M M M M M +CMP M M M M M M +CMPS M M M M M M +SCAS M M M M M M +NEG M M M M M M +DEC M M M M M +INC M M M M M +IMUL M M +MUL M M +RCL/RCR 1 M TM +RCL/RCR count TM +ROL/ROR 1 M M +ROL/ROR count M +SAL/SAR/SHL/SHR 1 M M M M M +SAL/SAR/SHL/SHR count M M M M +SHLD/SHRD M M M M +BSF/BSR M +BT/BTS/BTR/BTC M +AND 0 M M M 0 +OR 0 M M M 0 +TEST 0 M M M 0 +XOR 0 M M M 0 + + +Appendix D Condition Codes + + + + +Note: + The terms "above" and "below" refer to the relation between two + unsigned values (neither SF nor OF is tested). The terms "greater" and + "less" refer to the relation between two signed values (SF and OF are + tested). + + +Definition of Conditions + +(For conditional instructions Jcond, and SETcond) + + + Instruction Condition +Mnemonic Meaning Subcode Tested + +O Overflow 0000 OF = 1 + +NO No overflow 0001 OF = 0 + +B Below +NAE Neither above nor equal 0010 CF = 1 + +NB Not below +AE Above or equal 0011 CF = 0 + +E Equal +Z Zero 0100 ZF = 1 + +NE Not equal +NZ Not zero 0101 ZF = 0 + +BE Below or equal +NA Not above 0110 (CF or ZF) = 1 + +NBE Neither below nor equal +NA Above 0111 (CF or ZF) = 0 + +S Sign 1000 SF = 1 + +NS No sign 1001 SF = 0 + +P Parity +PE Parity even 1010 PF = 1 + +NP No parity +PO Parity odd 1011 PF = 0 + +L Less +NGE Neither greater nor equal 1100 (SF xor OF) = 1 + +NL Not less +GE Greater or equal 1101 (SF xor OF) = 0 + +LE Less or equal +NG Not greater 1110 ((SF xor OF) or ZF) = 1 + +NLE Neither less nor equal +G Greater 1111 ((SF xor OF) or ZF) = 0 diff --git a/bench/data/sliceslice/words.txt b/bench/data/sliceslice/words.txt new file mode 100644 index 0000000..495a017 --- /dev/null +++ b/bench/data/sliceslice/words.txt @@ -0,0 +1,4585 @@ +a +A +AA +AAA +AAD +AAM +AAS +AB +abandoned +abbreviations +Abbreviations +abilities +ability +able +abort +ABORT +aborts +Aborts +about +above +Above +absence +absent +absolute +abstraction +AC +acceptable +acceptance +accepted +access +Access +ACCESS +accessed +Accessed +ACCESSED +accesses +Accessibility +accessible +accessing +Accessing +accidental +accommodate +accompanied +accompanying +accomplish +accomplished +according +accordingly +account +accumulator +achieved +acknowledge +Acknowledge +Acknowledging +across +act +action +Action +actions +activates +activation +active +activities +activity +actual +Actual +actually +AD +ADC +add +Add +ADD +added +adding +addition +Addition +additional +Additional +additions +Addr +Addrees +address +Address +ADDRESS +addressability +addressable +Addressable +addressed +addresses +addressing +Addressing +addresss +addresssize +AddressSize +adds +adequate +adhere +adjacent +adjust +Adjust +adjusted +adjustment +Adjustment +adjusts +adopt +adresses +advanced +advances +advantage +advantages +AE +AF +AFE +affect +affected +Affected +affecting +affects +afforded +after +After +AFTER +again +against +Against +AH +ahead +aid +aids +AL +Algol +algorithm +algorithmic +algorithms +alias +Alias +ALIAS +aliases +aligned +Aligned +aligning +alignment +alike +all +All +allocate +allocated +allocates +Allocates +allocating +allocation +allow +Allow +allowable +allowed +allowing +Allowing +allows +Allows +almost +alone +along +alphabetic +alphabetical +already +also +Also +alter +alteration +altered +altering +alternate +alters +Although +always +Always +among +Among +amount +ampersand +an +An +AN +and +AND +anddoublewords +ANDed +anomaly +another +Another +answer +anticipate +any +Any +ANY +anywhere +Ap +apparent +appear +appears +appendices +Appendices +Appendix +appends +application +Application +applications +Applications +APPLICATIONS +applied +Applied +applies +apply +applying +approach +approaches +appropriate +Approximate +approximately +AR +arbitrarily +arbitrary +architectural +architecture +Architecture +architectures +are +ARE +area +areas +argument +arguments +arise +arithmetic +Arithmetic +arithmetically +armed +around +ARPL +arrangement +arranging +array +Array +arrest +arrives +as +As +AS +ASCII +ASM +aspect +aspects +assembled +assembler +assembly +Assembly +assert +Assert +asserted +assertion +asserts +assign +Assign +assigned +assigning +assignment +assignments +Assignments +assigns +assist +assistance +associated +associates +associative +assume +Assume +ASSUME +assumed +Assumed +assumes +assuming +assumptions +Assumptions +assure +assured +asynchronous +at +At +AT +attached +attempt +Attempt +attempted +attempting +attempts +attention +attributable +attribute +Attribute +attributes +Attributes +auto +automatic +Automatic +automatically +auxiliary +AUXILIARY +Av +AVAIL +available +Available +AVAILABLE +Avenue +AVL +avoid +AVOID +avoidable +avoided +avoiding +avoids +aware +away +awhile +ax +AX +b +B +BA +back +Back +BACK +backlink +backward +Bad +bas +base +Base +BASE +based +basic +Basic +BB +BC +BCD +BD +be +Be +BE +because +Because +become +becomes +been +before +Before +BEFORE +begin +beginning +Beginning +begins +begun +behave +behaves +behind +being +belong +below +Below +benefit +benefits +Benelux +benign +Benign +Besides +best +between +Between +beyond +Beyond +BEYOND +BF +BH +big +BIG +binary +Binary +BINARY +Bind +binders +bit +Bit +BIT +BitBase +BITBASE +bitbus +BITBUS +bitmap +BitOffset +BITOFFSET +bits +Bits +BITS +BitStringAddr +BL +blank +BLD +blink +block +Block +BLock +blocks +blt +BLT +BltLoop +Bn +board +book +books +Boolean +bootstrap +borrow +Borrow +borrowed +Boston +both +Both +bottom +BOTTOM +bound +BOUND +boundaries +Boundaries +boundary +bounds +Bounds +Bowers +BP +BPM +brackets +Brackets +branch +BranchCond +branches +branching +breadth +Break +Breakpeint +breakpoint +Breakpoint +BREAKPOINT +breakpoints +Breakpoints +briefly +bring +brings +broadcast +BS +BSF +BSR +BT +BTC +BTR +BTS +Bubble +BUBBLE +buffer +Buffer +Buffers +bug +bugs +build +builder +Builder +builders +bump +bus +Bus +BUS +busy +Busy +BUSY +but +But +BX +by +By +BY +bypasses +byte +Byte +BYTE +bytes +Bytes +BYTES +c +C +CA +cache +Cache +cacheability +cached +caches +calculate +calculated +calculates +calculation +Calculation +calculations +call +Call +CALL +called +Called +CALLed +caller +calling +calls +Calls +CALLs +can +Can +Canada +cannot +capabilities +capability +capable +care +careful +caret +carried +carry +Carry +CARRY +case +Case +CASE +cases +catalog +catches +categories +category +cause +Cause +caused +causes +Causes +causing +causingthe +caution +cautious +cb +CB +CBW +cc +CC +CCH +cd +Cd +CD +CDQ +CE +ceiling +center +Center +Centers +central +certain +Certain +Certified +CF +CFh +CG +CH +chain +chaining +change +Change +changed +CHANGED +changes +changing +Changing +Chaper +chapter +Chapter +chapters +Chapters +character +Character +characteristics +characterized +characters +check +Check +CHECK +checked +checking +Checking +checks +Checks +CheckString +Chicago +chip +choice +choices +choose +chooses +choosing +Choosing +chosen +chunk +circled +circuitry +circumstances +cited +CL +Clara +clarity +class +Class +classes +Classes +classification +classified +classifies +CLC +CLD +clear +Clear +cleared +Cleared +clearing +Clearing +Clearly +clears +CLI +clock +Clock +clocks +Clocks +CLOCKS +close +closely +CLTS +cluster +CMC +CMP +CMPB +CMPS +CMPSB +CMPSD +CMPSW +CMPW +code +Code +CODE +coded +CODED +codes +Codes +coding +collection +colon +column +columns +combination +combinations +Combinations +combine +combined +Combined +combines +combining +Combining +comes +command +commands +Comments +COMMENTS +commitment +committed +common +commonly +COMMputer +communicated +communicates +compact +compactly +compare +Compare +compared +compares +comparing +comparison +Comparison +comparisons +Compatability +compatibility +Compatibility +COMPATIBILITY +compatible +compiled +compiler +compilers +complement +Complement +complemented +complements +complete +Complete +completed +completely +completes +completion +complexities +component +Component +components +composed +Compound +COMPS +computation +Computation +computations +compute +computed +computes +concatenated +concatenates +concept +concepts +concerned +concerning +concurrently +cond +condition +Condition +conditional +Conditional +conditions +Conditions +confidence +configuration +configurations +confined +conformance +conforming +Conforming +CONFORMING +conforms +confusion +conjunction +connection +consecutive +Consequently +consider +Considerations +considered +considering +Considers +consist +consistent +consisting +consists +constant +constants +constrain +constraint +construct +constructed +consult +consulting +Consulting +consults +consume +contact +Contact +contain +contained +containing +contains +Contains +CONTAINS +content +contents +Contents +context +contiguous +continue +continued +continues +contracts +Contracts +contrary +contributory +Contributory +control +Control +CONTROL +controlled +controller +Controller +controllers +controlling +Controlling +controls +convenience +convenient +conveniently +convention +conventions +Conventions +conversion +Conversion +convert +Convert +converted +converting +converts +cooperate +cooperation +coordinate +coordinated +coordinates +Copenhagen +copied +copies +Coprecessor +Coprocessing +coprocessor +Coprocessor +COPROCESSOR +coprocessors +copy +Copy +copying +Corporation +CORPORATION +correct +correctly +corrects +correspond +correspondence +corresponding +corresponds +corrupt +corrupted +could +count +COUNT +Counter +COUNTER +counterparts +CountReg +counts +coupled +course +covered +covering +Covering +covers +cp +CPL +CPLs +CPU +CPUs +CR +create +created +creates +creating +Creation +CREDIT +criteria +critical +CRn +CRO +cross +Cross +crosses +crossing +crucial +CS +curly +current +Current +CURRENT +currently +CUSTOM +customarily +customer +Customer +customers +customizing +cw +CWD +CWDE +cx +CX +cycle +cycles +d +D +DA +DAA +damage +danger +DAS +data +Data +DATA +date +days +DB +DC +Dd +DD +DE +deal +dealing +deallocated +debug +Debug +debugger +debuggers +Debuggers +debugging +Debugging +dec +DEC +decimal +Decimal +DECIMAL +declared +decoded +decodes +decoding +decrement +Decrement +decremented +decrementing +decrements +dedicated +deeper +default +Default +DEFAULT +defaults +defeated +deferred +define +Define +DEFINE +defined +defines +Defines +definition +Definition +Definitions +degree +delay +delayed +delaying +delays +Delays +deleted +demand +demonstrate +denominator +denote +denoted +denotes +depend +DEPENDENCE +dependent +depending +Depending +depends +depth +derives +des +DES +DESC +describe +described +describes +describing +description +Description +descriptions +descriptive +descriptor +Descriptor +DESCRIPTOR +descriptors +Descriptors +DESCRIPTORS +design +designate +designated +designed +designers +Designers +designs +desirable +desired +dest +Dest +DEST +DestAddr +destination +Destination +DESTINATION +destinations +destined +DestReg +detail +detailed +details +Details +detect +Detect +detected +Detected +Detection +detects +determine +Determine +determined +determines +determining +developing +development +device +DEVICE +devices +DF +DH +di +DI +diagnose +diagnosing +diagnosis +DIAGRAM +dictionary +did +differ +difference +differences +Differences +different +Different +differently +differing +differs +difficult +digit +DIGIT +digits +dimension +dimensional +DIR +direct +Direct +direction +Direction +DIRECTION +directly +directories +DIRECTORIES +directory +Directory +DIRECTORY +dirty +Dirty +DIRTY +disable +Disable +disabled +DISABLED +disables +disabling +Disabling +discard +discarded +Discarded +discarding +discovered +discretion +discuss +discussed +discusses +Discusses +discussion +Discussion +disp +dispatch +dispatched +dispatching +displacement +Displacement +DISPLACEMENT +displacements +display +DISPLAY +displaying +disruptive +distinct +distinction +distinguish +distinguished +distinguishes +Distinguishes +Distribution +disturbing +DIV +divide +Divide +divided +dividend +Dividend +divides +dividing +divisible +division +Division +divisions +Divisions +divisor +Divisor +DL +do +Do +DO +document +documentation +does +doing +domain +Domain +don +Don +done +double +Double +DOUBLE +doubleword +Doubleword +DOUBLEWORD +doublewords +Doublewords +down +DOWN +DOWNTO +downward +DP +DPL +DPLs +DR +driven +driver +drivers +DRn +DRO +drop +DS +DSI +due +Due +DUMMY +dumped +DUP +duplicate +duration +during +During +DW +dword +DWORD +dwords +Dx +DX +dynamic +DYNAMIC +dynamically +e +E +EA +each +Each +EACH +earlier +early +EAS +easier +easily +easy +eAX +EAX +Eb +EB +EBCDIC +ebp +eBP +EBP +EBPA +EBPB +EBPM +eBX +EBX +EC +eCX +ECX +ED +eDI +EDI +eDX +EDX +EE +EF +effect +Effect +effective +Effective +EFFECTIVE +effectively +effects +efficiency +efficient +efficiently +effort +EFLAGS +eg +EH +eight +EIP +either +Either +EJECT +element +elements +eliminate +eliminated +eliminates +eliminating +else +ELSE +EM +embedded +employ +employed +employs +emulate +emulated +Emulating +emulation +Emulation +enable +Enable +ENABLE +enabled +ENABLED +enables +enabling +Enabling +enclosed +encode +encoded +encodes +encoding +encodings +encompass +encountered +encountering +encounters +end +End +END +ending +ends +ENDS +enforce +enforced +enforces +engaged +engineering +engineers +Engineers +enhance +enhanced +enough +ensure +Ensure +ensures +ensuring +enter +Enter +ENTER +entered +entering +Entering +enters +entire +entirely +entitled +entries +Entries +ENTRIES +entry +Entry +ENTRY +environment +environments +eP +Ep +EPB +epilog +eprom +EPROM +EPX +EQU +equal +Equal +equally +equals +equates +equivalent +er +ER +error +Error +ERROR +errors +Errors +es +ES +ESAC +ESC +escape +Escape +ESCAPE +eSI +ESI +esp +eSP +ESP +especially +essential +established +ET +etc +Ev +evaluated +evaluates +evaluating +evaluation +even +Even +evenly +event +events +every +Every +EvGvCL +EvGvIb +Ew +exact +exactly +examine +Examine +examined +examines +examining +example +Example +examples +Examples +exceed +Exceeded +Exceeding +exceeds +except +Except +exception +Exception +EXCEPTION +exceptional +exceptions +Exceptions +excessive +exchange +Exchange +exchanged +exchanges +excluding +exclusive +Exclusive +exclusively +executable +EXECUTABLE +execute +Execute +executed +executes +Executes +executing +Executing +execution +Execution +exeptions +exerts +exhausted +exist +existed +existence +existing +Existing +exists +exit +Exit +exited +exiting +exits +expand +Expand +EXPAND +expandable +expanded +Expands +expansion +Expansion +expect +expectations +expected +expedient +explain +explained +explaining +explains +Explains +explanation +Explanation +explanatory +explicit +Explicit +explicitly +exported +expressed +expression +expressions +expressly +EXT +extend +Extend +extended +Extended +extending +extends +extension +Extension +EXTENSION +extensions +Extensions +EXTENSIONS +extensive +extensively +external +External +externally +extra +Extra +extract +Extract +extracted +extraction +extremely +extremes +eXX +F +FA +facilitated +facilities +fact +factor +factors +factory +Fail +failed +failing +fails +failure +Failure +fall +falls +false +FALSE +families +family +far +Far +FAR +FARLABEL +fast +Fast +faster +FASTPATH +fault +Fault +FAULT +faulting +Faulting +faults +Faults +faulty +FB +FC +FD +FE +feasible +feature +features +Features +fetch +fetched +fetches +fetching +few +fewer +FF +FFEFH +FFF +FFFC +FFFDH +FFFE +FFFF +FFFFF +FFFFFFF +FFFFFFFFH +FFFFFH +FFFFH +FFFh +FFFH +FFH +FH +FI +field +Field +FIELD +fields +Fields +figure +Figure +Figures +file +files +fill +Fill +FILL +filled +fills +final +Find +finds +FINIT +first +First +FIRST +fit +fits +five +FIVE +fixed +fixes +flag +Flag +FLAG +flags +Flags +FLAGS +flat +Flat +FLAT +flexibility +flexible +floating +flow +flush +flushed +flushes +FNINIT +follow +followed +following +Following +follows +for +For +FOR +force +forces +forcing +forever +form +Form +formal +Formal +format +Format +formation +Formation +formats +Formats +former +formerly +forming +forms +Forms +formula +forward +Forward +found +four +Four +fourth +fragmented +fragments +frame +Frame +FRAME +frames +FRAMES +Francisco +FREAD +free +freedom +freely +frequency +from +From +FROM +FS +FSTENV +fulfill +full +Full +fully +function +Function +functionally +functions +Functions +fundamental +Fundamental +further +Further +Furthermore +future +Fv +FxFF +g +G +gap +gate +Gate +GATE +gated +gates +Gates +Gb +GB +Gbytes +GDL +gdt +GDT +GDTbase +GDTR +GE +general +General +GENERAL +Generalized +generally +generate +Generate +generated +Generated +generates +generating +generation +generations +Genius +get +Get +gets +gigabits +gigabyte +Gigabyte +gigabytes +GIGABYTES +give +given +gives +giving +global +Global +GLOBAL +Gn +go +GO +goes +going +GOTO +governs +GP +gran +granular +granularity +Granularity +GRANULARITY +graphically +graphics +great +greater +Greater +greatest +GREATEST +group +grouped +groupings +groups +grow +grows +Grp +Grpl +GS +guarantee +guaranteed +guarantees +Guard +Guide +guidelines +guides +guranteed +Gv +GvEvIv +Gw +h +H +had +half +Halt +HALT +halves +hand +handle +Handle +handled +handler +handlers +handles +handling +Handling +hardware +Hardware +has +HAS +have +having +Having +held +help +helps +Helps +here +herein +hex +hexadecimal +Hexadecimal +hidden +HIDDEN +high +High +HIGH +higher +highest +HIGHEST +highlighted +highlights +highly +hit +hlt +HLT +hold +Hold +HOLD +Holding +holds +holes +Hong +hours +how +How +however +However +HOWEVER +HT +hundreds +hypothetical +i +I +iAPX +ib +Ib +ICE +iCEL +iCS +id +ID +iDBP +ideals +identical +identically +identification +Identification +identified +identifier +Identifier +identifiers +identifies +Identifies +identify +identifying +Identifying +identity +iDIS +IDIV +IDs +idt +IDT +IDTbase +IDTR +IEEE +if +If +IF +ignore +ignored +ignores +II +III +iLBX +illegal +illustrate +illustrated +illustrates +illustrations +im +image +images +iMDDX +imm +immediate +Immediate +IMMEDIATE +immediately +Immediately +iMMX +implement +Implement +implementation +Implementation +implemented +implementing +implements +Implements +implications +implicit +Implicit +implicitly +implied +Implied +implies +imply +implying +important +imposed +imposes +improper +improperly +Improperly +IMUL +in +In +IN +inaccessible +inactive +Inactive +inappropriate +inBits +Inboard +INC +IncDec +include +included +includes +including +INCLUDING +inclusive +Inclusive +incoming +Incoming +incompatible +inconsistent +Inconsistent +incorrectly +increase +increased +increment +Increment +incremented +incrementing +increments +IndDec +Indeed +independent +indeterminate +index +Index +INDEX +indexed +indexes +Indexes +indexing +Indexing +INDEXING +indicate +indicated +indicates +INDICATES +indicating +indication +indicator +Indicator +INDICATOR +indices +Indirct +indirect +Indirect +indirection +indirectly +Indirectly +indistinguishable +individual +individually +individuals +indivisible +inevitable +infinite +infinity +influence +influences +information +Information +inherently +inhibit +inhibited +inhibits +init +INIT +inital +initally +initial +Initial +INITIAL +initialization +Initialization +initialize +initialized +initializes +initializing +initially +initiates +inner +INNER +innovation +input +Input +inputs +INS +INSB +INSD +insert +Insert +inserted +inserting +insertion +inside +Insite +inspected +instances +instant +instead +Instead +instruction +Instruction +INSTRUCTION +instructional +instructions +Instructions +INSTRUCTIONS +insufficient +insure +INSW +INT +integer +Integer +INTEGER +integers +Integers +integral +Integrated +integrity +Integrity +intel +Intel +INTEL +intelBOS +Intelevision +inteligent +Intellec +intelligent +Intellink +intended +inter +intercept +intercepted +interchangeably +interest +interface +Interface +interfaces +interfacing +interfere +interference +interfering +Interievel +interlevel +Interlevel +intermediate +internal +INTERNAL +internally +international +Interposing +interpret +interpretation +Interpretation +interpretations +interpreted +interpreting +Interpreting +interprets +interprocessor +interrogate +interrogated +interrupt +Interrupt +INTERRUPT +interrupted +Interrupted +interrupting +interruption +interrupts +Interrupts +intersegment +intertask +intervention +Intervention +into +INTO +intoBX +INTR +intralevel +intrasegment +intrastack +introduced +introduces +Introduces +introduction +Introduction +invalid +Invalid +Invalidate +inverts +invisible +INVISIBLE +invoke +Invoke +invoked +invokes +invoking +involve +involved +involves +involving +IO +IOPL +iOSP +IP +iPDS +iPSC +IRET +IRETD +IRETs +iRMK +iRMX +is +Is +IS +iSBC +iSBX +iSDM +isolate +isolated +isolation +Isreal +issued +iSXM +it +It +IT +item +items +ITEMS +iterated +iteration +iterations +its +Its +itself +Iv +IV +iw +Iw +J +JA +JAE +Jb +JB +JBE +JC +Jcc +Jcond +JCXZ +JE +JECXZ +JG +JGE +JL +JLE +jmp +JMP +JNA +JNAE +JNB +JNBE +JNC +JNE +JNG +JNGE +JNL +JNLE +JNO +JNP +JNS +jnz +JNZ +JO +JP +JPE +JPO +JS +jump +Jump +jumped +jumps +Jumps +just +Just +justified +justify +Jv +JZ +K +Kbyte +Kbytes +keeps +KEPROM +KERNAL +kernel +key +Key +keywords +kilobytes +Kilobytes +kind +kinds +know +knowledge +known +Kong +L +label +LABEL +labeled +labelled +lack +LAHF +LAN +language +Language +languages +Languages +LAR +large +largely +larger +largest +last +Last +LAST +later +latest +latter +layout +Layout +LDS +LDT +LDTR +LDTs +LE +LEA +lead +leading +learn +least +LEAST +leave +Leave +LEAVE +leaves +leaving +Leaving +led +left +Left +LEFT +LeftSRC +legal +legitimately +LEN +length +Length +LENn +LES +less +Less +lesser +let +Let +letter +letters +level +Level +LEVEL +levels +Levels +lexical +LEXICAL +LFS +LGDT +LGS +libraries +Library +LIDT +lie +lies +like +Like +likely +Likewise +lim +limit +Limit +LIMIT +limitation +limitations +limited +limiting +limits +LIMT +line +linear +Linear +LINEAR +lines +link +Link +LINK +linkage +linkages +Linkages +linkers +linking +Linking +links +list +listed +listing +lists +literals +literature +Literature +little +LLDT +LMSW +Ln +load +Load +loaded +loader +loaders +loading +Loading +loadings +LOADREG +loads +Loads +LOADS +local +Local +LOCAL +locate +located +locates +locating +location +Location +locations +Locations +LOCATIONS +locators +lock +Lock +LOCK +locked +Locked +LOCKed +locking +Locking +LODS +LODSB +LODSD +LODSW +log +logic +logical +Logical +LOGICAL +logically +London +long +Long +longer +look +Look +lookaside +Lookaside +lookup +Lookup +lookups +Lookups +loop +Loop +LOOP +LOOPcond +LOOPE +looping +LOOPNE +LOOPNZ +Loops +LOOPZ +loosely +loss +lost +LOT +low +LOW +lower +Lower +lowercase +lowest +LOWEST +LSB +LSL +LSS +LTD +LTR +m +M +Ma +Machanism +machine +Machine +machines +made +Made +Magazine +magnitude +MAGNITUDE +Mail +main +MAIN +maintain +maintained +maintaining +maintains +maintenance +major +make +Make +makes +making +manage +managed +management +Management +Manager +manages +manipulate +manipulated +manipulates +manipulation +Manipulation +manipulationinstructions +manner +manual +Manual +MANUAL +many +Many +map +Map +MAP +MAPNET +mapped +Mapped +mapping +Mapping +mappings +maps +mark +Mark +marked +MARKED +market +marking +mask +Mask +maskable +Maskable +masked +masking +masks +Masks +MaskShift +masters +match +Match +matches +matching +Matching +material +math +Math +matter +max +Max +MAX +maximum +may +May +Mbyte +Mbytes +MCS +MDS +mean +meaning +Meaning +means +MEANS +mechanism +Mechanism +mechanisms +Mechanisms +meet +megabyte +megabytes +Megachassis +mem +members +memory +Memory +MEMORY +mention +mentioned +merely +met +Met +method +Method +methods +Methods +MF +microcommunications +microcontrollers +MICROMAINFRAME +microprocessor +Microprocessor +microprocessors +middle +might +Milan +min +Min +minimum +minor +misaligned +misalignment +Miscellaneous +miss +mistake +mix +mixed +Mixed +mixes +mixing +Mixing +mnemonic +Mnemonic +mnemonics +mod +Mod +MOD +mode +Mode +MODE +model +Model +models +modes +Modes +modification +modifications +modified +modifier +modifies +modify +Modify +modifying +Modifying +modR +ModR +MODR +ModRM +module +MODULE +modules +Modules +modulo +MODULO +moffs +Mohawk +monitor +MONITOR +monitored +monitoring +more +More +MORE +most +Most +MOST +mostflexible +mov +MOV +move +Move +moved +movement +Movement +moves +moving +MOVS +MOVSB +MOVSD +MOVSW +MOVSX +MOVZX +Mp +MP +Ms +MSB +MSW +much +MUL +multi +multibit +MULTIBUS +MULTICHANNEL +MULTIMODULE +multiple +multiples +multiplicand +multiplication +Multiplication +multiplied +multiplier +multiplies +multiply +Multiply +multiprecision +multiprocessing +Multiprocessing +multiprocessor +multiprogram +multiprogrammed +MultiSERVER +multitasking +Multitasking +Munich +must +Must +n +N +NA +NAE +name +Name +NAME +named +namely +names +native +natural +nature +NB +NBE +nBitMask +NE +near +Near +NEAR +nearest +necessarily +necessary +need +needed +Needed +needing +needs +NEG +negate +Negate +Negation +negative +NEGATIVE +neither +Neither +nested +Nested +NESTED +nesting +network +never +Nevertheless +new +New +NEW +next +NG +NGE +nibble +nibbles +NL +NLE +NM +NMI +NMIs +NMls +nnn +no +No +NO +NoAdjust +non +Non +nonbusy +nonconforming +NONCONFORMING +Nonconventional +none +None +nonetheless +Nonintegral +nonmaskable +Nonmaskable +nonmatching +nonwritable +nonzero +nop +NOP +nor +normal +normally +Normally +not +Not +NOT +notation +notational +Notational +notations +Note +NOTE +Notes +NOTES +nothing +notice +now +Now +NP +NPX +NS +NT +null +NULL +number +Number +NUMBER +numbered +numbers +Numbers +numerator +numeric +Numeric +numerical +numerically +numerics +NZ +o +O +Ob +OB +object +objectives +objects +observe +observed +obtain +obtained +obtains +obvious +occasions +occupies +occupy +occur +occurred +occurrence +occurrences +occurs +OD +odd +of +Of +OF +ofCR +off +offered +offerings +offers +office +offices +offset +Offset +OFFSET +offsets +Offsets +often +OK +old +Old +OLD +Older +omitting +on +On +ON +onbyte +once +Once +ONCE +one +One +ones +only +Only +ONLY +onto +opcode +Opcode +OPCODE +opcodes +Opcodes +OpenNET +operand +Operand +OPERAND +OperandMode +operands +Operands +OPERANDS +OperandSize +Operant +operate +OPERATE +operated +operates +operating +Operating +operation +Operation +operational +operations +Operations +operators +opportunity +opposite +optimization +optimized +optimizing +optimum +option +optional +optionally +options +or +OR +order +ordering +ordinal +Ordinal +ORDINAL +ordinarily +Ordinarily +ordinary +organization +Organization +organized +oriented +origin +original +originally +originated +originates +OS +Osaka +other +Other +OTHER +others +Others +otherwise +Otherwise +OTP +our +out +Out +OUT +outer +Outer +OUTER +outgoing +output +Output +OUTS +OUTSB +OUTSD +outside +OUTSW +Ov +over +overcome +overflow +Overflow +OVERFLOW +overhead +overlap +overlapped +overlapping +Overlapping +overridden +override +OVERRIDE +overrides +Overrides +overriding +overrun +Overrun +overview +Overview +overviews +overwrite +overwrites +overwriting +overwritten +own +p +P +package +packed +Packed +PACKED +padded +page +Page +PAGE +paged +pages +Pages +paging +Paging +PAGING +pair +pairs +Pairs +paragraphs +parallel +parameter +Parameter +parameters +Parameters +parceled +parentheses +Paris +parity +Parity +PARITY +PARM +part +Part +PART +partial +partially +Partially +participating +particular +partly +parts +Parts +Pascal +pass +Pass +passed +passes +past +path +paths +pattern +PATTERN +PC +PDBR +PDE +PDEs +PDPR +PE +penalty +pending +per +perfectly +perform +Perform +performance +Performance +performed +Performed +performI +performing +performs +periodically +peripheral +permissible +permission +Permission +PERMISSION +permit +Permit +permits +Permits +permitted +permitting +personalizing +perspective +perspectives +pertains +PF +PG +phase +phases +Phone +physical +Physical +PHYSICAL +PIC +picture +pieces +pin +Pin +pinpointing +pins +Pipeline +PL +place +Place +placed +places +placing +planted +Plug +plus +pm +PO +point +Point +POINT +pointed +pointer +Pointer +POINTER +pointers +Pointers +POINTERS +pointing +points +Points +policies +pop +Pop +POP +POPA +POPAD +POPF +POPFD +popped +POPPED +popping +Popping +pops +POPS +port +Port +ported +porting +Porting +portion +portions +ports +position +POSITION +positions +POSITIONS +positive +POSITIVE +possess +possibilities +possibility +possible +possibly +potential +pound +power +practice +preceded +preceding +preceeded +preceeding +precise +precision +Precision +predefined +predetermined +predictable +predominant +preferred +prefetch +prefetched +prefetching +prefix +Prefix +PREFIX +prefixes +Prefixes +prepare +Prepare +prepares +presence +PRESENCE +present +Present +PRESENT +presents +Presents +preserve +preserved +preserves +PRESERVES +preserving +presumably +prevail +prevent +prevented +preventing +prevents +Prevents +previous +PREVIOUS +previously +primarily +primary +primitive +primitives +principal +prior +priorities +priority +Priority +privilege +Privilege +PRIVILEGE +privileged +Privileged +privileges +probably +problem +problems +procedure +Procedure +PROCEDURE +procedures +Procedures +proceed +proceeds +process +processed +processing +processor +Processor +processors +produce +produced +produces +producing +product +production +products +Products +program +Program +PROGRAM +Programmable +programmed +Programmed +programmer +Programmer +PROGRAMMER +programmers +Programmers +PROGRAMMERS +programming +Programming +PROGRAMMING +programs +Programs +PROGRAMS +prolog +PROMPT +Promware +Prooedure +proper +properly +properties +property +protect +protected +Protected +PROTECTED +protection +Protection +PROTECTION +protocol +provide +provided +provides +providing +pseudo +Pseudo +PT +PTE +PTEs +ptr +Ptr +PTR +PUBLIC +Pulse +purchases +pure +Pure +purpose +Purpose +purposes +push +Push +PUSH +PUSHA +PUSHAD +pushed +PUSHED +pushes +PUSHF +PUSHFD +pushing +put +Put +puts +putting +pword +PWORD +quad +Quad +Quadword +quantities +quantity +QUEST +question +queue +queuing +QueX +quick +Quick +quickly +quite +Quo +quotient +Quotient +quotients +r +R +raise +raised +raises +ram +RAM +range +Range +ranges +ranging +rapidly +rate +rather +raw +rb +RCL +RCR +rd +Rd +re +reach +reachable +reaches +reacts +read +Read +READ +readable +READABLE +reading +Reading +reads +Reads +ready +real +Real +REAL +reality +rearrange +reason +reasons +rebinding +receipt +receive +received +receives +RECEIVES +recent +recently +RECIEVES +recognition +Recognition +recognize +recognized +recognizes +recommended +record +recording +records +recover +recovering +redefines +redirect +rediscovered +reduce +reduces +reducing +redundant +Redundant +reenter +reentered +reenters +reentrable +reentrant +reentry +reexecuted +refer +Refer +reference +Reference +REFERENCE +referenced +references +References +referencing +referred +referring +Referring +refers +reflect +reflected +Reflecting +reg +Reg +REG +regard +regardless +REGARDLESS +region +register +Register +REGISTER +registered +registers +Registers +REGISTERS +regular +regularly +reimplement +rel +relate +related +Related +relates +relation +relational +relationship +relative +release +released +releases +relevance +relevant +reliable +relink +relinking +reload +reloaded +reloading +relocated +relocation +Relocation +RelOffset +rely +Rem +remain +remainder +Remainder +remaining +REMAINING +remains +remove +removed +removes +REP +repair +REPE +repeat +Repeat +repeated +Repeated +repeatedly +repetition +repetitions +replace +replaced +replaces +replacing +REPNE +REPNZ +report +reported +reporting +reports +reposition +represent +representation +represented +representing +represents +reproducible +REPZ +request +requested +Requested +requestor +Requestor +REQUESTOR +requests +require +required +requirement +requirements +requires +requiring +resembles +reserve +Reserve +reserved +Reserved +RESERVED +reserving +reset +Reset +RESET +resets +Resetting +reside +resident +resides +resource +resources +respective +respectively +respects +respond +responding +responds +response +responses +responsibility +responsible +rest +restart +restartable +restarted +restarting +restore +restored +restores +restoring +Restoring +restricted +Restricted +restricting +Restricting +restriction +Restriction +restrictions +result +Result +resulting +results +resume +Resume +RESUME +resumed +resumes +resuming +ret +RET +retain +retains +retries +retry +retrying +return +Return +RETURN +returned +returning +Returning +returns +Returns +reveal +Reveals +reverse +Reverse +reverses +review +revision +RF +right +Right +RIGHT +rightmost +rights +Rights +RightSRC +ring +rings +Ripplemode +risks +RMX +robust +ROL +ROM +ROMcode +ROMmed +room +ROR +rotate +Rotate +rotated +rotates +Rotates +rotation +Rotterdam +rounded +rounding +routine +routines +row +rows +RPL +rule +Rule +rules +Rules +run +runaway +running +runs +RUPI +rw +Rw +RW +RWn +s +S +safely +SAHF +sake +SAL +sales +same +Same +SAME +San +Santa +SAR +satisfaction +satisfied +satisfies +satisfy +save +Save +saved +Saved +saves +saving +Saving +SBB +SC +SCAB +scalar +scale +Scale +SCALE +scaled +Scaled +scaling +scan +Scan +scanned +scanning +scans +SCAS +SCASB +SCASD +SCASW +SCAW +scheduled +scheduler +schedulers +Sciences +scope +ScrAddr +scratch +script +scripts +Scripts +Scrutinize +Seamless +search +second +Second +SECOND +section +sections +see +See +seen +sees +seg +SEG +SEGMEMT +segment +Segment +SEGMENT +segmentation +Segmentation +segmented +Segmented +segments +Segments +SEGMENTS +SegReg +seldom +select +selected +Selected +SELECTED +selecting +selection +Selection +selective +selectively +Selectively +selector +Selector +SELECTOR +selectors +Selectors +selects +Selects +self +semantics +Semantics +semaphore +semaphores +send +sending +sense +sensitive +Sensitive +separate +Separate +separated +separately +Separately +sequence +sequences +sequential +Sequential +serially +series +serve +serves +service +Service +serviced +services +Services +SERVICES +servicing +set +Set +SET +SETA +SETAE +SETB +SETBE +SETC +SETcc +SETcond +SETE +SETG +SETGE +SETL +SETLE +SETNA +SETNAE +SETNB +SETNBE +SETNC +SETNE +SETNG +SETNGE +SETNL +SETNLE +SETNO +SETNP +SETNS +SETNZ +SETO +SETP +SETPE +SETPO +sets +Sets +SETS +setting +Setting +settings +SETZ +several +Several +severe +SF +SGDT +share +shared +SHARED +sharing +Sharing +Sheet +shift +Shift +ShiftAmt +shifted +SHIFTED +shifting +shifts +SHIFTS +shl +SHL +SHLD +short +Short +SHORT +shortened +should +showing +shown +shows +Shows +SHR +SHRD +shut +shutdown +shuts +si +SI +SIB +side +SIDT +sign +Sign +SIGN +signal +Signal +signalled +signals +signed +Signed +SignExtend +significance +significant +SIGNIFICANT +significantly +similar +similarly +Similarly +simple +Simple +simpler +simplicity +simplification +simplified +simplifies +simplify +simply +simulate +Simulate +simulated +simulating +Simultaneous +simultaneously +since +Since +single +Single +site +SITE +situation +six +Six +sixteen +size +Size +SIZE +sizes +skip +Skip +slash +SLD +SLDT +slight +slows +small +smaller +Smaller +smallest +SMALLEST +SMSW +so +software +Software +SOFTWARE +sold +sole +solely +solution +solutions +solved +some +Some +sometimes +Sometimes +somewhat +sophisticated +sort +Sortware +source +Source +SOURCE +sources +SP +space +Space +SPACE +spaces +Spaces +span +spanned +Spanning +spans +special +Special +SPECIAL +specialized +specific +specifically +specification +specifications +specified +SPECIFIED +specifier +specifiers +specifies +Specifies +specify +specifying +Specifying +speed +spooling +spurious +squeezed +Src +SRC +Sreg +ss +SS +stack +Stack +STACK +StackAddrSize +stacks +Stacks +StackTop +standard +Standard +start +Start +START +started +starting +starts +Starts +state +State +STATE +statement +statements +states +static +statically +status +Status +STATUS +STC +STD +step +Step +stepped +stepping +STEPPING +steps +STI +still +Stockholm +stop +Stop +stopped +stops +storage +STORAGE +store +Store +stored +stores +STORES +storing +STOS +STOSB +STOSD +STOSW +STR +strategies +strategy +stream +strg +strictly +string +String +STRING +strings +Strings +STRUC +structure +Structure +STRUCTURE +structured +Structured +structures +study +stuff +style +styles +sub +Sub +SUB +Subcode +subject +subroutine +Subroutine +subscript +Subscript +subscription +subscripts +subsequent +subsequently +subset +Subset +subsets +subspaces +substituting +substring +subsystem +SUBTOTAL +subtract +Subtract +subtracted +subtracting +subtraction +Subtraction +subtracts +subunits +succeeding +successful +successfully +such +Such +sufficient +sufficiently +suffix +SugarCube +suits +sum +summarize +summarized +summarizes +summary +Summary +sums +super +Super +Superscript +supervisor +Supervisor +SUPERVISOR +supplied +supplier +supplies +supply +supplying +support +Support +supported +SupportNET +supports +suppose +sure +surrounded +Surveys +suspend +suspended +suspends +Sw +SW +swap +Swap +swaps +switch +Switch +SWITCH +switched +Switched +switches +Switches +switching +Switching +symbol +symbolic +symbolically +symbols +synchronization +synchronous +synonym +SYNONYM +Synonymous +synonyms +syntax +system +System +SYSTEM +systems +Systems +SYSTEMS +t +T +table +Table +TABLE +tables +Tables +TABLES +tag +TAG +tags +Tags +tailoring +take +taken +takes +taking +Taking +target +TARGET +task +Task +TASK +tasks +Tasks +TASKS +TBL +Td +technical +Technical +technique +tells +Tells +temp +Temp +TempEFlags +TempESP +template +temporarily +temporary +TempSS +tempted +ten +terabyte +terabytes +terminate +terminated +terminates +termination +Termination +terminology +terms +test +Test +TEST +tested +Tested +testing +Testing +tests +Tests +TF +tGDT +TGDT +th +than +that +That +the +The +THE +thebit +theInterrupt +their +them +THEM +themselves +then +Then +THEN +theoretically +theory +therating +there +There +thereafter +thereby +therefore +Therefore +these +These +THESE +they +They +things +third +Third +this +This +those +Those +though +Though +thousands +three +Three +through +Through +throughout +throughput +throw +throwaway +thru +thus +Thus +TI +tied +tightly +time +times +Times +timing +TIPS +TITLE +TLB +TM +tmpcf +to +To +TO +together +Tokyo +too +took +tools +top +Top +TOP +topics +topmost +Toronto +tos +TOS +total +TOTAL +toward +towards +TR +trademark +trademarks +training +Training +transcendental +transfer +Transfer +transferred +transferring +Transferring +transfers +Transfers +transformation +transforms +Transition +TRANSITION +transitions +Transitions +translate +Translate +translated +translating +translation +Translation +TRANSLATION +translations +transparent +transported +trap +Trap +TRAP +trapped +trapping +traps +Traps +treat +treated +treats +trigger +triggered +triggers +TRn +troubleshooting +true +TRUE +truncate +Truncate +truncated +truncates +truncation +trusted +Trusted +try +trying +ts +TS +TSS +TSSs +turn +turned +twice +two +Two +type +Type +TYPE +types +Types +typical +typically +Typically +u +U +UD +unaffected +unaligned +unaltered +unary +Unary +unassigned +unauthorized +unchanged +Unchanged +unconditional +Unconditional +unconditionally +undefined +Undefined +UNDEFINED +under +Under +underlined +understanding +unequal +uniform +uninitialized +uninterruptible +unique +UNIQUE +uniquely +unit +units +UNIX +unless +unlike +Unlike +unlikely +unmasked +unmodified +unpacked +Unpacked +unpacks +unpredictability +unpredictable +unprivileged +unprogrammed +unprotected +unrecognized +unscrambled +unsegmented +unsigned +Unsigned +unspecified +until +Until +untrusted +unused +UNUSED +unwanted +unwittingly +up +update +Update +updated +updates +updating +Updating +UPI +upon +Upon +UPON +upper +Upper +uppercase +uppermost +upward +upwards +US +usable +usage +Usage +usages +use +Use +USE +used +Used +USED +useful +Useful +USEl +user +User +USER +users +uses +using +Using +usual +usually +utilization +utilize +utilized +UU +uuuuuuuT +uuuuuuuu +v +V +VACATED +val +valid +Valid +validate +validates +validation +Validation +validity +Validity +value +Value +VALUE +values +Values +VALUES +variable +Variable +variables +variant +variants +variations +varies +variety +various +variousconditions +vary +vector +Vector +vectored +Vectoring +vectors +Verification +verified +verifies +verify +Verify +verifying +VERR +VERRW +versa +versed +version +versions +VERW +very +via +Via +vice +view +viewed +violate +violated +violates +Violating +violation +violations +virtual +Virtual +VIRTUAL +virtualized +Virtualizing +visible +VISIBLE +VLSiCEL +VM +w +W +wait +Wait +WAIT +waiting +Waits +want +warranty +was +Washington +way +ways +Ways +we +weakened +weeks +well +were +what +whatever +when +When +WHEN +whenever +where +whereas +whether +Whether +which +WHICH +while +While +WHILE +who +whole +wholly +whose +Why +wide +width +will +wise +wish +with +With +WITH +within +without +Without +WITHOUT +Wn +word +Word +WORD +WordCnt +words +Words +woridwide +work +Working +workshop +workshops +worldwide +worse +would +wrap +wraparound +Wraparound +wrapping +wraps +writability +writable +Writable +WRITABLE +write +Write +WRITE +Writer +writes +Writes +writing +Writing +written +wrong +x +X +Xb +XCHG +XCNG +xero +XLAT +XLATB +xor +XOR +XORed +Xv +xx +Y +Yb +Yes +YES +yet +yield +you +You +your +Yv +Z +zero +Zero +ZERO +ZeroExtend +zeros +ZEROS +ZF +Zz diff --git a/bench/src/bench.rs b/bench/src/bench.rs index c5549ba..1076f90 100644 --- a/bench/src/bench.rs +++ b/bench/src/bench.rs @@ -1,30 +1,47 @@ use criterion::{ - criterion_group, criterion_main, Bencher, Benchmark, Criterion, Throughput, + criterion_group, criterion_main, Bencher, Criterion, Throughput, }; mod data; mod memchr; +mod memmem; fn all(c: &mut Criterion) { memchr::all(c); + memmem::all(c); } +/// A convenience function for defining a Criterion benchmark using our own +/// conventions and a common config. +/// +/// Note that we accept `bench` as a boxed closure to avoid the costs +/// of monomorphization. Particularly with the memchr benchmarks, this +/// function getting monomorphized (which also monomorphizes via Criterion's +/// `bench_function`) bloats compile times dramatically (by an order of +/// magnitude). This is okay to do since `bench` isn't the actual thing we +/// measure. The measurement comes from running `Bencher::iter` from within` +/// bench. So the dynamic dispatch is okay here. fn define( c: &mut Criterion, - group_name: &str, - bench_name: &str, + name: &str, corpus: &[u8], - bench: impl FnMut(&mut Bencher<'_>) + 'static, + bench: Box) + 'static>, ) { - let tput = Throughput::Bytes(corpus.len() as u64); - // let benchmark = Benchmark::new(bench_name, bench).throughput(tput); - - let benchmark = Benchmark::new(bench_name, bench) - .throughput(tput) - .sample_size(30) + // I don't really "get" the whole Criterion benchmark group thing. I just + // want a flat namespace to define all benchmarks. The only thing that + // matters to me is that we can group benchmarks arbitrarily using the + // name only. So we play Criterion's game by splitting our benchmark name + // on the first flash. + // + // N.B. We don't include the slash, since Criterion automatically adds it. + let mut it = name.splitn(2, "/"); + let (group_name, bench_name) = (it.next().unwrap(), it.next().unwrap()); + c.benchmark_group(group_name) + .throughput(Throughput::Bytes(corpus.len() as u64)) + .sample_size(10) .warm_up_time(std::time::Duration::from_millis(500)) - .measurement_time(std::time::Duration::from_secs(2)); - c.bench(group_name, benchmark); + .measurement_time(std::time::Duration::from_secs(2)) + .bench_function(bench_name, bench); } criterion_group!(does_not_matter, all); diff --git a/bench/src/data.rs b/bench/src/data.rs index c893f56..585c405 100644 --- a/bench/src/data.rs +++ b/bench/src/data.rs @@ -1,6 +1,64 @@ +#![allow(dead_code)] + pub const SHERLOCK_HUGE: &'static [u8] = - include_bytes!("../data/sherlock-holmes-huge.txt"); + include_bytes!("../data/sherlock/huge.txt"); pub const SHERLOCK_SMALL: &'static [u8] = - include_bytes!("../data/sherlock-holmes-small.txt"); + include_bytes!("../data/sherlock/small.txt"); pub const SHERLOCK_TINY: &'static [u8] = - include_bytes!("../data/sherlock-holmes-tiny.txt"); + include_bytes!("../data/sherlock/tiny.txt"); + +pub const SUBTITLE_EN_HUGE: &'static str = + include_str!("../data/opensubtitles/en-huge.txt"); +pub const SUBTITLE_EN_MEDIUM: &'static str = + include_str!("../data/opensubtitles/en-medium.txt"); +pub const SUBTITLE_EN_SMALL: &'static str = + include_str!("../data/opensubtitles/en-small.txt"); +pub const SUBTITLE_EN_TINY: &'static str = + include_str!("../data/opensubtitles/en-tiny.txt"); +pub const SUBTITLE_EN_TEENY: &'static str = + include_str!("../data/opensubtitles/en-teeny.txt"); + +pub const SUBTITLE_RU_HUGE: &'static str = + include_str!("../data/opensubtitles/ru-huge.txt"); +pub const SUBTITLE_RU_MEDIUM: &'static str = + include_str!("../data/opensubtitles/ru-medium.txt"); +pub const SUBTITLE_RU_SMALL: &'static str = + include_str!("../data/opensubtitles/ru-small.txt"); +pub const SUBTITLE_RU_TINY: &'static str = + include_str!("../data/opensubtitles/ru-tiny.txt"); +pub const SUBTITLE_RU_TEENY: &'static str = + include_str!("../data/opensubtitles/ru-teeny.txt"); + +pub const SUBTITLE_ZH_HUGE: &'static str = + include_str!("../data/opensubtitles/zh-huge.txt"); +pub const SUBTITLE_ZH_MEDIUM: &'static str = + include_str!("../data/opensubtitles/zh-medium.txt"); +pub const SUBTITLE_ZH_SMALL: &'static str = + include_str!("../data/opensubtitles/zh-small.txt"); +pub const SUBTITLE_ZH_TINY: &'static str = + include_str!("../data/opensubtitles/zh-tiny.txt"); +pub const SUBTITLE_ZH_TEENY: &'static str = + include_str!("../data/opensubtitles/zh-teeny.txt"); + +pub const PATHOLOGICAL_MD5_HUGE: &'static str = + include_str!("../data/pathological/md5-huge.txt"); +pub const PATHOLOGICAL_RANDOM_HUGE: &'static str = + include_str!("../data/pathological/random-huge.txt"); +pub const PATHOLOGICAL_REPEATED_RARE_HUGE: &'static str = + include_str!("../data/pathological/repeated-rare-huge.txt"); +pub const PATHOLOGICAL_REPEATED_RARE_SMALL: &'static str = + include_str!("../data/pathological/repeated-rare-small.txt"); +pub const PATHOLOGICAL_DEFEAT_SIMPLE_VECTOR: &'static str = + include_str!("../data/pathological/defeat-simple-vector.txt"); +pub const PATHOLOGICAL_DEFEAT_SIMPLE_VECTOR_FREQ: &'static str = + include_str!("../data/pathological/defeat-simple-vector-freq.txt"); +pub const PATHOLOGICAL_DEFEAT_SIMPLE_VECTOR_REPEATED: &'static str = + include_str!("../data/pathological/defeat-simple-vector-repeated.txt"); + +pub const SLICESLICE_I386: &'static str = + include_str!("../data/sliceslice/i386.txt"); +pub const SLICESLICE_WORDS: &'static str = + include_str!("../data/sliceslice/words.txt"); + +pub const CODE_RUST_LIBRARY: &'static str = + include_str!("../data/code/rust-library.rs"); diff --git a/bench/src/memchr/mod.rs b/bench/src/memchr/mod.rs index 99bfc46..8b8ca1a 100644 --- a/bench/src/memchr/mod.rs +++ b/bench/src/memchr/mod.rs @@ -12,18 +12,18 @@ use crate::{ }, }; -#[path = "../../../src/c.rs"] +#[path = "../../../src/memchr/c.rs"] mod c; #[allow(dead_code)] -#[path = "../../../src/fallback.rs"] +#[path = "../../../src/memchr/fallback.rs"] mod fallback; mod imp; mod inputs; -#[path = "../../../src/naive.rs"] +#[path = "../../../src/memchr/naive.rs"] mod naive; pub fn all(c: &mut Criterion) { - define_memchr_input1(c, "memchr1/rust/huge", HUGE, move |search, b| { + define_memchr_input1(c, "memchr1/krate/huge", HUGE, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count, @@ -31,7 +31,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input1(c, "memchr1/rust/small", SMALL, move |search, b| { + define_memchr_input1(c, "memchr1/krate/small", SMALL, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count, @@ -39,7 +39,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input1(c, "memchr1/rust/tiny", TINY, move |search, b| { + define_memchr_input1(c, "memchr1/krate/tiny", TINY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count, @@ -47,7 +47,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input1(c, "memchr1/rust/empty", EMPTY, move |search, b| { + define_memchr_input1(c, "memchr1/krate/empty", EMPTY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count, @@ -175,7 +175,7 @@ pub fn all(c: &mut Criterion) { }); }); - define_memchr_input2(c, "memchr2/rust/huge", HUGE, move |search, b| { + define_memchr_input2(c, "memchr2/krate/huge", HUGE, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count, @@ -187,7 +187,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input2(c, "memchr2/rust/small", SMALL, move |search, b| { + define_memchr_input2(c, "memchr2/krate/small", SMALL, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count, @@ -199,7 +199,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input2(c, "memchr2/rust/tiny", TINY, move |search, b| { + define_memchr_input2(c, "memchr2/krate/tiny", TINY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count, @@ -211,7 +211,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input2(c, "memchr2/rust/empty", EMPTY, move |search, b| { + define_memchr_input2(c, "memchr2/krate/empty", EMPTY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count, @@ -342,7 +342,7 @@ pub fn all(c: &mut Criterion) { }); }); - define_memchr_input3(c, "memchr3/rust/huge", HUGE, move |search, b| { + define_memchr_input3(c, "memchr3/krate/huge", HUGE, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count + search.byte3.count, @@ -355,7 +355,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input3(c, "memchr3/rust/small", SMALL, move |search, b| { + define_memchr_input3(c, "memchr3/krate/small", SMALL, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count + search.byte3.count, @@ -368,7 +368,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input3(c, "memchr3/rust/tiny", TINY, move |search, b| { + define_memchr_input3(c, "memchr3/krate/tiny", TINY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count + search.byte3.count, @@ -381,7 +381,7 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input3(c, "memchr3/rust/empty", EMPTY, move |search, b| { + define_memchr_input3(c, "memchr3/krate/empty", EMPTY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count + search.byte3.count, @@ -529,7 +529,7 @@ pub fn all(c: &mut Criterion) { }); }); - define_memchr_input1(c, "memrchr1/rust/huge", HUGE, move |search, b| { + define_memchr_input1(c, "memrchr1/krate/huge", HUGE, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count, @@ -537,23 +537,20 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input1(c, "memrchr1/rust/small", SMALL, move |search, b| { - b.iter(|| { - assert_eq!( - search.byte1.count, - memrchr1_count(search.byte1.byte, search.corpus) - ); - }); - }); - define_memchr_input1(c, "memrchr1/rust/tiny", TINY, move |search, b| { - b.iter(|| { - assert_eq!( - search.byte1.count, - memrchr1_count(search.byte1.byte, search.corpus) - ); - }); - }); - define_memchr_input1(c, "memrchr1/rust/empty", EMPTY, move |search, b| { + define_memchr_input1( + c, + "memrchr1/krate/small", + SMALL, + move |search, b| { + b.iter(|| { + assert_eq!( + search.byte1.count, + memrchr1_count(search.byte1.byte, search.corpus) + ); + }); + }, + ); + define_memchr_input1(c, "memrchr1/krate/tiny", TINY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count, @@ -561,6 +558,19 @@ pub fn all(c: &mut Criterion) { ); }); }); + define_memchr_input1( + c, + "memrchr1/krate/empty", + EMPTY, + move |search, b| { + b.iter(|| { + assert_eq!( + search.byte1.count, + memrchr1_count(search.byte1.byte, search.corpus) + ); + }); + }, + ); #[cfg(all(target_os = "linux"))] { @@ -630,7 +640,7 @@ pub fn all(c: &mut Criterion) { ); } - define_memchr_input2(c, "memrchr2/rust/huge", HUGE, move |search, b| { + define_memchr_input2(c, "memrchr2/krate/huge", HUGE, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count, @@ -642,31 +652,24 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input2(c, "memrchr2/rust/small", SMALL, move |search, b| { - b.iter(|| { - assert_eq!( - search.byte1.count + search.byte2.count, - memrchr2_count( - search.byte1.byte, - search.byte2.byte, - search.corpus, - ) - ); - }); - }); - define_memchr_input2(c, "memrchr2/rust/tiny", TINY, move |search, b| { - b.iter(|| { - assert_eq!( - search.byte1.count + search.byte2.count, - memrchr2_count( - search.byte1.byte, - search.byte2.byte, - search.corpus, - ) - ); - }); - }); - define_memchr_input2(c, "memrchr2/rust/empty", EMPTY, move |search, b| { + define_memchr_input2( + c, + "memrchr2/krate/small", + SMALL, + move |search, b| { + b.iter(|| { + assert_eq!( + search.byte1.count + search.byte2.count, + memrchr2_count( + search.byte1.byte, + search.byte2.byte, + search.corpus, + ) + ); + }); + }, + ); + define_memchr_input2(c, "memrchr2/krate/tiny", TINY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count, @@ -678,34 +681,25 @@ pub fn all(c: &mut Criterion) { ); }); }); + define_memchr_input2( + c, + "memrchr2/krate/empty", + EMPTY, + move |search, b| { + b.iter(|| { + assert_eq!( + search.byte1.count + search.byte2.count, + memrchr2_count( + search.byte1.byte, + search.byte2.byte, + search.corpus, + ) + ); + }); + }, + ); - define_memchr_input3(c, "memrchr3/rust/huge", HUGE, move |search, b| { - b.iter(|| { - assert_eq!( - search.byte1.count + search.byte2.count + search.byte3.count, - memrchr3_count( - search.byte1.byte, - search.byte2.byte, - search.byte3.byte, - search.corpus, - ) - ); - }); - }); - define_memchr_input3(c, "memrchr3/rust/small", SMALL, move |search, b| { - b.iter(|| { - assert_eq!( - search.byte1.count + search.byte2.count + search.byte3.count, - memrchr3_count( - search.byte1.byte, - search.byte2.byte, - search.byte3.byte, - search.corpus, - ) - ); - }); - }); - define_memchr_input3(c, "memrchr3/rust/tiny", TINY, move |search, b| { + define_memchr_input3(c, "memrchr3/krate/huge", HUGE, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count + search.byte3.count, @@ -718,7 +712,27 @@ pub fn all(c: &mut Criterion) { ); }); }); - define_memchr_input3(c, "memrchr3/rust/empty", EMPTY, move |search, b| { + define_memchr_input3( + c, + "memrchr3/krate/small", + SMALL, + move |search, b| { + b.iter(|| { + assert_eq!( + search.byte1.count + + search.byte2.count + + search.byte3.count, + memrchr3_count( + search.byte1.byte, + search.byte2.byte, + search.byte3.byte, + search.corpus, + ) + ); + }); + }, + ); + define_memchr_input3(c, "memrchr3/krate/tiny", TINY, move |search, b| { b.iter(|| { assert_eq!( search.byte1.count + search.byte2.count + search.byte3.count, @@ -731,6 +745,26 @@ pub fn all(c: &mut Criterion) { ); }); }); + define_memchr_input3( + c, + "memrchr3/krate/empty", + EMPTY, + move |search, b| { + b.iter(|| { + assert_eq!( + search.byte1.count + + search.byte2.count + + search.byte3.count, + memrchr3_count( + search.byte1.byte, + search.byte2.byte, + search.byte3.byte, + search.corpus, + ) + ); + }); + }, + ); } fn define_memchr_input1<'i>( @@ -739,34 +773,22 @@ fn define_memchr_input1<'i>( input: Input, bench: impl FnMut(Search1, &mut Bencher<'_>) + Clone + 'static, ) { - if let Some(search) = input.never1() { - let mut bench = bench.clone(); - define(c, group, "never", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.rare1() { - let mut bench = bench.clone(); - define(c, group, "rare", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.uncommon1() { - let mut bench = bench.clone(); - define(c, group, "uncommon", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.common1() { - let mut bench = bench.clone(); - define(c, group, "common", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.verycommon1() { - let mut bench = bench.clone(); - define(c, group, "verycommon", input.corpus, move |b| { - bench(search, b) - }); - } - if let Some(search) = input.supercommon1() { - let mut bench = bench.clone(); - define(c, group, "supercommon", input.corpus, move |b| { - bench(search, b) - }); + macro_rules! def { + ($name:expr, $kind:ident) => { + if let Some(search) = input.$kind() { + let corp = input.corpus; + let name = format!("{}/{}", group, $name); + let mut bench = bench.clone(); + define(c, &name, corp, Box::new(move |b| bench(search, b))); + } + }; } + def!("never", never1); + def!("rare", rare1); + def!("uncommon", uncommon1); + def!("common", common1); + def!("verycommon", verycommon1); + def!("supercommon", supercommon1); } fn define_memchr_input2<'i>( @@ -775,34 +797,22 @@ fn define_memchr_input2<'i>( input: Input, bench: impl FnMut(Search2, &mut Bencher<'_>) + Clone + 'static, ) { - if let Some(search) = input.never2() { - let mut bench = bench.clone(); - define(c, group, "never", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.rare2() { - let mut bench = bench.clone(); - define(c, group, "rare", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.uncommon2() { - let mut bench = bench.clone(); - define(c, group, "uncommon", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.common2() { - let mut bench = bench.clone(); - define(c, group, "common", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.verycommon2() { - let mut bench = bench.clone(); - define(c, group, "verycommon", input.corpus, move |b| { - bench(search, b) - }); - } - if let Some(search) = input.supercommon2() { - let mut bench = bench.clone(); - define(c, group, "supercommon", input.corpus, move |b| { - bench(search, b) - }); + macro_rules! def { + ($name:expr, $kind:ident) => { + if let Some(search) = input.$kind() { + let corp = input.corpus; + let name = format!("{}/{}", group, $name); + let mut bench = bench.clone(); + define(c, &name, corp, Box::new(move |b| bench(search, b))); + } + }; } + def!("never", never2); + def!("rare", rare2); + def!("uncommon", uncommon2); + def!("common", common2); + def!("verycommon", verycommon2); + def!("supercommon", supercommon2); } fn define_memchr_input3<'i>( @@ -811,32 +821,20 @@ fn define_memchr_input3<'i>( input: Input, bench: impl FnMut(Search3, &mut Bencher<'_>) + Clone + 'static, ) { - if let Some(search) = input.never3() { - let mut bench = bench.clone(); - define(c, group, "never", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.rare3() { - let mut bench = bench.clone(); - define(c, group, "rare", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.uncommon3() { - let mut bench = bench.clone(); - define(c, group, "uncommon", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.common3() { - let mut bench = bench.clone(); - define(c, group, "common", input.corpus, move |b| bench(search, b)); - } - if let Some(search) = input.verycommon3() { - let mut bench = bench.clone(); - define(c, group, "verycommon", input.corpus, move |b| { - bench(search, b) - }); - } - if let Some(search) = input.supercommon3() { - let mut bench = bench.clone(); - define(c, group, "supercommon", input.corpus, move |b| { - bench(search, b) - }); + macro_rules! def { + ($name:expr, $kind:ident) => { + if let Some(search) = input.$kind() { + let corp = input.corpus; + let name = format!("{}/{}", group, $name); + let mut bench = bench.clone(); + define(c, &name, corp, Box::new(move |b| bench(search, b))); + } + }; } + def!("never", never3); + def!("rare", rare3); + def!("uncommon", uncommon3); + def!("common", common3); + def!("verycommon", verycommon3); + def!("supercommon", supercommon3); } diff --git a/bench/src/memmem/imp.rs b/bench/src/memmem/imp.rs new file mode 100644 index 0000000..94232f0 --- /dev/null +++ b/bench/src/memmem/imp.rs @@ -0,0 +1,833 @@ +/* +This module defines a common API (by convention) for all of the different +impls that we benchmark. The intent here is to 1) make it easy to write macros +for generating benchmark definitions generic over impls and 2) make it easier +to read the benchmarks themselves and grok how exactly each of the impls are +being invoked. + +The naming scheme of each function follows the pertinent parts of our benchmark +naming scheme (see parent module docs). Namely, it is + + {impl}/{fwd|rev}/{config} + +Where 'impl' is the underlying implementation and 'config' is the manner of +search. The slash indicates a module boundary. We use modules for this because +it makes writing macros to define benchmarks for all variants much easier. +*/ + +/// memchr's implementation of memmem. This is the implementation that we hope +/// does approximately as well as all other implementations, and a lot better +/// in at least some cases. +pub(crate) mod krate { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["reverse", "oneshot", "prebuilt", "oneshotiter", "prebuiltiter"] + } + + pub(crate) mod fwd { + use memchr::memmem; + + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + memmem::find(haystack.as_bytes(), needle.as_bytes()).is_some() + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = memmem::Finder::new(needle).into_owned(); + move |h| finder.find(h.as_bytes()).is_some() + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + memmem::find_iter(haystack.as_bytes(), needle.as_bytes()) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(memmem::Finder::new(needle).into_owned()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(memmem::Finder<'static>); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + self.0.find_iter(haystack.as_bytes()) + } + } + } + + pub(crate) mod rev { + use memchr::memmem; + + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + memmem::rfind(haystack.as_bytes(), needle.as_bytes()).is_some() + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = memmem::FinderRev::new(needle).into_owned(); + move |h| finder.rfind(h.as_bytes()).is_some() + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + memmem::rfind_iter(haystack.as_bytes(), needle.as_bytes()) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(memmem::FinderRev::new(needle).into_owned()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(memmem::FinderRev<'static>); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + self.0.rfind_iter(haystack.as_bytes()) + } + } + } +} + +/// memchr's implementation of memmem, but without prefilters enabled. This +/// exists because sometimes prefilters aren't the right choice, and it's good +/// to be able to compare it against prefilter-accelerated searches to see +/// where this might be faster. +pub(crate) mod krate_nopre { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["reverse", "oneshot", "prebuilt", "oneshotiter", "prebuiltiter"] + } + + pub(crate) mod fwd { + use memchr::memmem; + + fn finder(needle: &[u8]) -> memmem::Finder<'_> { + memmem::FinderBuilder::new() + .prefilter(memmem::Prefilter::None) + .build_forward(needle) + } + + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + finder(needle.as_bytes()).find(haystack.as_bytes()).is_some() + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = finder(needle.as_bytes()).into_owned(); + move |h| finder.find(h.as_bytes()).is_some() + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_find( + haystack.as_bytes(), + needle.as_bytes(), + |h, n| finder(n).find(h), + ) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(finder(needle.as_bytes()).into_owned()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(memmem::Finder<'static>); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + self.0.find_iter(haystack.as_bytes()) + } + } + } + + // N.B. memrmem/krate_nopre and memrmem/krate should be equivalent for now + // since reverse searching doesn't have any prefilter support. + pub(crate) mod rev { + use memchr::memmem; + + fn finder(needle: &[u8]) -> memmem::FinderRev<'_> { + memmem::FinderBuilder::new() + .prefilter(memmem::Prefilter::None) + .build_reverse(needle) + } + + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + finder(needle.as_bytes()).rfind(haystack.as_bytes()).is_some() + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = finder(needle.as_bytes()).into_owned(); + move |h| finder.rfind(h.as_bytes()).is_some() + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_rfind( + haystack.as_bytes(), + needle.as_bytes(), + |h, n| finder(n).rfind(h), + ) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(finder(needle.as_bytes()).into_owned()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(memmem::FinderRev<'static>); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + self.0.rfind_iter(haystack.as_bytes()) + } + } + } +} + +/// bstr's implementation of memmem. +/// +/// The implementation in this crate was originally copied from bstr. +/// Eventually, bstr will just use the implementation in this crate, but at time +/// of writing, it was useful to benchmark against the "original" version. +pub(crate) mod bstr { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["reverse", "oneshot", "prebuilt", "oneshotiter", "prebuiltiter"] + } + + pub(crate) mod fwd { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + bstr::ByteSlice::find(haystack.as_bytes(), needle.as_bytes()) + .is_some() + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = bstr::Finder::new(needle).into_owned(); + move |h| finder.find(h.as_bytes()).is_some() + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + bstr::ByteSlice::find_iter(haystack.as_bytes(), needle.as_bytes()) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(bstr::Finder::new(needle).into_owned()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(bstr::Finder<'static>); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_find( + haystack.as_bytes(), + self.0.needle(), + move |h, _| self.0.find(h), + ) + } + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + bstr::ByteSlice::rfind(haystack.as_bytes(), needle.as_bytes()) + .is_some() + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = bstr::FinderReverse::new(needle).into_owned(); + move |h| finder.rfind(h.as_bytes()).is_some() + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + bstr::ByteSlice::rfind_iter(haystack.as_bytes(), needle.as_bytes()) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(bstr::FinderReverse::new(needle).into_owned()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(bstr::FinderReverse<'static>); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_rfind( + haystack.as_bytes(), + self.0.needle(), + move |h, _| self.0.rfind(h), + ) + } + } + } +} + +/// regex's implementation of substring search. +/// +/// regex is where the concept of using heuristics based on an a priori +/// assumption of byte frequency originated. Eventually, regex will just use the +/// implementation in this crate, but it will still be useful to benchmark since +/// regex tends to have higher latency. It would be good to measure that. +/// +/// For regex, we don't provide oneshots, since that requires compiling the +/// regex which we know is going to be ridiculously slow. No real need to +/// measure it I think. +pub(crate) mod regex { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["prebuilt", "prebuiltiter"] + } + + pub(crate) mod fwd { + pub(crate) fn oneshot(_haystack: &str, _needle: &str) -> bool { + unimplemented!("regex does not support oneshot searches") + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + let finder = regex::Regex::new(®ex::escape(needle)).unwrap(); + move |h| finder.is_match(h) + } + + pub(crate) fn oneshotiter( + _haystack: &str, + _needle: &str, + ) -> impl Iterator + 'static { + std::iter::from_fn(move || { + unimplemented!("regex does not support oneshot searches") + }) + } + + pub(crate) fn prebuiltiter(needle: &str) -> PrebuiltIter { + PrebuiltIter(regex::Regex::new(®ex::escape(needle)).unwrap()) + } + + #[derive(Debug)] + pub(crate) struct PrebuiltIter(regex::Regex); + + impl PrebuiltIter { + pub(crate) fn iter<'a>( + &'a self, + haystack: &'a str, + ) -> impl Iterator + 'a { + self.0.find_iter(haystack).map(|m| m.start()) + } + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(_haystack: &str, _needle: &str) -> bool { + unimplemented!("regex does not support reverse searches") + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("regex does not support reverse searches") + } + + pub(crate) fn oneshotiter( + _haystack: &str, + _needle: &str, + ) -> impl Iterator + 'static { + std::iter::from_fn(move || { + unimplemented!("regex does not support reverse searches") + }) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + unimplemented!("regex does not support reverse searches") + } + } +} + +/// std's substring search implementation. +/// +/// std uses Two-Way like this crate, but doesn't have any prefilter +/// heuristics. +/// +/// std doesn't have any way to amortize the construction of the searcher, so +/// we can't implement any of the prebuilt routines. +pub(crate) mod stud { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["reverse", "oneshot", "oneshotiter"] + } + + pub(crate) mod fwd { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + haystack.contains(needle) + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("std does not support prebuilt searches") + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + haystack.match_indices(needle).map(|(i, _)| i) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + super::super::NoIter { imp: "std" } + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + haystack.contains(needle) + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("std does not support prebuilt searches") + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + haystack.rmatch_indices(needle).map(|(i, _)| i) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + super::super::NoIter { imp: "std" } + } + } +} + +/// Substring search from the twoway crate. +/// +/// twoway uses, obviously, Two-Way as an implementation. AIUI, it was taken +/// from std at some point but heavily modified to support a prefilter via +/// PCMPESTRI from the SSE 4.2 ISA extension. (And also uses memchr for +/// single-byte needles.) +/// +/// Like std, there is no way to amortize the construction of the searcher, so +/// we can't implement any of the prebuilt routines. +pub(crate) mod twoway { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["reverse", "oneshot", "oneshotiter"] + } + + pub(crate) mod fwd { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + twoway::find_bytes(haystack.as_bytes(), needle.as_bytes()) + .is_some() + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("twoway does not support prebuilt searches") + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_find( + haystack.as_bytes(), + needle.as_bytes(), + twoway::find_bytes, + ) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + super::super::NoIter { imp: "twoway" } + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + twoway::rfind_bytes(haystack.as_bytes(), needle.as_bytes()) + .is_some() + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("twoway does not support prebuilt searches") + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_rfind( + haystack.as_bytes(), + needle.as_bytes(), + twoway::rfind_bytes, + ) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + super::super::NoIter { imp: "twoway" } + } + } +} + +/// Substring search from the sliceslice crate. +/// +/// This crate is what inspired me to write a vectorized memmem implementation +/// in the memchr crate in the first place. In particular, it exposed some +/// serious weaknesses in my implementation in the bstr crate. +/// +/// sliceslice doesn't actually do anything "new" other +/// than bringing a long known SIMD algorithm to Rust: +/// http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd +/// +/// The main thrust of the algorithm is that it picks a couple of bytes in the +/// needle and uses SIMD to check whether those two bytes occur in the haystack +/// in a way that could lead to a match. If so, then you do a simple memcmp +/// confirmation step. The main problem with this algorithm is that its worst +/// case is multiplicative: that confirmatory step can become quite costly if +/// the SIMD prefilter isn't effective. The elegance of this method, however, +/// is that the prefilter is routinely effective. +/// +/// The essence of memchr's implementation of memmem comes from sliceslice, +/// but also from regex's original idea to use heuristics based on an a priori +/// assumption of relative byte frequency AND from bstr's desire to have a +/// constant space and worst case O(m+n) substring search. My claim is that +/// it is the best of all words, and that's why this benchmark suite is so +/// comprehensive. There are a lot of cases and implementations to test. +/// +/// NOTE: The API of sliceslice is quite constrained. My guess is that it was +/// designed for a very specific use case, and the API is heavily constrained +/// to that use case (whatever it is). While its API doesn't provide any +/// oneshot routines, we emulate them. (Its main problem is that every such +/// search requires copying the needle into a fresh allocation. The memchr +/// crate avoids that problem by being generic over the needle: it can be owned +/// or borrowed.) Also, since the API only enables testing whether a substring +/// exists or not, we can't benchmark iteration. +/// +/// NOTE: sliceslice only works on x86_64 CPUs with AVX enabled. So not only +/// do we conditionally compile the routines below, but we only run these +/// benchmarks when AVX2 is available. +#[cfg(target_arch = "x86_64")] +pub(crate) mod sliceslice { + pub(crate) fn available(needle: &str) -> &'static [&'static str] { + // Apparently sliceslice doesn't support searching with an empty + // needle. Sheesh. + if !needle.is_empty() && is_x86_feature_detected!("avx2") { + &["oneshot", "prebuilt"] + } else { + &[] + } + } + + pub(crate) mod fwd { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + prebuilt(needle)(haystack) + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + if !is_x86_feature_detected!("avx2") { + unreachable!("sliceslice cannot be called without avx2"); + } + let needle = needle.as_bytes().to_owned().into_boxed_slice(); + // SAFETY: This code path is only entered when AVX2 is enabled, + // which is the only requirement for using DynamicAvx2Searcher. + unsafe { + let finder = sliceslice::x86::DynamicAvx2Searcher::new(needle); + move |h| finder.search_in(h.as_bytes()) + } + } + + pub(crate) fn oneshotiter( + _haystack: &str, + _needle: &str, + ) -> impl Iterator + 'static { + std::iter::from_fn(move || { + unimplemented!("sliceslice doesn't not support iteration") + }) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + unimplemented!("sliceslice doesn't support prebuilt iteration") + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(_haystack: &str, _needle: &str) -> bool { + unimplemented!("sliceslice does not support reverse searches") + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("sliceslice does not support reverse searches") + } + + pub(crate) fn oneshotiter( + _haystack: &str, + _needle: &str, + ) -> impl Iterator + 'static { + std::iter::from_fn(move || { + unimplemented!("sliceslice does not support reverse searches") + }) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + unimplemented!("sliceslice does not support reverse searches") + } + } +} + +#[cfg(not(target_arch = "x86_64"))] +pub(crate) mod sliceslice { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &[] + } + + pub(crate) mod fwd { + pub(crate) fn oneshot(_: &str, _: &str) -> bool { + unimplemented!("sliceslice only runs on x86") + } + + pub(crate) fn prebuilt(_: &str) -> impl Fn(&str) -> bool + 'static { + unimplemented!("sliceslice only runs on x86") + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'static { + std::iter::from_fn(move || { + unimplemented!("sliceslice only runs on x86") + }) + } + + pub(crate) fn prebuiltiter(needle: &str) -> super::super::NoIter { + unimplemented!("sliceslice only runs on x86") + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + unimplemented!("sliceslice does not support reverse searches") + } + + pub(crate) fn prebuilt( + needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("sliceslice does not support reverse searches") + } + + pub(crate) fn oneshotiter( + haystack: &str, + needle: &str, + ) -> impl Iterator + 'static { + std::iter::from_fn(move || { + unimplemented!("sliceslice does not support reverse searches") + }) + } + + pub(crate) fn prebuiltiter(needle: &str) -> super::super::NoIter { + unimplemented!("sliceslice does not support reverse searches") + } + } +} + +/// libc's substring search implementation. +/// +/// libc doesn't have any way to amortize the construction of the searcher, so +/// we can't implement any of the prebuilt routines. +pub(crate) mod libc { + pub(crate) fn available(_: &str) -> &'static [&'static str] { + &["oneshot", "oneshotiter"] + } + + pub(crate) mod fwd { + fn find(haystack: &[u8], needle: &[u8]) -> Option { + let p = unsafe { + libc::memmem( + haystack.as_ptr() as *const libc::c_void, + haystack.len(), + needle.as_ptr() as *const libc::c_void, + needle.len(), + ) + }; + if p.is_null() { + None + } else { + Some(p as usize - (haystack.as_ptr() as usize)) + } + } + + pub(crate) fn oneshot(haystack: &str, needle: &str) -> bool { + find(haystack.as_bytes(), needle.as_bytes()).is_some() + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("std does not support prebuilt searches") + } + + pub(crate) fn oneshotiter<'a>( + haystack: &'a str, + needle: &'a str, + ) -> impl Iterator + 'a { + super::super::iter_from_find( + haystack.as_bytes(), + needle.as_bytes(), + find, + ) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + super::super::NoIter { imp: "libc" } + } + } + + pub(crate) mod rev { + pub(crate) fn oneshot(_haystack: &str, _needle: &str) -> bool { + unimplemented!("libc does not support reverse searches") + } + + pub(crate) fn prebuilt( + _needle: &str, + ) -> impl Fn(&str) -> bool + 'static { + |_| unimplemented!("libc does not support reverse searches") + } + + pub(crate) fn oneshotiter<'a>( + _haystack: &'a str, + _needle: &'a str, + ) -> impl Iterator + 'a { + std::iter::from_fn(move || { + unimplemented!("libc does not support reverse searches") + }) + } + + pub(crate) fn prebuiltiter(_needle: &str) -> super::super::NoIter { + unimplemented!("libc does not support reverse searches") + } + } +} + +/// An iterator that looks like a PrebuilIter API-wise, but panics if it's +/// called. This should be used for implementations that don't support +/// prebuilt iteration. +#[derive(Debug)] +pub(crate) struct NoIter { + /// The name of the impl to use in the panic message in case it is invoked + /// by mistake. (But the benchmark harness should not invoke it, assuming + /// each impl's 'available' function is correct. + imp: &'static str, +} + +impl NoIter { + pub(crate) fn iter( + &self, + _: &str, + ) -> impl Iterator + 'static { + let imp = self.imp; + std::iter::from_fn(move || { + unimplemented!("{} does not support prebuilt iteration", imp) + }) + } +} + +/// Accepts a corpus and a needle and a routine that implements substring +/// search, and returns an iterator over all matches. This is useful for +/// benchmarking "find all matches" for substring search implementations that +/// don't expose a native way to do this. +/// +/// The closure given takes two parameters: the corpus and needle, in that +/// order. +fn iter_from_find<'a>( + haystack: &'a [u8], + needle: &'a [u8], + mut find: impl FnMut(&[u8], &[u8]) -> Option + 'a, +) -> impl Iterator + 'a { + let mut pos = 0; + std::iter::from_fn(move || { + if pos > haystack.len() { + return None; + } + match find(&haystack[pos..], needle) { + None => None, + Some(i) => { + let found = pos + i; + // We always need to add at least 1, in case of an empty needle. + pos += i + std::cmp::max(1, needle.len()); + Some(found) + } + } + }) +} + +/// Like iter_from_find, but for reverse searching. +fn iter_from_rfind<'a>( + haystack: &'a [u8], + needle: &'a [u8], + mut rfind: impl FnMut(&[u8], &[u8]) -> Option + 'a, +) -> impl Iterator + 'a { + let mut pos = Some(haystack.len()); + std::iter::from_fn(move || { + let end = match pos { + None => return None, + Some(end) => end, + }; + match rfind(&haystack[..end], needle) { + None => None, + Some(i) => { + if end == i { + // We always need to subtract at least 1, in case of an + // empty needle. + pos = end.checked_sub(1); + } else { + pos = Some(i); + } + Some(i) + } + } + }) +} diff --git a/bench/src/memmem/inputs.rs b/bench/src/memmem/inputs.rs new file mode 100644 index 0000000..c91ee9e --- /dev/null +++ b/bench/src/memmem/inputs.rs @@ -0,0 +1,257 @@ +use crate::data; + +#[derive(Clone, Copy, Debug)] +pub struct Input { + /// A name describing the corpus, used to identify it in benchmarks. + pub name: &'static str, + /// The haystack to search. + pub corpus: &'static str, + /// Queries that are expected to never occur. + pub never: &'static [Query], + /// Queries that are expected to occur rarely. + pub rare: &'static [Query], + /// Queries that are expected to fairly common. + pub common: &'static [Query], +} + +/// A substring search query for a particular haystack. +#[derive(Clone, Copy, Debug)] +pub struct Query { + /// A name for this query, used to identify it in benchmarks. + pub name: &'static str, + /// The needle to search for. + pub needle: &'static str, + /// The expected number of occurrences. + pub count: usize, +} + +pub const INPUTS: &'static [Input] = &[ + Input { + name: "code-rust-library", + corpus: data::CODE_RUST_LIBRARY, + never: &[ + Query { name: "fn-strength", needle: "fn strength", count: 0 }, + Query { + name: "fn-strength-paren", + needle: "fn strength(", + count: 0, + }, + Query { name: "fn-quux", needle: "fn quux(", count: 0 }, + ], + rare: &[ + Query { + name: "fn-from-str", + needle: "pub fn from_str(", + count: 1, + }, + ], + common: &[ + Query { name: "fn-is-empty", needle: "fn is_empty(", count: 17 }, + Query { name: "fn", needle: "fn", count: 2985 }, + Query { name: "paren", needle: "(", count: 30193 }, + Query { name: "let", needle: "let", count: 4737 }, + ], + }, + Input { + name: "huge-en", + corpus: data::SUBTITLE_EN_HUGE, + never: &[ + Query { name: "john-watson", needle: "John Watson", count: 0 }, + Query { name: "all-common-bytes", needle: "sternness", count: 0 }, + Query { name: "some-rare-bytes", needle: "quartz", count: 0 }, + Query { name: "two-space", needle: " ", count: 0 }, + ], + rare: &[ + Query { + name: "sherlock-holmes", + needle: "Sherlock Holmes", + count: 1, + }, + Query { name: "sherlock", needle: "Sherlock", count: 1 }, + Query { + name: "medium-needle", + needle: "homer, marge, bart, lisa, maggie", + count: 1, + }, + Query { + name: "long-needle", + needle: "I feel afraid of Mostafa\nHe is stronger and older than I am, and more experienced\nShould I turn back?\nDoc you're beginning to sound like Sherlock Holmes.", + count: 1, + }, + Query { + name: "huge-needle", + needle: "Since we will meet anyway, then the sooner, the better\nTomorrow at 4:30 in front of the Horse-Riding Club\nNo, 4:30\nI am confused, almost lost\nAs if an invisible hand pushed me towards an unknown fate\nI needed someone by my side\nI needed someone to guide me to the path of security\nBut I had no one\nI couldn't ask my father's opinion, nor his wife's\nI felt just as lonely as I had before\nI feel afraid of Mostafa\nHe is stronger and older than I am, and more experienced\nShould I turn back?\nDoc you're beginning to sound like Sherlock Holmes.", + count: 1, + }, + ], + common: &[ + Query { name: "that", needle: "that", count: 865 }, + Query { name: "one-space", needle: " ", count: 96606 }, + Query { name: "you", needle: "you", count: 5009 }, + // It would be nice to benchmark this case, although it's not + // terribly important. The problem is that std's substring + // implementation (correctly) never returns match offsets that + // split an encoded codepoint, where as memmem on bytes will. So + // the counts differ. We could modify our harness to skip this on + // std, but it seems like much ado about nothing. + // Query { name: "empty", needle: "", count: 613655 }, + ], + }, + Input { + name: "huge-ru", + corpus: data::SUBTITLE_RU_HUGE, + never: &[Query { + name: "john-watson", + needle: "Джон Уотсон", + count: 0, + }], + rare: &[ + Query { + name: "sherlock-holmes", + needle: "Шерлок Холмс", + count: 1, + }, + Query { name: "sherlock", needle: "Шерлок", count: 1 }, + ], + common: &[ + Query { name: "that", needle: "что", count: 998 }, + Query { name: "not", needle: "не", count: 3092 }, + Query { name: "one-space", needle: " ", count: 46941 }, + ], + }, + Input { + name: "huge-zh", + corpus: data::SUBTITLE_ZH_HUGE, + never: &[Query { + name: "john-watson", needle: "约翰·沃森", count: 0 + }], + rare: &[ + Query { + name: "sherlock-holmes", + needle: "夏洛克·福尔摩斯", + count: 1, + }, + Query { name: "sherlock", needle: "夏洛克", count: 1 }, + ], + common: &[ + Query { name: "that", needle: "那", count: 1056 }, + Query { name: "do-not", needle: "不", count: 2751 }, + Query { name: "one-space", needle: " ", count: 17232 }, + ], + }, + Input { + name: "teeny-en", + corpus: data::SUBTITLE_EN_TEENY, + never: &[ + Query { name: "john-watson", needle: "John Watson", count: 0 }, + Query { name: "all-common-bytes", needle: "sternness", count: 0 }, + Query { name: "some-rare-bytes", needle: "quartz", count: 0 }, + Query { name: "two-space", needle: " ", count: 0 }, + ], + rare: &[ + Query { + name: "sherlock-holmes", + needle: "Sherlock Holmes", + count: 1, + }, + Query { name: "sherlock", needle: "Sherlock", count: 1 }, + ], + common: &[], + }, + Input { + name: "teeny-ru", + corpus: data::SUBTITLE_RU_TEENY, + never: &[Query { + name: "john-watson", + needle: "Джон Уотсон", + count: 0, + }], + rare: &[ + Query { + name: "sherlock-holmes", + needle: "Шерлок Холмс", + count: 1, + }, + Query { name: "sherlock", needle: "Шерлок", count: 1 }, + ], + common: &[], + }, + Input { + name: "teeny-zh", + corpus: data::SUBTITLE_ZH_TEENY, + never: &[Query { + name: "john-watson", needle: "约翰·沃森", count: 0 + }], + rare: &[ + Query { + name: "sherlock-holmes", + needle: "夏洛克·福尔摩斯", + count: 1, + }, + Query { name: "sherlock", needle: "夏洛克", count: 1 }, + ], + common: &[], + }, + Input { + name: "pathological-md5-huge", + corpus: data::PATHOLOGICAL_MD5_HUGE, + never: &[Query { + name: "no-hash", + needle: "61a1a40effcf97de24505f154a306597", + count: 0, + }], + rare: &[Query { + name: "last-hash", + needle: "831df319d8597f5bc793d690f08b159b", + count: 1, + }], + common: &[Query { name: "two-bytes", needle: "fe", count: 520 }], + }, + Input { + name: "pathological-repeated-rare-huge", + corpus: data::PATHOLOGICAL_REPEATED_RARE_HUGE, + never: &[Query { name: "tricky", needle: "abczdef", count: 0 }], + rare: &[], + common: &[Query { name: "match", needle: "zzzzzzzzzz", count: 50010 }], + }, + Input { + name: "pathological-repeated-rare-small", + corpus: data::PATHOLOGICAL_REPEATED_RARE_SMALL, + never: &[Query { name: "tricky", needle: "abczdef", count: 0 }], + rare: &[], + common: &[Query { name: "match", needle: "zzzzzzzzzz", count: 100 }], + }, + Input { + name: "pathological-defeat-simple-vector", + corpus: data::PATHOLOGICAL_DEFEAT_SIMPLE_VECTOR, + never: &[], + rare: &[Query { + name: "alphabet", + needle: "qbz", + count: 1, + }], + common: &[], + }, + Input { + name: "pathological-defeat-simple-vector-freq", + corpus: data::PATHOLOGICAL_DEFEAT_SIMPLE_VECTOR_FREQ, + never: &[], + rare: &[Query { + name: "alphabet", + needle: "qjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz", + count: 1, + }], + common: &[], + }, + Input { + name: "pathological-defeat-simple-vector-repeated", + corpus: data::PATHOLOGICAL_DEFEAT_SIMPLE_VECTOR_REPEATED, + never: &[], + rare: &[Query { + name: "alphabet", + needle: "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzaz", + count: 1, + }], + common: &[], + }, +]; diff --git a/bench/src/memmem/mod.rs b/bench/src/memmem/mod.rs new file mode 100644 index 0000000..c817415 --- /dev/null +++ b/bench/src/memmem/mod.rs @@ -0,0 +1,383 @@ +/* +This module defines benchmarks for the memmem family of functions. +Benchmarking a substring algorithm is particularly difficult, especially +when implementations (like this one, and others) use heuristics to speed up +common cases, typically at the expense of less common cases. The job of this +benchmark suite is to not only highlight the fast common cases, but to also put +a spotlight on the less common or pathological cases. While some things are +generally expected to be slower because of these heuristics, the benchmarks +help us make sure they we don't let things get too slow. + +The naming scheme is as follows: + + memr?mem/{impl}/{config}/{corpus}/{needle} + +Where {...} is a variable. Variables should never contain slashes. They are as +follows: + + impl + A brief name describing the implementation under test. Possible values: + + krate + The implementation provided by this crate. + krate-nopre + The implementation provided by this crate without prefilters enabled. + bstr + The implementation provided by the bstr crate. + N.B. This is only applicable at time of writing, since bstr will + eventually just use this crate. + regex + The implementation of substring search provided by the regex crate. + N.B. This is only applicable at time of writing, since regex will + eventually just use this crate. + stud + The implementation of substring search provided by the standard + library. This implementation only works on valid UTF-8 by virtue of + how its API is exposed. + twoway + The implementation of substring search provided by the twoway crate. + sliceslice + The implementation of substring search provided by the sliceslice crate. + libc + The implementation of memmem in your friendly neighborhood libc. + + Note that there is also a 'memmem' crate, but it is unmaintained and + appears to just be a snapshot of std's implementation at a particular + point in time (but exposed in a way to permit it to search arbitrary + bytes). + + config + This should be a brief description of the configuration of the search. Not + all implementations can be benchmarked in all configurations. It depends on + the API they expose. Possible values: + + oneshot + Executes a single search without pre-building a searcher. That + this measurement includes the time it takes to initialize a + searcher. + prebuilt + Executes a single search without measuring the time it takes to + build a searcher. + iter-oneshot + Counts the total number of matches. This measures the time it takes to + build the searcher. + iter-prebuilt + Counts the total number of matches. This does not measure the time it + takes to build the searcher. + + corpus + A brief name describing the corpus or haystack used in the benchmark. In + general, we vary this with regard to size and language. Possible values: + + subtitles-{en,ru,zh} + Text from the OpenSubtitles project, in one of English, Russian or + Chinese. This is the primary input meant to represent most kinds of + haystacks. + pathological-{...} + A haystack that has been specifically constructed to exploit a + pathological case in or more substring search implementations. + sliceslice-words + The haystack is varied across words in an English dictionary. Using + this corpus means the benchmark is measuring performance on very small + haystacks. This was taken from the sliceslice crate benchmarks. + sliceslice-i386 + The haystack is an Intel 80386 reference manual. + This was also taken from the sliceslice crate benchmarks. + + needle + A brief name describing the needle used. Unlike other variables, there + isn't a strong controlled vocabularly for this parameter. The needle + variable is meant to be largely self explanatory. For example, a needle + named "rare" probably means that the number of occurrences of the needle + is expected to be particularly low. +*/ + +use criterion::Criterion; + +use crate::{define, memmem::inputs::INPUTS}; + +mod imp; +mod inputs; +mod sliceslice; + +pub fn all(c: &mut Criterion) { + oneshot(c); + prebuilt(c); + oneshot_iter(c); + prebuilt_iter(c); + sliceslice::all(c); +} + +fn oneshot(c: &mut Criterion) { + macro_rules! def_impl { + ($inp:expr, $q:expr, $freq:expr, $impl:ident) => { + let config = "oneshot"; + let available = imp::$impl::available($q.needle); + // We only define non-iter benchmarks when the count is <=1. Such + // queries are usually constructed to only appear at the end. + // Otherwise, for more common queries, the benchmark would be + // approximately duplicative with benchmarks on shorter haystacks + // for the implementations we benchmark. + if $q.count <= 1 && available.contains(&config) { + let expected = $q.count > 0; + macro_rules! define { + ($dir:expr, $find:expr) => { + let name = format!( + "{dir}/{imp}/{config}/{inp}/{freq}-{q}", + dir = $dir, + imp = stringify!($impl), + config = config, + inp = $inp.name, + freq = $freq, + q = $q.name, + ); + define( + c, + &name, + $inp.corpus.as_bytes(), + Box::new(move |b| { + b.iter(|| { + assert_eq!( + expected, + $find($inp.corpus, $q.needle) + ); + }); + }), + ); + }; + } + define!("memmem", imp::$impl::fwd::oneshot); + if available.contains(&"reverse") { + define!("memrmem", imp::$impl::rev::oneshot); + } + } + }; + } + macro_rules! def_all_impls { + ($inp:expr, $q:expr, $freq:expr) => { + def_impl!($inp, $q, $freq, krate); + def_impl!($inp, $q, $freq, krate_nopre); + def_impl!($inp, $q, $freq, bstr); + def_impl!($inp, $q, $freq, regex); + def_impl!($inp, $q, $freq, stud); + def_impl!($inp, $q, $freq, twoway); + def_impl!($inp, $q, $freq, sliceslice); + def_impl!($inp, $q, $freq, libc); + }; + } + for inp in INPUTS { + for q in inp.never { + def_all_impls!(inp, q, "never"); + } + for q in inp.rare { + def_all_impls!(inp, q, "rare"); + } + for q in inp.common { + def_all_impls!(inp, q, "common"); + } + } +} + +fn prebuilt(c: &mut Criterion) { + macro_rules! def_impl { + ($inp:expr, $q:expr, $freq:expr, $impl:ident) => { + let config = "prebuilt"; + let available = imp::$impl::available($q.needle); + // We only define non-iter benchmarks when the count is <=1. Such + // queries are usually constructed to only appear at the end. + // Otherwise, for more common queries, the benchmark would be + // approximately duplicative with benchmarks on shorter haystacks + // for the implementations we benchmark. + if $q.count <= 1 && available.contains(&config) { + let expected = $q.count > 0; + macro_rules! define { + ($dir:expr, $new_finder:expr) => { + let name = format!( + "{dir}/{imp}/{config}/{inp}/{freq}-{q}", + dir = $dir, + imp = stringify!($impl), + config = config, + inp = $inp.name, + freq = $freq, + q = $q.name, + ); + define( + c, + &name, + $inp.corpus.as_bytes(), + Box::new(move |b| { + let find = $new_finder($q.needle); + b.iter(|| { + assert_eq!(expected, find($inp.corpus)); + }); + }), + ); + }; + } + define!("memmem", imp::$impl::fwd::prebuilt); + if available.contains(&"reverse") { + define!("memrmem", imp::$impl::rev::prebuilt); + } + } + }; + } + macro_rules! def_all_impls { + ($inp:expr, $q:expr, $freq:expr) => { + def_impl!($inp, $q, $freq, krate); + def_impl!($inp, $q, $freq, krate_nopre); + def_impl!($inp, $q, $freq, bstr); + def_impl!($inp, $q, $freq, regex); + def_impl!($inp, $q, $freq, stud); + def_impl!($inp, $q, $freq, twoway); + def_impl!($inp, $q, $freq, sliceslice); + def_impl!($inp, $q, $freq, libc); + }; + } + for inp in INPUTS { + for q in inp.never { + def_all_impls!(inp, q, "never"); + } + for q in inp.rare { + def_all_impls!(inp, q, "rare"); + } + for q in inp.common { + def_all_impls!(inp, q, "common"); + } + } +} + +fn oneshot_iter(c: &mut Criterion) { + macro_rules! def_impl { + ($inp:expr, $q:expr, $freq:expr, $impl:ident) => { + let config = "oneshotiter"; + let available = imp::$impl::available($q.needle); + // We only define iter benchmarks when the count is >1. Since + // queries with count<=1 are usually constructed such that the + // match appears at the end of the haystack, it doesn't make much + // sense to also benchmark iteration for that case. Instead, we only + // benchmark iteration for queries that match more frequently. + if $q.count > 1 && available.contains(&config) { + macro_rules! define { + ($dir:expr, $find_iter:expr) => { + let name = format!( + "{dir}/{imp}/{config}/{inp}/{freq}-{q}", + dir = $dir, + imp = stringify!($impl), + config = config, + inp = $inp.name, + freq = $freq, + q = $q.name, + ); + define( + c, + &name, + $inp.corpus.as_bytes(), + Box::new(move |b| { + b.iter(|| { + let it = + $find_iter($inp.corpus, $q.needle); + assert_eq!($q.count, it.count()); + }); + }), + ); + }; + } + define!("memmem", imp::$impl::fwd::oneshotiter); + if available.contains(&"reverse") { + define!("memrmem", imp::$impl::rev::oneshotiter); + } + } + }; + } + macro_rules! def_all_impls { + ($inp:expr, $q:expr, $freq:expr) => { + def_impl!($inp, $q, $freq, krate); + def_impl!($inp, $q, $freq, krate_nopre); + def_impl!($inp, $q, $freq, bstr); + def_impl!($inp, $q, $freq, regex); + def_impl!($inp, $q, $freq, stud); + def_impl!($inp, $q, $freq, twoway); + def_impl!($inp, $q, $freq, sliceslice); + def_impl!($inp, $q, $freq, libc); + }; + } + for inp in INPUTS { + for q in inp.never { + def_all_impls!(inp, q, "never"); + } + for q in inp.rare { + def_all_impls!(inp, q, "rare"); + } + for q in inp.common { + def_all_impls!(inp, q, "common"); + } + } +} + +fn prebuilt_iter(c: &mut Criterion) { + macro_rules! def_impl { + ($inp:expr, $q:expr, $freq:expr, $impl:ident) => { + let config = "prebuiltiter"; + let available = imp::$impl::available($q.needle); + // We only define iter benchmarks when the count is >1. Since + // queries with count<=1 are usually constructed such that the + // match appears at the end of the haystack, it doesn't make much + // sense to also benchmark iteration for that case. Instead, we only + // benchmark iteration for queries that match more frequently. + if $q.count > 1 && available.contains(&config) { + macro_rules! define { + ($dir:expr, $new_finder:expr) => { + let name = format!( + "{dir}/{imp}/{config}/{inp}/{freq}-{q}", + dir = $dir, + imp = stringify!($impl), + config = config, + inp = $inp.name, + freq = $freq, + q = $q.name, + ); + define( + c, + &name, + $inp.corpus.as_bytes(), + Box::new(move |b| { + let finder = $new_finder($q.needle); + b.iter(|| { + let it = finder.iter($inp.corpus); + assert_eq!($q.count, it.count()); + }); + }), + ); + }; + } + define!("memmem", imp::$impl::fwd::prebuiltiter); + if available.contains(&"reverse") { + define!("memrmem", imp::$impl::rev::prebuiltiter); + } + } + }; + } + macro_rules! def_all_impls { + ($inp:expr, $q:expr, $freq:expr) => { + def_impl!($inp, $q, $freq, krate); + def_impl!($inp, $q, $freq, krate_nopre); + def_impl!($inp, $q, $freq, bstr); + def_impl!($inp, $q, $freq, regex); + def_impl!($inp, $q, $freq, stud); + def_impl!($inp, $q, $freq, twoway); + def_impl!($inp, $q, $freq, sliceslice); + def_impl!($inp, $q, $freq, libc); + }; + } + for inp in INPUTS { + for q in inp.never { + def_all_impls!(inp, q, "never"); + } + for q in inp.rare { + def_all_impls!(inp, q, "rare"); + } + for q in inp.common { + def_all_impls!(inp, q, "common"); + } + } +} diff --git a/bench/src/memmem/sliceslice.rs b/bench/src/memmem/sliceslice.rs new file mode 100644 index 0000000..6d19eae --- /dev/null +++ b/bench/src/memmem/sliceslice.rs @@ -0,0 +1,227 @@ +/* +These benchmarks were lifted almost verbtaim out of the sliceslice crate. The +reason why we have these benchmarks is because they were the primary thing that +motivated me to write this particular memmem implementation. In particular, my +existing substring search implementation in the bstr crate did quite poorly +on these particular benchmarks. Moreover, while the benchmark setup is a little +weird, these benchmarks do reflect cases that I think are somewhat common: + +N.B. In the sliceslice crate, the benchmarks are called "short" and "long." +Here, we call them sliceslice-words/words and sliceslice-i386/words, +respectively. The name change was made to be consistent with the naming +convention used for other benchmarks. + +* In the sliceslice-words/words case, the benchmark is primarily about + searching very short haystacks using common English words. +* In the sliceslice-words/i386 case, the benchmark is primarily about searching + a longer haystack with common English words. + +The main thing that's "weird" about these benchmarks is that each iteration +involves a lot of work. All of the other benchmarks in this crate focus on one +specific needle with one specific haystack, and each iteration is a single +search or iteration. But in these benchmarks, each iteration involves searching +with many needles against potentially many haystacks. Nevertheless, these have +proven useful targets for optimization. +*/ +use criterion::{black_box, Criterion}; +use memchr::memmem; + +use crate::{data::*, define}; + +pub fn all(c: &mut Criterion) { + search_short_haystack(c); + search_long_haystack(c); +} + +fn search_short_haystack(c: &mut Criterion) { + let mut words = SLICESLICE_WORDS.lines().collect::>(); + words.sort_unstable_by_key(|word| word.len()); + let words: Vec<&str> = words.iter().map(|&s| s).collect(); + + let needles = words.clone(); + define( + c, + "memmem/krate/prebuilt/sliceslice-words/words", + &[], + Box::new(move |b| { + let searchers = needles + .iter() + .map(|needle| memmem::Finder::new(needle.as_bytes())) + .collect::>(); + b.iter(|| { + for (i, searcher) in searchers.iter().enumerate() { + for haystack in &needles[i..] { + black_box( + searcher.find(haystack.as_bytes()).is_some(), + ); + } + } + }); + }), + ); + + let needles = words.clone(); + define( + c, + "memmem/krate-nopre/prebuilt/sliceslice-words/words", + &[], + Box::new(move |b| { + let searchers = needles + .iter() + .map(|needle| { + memmem::FinderBuilder::new() + .prefilter(memmem::Prefilter::None) + .build_forward(needle) + }) + .collect::>(); + b.iter(|| { + for (i, searcher) in searchers.iter().enumerate() { + for haystack in &needles[i..] { + black_box( + searcher.find(haystack.as_bytes()).is_some(), + ); + } + } + }); + }), + ); + + let needles = words.clone(); + define( + c, + "memmem/std/prebuilt/sliceslice-words/words", + &[], + Box::new(move |b| { + b.iter(|| { + for (i, needle) in needles.iter().enumerate() { + for haystack in &needles[i..] { + black_box(haystack.contains(needle)); + } + } + }); + }), + ); + + #[cfg(target_arch = "x86_64")] + { + use sliceslice::x86::DynamicAvx2Searcher; + + let needles = words.clone(); + define( + c, + "memmem/sliceslice/prebuilt/sliceslice-words/words", + &[], + Box::new(move |b| { + let searchers = needles + .iter() + .map(|&needle| unsafe { + DynamicAvx2Searcher::new( + needle.as_bytes().to_owned().into_boxed_slice(), + ) + }) + .collect::>(); + + b.iter(|| { + for (i, searcher) in searchers.iter().enumerate() { + for haystack in &needles[i..] { + black_box(unsafe { + searcher.search_in(haystack.as_bytes()) + }); + } + } + }); + }), + ); + } +} + +fn search_long_haystack(c: &mut Criterion) { + let words: Vec<&str> = SLICESLICE_WORDS.lines().collect(); + let haystack = SLICESLICE_I386; + let needles = words.clone(); + define( + c, + "memmem/krate/prebuilt/sliceslice-i386/words", + &[], + Box::new(move |b| { + let searchers = needles + .iter() + .map(|needle| memmem::Finder::new(needle.as_bytes())) + .collect::>(); + b.iter(|| { + for searcher in searchers.iter() { + black_box(searcher.find(haystack.as_bytes()).is_some()); + } + }); + }), + ); + + let haystack = SLICESLICE_I386; + let needles = words.clone(); + define( + c, + "memmem/krate-nopre/prebuilt/sliceslice-i386/words", + &[], + Box::new(move |b| { + let searchers = needles + .iter() + .map(|needle| { + memmem::FinderBuilder::new() + .prefilter(memmem::Prefilter::None) + .build_forward(needle) + }) + .collect::>(); + b.iter(|| { + for searcher in searchers.iter() { + black_box(searcher.find(haystack.as_bytes()).is_some()); + } + }); + }), + ); + + let haystack = SLICESLICE_I386; + let needles = words.clone(); + define( + c, + "memmem/std/prebuilt/sliceslice-i386/words", + &[], + Box::new(move |b| { + b.iter(|| { + for needle in needles.iter() { + black_box(haystack.contains(needle)); + } + }); + }), + ); + + #[cfg(target_arch = "x86_64")] + { + use sliceslice::x86::DynamicAvx2Searcher; + + let haystack = SLICESLICE_I386; + let needles = words.clone(); + define( + c, + "memmem/sliceslice/prebuilt/sliceslice-i386/words", + &[], + Box::new(move |b| { + let searchers = needles + .iter() + .map(|needle| unsafe { + DynamicAvx2Searcher::new( + needle.as_bytes().to_owned().into_boxed_slice(), + ) + }) + .collect::>(); + + b.iter(|| { + for searcher in &searchers { + black_box(unsafe { + searcher.search_in(haystack.as_bytes()) + }); + } + }); + }), + ); + } +} diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..b7fa0a7 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ +/target +/corpus +/artifacts +/coverage diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock new file mode 100644 index 0000000..da512a8 --- /dev/null +++ b/fuzz/Cargo.lock @@ -0,0 +1,37 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "698b65a961a9d730fb45b6b0327e20207810c9f61ee421b082b27ba003f49e2b" + +[[package]] +name = "cc" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86c975d637bc2a2f99440932b731491fc34c7f785d239e38af3addd3c2fd0e46" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "memchr" +version = "2.3.4" + +[[package]] +name = "memchr-fuzz" +version = "0.0.0" +dependencies = [ + "libfuzzer-sys", + "memchr", +] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..d9929cb --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,79 @@ +cargo-features = ['named-profiles'] + +[package] +publish = false +name = "memchr-fuzz" +version = "0.0.0" +authors = ["Andrew Gallant "] +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" + +[dependencies.memchr] +path = ".." + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[[bin]] +name = "memchr" +path = "fuzz_targets/memchr.rs" +test = false +doc = false + +[[bin]] +name = "memchr2" +path = "fuzz_targets/memchr2.rs" +test = false +doc = false + +[[bin]] +name = "memchr3" +path = "fuzz_targets/memchr3.rs" +test = false +doc = false + +[[bin]] +name = "memrchr" +path = "fuzz_targets/memrchr.rs" +test = false +doc = false + +[[bin]] +name = "memrchr2" +path = "fuzz_targets/memrchr2.rs" +test = false +doc = false + +[[bin]] +name = "memrchr3" +path = "fuzz_targets/memrchr3.rs" +test = false +doc = false + +[[bin]] +name = "memmem" +path = "fuzz_targets/memmem.rs" +test = false +doc = false + +[[bin]] +name = "memrmem" +path = "fuzz_targets/memrmem.rs" +test = false +doc = false + +[profile.release] +opt-level = 3 +debug = true + +[profile.debug] +inherits = "release" + +[profile.test] +inherits = "release" diff --git a/fuzz/fuzz_targets/memchr.rs b/fuzz/fuzz_targets/memchr.rs new file mode 100644 index 0000000..fb9ecaf --- /dev/null +++ b/fuzz/fuzz_targets/memchr.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memchr_iter; + +fuzz_target!(|data: &[u8]| { + if data.is_empty() { + return; + } + memchr_iter(data[0], &data[1..]).count(); +}); diff --git a/fuzz/fuzz_targets/memchr2.rs b/fuzz/fuzz_targets/memchr2.rs new file mode 100644 index 0000000..d6658bf --- /dev/null +++ b/fuzz/fuzz_targets/memchr2.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memchr2_iter; + +fuzz_target!(|data: &[u8]| { + if data.len() < 2 { + return; + } + memchr2_iter(data[0], data[1], &data[2..]).count(); +}); diff --git a/fuzz/fuzz_targets/memchr3.rs b/fuzz/fuzz_targets/memchr3.rs new file mode 100644 index 0000000..138c28d --- /dev/null +++ b/fuzz/fuzz_targets/memchr3.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memchr3_iter; + +fuzz_target!(|data: &[u8]| { + if data.len() < 3 { + return; + } + memchr3_iter(data[0], data[1], data[2], &data[3..]).count(); +}); diff --git a/fuzz/fuzz_targets/memmem.rs b/fuzz/fuzz_targets/memmem.rs new file mode 100644 index 0000000..0355fc8 --- /dev/null +++ b/fuzz/fuzz_targets/memmem.rs @@ -0,0 +1,13 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memmem; + +fuzz_target!(|data: &[u8]| { + if data.len() < 2 { + return; + } + let split = std::cmp::max(data[0] as usize, 1) % data.len() as usize; + let (needle, haystack) = (&data[..split], &data[split..]); + memmem::find_iter(haystack, needle).count(); +}); diff --git a/fuzz/fuzz_targets/memrchr.rs b/fuzz/fuzz_targets/memrchr.rs new file mode 100644 index 0000000..01da2e4 --- /dev/null +++ b/fuzz/fuzz_targets/memrchr.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memchr_iter; + +fuzz_target!(|data: &[u8]| { + if data.is_empty() { + return; + } + memchr_iter(data[0], &data[1..]).rev().count(); +}); diff --git a/fuzz/fuzz_targets/memrchr2.rs b/fuzz/fuzz_targets/memrchr2.rs new file mode 100644 index 0000000..000676d --- /dev/null +++ b/fuzz/fuzz_targets/memrchr2.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memchr2_iter; + +fuzz_target!(|data: &[u8]| { + if data.len() < 2 { + return; + } + memchr2_iter(data[0], data[1], &data[2..]).rev().count(); +}); diff --git a/fuzz/fuzz_targets/memrchr3.rs b/fuzz/fuzz_targets/memrchr3.rs new file mode 100644 index 0000000..4b96df7 --- /dev/null +++ b/fuzz/fuzz_targets/memrchr3.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memchr3_iter; + +fuzz_target!(|data: &[u8]| { + if data.len() < 3 { + return; + } + memchr3_iter(data[0], data[1], data[2], &data[3..]).rev().count(); +}); diff --git a/fuzz/fuzz_targets/memrmem.rs b/fuzz/fuzz_targets/memrmem.rs new file mode 100644 index 0000000..efae927 --- /dev/null +++ b/fuzz/fuzz_targets/memrmem.rs @@ -0,0 +1,13 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use memchr::memmem; + +fuzz_target!(|data: &[u8]| { + if data.len() < 2 { + return; + } + let split = std::cmp::max(data[0] as usize, 1) % data.len() as usize; + let (needle, haystack) = (&data[..split], &data[split..]); + memmem::rfind_iter(haystack, needle).count(); +}); diff --git a/src/cow.rs b/src/cow.rs new file mode 100644 index 0000000..95a0824 --- /dev/null +++ b/src/cow.rs @@ -0,0 +1,97 @@ +use core::ops; + +/// A specialized copy-on-write byte string. +/// +/// The purpose of this type is to permit usage of a "borrowed or owned +/// byte string" in a way that keeps std/no-std compatibility. That is, in +/// no-std mode, this type devolves into a simple &[u8] with no owned variant +/// availble. We can't just use a plain Cow because Cow is not in core. +#[derive(Clone, Debug)] +pub struct CowBytes<'a>(Imp<'a>); + +// N.B. We don't use std::borrow::Cow here since we can get away with a +// Box<[u8]> for our use case, which is 1/3 smaller than the Vec that +// a Cow<[u8]> would use. +#[cfg(feature = "std")] +#[derive(Clone, Debug)] +enum Imp<'a> { + Borrowed(&'a [u8]), + Owned(Box<[u8]>), +} + +#[cfg(not(feature = "std"))] +#[derive(Clone, Debug)] +struct Imp<'a>(&'a [u8]); + +impl<'a> ops::Deref for CowBytes<'a> { + type Target = [u8]; + + #[inline(always)] + fn deref(&self) -> &[u8] { + self.as_slice() + } +} + +impl<'a> CowBytes<'a> { + /// Create a new borrowed CowBytes. + #[inline(always)] + pub fn new>(bytes: &'a B) -> CowBytes<'a> { + CowBytes(Imp::new(bytes.as_ref())) + } + + /// Create a new owned CowBytes. + #[cfg(feature = "std")] + #[inline(always)] + pub fn new_owned(bytes: Box<[u8]>) -> CowBytes<'static> { + CowBytes(Imp::Owned(bytes)) + } + + /// Return a borrowed byte string, regardless of whether this is an owned + /// or borrowed byte string internally. + #[inline(always)] + pub fn as_slice(&self) -> &[u8] { + self.0.as_slice() + } + + /// Return an owned version of this copy-on-write byte string. + /// + /// If this is already an owned byte string internally, then this is a + /// no-op. Otherwise, the internal byte string is copied. + #[cfg(feature = "std")] + #[inline(always)] + pub fn into_owned(self) -> CowBytes<'static> { + match self.0 { + Imp::Borrowed(b) => CowBytes::new_owned(Box::from(b)), + Imp::Owned(b) => CowBytes::new_owned(b), + } + } +} + +impl<'a> Imp<'a> { + #[cfg(feature = "std")] + #[inline(always)] + pub fn new(bytes: &'a [u8]) -> Imp<'a> { + Imp::Borrowed(bytes) + } + + #[cfg(not(feature = "std"))] + #[inline(always)] + pub fn new(bytes: &'a [u8]) -> Imp<'a> { + Imp(bytes) + } + + #[cfg(feature = "std")] + #[inline(always)] + pub fn as_slice(&self) -> &[u8] { + match self { + Imp::Owned(ref x) => x, + Imp::Borrowed(x) => x, + } + } + + #[cfg(not(feature = "std"))] + #[inline(always)] + pub fn as_slice(&self) -> &[u8] { + self.0 + } +} diff --git a/src/lib.rs b/src/lib.rs index 85665cb..c3154b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,441 +1,181 @@ /*! -The `memchr` crate provides heavily optimized routines for searching bytes. - -The `memchr` function is traditionally provided by libc, however, the -performance of `memchr` can vary significantly depending on the specific -implementation of libc that is used. They can range from manually tuned -Assembly implementations (like that found in GNU's libc) all the way to -non-vectorized C implementations (like that found in MUSL). - -To smooth out the differences between implementations of libc, at least -on `x86_64` for Rust 1.27+, this crate provides its own implementation of -`memchr` that should perform competitively with the one found in GNU's libc. -The implementation is in pure Rust and has no dependency on a C compiler or an -Assembler. - -Additionally, GNU libc also provides an extension, `memrchr`. This crate -provides its own implementation of `memrchr` as well, on top of `memchr2`, -`memchr3`, `memrchr2` and `memrchr3`. The difference between `memchr` and -`memchr2` is that that `memchr2` permits finding all occurrences of two bytes -instead of one. Similarly for `memchr3`. -*/ +This library provides heavily optimized routines for string search primitives. -#![cfg_attr(not(feature = "std"), no_std)] -#![deny(missing_docs)] -#![doc(html_root_url = "https://docs.rs/memchr/2.0.0")] +# Overview -// Supporting 8-bit (or others) would be fine. If you need it, please submit a -// bug report at https://github.com/BurntSushi/rust-memchr -#[cfg(not(any( - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64" -)))] -compile_error!("memchr currently not supported on non-{16,32,64}"); +This section gives a brief high level overview of what this crate offers. -use core::iter::Rev; +* The top-level module provides routines for searching for 1, 2 or 3 bytes + in the forward or reverse direction. When searching for more than one byte, + positions are considered a match if the byte at that position matches any + of the bytes. +* The [`memmem`] sub-module provides forward and reverse substring search + routines. -pub use crate::iter::{Memchr, Memchr2, Memchr3}; +In all such cases, routines operate on `&[u8]` without regard to encoding. This +is exactly what you want when searching either UTF-8 or arbitrary bytes. -// N.B. If you're looking for the cfg knobs for libc, see build.rs. -#[cfg(memchr_libc)] -mod c; -#[allow(dead_code)] -mod fallback; -mod iter; -mod naive; -#[cfg(test)] -mod tests; -#[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] -mod x86; +# Example: using `memchr` -/// An iterator over all occurrences of the needle in a haystack. -#[inline] -pub fn memchr_iter(needle: u8, haystack: &[u8]) -> Memchr<'_> { - Memchr::new(needle, haystack) -} +This example shows how to use `memchr` to find the first occurrence of `z` in +a haystack: -/// An iterator over all occurrences of the needles in a haystack. -#[inline] -pub fn memchr2_iter(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2<'_> { - Memchr2::new(needle1, needle2, haystack) -} +``` +use memchr::memchr; -/// An iterator over all occurrences of the needles in a haystack. -#[inline] -pub fn memchr3_iter( - needle1: u8, - needle2: u8, - needle3: u8, - haystack: &[u8], -) -> Memchr3<'_> { - Memchr3::new(needle1, needle2, needle3, haystack) -} +let haystack = b"foo bar baz quuz"; +assert_eq!(Some(10), memchr(b'z', haystack)); +``` -/// An iterator over all occurrences of the needle in a haystack, in reverse. -#[inline] -pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev> { - Memchr::new(needle, haystack).rev() -} +# Example: matching one of three possible bytes -/// An iterator over all occurrences of the needles in a haystack, in reverse. -#[inline] -pub fn memrchr2_iter( - needle1: u8, - needle2: u8, - haystack: &[u8], -) -> Rev> { - Memchr2::new(needle1, needle2, haystack).rev() -} +This examples shows how to use `memrchr3` to find occurrences of `a`, `b` or +`c`, starting at the end of the haystack. -/// An iterator over all occurrences of the needles in a haystack, in reverse. -#[inline] -pub fn memrchr3_iter( - needle1: u8, - needle2: u8, - needle3: u8, - haystack: &[u8], -) -> Rev> { - Memchr3::new(needle1, needle2, needle3, haystack).rev() -} +``` +use memchr::memchr3_iter; -/// Search for the first occurrence of a byte in a slice. -/// -/// This returns the index corresponding to the first occurrence of `needle` in -/// `haystack`, or `None` if one is not found. -/// -/// While this is operationally the same as something like -/// `haystack.iter().position(|&b| b == needle)`, `memchr` will use a highly -/// optimized routine that can be up to an order of magnitude faster in some -/// cases. -/// -/// # Example -/// -/// This shows how to find the first position of a byte in a byte string. -/// -/// ``` -/// use memchr::memchr; -/// -/// let haystack = b"the quick brown fox"; -/// assert_eq!(memchr(b'k', haystack), Some(8)); -/// ``` -#[inline] -pub fn memchr(needle: u8, haystack: &[u8]) -> Option { - #[cfg(miri)] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - naive::memchr(n1, haystack) - } - - #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - x86::memchr(n1, haystack) - } - - #[cfg(all( - memchr_libc, - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - c::memchr(n1, haystack) - } - - #[cfg(all( - not(memchr_libc), - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - fallback::memchr(n1, haystack) - } - - if haystack.is_empty() { - None - } else { - imp(needle, haystack) - } -} +let haystack = b"xyzaxyzbxyzc"; -/// Like `memchr`, but searches for either of two bytes instead of just one. -/// -/// This returns the index corresponding to the first occurrence of `needle1` -/// or the first occurrence of `needle2` in `haystack` (whichever occurs -/// earlier), or `None` if neither one is found. -/// -/// While this is operationally the same as something like -/// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, `memchr2` -/// will use a highly optimized routine that can be up to an order of magnitude -/// faster in some cases. -/// -/// # Example -/// -/// This shows how to find the first position of either of two bytes in a byte -/// string. -/// -/// ``` -/// use memchr::memchr2; -/// -/// let haystack = b"the quick brown fox"; -/// assert_eq!(memchr2(b'k', b'q', haystack), Some(4)); -/// ``` -#[inline] -pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option { - #[cfg(miri)] - #[inline(always)] - fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { - naive::memchr2(n1, n2, haystack) - } - - #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] - #[inline(always)] - fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { - x86::memchr2(n1, n2, haystack) - } - - #[cfg(all( - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { - fallback::memchr2(n1, n2, haystack) - } - - if haystack.is_empty() { - None - } else { - imp(needle1, needle2, haystack) - } -} +let mut it = memchr3_iter(b'a', b'b', b'c', haystack).rev(); +assert_eq!(Some(11), it.next()); +assert_eq!(Some(7), it.next()); +assert_eq!(Some(3), it.next()); +assert_eq!(None, it.next()); +``` -/// Like `memchr`, but searches for any of three bytes instead of just one. -/// -/// This returns the index corresponding to the first occurrence of `needle1`, -/// the first occurrence of `needle2`, or the first occurrence of `needle3` in -/// `haystack` (whichever occurs earliest), or `None` if none are found. -/// -/// While this is operationally the same as something like -/// `haystack.iter().position(|&b| b == needle1 || b == needle2 || -/// b == needle3)`, `memchr3` will use a highly optimized routine that can be -/// up to an order of magnitude faster in some cases. -/// -/// # Example -/// -/// This shows how to find the first position of any of three bytes in a byte -/// string. -/// -/// ``` -/// use memchr::memchr3; -/// -/// let haystack = b"the quick brown fox"; -/// assert_eq!(memchr3(b'k', b'q', b'e', haystack), Some(2)); -/// ``` -#[inline] -pub fn memchr3( - needle1: u8, - needle2: u8, - needle3: u8, - haystack: &[u8], -) -> Option { - #[cfg(miri)] - #[inline(always)] - fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - naive::memchr3(n1, n2, n3, haystack) - } - - #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] - #[inline(always)] - fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - x86::memchr3(n1, n2, n3, haystack) - } - - #[cfg(all( - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - fallback::memchr3(n1, n2, n3, haystack) - } - - if haystack.is_empty() { - None - } else { - imp(needle1, needle2, needle3, haystack) - } -} +# Example: iterating over substring matches -/// Search for the last occurrence of a byte in a slice. -/// -/// This returns the index corresponding to the last occurrence of `needle` in -/// `haystack`, or `None` if one is not found. -/// -/// While this is operationally the same as something like -/// `haystack.iter().rposition(|&b| b == needle)`, `memrchr` will use a highly -/// optimized routine that can be up to an order of magnitude faster in some -/// cases. -/// -/// # Example -/// -/// This shows how to find the last position of a byte in a byte string. -/// -/// ``` -/// use memchr::memrchr; -/// -/// let haystack = b"the quick brown fox"; -/// assert_eq!(memrchr(b'o', haystack), Some(17)); -/// ``` -#[inline] -pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { - #[cfg(miri)] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - naive::memrchr(n1, haystack) - } - - #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - x86::memrchr(n1, haystack) - } - - #[cfg(all( - memchr_libc, - target_os = "linux", - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri) - ))] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - c::memrchr(n1, haystack) - } - - #[cfg(all( - not(all(memchr_libc, target_os = "linux")), - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, haystack: &[u8]) -> Option { - fallback::memrchr(n1, haystack) - } - - if haystack.is_empty() { - None - } else { - imp(needle, haystack) - } -} +This example shows how to use the [`memmem`] sub-module to find occurrences of +a substring in a haystack. + +``` +use memchr::memmem; + +let haystack = b"foo bar foo baz foo"; + +let mut it = memmem::find_iter(haystack, "foo"); +assert_eq!(Some(0), it.next()); +assert_eq!(Some(8), it.next()); +assert_eq!(Some(16), it.next()); +assert_eq!(None, it.next()); +``` -/// Like `memrchr`, but searches for either of two bytes instead of just one. -/// -/// This returns the index corresponding to the last occurrence of `needle1` -/// or the last occurrence of `needle2` in `haystack` (whichever occurs later), -/// or `None` if neither one is found. -/// -/// While this is operationally the same as something like -/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, `memrchr2` -/// will use a highly optimized routine that can be up to an order of magnitude -/// faster in some cases. -/// -/// # Example -/// -/// This shows how to find the last position of either of two bytes in a byte -/// string. -/// -/// ``` -/// use memchr::memrchr2; -/// -/// let haystack = b"the quick brown fox"; -/// assert_eq!(memrchr2(b'k', b'q', haystack), Some(8)); -/// ``` -#[inline] -pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option { - #[cfg(miri)] - #[inline(always)] - fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { - naive::memrchr2(n1, n2, haystack) - } - - #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] - #[inline(always)] - fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { - x86::memrchr2(n1, n2, haystack) - } - - #[cfg(all( - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { - fallback::memrchr2(n1, n2, haystack) - } - - if haystack.is_empty() { - None - } else { - imp(needle1, needle2, haystack) - } +# Example: repeating a search for the same needle + +It may be possible for the overhead of constructing a substring searcher to be +measurable in some workloads. In cases where the same needle is used to search +many haystacks, it is possible to do construction once and thus to avoid it for +subsequent searches. This can be done with a [`memmem::Finder`]: + +``` +use memchr::memmem; + +let finder = memmem::Finder::new("foo"); + +assert_eq!(Some(4), finder.find(b"baz foo quux")); +assert_eq!(None, finder.find(b"quux baz bar")); +``` + +# Why use this crate? + +At first glance, the APIs provided by this crate might seem weird. Why provide +a dedicated routine like `memchr` for something that could be implemented +clearly and trivially in one line: + +``` +fn memchr(needle: u8, haystack: &[u8]) -> Option { + haystack.iter().position(|&b| b == needle) } +``` -/// Like `memrchr`, but searches for any of three bytes instead of just one. -/// -/// This returns the index corresponding to the last occurrence of `needle1`, -/// the last occurrence of `needle2`, or the last occurrence of `needle3` in -/// `haystack` (whichever occurs later), or `None` if none are found. -/// -/// While this is operationally the same as something like -/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 || -/// b == needle3)`, `memrchr3` will use a highly optimized routine that can be -/// up to an order of magnitude faster in some cases. -/// -/// # Example -/// -/// This shows how to find the last position of any of three bytes in a byte -/// string. -/// -/// ``` -/// use memchr::memrchr3; -/// -/// let haystack = b"the quick brown fox"; -/// assert_eq!(memrchr3(b'k', b'q', b'e', haystack), Some(8)); -/// ``` -#[inline] -pub fn memrchr3( - needle1: u8, - needle2: u8, - needle3: u8, - haystack: &[u8], -) -> Option { - #[cfg(miri)] - #[inline(always)] - fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - naive::memrchr3(n1, n2, n3, haystack) - } - - #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] - #[inline(always)] - fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - x86::memrchr3(n1, n2, n3, haystack) - } - - #[cfg(all( - not(all(target_arch = "x86_64", memchr_runtime_simd)), - not(miri), - ))] - #[inline(always)] - fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - fallback::memrchr3(n1, n2, n3, haystack) - } - - if haystack.is_empty() { - None - } else { - imp(needle1, needle2, needle3, haystack) - } +Or similarly, why does this crate provide substring search routines when Rust's +core library already provides them? + +``` +fn search(haystack: &str, needle: &str) -> Option { + haystack.find(needle) } +``` + +The primary reason for both of them to exist is performance. When it comes to +performance, at a high level at least, there are two primary ways to look at +it: + +* **Throughput**: For this, think about it as, "given some very large haystack + and a byte that never occurs in that haystack, how long does it take to + search through it and determine that it, in fact, does not occur?" +* **Latency**: For this, think about it as, "given a tiny haystack---just a + few bytes---how long does it take to determine if a byte is in it?" + +The `memchr` routine in this crate has _slightly_ worse latency than the +solution presented above, however, its throughput can easily be over an +order of magnitude faster. This is a good general purpose trade off to make. +You rarely lose, but often gain big. + +**NOTE:** The name `memchr` comes from the corresponding routine in libc. A key +advantage of using this library is that its performance is not tied to its +quality of implementation in the libc you happen to be using, which can vary +greatly from platform to platform. + +But what about substring search? This one is a bit more complicated. The +primary reason for its existence is still indeed performance, but it's also +useful because Rust's core library doesn't actually expose any substring +search routine on arbitrary bytes. The only substring search routine that +exists works exclusively on valid UTF-8. + +So if you have valid UTF-8, is there a reason to use this over the standard +library substring search routine? Yes. This routine is faster on almost every +metric, including latency. The natural question then, is why isn't this +implementation in the standard library, even if only for searching on UTF-8? +The reason is that the implementation details for using SIMD in the standard +library haven't quite been worked out yet. + +**NOTE:** Currently, only `x86_64` targets have highly accelerated +implementations of substring search. For `memchr`, all targets have +somewhat-accelerated implementations, while only `x86_64` targets have highly +accelerated implementations. This limitation is expected to be lifted once the +standard library exposes a platform independent SIMD API. + +# Crate features + +* **std** - When enabled (the default), this will permit this crate to use + features specific to the standard library. Currently, the only thing used + from the standard library is runtime SIMD CPU feature detection. This means + that this feature must be enabled to get AVX accelerated routines. When + `std` is not enabled, this crate will still attempt to use SSE2 accelerated + routines on `x86_64`. +* **libc** - When enabled (**not** the default), this library will use your + platform's libc implementation of `memchr` (and `memrchr` on Linux). This + can be useful on non-`x86_64` targets where the fallback implementation in + this crate is not as good as the one found in your libc. All other routines + (e.g., `memchr[23]` and substring search) unconditionally use the + implementation in this crate. +*/ + +#![deny(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] +// It's not worth trying to gate all code on just miri, so turn off relevant +// dead code warnings. +#![cfg_attr(miri, allow(dead_code, unused_macros))] + +// Supporting 8-bit (or others) would be fine. If you need it, please submit a +// bug report at https://github.com/BurntSushi/rust-memchr +#[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" +)))] +compile_error!("memchr currently not supported on non-{16,32,64}"); + +pub use crate::memchr::{ + memchr, memchr2, memchr2_iter, memchr3, memchr3_iter, memchr_iter, + memrchr, memrchr2, memrchr2_iter, memrchr3, memrchr3_iter, memrchr_iter, + Memchr, Memchr2, Memchr3, +}; + +mod cow; +mod memchr; +pub mod memmem; +#[cfg(test)] +mod tests; diff --git a/src/c.rs b/src/memchr/c.rs similarity index 89% rename from src/c.rs rename to src/memchr/c.rs index 600a23e..608aabc 100644 --- a/src/c.rs +++ b/src/memchr/c.rs @@ -6,6 +6,7 @@ use libc::{c_int, c_void, size_t}; pub fn memchr(needle: u8, haystack: &[u8]) -> Option { + // SAFETY: This is safe to call since all pointers are valid. let p = unsafe { libc::memchr( haystack.as_ptr() as *const c_void, @@ -27,6 +28,7 @@ pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { if haystack.is_empty() { return None; } + // SAFETY: This is safe to call since all pointers are valid. let p = unsafe { libc::memrchr( haystack.as_ptr() as *const c_void, diff --git a/src/fallback.rs b/src/memchr/fallback.rs similarity index 96% rename from src/fallback.rs rename to src/memchr/fallback.rs index baee29d..b01f224 100644 --- a/src/fallback.rs +++ b/src/memchr/fallback.rs @@ -49,10 +49,10 @@ pub fn memchr(n1: u8, haystack: &[u8]) -> Option { let loop_size = cmp::min(LOOP_SIZE, haystack.len()); let align = USIZE_BYTES - 1; let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); let mut ptr = start_ptr; unsafe { + let end_ptr = start_ptr.add(haystack.len()); if haystack.len() < USIZE_BYTES { return forward_search(start_ptr, end_ptr, ptr, confirm); } @@ -88,10 +88,10 @@ pub fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { let confirm = |byte| byte == n1 || byte == n2; let align = USIZE_BYTES - 1; let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); let mut ptr = start_ptr; unsafe { + let end_ptr = start_ptr.add(haystack.len()); if haystack.len() < USIZE_BYTES { return forward_search(start_ptr, end_ptr, ptr, confirm); } @@ -129,10 +129,10 @@ pub fn memchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { let confirm = |byte| byte == n1 || byte == n2 || byte == n3; let align = USIZE_BYTES - 1; let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); let mut ptr = start_ptr; unsafe { + let end_ptr = start_ptr.add(haystack.len()); if haystack.len() < USIZE_BYTES { return forward_search(start_ptr, end_ptr, ptr, confirm); } @@ -171,10 +171,10 @@ pub fn memrchr(n1: u8, haystack: &[u8]) -> Option { let loop_size = cmp::min(LOOP_SIZE, haystack.len()); let align = USIZE_BYTES - 1; let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); - let mut ptr = end_ptr; unsafe { + let end_ptr = start_ptr.add(haystack.len()); + let mut ptr = end_ptr; if haystack.len() < USIZE_BYTES { return reverse_search(start_ptr, end_ptr, ptr, confirm); } @@ -209,10 +209,10 @@ pub fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { let confirm = |byte| byte == n1 || byte == n2; let align = USIZE_BYTES - 1; let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); - let mut ptr = end_ptr; unsafe { + let end_ptr = start_ptr.add(haystack.len()); + let mut ptr = end_ptr; if haystack.len() < USIZE_BYTES { return reverse_search(start_ptr, end_ptr, ptr, confirm); } @@ -249,10 +249,10 @@ pub fn memrchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { let confirm = |byte| byte == n1 || byte == n2 || byte == n3; let align = USIZE_BYTES - 1; let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); - let mut ptr = end_ptr; unsafe { + let end_ptr = start_ptr.add(haystack.len()); + let mut ptr = end_ptr; if haystack.len() < USIZE_BYTES { return reverse_search(start_ptr, end_ptr, ptr, confirm); } diff --git a/src/iter.rs b/src/memchr/iter.rs similarity index 100% rename from src/iter.rs rename to src/memchr/iter.rs diff --git a/src/memchr/mod.rs b/src/memchr/mod.rs new file mode 100644 index 0000000..09ce6ef --- /dev/null +++ b/src/memchr/mod.rs @@ -0,0 +1,410 @@ +use core::iter::Rev; + +pub use self::iter::{Memchr, Memchr2, Memchr3}; + +// N.B. If you're looking for the cfg knobs for libc, see build.rs. +#[cfg(memchr_libc)] +mod c; +#[allow(dead_code)] +pub mod fallback; +mod iter; +pub mod naive; +#[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] +mod x86; + +/// An iterator over all occurrences of the needle in a haystack. +#[inline] +pub fn memchr_iter(needle: u8, haystack: &[u8]) -> Memchr<'_> { + Memchr::new(needle, haystack) +} + +/// An iterator over all occurrences of the needles in a haystack. +#[inline] +pub fn memchr2_iter(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2<'_> { + Memchr2::new(needle1, needle2, haystack) +} + +/// An iterator over all occurrences of the needles in a haystack. +#[inline] +pub fn memchr3_iter( + needle1: u8, + needle2: u8, + needle3: u8, + haystack: &[u8], +) -> Memchr3<'_> { + Memchr3::new(needle1, needle2, needle3, haystack) +} + +/// An iterator over all occurrences of the needle in a haystack, in reverse. +#[inline] +pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev> { + Memchr::new(needle, haystack).rev() +} + +/// An iterator over all occurrences of the needles in a haystack, in reverse. +#[inline] +pub fn memrchr2_iter( + needle1: u8, + needle2: u8, + haystack: &[u8], +) -> Rev> { + Memchr2::new(needle1, needle2, haystack).rev() +} + +/// An iterator over all occurrences of the needles in a haystack, in reverse. +#[inline] +pub fn memrchr3_iter( + needle1: u8, + needle2: u8, + needle3: u8, + haystack: &[u8], +) -> Rev> { + Memchr3::new(needle1, needle2, needle3, haystack).rev() +} + +/// Search for the first occurrence of a byte in a slice. +/// +/// This returns the index corresponding to the first occurrence of `needle` in +/// `haystack`, or `None` if one is not found. If an index is returned, it is +/// guaranteed to be less than `usize::MAX`. +/// +/// While this is operationally the same as something like +/// `haystack.iter().position(|&b| b == needle)`, `memchr` will use a highly +/// optimized routine that can be up to an order of magnitude faster in some +/// cases. +/// +/// # Example +/// +/// This shows how to find the first position of a byte in a byte string. +/// +/// ``` +/// use memchr::memchr; +/// +/// let haystack = b"the quick brown fox"; +/// assert_eq!(memchr(b'k', haystack), Some(8)); +/// ``` +#[inline] +pub fn memchr(needle: u8, haystack: &[u8]) -> Option { + #[cfg(miri)] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + naive::memchr(n1, haystack) + } + + #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + x86::memchr(n1, haystack) + } + + #[cfg(all( + memchr_libc, + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + c::memchr(n1, haystack) + } + + #[cfg(all( + not(memchr_libc), + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + fallback::memchr(n1, haystack) + } + + if haystack.is_empty() { + None + } else { + imp(needle, haystack) + } +} + +/// Like `memchr`, but searches for either of two bytes instead of just one. +/// +/// This returns the index corresponding to the first occurrence of `needle1` +/// or the first occurrence of `needle2` in `haystack` (whichever occurs +/// earlier), or `None` if neither one is found. If an index is returned, it is +/// guaranteed to be less than `usize::MAX`. +/// +/// While this is operationally the same as something like +/// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, `memchr2` +/// will use a highly optimized routine that can be up to an order of magnitude +/// faster in some cases. +/// +/// # Example +/// +/// This shows how to find the first position of either of two bytes in a byte +/// string. +/// +/// ``` +/// use memchr::memchr2; +/// +/// let haystack = b"the quick brown fox"; +/// assert_eq!(memchr2(b'k', b'q', haystack), Some(4)); +/// ``` +#[inline] +pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option { + #[cfg(miri)] + #[inline(always)] + fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { + naive::memchr2(n1, n2, haystack) + } + + #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] + #[inline(always)] + fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { + x86::memchr2(n1, n2, haystack) + } + + #[cfg(all( + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { + fallback::memchr2(n1, n2, haystack) + } + + if haystack.is_empty() { + None + } else { + imp(needle1, needle2, haystack) + } +} + +/// Like `memchr`, but searches for any of three bytes instead of just one. +/// +/// This returns the index corresponding to the first occurrence of `needle1`, +/// the first occurrence of `needle2`, or the first occurrence of `needle3` in +/// `haystack` (whichever occurs earliest), or `None` if none are found. If an +/// index is returned, it is guaranteed to be less than `usize::MAX`. +/// +/// While this is operationally the same as something like +/// `haystack.iter().position(|&b| b == needle1 || b == needle2 || +/// b == needle3)`, `memchr3` will use a highly optimized routine that can be +/// up to an order of magnitude faster in some cases. +/// +/// # Example +/// +/// This shows how to find the first position of any of three bytes in a byte +/// string. +/// +/// ``` +/// use memchr::memchr3; +/// +/// let haystack = b"the quick brown fox"; +/// assert_eq!(memchr3(b'k', b'q', b'e', haystack), Some(2)); +/// ``` +#[inline] +pub fn memchr3( + needle1: u8, + needle2: u8, + needle3: u8, + haystack: &[u8], +) -> Option { + #[cfg(miri)] + #[inline(always)] + fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + naive::memchr3(n1, n2, n3, haystack) + } + + #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] + #[inline(always)] + fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + x86::memchr3(n1, n2, n3, haystack) + } + + #[cfg(all( + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + fallback::memchr3(n1, n2, n3, haystack) + } + + if haystack.is_empty() { + None + } else { + imp(needle1, needle2, needle3, haystack) + } +} + +/// Search for the last occurrence of a byte in a slice. +/// +/// This returns the index corresponding to the last occurrence of `needle` in +/// `haystack`, or `None` if one is not found. If an index is returned, it is +/// guaranteed to be less than `usize::MAX`. +/// +/// While this is operationally the same as something like +/// `haystack.iter().rposition(|&b| b == needle)`, `memrchr` will use a highly +/// optimized routine that can be up to an order of magnitude faster in some +/// cases. +/// +/// # Example +/// +/// This shows how to find the last position of a byte in a byte string. +/// +/// ``` +/// use memchr::memrchr; +/// +/// let haystack = b"the quick brown fox"; +/// assert_eq!(memrchr(b'o', haystack), Some(17)); +/// ``` +#[inline] +pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { + #[cfg(miri)] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + naive::memrchr(n1, haystack) + } + + #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + x86::memrchr(n1, haystack) + } + + #[cfg(all( + memchr_libc, + target_os = "linux", + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri) + ))] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + c::memrchr(n1, haystack) + } + + #[cfg(all( + not(all(memchr_libc, target_os = "linux")), + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, haystack: &[u8]) -> Option { + fallback::memrchr(n1, haystack) + } + + if haystack.is_empty() { + None + } else { + imp(needle, haystack) + } +} + +/// Like `memrchr`, but searches for either of two bytes instead of just one. +/// +/// This returns the index corresponding to the last occurrence of `needle1` or +/// the last occurrence of `needle2` in `haystack` (whichever occurs later), or +/// `None` if neither one is found. If an index is returned, it is guaranteed +/// to be less than `usize::MAX`. +/// +/// While this is operationally the same as something like +/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, `memrchr2` +/// will use a highly optimized routine that can be up to an order of magnitude +/// faster in some cases. +/// +/// # Example +/// +/// This shows how to find the last position of either of two bytes in a byte +/// string. +/// +/// ``` +/// use memchr::memrchr2; +/// +/// let haystack = b"the quick brown fox"; +/// assert_eq!(memrchr2(b'k', b'q', haystack), Some(8)); +/// ``` +#[inline] +pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option { + #[cfg(miri)] + #[inline(always)] + fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { + naive::memrchr2(n1, n2, haystack) + } + + #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] + #[inline(always)] + fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { + x86::memrchr2(n1, n2, haystack) + } + + #[cfg(all( + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option { + fallback::memrchr2(n1, n2, haystack) + } + + if haystack.is_empty() { + None + } else { + imp(needle1, needle2, haystack) + } +} + +/// Like `memrchr`, but searches for any of three bytes instead of just one. +/// +/// This returns the index corresponding to the last occurrence of `needle1`, +/// the last occurrence of `needle2`, or the last occurrence of `needle3` in +/// `haystack` (whichever occurs later), or `None` if none are found. If an +/// index is returned, it is guaranteed to be less than `usize::MAX`. +/// +/// While this is operationally the same as something like +/// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 || +/// b == needle3)`, `memrchr3` will use a highly optimized routine that can be +/// up to an order of magnitude faster in some cases. +/// +/// # Example +/// +/// This shows how to find the last position of any of three bytes in a byte +/// string. +/// +/// ``` +/// use memchr::memrchr3; +/// +/// let haystack = b"the quick brown fox"; +/// assert_eq!(memrchr3(b'k', b'q', b'e', haystack), Some(8)); +/// ``` +#[inline] +pub fn memrchr3( + needle1: u8, + needle2: u8, + needle3: u8, + haystack: &[u8], +) -> Option { + #[cfg(miri)] + #[inline(always)] + fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + naive::memrchr3(n1, n2, n3, haystack) + } + + #[cfg(all(target_arch = "x86_64", memchr_runtime_simd, not(miri)))] + #[inline(always)] + fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + x86::memrchr3(n1, n2, n3, haystack) + } + + #[cfg(all( + not(all(target_arch = "x86_64", memchr_runtime_simd)), + not(miri), + ))] + #[inline(always)] + fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + fallback::memrchr3(n1, n2, n3, haystack) + } + + if haystack.is_empty() { + None + } else { + imp(needle1, needle2, needle3, haystack) + } +} diff --git a/src/naive.rs b/src/memchr/naive.rs similarity index 100% rename from src/naive.rs rename to src/memchr/naive.rs diff --git a/src/x86/avx.rs b/src/memchr/x86/avx.rs similarity index 87% rename from src/x86/avx.rs rename to src/memchr/x86/avx.rs index 37ca53b..5351230 100644 --- a/src/x86/avx.rs +++ b/src/memchr/x86/avx.rs @@ -1,6 +1,6 @@ use core::{arch::x86_64::*, cmp, mem::size_of}; -use crate::x86::sse2; +use super::sse2; const VECTOR_SIZE: usize = size_of::<__m256i>(); const VECTOR_ALIGN: usize = VECTOR_SIZE - 1; @@ -20,8 +20,50 @@ pub unsafe fn memchr(n1: u8, haystack: &[u8]) -> Option { // sse2 implementation. The avx implementation here is the same, but with // 256-bit vectors instead of 128-bit vectors. + // This routine is called whenever a match is detected. It is specifically + // marked as unlineable because it improves the codegen of the unrolled + // loop below. Inlining this seems to cause codegen with some extra adds + // and a load that aren't necessary. This seems to result in about a 10% + // improvement for the memchr1/crate/huge/never benchmark. + // + // Interestingly, I couldn't observe a similar improvement for memrchr. + #[cold] + #[inline(never)] + #[target_feature(enable = "avx2")] + unsafe fn matched( + start_ptr: *const u8, + ptr: *const u8, + eqa: __m256i, + eqb: __m256i, + eqc: __m256i, + eqd: __m256i, + ) -> usize { + let mut at = sub(ptr, start_ptr); + let mask = _mm256_movemask_epi8(eqa); + if mask != 0 { + return at + forward_pos(mask); + } + + at += VECTOR_SIZE; + let mask = _mm256_movemask_epi8(eqb); + if mask != 0 { + return at + forward_pos(mask); + } + + at += VECTOR_SIZE; + let mask = _mm256_movemask_epi8(eqc); + if mask != 0 { + return at + forward_pos(mask); + } + + at += VECTOR_SIZE; + let mask = _mm256_movemask_epi8(eqd); + debug_assert!(mask != 0); + at + forward_pos(mask) + } + let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = start_ptr; if haystack.len() < VECTOR_SIZE { @@ -52,29 +94,9 @@ pub unsafe fn memchr(n1: u8, haystack: &[u8]) -> Option { let or1 = _mm256_or_si256(eqa, eqb); let or2 = _mm256_or_si256(eqc, eqd); let or3 = _mm256_or_si256(or1, or2); - if _mm256_movemask_epi8(or3) != 0 { - let mut at = sub(ptr, start_ptr); - let mask = _mm256_movemask_epi8(eqa); - if mask != 0 { - return Some(at + forward_pos(mask)); - } - at += VECTOR_SIZE; - let mask = _mm256_movemask_epi8(eqb); - if mask != 0 { - return Some(at + forward_pos(mask)); - } - - at += VECTOR_SIZE; - let mask = _mm256_movemask_epi8(eqc); - if mask != 0 { - return Some(at + forward_pos(mask)); - } - - at += VECTOR_SIZE; - let mask = _mm256_movemask_epi8(eqd); - debug_assert!(mask != 0); - return Some(at + forward_pos(mask)); + if _mm256_movemask_epi8(or3) != 0 { + return Some(matched(start_ptr, ptr, eqa, eqb, eqc, eqd)); } ptr = ptr.add(loop_size); } @@ -98,12 +120,36 @@ pub unsafe fn memchr(n1: u8, haystack: &[u8]) -> Option { #[target_feature(enable = "avx2")] pub unsafe fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { + #[cold] + #[inline(never)] + #[target_feature(enable = "avx2")] + unsafe fn matched( + start_ptr: *const u8, + ptr: *const u8, + eqa1: __m256i, + eqa2: __m256i, + eqb1: __m256i, + eqb2: __m256i, + ) -> usize { + let mut at = sub(ptr, start_ptr); + let mask1 = _mm256_movemask_epi8(eqa1); + let mask2 = _mm256_movemask_epi8(eqa2); + if mask1 != 0 || mask2 != 0 { + return at + forward_pos2(mask1, mask2); + } + + at += VECTOR_SIZE; + let mask1 = _mm256_movemask_epi8(eqb1); + let mask2 = _mm256_movemask_epi8(eqb2); + at + forward_pos2(mask1, mask2) + } + let vn1 = _mm256_set1_epi8(n1 as i8); let vn2 = _mm256_set1_epi8(n2 as i8); let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = start_ptr; if haystack.len() < VECTOR_SIZE { @@ -135,17 +181,7 @@ pub unsafe fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { let or2 = _mm256_or_si256(eqa2, eqb2); let or3 = _mm256_or_si256(or1, or2); if _mm256_movemask_epi8(or3) != 0 { - let mut at = sub(ptr, start_ptr); - let mask1 = _mm256_movemask_epi8(eqa1); - let mask2 = _mm256_movemask_epi8(eqa2); - if mask1 != 0 || mask2 != 0 { - return Some(at + forward_pos2(mask1, mask2)); - } - - at += VECTOR_SIZE; - let mask1 = _mm256_movemask_epi8(eqb1); - let mask2 = _mm256_movemask_epi8(eqb2); - return Some(at + forward_pos2(mask1, mask2)); + return Some(matched(start_ptr, ptr, eqa1, eqa2, eqb1, eqb2)); } ptr = ptr.add(loop_size); } @@ -172,13 +208,41 @@ pub unsafe fn memchr3( n3: u8, haystack: &[u8], ) -> Option { + #[cold] + #[inline(never)] + #[target_feature(enable = "avx2")] + unsafe fn matched( + start_ptr: *const u8, + ptr: *const u8, + eqa1: __m256i, + eqa2: __m256i, + eqa3: __m256i, + eqb1: __m256i, + eqb2: __m256i, + eqb3: __m256i, + ) -> usize { + let mut at = sub(ptr, start_ptr); + let mask1 = _mm256_movemask_epi8(eqa1); + let mask2 = _mm256_movemask_epi8(eqa2); + let mask3 = _mm256_movemask_epi8(eqa3); + if mask1 != 0 || mask2 != 0 || mask3 != 0 { + return at + forward_pos3(mask1, mask2, mask3); + } + + at += VECTOR_SIZE; + let mask1 = _mm256_movemask_epi8(eqb1); + let mask2 = _mm256_movemask_epi8(eqb2); + let mask3 = _mm256_movemask_epi8(eqb3); + at + forward_pos3(mask1, mask2, mask3) + } + let vn1 = _mm256_set1_epi8(n1 as i8); let vn2 = _mm256_set1_epi8(n2 as i8); let vn3 = _mm256_set1_epi8(n3 as i8); let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = start_ptr; if haystack.len() < VECTOR_SIZE { @@ -214,19 +278,9 @@ pub unsafe fn memchr3( let or4 = _mm256_or_si256(or1, or2); let or5 = _mm256_or_si256(or3, or4); if _mm256_movemask_epi8(or5) != 0 { - let mut at = sub(ptr, start_ptr); - let mask1 = _mm256_movemask_epi8(eqa1); - let mask2 = _mm256_movemask_epi8(eqa2); - let mask3 = _mm256_movemask_epi8(eqa3); - if mask1 != 0 || mask2 != 0 || mask3 != 0 { - return Some(at + forward_pos3(mask1, mask2, mask3)); - } - - at += VECTOR_SIZE; - let mask1 = _mm256_movemask_epi8(eqb1); - let mask2 = _mm256_movemask_epi8(eqb2); - let mask3 = _mm256_movemask_epi8(eqb3); - return Some(at + forward_pos3(mask1, mask2, mask3)); + return Some(matched( + start_ptr, ptr, eqa1, eqa2, eqa3, eqb1, eqb2, eqb3, + )); } ptr = ptr.add(loop_size); } @@ -254,7 +308,7 @@ pub unsafe fn memrchr(n1: u8, haystack: &[u8]) -> Option { let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = end_ptr; if haystack.len() < VECTOR_SIZE { @@ -334,7 +388,7 @@ pub unsafe fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = end_ptr; if haystack.len() < VECTOR_SIZE { @@ -407,7 +461,7 @@ pub unsafe fn memrchr3( let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = end_ptr; if haystack.len() < VECTOR_SIZE { diff --git a/src/memchr/x86/mod.rs b/src/memchr/x86/mod.rs new file mode 100644 index 0000000..aec35db --- /dev/null +++ b/src/memchr/x86/mod.rs @@ -0,0 +1,148 @@ +use super::fallback; + +// We only use AVX when we can detect at runtime whether it's available, which +// requires std. +#[cfg(feature = "std")] +mod avx; +mod sse2; + +/// This macro employs a gcc-like "ifunc" trick where by upon first calling +/// `memchr` (for example), CPU feature detection will be performed at runtime +/// to determine the best implementation to use. After CPU feature detection +/// is done, we replace `memchr`'s function pointer with the selection. Upon +/// subsequent invocations, the CPU-specific routine is invoked directly, which +/// skips the CPU feature detection and subsequent branch that's required. +/// +/// While this typically doesn't matter for rare occurrences or when used on +/// larger haystacks, `memchr` can be called in tight loops where the overhead +/// of this branch can actually add up *and is measurable*. This trick was +/// necessary to bring this implementation up to glibc's speeds for the 'tiny' +/// benchmarks, for example. +/// +/// At some point, I expect the Rust ecosystem will get a nice macro for doing +/// exactly this, at which point, we can replace our hand-jammed version of it. +/// +/// N.B. The ifunc strategy does prevent function inlining of course, but +/// on modern CPUs, you'll probably end up with the AVX2 implementation, +/// which probably can't be inlined anyway---unless you've compiled your +/// entire program with AVX2 enabled. However, even then, the various memchr +/// implementations aren't exactly small, so inlining might not help anyway! +/// +/// # Safety +/// +/// Callers must ensure that fnty is function pointer type. +#[cfg(feature = "std")] +macro_rules! unsafe_ifunc { + ($fnty:ty, $name:ident, $haystack:ident, $($needle:ident),+) => {{ + use std::{mem, sync::atomic::{AtomicPtr, Ordering}}; + + type FnRaw = *mut (); + + static FN: AtomicPtr<()> = AtomicPtr::new(detect as FnRaw); + + fn detect($($needle: u8),+, haystack: &[u8]) -> Option { + let fun = + if cfg!(memchr_runtime_avx) && is_x86_feature_detected!("avx2") { + avx::$name as FnRaw + } else if cfg!(memchr_runtime_sse2) { + sse2::$name as FnRaw + } else { + fallback::$name as FnRaw + }; + FN.store(fun as FnRaw, Ordering::Relaxed); + // SAFETY: By virtue of the caller contract, $fnty is a function + // pointer, which is always safe to transmute with a *mut (). + // Also, if 'fun is the AVX routine, then it is guaranteed to be + // supported since we checked the avx2 feature. + unsafe { + mem::transmute::(fun)($($needle),+, haystack) + } + } + + // SAFETY: By virtue of the caller contract, $fnty is a function + // pointer, which is always safe to transmute with a *mut (). Also, if + // 'fun is the AVX routine, then it is guaranteed to be supported since + // we checked the avx2 feature. + unsafe { + let fun = FN.load(Ordering::Relaxed); + mem::transmute::(fun)($($needle),+, $haystack) + } + }} +} + +/// When std isn't available to provide runtime CPU feature detection, or if +/// runtime CPU feature detection has been explicitly disabled, then just +/// call our optimized SSE2 routine directly. SSE2 is avalbale on all x86_64 +/// targets, so no CPU feature detection is necessary. +/// +/// # Safety +/// +/// There are no safety requirements for this definition of the macro. It is +/// safe for all inputs since it is restricted to either the fallback routine +/// or the SSE routine, which is always safe to call on x86_64. +#[cfg(not(feature = "std"))] +macro_rules! unsafe_ifunc { + ($fnty:ty, $name:ident, $haystack:ident, $($needle:ident),+) => {{ + if cfg!(memchr_runtime_sse2) { + unsafe { sse2::$name($($needle),+, $haystack) } + } else { + fallback::$name($($needle),+, $haystack) + } + }} +} + +#[inline(always)] +pub fn memchr(n1: u8, haystack: &[u8]) -> Option { + unsafe_ifunc!(fn(u8, &[u8]) -> Option, memchr, haystack, n1) +} + +#[inline(always)] +pub fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { + unsafe_ifunc!( + fn(u8, u8, &[u8]) -> Option, + memchr2, + haystack, + n1, + n2 + ) +} + +#[inline(always)] +pub fn memchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + unsafe_ifunc!( + fn(u8, u8, u8, &[u8]) -> Option, + memchr3, + haystack, + n1, + n2, + n3 + ) +} + +#[inline(always)] +pub fn memrchr(n1: u8, haystack: &[u8]) -> Option { + unsafe_ifunc!(fn(u8, &[u8]) -> Option, memrchr, haystack, n1) +} + +#[inline(always)] +pub fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { + unsafe_ifunc!( + fn(u8, u8, &[u8]) -> Option, + memrchr2, + haystack, + n1, + n2 + ) +} + +#[inline(always)] +pub fn memrchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { + unsafe_ifunc!( + fn(u8, u8, u8, &[u8]) -> Option, + memrchr3, + haystack, + n1, + n2, + n3 + ) +} diff --git a/src/x86/sse2.rs b/src/memchr/x86/sse2.rs similarity index 98% rename from src/x86/sse2.rs rename to src/memchr/x86/sse2.rs index 88c9a87..b7b3a93 100644 --- a/src/x86/sse2.rs +++ b/src/memchr/x86/sse2.rs @@ -109,7 +109,7 @@ pub unsafe fn memchr(n1: u8, haystack: &[u8]) -> Option { let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = start_ptr; if haystack.len() < VECTOR_SIZE { @@ -193,7 +193,7 @@ pub unsafe fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = start_ptr; if haystack.len() < VECTOR_SIZE { @@ -268,7 +268,7 @@ pub unsafe fn memchr3( let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = start_ptr; if haystack.len() < VECTOR_SIZE { @@ -344,7 +344,7 @@ pub unsafe fn memrchr(n1: u8, haystack: &[u8]) -> Option { let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = end_ptr; if haystack.len() < VECTOR_SIZE { @@ -424,7 +424,7 @@ pub unsafe fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = end_ptr; if haystack.len() < VECTOR_SIZE { @@ -497,7 +497,7 @@ pub unsafe fn memrchr3( let len = haystack.len(); let loop_size = cmp::min(LOOP_SIZE2, len); let start_ptr = haystack.as_ptr(); - let end_ptr = haystack[haystack.len()..].as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); let mut ptr = end_ptr; if haystack.len() < VECTOR_SIZE { diff --git a/src/x86/sse42.rs b/src/memchr/x86/sse42.rs similarity index 100% rename from src/x86/sse42.rs rename to src/memchr/x86/sse42.rs diff --git a/src/memmem/byte_frequencies.rs b/src/memmem/byte_frequencies.rs new file mode 100644 index 0000000..c313b62 --- /dev/null +++ b/src/memmem/byte_frequencies.rs @@ -0,0 +1,258 @@ +pub const BYTE_FREQUENCIES: [u8; 256] = [ + 55, // '\x00' + 52, // '\x01' + 51, // '\x02' + 50, // '\x03' + 49, // '\x04' + 48, // '\x05' + 47, // '\x06' + 46, // '\x07' + 45, // '\x08' + 103, // '\t' + 242, // '\n' + 66, // '\x0b' + 67, // '\x0c' + 229, // '\r' + 44, // '\x0e' + 43, // '\x0f' + 42, // '\x10' + 41, // '\x11' + 40, // '\x12' + 39, // '\x13' + 38, // '\x14' + 37, // '\x15' + 36, // '\x16' + 35, // '\x17' + 34, // '\x18' + 33, // '\x19' + 56, // '\x1a' + 32, // '\x1b' + 31, // '\x1c' + 30, // '\x1d' + 29, // '\x1e' + 28, // '\x1f' + 255, // ' ' + 148, // '!' + 164, // '"' + 149, // '#' + 136, // '$' + 160, // '%' + 155, // '&' + 173, // "'" + 221, // '(' + 222, // ')' + 134, // '*' + 122, // '+' + 232, // ',' + 202, // '-' + 215, // '.' + 224, // '/' + 208, // '0' + 220, // '1' + 204, // '2' + 187, // '3' + 183, // '4' + 179, // '5' + 177, // '6' + 168, // '7' + 178, // '8' + 200, // '9' + 226, // ':' + 195, // ';' + 154, // '<' + 184, // '=' + 174, // '>' + 126, // '?' + 120, // '@' + 191, // 'A' + 157, // 'B' + 194, // 'C' + 170, // 'D' + 189, // 'E' + 162, // 'F' + 161, // 'G' + 150, // 'H' + 193, // 'I' + 142, // 'J' + 137, // 'K' + 171, // 'L' + 176, // 'M' + 185, // 'N' + 167, // 'O' + 186, // 'P' + 112, // 'Q' + 175, // 'R' + 192, // 'S' + 188, // 'T' + 156, // 'U' + 140, // 'V' + 143, // 'W' + 123, // 'X' + 133, // 'Y' + 128, // 'Z' + 147, // '[' + 138, // '\\' + 146, // ']' + 114, // '^' + 223, // '_' + 151, // '`' + 249, // 'a' + 216, // 'b' + 238, // 'c' + 236, // 'd' + 253, // 'e' + 227, // 'f' + 218, // 'g' + 230, // 'h' + 247, // 'i' + 135, // 'j' + 180, // 'k' + 241, // 'l' + 233, // 'm' + 246, // 'n' + 244, // 'o' + 231, // 'p' + 139, // 'q' + 245, // 'r' + 243, // 's' + 251, // 't' + 235, // 'u' + 201, // 'v' + 196, // 'w' + 240, // 'x' + 214, // 'y' + 152, // 'z' + 182, // '{' + 205, // '|' + 181, // '}' + 127, // '~' + 27, // '\x7f' + 212, // '\x80' + 211, // '\x81' + 210, // '\x82' + 213, // '\x83' + 228, // '\x84' + 197, // '\x85' + 169, // '\x86' + 159, // '\x87' + 131, // '\x88' + 172, // '\x89' + 105, // '\x8a' + 80, // '\x8b' + 98, // '\x8c' + 96, // '\x8d' + 97, // '\x8e' + 81, // '\x8f' + 207, // '\x90' + 145, // '\x91' + 116, // '\x92' + 115, // '\x93' + 144, // '\x94' + 130, // '\x95' + 153, // '\x96' + 121, // '\x97' + 107, // '\x98' + 132, // '\x99' + 109, // '\x9a' + 110, // '\x9b' + 124, // '\x9c' + 111, // '\x9d' + 82, // '\x9e' + 108, // '\x9f' + 118, // '\xa0' + 141, // '¡' + 113, // '¢' + 129, // '£' + 119, // '¤' + 125, // '¥' + 165, // '¦' + 117, // '§' + 92, // '¨' + 106, // '©' + 83, // 'ª' + 72, // '«' + 99, // '¬' + 93, // '\xad' + 65, // '®' + 79, // '¯' + 166, // '°' + 237, // '±' + 163, // '²' + 199, // '³' + 190, // '´' + 225, // 'µ' + 209, // '¶' + 203, // '·' + 198, // '¸' + 217, // '¹' + 219, // 'º' + 206, // '»' + 234, // '¼' + 248, // '½' + 158, // '¾' + 239, // '¿' + 255, // 'À' + 255, // 'Á' + 255, // 'Â' + 255, // 'Ã' + 255, // 'Ä' + 255, // 'Å' + 255, // 'Æ' + 255, // 'Ç' + 255, // 'È' + 255, // 'É' + 255, // 'Ê' + 255, // 'Ë' + 255, // 'Ì' + 255, // 'Í' + 255, // 'Î' + 255, // 'Ï' + 255, // 'Ð' + 255, // 'Ñ' + 255, // 'Ò' + 255, // 'Ó' + 255, // 'Ô' + 255, // 'Õ' + 255, // 'Ö' + 255, // '×' + 255, // 'Ø' + 255, // 'Ù' + 255, // 'Ú' + 255, // 'Û' + 255, // 'Ü' + 255, // 'Ý' + 255, // 'Þ' + 255, // 'ß' + 255, // 'à' + 255, // 'á' + 255, // 'â' + 255, // 'ã' + 255, // 'ä' + 255, // 'å' + 255, // 'æ' + 255, // 'ç' + 255, // 'è' + 255, // 'é' + 255, // 'ê' + 255, // 'ë' + 255, // 'ì' + 255, // 'í' + 255, // 'î' + 255, // 'ï' + 255, // 'ð' + 255, // 'ñ' + 255, // 'ò' + 255, // 'ó' + 255, // 'ô' + 255, // 'õ' + 255, // 'ö' + 255, // '÷' + 255, // 'ø' + 255, // 'ù' + 255, // 'ú' + 255, // 'û' + 255, // 'ü' + 255, // 'ý' + 255, // 'þ' + 255, // 'ÿ' +]; diff --git a/src/memmem/genericsimd.rs b/src/memmem/genericsimd.rs new file mode 100644 index 0000000..2417f91 --- /dev/null +++ b/src/memmem/genericsimd.rs @@ -0,0 +1,264 @@ +use core::mem::size_of; + +use crate::memmem::{util::memcmp, vector::Vector, NeedleInfo}; + +/// The minimum length of a needle required for this algorithm. The minimum +/// is 2 since a length of 1 should just use memchr and a length of 0 isn't +/// a case handled by this searcher. +pub(crate) const MIN_NEEDLE_LEN: usize = 2; + +/// The maximum length of a needle required for this algorithm. +/// +/// In reality, there is no hard max here. The code below can handle any +/// length needle. (Perhaps that suggests there are missing optimizations.) +/// Instead, this is a heuristic and a bound guaranteeing our linear time +/// complexity. +/// +/// It is a heuristic because when a candidate match is found, memcmp is run. +/// For very large needles with lots of false positives, memcmp can make the +/// code run quite slow. +/// +/// It is a bound because the worst case behavior with memcmp is multiplicative +/// in the size of the needle and haystack, and we want to keep that additive. +/// This bound ensures we still meet that bound theoretically, since it's just +/// a constant. We aren't acting in bad faith here, memcmp on tiny needles +/// is so fast that even in pathological cases (see pathological vector +/// benchmarks), this is still just as fast or faster in practice. +/// +/// This specific number was chosen by tweaking a bit and running benchmarks. +/// The rare-medium-needle, for example, gets about 5% faster by using this +/// algorithm instead of a prefilter-accelerated Two-Way. There's also a +/// theoretical desire to keep this number reasonably low, to mitigate the +/// impact of pathological cases. I did try 64, and some benchmarks got a +/// little better, and others (particularly the pathological ones), got a lot +/// worse. So... 32 it is? +pub(crate) const MAX_NEEDLE_LEN: usize = 32; + +/// The implementation of the forward vector accelerated substring search. +/// +/// This is extremely similar to the prefilter vector module by the same name. +/// The key difference is that this is not a prefilter. Instead, it handles +/// confirming its own matches. The trade off is that this only works with +/// smaller needles. The speed up here is that an inlined memcmp on a tiny +/// needle is very quick, even on pathological inputs. This is much better than +/// combining a prefilter with Two-Way, where using Two-Way to confirm the +/// match has higher latency. +/// +/// So why not use this for all needles? We could, and it would probably work +/// really well on most inputs. But its worst case is multiplicative and we +/// want to guarantee worst case additive time. Some of the benchmarks try to +/// justify this (see the pathological ones). +/// +/// The prefilter variant of this has more comments. Also note that we only +/// implement this for forward searches for now. If you have a compelling use +/// case for accelerated reverse search, please file an issue. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Forward { + rare1i: u8, + rare2i: u8, +} + +impl Forward { + /// Create a new "generic simd" forward searcher. If one could not be + /// created from the given inputs, then None is returned. + pub(crate) fn new(ninfo: &NeedleInfo, needle: &[u8]) -> Option { + let (rare1i, rare2i) = ninfo.rarebytes.as_rare_ordered_u8(); + // If the needle is too short or too long, give up. Also, give up + // if the rare bytes detected are at the same position. (It likely + // suggests a degenerate case, although it should technically not be + // possible.) + if needle.len() < MIN_NEEDLE_LEN + || needle.len() > MAX_NEEDLE_LEN + || rare1i == rare2i + { + return None; + } + Some(Forward { rare1i, rare2i }) + } + + /// Returns the minimum length of haystack that is needed for this searcher + /// to work for a particular vector. Passing a haystack with a length + /// smaller than this will cause `fwd_find` to panic. + #[inline(always)] + pub(crate) fn min_haystack_len(&self) -> usize { + self.rare2i as usize + size_of::() + } +} + +/// Searches the given haystack for the given needle. The needle given should +/// be the same as the needle that this searcher was initialized with. +/// +/// # Panics +/// +/// When the given haystack has a length smaller than `min_haystack_len`. +/// +/// # Safety +/// +/// Since this is meant to be used with vector functions, callers need to +/// specialize this inside of a function with a `target_feature` attribute. +/// Therefore, callers must ensure that whatever target feature is being used +/// supports the vector functions that this function is specialized for. (For +/// the specific vector functions used, see the Vector trait implementations.) +#[inline(always)] +pub(crate) unsafe fn fwd_find( + fwd: &Forward, + haystack: &[u8], + needle: &[u8], +) -> Option { + // It would be nice if we didn't have this check here, since the meta + // searcher should handle it for us. But without this, I don't think we + // guarantee that end_ptr.sub(needle.len()) won't result in UB. We could + // put it as part of the safety contract, but it makes it more complicated + // than necessary. + if haystack.len() < needle.len() { + return None; + } + let min_haystack_len = fwd.min_haystack_len::(); + assert!(haystack.len() >= min_haystack_len, "haystack too small"); + debug_assert!(needle.len() <= haystack.len()); + debug_assert!( + needle.len() >= MIN_NEEDLE_LEN, + "needle must be at least {} bytes", + MIN_NEEDLE_LEN, + ); + debug_assert!( + needle.len() <= MAX_NEEDLE_LEN, + "needle must be at most {} bytes", + MAX_NEEDLE_LEN, + ); + + let (rare1i, rare2i) = (fwd.rare1i as usize, fwd.rare2i as usize); + let rare1chunk = V::splat(needle[rare1i]); + let rare2chunk = V::splat(needle[rare2i]); + + let start_ptr = haystack.as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); + let max_ptr = end_ptr.sub(min_haystack_len); + let mut ptr = start_ptr; + + // N.B. I did experiment with unrolling the loop to deal with size(V) + // bytes at a time and 2*size(V) bytes at a time. The double unroll was + // marginally faster while the quadruple unroll was unambiguously slower. + // In the end, I decided the complexity from unrolling wasn't worth it. I + // used the memmem/krate/prebuilt/huge-en/ benchmarks to compare. + while ptr <= max_ptr { + let m = fwd_find_in_chunk( + fwd, needle, ptr, end_ptr, rare1chunk, rare2chunk, !0, + ); + if let Some(chunki) = m { + return Some(matched(start_ptr, ptr, chunki)); + } + ptr = ptr.add(size_of::()); + } + if ptr < end_ptr { + let remaining = diff(end_ptr, ptr); + debug_assert!( + remaining < min_haystack_len, + "remaining bytes should be smaller than the minimum haystack \ + length of {}, but there are {} bytes remaining", + min_haystack_len, + remaining, + ); + if remaining < needle.len() { + return None; + } + debug_assert!( + max_ptr < ptr, + "after main loop, ptr should have exceeded max_ptr", + ); + let overlap = diff(ptr, max_ptr); + debug_assert!( + overlap > 0, + "overlap ({}) must always be non-zero", + overlap, + ); + debug_assert!( + overlap < size_of::(), + "overlap ({}) cannot possibly be >= than a vector ({})", + overlap, + size_of::(), + ); + // The mask has all of its bits set except for the first N least + // significant bits, where N=overlap. This way, any matches that + // occur in find_in_chunk within the overlap are automatically + // ignored. + let mask = !((1 << overlap) - 1); + ptr = max_ptr; + let m = fwd_find_in_chunk( + fwd, needle, ptr, end_ptr, rare1chunk, rare2chunk, mask, + ); + if let Some(chunki) = m { + return Some(matched(start_ptr, ptr, chunki)); + } + } + None +} + +/// Search for an occurrence of two rare bytes from the needle in the chunk +/// pointed to by ptr, with the end of the haystack pointed to by end_ptr. +/// +/// rare1chunk and rare2chunk correspond to vectors with the rare1 and rare2 +/// bytes repeated in each 8-bit lane, respectively. +/// +/// mask should have bits set corresponding the positions in the chunk in which +/// matches are considered. This is only used for the last vector load where +/// the beginning of the vector might have overlapped with the last load in +/// the main loop. The mask lets us avoid visiting positions that have already +/// been discarded as matches. +/// +/// # Safety +/// +/// It must be safe to do an unaligned read of size(V) bytes starting at both +/// (ptr + rare1i) and (ptr + rare2i). It must also be safe to do unaligned +/// loads on ptr up to end_ptr. +#[inline(always)] +unsafe fn fwd_find_in_chunk( + fwd: &Forward, + needle: &[u8], + ptr: *const u8, + end_ptr: *const u8, + rare1chunk: V, + rare2chunk: V, + mask: u32, +) -> Option { + let chunk0 = V::load_unaligned(ptr.add(fwd.rare1i as usize)); + let chunk1 = V::load_unaligned(ptr.add(fwd.rare2i as usize)); + + let eq0 = chunk0.cmpeq(rare1chunk); + let eq1 = chunk1.cmpeq(rare2chunk); + + let mut match_offsets = eq0.and(eq1).movemask() & mask; + while match_offsets != 0 { + let offset = match_offsets.trailing_zeros() as usize; + let ptr = ptr.add(offset); + if end_ptr.sub(needle.len()) < ptr { + return None; + } + let chunk = core::slice::from_raw_parts(ptr, needle.len()); + if memcmp(needle, chunk) { + return Some(offset); + } + match_offsets &= match_offsets - 1; + } + None +} + +/// Accepts a chunk-relative offset and returns a haystack relative offset +/// after updating the prefilter state. +/// +/// See the same function with the same name in the prefilter variant of this +/// algorithm to learned why it's tagged with inline(never). Even here, where +/// the function is simpler, inlining it leads to poorer codegen. (Although +/// it does improve some benchmarks, like prebuiltiter/huge-en/common-you.) +#[cold] +#[inline(never)] +fn matched(start_ptr: *const u8, ptr: *const u8, chunki: usize) -> usize { + diff(ptr, start_ptr) + chunki +} + +/// Subtract `b` from `a` and return the difference. `a` must be greater than +/// or equal to `b`. +fn diff(a: *const u8, b: *const u8) -> usize { + debug_assert!(a >= b); + (a as usize) - (b as usize) +} diff --git a/src/memmem/mod.rs b/src/memmem/mod.rs new file mode 100644 index 0000000..0dd6186 --- /dev/null +++ b/src/memmem/mod.rs @@ -0,0 +1,1296 @@ +/*! +This module provides forward and reverse substring search routines. + +Unlike the standard library's substring search routines, these work on +arbitrary bytes. For all non-empty needles, these routines will report exactly +the same values as the corresponding routines in the standard library. For +the empty needle, the standard library reports matches only at valid UTF-8 +boundaries, where as these routines will report matches at every position. + +Other than being able to work on arbitrary bytes, the primary reason to prefer +these routines over the standard library routines is that these will generally +be faster. In some cases, significantly so. + +# Example: iterating over substring matches + +This example shows how to use [`find_iter`] to find occurrences of a substring +in a haystack. + +``` +use memchr::memmem; + +let haystack = b"foo bar foo baz foo"; + +let mut it = memmem::find_iter(haystack, "foo"); +assert_eq!(Some(0), it.next()); +assert_eq!(Some(8), it.next()); +assert_eq!(Some(16), it.next()); +assert_eq!(None, it.next()); +``` + +# Example: iterating over substring matches in reverse + +This example shows how to use [`rfind_iter`] to find occurrences of a substring +in a haystack starting from the end of the haystack. + +**NOTE:** This module does not implement double ended iterators, so reverse +searches aren't done by calling `rev` on a forward iterator. + +``` +use memchr::memmem; + +let haystack = b"foo bar foo baz foo"; + +let mut it = memmem::rfind_iter(haystack, "foo"); +assert_eq!(Some(16), it.next()); +assert_eq!(Some(8), it.next()); +assert_eq!(Some(0), it.next()); +assert_eq!(None, it.next()); +``` + +# Example: repeating a search for the same needle + +It may be possible for the overhead of constructing a substring searcher to be +measurable in some workloads. In cases where the same needle is used to search +many haystacks, it is possible to do construction once and thus to avoid it for +subsequent searches. This can be done with a [`Finder`] (or a [`FinderRev`] for +reverse searches). + +``` +use memchr::memmem; + +let finder = memmem::Finder::new("foo"); + +assert_eq!(Some(4), finder.find(b"baz foo quux")); +assert_eq!(None, finder.find(b"quux baz bar")); +``` +*/ + +pub use self::prefilter::Prefilter; + +use crate::{ + cow::CowBytes, + memmem::{ + prefilter::{Pre, PrefilterFn, PrefilterState}, + rabinkarp::NeedleHash, + rarebytes::RareNeedleBytes, + }, +}; + +/// Defines a suite of quickcheck properties for forward and reverse +/// substring searching. +/// +/// This is defined in this specific spot so that it can be used freely among +/// the different substring search implementations. I couldn't be bothered to +/// fight with the macro-visibility rules enough to figure out how to stuff it +/// somewhere more convenient. +#[cfg(all(test, feature = "std"))] +macro_rules! define_memmem_quickcheck_tests { + ($fwd:expr, $rev:expr) => { + use crate::memmem::proptests; + + quickcheck::quickcheck! { + fn qc_fwd_prefix_is_substring(bs: Vec) -> bool { + proptests::prefix_is_substring(false, &bs, $fwd) + } + + fn qc_fwd_suffix_is_substring(bs: Vec) -> bool { + proptests::suffix_is_substring(false, &bs, $fwd) + } + + fn qc_fwd_matches_naive( + haystack: Vec, + needle: Vec + ) -> bool { + proptests::matches_naive(false, &haystack, &needle, $fwd) + } + + fn qc_rev_prefix_is_substring(bs: Vec) -> bool { + proptests::prefix_is_substring(true, &bs, $rev) + } + + fn qc_rev_suffix_is_substring(bs: Vec) -> bool { + proptests::suffix_is_substring(true, &bs, $rev) + } + + fn qc_rev_matches_naive( + haystack: Vec, + needle: Vec + ) -> bool { + proptests::matches_naive(true, &haystack, &needle, $rev) + } + } + }; +} + +/// Defines a suite of "simple" hand-written tests for a substring +/// implementation. +/// +/// This is defined here for the same reason that +/// define_memmem_quickcheck_tests is defined here. +#[cfg(test)] +macro_rules! define_memmem_simple_tests { + ($fwd:expr, $rev:expr) => { + use crate::memmem::testsimples; + + #[test] + fn simple_forward() { + testsimples::run_search_tests_fwd($fwd); + } + + #[test] + fn simple_reverse() { + testsimples::run_search_tests_rev($rev); + } + }; +} + +mod byte_frequencies; +#[cfg(all(target_arch = "x86_64", memchr_runtime_simd))] +mod genericsimd; +mod prefilter; +mod rabinkarp; +mod rarebytes; +mod twoway; +mod util; +// SIMD is only supported on x86_64 currently. +#[cfg(target_arch = "x86_64")] +mod vector; +#[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] +mod x86; + +/// Returns an iterator over all occurrences of a substring in a haystack. +/// +/// # Complexity +/// +/// This routine is guaranteed to have worst case linear time complexity +/// with respect to both the needle and the haystack. That is, this runs +/// in `O(needle.len() + haystack.len())` time. +/// +/// This routine is also guaranteed to have worst case constant space +/// complexity. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use memchr::memmem; +/// +/// let haystack = b"foo bar foo baz foo"; +/// let mut it = memmem::find_iter(haystack, b"foo"); +/// assert_eq!(Some(0), it.next()); +/// assert_eq!(Some(8), it.next()); +/// assert_eq!(Some(16), it.next()); +/// assert_eq!(None, it.next()); +/// ``` +#[inline] +pub fn find_iter<'h, 'n, N: 'n + ?Sized + AsRef<[u8]>>( + haystack: &'h [u8], + needle: &'n N, +) -> FindIter<'h, 'n> { + FindIter::new(haystack, Finder::new(needle)) +} + +/// Returns a reverse iterator over all occurrences of a substring in a +/// haystack. +/// +/// # Complexity +/// +/// This routine is guaranteed to have worst case linear time complexity +/// with respect to both the needle and the haystack. That is, this runs +/// in `O(needle.len() + haystack.len())` time. +/// +/// This routine is also guaranteed to have worst case constant space +/// complexity. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use memchr::memmem; +/// +/// let haystack = b"foo bar foo baz foo"; +/// let mut it = memmem::rfind_iter(haystack, b"foo"); +/// assert_eq!(Some(16), it.next()); +/// assert_eq!(Some(8), it.next()); +/// assert_eq!(Some(0), it.next()); +/// assert_eq!(None, it.next()); +/// ``` +#[inline] +pub fn rfind_iter<'h, 'n, N: 'n + ?Sized + AsRef<[u8]>>( + haystack: &'h [u8], + needle: &'n N, +) -> FindRevIter<'h, 'n> { + FindRevIter::new(haystack, FinderRev::new(needle)) +} + +/// Returns the index of the first occurrence of the given needle. +/// +/// Note that if you're are searching for the same needle in many different +/// small haystacks, it may be faster to initialize a [`Finder`] once, +/// and reuse it for each search. +/// +/// # Complexity +/// +/// This routine is guaranteed to have worst case linear time complexity +/// with respect to both the needle and the haystack. That is, this runs +/// in `O(needle.len() + haystack.len())` time. +/// +/// This routine is also guaranteed to have worst case constant space +/// complexity. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use memchr::memmem; +/// +/// let haystack = b"foo bar baz"; +/// assert_eq!(Some(0), memmem::find(haystack, b"foo")); +/// assert_eq!(Some(4), memmem::find(haystack, b"bar")); +/// assert_eq!(None, memmem::find(haystack, b"quux")); +/// ``` +#[inline] +pub fn find(haystack: &[u8], needle: &[u8]) -> Option { + if haystack.len() < 64 { + rabinkarp::find(haystack, needle) + } else { + Finder::new(needle).find(haystack) + } +} + +/// Returns the index of the last occurrence of the given needle. +/// +/// Note that if you're are searching for the same needle in many different +/// small haystacks, it may be faster to initialize a [`FinderRev`] once, +/// and reuse it for each search. +/// +/// # Complexity +/// +/// This routine is guaranteed to have worst case linear time complexity +/// with respect to both the needle and the haystack. That is, this runs +/// in `O(needle.len() + haystack.len())` time. +/// +/// This routine is also guaranteed to have worst case constant space +/// complexity. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use memchr::memmem; +/// +/// let haystack = b"foo bar baz"; +/// assert_eq!(Some(0), memmem::rfind(haystack, b"foo")); +/// assert_eq!(Some(4), memmem::rfind(haystack, b"bar")); +/// assert_eq!(Some(8), memmem::rfind(haystack, b"ba")); +/// assert_eq!(None, memmem::rfind(haystack, b"quux")); +/// ``` +#[inline] +pub fn rfind(haystack: &[u8], needle: &[u8]) -> Option { + if haystack.len() < 64 { + rabinkarp::rfind(haystack, needle) + } else { + FinderRev::new(needle).rfind(haystack) + } +} + +/// An iterator over non-overlapping substring matches. +/// +/// Matches are reported by the byte offset at which they begin. +/// +/// `'h` is the lifetime of the haystack while `'n` is the lifetime of the +/// needle. +#[derive(Debug)] +pub struct FindIter<'h, 'n> { + haystack: &'h [u8], + prestate: PrefilterState, + finder: Finder<'n>, + pos: usize, +} + +impl<'h, 'n> FindIter<'h, 'n> { + #[inline(always)] + pub(crate) fn new( + haystack: &'h [u8], + finder: Finder<'n>, + ) -> FindIter<'h, 'n> { + let prestate = finder.searcher.prefilter_state(); + FindIter { haystack, prestate, finder, pos: 0 } + } +} + +impl<'h, 'n> Iterator for FindIter<'h, 'n> { + type Item = usize; + + fn next(&mut self) -> Option { + if self.pos > self.haystack.len() { + return None; + } + let result = self + .finder + .searcher + .find(&mut self.prestate, &self.haystack[self.pos..]); + match result { + None => None, + Some(i) => { + let pos = self.pos + i; + self.pos = pos + core::cmp::max(1, self.finder.needle().len()); + Some(pos) + } + } + } +} + +/// An iterator over non-overlapping substring matches in reverse. +/// +/// Matches are reported by the byte offset at which they begin. +/// +/// `'h` is the lifetime of the haystack while `'n` is the lifetime of the +/// needle. +#[derive(Debug)] +pub struct FindRevIter<'h, 'n> { + haystack: &'h [u8], + finder: FinderRev<'n>, + /// When searching with an empty needle, this gets set to `None` after + /// we've yielded the last element at `0`. + pos: Option, +} + +impl<'h, 'n> FindRevIter<'h, 'n> { + #[inline(always)] + pub(crate) fn new( + haystack: &'h [u8], + finder: FinderRev<'n>, + ) -> FindRevIter<'h, 'n> { + let pos = Some(haystack.len()); + FindRevIter { haystack, finder, pos } + } +} + +impl<'h, 'n> Iterator for FindRevIter<'h, 'n> { + type Item = usize; + + fn next(&mut self) -> Option { + let pos = match self.pos { + None => return None, + Some(pos) => pos, + }; + let result = self.finder.rfind(&self.haystack[..pos]); + match result { + None => None, + Some(i) => { + if pos == i { + self.pos = pos.checked_sub(1); + } else { + self.pos = Some(i); + } + Some(i) + } + } + } +} + +/// A single substring searcher fixed to a particular needle. +/// +/// The purpose of this type is to permit callers to construct a substring +/// searcher that can be used to search haystacks without the overhead of +/// constructing the searcher in the first place. This is a somewhat niche +/// concern when it's necessary to re-use the same needle to search multiple +/// different haystacks with as little overhead as possible. In general, using +/// [`find`] is good enough, but `Finder` is useful when you can meaningfully +/// observe searcher construction time in a profile. +/// +/// When the `std` feature is enabled, then this type has an `into_owned` +/// version which permits building a `Finder` that is not connected to +/// the lifetime of its needle. +#[derive(Clone, Debug)] +pub struct Finder<'n> { + searcher: Searcher<'n>, +} + +impl<'n> Finder<'n> { + /// Create a new finder for the given needle. + #[inline] + pub fn new>(needle: &'n B) -> Finder<'n> { + FinderBuilder::new().build_forward(needle) + } + + /// Returns the index of the first occurrence of this needle in the given + /// haystack. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use memchr::memmem::Finder; + /// + /// let haystack = b"foo bar baz"; + /// assert_eq!(Some(0), Finder::new("foo").find(haystack)); + /// assert_eq!(Some(4), Finder::new("bar").find(haystack)); + /// assert_eq!(None, Finder::new("quux").find(haystack)); + /// ``` + pub fn find(&self, haystack: &[u8]) -> Option { + self.searcher.find(&mut self.searcher.prefilter_state(), haystack) + } + + /// Returns an iterator over all occurrences of a substring in a haystack. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use memchr::memmem::Finder; + /// + /// let haystack = b"foo bar foo baz foo"; + /// let finder = Finder::new(b"foo"); + /// let mut it = finder.find_iter(haystack); + /// assert_eq!(Some(0), it.next()); + /// assert_eq!(Some(8), it.next()); + /// assert_eq!(Some(16), it.next()); + /// assert_eq!(None, it.next()); + /// ``` + #[inline] + pub fn find_iter<'a, 'h>( + &'a self, + haystack: &'h [u8], + ) -> FindIter<'h, 'a> { + FindIter::new(haystack, self.as_ref()) + } + + /// Convert this finder into its owned variant, such that it no longer + /// borrows the needle. + /// + /// If this is already an owned finder, then this is a no-op. Otherwise, + /// this copies the needle. + /// + /// This is only available when the `std` feature is enabled. + #[cfg(feature = "std")] + #[inline] + pub fn into_owned(self) -> Finder<'static> { + Finder { searcher: self.searcher.into_owned() } + } + + /// Convert this finder into its borrowed variant. + /// + /// This is primarily useful if your finder is owned and you'd like to + /// store its borrowed variant in some intermediate data structure. + /// + /// Note that the lifetime parameter of the returned finder is tied to the + /// lifetime of `self`, and may be shorter than the `'n` lifetime of the + /// needle itself. Namely, a finder's needle can be either borrowed or + /// owned, so the lifetime of the needle returned must necessarily be the + /// shorter of the two. + #[inline] + pub fn as_ref(&self) -> Finder<'_> { + Finder { searcher: self.searcher.as_ref() } + } + + /// Returns the needle that this finder searches for. + /// + /// Note that the lifetime of the needle returned is tied to the lifetime + /// of the finder, and may be shorter than the `'n` lifetime. Namely, a + /// finder's needle can be either borrowed or owned, so the lifetime of the + /// needle returned must necessarily be the shorter of the two. + #[inline] + pub fn needle(&self) -> &[u8] { + self.searcher.needle() + } +} + +/// A single substring reverse searcher fixed to a particular needle. +/// +/// The purpose of this type is to permit callers to construct a substring +/// searcher that can be used to search haystacks without the overhead of +/// constructing the searcher in the first place. This is a somewhat niche +/// concern when it's necessary to re-use the same needle to search multiple +/// different haystacks with as little overhead as possible. In general, +/// using [`rfind`] is good enough, but `FinderRev` is useful when you can +/// meaningfully observe searcher construction time in a profile. +/// +/// When the `std` feature is enabled, then this type has an `into_owned` +/// version which permits building a `FinderRev` that is not connected to +/// the lifetime of its needle. +#[derive(Clone, Debug)] +pub struct FinderRev<'n> { + searcher: SearcherRev<'n>, +} + +impl<'n> FinderRev<'n> { + /// Create a new reverse finder for the given needle. + #[inline] + pub fn new>(needle: &'n B) -> FinderRev<'n> { + FinderBuilder::new().build_reverse(needle) + } + + /// Returns the index of the last occurrence of this needle in the given + /// haystack. + /// + /// The haystack may be any type that can be cheaply converted into a + /// `&[u8]`. This includes, but is not limited to, `&str` and `&[u8]`. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use memchr::memmem::FinderRev; + /// + /// let haystack = b"foo bar baz"; + /// assert_eq!(Some(0), FinderRev::new("foo").rfind(haystack)); + /// assert_eq!(Some(4), FinderRev::new("bar").rfind(haystack)); + /// assert_eq!(None, FinderRev::new("quux").rfind(haystack)); + /// ``` + pub fn rfind>(&self, haystack: B) -> Option { + self.searcher.rfind(haystack.as_ref()) + } + + /// Returns a reverse iterator over all occurrences of a substring in a + /// haystack. + /// + /// # Complexity + /// + /// This routine is guaranteed to have worst case linear time complexity + /// with respect to both the needle and the haystack. That is, this runs + /// in `O(needle.len() + haystack.len())` time. + /// + /// This routine is also guaranteed to have worst case constant space + /// complexity. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use memchr::memmem::FinderRev; + /// + /// let haystack = b"foo bar foo baz foo"; + /// let finder = FinderRev::new(b"foo"); + /// let mut it = finder.rfind_iter(haystack); + /// assert_eq!(Some(16), it.next()); + /// assert_eq!(Some(8), it.next()); + /// assert_eq!(Some(0), it.next()); + /// assert_eq!(None, it.next()); + /// ``` + #[inline] + pub fn rfind_iter<'a, 'h>( + &'a self, + haystack: &'h [u8], + ) -> FindRevIter<'h, 'a> { + FindRevIter::new(haystack, self.as_ref()) + } + + /// Convert this finder into its owned variant, such that it no longer + /// borrows the needle. + /// + /// If this is already an owned finder, then this is a no-op. Otherwise, + /// this copies the needle. + /// + /// This is only available when the `std` feature is enabled. + #[cfg(feature = "std")] + #[inline] + pub fn into_owned(self) -> FinderRev<'static> { + FinderRev { searcher: self.searcher.into_owned() } + } + + /// Convert this finder into its borrowed variant. + /// + /// This is primarily useful if your finder is owned and you'd like to + /// store its borrowed variant in some intermediate data structure. + /// + /// Note that the lifetime parameter of the returned finder is tied to the + /// lifetime of `self`, and may be shorter than the `'n` lifetime of the + /// needle itself. Namely, a finder's needle can be either borrowed or + /// owned, so the lifetime of the needle returned must necessarily be the + /// shorter of the two. + #[inline] + pub fn as_ref(&self) -> FinderRev<'_> { + FinderRev { searcher: self.searcher.as_ref() } + } + + /// Returns the needle that this finder searches for. + /// + /// Note that the lifetime of the needle returned is tied to the lifetime + /// of the finder, and may be shorter than the `'n` lifetime. Namely, a + /// finder's needle can be either borrowed or owned, so the lifetime of the + /// needle returned must necessarily be the shorter of the two. + #[inline] + pub fn needle(&self) -> &[u8] { + self.searcher.needle() + } +} + +/// A builder for constructing non-default forward or reverse memmem finders. +/// +/// A builder is primarily useful for configuring a substring searcher. +/// Currently, the only configuration exposed is the ability to disable +/// heuristic prefilters used to speed up certain searches. +#[derive(Clone, Debug, Default)] +pub struct FinderBuilder { + config: SearcherConfig, +} + +impl FinderBuilder { + /// Create a new finder builder with default settings. + pub fn new() -> FinderBuilder { + FinderBuilder::default() + } + + /// Build a forward finder using the given needle from the current + /// settings. + pub fn build_forward<'n, B: ?Sized + AsRef<[u8]>>( + &self, + needle: &'n B, + ) -> Finder<'n> { + Finder { searcher: Searcher::new(self.config, needle.as_ref()) } + } + + /// Build a reverse finder using the given needle from the current + /// settings. + pub fn build_reverse<'n, B: ?Sized + AsRef<[u8]>>( + &self, + needle: &'n B, + ) -> FinderRev<'n> { + FinderRev { searcher: SearcherRev::new(needle.as_ref()) } + } + + /// Configure the prefilter setting for the finder. + /// + /// See the documentation for [`Prefilter`] for more discussion on why + /// you might want to configure this. + pub fn prefilter(&mut self, prefilter: Prefilter) -> &mut FinderBuilder { + self.config.prefilter = prefilter; + self + } +} + +/// The internal implementation of a forward substring searcher. +/// +/// The reality is that this is a "meta" searcher. Namely, depending on a +/// variety of parameters (CPU support, target, needle size, haystack size and +/// even dynamic properties such as prefilter effectiveness), the actual +/// algorithm employed to do substring search may change. +#[derive(Clone, Debug)] +struct Searcher<'n> { + /// The actual needle we're searching for. + /// + /// A CowBytes is like a Cow<[u8]>, except in no_std environments, it is + /// specialized to a single variant (the borrowed form). + needle: CowBytes<'n>, + /// A collection of facts computed on the needle that are useful for more + /// than one substring search algorithm. + ninfo: NeedleInfo, + /// A prefilter function, if it was deemed appropriate. + /// + /// Some substring search implementations (like Two-Way) benefit greatly + /// if we can quickly find candidate starting positions for a match. + prefn: Option, + /// The actual substring implementation in use. + kind: SearcherKind, +} + +/// A collection of facts computed about a search needle. +/// +/// We group these things together because it's useful to be able to hand them +/// to prefilters or substring algorithms that want them. +#[derive(Clone, Copy, Debug)] +pub(crate) struct NeedleInfo { + /// The offsets of "rare" bytes detected in the needle. + /// + /// This is meant to be a heuristic in order to maximize the effectiveness + /// of vectorized code. Namely, vectorized code tends to focus on only + /// one or two bytes. If we pick bytes from the needle that occur + /// infrequently, then more time will be spent in the vectorized code and + /// will likely make the overall search (much) faster. + /// + /// Of course, this is only a heuristic based on a background frequency + /// distribution of bytes. But it tends to work very well in practice. + pub(crate) rarebytes: RareNeedleBytes, + /// A Rabin-Karp hash of the needle. + /// + /// This is store here instead of in a more specific Rabin-Karp search + /// since Rabin-Karp may be used even if another SearchKind corresponds + /// to some other search implementation. e.g., If measurements suggest RK + /// is faster in some cases or if a search implementation can't handle + /// particularly small haystack. (Moreover, we cannot use RK *generally*, + /// since its worst case time is multiplicative. Instead, we only use it + /// some small haystacks, where "small" is a constant.) + pub(crate) nhash: NeedleHash, +} + +/// Configuration for substring search. +#[derive(Clone, Copy, Debug, Default)] +struct SearcherConfig { + /// This permits changing the behavior of the prefilter, since it can have + /// a variable impact on performance. + prefilter: Prefilter, +} + +#[derive(Clone, Debug)] +enum SearcherKind { + /// A special case for empty needles. An empty needle always matches, even + /// in an empty haystack. + Empty, + /// This is used whenever the needle is a single byte. In this case, we + /// always use memchr. + OneByte(u8), + /// Two-Way is the generic work horse and is what provides our additive + /// linear time guarantee. In general, it's used when the needle is bigger + /// than 8 bytes or so. + TwoWay(twoway::Forward), + #[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] + GenericSIMD128(x86::sse::Forward), + #[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] + GenericSIMD256(x86::avx::Forward), +} + +impl<'n> Searcher<'n> { + #[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] + fn new(config: SearcherConfig, needle: &'n [u8]) -> Searcher<'n> { + use self::SearcherKind::*; + + let ninfo = NeedleInfo::new(needle); + let prefn = + prefilter::forward(&config.prefilter, &ninfo.rarebytes, needle); + let kind = if needle.len() == 0 { + Empty + } else if needle.len() == 1 { + OneByte(needle[0]) + } else if let Some(fwd) = x86::avx::Forward::new(&ninfo, needle) { + GenericSIMD256(fwd) + } else if let Some(fwd) = x86::sse::Forward::new(&ninfo, needle) { + GenericSIMD128(fwd) + } else { + TwoWay(twoway::Forward::new(needle)) + }; + Searcher { needle: CowBytes::new(needle), ninfo, prefn, kind } + } + + #[cfg(not(all(not(miri), target_arch = "x86_64", memchr_runtime_simd)))] + fn new(config: SearcherConfig, needle: &'n [u8]) -> Searcher<'n> { + use self::SearcherKind::*; + + let ninfo = NeedleInfo::new(needle); + let prefn = + prefilter::forward(&config.prefilter, &ninfo.rarebytes, needle); + let kind = if needle.len() == 0 { + Empty + } else if needle.len() == 1 { + OneByte(needle[0]) + } else { + TwoWay(twoway::Forward::new(needle)) + }; + Searcher { needle: CowBytes::new(needle), ninfo, prefn, kind } + } + + /// Return a fresh prefilter state that can be used with this searcher. + /// A prefilter state is used to track the effectiveness of a searcher's + /// prefilter for speeding up searches. Therefore, the prefilter state + /// should generally be reused on subsequent searches (such as in an + /// iterator). For searches on a different haystack, then a new prefilter + /// state should be used. + /// + /// This always initializes a valid (but possibly inert) prefilter state + /// even if this searcher does not have a prefilter enabled. + fn prefilter_state(&self) -> PrefilterState { + if self.prefn.is_none() { + PrefilterState::inert() + } else { + PrefilterState::new() + } + } + + fn needle(&self) -> &[u8] { + self.needle.as_slice() + } + + fn as_ref(&self) -> Searcher<'_> { + use self::SearcherKind::*; + + let kind = match self.kind { + Empty => Empty, + OneByte(b) => OneByte(b), + TwoWay(tw) => TwoWay(tw), + #[cfg(all( + not(miri), + target_arch = "x86_64", + memchr_runtime_simd + ))] + GenericSIMD128(gs) => GenericSIMD128(gs), + #[cfg(all( + not(miri), + target_arch = "x86_64", + memchr_runtime_simd + ))] + GenericSIMD256(gs) => GenericSIMD256(gs), + }; + Searcher { + needle: CowBytes::new(self.needle()), + ninfo: self.ninfo, + prefn: self.prefn, + kind, + } + } + + #[cfg(feature = "std")] + fn into_owned(self) -> Searcher<'static> { + use self::SearcherKind::*; + + let kind = match self.kind { + Empty => Empty, + OneByte(b) => OneByte(b), + TwoWay(tw) => TwoWay(tw), + #[cfg(all( + not(miri), + target_arch = "x86_64", + memchr_runtime_simd + ))] + GenericSIMD128(gs) => GenericSIMD128(gs), + #[cfg(all( + not(miri), + target_arch = "x86_64", + memchr_runtime_simd + ))] + GenericSIMD256(gs) => GenericSIMD256(gs), + }; + Searcher { + needle: self.needle.into_owned(), + ninfo: self.ninfo, + prefn: self.prefn, + kind, + } + } + + /// Implements forward substring search by selecting the implementation + /// chosen at construction and executing it on the given haystack with the + /// prefilter's current state of effectiveness. + #[inline(always)] + fn find( + &self, + state: &mut PrefilterState, + haystack: &[u8], + ) -> Option { + use self::SearcherKind::*; + + let needle = self.needle(); + if haystack.len() < needle.len() { + return None; + } + match self.kind { + Empty => Some(0), + OneByte(b) => crate::memchr(b, haystack), + TwoWay(ref tw) => { + // For very short haystacks (e.g., where the prefilter probably + // can't run), it's faster to just run RK. + if rabinkarp::is_fast(haystack, needle) { + rabinkarp::find_with(&self.ninfo.nhash, haystack, needle) + } else { + self.find_tw(tw, state, haystack, needle) + } + } + #[cfg(all( + not(miri), + target_arch = "x86_64", + memchr_runtime_simd + ))] + GenericSIMD128(ref gs) => { + // The SIMD matcher can't handle particularly short haystacks, + // so we fall back to RK in these cases. + if haystack.len() < gs.min_haystack_len() { + rabinkarp::find_with(&self.ninfo.nhash, haystack, needle) + } else { + gs.find(haystack, needle) + } + } + #[cfg(all( + not(miri), + target_arch = "x86_64", + memchr_runtime_simd + ))] + GenericSIMD256(ref gs) => { + // The SIMD matcher can't handle particularly short haystacks, + // so we fall back to RK in these cases. + if haystack.len() < gs.min_haystack_len() { + rabinkarp::find_with(&self.ninfo.nhash, haystack, needle) + } else { + gs.find(haystack, needle) + } + } + } + } + + /// Calls Two-Way on the given haystack/needle. + /// + /// This is marked as unlineable since it seems to have a better overall + /// effect on benchmarks. However, this is one of those cases where + /// inlining it results an improvement in other benchmarks too, so I + /// suspect we just don't have enough data yet to make the right call here. + /// + /// I suspect the main problem is that this function contains two different + /// inlined copies of Two-Way: one with and one without prefilters enabled. + #[inline(never)] + fn find_tw( + &self, + tw: &twoway::Forward, + state: &mut PrefilterState, + haystack: &[u8], + needle: &[u8], + ) -> Option { + if let Some(prefn) = self.prefn { + // We used to look at the length of a haystack here. That is, if + // it was too small, then don't bother with the prefilter. But two + // things changed: the prefilter falls back to memchr for small + // haystacks, and, above, Rabin-Karp is employed for tiny haystacks + // anyway. + if state.is_effective() { + let mut pre = Pre { state, prefn, ninfo: &self.ninfo }; + return tw.find(Some(&mut pre), haystack, needle); + } + } + tw.find(None, haystack, needle) + } +} + +impl NeedleInfo { + pub(crate) fn new(needle: &[u8]) -> NeedleInfo { + NeedleInfo { + rarebytes: RareNeedleBytes::forward(needle), + nhash: NeedleHash::forward(needle), + } + } +} + +/// The internal implementation of a reverse substring searcher. +/// +/// See the forward searcher docs for more details. Currently, the reverse +/// searcher is considerably simpler since it lacks prefilter support. This +/// was done because it adds a lot of code, and more surface area to test. And +/// in particular, it's not clear whether a prefilter on reverse searching is +/// worth it. (If you have a compelling use case, please file an issue!) +#[derive(Clone, Debug)] +struct SearcherRev<'n> { + /// The actual needle we're searching for. + needle: CowBytes<'n>, + /// A Rabin-Karp hash of the needle. + nhash: NeedleHash, + /// The actual substring implementation in use. + kind: SearcherRevKind, +} + +#[derive(Clone, Debug)] +enum SearcherRevKind { + /// A special case for empty needles. An empty needle always matches, even + /// in an empty haystack. + Empty, + /// This is used whenever the needle is a single byte. In this case, we + /// always use memchr. + OneByte(u8), + /// Two-Way is the generic work horse and is what provides our additive + /// linear time guarantee. In general, it's used when the needle is bigger + /// than 8 bytes or so. + TwoWay(twoway::Reverse), +} + +impl<'n> SearcherRev<'n> { + fn new(needle: &'n [u8]) -> SearcherRev<'n> { + use self::SearcherRevKind::*; + + let kind = if needle.len() == 0 { + Empty + } else if needle.len() == 1 { + OneByte(needle[0]) + } else { + TwoWay(twoway::Reverse::new(needle)) + }; + SearcherRev { + needle: CowBytes::new(needle), + nhash: NeedleHash::reverse(needle), + kind, + } + } + + fn needle(&self) -> &[u8] { + self.needle.as_slice() + } + + fn as_ref(&self) -> SearcherRev<'_> { + use self::SearcherRevKind::*; + + let kind = match self.kind { + Empty => Empty, + OneByte(b) => OneByte(b), + TwoWay(tw) => TwoWay(tw), + }; + SearcherRev { + needle: CowBytes::new(self.needle()), + nhash: self.nhash, + kind, + } + } + + #[cfg(feature = "std")] + fn into_owned(self) -> SearcherRev<'static> { + use self::SearcherRevKind::*; + + let kind = match self.kind { + Empty => Empty, + OneByte(b) => OneByte(b), + TwoWay(tw) => TwoWay(tw), + }; + SearcherRev { + needle: self.needle.into_owned(), + nhash: self.nhash, + kind, + } + } + + /// Implements reverse substring search by selecting the implementation + /// chosen at construction and executing it on the given haystack with the + /// prefilter's current state of effectiveness. + #[inline(always)] + fn rfind(&self, haystack: &[u8]) -> Option { + use self::SearcherRevKind::*; + + let needle = self.needle(); + if haystack.len() < needle.len() { + return None; + } + match self.kind { + Empty => Some(haystack.len()), + OneByte(b) => crate::memrchr(b, haystack), + TwoWay(ref tw) => { + // For very short haystacks (e.g., where the prefilter probably + // can't run), it's faster to just run RK. + if rabinkarp::is_fast(haystack, needle) { + rabinkarp::rfind_with(&self.nhash, haystack, needle) + } else { + tw.rfind(haystack, needle) + } + } + } + } +} + +/// This module defines some generic quickcheck properties useful for testing +/// any substring search algorithm. It also runs those properties for the +/// top-level public API memmem routines. (The properties are also used to +/// test various substring search implementations more granularly elsewhere as +/// well.) +#[cfg(all(test, feature = "std", not(miri)))] +mod proptests { + // N.B. This defines the quickcheck tests using the properties defined + // below. Because of macro-visibility weirdness, the actual macro is + // defined at the top of this file. + define_memmem_quickcheck_tests!(super::find, super::rfind); + + /// Check that every prefix of the given byte string is a substring. + pub(crate) fn prefix_is_substring( + reverse: bool, + bs: &[u8], + mut search: impl FnMut(&[u8], &[u8]) -> Option, + ) -> bool { + if bs.is_empty() { + return true; + } + for i in 0..(bs.len() - 1) { + let prefix = &bs[..i]; + if reverse { + assert_eq!(naive_rfind(bs, prefix), search(bs, prefix)); + } else { + assert_eq!(naive_find(bs, prefix), search(bs, prefix)); + } + } + true + } + + /// Check that every suffix of the given byte string is a substring. + pub(crate) fn suffix_is_substring( + reverse: bool, + bs: &[u8], + mut search: impl FnMut(&[u8], &[u8]) -> Option, + ) -> bool { + if bs.is_empty() { + return true; + } + for i in 0..(bs.len() - 1) { + let suffix = &bs[i..]; + if reverse { + assert_eq!(naive_rfind(bs, suffix), search(bs, suffix)); + } else { + assert_eq!(naive_find(bs, suffix), search(bs, suffix)); + } + } + true + } + + /// Check that naive substring search matches the result of the given search + /// algorithm. + pub(crate) fn matches_naive( + reverse: bool, + haystack: &[u8], + needle: &[u8], + mut search: impl FnMut(&[u8], &[u8]) -> Option, + ) -> bool { + if reverse { + naive_rfind(haystack, needle) == search(haystack, needle) + } else { + naive_find(haystack, needle) == search(haystack, needle) + } + } + + /// Naively search forwards for the given needle in the given haystack. + fn naive_find(haystack: &[u8], needle: &[u8]) -> Option { + if needle.is_empty() { + return Some(0); + } else if haystack.len() < needle.len() { + return None; + } + for i in 0..(haystack.len() - needle.len() + 1) { + if needle == &haystack[i..i + needle.len()] { + return Some(i); + } + } + None + } + + /// Naively search in reverse for the given needle in the given haystack. + fn naive_rfind(haystack: &[u8], needle: &[u8]) -> Option { + if needle.is_empty() { + return Some(haystack.len()); + } else if haystack.len() < needle.len() { + return None; + } + for i in (0..(haystack.len() - needle.len() + 1)).rev() { + if needle == &haystack[i..i + needle.len()] { + return Some(i); + } + } + None + } +} + +/// This module defines some hand-written "simple" substring tests. It +/// also provides routines for easily running them on any substring search +/// implementation. +#[cfg(test)] +mod testsimples { + define_memmem_simple_tests!(super::find, super::rfind); + + /// Each test is a (needle, haystack, expected_fwd, expected_rev) tuple. + type SearchTest = + (&'static str, &'static str, Option, Option); + + const SEARCH_TESTS: &'static [SearchTest] = &[ + ("", "", Some(0), Some(0)), + ("", "a", Some(0), Some(1)), + ("", "ab", Some(0), Some(2)), + ("", "abc", Some(0), Some(3)), + ("a", "", None, None), + ("a", "a", Some(0), Some(0)), + ("a", "aa", Some(0), Some(1)), + ("a", "ba", Some(1), Some(1)), + ("a", "bba", Some(2), Some(2)), + ("a", "bbba", Some(3), Some(3)), + ("a", "bbbab", Some(3), Some(3)), + ("a", "bbbabb", Some(3), Some(3)), + ("a", "bbbabbb", Some(3), Some(3)), + ("a", "bbbbbb", None, None), + ("ab", "", None, None), + ("ab", "a", None, None), + ("ab", "b", None, None), + ("ab", "ab", Some(0), Some(0)), + ("ab", "aab", Some(1), Some(1)), + ("ab", "aaab", Some(2), Some(2)), + ("ab", "abaab", Some(0), Some(3)), + ("ab", "baaab", Some(3), Some(3)), + ("ab", "acb", None, None), + ("ab", "abba", Some(0), Some(0)), + ("abc", "ab", None, None), + ("abc", "abc", Some(0), Some(0)), + ("abc", "abcz", Some(0), Some(0)), + ("abc", "abczz", Some(0), Some(0)), + ("abc", "zabc", Some(1), Some(1)), + ("abc", "zzabc", Some(2), Some(2)), + ("abc", "azbc", None, None), + ("abc", "abzc", None, None), + ("abczdef", "abczdefzzzzzzzzzzzzzzzzzzzz", Some(0), Some(0)), + ("abczdef", "zzzzzzzzzzzzzzzzzzzzabczdef", Some(20), Some(20)), + ("xyz", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxyz", Some(32), Some(32)), + // Failures caught by quickcheck. + ("\u{0}\u{15}", "\u{0}\u{15}\u{15}\u{0}", Some(0), Some(0)), + ("\u{0}\u{1e}", "\u{1e}\u{0}", None, None), + ]; + + /// Run the substring search tests. `search` should be a closure that + /// accepts a haystack and a needle and returns the starting position + /// of the first occurrence of needle in the haystack, or `None` if one + /// doesn't exist. + pub(crate) fn run_search_tests_fwd( + mut search: impl FnMut(&[u8], &[u8]) -> Option, + ) { + for &(needle, haystack, expected_fwd, _) in SEARCH_TESTS { + let (n, h) = (needle.as_bytes(), haystack.as_bytes()); + assert_eq!( + expected_fwd, + search(h, n), + "needle: {:?}, haystack: {:?}, expected: {:?}", + n, + h, + expected_fwd + ); + } + } + + /// Run the substring search tests. `search` should be a closure that + /// accepts a haystack and a needle and returns the starting position of + /// the last occurrence of needle in the haystack, or `None` if one doesn't + /// exist. + pub(crate) fn run_search_tests_rev( + mut search: impl FnMut(&[u8], &[u8]) -> Option, + ) { + for &(needle, haystack, _, expected_rev) in SEARCH_TESTS { + let (n, h) = (needle.as_bytes(), haystack.as_bytes()); + assert_eq!( + expected_rev, + search(h, n), + "needle: {:?}, haystack: {:?}, expected: {:?}", + n, + h, + expected_rev + ); + } + } +} diff --git a/src/memmem/prefilter/fallback.rs b/src/memmem/prefilter/fallback.rs new file mode 100644 index 0000000..8ae1f4e --- /dev/null +++ b/src/memmem/prefilter/fallback.rs @@ -0,0 +1,122 @@ +/* +This module implements a "fallback" prefilter that only relies on memchr to +function. While memchr works best when it's explicitly vectorized, its +fallback implementations are fast enough to make a prefilter like this +worthwhile. + +The essence of this implementation is to identify two rare bytes in a needle +based on a background frequency distribution of bytes. We then run memchr on the +rarer byte. For each match, we use the second rare byte as a guard to quickly +check if a match is possible. If the position passes the guard test, then we do +a naive memcmp to confirm the match. + +In practice, this formulation works amazingly well, primarily because of the +heuristic use of a background frequency distribution. However, it does have a +number of weaknesses where it can get quite slow when its background frequency +distribution doesn't line up with the haystack being searched. This is why we +have specialized vector routines that essentially take this idea and move the +guard check into vectorized code. (Those specialized vector routines do still +make use of the background frequency distribution of bytes though.) + +This fallback implementation was originally formulated in regex many moons ago: +https://github.com/rust-lang/regex/blob/3db8722d0b204a85380fe2a65e13d7065d7dd968/src/literal/imp.rs#L370-L501 +Prior to that, I'm not aware of anyone using this technique in any prominant +substring search implementation. Although, I'm sure folks have had this same +insight long before me. + +Another version of this also appeared in bstr: +https://github.com/BurntSushi/bstr/blob/a444256ca7407fe180ee32534688549655b7a38e/src/search/prefilter.rs#L83-L340 +*/ + +use crate::memmem::{ + prefilter::{PrefilterFnTy, PrefilterState}, + NeedleInfo, +}; + +// Check that the functions below satisfy the Prefilter function type. +const _: PrefilterFnTy = find; + +/// Look for a possible occurrence of needle. The position returned +/// corresponds to the beginning of the occurrence, if one exists. +/// +/// Callers may assume that this never returns false negatives (i.e., it +/// never misses an actual occurrence), but must check that the returned +/// position corresponds to a match. That is, it can return false +/// positives. +/// +/// This should only be used when Freqy is constructed for forward +/// searching. +pub(crate) fn find( + prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], +) -> Option { + let mut i = 0; + let (rare1i, rare2i) = ninfo.rarebytes.as_rare_usize(); + let (rare1, rare2) = ninfo.rarebytes.as_rare_bytes(needle); + while prestate.is_effective() { + // Use a fast vectorized implementation to skip to the next + // occurrence of the rarest byte (heuristically chosen) in the + // needle. + let found = crate::memchr(rare1, &haystack[i..])?; + prestate.update(found); + i += found; + + // If we can't align our first match with the haystack, then a + // match is impossible. + if i < rare1i { + i += 1; + continue; + } + + // Align our rare2 byte with the haystack. A mismatch means that + // a match is impossible. + let aligned_rare2i = i - rare1i + rare2i; + if haystack.get(aligned_rare2i) != Some(&rare2) { + i += 1; + continue; + } + + // We've done what we can. There might be a match here. + return Some(i - rare1i); + } + // The only way we get here is if we believe our skipping heuristic + // has become ineffective. We're allowed to return false positives, + // so return the position at which we advanced to, aligned to the + // haystack. + Some(i.saturating_sub(rare1i)) +} + +#[cfg(all(test, feature = "std"))] +mod tests { + use super::*; + + fn freqy_find(haystack: &[u8], needle: &[u8]) -> Option { + let ninfo = NeedleInfo::new(needle); + let mut prestate = PrefilterState::new(); + find(&mut prestate, &ninfo, haystack, needle) + } + + #[test] + fn freqy_forward() { + assert_eq!(Some(0), freqy_find(b"BARFOO", b"BAR")); + assert_eq!(Some(3), freqy_find(b"FOOBAR", b"BAR")); + assert_eq!(Some(0), freqy_find(b"zyzz", b"zyzy")); + assert_eq!(Some(2), freqy_find(b"zzzy", b"zyzy")); + assert_eq!(None, freqy_find(b"zazb", b"zyzy")); + assert_eq!(Some(0), freqy_find(b"yzyy", b"yzyz")); + assert_eq!(Some(2), freqy_find(b"yyyz", b"yzyz")); + assert_eq!(None, freqy_find(b"yayb", b"yzyz")); + } + + #[test] + #[cfg(not(miri))] + fn prefilter_permutations() { + use crate::memmem::prefilter::tests::PrefilterTest; + + // SAFETY: super::find is safe to call for all inputs and on all + // platforms. + unsafe { PrefilterTest::run_all_tests(super::find) }; + } +} diff --git a/src/memmem/prefilter/genericsimd.rs b/src/memmem/prefilter/genericsimd.rs new file mode 100644 index 0000000..1a6e387 --- /dev/null +++ b/src/memmem/prefilter/genericsimd.rs @@ -0,0 +1,207 @@ +use core::mem::size_of; + +use crate::memmem::{ + prefilter::{PrefilterFnTy, PrefilterState}, + vector::Vector, + NeedleInfo, +}; + +/// The implementation of the forward vector accelerated candidate finder. +/// +/// This is inspired by the "generic SIMD" algorithm described here: +/// http://0x80.pl/articles/simd-strfind.html#algorithm-1-generic-simd +/// +/// The main difference is that this is just a prefilter. That is, it reports +/// candidates once they are seen and doesn't attempt to confirm them. Also, +/// the bytes this routine uses to check for candidates are selected based on +/// an a priori background frequency distribution. This means that on most +/// haystacks, this will on average spend more time in vectorized code than you +/// would if you just selected the first and last bytes of the needle. +/// +/// Note that a non-prefilter variant of this algorithm can be found in the +/// parent module, but it only works on smaller needles. +/// +/// `prestate`, `ninfo`, `haystack` and `needle` are the four prefilter +/// function parameters. `fallback` is a prefilter that is used if the haystack +/// is too small to be handled with the given vector size. +/// +/// This routine is not safe because it is intended for callers to specialize +/// this with a particular vector (e.g., __m256i) and then call it with the +/// relevant target feature (e.g., avx2) enabled. +/// +/// # Panics +/// +/// If `needle.len() <= 1`, then this panics. +/// +/// # Safety +/// +/// Since this is meant to be used with vector functions, callers need to +/// specialize this inside of a function with a `target_feature` attribute. +/// Therefore, callers must ensure that whatever target feature is being used +/// supports the vector functions that this function is specialized for. (For +/// the specific vector functions used, see the Vector trait implementations.) +#[inline(always)] +pub(crate) unsafe fn find( + prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], + fallback: PrefilterFnTy, +) -> Option { + assert!(needle.len() >= 2, "needle must be at least 2 bytes"); + let (rare1i, rare2i) = ninfo.rarebytes.as_rare_ordered_usize(); + let min_haystack_len = rare2i + size_of::(); + if haystack.len() < min_haystack_len { + return fallback(prestate, ninfo, haystack, needle); + } + + let start_ptr = haystack.as_ptr(); + let end_ptr = start_ptr.add(haystack.len()); + let max_ptr = end_ptr.sub(min_haystack_len); + let mut ptr = start_ptr; + + let rare1chunk = V::splat(needle[rare1i]); + let rare2chunk = V::splat(needle[rare2i]); + + // N.B. I did experiment with unrolling the loop to deal with size(V) + // bytes at a time and 2*size(V) bytes at a time. The double unroll + // was marginally faster while the quadruple unroll was unambiguously + // slower. In the end, I decided the complexity from unrolling wasn't + // worth it. I used the memmem/krate/prebuilt/huge-en/ benchmarks to + // compare. + while ptr <= max_ptr { + let m = find_in_chunk2(ptr, rare1i, rare2i, rare1chunk, rare2chunk); + if let Some(chunki) = m { + return Some(matched(prestate, start_ptr, ptr, chunki)); + } + ptr = ptr.add(size_of::()); + } + if ptr < end_ptr { + // This routine immediately quits if a candidate match is found. + // That means that if we're here, no candidate matches have been + // found at or before 'ptr'. Thus, we don't need to mask anything + // out even though we might technically search part of the haystack + // that we've already searched (because we know it can't match). + ptr = max_ptr; + let m = find_in_chunk2(ptr, rare1i, rare2i, rare1chunk, rare2chunk); + if let Some(chunki) = m { + return Some(matched(prestate, start_ptr, ptr, chunki)); + } + } + prestate.update(haystack.len()); + None +} + +// Below are two different techniques for checking whether a candidate +// match exists in a given chunk or not. find_in_chunk2 checks two bytes +// where as find_in_chunk3 checks three bytes. The idea behind checking +// three bytes is that while we do a bit more work per iteration, we +// decrease the chances of a false positive match being reported and thus +// make the search faster overall. This actually works out for the +// memmem/krate/prebuilt/huge-en/never-all-common-bytes benchmark, where +// using find_in_chunk3 is about 25% faster than find_in_chunk2. However, +// it turns out that find_in_chunk2 is faster for all other benchmarks, so +// perhaps the extra check isn't worth it in practice. +// +// For now, we go with find_in_chunk2, but we leave find_in_chunk3 around +// to make it easy to switch to and benchmark when possible. + +/// Search for an occurrence of two rare bytes from the needle in the current +/// chunk pointed to by ptr. +/// +/// rare1chunk and rare2chunk correspond to vectors with the rare1 and rare2 +/// bytes repeated in each 8-bit lane, respectively. +/// +/// # Safety +/// +/// It must be safe to do an unaligned read of size(V) bytes starting at both +/// (ptr + rare1i) and (ptr + rare2i). +#[inline(always)] +unsafe fn find_in_chunk2( + ptr: *const u8, + rare1i: usize, + rare2i: usize, + rare1chunk: V, + rare2chunk: V, +) -> Option { + let chunk0 = V::load_unaligned(ptr.add(rare1i)); + let chunk1 = V::load_unaligned(ptr.add(rare2i)); + + let eq0 = chunk0.cmpeq(rare1chunk); + let eq1 = chunk1.cmpeq(rare2chunk); + + let match_offsets = eq0.and(eq1).movemask(); + if match_offsets == 0 { + return None; + } + Some(match_offsets.trailing_zeros() as usize) +} + +/// Search for an occurrence of two rare bytes and the first byte (even if one +/// of the rare bytes is equivalent to the first byte) from the needle in the +/// current chunk pointed to by ptr. +/// +/// firstchunk, rare1chunk and rare2chunk correspond to vectors with the first, +/// rare1 and rare2 bytes repeated in each 8-bit lane, respectively. +/// +/// # Safety +/// +/// It must be safe to do an unaligned read of size(V) bytes starting at ptr, +/// (ptr + rare1i) and (ptr + rare2i). +#[allow(dead_code)] +#[inline(always)] +unsafe fn find_in_chunk3( + ptr: *const u8, + rare1i: usize, + rare2i: usize, + firstchunk: V, + rare1chunk: V, + rare2chunk: V, +) -> Option { + let chunk0 = V::load_unaligned(ptr); + let chunk1 = V::load_unaligned(ptr.add(rare1i)); + let chunk2 = V::load_unaligned(ptr.add(rare2i)); + + let eq0 = chunk0.cmpeq(firstchunk); + let eq1 = chunk1.cmpeq(rare1chunk); + let eq2 = chunk2.cmpeq(rare2chunk); + + let match_offsets = eq0.and(eq1).and(eq2).movemask(); + if match_offsets == 0 { + return None; + } + Some(match_offsets.trailing_zeros() as usize) +} + +/// Accepts a chunk-relative offset and returns a haystack relative offset +/// after updating the prefilter state. +/// +/// Why do we use this unlineable function when a search completes? Well, +/// I don't know. Really. Obviously this function was not here initially. +/// When doing profiling, the codegen for the inner loop here looked bad and +/// I didn't know why. There were a couple extra 'add' instructions and an +/// extra 'lea' instruction that I couldn't explain. I hypothesized that the +/// optimizer was having trouble untangling the hot code in the loop from the +/// code that deals with a candidate match. By putting the latter into an +/// unlineable function, it kind of forces the issue and it had the intended +/// effect: codegen improved measurably. It's good for a ~10% improvement +/// across the board on the memmem/krate/prebuilt/huge-en/ benchmarks. +#[cold] +#[inline(never)] +fn matched( + prestate: &mut PrefilterState, + start_ptr: *const u8, + ptr: *const u8, + chunki: usize, +) -> usize { + let found = diff(ptr, start_ptr) + chunki; + prestate.update(found); + found +} + +/// Subtract `b` from `a` and return the difference. `a` must be greater than +/// or equal to `b`. +fn diff(a: *const u8, b: *const u8) -> usize { + debug_assert!(a >= b); + (a as usize) - (b as usize) +} diff --git a/src/memmem/prefilter/mod.rs b/src/memmem/prefilter/mod.rs new file mode 100644 index 0000000..2481cfe --- /dev/null +++ b/src/memmem/prefilter/mod.rs @@ -0,0 +1,562 @@ +use crate::memmem::{rarebytes::RareNeedleBytes, NeedleInfo}; + +mod fallback; +#[cfg(all(target_arch = "x86_64", memchr_runtime_simd))] +mod genericsimd; +#[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] +mod x86; + +/// The maximum frequency rank permitted for the fallback prefilter. If the +/// rarest byte in the needle has a frequency rank above this value, then no +/// prefilter is used if the fallback prefilter would otherwise be selected. +const MAX_FALLBACK_RANK: usize = 250; + +/// A combination of prefilter effectiveness state, the prefilter function and +/// the needle info required to run a prefilter. +/// +/// For the most part, these are grouped into a single type for convenience, +/// instead of needing to pass around all three as distinct function +/// parameters. +pub(crate) struct Pre<'a> { + /// State that tracks the effectivess of a prefilter. + pub(crate) state: &'a mut PrefilterState, + /// The actual prefilter function. + pub(crate) prefn: PrefilterFn, + /// Information about a needle, such as its RK hash and rare byte offsets. + pub(crate) ninfo: &'a NeedleInfo, +} + +impl<'a> Pre<'a> { + /// Call this prefilter on the given haystack with the given needle. + #[inline(always)] + pub(crate) fn call( + &mut self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + self.prefn.call(self.state, self.ninfo, haystack, needle) + } + + /// Return true if and only if this prefilter should be used. + #[inline(always)] + pub(crate) fn should_call(&mut self) -> bool { + self.state.is_effective() + } +} + +/// A prefilter function. +/// +/// A prefilter function describes both forward and reverse searches. +/// (Although, we don't currently implement prefilters for reverse searching.) +/// In the case of a forward search, the position returned corresponds to +/// the starting offset of a match (confirmed or possible). Its minimum +/// value is `0`, and its maximum value is `haystack.len() - 1`. In the case +/// of a reverse search, the position returned corresponds to the position +/// immediately after a match (confirmed or possible). Its minimum value is `1` +/// and its maximum value is `haystack.len()`. +/// +/// In both cases, the position returned is the starting (or ending) point of a +/// _possible_ match. That is, returning a false positive is okay. A prefilter, +/// however, must never return any false negatives. That is, if a match exists +/// at a particular position `i`, then a prefilter _must_ return that position. +/// It cannot skip past it. +/// +/// # Safety +/// +/// A prefilter function is not safe to create, since not all prefilters are +/// safe to call in all contexts. (e.g., A prefilter that uses AVX instructions +/// may only be called on x86_64 CPUs with the relevant AVX feature enabled.) +/// Thus, callers must ensure that when a prefilter function is created that it +/// is safe to call for the current environment. +#[derive(Clone, Copy)] +pub(crate) struct PrefilterFn(PrefilterFnTy); + +/// The type of a prefilter function. All prefilters must satisfy this +/// signature. +/// +/// Using a function pointer like this does inhibit inlining, but it does +/// eliminate branching and the extra costs associated with copying a larger +/// enum. Note also, that using Box can't really work +/// here, since we want to work in contexts that don't have dynamic memory +/// allocation. Moreover, in the default configuration of this crate on x86_64 +/// CPUs released in the past ~decade, we will use an AVX2-optimized prefilter, +/// which generally won't be inlineable into the surrounding code anyway. +/// (Unless AVX2 is enabled at compile time, but this is typically rare, since +/// it produces a non-portable binary.) +pub(crate) type PrefilterFnTy = unsafe fn( + prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], +) -> Option; + +impl PrefilterFn { + /// Create a new prefilter function from the function pointer given. + /// + /// # Safety + /// + /// Callers must ensure that the given prefilter function is safe to call + /// for all inputs in the current environment. For example, if the given + /// prefilter function uses AVX instructions, then the caller must ensure + /// that the appropriate AVX CPU features are enabled. + pub(crate) unsafe fn new(prefn: PrefilterFnTy) -> PrefilterFn { + PrefilterFn(prefn) + } + + /// Call the underlying prefilter function with the given arguments. + pub fn call( + self, + prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], + ) -> Option { + // SAFETY: Callers have the burden of ensuring that a prefilter + // function is safe to call for all inputs in the current environment. + unsafe { (self.0)(prestate, ninfo, haystack, needle) } + } +} + +impl core::fmt::Debug for PrefilterFn { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + "".fmt(f) + } +} + +/// Prefilter controls whether heuristics are used to accelerate searching. +/// +/// A prefilter refers to the idea of detecting candidate matches very quickly, +/// and then confirming whether those candidates are full matches. This +/// idea can be quite effective since it's often the case that looking for +/// candidates can be a lot faster than running a complete substring search +/// over the entire input. Namely, looking for candidates can be done with +/// extremely fast vectorized code. +/// +/// The downside of a prefilter is that it assumes false positives (which are +/// candidates generated by a prefilter that aren't matches) are somewhat rare +/// relative to the frequency of full matches. That is, if a lot of false +/// positives are generated, then it's possible for search time to be worse +/// than if the prefilter wasn't enabled in the first place. +/// +/// Another downside of a prefilter is that it can result in highly variable +/// performance, where some cases are extraordinarily fast and others aren't. +/// Typically, variable performance isn't a problem, but it may be for your use +/// case. +/// +/// The use of prefilters in this implementation does use a heuristic to detect +/// when a prefilter might not be carrying its weight, and will dynamically +/// disable its use. Nevertheless, this configuration option gives callers +/// the ability to disable pefilters if you have knowledge that they won't be +/// useful. +#[derive(Clone, Copy, Debug)] +#[non_exhaustive] +pub enum Prefilter { + /// Never used a prefilter in substring search. + None, + /// Automatically detect whether a heuristic prefilter should be used. If + /// it is used, then heuristics will be used to dynamically disable the + /// prefilter if it is believed to not be carrying its weight. + Auto, +} + +impl Default for Prefilter { + fn default() -> Prefilter { + Prefilter::Auto + } +} + +impl Prefilter { + pub(crate) fn is_none(&self) -> bool { + match *self { + Prefilter::None => true, + _ => false, + } + } +} + +/// PrefilterState tracks state associated with the effectiveness of a +/// prefilter. It is used to track how many bytes, on average, are skipped by +/// the prefilter. If this average dips below a certain threshold over time, +/// then the state renders the prefilter inert and stops using it. +/// +/// A prefilter state should be created for each search. (Where creating an +/// iterator is treated as a single search.) A prefilter state should only be +/// created from a `Freqy`. e.g., An inert `Freqy` will produce an inert +/// `PrefilterState`. +#[derive(Clone, Debug)] +pub(crate) struct PrefilterState { + /// The number of skips that has been executed. This is always 1 greater + /// than the actual number of skips. The special sentinel value of 0 + /// indicates that the prefilter is inert. This is useful to avoid + /// additional checks to determine whether the prefilter is still + /// "effective." Once a prefilter becomes inert, it should no longer be + /// used (according to our heuristics). + skips: u32, + /// The total number of bytes that have been skipped. + skipped: u32, +} + +impl PrefilterState { + /// The minimum number of skip attempts to try before considering whether + /// a prefilter is effective or not. + const MIN_SKIPS: u32 = 50; + + /// The minimum amount of bytes that skipping must average. + /// + /// This value was chosen based on varying it and checking + /// the microbenchmarks. In particular, this can impact the + /// pathological/repeated-{huge,small} benchmarks quite a bit if it's set + /// too low. + const MIN_SKIP_BYTES: u32 = 8; + + /// Create a fresh prefilter state. + pub(crate) fn new() -> PrefilterState { + PrefilterState { skips: 1, skipped: 0 } + } + + /// Create a fresh prefilter state that is always inert. + pub(crate) fn inert() -> PrefilterState { + PrefilterState { skips: 0, skipped: 0 } + } + + /// Update this state with the number of bytes skipped on the last + /// invocation of the prefilter. + #[inline] + pub(crate) fn update(&mut self, skipped: usize) { + self.skips = self.skips.saturating_add(1); + // We need to do this dance since it's technically possible for + // `skipped` to overflow a `u32`. (And we use a `u32` to reduce the + // size of a prefilter state.) + if skipped > core::u32::MAX as usize { + self.skipped = core::u32::MAX; + } else { + self.skipped = self.skipped.saturating_add(skipped as u32); + } + } + + /// Return true if and only if this state indicates that a prefilter is + /// still effective. + #[inline] + pub(crate) fn is_effective(&mut self) -> bool { + if self.is_inert() { + return false; + } + if self.skips() < PrefilterState::MIN_SKIPS { + return true; + } + if self.skipped >= PrefilterState::MIN_SKIP_BYTES * self.skips() { + return true; + } + + // We're inert. + self.skips = 0; + false + } + + #[inline] + fn is_inert(&self) -> bool { + self.skips == 0 + } + + #[inline] + fn skips(&self) -> u32 { + self.skips.saturating_sub(1) + } +} + +/// Determine which prefilter function, if any, to use. +/// +/// This only applies to x86_64 when runtime SIMD detection is enabled (which +/// is the default). In general, we try to use an AVX prefilter, followed by +/// SSE and then followed by a generic one based on memchr. +#[cfg(all(not(miri), target_arch = "x86_64", memchr_runtime_simd))] +#[inline(always)] +pub(crate) fn forward( + config: &Prefilter, + rare: &RareNeedleBytes, + needle: &[u8], +) -> Option { + if config.is_none() || needle.len() <= 1 { + return None; + } + + #[cfg(feature = "std")] + { + if cfg!(memchr_runtime_avx) { + if is_x86_feature_detected!("avx2") { + // SAFETY: x86::avx::find only requires the avx2 feature, + // which we've just checked above. + return unsafe { Some(PrefilterFn::new(x86::avx::find)) }; + } + } + } + if cfg!(memchr_runtime_sse2) { + // SAFETY: x86::sse::find only requires the sse2 feature, which is + // guaranteed to be available on x86_64. + return unsafe { Some(PrefilterFn::new(x86::sse::find)) }; + } + // Check that our rarest byte has a reasonably low rank. The main issue + // here is that the fallback prefilter can perform pretty poorly if it's + // given common bytes. So we try to avoid the worst cases here. + let (rare1_rank, _) = rare.as_ranks(needle); + if rare1_rank <= MAX_FALLBACK_RANK { + // SAFETY: fallback::find is safe to call in all environments. + return unsafe { Some(PrefilterFn::new(fallback::find)) }; + } + None +} + +/// Determine which prefilter function, if any, to use. +/// +/// Since SIMD is currently only supported on x86_64, this will just select +/// the fallback prefilter if the rare bytes provided have a low enough rank. +#[cfg(not(all(not(miri), target_arch = "x86_64", memchr_runtime_simd)))] +#[inline(always)] +pub(crate) fn forward( + config: &Prefilter, + rare: &RareNeedleBytes, + needle: &[u8], +) -> Option { + if config.is_none() || needle.len() <= 1 { + return None; + } + let (rare1_rank, _) = rare.as_ranks(needle); + if rare1_rank <= MAX_FALLBACK_RANK { + // SAFETY: fallback::find is safe to call in all environments. + return unsafe { Some(PrefilterFn::new(fallback::find)) }; + } + None +} + +/// Return the minimum length of the haystack in which a prefilter should be +/// used. If the haystack is below this length, then it's probably not worth +/// the overhead of running the prefilter. +/// +/// We used to look at the length of a haystack here. That is, if it was too +/// small, then don't bother with the prefilter. But two things changed: +/// the prefilter falls back to memchr for small haystacks, and, at the +/// meta-searcher level, Rabin-Karp is employed for tiny haystacks anyway. +/// +/// We keep it around for now in case we want to bring it back. +#[allow(dead_code)] +pub(crate) fn minimum_len(_haystack: &[u8], needle: &[u8]) -> usize { + // If the haystack length isn't greater than needle.len() * FACTOR, then + // no prefilter will be used. The presumption here is that since there + // are so few bytes to check, it's not worth running the prefilter since + // there will need to be a validation step anyway. Thus, the prefilter is + // largely redundant work. + // + // Increase the factor noticeably hurts the + // memmem/krate/prebuilt/teeny-*/never-john-watson benchmarks. + const PREFILTER_LENGTH_FACTOR: usize = 2; + const VECTOR_MIN_LENGTH: usize = 16; + let min = core::cmp::max( + VECTOR_MIN_LENGTH, + PREFILTER_LENGTH_FACTOR * needle.len(), + ); + // For haystacks with length==min, we still want to avoid the prefilter, + // so add 1. + min + 1 +} + +#[cfg(all(test, feature = "std", not(miri)))] +pub(crate) mod tests { + use std::convert::{TryFrom, TryInto}; + + use super::*; + use crate::memmem::{ + prefilter::PrefilterFnTy, rabinkarp, rarebytes::RareNeedleBytes, + }; + + // Below is a small jig that generates prefilter tests. The main purpose + // of this jig is to generate tests of varying needle/haystack lengths + // in order to try and exercise all code paths in our prefilters. And in + // particular, this is especially important for vectorized prefilters where + // certain code paths might only be exercised at certain lengths. + + /// A test that represents the input and expected output to a prefilter + /// function. The test should be able to run with any prefilter function + /// and get the expected output. + pub(crate) struct PrefilterTest { + // These fields represent the inputs and expected output of a forwards + // prefilter function. + pub(crate) ninfo: NeedleInfo, + pub(crate) haystack: Vec, + pub(crate) needle: Vec, + pub(crate) output: Option, + } + + impl PrefilterTest { + /// Run all generated forward prefilter tests on the given prefn. + /// + /// # Safety + /// + /// Callers must ensure that the given prefilter function pointer is + /// safe to call for all inputs in the current environment. + pub(crate) unsafe fn run_all_tests(prefn: PrefilterFnTy) { + PrefilterTest::run_all_tests_filter(prefn, |_| true) + } + + /// Run all generated forward prefilter tests that pass the given + /// predicate on the given prefn. + /// + /// # Safety + /// + /// Callers must ensure that the given prefilter function pointer is + /// safe to call for all inputs in the current environment. + pub(crate) unsafe fn run_all_tests_filter( + prefn: PrefilterFnTy, + mut predicate: impl FnMut(&PrefilterTest) -> bool, + ) { + for seed in PREFILTER_TEST_SEEDS { + for test in seed.generate() { + if predicate(&test) { + test.run(prefn); + } + } + } + } + + /// Create a new prefilter test from a seed and some chose offsets to + /// rare bytes in the seed's needle. + /// + /// If a valid test could not be constructed, then None is returned. + /// (Currently, we take the approach of massaging tests to be valid + /// instead of rejecting them outright.) + fn new( + seed: &PrefilterTestSeed, + rare1i: usize, + rare2i: usize, + haystack_len: usize, + needle_len: usize, + output: Option, + ) -> Option { + let mut rare1i: u8 = rare1i.try_into().unwrap(); + let mut rare2i: u8 = rare2i.try_into().unwrap(); + // The '#' byte is never used in a haystack (unless we're expecting + // a match), while the '@' byte is never used in a needle. + let mut haystack = vec![b'@'; haystack_len]; + let mut needle = vec![b'#'; needle_len]; + needle[0] = seed.first; + needle[rare1i as usize] = seed.rare1; + needle[rare2i as usize] = seed.rare2; + // If we're expecting a match, then make sure the needle occurs + // in the haystack at the expected position. + if let Some(i) = output { + haystack[i..i + needle.len()].copy_from_slice(&needle); + } + // If the operations above lead to rare offsets pointing to the + // non-first occurrence of a byte, then adjust it. This might lead + // to redundant tests, but it's simpler than trying to change the + // generation process I think. + if let Some(i) = crate::memchr(seed.rare1, &needle) { + rare1i = u8::try_from(i).unwrap(); + } + if let Some(i) = crate::memchr(seed.rare2, &needle) { + rare2i = u8::try_from(i).unwrap(); + } + let ninfo = NeedleInfo { + rarebytes: RareNeedleBytes::new(rare1i, rare2i), + nhash: rabinkarp::NeedleHash::forward(&needle), + }; + Some(PrefilterTest { ninfo, haystack, needle, output }) + } + + /// Run this specific test on the given prefilter function. If the + /// outputs do no match, then this routine panics with a failure + /// message. + /// + /// # Safety + /// + /// Callers must ensure that the given prefilter function pointer is + /// safe to call for all inputs in the current environment. + unsafe fn run(&self, prefn: PrefilterFnTy) { + let mut prestate = PrefilterState::new(); + assert_eq!( + self.output, + prefn( + &mut prestate, + &self.ninfo, + &self.haystack, + &self.needle + ), + "ninfo: {:?}, haystack(len={}): {:?}, needle(len={}): {:?}", + self.ninfo, + self.haystack.len(), + std::str::from_utf8(&self.haystack).unwrap(), + self.needle.len(), + std::str::from_utf8(&self.needle).unwrap(), + ); + } + } + + /// A set of prefilter test seeds. Each seed serves as the base for the + /// generation of many other tests. In essence, the seed captures the + /// "rare" and first bytes among our needle. The tests generated from each + /// seed essentially vary the length of the needle and haystack, while + /// using the rare/first byte configuration from the seed. + /// + /// The purpose of this is to test many different needle/haystack lengths. + /// In particular, some of the vector optimizations might only have bugs + /// in haystacks of a certain size. + const PREFILTER_TEST_SEEDS: &[PrefilterTestSeed] = &[ + PrefilterTestSeed { first: b'x', rare1: b'y', rare2: b'z' }, + PrefilterTestSeed { first: b'x', rare1: b'x', rare2: b'z' }, + PrefilterTestSeed { first: b'x', rare1: b'y', rare2: b'x' }, + PrefilterTestSeed { first: b'x', rare1: b'x', rare2: b'x' }, + PrefilterTestSeed { first: b'x', rare1: b'y', rare2: b'y' }, + ]; + + /// Data that describes a single prefilter test seed. + struct PrefilterTestSeed { + first: u8, + rare1: u8, + rare2: u8, + } + + impl PrefilterTestSeed { + /// Generate a series of prefilter tests from this seed. + fn generate(&self) -> Vec { + let mut tests = vec![]; + let mut push = |test: Option| { + if let Some(test) = test { + tests.push(test); + } + }; + let len_start = 2; + // The loop below generates *a lot* of tests. The number of tests + // was chosen somewhat empirically to be "bearable" when running + // the test suite. + for needle_len in len_start..=40 { + let rare_start = len_start - 1; + for rare1i in rare_start..needle_len { + for rare2i in rare1i..needle_len { + for haystack_len in needle_len..=66 { + push(PrefilterTest::new( + self, + rare1i, + rare2i, + haystack_len, + needle_len, + None, + )); + // Test all possible match scenarios for this + // needle and haystack. + for output in 0..=(haystack_len - needle_len) { + push(PrefilterTest::new( + self, + rare1i, + rare2i, + haystack_len, + needle_len, + Some(output), + )); + } + } + } + } + } + tests + } + } +} diff --git a/src/memmem/prefilter/x86/avx.rs b/src/memmem/prefilter/x86/avx.rs new file mode 100644 index 0000000..fb11f33 --- /dev/null +++ b/src/memmem/prefilter/x86/avx.rs @@ -0,0 +1,46 @@ +use core::arch::x86_64::__m256i; + +use crate::memmem::{ + prefilter::{PrefilterFnTy, PrefilterState}, + NeedleInfo, +}; + +// Check that the functions below satisfy the Prefilter function type. +const _: PrefilterFnTy = find; + +/// An AVX2 accelerated candidate finder for single-substring search. +/// +/// # Safety +/// +/// Callers must ensure that the avx2 CPU feature is enabled in the current +/// environment. +#[target_feature(enable = "avx2")] +pub(crate) unsafe fn find( + prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], +) -> Option { + super::super::genericsimd::find::<__m256i>( + prestate, + ninfo, + haystack, + needle, + super::sse::find, + ) +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(not(miri))] + fn prefilter_permutations() { + use crate::memmem::prefilter::tests::PrefilterTest; + if !is_x86_feature_detected!("avx2") { + return; + } + // SAFETY: The safety of super::find only requires that the current + // CPU support AVX2, which we checked above. + unsafe { PrefilterTest::run_all_tests(super::find) }; + } +} diff --git a/src/memmem/prefilter/x86/mod.rs b/src/memmem/prefilter/x86/mod.rs new file mode 100644 index 0000000..91381e5 --- /dev/null +++ b/src/memmem/prefilter/x86/mod.rs @@ -0,0 +1,5 @@ +// We only use AVX when we can detect at runtime whether it's available, which +// requires std. +#[cfg(feature = "std")] +pub(crate) mod avx; +pub(crate) mod sse; diff --git a/src/memmem/prefilter/x86/sse.rs b/src/memmem/prefilter/x86/sse.rs new file mode 100644 index 0000000..b11356e --- /dev/null +++ b/src/memmem/prefilter/x86/sse.rs @@ -0,0 +1,55 @@ +use core::arch::x86_64::__m128i; + +use crate::memmem::{ + prefilter::{PrefilterFnTy, PrefilterState}, + NeedleInfo, +}; + +// Check that the functions below satisfy the Prefilter function type. +const _: PrefilterFnTy = find; + +/// An SSE2 accelerated candidate finder for single-substring search. +/// +/// # Safety +/// +/// Callers must ensure that the sse2 CPU feature is enabled in the current +/// environment. This feature should be enabled in all x86_64 targets. +#[target_feature(enable = "sse2")] +pub(crate) unsafe fn find( + prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], +) -> Option { + // If the haystack is too small for SSE2, then just run memchr on the + // rarest byte and be done with it. (It is likely that this code path is + // rarely exercised, since a higher level routine will probably dispatch to + // Rabin-Karp for such a small haystack.) + fn simple_memchr_fallback( + _prestate: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], + ) -> Option { + let (rare, _) = ninfo.rarebytes.as_rare_ordered_usize(); + crate::memchr(needle[rare], haystack).map(|i| i.saturating_sub(rare)) + } + super::super::genericsimd::find::<__m128i>( + prestate, + ninfo, + haystack, + needle, + simple_memchr_fallback, + ) +} + +#[cfg(all(test, feature = "std"))] +mod tests { + #[test] + #[cfg(not(miri))] + fn prefilter_permutations() { + use crate::memmem::prefilter::tests::PrefilterTest; + // SAFETY: super::find is safe to call for all inputs on x86. + unsafe { PrefilterTest::run_all_tests(super::find) }; + } +} diff --git a/src/memmem/rabinkarp.rs b/src/memmem/rabinkarp.rs new file mode 100644 index 0000000..daa4015 --- /dev/null +++ b/src/memmem/rabinkarp.rs @@ -0,0 +1,233 @@ +/* +This module implements the classical Rabin-Karp substring search algorithm, +with no extra frills. While its use would seem to break our time complexity +guarantee of O(m+n) (RK's time complexity is O(mn)), we are careful to only +ever use RK on a constant subset of haystacks. The main point here is that +RK has good latency properties for small needles/haystacks. It's very quick +to compute a needle hash and zip through the haystack when compared to +initializing Two-Way, for example. And this is especially useful for cases +where the haystack is just too short for vector instructions to do much good. + +The hashing function used here is the same one recommended by ESMAJ. + +Another choice instead of Rabin-Karp would be Shift-Or. But its latency +isn't quite as good since its preprocessing time is a bit more expensive +(both in practice and in theory). However, perhaps Shift-Or has a place +somewhere else for short patterns. I think the main problem is that it +requires space proportional to the alphabet and the needle. If we, for +example, supported needles up to length 16, then the total table size would be +len(alphabet)*size_of::()==512 bytes. Which isn't exactly small, and it's +probably bad to put that on the stack. So ideally, we'd throw it on the heap, +but we'd really like to write as much code without using alloc/std as possible. +But maybe it's worth the special casing. It's a TODO to benchmark. + +Wikipedia has a decent explanation, if a bit heavy on the theory: +https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm + +But ESMAJ provides something a bit more concrete: +http://www-igm.univ-mlv.fr/~lecroq/string/node5.html + +Finally, aho-corasick uses Rabin-Karp for multiple pattern match in some cases: +https://github.com/BurntSushi/aho-corasick/blob/3852632f10587db0ff72ef29e88d58bf305a0946/src/packed/rabinkarp.rs +*/ + +/// Whether RK is believed to be very fast for the given needle/haystack. +pub(crate) fn is_fast(haystack: &[u8], _needle: &[u8]) -> bool { + haystack.len() < 16 +} + +/// Search for the first occurrence of needle in haystack using Rabin-Karp. +pub(crate) fn find(haystack: &[u8], needle: &[u8]) -> Option { + find_with(&NeedleHash::forward(needle), haystack, needle) +} + +/// Search for the first occurrence of needle in haystack using Rabin-Karp with +/// a pre-computed needle hash. +pub(crate) fn find_with( + nhash: &NeedleHash, + mut haystack: &[u8], + needle: &[u8], +) -> Option { + if haystack.len() < needle.len() { + return None; + } + let start = haystack.as_ptr() as usize; + let mut hash = Hash::from_bytes_fwd(&haystack[..needle.len()]); + // N.B. I've experimented with unrolling this loop, but couldn't realize + // any obvious gains. + loop { + if nhash.eq(hash) && is_prefix(haystack, needle) { + return Some(haystack.as_ptr() as usize - start); + } + if needle.len() >= haystack.len() { + return None; + } + hash.roll(&nhash, haystack[0], haystack[needle.len()]); + haystack = &haystack[1..]; + } +} + +/// Search for the last occurrence of needle in haystack using Rabin-Karp. +pub(crate) fn rfind(haystack: &[u8], needle: &[u8]) -> Option { + rfind_with(&NeedleHash::reverse(needle), haystack, needle) +} + +/// Search for the last occurrence of needle in haystack using Rabin-Karp with +/// a pre-computed needle hash. +pub(crate) fn rfind_with( + nhash: &NeedleHash, + mut haystack: &[u8], + needle: &[u8], +) -> Option { + if haystack.len() < needle.len() { + return None; + } + let mut hash = + Hash::from_bytes_rev(&haystack[haystack.len() - needle.len()..]); + loop { + if nhash.eq(hash) && is_suffix(haystack, needle) { + return Some(haystack.len() - needle.len()); + } + if needle.len() >= haystack.len() { + return None; + } + hash.roll( + &nhash, + haystack[haystack.len() - 1], + haystack[haystack.len() - needle.len() - 1], + ); + haystack = &haystack[..haystack.len() - 1]; + } +} + +/// A hash derived from a needle. +#[derive(Clone, Copy, Debug, Default)] +pub(crate) struct NeedleHash { + /// The actual hash. + hash: Hash, + /// The factor needed to multiply a byte by in order to subtract it from + /// the hash. It is defined to be 2^(n-1) (using wrapping exponentiation), + /// where n is the length of the needle. This is how we "remove" a byte + /// from the hash once the hash window rolls past it. + hash_2pow: u32, +} + +impl NeedleHash { + /// Create a new Rabin-Karp hash for the given needle for use in forward + /// searching. + pub(crate) fn forward(needle: &[u8]) -> NeedleHash { + let mut nh = NeedleHash { hash: Hash::new(), hash_2pow: 1 }; + if needle.is_empty() { + return nh; + } + nh.hash.add(needle[0]); + for &b in needle.iter().skip(1) { + nh.hash.add(b); + nh.hash_2pow = nh.hash_2pow.wrapping_shl(1); + } + nh + } + + /// Create a new Rabin-Karp hash for the given needle for use in reverse + /// searching. + pub(crate) fn reverse(needle: &[u8]) -> NeedleHash { + let mut nh = NeedleHash { hash: Hash::new(), hash_2pow: 1 }; + if needle.is_empty() { + return nh; + } + nh.hash.add(needle[needle.len() - 1]); + for &b in needle.iter().rev().skip(1) { + nh.hash.add(b); + nh.hash_2pow = nh.hash_2pow.wrapping_shl(1); + } + nh + } + + /// Return true if the hashes are equivalent. + fn eq(&self, hash: Hash) -> bool { + self.hash == hash + } +} + +/// A Rabin-Karp hash. This might represent the hash of a needle, or the hash +/// of a rolling window in the haystack. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub(crate) struct Hash(u32); + +impl Hash { + /// Create a new hash that represents the empty string. + pub(crate) fn new() -> Hash { + Hash(0) + } + + /// Create a new hash from the bytes given for use in forward searches. + pub(crate) fn from_bytes_fwd(bytes: &[u8]) -> Hash { + let mut hash = Hash::new(); + for &b in bytes { + hash.add(b); + } + hash + } + + /// Create a new hash from the bytes given for use in reverse searches. + fn from_bytes_rev(bytes: &[u8]) -> Hash { + let mut hash = Hash::new(); + for &b in bytes.iter().rev() { + hash.add(b); + } + hash + } + + /// Add 'new' and remove 'old' from this hash. The given needle hash should + /// correspond to the hash computed for the needle being searched for. + /// + /// This is meant to be used when the rolling window of the haystack is + /// advanced. + fn roll(&mut self, nhash: &NeedleHash, old: u8, new: u8) { + self.del(nhash, old); + self.add(new); + } + + /// Add a byte to this hash. + fn add(&mut self, byte: u8) { + self.0 = self.0.wrapping_shl(1).wrapping_add(byte as u32); + } + + /// Remove a byte from this hash. The given needle hash should correspond + /// to the hash computed for the needle being searched for. + fn del(&mut self, nhash: &NeedleHash, byte: u8) { + let factor = nhash.hash_2pow; + self.0 = self.0.wrapping_sub((byte as u32).wrapping_mul(factor)); + } +} + +/// Returns true if the given needle is a prefix of the given haystack. +/// +/// We forcefully don't inline the is_prefix call and hint at the compiler that +/// it is unlikely to be called. This causes the inner rabinkarp loop above +/// to be a bit tighter and leads to some performance improvement. See the +/// memmem/krate/prebuilt/sliceslice-words/words benchmark. +#[cold] +#[inline(never)] +fn is_prefix(haystack: &[u8], needle: &[u8]) -> bool { + crate::memmem::util::is_prefix(haystack, needle) +} + +/// Returns true if the given needle is a suffix of the given haystack. +/// +/// See is_prefix for why this is forcefully not inlined. +#[cold] +#[inline(never)] +fn is_suffix(haystack: &[u8], needle: &[u8]) -> bool { + crate::memmem::util::is_suffix(haystack, needle) +} + +#[cfg(test)] +mod simpletests { + define_memmem_simple_tests!(super::find, super::rfind); +} + +#[cfg(all(test, feature = "std", not(miri)))] +mod proptests { + define_memmem_quickcheck_tests!(super::find, super::rfind); +} diff --git a/src/memmem/rarebytes.rs b/src/memmem/rarebytes.rs new file mode 100644 index 0000000..fb33f68 --- /dev/null +++ b/src/memmem/rarebytes.rs @@ -0,0 +1,136 @@ +/// A heuristic frequency based detection of rare bytes for substring search. +/// +/// This detector attempts to pick out two bytes in a needle that are predicted +/// to occur least frequently. The purpose is to use these bytes to implement +/// fast candidate search using vectorized code. +/// +/// A set of offsets is only computed for needles of length 2 or greater. +/// Smaller needles should be special cased by the substring search algorithm +/// in use. (e.g., Use memchr for single byte needles.) +/// +/// Note that we use `u8` to represent the offsets of the rare bytes in a +/// needle to reduce space usage. This means that rare byte occurring after the +/// first 255 bytes in a needle will never be used. +#[derive(Clone, Copy, Debug, Default)] +pub(crate) struct RareNeedleBytes { + /// The leftmost offset of the rarest byte in the needle, according to + /// pre-computed frequency analysis. The "leftmost offset" means that + /// rare1i <= i for all i where needle[i] == needle[rare1i]. + rare1i: u8, + /// The leftmost offset of the second rarest byte in the needle, according + /// to pre-computed frequency analysis. The "leftmost offset" means that + /// rare2i <= i for all i where needle[i] == needle[rare2i]. + /// + /// The second rarest byte is used as a type of guard for quickly detecting + /// a mismatch if the first byte matches. This is a hedge against + /// pathological cases where the pre-computed frequency analysis may be + /// off. (But of course, does not prevent *all* pathological cases.) + /// + /// In general, rare1i != rare2i by construction, although there is no hard + /// requirement that they be different. However, since the case of a single + /// byte needle is handled specially by memchr itself, rare2i generally + /// always should be different from rare1i since it would otherwise be + /// ineffective as a guard. + rare2i: u8, +} + +impl RareNeedleBytes { + /// Create a new pair of rare needle bytes with the given offsets. This is + /// only used in tests for generating input data. + #[cfg(all(test, feature = "std"))] + pub(crate) fn new(rare1i: u8, rare2i: u8) -> RareNeedleBytes { + RareNeedleBytes { rare1i, rare2i } + } + + /// Detect the leftmost offsets of the two rarest bytes in the given + /// needle. + pub(crate) fn forward(needle: &[u8]) -> RareNeedleBytes { + if needle.len() <= 1 || needle.len() > core::u8::MAX as usize { + // For needles bigger than u8::MAX, our offsets aren't big enough. + // (We make our offsets small to reduce stack copying.) + // If you have a use case for it, please file an issue. In that + // case, we should probably just adjust the routine below to pick + // some rare bytes from the first 255 bytes of the needle. + // + // Also note that for needles of size 0 or 1, they are special + // cased in Two-Way. + // + // TODO: Benchmar this. + return RareNeedleBytes { rare1i: 0, rare2i: 0 }; + } + + // Find the rarest two bytes. We make them distinct by construction. + let (mut rare1, mut rare1i) = (needle[0], 0); + let (mut rare2, mut rare2i) = (needle[1], 1); + if rank(rare2) < rank(rare1) { + core::mem::swap(&mut rare1, &mut rare2); + core::mem::swap(&mut rare1i, &mut rare2i); + } + for (i, &b) in needle.iter().enumerate().skip(2) { + if rank(b) < rank(rare1) { + rare2 = rare1; + rare2i = rare1i; + rare1 = b; + rare1i = i as u8; + } else if b != rare1 && rank(b) < rank(rare2) { + rare2 = b; + rare2i = i as u8; + } + } + // While not strictly required, we really don't want these to be + // equivalent. If they were, it would reduce the effectiveness of + // candidate searching using these rare bytes by increasing the rate of + // false positives. + assert_ne!(rare1i, rare2i); + RareNeedleBytes { rare1i, rare2i } + } + + /// Return the rare bytes in the given needle in the forward direction. + /// The needle given must be the same one given to the RareNeedleBytes + /// constructor. + pub(crate) fn as_rare_bytes(&self, needle: &[u8]) -> (u8, u8) { + (needle[self.rare1i as usize], needle[self.rare2i as usize]) + } + + /// Return the rare offsets such that the first offset is always <= to the + /// second offset. This is useful when the caller doesn't care whether + /// rare1 is rarer than rare2, but just wants to ensure that they are + /// ordered with respect to one another. + #[cfg(memchr_runtime_simd)] + pub(crate) fn as_rare_ordered_usize(&self) -> (usize, usize) { + let (rare1i, rare2i) = self.as_rare_ordered_u8(); + (rare1i as usize, rare2i as usize) + } + + /// Like as_rare_ordered_usize, but returns the offsets as their native + /// u8 values. + #[cfg(memchr_runtime_simd)] + pub(crate) fn as_rare_ordered_u8(&self) -> (u8, u8) { + if self.rare1i <= self.rare2i { + (self.rare1i, self.rare2i) + } else { + (self.rare2i, self.rare1i) + } + } + + /// Return the rare offsets as usize values in the order in which they were + /// constructed. rare1, for example, is constructed as the "rarer" byte, + /// and thus, callers may want to treat it differently from rare2. + pub(crate) fn as_rare_usize(&self) -> (usize, usize) { + (self.rare1i as usize, self.rare2i as usize) + } + + /// Return the byte frequency rank of each byte. The higher the rank, the + /// more frequency the byte is predicted to be. The needle given must be + /// the same one given to the RareNeedleBytes constructor. + pub(crate) fn as_ranks(&self, needle: &[u8]) -> (usize, usize) { + let (b1, b2) = self.as_rare_bytes(needle); + (rank(b1), rank(b2)) + } +} + +/// Return the heuristical frequency rank of the given byte. A lower rank +/// means the byte is believed to occur less frequently. +fn rank(b: u8) -> usize { + crate::memmem::byte_frequencies::BYTE_FREQUENCIES[b as usize] as usize +} diff --git a/src/memmem/twoway.rs b/src/memmem/twoway.rs new file mode 100644 index 0000000..7f82ed1 --- /dev/null +++ b/src/memmem/twoway.rs @@ -0,0 +1,878 @@ +use core::cmp; + +use crate::memmem::{prefilter::Pre, util}; + +/// Two-Way search in the forward direction. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Forward(TwoWay); + +/// Two-Way search in the reverse direction. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Reverse(TwoWay); + +/// An implementation of the TwoWay substring search algorithm, with heuristics +/// for accelerating search based on frequency analysis. +/// +/// This searcher supports forward and reverse search, although not +/// simultaneously. It runs in O(n + m) time and O(1) space, where +/// `n ~ len(needle)` and `m ~ len(haystack)`. +/// +/// The implementation here roughly matches that which was developed by +/// Crochemore and Perrin in their 1991 paper "Two-way string-matching." The +/// changes in this implementation are 1) the use of zero-based indices, 2) a +/// heuristic skip table based on the last byte (borrowed from Rust's standard +/// library) and 3) the addition of heuristics for a fast skip loop. That is, +/// (3) this will detect bytes that are believed to be rare in the needle and +/// use fast vectorized instructions to find their occurrences quickly. The +/// Two-Way algorithm is then used to confirm whether a match at that location +/// occurred. +/// +/// The heuristic for fast skipping is automatically shut off if it's +/// detected to be ineffective at search time. Generally, this only occurs in +/// pathological cases. But this is generally necessary in order to preserve +/// a `O(n + m)` time bound. +/// +/// The code below is fairly complex and not obviously correct at all. It's +/// likely necessary to read the Two-Way paper cited above in order to fully +/// grok this code. The essence of it is: +/// +/// 1) Do something to detect a "critical" position in the needle. +/// 2) For the current position in the haystack, look if needle[critical..] +/// matches at that position. +/// 3) If so, look if needle[..critical] matches. +/// 4) If a mismatch occurs, shift the search by some amount based on the +/// critical position and a pre-computed shift. +/// +/// This type is wrapped in Forward and Reverse types that expose consistent +/// forward or reverse APIs. +#[derive(Clone, Copy, Debug)] +struct TwoWay { + /// A small bitset used as a quick prefilter (in addition to the faster + /// SIMD based prefilter). Namely, a bit 'i' is set if and only if b%64==i + /// for any b in the needle. + /// + /// When used as a prefilter, if the last byte at the current candidate + /// position is NOT in this set, then we can skip that entire candidate + /// position (the length of the needle). This is essentially the shift + /// trick found in Boyer-Moore, but only applied to bytes that don't appear + /// in the needle. + /// + /// N.B. This trick was inspired by something similar in std's + /// implementation of Two-Way. + byteset: ApproximateByteSet, + /// A critical position in needle. Specifically, this position corresponds + /// to beginning of either the minimal or maximal suffix in needle. (N.B. + /// See SuffixType below for why "minimal" isn't quite the correct word + /// here.) + /// + /// This is the position at which every search begins. Namely, search + /// starts by scanning text to the right of this position, and only if + /// there's a match does the text to the left of this position get scanned. + critical_pos: usize, + /// The amount we shift by in the Two-Way search algorithm. This + /// corresponds to the "small period" and "large period" cases. + shift: Shift, +} + +impl Forward { + /// Create a searcher that uses the Two-Way algorithm by searching forwards + /// through any haystack. + pub(crate) fn new(needle: &[u8]) -> Forward { + if needle.is_empty() { + return Forward(TwoWay::empty()); + } + + let byteset = ApproximateByteSet::new(needle); + let min_suffix = Suffix::forward(needle, SuffixKind::Minimal); + let max_suffix = Suffix::forward(needle, SuffixKind::Maximal); + let (period_lower_bound, critical_pos) = + if min_suffix.pos > max_suffix.pos { + (min_suffix.period, min_suffix.pos) + } else { + (max_suffix.period, max_suffix.pos) + }; + let shift = Shift::forward(needle, period_lower_bound, critical_pos); + Forward(TwoWay { byteset, critical_pos, shift }) + } + + /// Find the position of the first occurrence of this searcher's needle in + /// the given haystack. If one does not exist, then return None. + /// + /// This accepts prefilter state that is useful when using the same + /// searcher multiple times, such as in an iterator. + /// + /// Callers must guarantee that the needle is non-empty and its length is + /// <= the haystack's length. + #[inline(always)] + pub(crate) fn find( + &self, + pre: Option<&mut Pre<'_>>, + haystack: &[u8], + needle: &[u8], + ) -> Option { + debug_assert!(!needle.is_empty(), "needle should not be empty"); + debug_assert!(needle.len() <= haystack.len(), "haystack too short"); + + match self.0.shift { + Shift::Small { period } => { + self.find_small_imp(pre, haystack, needle, period) + } + Shift::Large { shift } => { + self.find_large_imp(pre, haystack, needle, shift) + } + } + } + + /// Like find, but handles the degenerate substring test cases. This is + /// only useful for conveniently testing this substring implementation in + /// isolation. + #[cfg(test)] + fn find_general( + &self, + pre: Option<&mut Pre<'_>>, + haystack: &[u8], + needle: &[u8], + ) -> Option { + if needle.is_empty() { + Some(0) + } else if haystack.len() < needle.len() { + None + } else { + self.find(pre, haystack, needle) + } + } + + // Each of the two search implementations below can be accelerated by a + // prefilter, but it is not always enabled. To avoid its overhead when + // its disabled, we explicitly inline each search implementation based on + // whether a prefilter will be used or not. The decision on which to use + // is made in the parent meta searcher. + + #[inline(always)] + fn find_small_imp( + &self, + mut pre: Option<&mut Pre<'_>>, + haystack: &[u8], + needle: &[u8], + period: usize, + ) -> Option { + let last_byte = needle.len() - 1; + let mut pos = 0; + let mut shift = 0; + while pos + needle.len() <= haystack.len() { + let mut i = cmp::max(self.0.critical_pos, shift); + if let Some(pre) = pre.as_mut() { + if pre.should_call() { + pos += pre.call(&haystack[pos..], needle)?; + shift = 0; + i = self.0.critical_pos; + if pos + needle.len() > haystack.len() { + return None; + } + } + } + if !self.0.byteset.contains(haystack[pos + last_byte]) { + pos += needle.len(); + shift = 0; + continue; + } + while i < needle.len() && needle[i] == haystack[pos + i] { + i += 1; + } + if i < needle.len() { + pos += i - self.0.critical_pos + 1; + shift = 0; + } else { + let mut j = self.0.critical_pos; + while j > shift && needle[j] == haystack[pos + j] { + j -= 1; + } + if j <= shift && needle[shift] == haystack[pos + shift] { + return Some(pos); + } + pos += period; + shift = needle.len() - period; + } + } + None + } + + #[inline(always)] + fn find_large_imp( + &self, + mut pre: Option<&mut Pre<'_>>, + haystack: &[u8], + needle: &[u8], + shift: usize, + ) -> Option { + let last_byte = needle.len() - 1; + let mut pos = 0; + 'outer: while pos + needle.len() <= haystack.len() { + if let Some(pre) = pre.as_mut() { + if pre.should_call() { + pos += pre.call(&haystack[pos..], needle)?; + if pos + needle.len() > haystack.len() { + return None; + } + } + } + + if !self.0.byteset.contains(haystack[pos + last_byte]) { + pos += needle.len(); + continue; + } + let mut i = self.0.critical_pos; + while i < needle.len() && needle[i] == haystack[pos + i] { + i += 1; + } + if i < needle.len() { + pos += i - self.0.critical_pos + 1; + } else { + for j in (0..self.0.critical_pos).rev() { + if needle[j] != haystack[pos + j] { + pos += shift; + continue 'outer; + } + } + return Some(pos); + } + } + None + } +} + +impl Reverse { + /// Create a searcher that uses the Two-Way algorithm by searching in + /// reverse through any haystack. + pub(crate) fn new(needle: &[u8]) -> Reverse { + if needle.is_empty() { + return Reverse(TwoWay::empty()); + } + + let byteset = ApproximateByteSet::new(needle); + let min_suffix = Suffix::reverse(needle, SuffixKind::Minimal); + let max_suffix = Suffix::reverse(needle, SuffixKind::Maximal); + let (period_lower_bound, critical_pos) = + if min_suffix.pos < max_suffix.pos { + (min_suffix.period, min_suffix.pos) + } else { + (max_suffix.period, max_suffix.pos) + }; + // let critical_pos = needle.len() - critical_pos; + let shift = Shift::reverse(needle, period_lower_bound, critical_pos); + Reverse(TwoWay { byteset, critical_pos, shift }) + } + + /// Find the position of the last occurrence of this searcher's needle + /// in the given haystack. If one does not exist, then return None. + /// + /// This will automatically initialize prefilter state. This should only + /// be used for one-off searches. + /// + /// Callers must guarantee that the needle is non-empty and its length is + /// <= the haystack's length. + #[inline(always)] + pub(crate) fn rfind( + &self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + debug_assert!(!needle.is_empty(), "needle should not be empty"); + debug_assert!(needle.len() <= haystack.len(), "haystack too short"); + // For the reverse case, we don't use a prefilter. It's plausible that + // perhaps we should, but it's a lot of additional code to do it, and + // it's not clear that it's actually worth it. If you have a really + // compelling use case for this, please file an issue. + match self.0.shift { + Shift::Small { period } => { + self.rfind_small_imp(haystack, needle, period) + } + Shift::Large { shift } => { + self.rfind_large_imp(haystack, needle, shift) + } + } + } + + /// Like rfind, but handles the degenerate substring test cases. This is + /// only useful for conveniently testing this substring implementation in + /// isolation. + #[cfg(test)] + fn rfind_general(&self, haystack: &[u8], needle: &[u8]) -> Option { + if needle.is_empty() { + Some(haystack.len()) + } else if haystack.len() < needle.len() { + None + } else { + self.rfind(haystack, needle) + } + } + + #[inline(always)] + fn rfind_small_imp( + &self, + haystack: &[u8], + needle: &[u8], + period: usize, + ) -> Option { + let nlen = needle.len(); + let mut pos = haystack.len(); + let mut shift = nlen; + while pos >= nlen { + if !self.0.byteset.contains(haystack[pos - nlen]) { + pos -= nlen; + shift = nlen; + continue; + } + let mut i = cmp::min(self.0.critical_pos, shift); + while i > 0 && needle[i - 1] == haystack[pos - nlen + i - 1] { + i -= 1; + } + if i > 0 || needle[0] != haystack[pos - nlen] { + pos -= self.0.critical_pos - i + 1; + shift = nlen; + } else { + let mut j = self.0.critical_pos; + while j < shift && needle[j] == haystack[pos - nlen + j] { + j += 1; + } + if j >= shift { + return Some(pos - nlen); + } + pos -= period; + shift = period; + } + } + None + } + + #[inline(always)] + fn rfind_large_imp( + &self, + haystack: &[u8], + needle: &[u8], + shift: usize, + ) -> Option { + let nlen = needle.len(); + let mut pos = haystack.len(); + while pos >= nlen { + if !self.0.byteset.contains(haystack[pos - nlen]) { + pos -= nlen; + continue; + } + let mut i = self.0.critical_pos; + while i > 0 && needle[i - 1] == haystack[pos - nlen + i - 1] { + i -= 1; + } + if i > 0 || needle[0] != haystack[pos - nlen] { + pos -= self.0.critical_pos - i + 1; + } else { + let mut j = self.0.critical_pos; + while j < nlen && needle[j] == haystack[pos - nlen + j] { + j += 1; + } + if j == nlen { + return Some(pos - nlen); + } + pos -= shift; + } + } + None + } +} + +impl TwoWay { + fn empty() -> TwoWay { + TwoWay { + byteset: ApproximateByteSet::new(b""), + critical_pos: 0, + shift: Shift::Large { shift: 0 }, + } + } +} + +/// A representation of the amount we're allowed to shift by during Two-Way +/// search. +/// +/// When computing a critical factorization of the needle, we find the position +/// of the critical factorization by finding the needle's maximal (or minimal) +/// suffix, along with the period of that suffix. It turns out that the period +/// of that suffix is a lower bound on the period of the needle itself. +/// +/// This lower bound is equivalent to the actual period of the needle in +/// some cases. To describe that case, we denote the needle as `x` where +/// `x = uv` and `v` is the lexicographic maximal suffix of `v`. The lower +/// bound given here is always the period of `v`, which is `<= period(x)`. The +/// case where `period(v) == period(x)` occurs when `len(u) < (len(x) / 2)` and +/// where `u` is a suffix of `v[0..period(v)]`. +/// +/// This case is important because the search algorithm for when the +/// periods are equivalent is slightly different than the search algorithm +/// for when the periods are not equivalent. In particular, when they aren't +/// equivalent, we know that the period of the needle is no less than half its +/// length. In this case, we shift by an amount less than or equal to the +/// period of the needle (determined by the maximum length of the components +/// of the critical factorization of `x`, i.e., `max(len(u), len(v))`).. +/// +/// The above two cases are represented by the variants below. Each entails +/// a different instantiation of the Two-Way search algorithm. +/// +/// N.B. If we could find a way to compute the exact period in all cases, +/// then we could collapse this case analysis and simplify the algorithm. The +/// Two-Way paper suggests this is possible, but more reading is required to +/// grok why the authors didn't pursue that path. +#[derive(Clone, Copy, Debug)] +enum Shift { + Small { period: usize }, + Large { shift: usize }, +} + +impl Shift { + /// Compute the shift for a given needle in the forward direction. + /// + /// This requires a lower bound on the period and a critical position. + /// These can be computed by extracting both the minimal and maximal + /// lexicographic suffixes, and choosing the right-most starting position. + /// The lower bound on the period is then the period of the chosen suffix. + fn forward( + needle: &[u8], + period_lower_bound: usize, + critical_pos: usize, + ) -> Shift { + let large = cmp::max(critical_pos, needle.len() - critical_pos); + if critical_pos * 2 >= needle.len() { + return Shift::Large { shift: large }; + } + + let (u, v) = needle.split_at(critical_pos); + if !util::is_suffix(&v[..period_lower_bound], u) { + return Shift::Large { shift: large }; + } + Shift::Small { period: period_lower_bound } + } + + /// Compute the shift for a given needle in the reverse direction. + /// + /// This requires a lower bound on the period and a critical position. + /// These can be computed by extracting both the minimal and maximal + /// lexicographic suffixes, and choosing the left-most starting position. + /// The lower bound on the period is then the period of the chosen suffix. + fn reverse( + needle: &[u8], + period_lower_bound: usize, + critical_pos: usize, + ) -> Shift { + let large = cmp::max(critical_pos, needle.len() - critical_pos); + if (needle.len() - critical_pos) * 2 >= needle.len() { + return Shift::Large { shift: large }; + } + + let (v, u) = needle.split_at(critical_pos); + if !util::is_prefix(&v[v.len() - period_lower_bound..], u) { + return Shift::Large { shift: large }; + } + Shift::Small { period: period_lower_bound } + } +} + +/// A suffix extracted from a needle along with its period. +#[derive(Debug)] +struct Suffix { + /// The starting position of this suffix. + /// + /// If this is a forward suffix, then `&bytes[pos..]` can be used. If this + /// is a reverse suffix, then `&bytes[..pos]` can be used. That is, for + /// forward suffixes, this is an inclusive starting position, where as for + /// reverse suffixes, this is an exclusive ending position. + pos: usize, + /// The period of this suffix. + /// + /// Note that this is NOT necessarily the period of the string from which + /// this suffix comes from. (It is always less than or equal to the period + /// of the original string.) + period: usize, +} + +impl Suffix { + fn forward(needle: &[u8], kind: SuffixKind) -> Suffix { + debug_assert!(!needle.is_empty()); + + // suffix represents our maximal (or minimal) suffix, along with + // its period. + let mut suffix = Suffix { pos: 0, period: 1 }; + // The start of a suffix in `needle` that we are considering as a + // more maximal (or minimal) suffix than what's in `suffix`. + let mut candidate_start = 1; + // The current offset of our suffixes that we're comparing. + // + // When the characters at this offset are the same, then we mush on + // to the next position since no decision is possible. When the + // candidate's character is greater (or lesser) than the corresponding + // character than our current maximal (or minimal) suffix, then the + // current suffix is changed over to the candidate and we restart our + // search. Otherwise, the candidate suffix is no good and we restart + // our search on the next candidate. + // + // The three cases above correspond to the three cases in the loop + // below. + let mut offset = 0; + + while candidate_start + offset < needle.len() { + let current = needle[suffix.pos + offset]; + let candidate = needle[candidate_start + offset]; + match kind.cmp(current, candidate) { + SuffixOrdering::Accept => { + suffix = Suffix { pos: candidate_start, period: 1 }; + candidate_start += 1; + offset = 0; + } + SuffixOrdering::Skip => { + candidate_start += offset + 1; + offset = 0; + suffix.period = candidate_start - suffix.pos; + } + SuffixOrdering::Push => { + if offset + 1 == suffix.period { + candidate_start += suffix.period; + offset = 0; + } else { + offset += 1; + } + } + } + } + suffix + } + + fn reverse(needle: &[u8], kind: SuffixKind) -> Suffix { + debug_assert!(!needle.is_empty()); + + // See the comments in `forward` for how this works. + let mut suffix = Suffix { pos: needle.len(), period: 1 }; + if needle.len() == 1 { + return suffix; + } + let mut candidate_start = needle.len() - 1; + let mut offset = 0; + + while offset < candidate_start { + let current = needle[suffix.pos - offset - 1]; + let candidate = needle[candidate_start - offset - 1]; + match kind.cmp(current, candidate) { + SuffixOrdering::Accept => { + suffix = Suffix { pos: candidate_start, period: 1 }; + candidate_start -= 1; + offset = 0; + } + SuffixOrdering::Skip => { + candidate_start -= offset + 1; + offset = 0; + suffix.period = suffix.pos - candidate_start; + } + SuffixOrdering::Push => { + if offset + 1 == suffix.period { + candidate_start -= suffix.period; + offset = 0; + } else { + offset += 1; + } + } + } + } + suffix + } +} + +/// The kind of suffix to extract. +#[derive(Clone, Copy, Debug)] +enum SuffixKind { + /// Extract the smallest lexicographic suffix from a string. + /// + /// Technically, this doesn't actually pick the smallest lexicographic + /// suffix. e.g., Given the choice between `a` and `aa`, this will choose + /// the latter over the former, even though `a < aa`. The reasoning for + /// this isn't clear from the paper, but it still smells like a minimal + /// suffix. + Minimal, + /// Extract the largest lexicographic suffix from a string. + /// + /// Unlike `Minimal`, this really does pick the maximum suffix. e.g., Given + /// the choice between `z` and `zz`, this will choose the latter over the + /// former. + Maximal, +} + +/// The result of comparing corresponding bytes between two suffixes. +#[derive(Clone, Copy, Debug)] +enum SuffixOrdering { + /// This occurs when the given candidate byte indicates that the candidate + /// suffix is better than the current maximal (or minimal) suffix. That is, + /// the current candidate suffix should supplant the current maximal (or + /// minimal) suffix. + Accept, + /// This occurs when the given candidate byte excludes the candidate suffix + /// from being better than the current maximal (or minimal) suffix. That + /// is, the current candidate suffix should be dropped and the next one + /// should be considered. + Skip, + /// This occurs when no decision to accept or skip the candidate suffix + /// can be made, e.g., when corresponding bytes are equivalent. In this + /// case, the next corresponding bytes should be compared. + Push, +} + +impl SuffixKind { + /// Returns true if and only if the given candidate byte indicates that + /// it should replace the current suffix as the maximal (or minimal) + /// suffix. + fn cmp(self, current: u8, candidate: u8) -> SuffixOrdering { + use self::SuffixOrdering::*; + + match self { + SuffixKind::Minimal if candidate < current => Accept, + SuffixKind::Minimal if candidate > current => Skip, + SuffixKind::Minimal => Push, + SuffixKind::Maximal if candidate > current => Accept, + SuffixKind::Maximal if candidate < current => Skip, + SuffixKind::Maximal => Push, + } + } +} + +/// A bitset used to track whether a particular byte exists in a needle or not. +/// +/// Namely, bit 'i' is set if and only if byte%64==i for any byte in the +/// needle. If a particular byte in the haystack is NOT in this set, then one +/// can conclude that it is also not in the needle, and thus, one can advance +/// in the haystack by needle.len() bytes. +#[derive(Clone, Copy, Debug)] +struct ApproximateByteSet(u64); + +impl ApproximateByteSet { + /// Create a new set from the given needle. + fn new(needle: &[u8]) -> ApproximateByteSet { + let mut bits = 0; + for &b in needle { + bits |= 1 << (b % 64); + } + ApproximateByteSet(bits) + } + + /// Return true if and only if the given byte might be in this set. This + /// may return a false positive, but will never return a false negative. + #[inline(always)] + fn contains(&self, byte: u8) -> bool { + self.0 & (1 << (byte % 64)) != 0 + } +} + +#[cfg(all(test, feature = "std", not(miri)))] +mod tests { + use quickcheck::quickcheck; + + use super::*; + + define_memmem_quickcheck_tests!( + super::simpletests::twoway_find, + super::simpletests::twoway_rfind + ); + + /// Convenience wrapper for computing the suffix as a byte string. + fn get_suffix_forward(needle: &[u8], kind: SuffixKind) -> (&[u8], usize) { + let s = Suffix::forward(needle, kind); + (&needle[s.pos..], s.period) + } + + /// Convenience wrapper for computing the reverse suffix as a byte string. + fn get_suffix_reverse(needle: &[u8], kind: SuffixKind) -> (&[u8], usize) { + let s = Suffix::reverse(needle, kind); + (&needle[..s.pos], s.period) + } + + /// Return all of the non-empty suffixes in the given byte string. + fn suffixes(bytes: &[u8]) -> Vec<&[u8]> { + (0..bytes.len()).map(|i| &bytes[i..]).collect() + } + + /// Return the lexicographically maximal suffix of the given byte string. + fn naive_maximal_suffix_forward(needle: &[u8]) -> &[u8] { + let mut sufs = suffixes(needle); + sufs.sort(); + sufs.pop().unwrap() + } + + /// Return the lexicographically maximal suffix of the reverse of the given + /// byte string. + fn naive_maximal_suffix_reverse(needle: &[u8]) -> Vec { + let mut reversed = needle.to_vec(); + reversed.reverse(); + let mut got = naive_maximal_suffix_forward(&reversed).to_vec(); + got.reverse(); + got + } + + #[test] + fn suffix_forward() { + macro_rules! assert_suffix_min { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_forward($given.as_bytes(), SuffixKind::Minimal); + let got_suffix = std::str::from_utf8(got_suffix).unwrap(); + assert_eq!(($expected, $period), (got_suffix, got_period)); + }; + } + + macro_rules! assert_suffix_max { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_forward($given.as_bytes(), SuffixKind::Maximal); + let got_suffix = std::str::from_utf8(got_suffix).unwrap(); + assert_eq!(($expected, $period), (got_suffix, got_period)); + }; + } + + assert_suffix_min!("a", "a", 1); + assert_suffix_max!("a", "a", 1); + + assert_suffix_min!("ab", "ab", 2); + assert_suffix_max!("ab", "b", 1); + + assert_suffix_min!("ba", "a", 1); + assert_suffix_max!("ba", "ba", 2); + + assert_suffix_min!("abc", "abc", 3); + assert_suffix_max!("abc", "c", 1); + + assert_suffix_min!("acb", "acb", 3); + assert_suffix_max!("acb", "cb", 2); + + assert_suffix_min!("cba", "a", 1); + assert_suffix_max!("cba", "cba", 3); + + assert_suffix_min!("abcabc", "abcabc", 3); + assert_suffix_max!("abcabc", "cabc", 3); + + assert_suffix_min!("abcabcabc", "abcabcabc", 3); + assert_suffix_max!("abcabcabc", "cabcabc", 3); + + assert_suffix_min!("abczz", "abczz", 5); + assert_suffix_max!("abczz", "zz", 1); + + assert_suffix_min!("zzabc", "abc", 3); + assert_suffix_max!("zzabc", "zzabc", 5); + + assert_suffix_min!("aaa", "aaa", 1); + assert_suffix_max!("aaa", "aaa", 1); + + assert_suffix_min!("foobar", "ar", 2); + assert_suffix_max!("foobar", "r", 1); + } + + #[test] + fn suffix_reverse() { + macro_rules! assert_suffix_min { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_reverse($given.as_bytes(), SuffixKind::Minimal); + let got_suffix = std::str::from_utf8(got_suffix).unwrap(); + assert_eq!(($expected, $period), (got_suffix, got_period)); + }; + } + + macro_rules! assert_suffix_max { + ($given:expr, $expected:expr, $period:expr) => { + let (got_suffix, got_period) = + get_suffix_reverse($given.as_bytes(), SuffixKind::Maximal); + let got_suffix = std::str::from_utf8(got_suffix).unwrap(); + assert_eq!(($expected, $period), (got_suffix, got_period)); + }; + } + + assert_suffix_min!("a", "a", 1); + assert_suffix_max!("a", "a", 1); + + assert_suffix_min!("ab", "a", 1); + assert_suffix_max!("ab", "ab", 2); + + assert_suffix_min!("ba", "ba", 2); + assert_suffix_max!("ba", "b", 1); + + assert_suffix_min!("abc", "a", 1); + assert_suffix_max!("abc", "abc", 3); + + assert_suffix_min!("acb", "a", 1); + assert_suffix_max!("acb", "ac", 2); + + assert_suffix_min!("cba", "cba", 3); + assert_suffix_max!("cba", "c", 1); + + assert_suffix_min!("abcabc", "abca", 3); + assert_suffix_max!("abcabc", "abcabc", 3); + + assert_suffix_min!("abcabcabc", "abcabca", 3); + assert_suffix_max!("abcabcabc", "abcabcabc", 3); + + assert_suffix_min!("abczz", "a", 1); + assert_suffix_max!("abczz", "abczz", 5); + + assert_suffix_min!("zzabc", "zza", 3); + assert_suffix_max!("zzabc", "zz", 1); + + assert_suffix_min!("aaa", "aaa", 1); + assert_suffix_max!("aaa", "aaa", 1); + } + + quickcheck! { + fn qc_suffix_forward_maximal(bytes: Vec) -> bool { + if bytes.is_empty() { + return true; + } + + let (got, _) = get_suffix_forward(&bytes, SuffixKind::Maximal); + let expected = naive_maximal_suffix_forward(&bytes); + got == expected + } + + fn qc_suffix_reverse_maximal(bytes: Vec) -> bool { + if bytes.is_empty() { + return true; + } + + let (got, _) = get_suffix_reverse(&bytes, SuffixKind::Maximal); + let expected = naive_maximal_suffix_reverse(&bytes); + expected == got + } + } +} + +#[cfg(test)] +mod simpletests { + use super::*; + + pub(crate) fn twoway_find( + haystack: &[u8], + needle: &[u8], + ) -> Option { + Forward::new(needle).find_general(None, haystack, needle) + } + + pub(crate) fn twoway_rfind( + haystack: &[u8], + needle: &[u8], + ) -> Option { + Reverse::new(needle).rfind_general(haystack, needle) + } + + define_memmem_simple_tests!(twoway_find, twoway_rfind); + + // This is a regression test caught by quickcheck that exercised a bug in + // the reverse small period handling. The bug was that we were using 'if j + // == shift' to determine if a match occurred, but the correct guard is 'if + // j >= shift', which matches the corresponding guard in the forward impl. + #[test] + fn regression_rev_small_period() { + let rfind = super::simpletests::twoway_rfind; + let haystack = "ababaz"; + let needle = "abab"; + assert_eq!(Some(0), rfind(haystack.as_bytes(), needle.as_bytes())); + } +} diff --git a/src/memmem/util.rs b/src/memmem/util.rs new file mode 100644 index 0000000..de0e385 --- /dev/null +++ b/src/memmem/util.rs @@ -0,0 +1,88 @@ +// These routines are meant to be optimized specifically for low latency as +// compared to the equivalent routines offered by std. (Which may invoke the +// dynamic linker and call out to libc, which introduces a bit more latency +// than we'd like.) + +/// Returns true if and only if needle is a prefix of haystack. +#[inline(always)] +pub(crate) fn is_prefix(haystack: &[u8], needle: &[u8]) -> bool { + needle.len() <= haystack.len() && memcmp(&haystack[..needle.len()], needle) +} + +/// Returns true if and only if needle is a suffix of haystack. +#[inline(always)] +pub(crate) fn is_suffix(haystack: &[u8], needle: &[u8]) -> bool { + needle.len() <= haystack.len() + && memcmp(&haystack[haystack.len() - needle.len()..], needle) +} + +/// Return true if and only if x.len() == y.len() && x[i] == y[i] for all +/// 0 <= i < x.len(). +/// +/// Why not just use actual memcmp for this? Well, memcmp requires calling out +/// to libc, and this routine is called in fairly hot code paths. Other than +/// just calling out to libc, it also seems to result in worse codegen. By +/// rolling our own memcmp in pure Rust, it seems to appear more friendly to +/// the optimizer. +/// +/// We mark this as inline always, although, some callers may not want it +/// inlined for better codegen (like Rabin-Karp). In that case, callers are +/// advised to create a non-inlineable wrapper routine that calls memcmp. +#[inline(always)] +pub(crate) fn memcmp(x: &[u8], y: &[u8]) -> bool { + if x.len() != y.len() { + return false; + } + // If we don't have enough bytes to do 4-byte at a time loads, then + // fall back to the naive slow version. + // + // TODO: We could do a copy_nonoverlapping combined with a mask instead + // of a loop. Benchmark it. + if x.len() < 4 { + for (&b1, &b2) in x.iter().zip(y) { + if b1 != b2 { + return false; + } + } + return true; + } + // When we have 4 or more bytes to compare, then proceed in chunks of 4 at + // a time using unaligned loads. + // + // Also, why do 4 byte loads instead of, say, 8 byte loads? The reason is + // that this particular version of memcmp is likely to be called with tiny + // needles. That means that if we do 8 byte loads, then a higher proportion + // of memcmp calls will use the slower variant above. With that said, this + // is a hypothesis and is only loosely supported by benchmarks. There's + // likely some improvement that could be made here. The main thing here + // though is to optimize for latency, not throughput. + + // SAFETY: Via the conditional above, we know that both `px` and `py` + // have the same length, so `px < pxend` implies that `py < pyend`. + // Thus, derefencing both `px` and `py` in the loop below is safe. + // + // Moreover, we set `pxend` and `pyend` to be 4 bytes before the actual + // end of of `px` and `py`. Thus, the final dereference outside of the + // loop is guaranteed to be valid. (The final comparison will overlap with + // the last comparison done in the loop for lengths that aren't multiples + // of four.) + // + // Finally, we needn't worry about alignment here, since we do unaligned + // loads. + unsafe { + let (mut px, mut py) = (x.as_ptr(), y.as_ptr()); + let (pxend, pyend) = (px.add(x.len() - 4), py.add(y.len() - 4)); + while px < pxend { + let vx = (px as *const u32).read_unaligned(); + let vy = (py as *const u32).read_unaligned(); + if vx != vy { + return false; + } + px = px.add(4); + py = py.add(4); + } + let vx = (pxend as *const u32).read_unaligned(); + let vy = (pyend as *const u32).read_unaligned(); + vx == vy + } +} diff --git a/src/memmem/vector.rs b/src/memmem/vector.rs new file mode 100644 index 0000000..a67d3c5 --- /dev/null +++ b/src/memmem/vector.rs @@ -0,0 +1,98 @@ +/// A trait for describing vector operations used by vectorized searchers. +/// +/// The trait is highly constrained to low level vector operations needed. In +/// general, it was invented mostly to be generic over x86's __m128i and +/// __m256i types. It's likely that once std::simd becomes a thing, we can +/// migrate to that since the operations required are quite simple. +/// +/// TODO: Consider moving this trait up a level and using it to implement +/// memchr as well. The trait might need to grow one or two methods, but +/// otherwise should be close to sufficient already. +/// +/// # Safety +/// +/// All methods are not safe since they are intended to be implemented using +/// vendor intrinsics, which are also not safe. Callers must ensure that the +/// appropriate target features are enabled in the calling function, and that +/// the current CPU supports them. All implementations should avoid marking the +/// routines with #[target_feature] and instead mark them as #[inline(always)] +/// to ensure they get appropriately inlined. (inline(always) cannot be used +/// with target_feature.) +pub(crate) trait Vector: Copy + core::fmt::Debug { + /// _mm_set1_epi8 or _mm256_set1_epi8 + unsafe fn splat(byte: u8) -> Self; + /// _mm_loadu_si128 or _mm256_loadu_si256 + unsafe fn load_unaligned(data: *const u8) -> Self; + /// _mm_movemask_epi8 or _mm256_movemask_epi8 + unsafe fn movemask(self) -> u32; + /// _mm_cmpeq_epi8 or _mm256_cmpeq_epi8 + unsafe fn cmpeq(self, vector2: Self) -> Self; + /// _mm_and_si128 or _mm256_and_si256 + unsafe fn and(self, vector2: Self) -> Self; +} + +#[cfg(target_arch = "x86_64")] +mod x86sse { + use super::Vector; + use core::arch::x86_64::*; + + impl Vector for __m128i { + #[inline(always)] + unsafe fn splat(byte: u8) -> __m128i { + _mm_set1_epi8(byte as i8) + } + + #[inline(always)] + unsafe fn load_unaligned(data: *const u8) -> __m128i { + _mm_loadu_si128(data as *const __m128i) + } + + #[inline(always)] + unsafe fn movemask(self) -> u32 { + _mm_movemask_epi8(self) as u32 + } + + #[inline(always)] + unsafe fn cmpeq(self, vector2: Self) -> __m128i { + _mm_cmpeq_epi8(self, vector2) + } + + #[inline(always)] + unsafe fn and(self, vector2: Self) -> __m128i { + _mm_and_si128(self, vector2) + } + } +} + +#[cfg(all(feature = "std", target_arch = "x86_64"))] +mod x86avx { + use super::Vector; + use core::arch::x86_64::*; + + impl Vector for __m256i { + #[inline(always)] + unsafe fn splat(byte: u8) -> __m256i { + _mm256_set1_epi8(byte as i8) + } + + #[inline(always)] + unsafe fn load_unaligned(data: *const u8) -> __m256i { + _mm256_loadu_si256(data as *const __m256i) + } + + #[inline(always)] + unsafe fn movemask(self) -> u32 { + _mm256_movemask_epi8(self) as u32 + } + + #[inline(always)] + unsafe fn cmpeq(self, vector2: Self) -> __m256i { + _mm256_cmpeq_epi8(self, vector2) + } + + #[inline(always)] + unsafe fn and(self, vector2: Self) -> __m256i { + _mm256_and_si256(self, vector2) + } + } +} diff --git a/src/memmem/x86/avx.rs b/src/memmem/x86/avx.rs new file mode 100644 index 0000000..ce168dd --- /dev/null +++ b/src/memmem/x86/avx.rs @@ -0,0 +1,139 @@ +#[cfg(not(feature = "std"))] +pub(crate) use self::nostd::Forward; +#[cfg(feature = "std")] +pub(crate) use self::std::Forward; + +#[cfg(feature = "std")] +mod std { + use core::arch::x86_64::{__m128i, __m256i}; + + use crate::memmem::{genericsimd, NeedleInfo}; + + /// An AVX accelerated vectorized substring search routine that only works + /// on small needles. + #[derive(Clone, Copy, Debug)] + pub(crate) struct Forward(genericsimd::Forward); + + impl Forward { + /// Create a new "generic simd" forward searcher. If one could not be + /// created from the given inputs, then None is returned. + pub(crate) fn new( + ninfo: &NeedleInfo, + needle: &[u8], + ) -> Option { + if !cfg!(memchr_runtime_avx) || !is_x86_feature_detected!("avx2") { + return None; + } + genericsimd::Forward::new(ninfo, needle).map(Forward) + } + + /// Returns the minimum length of haystack that is needed for this + /// searcher to work. Passing a haystack with a length smaller than + /// this will cause `find` to panic. + #[inline(always)] + pub(crate) fn min_haystack_len(&self) -> usize { + self.0.min_haystack_len::<__m128i>() + } + + #[inline(always)] + pub(crate) fn find( + &self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + // SAFETY: The only way a Forward value can exist is if the avx2 + // target feature is enabled. This is the only safety requirement + // for calling the genericsimd searcher. + unsafe { self.find_impl(haystack, needle) } + } + + /// The implementation of find marked with the appropriate target + /// feature. + /// + /// # Safety + /// + /// Callers must ensure that the avx2 CPU feature is enabled in the + /// current environment. + #[target_feature(enable = "avx2")] + unsafe fn find_impl( + &self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + if haystack.len() < self.0.min_haystack_len::<__m256i>() { + genericsimd::fwd_find::<__m128i>(&self.0, haystack, needle) + } else { + genericsimd::fwd_find::<__m256i>(&self.0, haystack, needle) + } + } + } +} + +// We still define the avx "forward" type on nostd to make caller code a bit +// simpler. This avoids needing a lot more conditional compilation. +#[cfg(not(feature = "std"))] +mod nostd { + use crate::memmem::NeedleInfo; + + #[derive(Clone, Copy, Debug)] + pub(crate) struct Forward(()); + + impl Forward { + pub(crate) fn new( + ninfo: &NeedleInfo, + needle: &[u8], + ) -> Option { + None + } + + pub(crate) fn min_haystack_len(&self) -> usize { + unreachable!() + } + + pub(crate) fn find( + &self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + unreachable!() + } + } +} + +#[cfg(all(test, feature = "std", not(miri)))] +mod tests { + use crate::memmem::{prefilter::PrefilterState, NeedleInfo}; + + fn find( + _: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], + ) -> Option { + super::Forward::new(ninfo, needle).unwrap().find(haystack, needle) + } + + #[test] + fn prefilter_permutations() { + use crate::memmem::prefilter::tests::PrefilterTest; + + if !is_x86_feature_detected!("avx2") { + return; + } + // SAFETY: The safety of find only requires that the current CPU + // support AVX2, which we checked above. + unsafe { + PrefilterTest::run_all_tests_filter(find, |t| { + // This substring searcher only works on certain configs, so + // filter our tests such that Forward::new will be guaranteed + // to succeed. (And also remove tests with a haystack that is + // too small.) + let fwd = match super::Forward::new(&t.ninfo, &t.needle) { + None => return false, + Some(fwd) => fwd, + }; + t.haystack.len() >= fwd.min_haystack_len() + }) + } + } +} diff --git a/src/memmem/x86/mod.rs b/src/memmem/x86/mod.rs new file mode 100644 index 0000000..c1cc73f --- /dev/null +++ b/src/memmem/x86/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod avx; +pub(crate) mod sse; diff --git a/src/memmem/x86/sse.rs b/src/memmem/x86/sse.rs new file mode 100644 index 0000000..22e7d99 --- /dev/null +++ b/src/memmem/x86/sse.rs @@ -0,0 +1,89 @@ +use core::arch::x86_64::__m128i; + +use crate::memmem::{genericsimd, NeedleInfo}; + +/// An SSE accelerated vectorized substring search routine that only works on +/// small needles. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Forward(genericsimd::Forward); + +impl Forward { + /// Create a new "generic simd" forward searcher. If one could not be + /// created from the given inputs, then None is returned. + pub(crate) fn new(ninfo: &NeedleInfo, needle: &[u8]) -> Option { + if !cfg!(memchr_runtime_sse2) { + return None; + } + genericsimd::Forward::new(ninfo, needle).map(Forward) + } + + /// Returns the minimum length of haystack that is needed for this searcher + /// to work. Passing a haystack with a length smaller than this will cause + /// `find` to panic. + #[inline(always)] + pub(crate) fn min_haystack_len(&self) -> usize { + self.0.min_haystack_len::<__m128i>() + } + + #[inline(always)] + pub(crate) fn find( + &self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + // SAFETY: sse2 is enabled on all x86_64 targets, so this is always + // safe to call. + unsafe { self.find_impl(haystack, needle) } + } + + /// The implementation of find marked with the appropriate target feature. + /// + /// # Safety + /// + /// This is safe to call in all cases since sse2 is guaranteed to be part + /// of x86_64. It is marked as unsafe because of the target feature + /// attribute. + #[target_feature(enable = "sse2")] + unsafe fn find_impl( + &self, + haystack: &[u8], + needle: &[u8], + ) -> Option { + genericsimd::fwd_find::<__m128i>(&self.0, haystack, needle) + } +} + +#[cfg(all(test, feature = "std", not(miri)))] +mod tests { + use crate::memmem::{prefilter::PrefilterState, NeedleInfo}; + + fn find( + _: &mut PrefilterState, + ninfo: &NeedleInfo, + haystack: &[u8], + needle: &[u8], + ) -> Option { + super::Forward::new(ninfo, needle).unwrap().find(haystack, needle) + } + + #[test] + fn prefilter_permutations() { + use crate::memmem::prefilter::tests::PrefilterTest; + + // SAFETY: sse2 is enabled on all x86_64 targets, so this is always + // safe to call. + unsafe { + PrefilterTest::run_all_tests_filter(find, |t| { + // This substring searcher only works on certain configs, so + // filter our tests such that Forward::new will be guaranteed + // to succeed. (And also remove tests with a haystack that is + // too small.) + let fwd = match super::Forward::new(&t.ninfo, &t.needle) { + None => return false, + Some(fwd) => fwd, + }; + t.haystack.len() >= fwd.min_haystack_len() + }) + } + } +} diff --git a/src/tests/memchr/memchr.rs b/src/tests/memchr/memchr.rs index 4dc52a2..ac955ed 100644 --- a/src/tests/memchr/memchr.rs +++ b/src/tests/memchr/memchr.rs @@ -1,7 +1,9 @@ use quickcheck::quickcheck; use crate::{ - fallback, memchr, memchr2, memchr3, memrchr, memrchr2, memrchr3, naive, + memchr, + memchr::{fallback, naive}, + memchr2, memchr3, memrchr, memrchr2, memrchr3, tests::memchr::testdata::memchr_tests, }; diff --git a/src/x86/mod.rs b/src/x86/mod.rs deleted file mode 100644 index 27f1bab..0000000 --- a/src/x86/mod.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::fallback; - -// We only use AVX when we can detect at runtime whether it's available, which -// requires std. -#[cfg(feature = "std")] -mod avx; -mod sse2; - -// This macro employs a gcc-like "ifunc" trick where by upon first calling -// `memchr` (for example), CPU feature detection will be performed at runtime -// to determine the best implementation to use. After CPU feature detection -// is done, we replace `memchr`'s function pointer with the selection. Upon -// subsequent invocations, the CPU-specific routine is invoked directly, which -// skips the CPU feature detection and subsequent branch that's required. -// -// While this typically doesn't matter for rare occurrences or when used on -// larger haystacks, `memchr` can be called in tight loops where the overhead -// of this branch can actually add up *and is measurable*. This trick was -// necessary to bring this implementation up to glibc's speeds for the 'tiny' -// benchmarks, for example. -// -// At some point, I expect the Rust ecosystem will get a nice macro for doing -// exactly this, at which point, we can replace our hand-jammed version of it. -// -// N.B. The ifunc strategy does prevent function inlining of course, but on -// modern CPUs, you'll probably end up with the AVX2 implementation, which -// probably can't be inlined anyway---unless you've compiled your entire -// program with AVX2 enabled. However, even then, the various memchr -// implementations aren't exactly small, so inlining might not help anyway! -#[cfg(feature = "std")] -macro_rules! ifunc { - ($fnty:ty, $name:ident, $haystack:ident, $($needle:ident),+) => {{ - use std::mem; - use std::sync::atomic::{AtomicPtr, Ordering}; - - type FnRaw = *mut (); - - static FN: AtomicPtr<()> = AtomicPtr::new(detect as FnRaw); - - fn detect($($needle: u8),+, haystack: &[u8]) -> Option { - let fun = - if cfg!(memchr_runtime_avx) && is_x86_feature_detected!("avx2") { - avx::$name as FnRaw - } else if cfg!(memchr_runtime_sse2) { - sse2::$name as FnRaw - } else { - fallback::$name as FnRaw - }; - FN.store(fun as FnRaw, Ordering::Relaxed); - unsafe { - mem::transmute::(fun)($($needle),+, haystack) - } - } - - unsafe { - let fun = FN.load(Ordering::Relaxed); - mem::transmute::(fun)($($needle),+, $haystack) - } - }} -} - -// When std isn't available to provide runtime CPU feature detection, or if -// runtime CPU feature detection has been explicitly disabled, then just call -// our optimized SSE2 routine directly. SSE2 is avalbale on all x86_64 targets, -// so no CPU feature detection is necessary. -#[cfg(not(feature = "std"))] -macro_rules! ifunc { - ($fnty:ty, $name:ident, $haystack:ident, $($needle:ident),+) => {{ - if cfg!(memchr_runtime_sse2) { - unsafe { sse2::$name($($needle),+, $haystack) } - } else { - fallback::$name($($needle),+, $haystack) - } - }} -} - -#[inline(always)] -pub fn memchr(n1: u8, haystack: &[u8]) -> Option { - ifunc!(fn(u8, &[u8]) -> Option, memchr, haystack, n1) -} - -#[inline(always)] -pub fn memchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { - ifunc!(fn(u8, u8, &[u8]) -> Option, memchr2, haystack, n1, n2) -} - -#[inline(always)] -pub fn memchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - ifunc!( - fn(u8, u8, u8, &[u8]) -> Option, - memchr3, - haystack, - n1, - n2, - n3 - ) -} - -#[inline(always)] -pub fn memrchr(n1: u8, haystack: &[u8]) -> Option { - ifunc!(fn(u8, &[u8]) -> Option, memrchr, haystack, n1) -} - -#[inline(always)] -pub fn memrchr2(n1: u8, n2: u8, haystack: &[u8]) -> Option { - ifunc!(fn(u8, u8, &[u8]) -> Option, memrchr2, haystack, n1, n2) -} - -#[inline(always)] -pub fn memrchr3(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option { - ifunc!( - fn(u8, u8, u8, &[u8]) -> Option, - memrchr3, - haystack, - n1, - n2, - n3 - ) -}