5 changed files with 463 additions and 0 deletions
-
8fractional/Cargo.toml
-
224fractional/src/fractional.rs
-
26fractional/src/lib.rs
-
113fractional/src/main.rs
-
92fractional/src/trigonometry.rs
@ -0,0 +1,8 @@ |
|||||
|
[package] |
||||
|
name = "fractional" |
||||
|
version = "0.1.0" |
||||
|
authors = ["Georg Hopp <georg@steffers.org>"] |
||||
|
edition = "2018" |
||||
|
|
||||
|
[dependencies] |
||||
|
lazy_static = "1.4.0" |
||||
@ -0,0 +1,224 @@ |
|||||
|
//
|
||||
|
// Some code to support fractional numbers for full precision rational number
|
||||
|
// calculations.
|
||||
|
// TODO
|
||||
|
// - maybe this could be build as a generic for all integral numbers.
|
||||
|
// (Question, how can I assure that it is build from integral numbers?
|
||||
|
//
|
||||
|
// Georg Hopp <georg@steffers.org>
|
||||
|
//
|
||||
|
// Copyright © 2019 Georg Hopp
|
||||
|
//
|
||||
|
// This program is free software: you can redistribute it and/or modify
|
||||
|
// it under the terms of the GNU General Public License as published by
|
||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||
|
// (at your option) any later version.
|
||||
|
//
|
||||
|
// This program is distributed in the hope that it will be useful,
|
||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
// GNU General Public License for more details.
|
||||
|
//
|
||||
|
// You should have received a copy of the GNU General Public License
|
||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
//
|
||||
|
use std::cmp::Ordering;
|
||||
|
use std::ops::{Add,Sub,Neg,Mul,Div};
|
||||
|
use std::fmt;
|
||||
|
use std::convert::{TryFrom, TryInto};
|
||||
|
use std::num::TryFromIntError;
|
||||
|
|
||||
|
#[derive(Debug, Eq, Clone, Copy)]
|
||||
|
pub struct Fractional (pub i64, pub i64);
|
||||
|
|
||||
|
#[inline]
|
||||
|
fn hcf(x :i64, y :i64) -> i64 {
|
||||
|
match y {
|
||||
|
0 => x,
|
||||
|
_ => hcf(y, x % y),
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Fractional {
|
||||
|
#[inline]
|
||||
|
pub fn gcd(self, other: Self) -> i64 {
|
||||
|
let Fractional(_, d1) = self;
|
||||
|
let Fractional(_, d2) = other;
|
||||
|
(d1 * d2) / hcf(d1, d2)
|
||||
|
}
|
||||
|
|
||||
|
#[inline]
|
||||
|
pub fn reduce(self) -> Self {
|
||||
|
let Fractional(n, d) = self;
|
||||
|
Self(n / hcf(n, d), d / hcf(n, d))
|
||||
|
}
|
||||
|
|
||||
|
#[inline]
|
||||
|
pub fn numerator(self) -> i64 {
|
||||
|
self.0
|
||||
|
}
|
||||
|
|
||||
|
#[inline]
|
||||
|
pub fn denominator(self) -> i64 {
|
||||
|
self.1
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl fmt::Display for Fractional {
|
||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
write!(f, "({}/{})", self.0, self.1)
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl From<i64> for Fractional {
|
||||
|
fn from(x: i64) -> Self {
|
||||
|
Self(x, 1)
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl TryFrom<usize> for Fractional {
|
||||
|
type Error = &'static str;
|
||||
|
|
||||
|
fn try_from(x: usize) -> Result<Self, Self::Error> {
|
||||
|
let v = i64::try_from(x);
|
||||
|
match v {
|
||||
|
Err(_) => Err("Conversion from usize to i32 failed"),
|
||||
|
Ok(_v) => Ok(Self(_v, 1)),
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
pub fn from_vector(xs: &Vec<i64>) -> Vec<Fractional> {
|
||||
|
xs.iter().map(|x| Fractional(*x, 1)).collect()
|
||||
|
}
|
||||
|
|
||||
|
impl TryInto<f64> for Fractional {
|
||||
|
type Error = TryFromIntError;
|
||||
|
|
||||
|
fn try_into(self) -> Result<f64, Self::Error> {
|
||||
|
let n :i32 = self.0.try_into()?;
|
||||
|
let d :i32 = self.1.try_into()?;
|
||||
|
Ok(f64::from(n) / f64::from(d))
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl TryInto<(i32, i32)> for Fractional {
|
||||
|
type Error = TryFromIntError;
|
||||
|
|
||||
|
fn try_into(self) -> Result<(i32, i32), Self::Error> {
|
||||
|
let a :i32 = (self.0 / self.1).try_into()?;
|
||||
|
let b :i32 = (self.0 % self.1).try_into()?;
|
||||
|
Ok((a, b))
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl PartialEq for Fractional {
|
||||
|
fn eq(&self, other: &Self) -> bool {
|
||||
|
let Fractional(n1, d1) = self;
|
||||
|
let Fractional(n2, d2) = other;
|
||||
|
n1 * (self.gcd(*other) / d1) == n2 * (self.gcd(*other) / d2)
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl PartialOrd for Fractional {
|
||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
|
Some(self.cmp(other))
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Ord for Fractional {
|
||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||
|
let Fractional(n1, d1) = self;
|
||||
|
let Fractional(n2, d2) = other;
|
||||
|
let x = n1 * (self.gcd(*other) / d1);
|
||||
|
let y = n2 * (self.gcd(*other) / d2);
|
||||
|
x.cmp(&y)
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Add for Fractional {
|
||||
|
type Output = Self;
|
||||
|
|
||||
|
fn add(self, other: Self) -> Self {
|
||||
|
let Fractional(n1, d1) = self;
|
||||
|
let Fractional(n2, d2) = other;
|
||||
|
let n = n1 * (self.gcd(other) / d1) + n2 * (self.gcd(other) / d2);
|
||||
|
Self(n, self.gcd(other)).reduce()
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Sub for Fractional {
|
||||
|
type Output = Self;
|
||||
|
|
||||
|
fn sub(self, other: Self) -> Self {
|
||||
|
let Fractional(n1, d1) = self;
|
||||
|
let Fractional(n2, d2) = other;
|
||||
|
let n = n1 * (self.gcd(other) / d1) - n2 * (self.gcd(other) / d2);
|
||||
|
Self(n, self.gcd(other)).reduce()
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Neg for Fractional {
|
||||
|
type Output = Self;
|
||||
|
|
||||
|
fn neg(self) -> Self {
|
||||
|
let Fractional(n, d) = self;
|
||||
|
Self(-n, d).reduce()
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Mul for Fractional {
|
||||
|
type Output = Self;
|
||||
|
|
||||
|
fn mul(self, other :Self) -> Self {
|
||||
|
let Fractional(n1, d1) = self;
|
||||
|
let Fractional(n2, d2) = other;
|
||||
|
Self(n1 * n2, d1 * d2).reduce()
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl Div for Fractional {
|
||||
|
type Output = Self;
|
||||
|
|
||||
|
fn div(self, other: Self) -> Self {
|
||||
|
let Fractional(n, d) = other;
|
||||
|
self * Fractional(d, n)
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
/* some stuff that could be tested...
|
||||
|
let x = Fractional(1, 3);
|
||||
|
let y = Fractional(1, 6);
|
||||
|
|
||||
|
println!(
|
||||
|
"Greatest common denominator of {} and {}: {}", x, y, x.gcd(y));
|
||||
|
println!("Numerator of {}: {}", x, x.numerator());
|
||||
|
println!("Denominator of {}: {}", x, x.denominator());
|
||||
|
assert_eq!(Fractional(1, 3), Fractional(2, 6));
|
||||
|
assert_eq!(Fractional(1, 3), Fractional(1, 3));
|
||||
|
assert_eq!(y < x, true);
|
||||
|
assert_eq!(y > x, false);
|
||||
|
assert_eq!(x == y, false);
|
||||
|
assert_eq!(x == x, true);
|
||||
|
assert_eq!(x + y, Fractional(1, 2));
|
||||
|
println!("{} + {} = {}", x, y, x + y);
|
||||
|
assert_eq!(x - y, Fractional(1, 6));
|
||||
|
println!("{} - {} = {}", x, y, x - y);
|
||||
|
assert_eq!(y - x, Fractional(-1, 6));
|
||||
|
println!("{} - {} = {}", y, x, y - x);
|
||||
|
assert_eq!(-x, Fractional(-1, 3));
|
||||
|
println!("-{} = {}", x, -x);
|
||||
|
assert_eq!(x * y, Fractional(1, 18));
|
||||
|
println!("{} * {} = {}", x, y, x * y);
|
||||
|
assert_eq!(x / y, Fractional(2, 1));
|
||||
|
println!("{} / {} = {}", x, y, x / y);
|
||||
|
assert_eq!(y / x, Fractional(1, 2));
|
||||
|
println!("{} / {} = {}", y, x, y / x);
|
||||
|
|
||||
|
println!("Fractional from 3: {}", Fractional::from(3));
|
||||
|
let z :f64 = Fractional::into(x);
|
||||
|
println!("Floating point of {}: {}", x, z);
|
||||
|
let (d, r) = Fractional::into(x);
|
||||
|
println!("(div, rest) of {}: ({}, {})", x, d, r);
|
||||
|
*/
|
||||
|
|
||||
@ -0,0 +1,26 @@ |
|||||
|
//
|
||||
|
// Lib for fractional calculations.
|
||||
|
//
|
||||
|
// Georg Hopp <georg@steffers.org>
|
||||
|
//
|
||||
|
// Copyright © 2019 Georg Hopp
|
||||
|
//
|
||||
|
// This program is free software: you can redistribute it and/or modify
|
||||
|
// it under the terms of the GNU General Public License as published by
|
||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||
|
// (at your option) any later version.
|
||||
|
//
|
||||
|
// This program is distributed in the hope that it will be useful,
|
||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
// GNU General Public License for more details.
|
||||
|
//
|
||||
|
// You should have received a copy of the GNU General Public License
|
||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
//
|
||||
|
extern crate lazy_static;
|
||||
|
|
||||
|
pub mod fractional;
|
||||
|
pub mod trigonometry;
|
||||
|
|
||||
|
use fractional::{Fractional};
|
||||
@ -0,0 +1,113 @@ |
|||||
|
//
|
||||
|
// Test our fractional crate / module...
|
||||
|
//
|
||||
|
// Georg Hopp <georg@steffers.org>
|
||||
|
//
|
||||
|
// Copyright © 2019 Georg Hopp
|
||||
|
//
|
||||
|
// This program is free software: you can redistribute it and/or modify
|
||||
|
// it under the terms of the GNU General Public License as published by
|
||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||
|
// (at your option) any later version.
|
||||
|
//
|
||||
|
// This program is distributed in the hope that it will be useful,
|
||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
// GNU General Public License for more details.
|
||||
|
//
|
||||
|
// You should have received a copy of the GNU General Public License
|
||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
//
|
||||
|
use std::convert::{TryFrom, TryInto};
|
||||
|
use std::num::TryFromIntError;
|
||||
|
use std::f64::consts::PI as FPI;
|
||||
|
|
||||
|
use fractional::fractional::{Fractional, from_vector};
|
||||
|
use fractional::trigonometry::{sin, cos, PI};
|
||||
|
|
||||
|
struct Vector {
|
||||
|
x: Fractional,
|
||||
|
y: Fractional,
|
||||
|
z: Fractional,
|
||||
|
}
|
||||
|
|
||||
|
fn mean(v: &Vec<i64>) -> Result<Fractional, TryFromIntError> {
|
||||
|
let r = v.iter().fold(0, |acc, x| acc + x);
|
||||
|
let l = i64::try_from(v.len())?;
|
||||
|
Ok(Fractional(r, l))
|
||||
|
}
|
||||
|
|
||||
|
fn main() {
|
||||
|
let a = vec![3, 6, 1, 9];
|
||||
|
let b = from_vector(&a);
|
||||
|
let c = mean(&a).unwrap(); // This might fail if the len of the
|
||||
|
// vector (usize) does not fit into i32.
|
||||
|
let d :f64 = c.try_into().unwrap();
|
||||
|
let e :f64 = Fractional::try_into(c).unwrap();
|
||||
|
|
||||
|
println!(" [i32] : {:?}" , a);
|
||||
|
println!(" [Fractional] : {:?}" , b);
|
||||
|
println!(" mean of [i32] : {}" , c);
|
||||
|
println!(" as f64 : {}" , d);
|
||||
|
println!(" and as f64 : {}" , e);
|
||||
|
println!(" again as f64 : {}" , TryInto::<f64>::try_into(c).unwrap());
|
||||
|
println!(" Rust π : {}" , FPI);
|
||||
|
println!(" π : {} {}" , TryInto::<f64>::try_into(PI).unwrap(), PI);
|
||||
|
println!(" π as tuple : {:?}" , TryInto::<(i32, i32)>::try_into(PI).unwrap());
|
||||
|
println!(" Rust π² : {}" , FPI * FPI);
|
||||
|
println!(" π² : {} {}" , TryInto::<f64>::try_into(PI * PI).unwrap(), PI * PI);
|
||||
|
println!(" sin 9 : {}" , sin(9));
|
||||
|
println!(" sin 9 : {}" , TryInto::<f64>::try_into(sin(9)).unwrap());
|
||||
|
println!(" Rust sin 9 : {}" , f64::sin(9.0 * FPI / 180.0));
|
||||
|
println!(" sin 17 : {}" , sin(17));
|
||||
|
println!(" sin 17 : {}" , TryInto::<f64>::try_into(sin(17)).unwrap());
|
||||
|
println!(" Rust sin 17 : {}" , f64::sin(17.0 * FPI / 180.0));
|
||||
|
println!(" sin 31 : {}" , sin(31));
|
||||
|
println!(" sin 31 : {}" , TryInto::<f64>::try_into(sin(31)).unwrap());
|
||||
|
println!(" Rust sin 31 : {}" , f64::sin(31.0 * FPI / 180.0));
|
||||
|
println!(" sin 45 : {}" , sin(45));
|
||||
|
println!(" sin 45 : {}" , TryInto::<f64>::try_into(sin(45)).unwrap());
|
||||
|
println!(" Rust sin 45 : {}" , f64::sin(45.0 * FPI / 180.0));
|
||||
|
println!(" sin 73 : {}" , sin(73));
|
||||
|
println!(" sin 73 : {}" , TryInto::<f64>::try_into(sin(73)).unwrap());
|
||||
|
println!(" Rust sin 73 : {}" , f64::sin(73.0 * FPI / 180.0));
|
||||
|
println!(" sin 123 : {}" , sin(123));
|
||||
|
println!(" sin 123 : {}" , TryInto::<f64>::try_into(sin(123)).unwrap());
|
||||
|
println!(" Rust sin 123 : {}" , f64::sin(123.0 * FPI / 180.0));
|
||||
|
println!(" sin 213 : {}" , sin(213));
|
||||
|
println!(" sin 213 : {}" , TryInto::<f64>::try_into(sin(213)).unwrap());
|
||||
|
println!(" Rust sin 213 : {}" , f64::sin(213.0 * FPI / 180.0));
|
||||
|
println!(" sin 312 : {}" , sin(312));
|
||||
|
println!(" sin 312 : {}" , TryInto::<f64>::try_into(sin(312)).unwrap());
|
||||
|
println!(" Rust sin 312 : {}" , f64::sin(312.0 * FPI / 180.0));
|
||||
|
println!(" sin 876 : {}" , sin(876));
|
||||
|
println!(" sin 876 : {}" , TryInto::<f64>::try_into(sin(876)).unwrap());
|
||||
|
println!(" Rust sin 876 : {}" , f64::sin(876.0 * FPI / 180.0));
|
||||
|
println!(" cos 9 : {}" , cos(9));
|
||||
|
println!(" cos 9 : {}" , TryInto::<f64>::try_into(cos(9)).unwrap());
|
||||
|
println!(" Rust cos 9 : {}" , f64::cos(9.0 * FPI / 180.0));
|
||||
|
println!(" cos 17 : {}" , cos(17));
|
||||
|
println!(" cos 17 : {}" , TryInto::<f64>::try_into(cos(17)).unwrap());
|
||||
|
println!(" Rust cos 17 : {}" , f64::cos(17.0 * FPI / 180.0));
|
||||
|
println!(" cos 31 : {}" , cos(31));
|
||||
|
println!(" cos 31 : {}" , TryInto::<f64>::try_into(cos(31)).unwrap());
|
||||
|
println!(" Rust cos 31 : {}" , f64::cos(31.0 * FPI / 180.0));
|
||||
|
println!(" cos 45 : {}" , cos(45));
|
||||
|
println!(" cos 45 : {}" , TryInto::<f64>::try_into(cos(45)).unwrap());
|
||||
|
println!(" Rust cos 45 : {}" , f64::cos(45.0 * FPI / 180.0));
|
||||
|
println!(" cos 73 : {}" , cos(73));
|
||||
|
println!(" cos 73 : {}" , TryInto::<f64>::try_into(cos(73)).unwrap());
|
||||
|
println!(" Rust cos 73 : {}" , f64::cos(73.0 * FPI / 180.0));
|
||||
|
println!(" cos 123 : {}" , cos(123));
|
||||
|
println!(" cos 123 : {}" , TryInto::<f64>::try_into(cos(123)).unwrap());
|
||||
|
println!(" Rust cos 123 : {}" , f64::cos(123.0 * FPI / 180.0));
|
||||
|
println!(" cos 213 : {}" , cos(213));
|
||||
|
println!(" cos 213 : {}" , TryInto::<f64>::try_into(cos(213)).unwrap());
|
||||
|
println!(" Rust cos 213 : {}" , f64::cos(213.0 * FPI / 180.0));
|
||||
|
println!(" cos 312 : {}" , cos(312));
|
||||
|
println!(" cos 312 : {}" , TryInto::<f64>::try_into(cos(312)).unwrap());
|
||||
|
println!(" Rust cos 312 : {}" , f64::cos(312.0 * FPI / 180.0));
|
||||
|
println!(" cos 876 : {}" , cos(876));
|
||||
|
println!(" cos 876 : {}" , TryInto::<f64>::try_into(cos(876)).unwrap());
|
||||
|
println!(" Rust cos 876 : {}" , f64::cos(876.0 * FPI / 180.0));
|
||||
|
}
|
||||
@ -0,0 +1,92 @@ |
|||||
|
//
|
||||
|
// Test our fractional crate / module...
|
||||
|
//
|
||||
|
// Georg Hopp <georg@steffers.org>
|
||||
|
//
|
||||
|
// Copyright © 2019 Georg Hopp
|
||||
|
//
|
||||
|
// This program is free software: you can redistribute it and/or modify
|
||||
|
// it under the terms of the GNU General Public License as published by
|
||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||
|
// (at your option) any later version.
|
||||
|
//
|
||||
|
// This program is distributed in the hope that it will be useful,
|
||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
// GNU General Public License for more details.
|
||||
|
//
|
||||
|
// You should have received a copy of the GNU General Public License
|
||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
//
|
||||
|
use crate::{Fractional};
|
||||
|
|
||||
|
pub const PI :Fractional = Fractional(355, 113); // This is a really close
|
||||
|
// fractional approximation
|
||||
|
// for pi
|
||||
|
|
||||
|
const PRECISION :i64 = 100000;
|
||||
|
|
||||
|
#[inline]
|
||||
|
pub fn rad(d: u32) -> f64 {
|
||||
|
use std::f64::consts::PI;
|
||||
|
d as f64 * PI / 180.0
|
||||
|
}
|
||||
|
|
||||
|
pub fn sin(d: i32) -> Fractional {
|
||||
|
// hold sin Fractionals from 0 to 89 ...
|
||||
|
lazy_static::lazy_static! {
|
||||
|
static ref SINTAB :Vec<Fractional> =
|
||||
|
(0..90).map(|x| _sin(x)).collect();
|
||||
|
}
|
||||
|
|
||||
|
// fractional sin from f64 sin. (From 1° to 89°)
|
||||
|
fn _sin(d: u32) -> Fractional {
|
||||
|
match d {
|
||||
|
0 => Fractional(0, 1),
|
||||
|
_ => {
|
||||
|
// This is undefined behaviour for very large f64, but our f64
|
||||
|
// is always between 0.0 and 10000.0 which should be fine.
|
||||
|
let s = (f64::sin(rad(d)) * PRECISION as f64).round() as i64;
|
||||
|
Fractional(s, PRECISION).reduce()
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
match d {
|
||||
|
90 => Fractional(1, 1),
|
||||
|
180 => SINTAB[0],
|
||||
|
270 => -Fractional(1, 1),
|
||||
|
1..=89 => SINTAB[d as usize],
|
||||
|
91..=179 => SINTAB[180 - d as usize],
|
||||
|
181..=269 => -SINTAB[d as usize - 180],
|
||||
|
271..=359 => -SINTAB[360 - d as usize],
|
||||
|
_ => sin(d % 360),
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
pub fn cos(d: i32) -> Fractional {
|
||||
|
lazy_static::lazy_static! {
|
||||
|
static ref COSTAB :Vec<Fractional> =
|
||||
|
(0..90).map(|x| _cos(x)).collect();
|
||||
|
}
|
||||
|
|
||||
|
fn _cos(d: u32) -> Fractional {
|
||||
|
match d {
|
||||
|
0 => Fractional(1, 1),
|
||||
|
_ => {
|
||||
|
let s = (f64::cos(rad(d)) * PRECISION as f64).round() as i64;
|
||||
|
Fractional(s, PRECISION).reduce()
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
match d {
|
||||
|
90 | 270 => Fractional(0, 1),
|
||||
|
180 => -COSTAB[0],
|
||||
|
1..=89 => COSTAB[d as usize],
|
||||
|
91..=179 => -COSTAB[180 - d as usize],
|
||||
|
181..=269 => -COSTAB[d as usize - 180],
|
||||
|
271..=359 => COSTAB[360 - d as usize],
|
||||
|
_ => cos(d % 360),
|
||||
|
}
|
||||
|
}
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue