Commit fef116697a5f39740ccdb8b7ad7442e77dd19ad2
1 parent
d70c0220
add trigon functions sin and cos as static tables of Fractional
Showing
5 changed files
with
463 additions
and
0 deletions
fractional/Cargo.toml
0 → 100644
fractional/src/fractional.rs
0 → 100644
1 | +// | ||
2 | +// Some code to support fractional numbers for full precision rational number | ||
3 | +// calculations. | ||
4 | +// TODO | ||
5 | +// - maybe this could be build as a generic for all integral numbers. | ||
6 | +// (Question, how can I assure that it is build from integral numbers? | ||
7 | +// | ||
8 | +// Georg Hopp <georg@steffers.org> | ||
9 | +// | ||
10 | +// Copyright © 2019 Georg Hopp | ||
11 | +// | ||
12 | +// This program is free software: you can redistribute it and/or modify | ||
13 | +// it under the terms of the GNU General Public License as published by | ||
14 | +// the Free Software Foundation, either version 3 of the License, or | ||
15 | +// (at your option) any later version. | ||
16 | +// | ||
17 | +// This program is distributed in the hope that it will be useful, | ||
18 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | +// GNU General Public License for more details. | ||
21 | +// | ||
22 | +// You should have received a copy of the GNU General Public License | ||
23 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
24 | +// | ||
25 | +use std::cmp::Ordering; | ||
26 | +use std::ops::{Add,Sub,Neg,Mul,Div}; | ||
27 | +use std::fmt; | ||
28 | +use std::convert::{TryFrom, TryInto}; | ||
29 | +use std::num::TryFromIntError; | ||
30 | + | ||
31 | +#[derive(Debug, Eq, Clone, Copy)] | ||
32 | +pub struct Fractional (pub i64, pub i64); | ||
33 | + | ||
34 | +#[inline] | ||
35 | +fn hcf(x :i64, y :i64) -> i64 { | ||
36 | + match y { | ||
37 | + 0 => x, | ||
38 | + _ => hcf(y, x % y), | ||
39 | + } | ||
40 | +} | ||
41 | + | ||
42 | +impl Fractional { | ||
43 | + #[inline] | ||
44 | + pub fn gcd(self, other: Self) -> i64 { | ||
45 | + let Fractional(_, d1) = self; | ||
46 | + let Fractional(_, d2) = other; | ||
47 | + (d1 * d2) / hcf(d1, d2) | ||
48 | + } | ||
49 | + | ||
50 | + #[inline] | ||
51 | + pub fn reduce(self) -> Self { | ||
52 | + let Fractional(n, d) = self; | ||
53 | + Self(n / hcf(n, d), d / hcf(n, d)) | ||
54 | + } | ||
55 | + | ||
56 | + #[inline] | ||
57 | + pub fn numerator(self) -> i64 { | ||
58 | + self.0 | ||
59 | + } | ||
60 | + | ||
61 | + #[inline] | ||
62 | + pub fn denominator(self) -> i64 { | ||
63 | + self.1 | ||
64 | + } | ||
65 | +} | ||
66 | + | ||
67 | +impl fmt::Display for Fractional { | ||
68 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
69 | + write!(f, "({}/{})", self.0, self.1) | ||
70 | + } | ||
71 | +} | ||
72 | + | ||
73 | +impl From<i64> for Fractional { | ||
74 | + fn from(x: i64) -> Self { | ||
75 | + Self(x, 1) | ||
76 | + } | ||
77 | +} | ||
78 | + | ||
79 | +impl TryFrom<usize> for Fractional { | ||
80 | + type Error = &'static str; | ||
81 | + | ||
82 | + fn try_from(x: usize) -> Result<Self, Self::Error> { | ||
83 | + let v = i64::try_from(x); | ||
84 | + match v { | ||
85 | + Err(_) => Err("Conversion from usize to i32 failed"), | ||
86 | + Ok(_v) => Ok(Self(_v, 1)), | ||
87 | + } | ||
88 | + } | ||
89 | +} | ||
90 | + | ||
91 | +pub fn from_vector(xs: &Vec<i64>) -> Vec<Fractional> { | ||
92 | + xs.iter().map(|x| Fractional(*x, 1)).collect() | ||
93 | +} | ||
94 | + | ||
95 | +impl TryInto<f64> for Fractional { | ||
96 | + type Error = TryFromIntError; | ||
97 | + | ||
98 | + fn try_into(self) -> Result<f64, Self::Error> { | ||
99 | + let n :i32 = self.0.try_into()?; | ||
100 | + let d :i32 = self.1.try_into()?; | ||
101 | + Ok(f64::from(n) / f64::from(d)) | ||
102 | + } | ||
103 | +} | ||
104 | + | ||
105 | +impl TryInto<(i32, i32)> for Fractional { | ||
106 | + type Error = TryFromIntError; | ||
107 | + | ||
108 | + fn try_into(self) -> Result<(i32, i32), Self::Error> { | ||
109 | + let a :i32 = (self.0 / self.1).try_into()?; | ||
110 | + let b :i32 = (self.0 % self.1).try_into()?; | ||
111 | + Ok((a, b)) | ||
112 | + } | ||
113 | +} | ||
114 | + | ||
115 | +impl PartialEq for Fractional { | ||
116 | + fn eq(&self, other: &Self) -> bool { | ||
117 | + let Fractional(n1, d1) = self; | ||
118 | + let Fractional(n2, d2) = other; | ||
119 | + n1 * (self.gcd(*other) / d1) == n2 * (self.gcd(*other) / d2) | ||
120 | + } | ||
121 | +} | ||
122 | + | ||
123 | +impl PartialOrd for Fractional { | ||
124 | + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||
125 | + Some(self.cmp(other)) | ||
126 | + } | ||
127 | +} | ||
128 | + | ||
129 | +impl Ord for Fractional { | ||
130 | + fn cmp(&self, other: &Self) -> Ordering { | ||
131 | + let Fractional(n1, d1) = self; | ||
132 | + let Fractional(n2, d2) = other; | ||
133 | + let x = n1 * (self.gcd(*other) / d1); | ||
134 | + let y = n2 * (self.gcd(*other) / d2); | ||
135 | + x.cmp(&y) | ||
136 | + } | ||
137 | +} | ||
138 | + | ||
139 | +impl Add for Fractional { | ||
140 | + type Output = Self; | ||
141 | + | ||
142 | + fn add(self, other: Self) -> Self { | ||
143 | + let Fractional(n1, d1) = self; | ||
144 | + let Fractional(n2, d2) = other; | ||
145 | + let n = n1 * (self.gcd(other) / d1) + n2 * (self.gcd(other) / d2); | ||
146 | + Self(n, self.gcd(other)).reduce() | ||
147 | + } | ||
148 | +} | ||
149 | + | ||
150 | +impl Sub for Fractional { | ||
151 | + type Output = Self; | ||
152 | + | ||
153 | + fn sub(self, other: Self) -> Self { | ||
154 | + let Fractional(n1, d1) = self; | ||
155 | + let Fractional(n2, d2) = other; | ||
156 | + let n = n1 * (self.gcd(other) / d1) - n2 * (self.gcd(other) / d2); | ||
157 | + Self(n, self.gcd(other)).reduce() | ||
158 | + } | ||
159 | +} | ||
160 | + | ||
161 | +impl Neg for Fractional { | ||
162 | + type Output = Self; | ||
163 | + | ||
164 | + fn neg(self) -> Self { | ||
165 | + let Fractional(n, d) = self; | ||
166 | + Self(-n, d).reduce() | ||
167 | + } | ||
168 | +} | ||
169 | + | ||
170 | +impl Mul for Fractional { | ||
171 | + type Output = Self; | ||
172 | + | ||
173 | + fn mul(self, other :Self) -> Self { | ||
174 | + let Fractional(n1, d1) = self; | ||
175 | + let Fractional(n2, d2) = other; | ||
176 | + Self(n1 * n2, d1 * d2).reduce() | ||
177 | + } | ||
178 | +} | ||
179 | + | ||
180 | +impl Div for Fractional { | ||
181 | + type Output = Self; | ||
182 | + | ||
183 | + fn div(self, other: Self) -> Self { | ||
184 | + let Fractional(n, d) = other; | ||
185 | + self * Fractional(d, n) | ||
186 | + } | ||
187 | +} | ||
188 | + | ||
189 | + /* some stuff that could be tested... | ||
190 | + let x = Fractional(1, 3); | ||
191 | + let y = Fractional(1, 6); | ||
192 | + | ||
193 | + println!( | ||
194 | + "Greatest common denominator of {} and {}: {}", x, y, x.gcd(y)); | ||
195 | + println!("Numerator of {}: {}", x, x.numerator()); | ||
196 | + println!("Denominator of {}: {}", x, x.denominator()); | ||
197 | + assert_eq!(Fractional(1, 3), Fractional(2, 6)); | ||
198 | + assert_eq!(Fractional(1, 3), Fractional(1, 3)); | ||
199 | + assert_eq!(y < x, true); | ||
200 | + assert_eq!(y > x, false); | ||
201 | + assert_eq!(x == y, false); | ||
202 | + assert_eq!(x == x, true); | ||
203 | + assert_eq!(x + y, Fractional(1, 2)); | ||
204 | + println!("{} + {} = {}", x, y, x + y); | ||
205 | + assert_eq!(x - y, Fractional(1, 6)); | ||
206 | + println!("{} - {} = {}", x, y, x - y); | ||
207 | + assert_eq!(y - x, Fractional(-1, 6)); | ||
208 | + println!("{} - {} = {}", y, x, y - x); | ||
209 | + assert_eq!(-x, Fractional(-1, 3)); | ||
210 | + println!("-{} = {}", x, -x); | ||
211 | + assert_eq!(x * y, Fractional(1, 18)); | ||
212 | + println!("{} * {} = {}", x, y, x * y); | ||
213 | + assert_eq!(x / y, Fractional(2, 1)); | ||
214 | + println!("{} / {} = {}", x, y, x / y); | ||
215 | + assert_eq!(y / x, Fractional(1, 2)); | ||
216 | + println!("{} / {} = {}", y, x, y / x); | ||
217 | + | ||
218 | + println!("Fractional from 3: {}", Fractional::from(3)); | ||
219 | + let z :f64 = Fractional::into(x); | ||
220 | + println!("Floating point of {}: {}", x, z); | ||
221 | + let (d, r) = Fractional::into(x); | ||
222 | + println!("(div, rest) of {}: ({}, {})", x, d, r); | ||
223 | + */ | ||
224 | + |
fractional/src/lib.rs
0 → 100644
1 | +// | ||
2 | +// Lib for fractional calculations. | ||
3 | +// | ||
4 | +// Georg Hopp <georg@steffers.org> | ||
5 | +// | ||
6 | +// Copyright © 2019 Georg Hopp | ||
7 | +// | ||
8 | +// This program is free software: you can redistribute it and/or modify | ||
9 | +// it under the terms of the GNU General Public License as published by | ||
10 | +// the Free Software Foundation, either version 3 of the License, or | ||
11 | +// (at your option) any later version. | ||
12 | +// | ||
13 | +// This program is distributed in the hope that it will be useful, | ||
14 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | +// GNU General Public License for more details. | ||
17 | +// | ||
18 | +// You should have received a copy of the GNU General Public License | ||
19 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | +// | ||
21 | +extern crate lazy_static; | ||
22 | + | ||
23 | +pub mod fractional; | ||
24 | +pub mod trigonometry; | ||
25 | + | ||
26 | +use fractional::{Fractional}; |
fractional/src/main.rs
0 → 100644
1 | +// | ||
2 | +// Test our fractional crate / module... | ||
3 | +// | ||
4 | +// Georg Hopp <georg@steffers.org> | ||
5 | +// | ||
6 | +// Copyright © 2019 Georg Hopp | ||
7 | +// | ||
8 | +// This program is free software: you can redistribute it and/or modify | ||
9 | +// it under the terms of the GNU General Public License as published by | ||
10 | +// the Free Software Foundation, either version 3 of the License, or | ||
11 | +// (at your option) any later version. | ||
12 | +// | ||
13 | +// This program is distributed in the hope that it will be useful, | ||
14 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | +// GNU General Public License for more details. | ||
17 | +// | ||
18 | +// You should have received a copy of the GNU General Public License | ||
19 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | +// | ||
21 | +use std::convert::{TryFrom, TryInto}; | ||
22 | +use std::num::TryFromIntError; | ||
23 | +use std::f64::consts::PI as FPI; | ||
24 | + | ||
25 | +use fractional::fractional::{Fractional, from_vector}; | ||
26 | +use fractional::trigonometry::{sin, cos, PI}; | ||
27 | + | ||
28 | +struct Vector { | ||
29 | + x: Fractional, | ||
30 | + y: Fractional, | ||
31 | + z: Fractional, | ||
32 | +} | ||
33 | + | ||
34 | +fn mean(v: &Vec<i64>) -> Result<Fractional, TryFromIntError> { | ||
35 | + let r = v.iter().fold(0, |acc, x| acc + x); | ||
36 | + let l = i64::try_from(v.len())?; | ||
37 | + Ok(Fractional(r, l)) | ||
38 | +} | ||
39 | + | ||
40 | +fn main() { | ||
41 | + let a = vec![3, 6, 1, 9]; | ||
42 | + let b = from_vector(&a); | ||
43 | + let c = mean(&a).unwrap(); // This might fail if the len of the | ||
44 | + // vector (usize) does not fit into i32. | ||
45 | + let d :f64 = c.try_into().unwrap(); | ||
46 | + let e :f64 = Fractional::try_into(c).unwrap(); | ||
47 | + | ||
48 | + println!(" [i32] : {:?}" , a); | ||
49 | + println!(" [Fractional] : {:?}" , b); | ||
50 | + println!(" mean of [i32] : {}" , c); | ||
51 | + println!(" as f64 : {}" , d); | ||
52 | + println!(" and as f64 : {}" , e); | ||
53 | + println!(" again as f64 : {}" , TryInto::<f64>::try_into(c).unwrap()); | ||
54 | + println!(" Rust π : {}" , FPI); | ||
55 | + println!(" π : {} {}" , TryInto::<f64>::try_into(PI).unwrap(), PI); | ||
56 | + println!(" π as tuple : {:?}" , TryInto::<(i32, i32)>::try_into(PI).unwrap()); | ||
57 | + println!(" Rust π² : {}" , FPI * FPI); | ||
58 | + println!(" π² : {} {}" , TryInto::<f64>::try_into(PI * PI).unwrap(), PI * PI); | ||
59 | + println!(" sin 9 : {}" , sin(9)); | ||
60 | + println!(" sin 9 : {}" , TryInto::<f64>::try_into(sin(9)).unwrap()); | ||
61 | + println!(" Rust sin 9 : {}" , f64::sin(9.0 * FPI / 180.0)); | ||
62 | + println!(" sin 17 : {}" , sin(17)); | ||
63 | + println!(" sin 17 : {}" , TryInto::<f64>::try_into(sin(17)).unwrap()); | ||
64 | + println!(" Rust sin 17 : {}" , f64::sin(17.0 * FPI / 180.0)); | ||
65 | + println!(" sin 31 : {}" , sin(31)); | ||
66 | + println!(" sin 31 : {}" , TryInto::<f64>::try_into(sin(31)).unwrap()); | ||
67 | + println!(" Rust sin 31 : {}" , f64::sin(31.0 * FPI / 180.0)); | ||
68 | + println!(" sin 45 : {}" , sin(45)); | ||
69 | + println!(" sin 45 : {}" , TryInto::<f64>::try_into(sin(45)).unwrap()); | ||
70 | + println!(" Rust sin 45 : {}" , f64::sin(45.0 * FPI / 180.0)); | ||
71 | + println!(" sin 73 : {}" , sin(73)); | ||
72 | + println!(" sin 73 : {}" , TryInto::<f64>::try_into(sin(73)).unwrap()); | ||
73 | + println!(" Rust sin 73 : {}" , f64::sin(73.0 * FPI / 180.0)); | ||
74 | + println!(" sin 123 : {}" , sin(123)); | ||
75 | + println!(" sin 123 : {}" , TryInto::<f64>::try_into(sin(123)).unwrap()); | ||
76 | + println!(" Rust sin 123 : {}" , f64::sin(123.0 * FPI / 180.0)); | ||
77 | + println!(" sin 213 : {}" , sin(213)); | ||
78 | + println!(" sin 213 : {}" , TryInto::<f64>::try_into(sin(213)).unwrap()); | ||
79 | + println!(" Rust sin 213 : {}" , f64::sin(213.0 * FPI / 180.0)); | ||
80 | + println!(" sin 312 : {}" , sin(312)); | ||
81 | + println!(" sin 312 : {}" , TryInto::<f64>::try_into(sin(312)).unwrap()); | ||
82 | + println!(" Rust sin 312 : {}" , f64::sin(312.0 * FPI / 180.0)); | ||
83 | + println!(" sin 876 : {}" , sin(876)); | ||
84 | + println!(" sin 876 : {}" , TryInto::<f64>::try_into(sin(876)).unwrap()); | ||
85 | + println!(" Rust sin 876 : {}" , f64::sin(876.0 * FPI / 180.0)); | ||
86 | + println!(" cos 9 : {}" , cos(9)); | ||
87 | + println!(" cos 9 : {}" , TryInto::<f64>::try_into(cos(9)).unwrap()); | ||
88 | + println!(" Rust cos 9 : {}" , f64::cos(9.0 * FPI / 180.0)); | ||
89 | + println!(" cos 17 : {}" , cos(17)); | ||
90 | + println!(" cos 17 : {}" , TryInto::<f64>::try_into(cos(17)).unwrap()); | ||
91 | + println!(" Rust cos 17 : {}" , f64::cos(17.0 * FPI / 180.0)); | ||
92 | + println!(" cos 31 : {}" , cos(31)); | ||
93 | + println!(" cos 31 : {}" , TryInto::<f64>::try_into(cos(31)).unwrap()); | ||
94 | + println!(" Rust cos 31 : {}" , f64::cos(31.0 * FPI / 180.0)); | ||
95 | + println!(" cos 45 : {}" , cos(45)); | ||
96 | + println!(" cos 45 : {}" , TryInto::<f64>::try_into(cos(45)).unwrap()); | ||
97 | + println!(" Rust cos 45 : {}" , f64::cos(45.0 * FPI / 180.0)); | ||
98 | + println!(" cos 73 : {}" , cos(73)); | ||
99 | + println!(" cos 73 : {}" , TryInto::<f64>::try_into(cos(73)).unwrap()); | ||
100 | + println!(" Rust cos 73 : {}" , f64::cos(73.0 * FPI / 180.0)); | ||
101 | + println!(" cos 123 : {}" , cos(123)); | ||
102 | + println!(" cos 123 : {}" , TryInto::<f64>::try_into(cos(123)).unwrap()); | ||
103 | + println!(" Rust cos 123 : {}" , f64::cos(123.0 * FPI / 180.0)); | ||
104 | + println!(" cos 213 : {}" , cos(213)); | ||
105 | + println!(" cos 213 : {}" , TryInto::<f64>::try_into(cos(213)).unwrap()); | ||
106 | + println!(" Rust cos 213 : {}" , f64::cos(213.0 * FPI / 180.0)); | ||
107 | + println!(" cos 312 : {}" , cos(312)); | ||
108 | + println!(" cos 312 : {}" , TryInto::<f64>::try_into(cos(312)).unwrap()); | ||
109 | + println!(" Rust cos 312 : {}" , f64::cos(312.0 * FPI / 180.0)); | ||
110 | + println!(" cos 876 : {}" , cos(876)); | ||
111 | + println!(" cos 876 : {}" , TryInto::<f64>::try_into(cos(876)).unwrap()); | ||
112 | + println!(" Rust cos 876 : {}" , f64::cos(876.0 * FPI / 180.0)); | ||
113 | +} |
fractional/src/trigonometry.rs
0 → 100644
1 | +// | ||
2 | +// Test our fractional crate / module... | ||
3 | +// | ||
4 | +// Georg Hopp <georg@steffers.org> | ||
5 | +// | ||
6 | +// Copyright © 2019 Georg Hopp | ||
7 | +// | ||
8 | +// This program is free software: you can redistribute it and/or modify | ||
9 | +// it under the terms of the GNU General Public License as published by | ||
10 | +// the Free Software Foundation, either version 3 of the License, or | ||
11 | +// (at your option) any later version. | ||
12 | +// | ||
13 | +// This program is distributed in the hope that it will be useful, | ||
14 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | +// GNU General Public License for more details. | ||
17 | +// | ||
18 | +// You should have received a copy of the GNU General Public License | ||
19 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | +// | ||
21 | +use crate::{Fractional}; | ||
22 | + | ||
23 | +pub const PI :Fractional = Fractional(355, 113); // This is a really close | ||
24 | + // fractional approximation | ||
25 | + // for pi | ||
26 | + | ||
27 | +const PRECISION :i64 = 100000; | ||
28 | + | ||
29 | +#[inline] | ||
30 | +pub fn rad(d: u32) -> f64 { | ||
31 | + use std::f64::consts::PI; | ||
32 | + d as f64 * PI / 180.0 | ||
33 | +} | ||
34 | + | ||
35 | +pub fn sin(d: i32) -> Fractional { | ||
36 | + // hold sin Fractionals from 0 to 89 ... | ||
37 | + lazy_static::lazy_static! { | ||
38 | + static ref SINTAB :Vec<Fractional> = | ||
39 | + (0..90).map(|x| _sin(x)).collect(); | ||
40 | + } | ||
41 | + | ||
42 | + // fractional sin from f64 sin. (From 1° to 89°) | ||
43 | + fn _sin(d: u32) -> Fractional { | ||
44 | + match d { | ||
45 | + 0 => Fractional(0, 1), | ||
46 | + _ => { | ||
47 | + // This is undefined behaviour for very large f64, but our f64 | ||
48 | + // is always between 0.0 and 10000.0 which should be fine. | ||
49 | + let s = (f64::sin(rad(d)) * PRECISION as f64).round() as i64; | ||
50 | + Fractional(s, PRECISION).reduce() | ||
51 | + } | ||
52 | + } | ||
53 | + } | ||
54 | + | ||
55 | + match d { | ||
56 | + 90 => Fractional(1, 1), | ||
57 | + 180 => SINTAB[0], | ||
58 | + 270 => -Fractional(1, 1), | ||
59 | + 1..=89 => SINTAB[d as usize], | ||
60 | + 91..=179 => SINTAB[180 - d as usize], | ||
61 | + 181..=269 => -SINTAB[d as usize - 180], | ||
62 | + 271..=359 => -SINTAB[360 - d as usize], | ||
63 | + _ => sin(d % 360), | ||
64 | + } | ||
65 | +} | ||
66 | + | ||
67 | +pub fn cos(d: i32) -> Fractional { | ||
68 | + lazy_static::lazy_static! { | ||
69 | + static ref COSTAB :Vec<Fractional> = | ||
70 | + (0..90).map(|x| _cos(x)).collect(); | ||
71 | + } | ||
72 | + | ||
73 | + fn _cos(d: u32) -> Fractional { | ||
74 | + match d { | ||
75 | + 0 => Fractional(1, 1), | ||
76 | + _ => { | ||
77 | + let s = (f64::cos(rad(d)) * PRECISION as f64).round() as i64; | ||
78 | + Fractional(s, PRECISION).reduce() | ||
79 | + } | ||
80 | + } | ||
81 | + } | ||
82 | + | ||
83 | + match d { | ||
84 | + 90 | 270 => Fractional(0, 1), | ||
85 | + 180 => -COSTAB[0], | ||
86 | + 1..=89 => COSTAB[d as usize], | ||
87 | + 91..=179 => -COSTAB[180 - d as usize], | ||
88 | + 181..=269 => -COSTAB[d as usize - 180], | ||
89 | + 271..=359 => COSTAB[360 - d as usize], | ||
90 | + _ => cos(d % 360), | ||
91 | + } | ||
92 | +} |
Please
register
or
login
to post a comment