Compare commits
6 Commits
better-cla
...
master
Author | SHA1 | Date |
---|---|---|
Dorian | b13cab107b | |
Dorian | 85bd911959 | |
Dorian | 4d8777a9af | |
Dorian | 5c53942b62 | |
Dorian | 57bfde36c0 | |
Dorian | b6943545be |
10
Cargo.toml
10
Cargo.toml
|
@ -7,7 +7,11 @@ license = "Apache-2.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "unit_converter"
|
name = "unit_converter"
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies.pyo3]
|
||||||
pyo3 = { version = "0.8", features = ["extension-module"] }
|
version = "0.8"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
extension-module = ["pyo3/extension-module"]
|
||||||
|
default = ["extension-module"]
|
||||||
|
|
|
@ -20,8 +20,13 @@ Insure the following dependencies are in place:
|
||||||
1. Build the rust crate first: `cargo build`
|
1. Build the rust crate first: `cargo build`
|
||||||
1. Install dependencies and run in a virtualenv: `pipenv install && pipenv shell`
|
1. Install dependencies and run in a virtualenv: `pipenv install && pipenv shell`
|
||||||
1. Create the Python package with: `maturin build`
|
1. Create the Python package with: `maturin build`
|
||||||
1. Run the tests: `pytest test.py`
|
1. Run the Python tests: `pytest test.py batch_test.py`
|
||||||
|
1. Run the Rust test: `cargo test --no-default-features`
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
* [PyO3 Python - Rust bindings](https://pyo3.rs/master/get_started.html)
|
* [PyO3 Python - Rust bindings](https://pyo3.rs/master/get_started.html)
|
||||||
|
* Windchill calculations:
|
||||||
|
* [PDF from US Gov](https://www.weather.gov/media/epz/wxcalc/windChill.pdf)
|
||||||
|
* [Calculation in Celsius and kph](https://www.calcunation.com/calculator/wind-chill-celsius.php)
|
||||||
|
* [Windchill Calculator](https://www.weather.gov/epz/wxcalc_windchill)
|
||||||
|
|
|
@ -21,4 +21,4 @@ def test_using_python_batch(benchmark, batch_numbers):
|
||||||
|
|
||||||
|
|
||||||
def test_using_rust_batch(benchmark, batch_numbers):
|
def test_using_rust_batch(benchmark, batch_numbers):
|
||||||
benchmark(unit_converter.batch_convert_celsius_to_fahrenheit, batch_numbers)
|
benchmark(unit_converter.batch_convert_to_fahrenheit, batch_numbers)
|
||||||
|
|
47
src/lib.rs
47
src/lib.rs
|
@ -5,33 +5,64 @@ extern crate pyo3;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
#[pyclass(module = "unit_converter")]
|
||||||
|
struct Temperature {
|
||||||
|
celsius: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl Temperature {
|
||||||
|
#[new]
|
||||||
|
fn new(obj: &PyRawObject, temperature: f32) {
|
||||||
|
obj.init(Temperature {
|
||||||
|
celsius: temperature,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_fahrenheit(&self) -> f32 {
|
||||||
|
self.celsius * 1.8 + 32.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn windchill(&self, wind_speed_kph: f32) -> f32 {
|
||||||
|
13.12 + (0.6215 * self.celsius) - (11.37 * wind_speed_kph.powf(0.16))
|
||||||
|
+ (0.3965 * self.celsius * wind_speed_kph.powf(0.16))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn convert_celsius_to_fahrenheit(celsius: f32) -> f32 {
|
fn convert_to_fahrenheit(celsius: f32) -> f32 {
|
||||||
celsius * 1.8 + 32.0
|
celsius * 1.8 + 32.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn batch_convert_celsius_to_fahrenheit(celsius: Vec<f32>) -> Vec<f32> {
|
fn batch_convert_to_fahrenheit(celsius: Vec<f32>) -> Vec<f32> {
|
||||||
celsius
|
celsius
|
||||||
.iter()
|
.iter()
|
||||||
.map(|temperature| convert_celsius_to_fahrenheit(temperature.clone()))
|
.map(|temperature| convert_to_fahrenheit(temperature.clone()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn unit_converter(_py: Python, m: &PyModule) -> PyResult<()> {
|
fn unit_converter(_py: Python, module: &PyModule) -> PyResult<()> {
|
||||||
m.add_wrapped(wrap_pyfunction!(convert_celsius_to_fahrenheit))?;
|
module.add_wrapped(wrap_pyfunction!(convert_to_fahrenheit))?;
|
||||||
m.add_wrapped(wrap_pyfunction!(batch_convert_celsius_to_fahrenheit))?;
|
module.add_wrapped(wrap_pyfunction!(batch_convert_to_fahrenheit))?;
|
||||||
|
module.add_class::<Temperature>()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::convert_celsius_to_fahrenheit;
|
use super::{convert_to_fahrenheit, Temperature};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn conversion_celsius_to_fahrenheit() {
|
fn conversion_celsius_to_fahrenheit() {
|
||||||
assert_eq!(convert_celsius_to_fahrenheit(25.0), 77.0);
|
assert_eq!(convert_to_fahrenheit(25.0), 77.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn windchill_test() {
|
||||||
|
let temperature = Temperature{ celsius: -20.0 };
|
||||||
|
assert_eq!(temperature.windchill(32.0).round(), -33.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
test.py
15
test.py
|
@ -7,22 +7,23 @@ def python_unit_converter(celsius):
|
||||||
return celsius * 1.8 + 32.0
|
return celsius * 1.8 + 32.0
|
||||||
|
|
||||||
|
|
||||||
def batch_python_unit_converter(temperatures):
|
|
||||||
return [celsius * 1.8 + 32.0 for celsius in temperatures]
|
|
||||||
|
|
||||||
|
|
||||||
def test_using_unit_converter():
|
def test_using_unit_converter():
|
||||||
assert unit_converter.convert_celsius_to_fahrenheit(25.0) == 77.0
|
assert unit_converter.convert_to_fahrenheit(25.0) == 77.0
|
||||||
assert python_unit_converter(25.0) == 77.0
|
assert python_unit_converter(25.0) == 77.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_windchill():
|
||||||
|
temperature = unit_converter.Temperature(-20.0)
|
||||||
|
assert round(temperature.windchill(32.0), 1) == -32.9
|
||||||
|
|
||||||
|
|
||||||
def test_using_python_constant(benchmark):
|
def test_using_python_constant(benchmark):
|
||||||
result = benchmark(python_unit_converter, 25.0)
|
result = benchmark(python_unit_converter, 25.0)
|
||||||
assert round(result, 3) == round(77.0, 3)
|
assert round(result, 3) == round(77.0, 3)
|
||||||
|
|
||||||
|
|
||||||
def test_using_rust_constant(benchmark):
|
def test_using_rust_constant(benchmark):
|
||||||
result = benchmark(unit_converter.convert_celsius_to_fahrenheit, 25.0)
|
result = benchmark(unit_converter.convert_to_fahrenheit, 25.0)
|
||||||
assert round(result, 3) == round(77.0, 3)
|
assert round(result, 3) == round(77.0, 3)
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,5 +35,5 @@ def test_using_python(benchmark):
|
||||||
|
|
||||||
def test_using_rust(benchmark):
|
def test_using_rust(benchmark):
|
||||||
temperature = random.random() * 100
|
temperature = random.random() * 100
|
||||||
result = benchmark(unit_converter.convert_celsius_to_fahrenheit, temperature)
|
result = benchmark(unit_converter.convert_to_fahrenheit, temperature)
|
||||||
assert round(result, 3) == round(python_unit_converter(temperature), 3)
|
assert round(result, 3) == round(python_unit_converter(temperature), 3)
|
||||||
|
|
Loading…
Reference in New Issue