use core::fmt::Debug;
use core::ops::{Add, Mul, Neg, Sub};
use rand::Rng;
use crate::{CartanError, Real};
pub trait Manifold {
type Point: Clone + Debug;
type Tangent: Clone
+ Debug
+ Add<Output = Self::Tangent>
+ Sub<Output = Self::Tangent>
+ Mul<Real, Output = Self::Tangent>
+ Neg<Output = Self::Tangent>;
fn dim(&self) -> usize;
fn ambient_dim(&self) -> usize;
fn injectivity_radius(&self, p: &Self::Point) -> Real;
fn inner(&self, p: &Self::Point, u: &Self::Tangent, v: &Self::Tangent) -> Real;
fn norm(&self, p: &Self::Point, v: &Self::Tangent) -> Real {
let sq = self.inner(p, v, v);
#[cfg(feature = "std")]
return sq.sqrt();
#[cfg(not(feature = "std"))]
return libm::sqrt(sq);
}
fn dist(&self, p: &Self::Point, q: &Self::Point) -> Result<Real, CartanError> {
let v = self.log(p, q)?;
Ok(self.norm(p, &v))
}
fn exp(&self, p: &Self::Point, v: &Self::Tangent) -> Self::Point;
fn log(&self, p: &Self::Point, q: &Self::Point) -> Result<Self::Tangent, CartanError>;
fn project_tangent(&self, p: &Self::Point, v: &Self::Tangent) -> Self::Tangent;
fn project_point(&self, p: &Self::Point) -> Self::Point;
fn zero_tangent(&self, p: &Self::Point) -> Self::Tangent;
fn check_point(&self, p: &Self::Point) -> Result<(), CartanError>;
fn check_tangent(&self, p: &Self::Point, v: &Self::Tangent) -> Result<(), CartanError>;
fn random_point<R: Rng>(&self, rng: &mut R) -> Self::Point;
fn random_tangent<R: Rng>(&self, p: &Self::Point, rng: &mut R) -> Self::Tangent;
}