#![cfg_attr(not(feature = "std"), no_std)]
#![allow(non_camel_case_types, non_upper_case_globals)]
#![forbid(missing_docs, unconditional_recursion)]
#![cfg_attr(test, deny(warnings))]
#[cfg(feature = "std")]
extern crate core;
use core::{cmp::Ordering, fmt};
macro_rules! const_type {
($(
$(#[$attr:meta])*
pub type $struct:ident;
)*) => {$(
$(#[$attr])*
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct $struct;
impl fmt::Display for $struct {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&f64::from(*self), f)
}
}
)*};
}
macro_rules! const_type_impls {
($($struct:ident => $val:expr, $($t:ident)*;)*) => {$($(
impl From<$struct> for $t {
#[inline]
fn from(_: $struct) -> $t { $val as $t }
}
impl PartialEq<$struct> for $t {
#[inline]
fn eq(&self, _: &$struct) -> bool { *self == ($val as $t) }
}
#[allow(unused_comparisons)]
impl PartialOrd<$struct> for $t {
#[inline]
fn partial_cmp(&self, _: &$struct) -> Option<Ordering> {
self.partial_cmp(&($val as $t))
}
}
impl PartialEq<$t> for $struct {
#[inline]
fn eq(&self, rhs: &$t) -> bool { ($val as $t) == *rhs }
}
#[allow(unused_comparisons)]
impl PartialOrd<$t> for $struct {
#[inline]
fn partial_cmp(&self, rhs: &$t) -> Option<Ordering> {
($val as $t).partial_cmp(rhs)
}
}
)*)*};
}
const_type!(
pub type _0;
pub type _1;
pub type _2;
pub type _45;
pub type _90;
pub type _180;
pub type _270;
pub type _360;
pub type _45_rad;
pub type _90_rad;
pub type _180_rad;
pub type _270_rad;
pub type _360_rad;
);
pub const _pi_4: _45_rad = _45_rad;
pub const _pi_2: _90_rad = _90_rad;
pub const _pi: _180_rad = _180_rad;
pub const _3pi_2: _270_rad = _270_rad;
pub const _2pi: _360_rad = _360_rad;
pub const _tau_8: _45_rad = _45_rad;
pub const _tau_4: _90_rad = _90_rad;
pub const _tau_2: _180_rad = _180_rad;
pub const _3tau_4: _270_rad = _270_rad;
pub const _tau: _360_rad = _360_rad;
const_type_impls!(
_0 => 0, i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_1 => 1, i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_2 => 2, i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_45 => 45, i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_90 => 90, i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_180 => 180, u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_270 => 270, i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_360 => 360, i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64;
_45_rad => 0.78539816339744830961566084581987572, f32 f64;
_90_rad => 1.57079632679489661923132169163975144, f32 f64;
_180_rad => 3.14159265358979323846264338327950288, f32 f64;
_270_rad => 4.71238898038468985769396507491925432, f32 f64;
_360_rad => 6.28318530717958647692528676655900576, f32 f64;
);
#[cfg(test)]
mod tests {
use super::*;
macro_rules! verify_equal {
($struct:ident == $val:expr; $($t:ident)*) => {
[
$val as f32,
$($t::from($struct) as f32),*
].windows(2).for_each(|a| assert!(a[0] == a[1]))
}
}
#[test]
fn basic_ints() {
verify_equal!(_0 == 0; i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
verify_equal!(_1 == 1; i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
verify_equal!(_2 == 2; i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
}
#[test]
fn degrees() {
verify_equal!(_45 == 45; i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
verify_equal!(_90 == 90; i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
verify_equal!(_180 == 180; u8 i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
verify_equal!(_270 == 270; i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
verify_equal!(_360 == 360; i16 u16 i32 u32 i64 u64 i128 u128 isize usize f32 f64);
}
#[test]
fn pi_radians() {
use core::f64::consts::PI;
verify_equal!(_pi_4 == PI / 4.0; f32 f64);
verify_equal!(_pi_2 == PI / 2.0; f32 f64);
verify_equal!(_pi == PI; f32 f64);
verify_equal!(_3pi_2 == 3.0 * PI / 2.0; f32 f64);
verify_equal!(_2pi == 2.0 * PI; f32 f64);
}
#[test]
fn tau_radians() {
use core::f64::consts::PI;
const TAU: f64 = PI * 2.0;
verify_equal!(_tau_8 == TAU / 8.0; f32 f64);
verify_equal!(_tau_4 == TAU / 4.0; f32 f64);
verify_equal!(_tau_2 == TAU / 2.0; f32 f64);
verify_equal!(_3tau_4 == 3.0 * TAU / 4.0; f32 f64);
verify_equal!(_tau == TAU; f32 f64);
}
}