#![warn(missing_docs)]
pub struct DTrig {
sine_array: [i16; 6283],
cosine_array: [i16; 6283],
tangent_array: [i32; 6283],
arcsine_array: [i16; 2001],
arccosine_array: [i16; 2001],
arctangent_thousandths: [i16; 8001],
arctangent_hundredths: [i16; 4001],
arctangent_tenths: [i16; 2001],
arctangent_ones: [i16; 2001],
}
pub mod initialize;
pub (self) mod utility;
impl DTrig {
pub fn sine(&self, argument_fraction: (i32, i32)) -> (i32, i32) {
return (
i32::from(
self.sine_array
[
utility::normalize_angle(
utility::denominator_to_1000(argument_fraction)
) as usize
]
),
1000,
);
}
pub fn cosine(&self, argument_fraction: (i32, i32)) -> (i32, i32) {
return (
i32::from(
self.cosine_array
[
utility::normalize_angle(
utility::denominator_to_1000(argument_fraction)
) as usize
]
),
1000,
);
}
pub fn tangent(&self, argument_fraction: (i32, i32)) -> (i32, i32) {
return (
self.tangent_array
[
utility::normalize_angle(
utility::denominator_to_1000(argument_fraction)
) as usize
],
1000,
);
}
pub fn arcsine(&self, argument_fraction: (i32, i32)) -> (i32, i32) {
if utility::denominator_to_1000(argument_fraction) < -1000 {
panic!("Arcsine input less than 1.");
} else if utility::denominator_to_1000(argument_fraction) > 1000 {
panic!("Arcsine input greater than 1.");
} else {
return (
i32::from(
self.arcsine_array
[(utility::denominator_to_1000(argument_fraction) + 1000) as usize]
),
1000,
);
}
}
pub fn arccosine(&self, argument_fraction: (i32, i32)) -> (i32, i32) {
if utility::denominator_to_1000(argument_fraction) < -1000 {
panic!("Arccosine input less than 1, which is undefined.");
} else if utility::denominator_to_1000(argument_fraction) > 1000 {
panic!("Arccosine input greater than 1, which is undefined.");
} else {
return (
i32::from(
self.arccosine_array
[(utility::denominator_to_1000(argument_fraction) + 1000) as usize]
),
1000,
);
}
}
pub fn arctangent(&self, argument_fraction: (i32, i32)) -> (i32, i32) {
let numerator_out_of_1000 = utility::denominator_to_1000(argument_fraction);
if numerator_out_of_1000 >= -4000 && numerator_out_of_1000 <= 4000 {
return (
i32::from(self.arctangent_thousandths[(numerator_out_of_1000 + 4000) as usize]),
1000,
);
} else if numerator_out_of_1000 >= -20000 && numerator_out_of_1000 <= 20000 {
if (numerator_out_of_1000 % 10).abs() < 5 {
return (
i32::from(
self.arctangent_hundredths[(numerator_out_of_1000 / 10 + 2000) as usize]
),
1000,
);
} else {
if numerator_out_of_1000 > 0 {
return (
i32::from(
self.arctangent_hundredths
[(numerator_out_of_1000 / 10 + 1 + 2000) as usize]
),
1000,
);
} else {
return (
i32::from(
self.arctangent_hundredths
[(numerator_out_of_1000 / 10 - 1 + 2000) as usize]
),
1000,
);
}
}
} else if numerator_out_of_1000 >= -100000 && numerator_out_of_1000 <= 100000 {
if (numerator_out_of_1000 % 100).abs() < 50 {
return (
i32::from(
self.arctangent_tenths[(numerator_out_of_1000 / 100 + 1000) as usize]
),
1000,
);
} else {
if numerator_out_of_1000 > 0 {
return (
i32::from(
self.arctangent_tenths
[(numerator_out_of_1000 / 100 + 1 + 1000) as usize]
),
1000,
);
} else {
return (
i32::from(
self.arctangent_tenths
[(numerator_out_of_1000 / 100 - 1 + 1000) as usize]
),
1000,
);
}
}
} else if numerator_out_of_1000 >= -1000000 && numerator_out_of_1000 <= 1000000 {
if numerator_out_of_1000 % 1000 < 500 {
return (
i32::from(self.arctangent_ones[(numerator_out_of_1000 / 1000 + 1000) as usize]),
1000,
);
} else {
if numerator_out_of_1000 > 0 {
return (
i32::from(
self.arctangent_ones[(numerator_out_of_1000 / 1000 + 1 + 1000) as usize]
),
1000,
);
} else {
return (
i32::from(
self.arctangent_ones[(numerator_out_of_1000 / 1000 - 1 + 1000) as usize]
),
1000,
);
}
}
} else {
if numerator_out_of_1000 < -1000000 && numerator_out_of_1000 > -3374653 {
return (-1570, 1000);
} else if numerator_out_of_1000 > 1000000 && numerator_out_of_1000 < 3374653 {
return (1570, 1000);
} else if numerator_out_of_1000 <= -3374653 {
return (-1571, 1000);
} else {
return (1571, 1000);
}
}
}
}
#[cfg(test)]
mod tests {
use crate::DTrig;
#[test]
fn test_sine() {
let dtrig = DTrig::initialize();
let mut result: bool;
for a in 0..6283 {
if ((((a as f64) / 1000.0).sin() * 1000.0).round() as i32) == dtrig.sine((a, 1000)).0 {
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
for a in -1000000000..1000000001 {
if
(
((((a as f64) / 1000.0).sin() * 1000.0).round() as i32) -
dtrig.sine((a, 1000)).0
).abs() <= 1
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
}
#[test]
fn test_cosine() {
let dtrig = DTrig::initialize();
let mut result: bool;
for a in 0..6283 {
if ((((a as f64) / 1000.0).cos() * 1000.0).round() as i32) == dtrig.cosine((a, 1000)).0 {
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
for a in -1000000000..1000000001 {
if
(
((((a as f64) / 1000.0).cos() * 1000.0).round() as i32) -
dtrig.cosine((a, 1000)).0
).abs() <= 1
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
}
#[test]
fn test_tangent() {
let dtrig = DTrig::initialize();
let mut result: bool;
for a in 0..6283 {
if
((((a as f64) / 1000.0).tan() * 1000.0).round() as i32) ==
dtrig.tangent((a, 1000)).0
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
for a in -1000000000..1000000001 {
if
((((a as f64) / 1000.0).tan() * 1000.0).round() as i64) -
(dtrig.tangent((a, 1000)).0 as i64) <= 1 ||
(
(((a as f64) / 1000.0).tan() * 1000.0 - (dtrig.tangent((a, 1000)).0 as f64)) /
(((a as f64) / 1000.0).tan() * 1000.0)
).abs() <= 0.02 ||
(((a as f64) / 1000.0).tan().abs() * 1000.0 > 10000.0 &&
(
(((a as f64) / 1000.0).tan() * 1000.0 -
(dtrig.tangent((a, 1000)).0 as f64)) /
(((a as f64) / 1000.0).tan() * 1000.0)
).abs() <= 0.1) ||
(((a as f64) / 1000.0).tan() * 1000.0).abs() > 100000.0
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
}
#[test]
fn test_arcsine() {
let dtrig = DTrig::initialize();
let mut result: bool;
for a in -1000..1001 {
if
((((a as f64) / 1000.0).asin() * 1000.0).round() as i32) ==
dtrig.arcsine((a, 1000)).0
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
}
#[test]
fn test_arccosine() {
let dtrig = DTrig::initialize();
let mut result: bool;
for a in -1000..1001 {
if
((((a as f64) / 1000.0).acos() * 1000.0).round() as i32) ==
dtrig.arccosine((a, 1000)).0
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
}
#[test]
fn test_arctangent() {
let dtrig = DTrig::initialize();
let mut result: bool;
for a in -2000..2001 {
if
((((a as f64) / 1000.0).atan() * 1000.0).round() as i32) ==
dtrig.arctangent((a, 1000)).0
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
for a in -10000000..10000001 {
if
((((a as f64) / 1000.0).atan() * 1000.0).round() as i32) -
dtrig.arctangent((a, 1000)).0 <= 1
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
for a in -10000..10001 {
for b in 1..10001 {
if
((((a as f64) / (b as f64)).atan() * 1000.0).round() as i32) -
dtrig.arctangent((a, b)).0 <= 1
{
result = true;
} else {
result = false;
}
assert_eq!(result, true);
}
}
}
}