- Commit
- fbd0555b91f701ea72f6027d4d7d7a1c36540ffd
- Parent
- adfd52d53c6f4a6b1e0a0dd1cbf5b06f0afdf470
- Author
- Gark Garcia <37553739+GarkGarcia@users.noreply.github.com>
- Date
Implemented multi-threading functionality.
An exercise on polyglossy: the same problem solved on multiple languages
Implemented multi-threading functionality.
3 files changed, 110 insertions, 126 deletions
Status | File Name | N° Changes | Insertions | Deletions |
Modified | Cargo.lock | 49 | 37 | 12 |
Modified | Cargo.toml | 5 | 2 | 3 |
Modified | src/main.rs | 182 | 71 | 111 |
diff --git a/Cargo.lock b/Cargo.lock @@ -2,30 +2,55 @@ name = "conjecture_tester" version = "0.1.0" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossterm 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "crossterm" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "termios" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "winapi" -version = "0.2.8" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "winapi-build" -version = "0.1.1" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum crossterm 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3069b1b614f818b56d12eabb91d3fe39bfedb40d99f111b07969ac86039ce60e" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml @@ -4,5 +4,4 @@ version = "0.1.0" authors = ["Gark Garcia <37553739+GarkGarcia@users.noreply.github.com>"] [dependencies] -winapi = "0.2.8" -kernel32-sys = "0.2.1"- \ No newline at end of file +crossterm = "0.4.0"+ \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs @@ -3,28 +3,28 @@ // Let S: N -> N be the sum of the digits of a positive integer. // For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an interger. -extern crate kernel32; -extern crate winapi; - -use winapi::HANDLE; -use winapi::wincon::CONSOLE_SCREEN_BUFFER_INFO; -use winapi::wincon::COORD; -use winapi::wincon::SMALL_RECT; -use winapi::WORD; -use winapi::DWORD; -use std::io::stdin; +extern crate crossterm; -static mut CONSOLE_HANDLE: Option<HANDLE> = None; +use std::io::stdin; +use std::sync::mpsc::{Sender, Receiver}; +use std::sync::mpsc; +use std::thread; +use std::ops::Range; +use crossterm::terminal::{terminal,ClearType}; +use crossterm::Screen; fn main() { + let screen = Screen::default(); + let prompt = terminal(&screen); + let mut user_input = String::new(); - println!(" This program is a simple test for the following conjecture: + println!("This program is a simple test for the following conjecture: - Let S: N -> N be the sum of the digits of a positive integer. - For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an interger. +Let S: N -> N be the sum of the digits of a positive integer. +For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an interger. - What value would you like to test the conjecture for?"); +What value would you like to test the conjecture for?"); // Listen for user input stdin().read_line(&mut user_input).expect("Did not enter a correct string"); @@ -32,18 +32,20 @@ fn main() { // If the user input is a valid int if !input_parsing_result.is_err() { + println!("\nLOADING..."); + let max = input_parsing_result.unwrap().abs(); - let counter_examples = get_counter_expl(max); + let counterexpls = get_all_countrexpls(max); // Print the results - clear_console(); - if counter_examples.len() == 0 { + prompt.clear(ClearType::CurrentLine); + if counterexpls.len() == 0 { println!("The conjecture is proved for all natural numbers smaller or equals to {}!", max); } else { println!("The conjecture is disproved! Here are the counter examples:"); - for pair in counter_examples { - println!("{} and {};", pair[0], pair[1]); + for pair in counterexpls { + println!("{} and {}", pair[0], pair[1]); } } } else { @@ -51,121 +53,79 @@ fn main() { } } -// Test the conjecture for all values up to max and return the counterexamples -fn get_counter_expl(max : i32) -> Vec<[i32; 2]> { - let mut counter_examples : Vec<[i32; 2]> = Vec::new(); - let mut load_bar = 0; +fn get_all_countrexpls(max: i32) -> Vec<[i32; 2]> { + + if max > 1000 { + + // Thread related variables + let (coutexpl_sender, coutexpl_reciever): (Sender<Vec<[i32; 2]>>, Receiver<Vec<[i32; 2]>>) = mpsc::channel(); + let mut child_threads = Vec::new(); + let n_threads = 10; + let range_lenght = ((max as f32) / n_threads as f32).ceil() as i32; + + // Conjecture related variables + let mut counterexpls: Vec<[i32; 2]> = Vec::new(); + + for i in 0..n_threads { + let thread_countr_sd = coutexpl_sender.clone(); + let end = std::cmp::min(i * (range_lenght + 1) + range_lenght, max); + let range = Range {start: i * (range_lenght + 1), end: end}; + + let child = thread::spawn(move || { + thread_countr_sd.send(get_range_countrexpls(range, max)) + .expect("The thread was unable to sent a message trought the channel"); + }); + child_threads.push(child); + } - for a in 0..max { + for _ in 0..n_threads { + counterexpls.append(&mut coutexpl_reciever.recv().unwrap()); + } - // Print the progress on the screen - let new_load_bar = a * 100 / max; - if new_load_bar != load_bar { - load_bar = new_load_bar; - clear_console(); - println!("LOADING: {}%", new_load_bar); + for child in child_threads { + child.join().expect("Child thread panicked"); } + return counterexpls; + + } else { + return get_range_countrexpls(0..max, max); + } +} + +fn get_range_countrexpls(range: Range<i32>, max: i32) -> Vec<[i32; 2]> { + let mut counterexpls = Vec::new(); + + for a in range { for b in a..max { - let difference : i32 = sum_digits(a + b) - sum_digits(a) - sum_digits(b); + let difference: i32 = sum_digits(a + b) - sum_digits(a) - sum_digits(b); if !is_multiple_of_nine(difference) { - counter_examples.push([a, b]); + counterexpls.push([a, b]); } } } - return counter_examples; + return counterexpls; } -fn is_multiple_of_nine(n : i32) -> bool { +fn is_multiple_of_nine(n: i32) -> bool { let n_float = n as f32; return (n_float/9f32) % 1f32 == 0f32; } -fn get_digits(n : i32) -> Vec<u32> { +fn get_digits(n: i32) -> Vec<u32> { return n.to_string().chars().map(|d| d.to_digit(10).unwrap()).collect(); } -fn sum_digits(n : i32) -> i32 { - let mut sum : i32 = 0i32; +fn sum_digits(n: i32) -> i32 { + let mut sum = 0; for d in get_digits(n) { - let d_ = d as i32; - sum += d_; + let _d = d as i32; + sum += _d; } return sum; } - - -// Console releted code: - -fn get_output_handle() -> HANDLE { - unsafe { - if let Some(handle) = CONSOLE_HANDLE { - return handle; - } else { - let handle = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE); - CONSOLE_HANDLE = Some(handle); - return handle; - } - } -} - -fn get_buffer_info() -> winapi::CONSOLE_SCREEN_BUFFER_INFO { - let handle = get_output_handle(); - if handle == winapi::INVALID_HANDLE_VALUE { - panic!("NoConsole") - } - let mut buffer = CONSOLE_SCREEN_BUFFER_INFO { - dwSize: COORD { X: 0, Y: 0 }, - dwCursorPosition: COORD { X: 0, Y: 0 }, - wAttributes: 0 as WORD, - srWindow: SMALL_RECT { - Left: 0, - Top: 0, - Right: 0, - Bottom: 0, - }, - dwMaximumWindowSize: COORD { X: 0, Y: 0 }, - }; - unsafe { - kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer); - } - buffer -} - -fn clear_console() { - let handle = get_output_handle(); - if handle == winapi::INVALID_HANDLE_VALUE { - panic!("NoConsole") - } - - let screen_buffer = get_buffer_info(); - let console_size: DWORD = screen_buffer.dwSize.X as u32 * screen_buffer.dwSize.Y as u32; - let coord_screen = COORD { X: 0, Y: 0 }; - - let mut amount_chart_written: DWORD = 0; - unsafe { - kernel32::FillConsoleOutputCharacterW( - handle, - 32 as winapi::WCHAR, - console_size, - coord_screen, - &mut amount_chart_written, - ); - } - set_cursor_possition(0, 0); -} - -fn set_cursor_possition(y: i16, x: i16) { - let handle = get_output_handle(); - if handle == winapi::INVALID_HANDLE_VALUE { - panic!("NoConsole") - } - unsafe { - kernel32::SetConsoleCursorPosition(handle, COORD { X: x, Y: y }); - } -}