From 60af0afba65853c9d56126da27e781047f5b19fd Mon Sep 17 00:00:00 2001 From: Mattrixwv Date: Fri, 12 Jun 2020 19:26:17 -0400 Subject: [PATCH] Initial commit with a few functions --- .gitignore | 6 ++ Cargo.toml | 11 ++++ src/Algorithms.rs | 41 +++++++++++++ src/Stopwatch.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 71 +++++++++++++++++++++++ 5 files changed, 272 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/Algorithms.rs create mode 100644 src/Stopwatch.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f4bcff --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +#vscode +.vscode/ + +#build files +target/ +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6a29c84 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "myClasses" +version = "0.1.0" +authors = ["Mattrixwv "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +num = "0.2.1" +assert_approx_eq = "1.1.0" diff --git a/src/Algorithms.rs b/src/Algorithms.rs new file mode 100644 index 0000000..681fa79 --- /dev/null +++ b/src/Algorithms.rs @@ -0,0 +1,41 @@ +extern crate num; + + +pub fn getAllFib(goalNumber: u64) -> Vec{ + let mut fibNums = Vec::new(); //A list to save the Fibonacci numbers + //If the number is <= 0 return an empty list + if(goalNumber <= 0){ + return fibNums; + } + + //This means that at least 2 1's are elements + fibNums.push(1); + fibNums.push(1); + + //Loop to generate the rest of the Fibonacci numbers + while(fibNums[fibNums.len() - 1] <= goalNumber){ + fibNums.push(fibNums[fibNums.len() - 1] + fibNums[fibNums.len() - 2]); + } + //At this point the most recent number is > goalNumber, so remove it and return the rest of the list + fibNums.remove(fibNums.len() - 1); + return fibNums; +} + +pub fn getAllFibBig(goalNumber: num::BigInt) -> Vec{ + let mut fibNums = Vec::new(); //A list to save the Fibonacci numbers in + //If the number is <= 0 return an empty list + if(goalNumber <= num::BigInt::from(0)){ + return fibNums; + } + + //This means that at least 2 1's are elements + fibNums.push(num::BigInt::from(1)); + fibNums.push(num::BigInt::from(1)); + + while(fibNums[fibNums.len() - 1] <= goalNumber){ + fibNums.push(&fibNums[fibNums.len() - 1] + &fibNums[fibNums.len() - 2]); + } + //At this point the most recent number is > goalNumber, so remove it and return the rest of the list + fibNums.remove(fibNums.len() - 1); + return fibNums; +} diff --git a/src/Stopwatch.rs b/src/Stopwatch.rs new file mode 100644 index 0000000..9c27641 --- /dev/null +++ b/src/Stopwatch.rs @@ -0,0 +1,143 @@ + + +enum TimeResolution{NANOSECOND, MICROSECOND, MILLISECOND, SECOND, MINUTE, HOUR, SIZE} + +pub struct Stopwatch{ + startTime: std::time::Instant, + stopTime: std::time::Instant, + hasStarted: bool, + hasStopped: bool, +} +impl Stopwatch{ + //Constructor. Returns a new, blank Stopwatch + pub fn new() -> Stopwatch{ + let timer = Stopwatch{startTime: std::time::Instant::now(), stopTime: std::time::Instant::now(), hasStarted: false, hasStopped: false}; + timer + } + //Returns a long with the elapsed time in nanoseconds. Used by other functions to get the time before converting it to the correct resolution + fn getTime(&self) -> std::time::Duration{ + //If the Stopwatch hasn't been started yet + if(!self.hasStarted){ + //TODO: This should throw an exception instead of returning 0 + return std::time::Duration::new(0, 0); + } + //If the Stopwatch was started but not stopped use the current time as stopTime + else if(!self.hasStopped){ + return std::time::Instant::now().duration_since(self.startTime); + } + //If the Stopwatch was started and stopped + else{ + return self.stopTime.duration_since(self.startTime); + } + } + //Start the Stopwatch + //Because of how this is implemented if one restarts the stopwatch it resets itself + pub fn start(&mut self){ + //Start the Stopwatch + self.hasStarted = true; + //It hasn't been stopped yet + self.hasStopped = false; + //Put this last to ensure that the time recorded is as close to the return time as possible + self.startTime = std::time::Instant::now(); + } + pub fn stop(&mut self){ + //Put this first to ensure the time recorded is as close to the call time as possible + let tempTime = std::time::Instant::now(); + //Make sure that the Stopwatch has started before it can be stopped + if(self.hasStarted && !self.hasStopped){ + //Set the stop time + self.stopTime = tempTime; + //Record that stop has been called + self.hasStopped = true; + } + //If the stopwatch hasn't been started throw an exception + else if(!self.hasStarted){ + //TODO: An exception should be thrown here + } + //If the stopwatch has already been stopped throw an exception + else if(self.hasStopped){ + //TODO: An exception should be thrown here + } + } + pub fn getNano(&self) -> u128{ + return self.getTime().as_nanos(); + } + pub fn getMicro(&self) -> u128{ + return self.getTime().as_micros(); + } + pub fn getMilli(&self) -> u128{ + return self.getTime().as_millis(); + } + pub fn getSeconds(&self) -> u64{ + return self.getTime().as_secs(); + } + pub fn getMinutes(&self) -> f64{ + return self.getTime().as_secs_f64() / 60.0; + } + pub fn getHours(&self) -> f64{ + return self.getTime().as_secs_f64() / 3600.0; + } + pub fn getString(&self) -> String{ + //Get the time in the most granular form possible + let mut duration = self.getNano() as f64; + let mut timeRes = TimeResolution::NANOSECOND as i32; + //Reduce the number until it has the appropriate number of digits. (xxx.xxx) + //This loop works down to seconds + while((timeRes < TimeResolution::SECOND as i32) && (duration >= 1000.0)){ + duration /= 1000.0; + timeRes += 1; + } + //Check if the duration needs reduced to minutes + if(duration >= 1000.0){ + duration /= 60.0; + timeRes = TimeResolution::MINUTE as i32; + } + //Check if the duration needs reduced to hours + if(duration >= 1000.0){ + duration /= 60.0; + timeRes = TimeResolution::HOUR as i32; + } + + //Turn the number into a string + let mut time = format!("{:0.3} ", duration); + //Doing this with an if/else if statement because case doesn't exist and match doesn't do what I need it to + if(timeRes == TimeResolution::NANOSECOND as i32){ + time += "nanoseconds"; + } + else if(timeRes == TimeResolution::MICROSECOND as i32){ + time += "microseconds"; + } + else if(timeRes == TimeResolution::MILLISECOND as i32){ + time += "milliseconds"; + } + else if(timeRes == TimeResolution::SECOND as i32){ + time += "seconds"; + } + else if(timeRes == TimeResolution::MINUTE as i32){ + time += "minutes"; + } + else if(timeRes == TimeResolution::HOUR as i32){ + time += "hours"; + } + else{ + time = "There was an error in getStr".to_string(); + } + + return time; + } + pub fn reset(&mut self){ + self.hasStarted = false; + self.hasStopped = false; + //Set the times equal to each other for a duration of 0 + self.startTime = std::time::Instant::now(); + self.stopTime = self.startTime; + } + pub fn to_string(&self) -> String{ + return self.getString(); + } +} +impl std::fmt::Display for Stopwatch{ + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result{ + write!(f, "{}", self.getString()) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..386aed3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,71 @@ +#![allow(non_snake_case)] +#![allow(unused_parens)] +#![allow(dead_code)] + + +extern crate num; +extern crate assert_approx_eq; + +pub mod Stopwatch; +pub mod Algorithms; + + +#[cfg(test)] +mod StopwatchTests{ + #[test] + fn testStartStop(){ + let mut timer = super::Stopwatch::Stopwatch::new(); + timer.start(); + timer.stop(); + //If it gets to here without panicing everything went well + } + #[test] + fn testConversion(){ + let mut timer = super::Stopwatch::Stopwatch::new(); + let mut sum = 0i64; + //Start the timer + timer.start(); + //Do something to run some time + for cnt in 0..100_000{ + sum += cnt; + } + //Stop the timer + timer.stop(); + //Asser something so the sum isn't ignored during compile + assert_ne!(sum, 0); + //Check that the different resolutions work out correctly + let nano = timer.getNano(); + assert_eq!(timer.getMicro(), (nano / 1000)); + assert_eq!(timer.getMilli(), (nano / 1000000)); + assert_eq!(timer.getSeconds(), (nano / 1000000000) as u64); + super::assert_approx_eq::assert_approx_eq!(timer.getMinutes(), (nano as f64 / 60000000000.0)); + super::assert_approx_eq::assert_approx_eq!(timer.getHours(), (nano as f64 / 3600000000000.0)); + } +} + +#[cfg(test)] +mod AlgorithmsTests{ + #[test] + fn testGetAllFib(){ + //Test 1 + let mut correctAnswer1 = Vec::new(); + correctAnswer1.extend_from_slice(&[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]); + let highestNumber1 = 100; + let answer1 = super::Algorithms::getAllFib(highestNumber1); + assert_eq!(correctAnswer1, answer1); + + //Test 2 + let mut correctAnswer2 = Vec::new(); + correctAnswer2.extend_from_slice(&[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]); + let highestNumber2 = 1000; + let answer2 = super::Algorithms::getAllFib(highestNumber2); + assert_eq!(correctAnswer2, answer2); + + //Test3 + let mut correctAnswerBig = Vec::new(); + correctAnswerBig.extend_from_slice(&[num::BigInt::from(1), num::BigInt::from(1), num::BigInt::from(2), num::BigInt::from(3), num::BigInt::from(5), num::BigInt::from(8), num::BigInt::from(13), num::BigInt::from(21), num::BigInt::from(34), num::BigInt::from(55), num::BigInt::from(89)]); + let highestNumberBig = num::BigInt::from(100); + let answerBig = super::Algorithms::getAllFibBig(highestNumberBig); + assert_eq!(correctAnswerBig, answerBig); + } +}