diff --git a/fractional/src/lib.rs b/fractional/src/lib.rs index dc6389a..ba6fae9 100644 --- a/fractional/src/lib.rs +++ b/fractional/src/lib.rs @@ -22,5 +22,6 @@ extern crate lazy_static; pub mod fractional; pub mod trigonometry; +pub mod vector; use fractional::{Fractional}; diff --git a/fractional/src/main.rs b/fractional/src/main.rs index 2cde98b..f028e29 100644 --- a/fractional/src/main.rs +++ b/fractional/src/main.rs @@ -23,13 +23,8 @@ use std::num::TryFromIntError; use std::f64::consts::PI as FPI; use fractional::fractional::{Fractional, from_vector, Continuous}; -use fractional::trigonometry::{sin, cos, PI}; - -struct Vector { - x: Fractional, - y: Fractional, - z: Fractional, -} +use fractional::trigonometry::{sin, cos, tan, PI}; +use fractional::vector::{Vector}; fn mean(v: &Vec) -> Result { let r = v.iter().fold(0, |acc, x| acc + x); @@ -98,7 +93,8 @@ fn pi() { } fn _sin() { - for d in [9, 17, 31, 45, 73, 123, 213, 312, 876].iter() { + for d in [ 0, 45, 90, 135, 180, 225, 270, 315 + , 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() { let s = sin(*d as i32); let sr :f64 = s.try_into().unwrap(); let _s = f64::sin(*d as f64 * FPI / 180.0); @@ -107,8 +103,20 @@ fn _sin() { } } +fn _tan() { + for d in [ 0, 45, 90, 135, 180, 225, 270, 315 + , 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() { + let s = tan(*d as i32); + let sr :f64 = s.try_into().unwrap(); + let _s = f64::tan(*d as f64 * FPI / 180.0); + + println!("{:>14} : {} {} / {}", format!("tan {}", d), s, sr, _s); + } +} + fn _cos() { - for d in [9, 17, 31, 45, 73, 123, 213, 312, 876].iter() { + for d in [ 0, 45, 90, 135, 180, 225, 270, 315 + , 9, 17, 31, 73, 89, 123, 213, 312, 876 ].iter() { let s = cos(*d as i32); let sr :f64 = s.try_into().unwrap(); let _s = f64::cos(*d as f64 * FPI / 180.0); @@ -117,6 +125,29 @@ fn _cos() { } } +fn _vector() { + let v1 = Vector(1.into(), 2.into(), 3.into()); + let v2 = Vector(2.into(), 2.into(), 3.into()); + let s :Fractional = 3.into(); + + println!("{:>14} : {:?}", "Vector v1", v1); + println!("{:>14} : {:?}", "Vector v2", v2); + println!("{:>14} : {}" , "abs v1", v1.abs()); + println!("{:>14} : {:?}", "-v1", -v1); + println!("{:>14} : {:?}", "v1 + v1", v1 + v1); + println!("{:>14} : {:?}", "v1 - v1", v1 - v1); + println!("{:>14} : {:?}", "v2 - v1", v2 - v1); + println!("{:>14} : {:?}", format!("v1 * {}", s), v1.mul(&s)); + println!("{:>14} : {:?}", "norm v1", v1.norm()); + println!("{:>14} : {}" , "abs norm v1", v1.norm().abs()); + println!("{:>14} : {}" , "distance v1 v2", v1.distance(v2)); + println!("{:>14} : {}" , "distance v2 v1", v2.distance(v1)); + println!("{:>14} : {}" , "v1 dot v2", v1.dot(v2)); + println!("{:>14} : {}" , "v2 dot v1", v2.dot(v1)); + println!("{:>14} : {:?}", "v1 * v2", v1 * v2); + println!("{:>14} : {:?}", "v2 * v1", v2 * v1); +} + fn main() { common_fractional(); println!(); @@ -129,4 +160,8 @@ fn main() { _sin(); println!(); _cos(); + println!(); + _tan(); + println!(); + _vector(); } diff --git a/fractional/src/vector.rs b/fractional/src/vector.rs new file mode 100644 index 0000000..db53c2e --- /dev/null +++ b/fractional/src/vector.rs @@ -0,0 +1,107 @@ +// +// Stuff for manipulating 3 dimensional vectors. +// +// Georg Hopp +// +// 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 . +// +use std::ops::{Add, Sub, Neg, Mul}; +use crate::{Fractional}; + +#[derive(Debug, Eq, Clone, Copy)] +pub struct Vector(pub Fractional, pub Fractional, pub Fractional); + +impl Vector { + pub fn x(self) -> Fractional { self.0 } + pub fn y(self) -> Fractional { self.1 } + pub fn z(self) -> Fractional { self.2 } + + pub fn abs(self) -> Fractional { + let Vector(x, y, z) = self; + (x * x + y * y + z * z).sqrt().unwrap() + } + + pub fn mul(self, s :&Fractional) -> Self { + let Vector(x, y, z) = self; + Vector(x * *s, y * *s, z * *s) + } + + pub fn dot(self, other :Self) -> Fractional { + let Vector(x1, y1, z1) = self; + let Vector(x2, y2, z2) = other; + + x1 * x2 + y1 * y2 + z1 * z2 + } + + pub fn norm(self) -> Self { + let Fractional(n, d) = self.abs(); + // TODO This can result in 0 or inf Vectors… + // Maybe we need to handle zero and inf abs here… + self.mul(&Fractional(d, n)) + } + + pub fn distance(self, other :Self) -> Fractional { + (self - other).abs() + } +} + +impl PartialEq for Vector { + fn eq(&self, other :&Self) -> bool { + let Vector(x1, y1, z1) = self; + let Vector(x2, y2, z2) = other; + x1 == x2 && y1 == y2 && z1 == z2 + } +} + +impl Add for Vector { + type Output = Self; + + fn add(self, other :Self) -> Self { + let Vector(x1, y1, z1) = self; + let Vector(x2, y2, z2) = other; + Vector(x1 + x2, y1 + y2, z1 + z2) + } +} + +impl Sub for Vector { + type Output = Self; + + fn sub(self, other :Self) -> Self { + self + -other + } +} + +impl Neg for Vector { + type Output = Self; + + fn neg(self) -> Self { + let Vector(x, y, z) = self; + Self(-x, -y, -z) + } +} + +impl Mul for Vector { + type Output = Self; + + fn mul(self, other :Self) -> Self { + let Vector(ax, ay, az) = self; + let Vector(bx, by, bz) = other; + + Vector( ay * bz - az * by + , az * bx - ax * bz + , ax * by - ay * bx ) + } +}