Added Radians and Degrees to the trig module.
These types allow the correct tracking of the type of angle measurement being used.
This commit is contained in:
parent
b51a93fc01
commit
40f5c0f462
@ -236,6 +236,30 @@ pub trait Constants
|
|||||||
/// # assert_eq!(val64, 2.0f64 * (std::f64::consts::PI).sqrt().recip());
|
/// # assert_eq!(val64, 2.0f64 * (std::f64::consts::PI).sqrt().recip());
|
||||||
///```
|
///```
|
||||||
const TWO_INVERSE_SQRT_PI: Self;
|
const TWO_INVERSE_SQRT_PI: Self;
|
||||||
|
|
||||||
|
/// PI divided by 180. This is used for radian and degree conversions.
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let val32: f32 = Constants::PI_DIVIDED_BY_180;
|
||||||
|
/// let val64: f64 = Constants::PI_DIVIDED_BY_180;
|
||||||
|
/// # assert_eq!(val32, (std::f32::consts::PI) / 180.0f32);
|
||||||
|
/// # assert_eq!(val64, (std::f64::consts::PI) / 180.0f64);
|
||||||
|
///```
|
||||||
|
const PI_DIVIDED_BY_180: Self;
|
||||||
|
|
||||||
|
/// 180 divided by PI. This is used for radian and degree conversions.
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let val32: f32 = Constants::INVERSE_PI_DIVIDED_BY_180;
|
||||||
|
/// let val64: f64 = Constants::INVERSE_PI_DIVIDED_BY_180;
|
||||||
|
/// # assert_eq!(val32, 180.0f32 / (std::f32::consts::PI));
|
||||||
|
/// # assert_eq!(val64, 180.0f64 / (std::f64::consts::PI));
|
||||||
|
///```
|
||||||
|
const INVERSE_PI_DIVIDED_BY_180: Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -271,6 +295,8 @@ macro_rules! constants_trait_impl
|
|||||||
const INVERSE_PI: $T = 1.0 / $pi;
|
const INVERSE_PI: $T = 1.0 / $pi;
|
||||||
const TWO_INVERSE_PI: $T = 2.0 / $pi;
|
const TWO_INVERSE_PI: $T = 2.0 / $pi;
|
||||||
const TWO_INVERSE_SQRT_PI: $T = 2.0 / $sqrtPI;
|
const TWO_INVERSE_SQRT_PI: $T = 2.0 / $sqrtPI;
|
||||||
|
const PI_DIVIDED_BY_180: $T = $pi / 180.0;
|
||||||
|
const INVERSE_PI_DIVIDED_BY_180: $T = 180.0 / $pi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
#![feature(associated_consts)]
|
#![feature(associated_consts)]
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
|
||||||
mod zero;
|
mod zero;
|
||||||
mod one;
|
mod one;
|
||||||
mod bounded;
|
mod bounded;
|
||||||
@ -15,7 +18,7 @@ mod integer;
|
|||||||
mod real;
|
mod real;
|
||||||
mod constants;
|
mod constants;
|
||||||
|
|
||||||
pub mod trig;
|
mod trig;
|
||||||
pub mod vector;
|
pub mod vector;
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod quaternion;
|
pub mod quaternion;
|
||||||
@ -28,3 +31,4 @@ pub use self::whole::Whole;
|
|||||||
pub use self::integer::Integer;
|
pub use self::integer::Integer;
|
||||||
pub use self::real::Real;
|
pub use self::real::Real;
|
||||||
pub use self::constants::Constants;
|
pub use self::constants::Constants;
|
||||||
|
pub use self::trig::{Degree, Radian};
|
||||||
|
143
src/macros.rs
Normal file
143
src/macros.rs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/// A macro that will define a binary operation for
|
||||||
|
/// a structure and its components.
|
||||||
|
macro_rules! binary_operator_impl
|
||||||
|
{
|
||||||
|
($traitName: ident :: $funcName: ident,
|
||||||
|
$structName: ident {$($field: ident),+},
|
||||||
|
$generic_type: ident) =>
|
||||||
|
{
|
||||||
|
impl<T> $traitName<T> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, val: T) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(val)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> $traitName<T> for &'a $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, val: T) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(val)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> $traitName<&'a T> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, val: &'a T) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(*val)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, T> $traitName<&'b T> for &'a $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, val: &'b T) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(*val)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> $traitName<$structName<T>> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, other: $structName<T>) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(other.$field)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> $traitName<$structName<T>> for &'a $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, other: $structName<T>) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(other.$field)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> $traitName<&'a $structName<T>> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, other: &'a $structName<T>) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(other.$field)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, T> $traitName<&'a $structName<T>> for &'b $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
type Output = $structName<T>;
|
||||||
|
|
||||||
|
fn $funcName(self, other: &'a $structName<T>) -> $structName<T>
|
||||||
|
{
|
||||||
|
$structName::new($(self.$field.$funcName(other.$field)),+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A macro that will define an assignment binary operation for
|
||||||
|
/// a structure and its components.
|
||||||
|
macro_rules! binary_operator_assign_impl
|
||||||
|
{
|
||||||
|
($traitName: ident :: $funcName: ident,
|
||||||
|
$structName: ident {$($field: ident),+},
|
||||||
|
$generic_type: ident) =>
|
||||||
|
{
|
||||||
|
impl<T> $traitName<$structName<T>> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
fn $funcName(&mut self, rhs: $structName<T>)
|
||||||
|
{
|
||||||
|
$(self.$field.$funcName(rhs.$field);)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> $traitName<T> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
fn $funcName(&mut self, rhs: T)
|
||||||
|
{
|
||||||
|
$(self.$field.$funcName(rhs);)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> $traitName<&'a $structName<T>> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
fn $funcName(&mut self, rhs: &'a $structName<T>)
|
||||||
|
{
|
||||||
|
$(self.$field.$funcName(rhs.$field);)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> $traitName<&'a T> for $structName<T>
|
||||||
|
where T: $generic_type
|
||||||
|
{
|
||||||
|
fn $funcName(&mut self, rhs: &'a T)
|
||||||
|
{
|
||||||
|
$(self.$field.$funcName(*rhs);)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
src/real.rs
55
src/real.rs
@ -1,7 +1,8 @@
|
|||||||
use std::num::FpCategory;
|
use std::num::FpCategory;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
|
|
||||||
use super::number::Number;
|
use ::number::Number;
|
||||||
|
use ::trig::Radian;
|
||||||
|
|
||||||
|
|
||||||
// TODO: Double check these examples. Most are OK,
|
// TODO: Double check these examples. Most are OK,
|
||||||
@ -730,7 +731,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn asin(self) -> Self;
|
fn asin(self) -> Radian<Self>;
|
||||||
|
|
||||||
/// Computes the arccosine of a number. Return value is in radians in
|
/// Computes the arccosine of a number. Return value is in radians in
|
||||||
/// the range [0, pi] or NaN if the number is outside the range
|
/// the range [0, pi] or NaN if the number is outside the range
|
||||||
@ -747,7 +748,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn acos(self) -> Self;
|
fn acos(self) -> Radian<Self>;
|
||||||
|
|
||||||
/// Computes the arctangent of a number. Return value is in radians in the
|
/// Computes the arctangent of a number. Return value is in radians in the
|
||||||
/// range [-pi/2, pi/2];
|
/// range [-pi/2, pi/2];
|
||||||
@ -762,7 +763,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// assert!(abs_difference < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn atan(self) -> Self;
|
fn atan(self) -> Radian<Self>;
|
||||||
|
|
||||||
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
|
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
|
||||||
///
|
///
|
||||||
@ -791,7 +792,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
/// assert!(abs_difference_1 < 1e-10);
|
/// assert!(abs_difference_1 < 1e-10);
|
||||||
/// assert!(abs_difference_2 < 1e-10);
|
/// assert!(abs_difference_2 < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn atan2(self, other: Self) -> Self;
|
fn atan2(self, other: Self) -> Radian<Self>;
|
||||||
|
|
||||||
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
|
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
|
||||||
/// `(sin(x), cos(x))`.
|
/// `(sin(x), cos(x))`.
|
||||||
@ -935,7 +936,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn asinh(self) -> Self;
|
fn asinh(self) -> Radian<Self>;
|
||||||
|
|
||||||
/// Inverse hyperbolic cosine function.
|
/// Inverse hyperbolic cosine function.
|
||||||
///
|
///
|
||||||
@ -949,7 +950,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// assert!(abs_difference < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn acosh(self) -> Self;
|
fn acosh(self) -> Radian<Self>;
|
||||||
|
|
||||||
/// Inverse hyperbolic tangent function.
|
/// Inverse hyperbolic tangent function.
|
||||||
///
|
///
|
||||||
@ -968,7 +969,7 @@ pub trait Real : Number + Neg<Output=Self>
|
|||||||
/// //assert!(abs_difference32 < 1.0e-10);
|
/// //assert!(abs_difference32 < 1.0e-10);
|
||||||
/// assert!(abs_difference64 < 1.0e-10);
|
/// assert!(abs_difference64 < 1.0e-10);
|
||||||
/// ```
|
/// ```
|
||||||
fn atanh(self) -> Self;
|
fn atanh(self) -> Radian<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -997,6 +998,18 @@ macro_rules! define_self_bool_func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
macro_rules! define_self_rad_func
|
||||||
|
{
|
||||||
|
($varType: ident, $funcName: ident) =>
|
||||||
|
{
|
||||||
|
fn $funcName(self) -> Radian<$varType>
|
||||||
|
{
|
||||||
|
Radian::new(<$varType>::$funcName(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
macro_rules! define_self_other_func
|
macro_rules! define_self_other_func
|
||||||
{
|
{
|
||||||
@ -1009,6 +1022,18 @@ macro_rules! define_self_other_func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
macro_rules! define_self_other_rad_func
|
||||||
|
{
|
||||||
|
($varType: ident, $funcName: ident) =>
|
||||||
|
{
|
||||||
|
fn $funcName(self, other: $varType) -> Radian<$varType>
|
||||||
|
{
|
||||||
|
Radian::new(<$varType>::$funcName(self, other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A macro to make implementing the trait easier for all the
|
/// A macro to make implementing the trait easier for all the
|
||||||
/// base float types in rust.
|
/// base float types in rust.
|
||||||
macro_rules! real_trait_impl
|
macro_rules! real_trait_impl
|
||||||
@ -1097,16 +1122,16 @@ macro_rules! real_trait_impl
|
|||||||
define_self_func!($varType, cos);
|
define_self_func!($varType, cos);
|
||||||
define_self_func!($varType, sin);
|
define_self_func!($varType, sin);
|
||||||
define_self_func!($varType, tan);
|
define_self_func!($varType, tan);
|
||||||
define_self_func!($varType, acos);
|
define_self_rad_func!($varType, acos);
|
||||||
define_self_func!($varType, asin);
|
define_self_rad_func!($varType, asin);
|
||||||
define_self_func!($varType, atan);
|
define_self_rad_func!($varType, atan);
|
||||||
define_self_func!($varType, cosh);
|
define_self_func!($varType, cosh);
|
||||||
define_self_func!($varType, sinh);
|
define_self_func!($varType, sinh);
|
||||||
define_self_func!($varType, tanh);
|
define_self_func!($varType, tanh);
|
||||||
define_self_func!($varType, acosh);
|
define_self_rad_func!($varType, acosh);
|
||||||
define_self_func!($varType, asinh);
|
define_self_rad_func!($varType, asinh);
|
||||||
define_self_func!($varType, atanh);
|
define_self_rad_func!($varType, atanh);
|
||||||
define_self_other_func!($varType, atan2);
|
define_self_other_rad_func!($varType, atan2);
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
722
src/trig.rs
722
src/trig.rs
@ -1,26 +1,716 @@
|
|||||||
//use super::constants::Constants;
|
use std::ops::{Add, Sub, Mul, Div, Rem, Neg};
|
||||||
use super::real::Real;
|
use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
||||||
|
|
||||||
|
use ::constants::Constants;
|
||||||
|
use ::real::Real;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
pub struct Radians<T> where T: Real
|
/// A degree usually denoted by ° (the degree symbol),
|
||||||
|
/// is a measurement of a plane angle, defined so that a
|
||||||
|
/// full rotation is 360 degrees.
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Degree<T>
|
||||||
{
|
{
|
||||||
pub value: T
|
value: T
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Degrees<T> where T: Real
|
/// A unit of angle, equal to an angle at the center of
|
||||||
|
/// a circle whose arc is equal in length to the radius.
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Radian<T>
|
||||||
{
|
{
|
||||||
pub value: T
|
value: T
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
pub fn acos<T>(x: T) -> T where T: Real
|
|
||||||
{
|
|
||||||
x.acos()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn atan2<T>(x: T, y: T) -> T where T: Real
|
|
||||||
|
|
||||||
|
impl<T> Degree<T> where T: Real
|
||||||
{
|
{
|
||||||
x.atan2(y)
|
/// Create a new Degree structure with the given value.
|
||||||
|
pub fn new(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
Degree
|
||||||
|
{
|
||||||
|
value: val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the arccosine of a number. Return value is in Degrees in
|
||||||
|
/// the range [0, 180] or NaN if the number is outside the range
|
||||||
|
/// [-1, 1].
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::{Degree, Real};
|
||||||
|
///
|
||||||
|
/// let f: Degree<f64>;
|
||||||
|
///
|
||||||
|
/// f = Degree::from(45.0f64);
|
||||||
|
/// assert!((45.0f64 - *Degree::acos(f.cos())) < 1e-10);
|
||||||
|
///```
|
||||||
|
pub fn acos(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = val.acos();
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the arcsine of a number. Return value is in Degrees in
|
||||||
|
/// the range [-57.2957795/2, 57.2957795/2] or NaN if the number is
|
||||||
|
/// outside the range [-1, 1].
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::{Degree, Real};
|
||||||
|
///
|
||||||
|
/// let f: Degree<f64>;
|
||||||
|
///
|
||||||
|
/// f = Degree::from(45.0f64);
|
||||||
|
/// assert!((45.0f64 - *Degree::asin(f.sin())) < 1e-10);
|
||||||
|
///```
|
||||||
|
pub fn asin(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = val.asin();
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the arctangent of a number. Return value is in degrees in the
|
||||||
|
/// range [-57.2957795/2, 57.2957795/2];
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::{Degree, Real};
|
||||||
|
///
|
||||||
|
/// let f: Degree<f64>;
|
||||||
|
///
|
||||||
|
/// f = Degree::from(45.0f64);
|
||||||
|
/// assert!((45.0f64 - *Degree::atan(f.tan())) < 1e-10);
|
||||||
|
///```
|
||||||
|
pub fn atan(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = val.atan();
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse hyperbolic cosine function.
|
||||||
|
pub fn acosh(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = val.acosh();
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse hyperbolic sine function.
|
||||||
|
pub fn asinh(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = val.asinh();
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse hyperbolic tangent function.
|
||||||
|
pub fn atanh(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = val.atanh();
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
|
||||||
|
pub fn atan2(y: T, x: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = y.atan2(x);
|
||||||
|
Degree::from(radians)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the cosine of this angle.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Degree;
|
||||||
|
/// use std::f64;
|
||||||
|
///
|
||||||
|
/// let x: Degree<f64> = Degree::from(360.0f64);
|
||||||
|
///
|
||||||
|
/// let abs_difference = (x.cos() - 1.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn cos(&self) -> T
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = Radian::from(*self);
|
||||||
|
radians.cos()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the sine of this angle.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Degree;
|
||||||
|
/// use std::f64;
|
||||||
|
///
|
||||||
|
/// let x: Degree<f64> = Degree::from(90.0f64);
|
||||||
|
///
|
||||||
|
/// let abs_difference = (x.sin() - 1.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn sin(&self) -> T
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = Radian::from(*self);
|
||||||
|
radians.sin()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the tangent of this angle.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Degree;
|
||||||
|
/// use std::f64;
|
||||||
|
///
|
||||||
|
/// let x: Degree<f64> = Degree::from(45.0f64);
|
||||||
|
///
|
||||||
|
/// let abs_difference = (x.tan() - 1.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-14);
|
||||||
|
/// ```
|
||||||
|
pub fn tan(&self) -> T
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = Radian::from(*self);
|
||||||
|
radians.tan()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hyperbolic cosine function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Degree;
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let e32: f32 = Constants::E;
|
||||||
|
/// let x32: Degree<f32> = Degree::from(f32::INVERSE_PI_DIVIDED_BY_180);
|
||||||
|
/// let f_val32 = x32.cosh();
|
||||||
|
/// let g_val32 = (e32*e32 + 1.0f32)/(2.0f32*e32);
|
||||||
|
/// let abs_difference32 = (f_val32 - g_val32).abs();
|
||||||
|
///
|
||||||
|
/// let e64: f64 = Constants::E;
|
||||||
|
/// let x64: Degree<f64> = Degree::from(f64::INVERSE_PI_DIVIDED_BY_180);
|
||||||
|
/// let f_val64 = x64.cosh();
|
||||||
|
/// let g_val64 = (e64*e64 + 1.0f64)/(2.0f64*e64);
|
||||||
|
/// let abs_difference64 = (f_val64 - g_val64).abs();
|
||||||
|
///
|
||||||
|
/// // Solving cosh() at 1 gives this result
|
||||||
|
/// //assert!(abs_difference32 < 1.0e-10);
|
||||||
|
/// assert!(abs_difference64 < 1.0e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn cosh(&self) -> T
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = Radian::from(*self);
|
||||||
|
radians.cosh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hyperbolic sine function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Degree;
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let e32: f32 = Constants::E;
|
||||||
|
/// let x32: Degree<f32> = Degree::from(f32::INVERSE_PI_DIVIDED_BY_180);
|
||||||
|
///
|
||||||
|
/// let f_val32 = x32.sinh();
|
||||||
|
/// let g_val32 = (e32*e32 - 1.0f32)/(2.0f32*e32);
|
||||||
|
/// let abs_difference32 = (f_val32 - g_val32).abs();
|
||||||
|
///
|
||||||
|
/// let e64: f64 = Constants::E;
|
||||||
|
/// let x64: Degree<f64> = Degree::from(f64::INVERSE_PI_DIVIDED_BY_180);
|
||||||
|
///
|
||||||
|
/// let f_val64 = x64.sinh();
|
||||||
|
/// let g_val64 = (e64*e64 - 1.0f64)/(2.0f64*e64);
|
||||||
|
/// let abs_difference64 = (f_val64 - g_val64).abs();
|
||||||
|
///
|
||||||
|
/// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
|
||||||
|
/// //assert!(abs_difference32 < 1e-10);
|
||||||
|
/// assert!(abs_difference64 < 1e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn sinh(&self) -> T
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = Radian::from(*self);
|
||||||
|
radians.sinh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hyperbolic tangent function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Degree;
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let e32: f32 = Constants::E;
|
||||||
|
/// let x32: Degree<f32> = Degree::from(f32::INVERSE_PI_DIVIDED_BY_180);
|
||||||
|
///
|
||||||
|
/// let f_val32 = x32.tanh();
|
||||||
|
/// let g_val32 = (1.0f32 - e32.powi(-2i32))/(1.0f32 + e32.powi(-2i32));
|
||||||
|
/// let abs_difference32 = (f_val32 - g_val32).abs();
|
||||||
|
///
|
||||||
|
/// let e64: f64 = Constants::E;
|
||||||
|
/// let x64: Degree<f64> = Degree::from(f64::INVERSE_PI_DIVIDED_BY_180);
|
||||||
|
///
|
||||||
|
/// let f_val64 = x64.tanh();
|
||||||
|
/// let g_val64 = (1.0f64 - e64.powi(-2i32))/(1.0f64 + e64.powi(-2i32));
|
||||||
|
/// let abs_difference64 = (f_val64 - g_val64).abs();
|
||||||
|
///
|
||||||
|
/// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
|
||||||
|
/// //assert!(abs_difference32 < 1.0e-10);
|
||||||
|
/// assert!(abs_difference64 < 1.0e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn tanh(&self) -> T
|
||||||
|
{
|
||||||
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = Radian::from(*self);
|
||||||
|
radians.tanh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::ops::Deref for Degree<T> where T: Real
|
||||||
|
{
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T
|
||||||
|
{
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::ops::DerefMut for Degree<T> where T: Real
|
||||||
|
{
|
||||||
|
fn deref_mut<'a>(&'a mut self) -> &'a mut T
|
||||||
|
{
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_operator_impl!(Add::add, Degree {value}, Real);
|
||||||
|
binary_operator_impl!(Sub::sub, Degree {value}, Real);
|
||||||
|
binary_operator_impl!(Mul::mul, Degree {value}, Real);
|
||||||
|
binary_operator_impl!(Div::div, Degree {value}, Real);
|
||||||
|
binary_operator_impl!(Rem::rem, Degree {value}, Real);
|
||||||
|
|
||||||
|
impl<T> ::std::ops::Neg for Degree<T>
|
||||||
|
where T: Neg<Output = T>
|
||||||
|
{
|
||||||
|
type Output = Degree<T>;
|
||||||
|
|
||||||
|
fn neg(self) -> Degree<T>
|
||||||
|
{
|
||||||
|
let mut degrees: Degree<T>;
|
||||||
|
|
||||||
|
degrees = self;
|
||||||
|
degrees.value = degrees.value.neg();
|
||||||
|
degrees
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_operator_assign_impl!(AddAssign::add_assign,
|
||||||
|
Degree {value}, Real);
|
||||||
|
binary_operator_assign_impl!(SubAssign::sub_assign,
|
||||||
|
Degree {value}, Real);
|
||||||
|
binary_operator_assign_impl!(MulAssign::mul_assign,
|
||||||
|
Degree {value}, Real);
|
||||||
|
binary_operator_assign_impl!(DivAssign::div_assign,
|
||||||
|
Degree {value}, Real);
|
||||||
|
binary_operator_assign_impl!(RemAssign::rem_assign,
|
||||||
|
Degree {value}, Real);
|
||||||
|
|
||||||
|
impl ::std::convert::From<Degree<f32>> for f32
|
||||||
|
{
|
||||||
|
fn from(degrees: Degree<f32>) -> f32
|
||||||
|
{
|
||||||
|
degrees.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::convert::From<Degree<f64>> for f64
|
||||||
|
{
|
||||||
|
fn from(degrees: Degree<f64>) -> f64
|
||||||
|
{
|
||||||
|
degrees.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::convert::From<T> for Degree<T> where T: Real
|
||||||
|
{
|
||||||
|
fn from(val: T) -> Degree<T>
|
||||||
|
{
|
||||||
|
Degree::new(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::convert::From<Radian<T>> for Degree<T> where T: Real
|
||||||
|
{
|
||||||
|
fn from(radians: Radian<T>) -> Degree<T>
|
||||||
|
{
|
||||||
|
let degs: T;
|
||||||
|
|
||||||
|
degs = radians.value * Constants::INVERSE_PI_DIVIDED_BY_180;
|
||||||
|
Degree::new(degs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::fmt::Debug for Degree<T>
|
||||||
|
where T: Real
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||||||
|
{
|
||||||
|
::std::fmt::Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::fmt::Display for Degree<T>
|
||||||
|
where T: Real
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||||||
|
{
|
||||||
|
write!(f, "{}", self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Radian<T> where T: Real
|
||||||
|
{
|
||||||
|
/// Create a new Radian structure with the given value.
|
||||||
|
pub fn new(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
Radian
|
||||||
|
{
|
||||||
|
value: val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the arccosine of a number. Return value is in Degrees in
|
||||||
|
/// the range [0, pi] or NaN if the number is outside the range
|
||||||
|
/// [-1, 1].
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::{Constants, Radian, Real};
|
||||||
|
///
|
||||||
|
/// let f: Radian<f64>;
|
||||||
|
///
|
||||||
|
/// f = Radian::from(f64::PI / 4.0f64);
|
||||||
|
/// assert!(((f64::PI / 4.0f64) - *Radian::acos(f.cos())) < 1e-10);
|
||||||
|
///```
|
||||||
|
pub fn acos(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
val.acos()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the arcsine of a number. Return value is in Degrees in
|
||||||
|
/// the range [-pi/2, pi/2] or NaN if the number is
|
||||||
|
/// outside the range [-1, 1].
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::{Constants, Radian, Real};
|
||||||
|
///
|
||||||
|
/// let f: Radian<f64>;
|
||||||
|
///
|
||||||
|
/// f = Radian::from(f64::PI / 4.0f64);
|
||||||
|
/// assert!(((f64::PI / 4.0f64) - *Radian::asin(f.sin())) < 1e-10);
|
||||||
|
///```
|
||||||
|
pub fn asin(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
val.asin()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the arctangent of a number. Return value is in degrees in the
|
||||||
|
/// range [-pi/2, pi/2];
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use sigils::{Constants, Radian, Real};
|
||||||
|
///
|
||||||
|
/// let f: Radian<f64>;
|
||||||
|
///
|
||||||
|
/// f = Radian::from(f64::PI / 4.0f64);
|
||||||
|
/// assert!(((f64::PI / 4.0f64) - *Radian::atan(f.tan())) < 1e-10);
|
||||||
|
///```
|
||||||
|
pub fn atan(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
val.atan()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse hyperbolic cosine function.
|
||||||
|
pub fn acosh(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
val.acosh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse hyperbolic sine function.
|
||||||
|
pub fn asinh(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
val.asinh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inverse hyperbolic tangent function.
|
||||||
|
pub fn atanh(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
val.atanh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
|
||||||
|
pub fn atan2(y: T, x: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
y.atan2(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the cosine of this angle.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Radian;
|
||||||
|
/// use std::f64;
|
||||||
|
///
|
||||||
|
/// let x: Radian<f64> = Radian::from(2.0*f64::consts::PI);
|
||||||
|
///
|
||||||
|
/// let abs_difference = (x.cos() - 1.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn cos(&self) -> T
|
||||||
|
{
|
||||||
|
self.value.cos()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the sine of this angle.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Radian;
|
||||||
|
/// use std::f64;
|
||||||
|
///
|
||||||
|
/// let x: Radian<f64> = Radian::from(f64::consts::PI/2.0);
|
||||||
|
///
|
||||||
|
/// let abs_difference = (x.sin() - 1.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn sin(&self) -> T
|
||||||
|
{
|
||||||
|
self.value.sin()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the tangent of this angle.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Radian;
|
||||||
|
/// use std::f64;
|
||||||
|
///
|
||||||
|
/// let x: Radian<f64> = Radian::from(f64::consts::PI/4.0);
|
||||||
|
///
|
||||||
|
/// let abs_difference = (x.tan() - 1.0).abs();
|
||||||
|
///
|
||||||
|
/// assert!(abs_difference < 1e-14);
|
||||||
|
/// ```
|
||||||
|
pub fn tan(&self) -> T
|
||||||
|
{
|
||||||
|
self.value.tan()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hyperbolic cosine function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Radian;
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let e32: f32 = Constants::E;
|
||||||
|
/// let x32: Radian<f32> = Radian::new(1.0f32);
|
||||||
|
/// let f_val32 = x32.cosh();
|
||||||
|
/// let g_val32 = (e32*e32 + 1.0f32)/(2.0f32*e32);
|
||||||
|
/// let abs_difference32 = (f_val32 - g_val32).abs();
|
||||||
|
///
|
||||||
|
/// let e64: f64 = Constants::E;
|
||||||
|
/// let x64: Radian<f64> = Radian::new(1.0f64);
|
||||||
|
/// let f_val64 = x64.cosh();
|
||||||
|
/// let g_val64 = (e64*e64 + 1.0f64)/(2.0f64*e64);
|
||||||
|
/// let abs_difference64 = (f_val64 - g_val64).abs();
|
||||||
|
///
|
||||||
|
/// // Solving cosh() at 1 gives this result
|
||||||
|
/// //assert!(abs_difference32 < 1.0e-10);
|
||||||
|
/// assert!(abs_difference64 < 1.0e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn cosh(&self) -> T
|
||||||
|
{
|
||||||
|
self.value.cosh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hyperbolic sine function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Radian;
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let e32: f32 = Constants::E;
|
||||||
|
/// let x32: Radian<f32> = Radian::from(1.0f32);
|
||||||
|
///
|
||||||
|
/// let f_val32 = x32.sinh();
|
||||||
|
/// let g_val32 = (e32*e32 - 1.0f32)/(2.0f32*e32);
|
||||||
|
/// let abs_difference32 = (f_val32 - g_val32).abs();
|
||||||
|
///
|
||||||
|
/// let e64: f64 = Constants::E;
|
||||||
|
/// let x64: Radian<f64> = Radian::from(1.0f64);
|
||||||
|
///
|
||||||
|
/// let f_val64 = x64.sinh();
|
||||||
|
/// let g_val64 = (e64*e64 - 1.0f64)/(2.0f64*e64);
|
||||||
|
/// let abs_difference64 = (f_val64 - g_val64).abs();
|
||||||
|
///
|
||||||
|
/// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
|
||||||
|
/// //assert!(abs_difference32 < 1e-10);
|
||||||
|
/// assert!(abs_difference64 < 1e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn sinh(&self) -> T
|
||||||
|
{
|
||||||
|
self.value.sinh()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hyperbolic tangent function.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use sigils::Radian;
|
||||||
|
/// use sigils::Constants;
|
||||||
|
///
|
||||||
|
/// let e32: f32 = Constants::E;
|
||||||
|
/// let x32: Radian<f32> = Radian::from(1.0f32);
|
||||||
|
///
|
||||||
|
/// let f_val32 = x32.tanh();
|
||||||
|
/// let g_val32 = (1.0f32 - e32.powi(-2i32))/(1.0f32 + e32.powi(-2i32));
|
||||||
|
/// let abs_difference32 = (f_val32 - g_val32).abs();
|
||||||
|
///
|
||||||
|
/// let e64: f64 = Constants::E;
|
||||||
|
/// let x64: Radian<f64> = Radian::from(1.0f64);
|
||||||
|
///
|
||||||
|
/// let f_val64 = x64.tanh();
|
||||||
|
/// let g_val64 = (1.0f64 - e64.powi(-2i32))/(1.0f64 + e64.powi(-2i32));
|
||||||
|
/// let abs_difference64 = (f_val64 - g_val64).abs();
|
||||||
|
///
|
||||||
|
/// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
|
||||||
|
/// //assert!(abs_difference32 < 1.0e-10);
|
||||||
|
/// assert!(abs_difference64 < 1.0e-10);
|
||||||
|
/// ```
|
||||||
|
pub fn tanh(&self) -> T
|
||||||
|
{
|
||||||
|
self.value.tanh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::ops::Deref for Radian<T> where T: Real
|
||||||
|
{
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T
|
||||||
|
{
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::ops::DerefMut for Radian<T> where T: Real
|
||||||
|
{
|
||||||
|
fn deref_mut<'a>(&'a mut self) -> &'a mut T
|
||||||
|
{
|
||||||
|
&mut self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_operator_impl!(Add::add, Radian {value}, Real);
|
||||||
|
binary_operator_impl!(Sub::sub, Radian {value}, Real);
|
||||||
|
binary_operator_impl!(Mul::mul, Radian {value}, Real);
|
||||||
|
binary_operator_impl!(Div::div, Radian {value}, Real);
|
||||||
|
binary_operator_impl!(Rem::rem, Radian {value}, Real);
|
||||||
|
|
||||||
|
impl<T> ::std::ops::Neg for Radian<T>
|
||||||
|
where T: Neg<Output = T>
|
||||||
|
{
|
||||||
|
type Output = Radian<T>;
|
||||||
|
|
||||||
|
fn neg(self) -> Radian<T>
|
||||||
|
{
|
||||||
|
let mut radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = self;
|
||||||
|
radians.value = radians.value.neg();
|
||||||
|
radians
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binary_operator_assign_impl!(AddAssign::add_assign,
|
||||||
|
Radian {value}, Real);
|
||||||
|
binary_operator_assign_impl!(SubAssign::sub_assign,
|
||||||
|
Radian {value}, Real);
|
||||||
|
binary_operator_assign_impl!(MulAssign::mul_assign,
|
||||||
|
Radian {value}, Real);
|
||||||
|
binary_operator_assign_impl!(DivAssign::div_assign,
|
||||||
|
Radian {value}, Real);
|
||||||
|
binary_operator_assign_impl!(RemAssign::rem_assign,
|
||||||
|
Radian {value}, Real);
|
||||||
|
|
||||||
|
impl ::std::convert::From<Radian<f32>> for f32
|
||||||
|
{
|
||||||
|
fn from(radians: Radian<f32>) -> f32
|
||||||
|
{
|
||||||
|
radians.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::convert::From<Radian<f64>> for f64
|
||||||
|
{
|
||||||
|
fn from(radians: Radian<f64>) -> f64
|
||||||
|
{
|
||||||
|
radians.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::convert::From<T> for Radian<T> where T: Real
|
||||||
|
{
|
||||||
|
fn from(val: T) -> Radian<T>
|
||||||
|
{
|
||||||
|
Radian::new(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::convert::From<Degree<T>> for Radian<T>
|
||||||
|
where T: Real
|
||||||
|
{
|
||||||
|
fn from(degrees: Degree<T>) -> Radian<T>
|
||||||
|
{
|
||||||
|
let rads: T;
|
||||||
|
|
||||||
|
rads = degrees.value * Constants::PI_DIVIDED_BY_180;
|
||||||
|
Radian::new(rads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::fmt::Debug for Radian<T>
|
||||||
|
where T: Real
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||||||
|
{
|
||||||
|
::std::fmt::Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ::std::fmt::Display for Radian<T>
|
||||||
|
where T: Real
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
|
||||||
|
{
|
||||||
|
write!(f, "{}", self.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
251
src/vector.rs
251
src/vector.rs
@ -9,7 +9,7 @@ use ::zero::Zero;
|
|||||||
use ::one::One;
|
use ::one::One;
|
||||||
use ::number::Number;
|
use ::number::Number;
|
||||||
use ::real::Real;
|
use ::real::Real;
|
||||||
use ::trig::{acos, atan2};
|
use ::trig::Radian;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -264,13 +264,15 @@ pub trait Vector<T>: Debug + Display + Clone + Default + Zero + One
|
|||||||
/// // the components are 3. Then get the
|
/// // the components are 3. Then get the
|
||||||
/// // dot product of the two Vectors.
|
/// // dot product of the two Vectors.
|
||||||
/// use sigils::vector::*;
|
/// use sigils::vector::*;
|
||||||
|
/// use sigils::Radian;
|
||||||
///
|
///
|
||||||
/// let vector: Vector3<i64> = Vector3::<i64>::from_value(3i64);
|
/// let vector: Vector3<i32> = Vector3::<i32>::from_value(3i32);
|
||||||
/// let vector_two: Vector3<i64> = Vector3::<i64>::from_value(3i64);
|
/// let vector_two: Vector3<i32> = Vector3::<i32>::from_value(3i32);
|
||||||
/// let dotProduct: i64 = vector.dot(&vector_two);
|
/// let dotProduct: Radian<f64> = vector.dot(&vector_two);
|
||||||
/// # assert_eq!(dotProduct, 27i64);
|
/// # assert_eq!(*dotProduct, 27f64);
|
||||||
///```
|
///```
|
||||||
fn dot(&self, vector: &Self) -> T;
|
fn dot<R>(&self, vector: &Self) -> Radian<R>
|
||||||
|
where R: Real + ::std::convert::From<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the [EuclideanVector][1] trait.
|
/// Defines the [EuclideanVector][1] trait.
|
||||||
@ -290,12 +292,14 @@ pub trait EuclideanVector<T> : Vector<T> where T: Real
|
|||||||
///```
|
///```
|
||||||
fn get_length(&self) -> T
|
fn get_length(&self) -> T
|
||||||
{
|
{
|
||||||
let length: T;
|
let sq_rt: T;
|
||||||
|
let length: Radian<T>;
|
||||||
|
|
||||||
length = self.dot(self).sqrt();
|
length = self.dot(self);
|
||||||
assert!(length.is_finite());
|
sq_rt = (*length).sqrt();
|
||||||
|
assert!(sq_rt.is_finite());
|
||||||
|
|
||||||
length
|
sq_rt
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the squared length of the Vector.
|
/// Get the squared length of the Vector.
|
||||||
@ -310,7 +314,10 @@ pub trait EuclideanVector<T> : Vector<T> where T: Real
|
|||||||
///```
|
///```
|
||||||
fn get_length_squared(&self) -> T
|
fn get_length_squared(&self) -> T
|
||||||
{
|
{
|
||||||
self.dot(self)
|
let radians: Radian<T>;
|
||||||
|
|
||||||
|
radians = self.dot(self);
|
||||||
|
*radians
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalizes the Vector by multplying all the
|
/// Normalizes the Vector by multplying all the
|
||||||
@ -362,15 +369,18 @@ pub trait EuclideanVector<T> : Vector<T> where T: Real
|
|||||||
// TODO: Add an example here.
|
// TODO: Add an example here.
|
||||||
fn is_perpendicular_to(&self, vector: &Self) -> bool
|
fn is_perpendicular_to(&self, vector: &Self) -> bool
|
||||||
{
|
{
|
||||||
|
let dot: T;
|
||||||
|
|
||||||
// TODO: Make this work with a fudge factor since floats
|
// TODO: Make this work with a fudge factor since floats
|
||||||
// are tricky.
|
// are tricky.
|
||||||
self.dot(vector) == T::zero()
|
dot = *self.dot(vector);
|
||||||
|
dot == T::zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the angle between this vector and
|
/// Calculates the angle between this vector and
|
||||||
/// another Vector, in radians.
|
/// another Vector, in radians.
|
||||||
// TODO: Add an example here.
|
// TODO: Add an example here.
|
||||||
fn angle(&self, vector: &Self) -> T;
|
fn angle(&self, vector: &Self) -> Radian<T>;
|
||||||
|
|
||||||
/// Linearly interpolate the length of this Vector
|
/// Linearly interpolate the length of this Vector
|
||||||
/// towards the length of another Vector by a given amount.
|
/// towards the length of another Vector by a given amount.
|
||||||
@ -425,141 +435,6 @@ macro_rules! perform_method_on_components
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A macro that will define a binary operation for
|
|
||||||
/// a Vector and its components.
|
|
||||||
macro_rules! binary_operator_impl
|
|
||||||
{
|
|
||||||
($traitName: ident :: $funcName: ident,
|
|
||||||
$structName: ident {$($field: ident),+}) =>
|
|
||||||
{
|
|
||||||
impl<T> $traitName<T> for $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, scalar: T) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(scalar)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> $traitName<T> for &'a $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, scalar: T) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(scalar)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> $traitName<&'a T> for $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, scalar: &'a T) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(*scalar)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, T> $traitName<&'b T> for &'a $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, scalar: &'b T) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(*scalar)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> $traitName<$structName<T>> for $structName<T>
|
|
||||||
where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, vector: $structName<T>) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(vector.$field)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> $traitName<$structName<T>> for &'a $structName<T>
|
|
||||||
where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, vector: $structName<T>) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(vector.$field)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> $traitName<&'a $structName<T>> for $structName<T>
|
|
||||||
where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, vector: &'a $structName<T>) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(vector.$field)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, T> $traitName<&'a $structName<T>> for &'b $structName<T>
|
|
||||||
where T: Number
|
|
||||||
{
|
|
||||||
type Output = $structName<T>;
|
|
||||||
|
|
||||||
fn $funcName(self, vector: &'a $structName<T>) -> $structName<T>
|
|
||||||
{
|
|
||||||
$structName::new($(self.$field.$funcName(vector.$field)),+)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A macro that will define a binary operation for
|
|
||||||
/// a Vector and its components.
|
|
||||||
macro_rules! binary_operator_assign_impl
|
|
||||||
{
|
|
||||||
($traitName: ident :: $funcName: ident,
|
|
||||||
$structName: ident {$($field: ident),+}) =>
|
|
||||||
{
|
|
||||||
impl<T> $traitName<$structName<T>> for $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
fn $funcName(&mut self, rhs: $structName<T>)
|
|
||||||
{
|
|
||||||
$(self.$field.$funcName(rhs.$field);)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> $traitName<T> for $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
fn $funcName(&mut self, rhs: T)
|
|
||||||
{
|
|
||||||
$(self.$field.$funcName(rhs);)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> $traitName<&'a $structName<T>> for $structName<T>
|
|
||||||
where T: Number
|
|
||||||
{
|
|
||||||
fn $funcName(&mut self, rhs: &'a $structName<T>)
|
|
||||||
{
|
|
||||||
$(self.$field.$funcName(rhs.$field);)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> $traitName<&'a T> for $structName<T> where T: Number
|
|
||||||
{
|
|
||||||
fn $funcName(&mut self, rhs: &'a T)
|
|
||||||
{
|
|
||||||
$(self.$field.$funcName(*rhs);)+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A macro that defines a Vector structure
|
/// A macro that defines a Vector structure
|
||||||
/// that implements the Vector trait.
|
/// that implements the Vector trait.
|
||||||
macro_rules! define_vector
|
macro_rules! define_vector
|
||||||
@ -589,21 +464,6 @@ macro_rules! define_vector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give this vector a negation function when the
|
|
||||||
// type stored in it is negatable.
|
|
||||||
impl<$T> $structName<$T> where T: Copy + Neg<Output = $T>
|
|
||||||
{
|
|
||||||
/// Negate this vector in-place (multiply by -1).
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
///
|
|
||||||
///```
|
|
||||||
pub fn negate(&mut self)
|
|
||||||
{
|
|
||||||
$(self.$field = -self.$field);+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Vector<T> for $structName<T> where T: Number
|
impl<T> Vector<T> for $structName<T> where T: Number
|
||||||
{
|
{
|
||||||
fn from_value(val: T) -> $structName<T>
|
fn from_value(val: T) -> $structName<T>
|
||||||
@ -678,15 +538,19 @@ macro_rules! define_vector
|
|||||||
perform_method_on_components!(mul, {$(self.$field),+})
|
perform_method_on_components!(mul, {$(self.$field),+})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dot(&self, vector: &$structName<T>) -> T
|
fn dot<R>(&self, vector: &$structName<T>) -> Radian<R>
|
||||||
|
where R: Real + ::std::convert::From<T>
|
||||||
{
|
{
|
||||||
self.mul(vector).get_sum()
|
let dot: R;
|
||||||
|
dot = R::from(self.mul(vector).get_sum());
|
||||||
|
Radian::new(dot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement the Debug trait for the Vector.
|
// Implement the Debug trait for the Vector.
|
||||||
impl<T> Debug for $structName<T> where T: Number
|
impl<T> Debug for $structName<T> where T: Number
|
||||||
{
|
{
|
||||||
|
#[allow(unused_assignments)]
|
||||||
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error>
|
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
let mut count: u8;
|
let mut count: u8;
|
||||||
@ -695,12 +559,12 @@ macro_rules! define_vector
|
|||||||
// pretty up the printing.
|
// pretty up the printing.
|
||||||
count = self.get_size();
|
count = self.get_size();
|
||||||
|
|
||||||
write!(formatter, "<");
|
try!(write!(formatter, "<"));
|
||||||
$(
|
$(
|
||||||
write!(formatter, "{:?}", self.$field);
|
try!(write!(formatter, "{:?}", self.$field));
|
||||||
if count > 0
|
if count > 0
|
||||||
{
|
{
|
||||||
write!(formatter, ", ");
|
try!(write!(formatter, ", "));
|
||||||
}
|
}
|
||||||
count -= 1;
|
count -= 1;
|
||||||
)*
|
)*
|
||||||
@ -711,6 +575,7 @@ macro_rules! define_vector
|
|||||||
// Implement the Display trait for the Vector.
|
// Implement the Display trait for the Vector.
|
||||||
impl<T> Display for $structName<T> where T: Number
|
impl<T> Display for $structName<T> where T: Number
|
||||||
{
|
{
|
||||||
|
#[allow(unused_assignments)]
|
||||||
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error>
|
fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
let mut count: u8;
|
let mut count: u8;
|
||||||
@ -719,12 +584,12 @@ macro_rules! define_vector
|
|||||||
// pretty up the printing.
|
// pretty up the printing.
|
||||||
count = self.get_size();
|
count = self.get_size();
|
||||||
|
|
||||||
write!(formatter, "<");
|
try!(write!(formatter, "<"));
|
||||||
$(
|
$(
|
||||||
write!(formatter, "{}", self.$field);
|
try!(write!(formatter, "{}", self.$field));
|
||||||
if count > 1
|
if count > 1
|
||||||
{
|
{
|
||||||
write!(formatter, ", ");
|
try!(write!(formatter, ", "));
|
||||||
}
|
}
|
||||||
count -= 1;
|
count -= 1;
|
||||||
)*
|
)*
|
||||||
@ -770,23 +635,23 @@ macro_rules! define_vector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implement the binary operations for this Vector structure.
|
// Implement the binary operations for this Vector structure.
|
||||||
binary_operator_impl!(Add::add, $structName {$($field),+});
|
binary_operator_impl!(Add::add, $structName {$($field),+}, Number);
|
||||||
binary_operator_impl!(Sub::sub, $structName {$($field),+});
|
binary_operator_impl!(Sub::sub, $structName {$($field),+}, Number);
|
||||||
binary_operator_impl!(Mul::mul, $structName {$($field),+});
|
binary_operator_impl!(Mul::mul, $structName {$($field),+}, Number);
|
||||||
binary_operator_impl!(Div::div, $structName {$($field),+});
|
binary_operator_impl!(Div::div, $structName {$($field),+}, Number);
|
||||||
binary_operator_impl!(Rem::rem, $structName {$($field),+});
|
binary_operator_impl!(Rem::rem, $structName {$($field),+}, Number);
|
||||||
|
|
||||||
// Handle the assignment operators.
|
// Handle the assignment operators.
|
||||||
binary_operator_assign_impl!(AddAssign::add_assign,
|
binary_operator_assign_impl!(AddAssign::add_assign,
|
||||||
$structName {$($field),+});
|
$structName {$($field),+}, Number);
|
||||||
binary_operator_assign_impl!(SubAssign::sub_assign,
|
binary_operator_assign_impl!(SubAssign::sub_assign,
|
||||||
$structName {$($field),+});
|
$structName {$($field),+}, Number);
|
||||||
binary_operator_assign_impl!(MulAssign::mul_assign,
|
binary_operator_assign_impl!(MulAssign::mul_assign,
|
||||||
$structName {$($field),+});
|
$structName {$($field),+}, Number);
|
||||||
binary_operator_assign_impl!(DivAssign::div_assign,
|
binary_operator_assign_impl!(DivAssign::div_assign,
|
||||||
$structName {$($field),+});
|
$structName {$($field),+}, Number);
|
||||||
binary_operator_assign_impl!(RemAssign::rem_assign,
|
binary_operator_assign_impl!(RemAssign::rem_assign,
|
||||||
$structName {$($field),+});
|
$structName {$($field),+}, Number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,6 +662,7 @@ define_vector!(Vector3<T> {x, y, z}, 3u8);
|
|||||||
define_vector!(Vector4<T> {x, y, z, w}, 4u8);
|
define_vector!(Vector4<T> {x, y, z, w}, 4u8);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Implements operations specific to the different
|
// Implements operations specific to the different
|
||||||
// Vector structure sizes.
|
// Vector structure sizes.
|
||||||
impl<T> Vector2<T> where T: Number
|
impl<T> Vector2<T> where T: Number
|
||||||
@ -833,9 +699,13 @@ impl<T> Vector2<T> where T: Number
|
|||||||
|
|
||||||
/// Calculate the perpendicular dot product.
|
/// Calculate the perpendicular dot product.
|
||||||
// TODO: Add an example.
|
// TODO: Add an example.
|
||||||
pub fn perpendicular_dot(&self, vector: &Vector2<T>) -> T
|
pub fn perpendicular_dot<R>(&self, vector: &Vector2<T>) -> Radian<R>
|
||||||
|
where R: Real + ::std::convert::From<T>
|
||||||
{
|
{
|
||||||
(self.x * vector.y) - (self.y * vector.x)
|
let val: R;
|
||||||
|
|
||||||
|
val = R::from((self.x * vector.y) - (self.y * vector.x));
|
||||||
|
Radian::new(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a z component with the given value to the Vector.
|
/// Adds a z component with the given value to the Vector.
|
||||||
@ -1056,24 +926,27 @@ impl<T> Vector4<T> where T: Number
|
|||||||
// Implement the angle specific portion of the EuclideanVector.
|
// Implement the angle specific portion of the EuclideanVector.
|
||||||
impl<T> EuclideanVector<T> for Vector2<T> where T: Real
|
impl<T> EuclideanVector<T> for Vector2<T> where T: Real
|
||||||
{
|
{
|
||||||
fn angle(&self, vector: &Vector2<T>) -> T
|
fn angle(&self, vector: &Vector2<T>) -> Radian<T>
|
||||||
{
|
{
|
||||||
atan2(self.perpendicular_dot(vector), self.dot(vector))
|
Radian::atan2((*self.perpendicular_dot(vector)), (*self.dot(vector)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> EuclideanVector<T> for Vector3<T> where T: Real
|
impl<T> EuclideanVector<T> for Vector3<T> where T: Real
|
||||||
{
|
{
|
||||||
fn angle(&self, vector: &Vector3<T>) -> T
|
fn angle(&self, vector: &Vector3<T>) -> Radian<T>
|
||||||
{
|
{
|
||||||
atan2(self.cross(vector).get_length(), self.dot(vector))
|
Radian::atan2(self.cross(vector).get_length(), (*self.dot(vector)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> EuclideanVector<T> for Vector4<T> where T: Real
|
impl<T> EuclideanVector<T> for Vector4<T> where T: Real
|
||||||
{
|
{
|
||||||
fn angle(&self, vector: &Vector4<T>) -> T
|
fn angle(&self, vector: &Vector4<T>) -> Radian<T>
|
||||||
{
|
{
|
||||||
acos(self.dot(vector) / (self.get_length() * vector.get_length()))
|
let dot: T;
|
||||||
|
|
||||||
|
dot = *self.dot(vector);
|
||||||
|
Radian::acos(dot / self.get_length() * vector.get_length())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user