Skip to content

Commit 7179bc8

Browse files
initial electronics module
initial coulombs_law module with tests
1 parent 7f5b659 commit 7179bc8

File tree

3 files changed

+189
-0
lines changed

3 files changed

+189
-0
lines changed

src/electronics/coulombs_law.rs

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/// Apply Coulomb's Law on any three given values. These can be force, charge1,
2+
/// charge2, or distance, and then in a Python dict return name/value pair of
3+
/// the zero value.
4+
///
5+
/// Coulomb's Law states that the magnitude of the electrostatic force of
6+
/// attraction or repulsion between two point charges is directly proportional
7+
/// to the product of the magnitudes of charges and inversely proportional to
8+
/// the square of the distance between them.
9+
const COULOMBS_CONSTANT: f64 = 8.9875517923e9;
10+
#[derive(PartialEq, Eq, Debug)]
11+
pub enum CoulombsLawError {
12+
ExtraZeroArg(String),
13+
NegativeDistance(String),
14+
NoneZeroArg(String),
15+
}
16+
pub fn coulombs_law(
17+
force: f64,
18+
charge1: f64,
19+
charge2: f64,
20+
distance: f64,
21+
) -> Result<String, CoulombsLawError> {
22+
let charge_product = (charge1 * charge2).abs();
23+
24+
if invalid_arguments(force, charge1, charge2, distance) {
25+
return Err(CoulombsLawError::ExtraZeroArg(String::from(
26+
"One and only one argument must be 0",
27+
)));
28+
}
29+
30+
if distance < 0.0 {
31+
return Err(CoulombsLawError::NegativeDistance(String::from(
32+
"Distance cannot be negative",
33+
)));
34+
}
35+
36+
if force == 0.0 {
37+
return Ok(format!(
38+
"force: {}",
39+
calculate_force(charge_product, distance)
40+
));
41+
} else if charge1 == 0.0 {
42+
return Ok(format!(
43+
"charge1: {}",
44+
calculate_charge(charge2, force, distance)
45+
));
46+
} else if charge2 == 0.0 {
47+
return Ok(format!(
48+
"charge2: {}",
49+
calculate_charge(charge1, force, distance)
50+
));
51+
} else if distance == 0.0 {
52+
return Ok(format!(
53+
"distance: {}",
54+
calculate_distance(charge_product, force)
55+
));
56+
}
57+
58+
Err(CoulombsLawError::NoneZeroArg(String::from(
59+
"Exactly one argument must be 0",
60+
)))
61+
}
62+
fn calculate_distance(charge_product: f64, force: f64) -> f64 {
63+
(COULOMBS_CONSTANT * charge_product / force.abs()).sqrt()
64+
}
65+
fn calculate_charge(charge: f64, force: f64, distance: f64) -> f64 {
66+
force.abs() * distance.powi(2) / (COULOMBS_CONSTANT * charge)
67+
}
68+
fn calculate_force(charge_product: f64, distance: f64) -> f64 {
69+
COULOMBS_CONSTANT * charge_product / distance.powi(2)
70+
}
71+
72+
fn invalid_arguments(force: f64, charge1: f64, charge2: f64, distance: f64) -> bool {
73+
[force, charge1, charge2, distance]
74+
.iter()
75+
.filter(|&&x| x == 0.0)
76+
.count()
77+
!= 1
78+
}
79+
80+
#[cfg(test)]
81+
mod tests {
82+
use super::*;
83+
84+
macro_rules! test_calculate_force {
85+
($($name:ident: $inputs:expr,)*) => {
86+
$(
87+
#[test]
88+
fn $name() {
89+
let ((charge_product,distance), expected) = $inputs;
90+
assert_eq!(calculate_force(charge_product,distance), expected);
91+
}
92+
)*
93+
}
94+
}
95+
96+
macro_rules! test_calculate_charge {
97+
($($name:ident: $inputs:expr,)*) => {
98+
$(
99+
#[test]
100+
fn $name() {
101+
let ((charge,force,distance), expected) = $inputs;
102+
assert_eq!(calculate_charge(charge,force,distance), expected);
103+
}
104+
)*
105+
}
106+
}
107+
macro_rules! test_calculate_distance {
108+
($($name:ident: $inputs:expr,)*) => {
109+
$(
110+
#[test]
111+
fn $name() {
112+
let ((charge_product,force), expected) = $inputs;
113+
assert_eq!(calculate_distance(charge_product,force), expected);
114+
}
115+
)*
116+
}
117+
}
118+
119+
macro_rules! test_invalid_arguments {
120+
($($name:ident: $inputs:expr,)*) => {
121+
$(
122+
#[test]
123+
fn $name() {
124+
let ((force,charge1,charge2,distance), expected) = $inputs;
125+
assert_eq!(invalid_arguments(force,charge1,charge2,distance), expected);
126+
}
127+
)*
128+
}
129+
}
130+
macro_rules! test_coulombs_law {
131+
($($name:ident: $inputs:expr,)*) => {
132+
$(
133+
#[test]
134+
fn $name() {
135+
let ((force,charge1,charge2,distance), expected) = $inputs;
136+
assert_eq!(coulombs_law(force,charge1,charge2,distance).unwrap(), String::from(expected));
137+
}
138+
)*
139+
}
140+
}
141+
142+
macro_rules! test_coulombs_law_err {
143+
($($name:ident: $inputs:expr,)*) => {
144+
$(
145+
#[test]
146+
fn $name() {
147+
let ((force,charge1,charge2,distance), expected) = $inputs;
148+
assert_eq!(coulombs_law(force,charge1,charge2,distance).unwrap_err(), expected);
149+
}
150+
)*
151+
}
152+
}
153+
154+
test_coulombs_law! {
155+
general_inputs1:((0.0, 3.0, 5.0, 2000.0), "force: 33703.319221125"),
156+
general_inputs2:((10.0, 3.0, 5.0, 0.0), "distance: 116109.11974711547"),
157+
general_inputs3:((10.0, 0.0, 5.0, 2000.0), "charge1: 0.0008901200443544508"),
158+
general_inputs4:((10.0, 5.0,0.0 , 2000.0), "charge2: 0.0008901200443544508"),
159+
}
160+
161+
test_coulombs_law_err! {
162+
extra_zero_arg_err: ((0.0, 3.0, 0.0, 2000.0), CoulombsLawError::ExtraZeroArg(String::from("One and only one argument must be 0"))),
163+
negative_distance_err: ((0.0, 3.0, 5.0, -2000.0), CoulombsLawError::NegativeDistance(String::from("Distance cannot be negative"))),
164+
}
165+
166+
test_invalid_arguments! {
167+
valid_argument_input: ((0.0, 3.0, 5.0, 2000.0), false),
168+
invalid_argument_input: ((0.0, 0.0, 5.0, 2000.0), true),
169+
all_argument_zero: ((0.0, 0.0, 0.0, 0.0), true),
170+
}
171+
172+
test_calculate_force! {
173+
force_test1: ((15.0,2000.0),33703.319221125),
174+
force_test2: ((18.0,0.12),11234439740375.0),
175+
}
176+
177+
test_calculate_charge! {
178+
charge_test1: ((15.0,6.0,2000.0),0.00017802400887089018),
179+
charge_test2: ((18.0,3.0,0.12),2.6703601330633526e-13),
180+
}
181+
182+
test_calculate_distance! {
183+
distance_test1: ((15.0,5.0),164203.09186157244),
184+
distance_test2: ((18.0,11.0),121272.02040394374),
185+
}
186+
}

src/electronics/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mod coulombs_law;
2+
pub use coulombs_law::coulombs_law;

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod compression;
88
pub mod conversions;
99
pub mod data_structures;
1010
pub mod dynamic_programming;
11+
pub mod electronics;
1112
pub mod financial;
1213
pub mod general;
1314
pub mod geometry;

0 commit comments

Comments
 (0)