From 66bd7ee3a3d83306614d1096a06ec1e284b51680 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 27 Jun 2020 17:55:18 -0400 Subject: cos: Add a TryFrom impl for AngularDistance --- src/cos.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/cos.rs b/src/cos.rs index 99a08f4..e7f0a87 100644 --- a/src/cos.rs +++ b/src/cos.rs @@ -7,6 +7,7 @@ use num_traits::real::Real; use num_traits::{one, zero}; use std::cmp::Ordering; +use std::convert::TryFrom; /// Compute the [cosine *similarity*] between two points. /// @@ -397,6 +398,7 @@ where /// /// # use acap::distance::Distance; /// # use acap::cos::AngularDistance; +/// # use std::convert::TryFrom; /// let zero = AngularDistance::from_cos(1.0); /// let pi_2 = AngularDistance::from_cos(0.0); /// let pi = AngularDistance::from_cos(-1.0); @@ -425,8 +427,25 @@ impl PartialOrd for AngularDistance { } } +/// Error type for failed conversions from angles outside of `$[0, \pi]$` to [`AngularDistance`]. +#[derive(Debug)] +pub struct InvalidAngleError; + macro_rules! impl_distance { - ($f:ty) => { + ($f:ident) => { + impl TryFrom<$f> for AngularDistance<$f> { + type Error = InvalidAngleError; + + #[inline] + fn try_from(value: $f) -> Result { + if value >= 0.0 && value <= std::$f::consts::PI { + Ok(Self(value.cos())) + } else { + Err(InvalidAngleError) + } + } + } + impl From> for $f { #[inline] fn from(value: AngularDistance<$f>) -> $f { -- cgit v1.2.3