hcomplex/transform/moebius/
base.rs1use core::ops::{Neg, Add, Sub, Mul, Div};
2use num_traits::{Zero, One, NumCast};
3use crate::{*, transform::*};
4
5
6#[derive(Copy, Clone, Debug, PartialEq)]
7pub struct Moebius<U> {
8 data: [U; 4],
9}
10
11impl<U> From<[U; 4]> for Moebius<U> {
12 fn from(array: [U; 4]) -> Self {
13 Self { data: array }
14 }
15}
16impl<U> Into<[U; 4]> for Moebius<U> {
17 fn into(self) -> [U; 4] {
18 self.data
19 }
20}
21
22impl<U> Moebius<U> {
23 pub fn new(a: U, b: U, c: U, d: U) -> Self {
24 Self::from([a, b, c, d])
25 }
26
27 pub fn a_ref(&self) -> &U { &self.data[0] }
28 pub fn b_ref(&self) -> &U { &self.data[1] }
29 pub fn c_ref(&self) -> &U { &self.data[2] }
30 pub fn d_ref(&self) -> &U { &self.data[3] }
31
32 pub fn a_mut(&mut self) -> &mut U { &mut self.data[0] }
33 pub fn b_mut(&mut self) -> &mut U { &mut self.data[1] }
34 pub fn c_mut(&mut self) -> &mut U { &mut self.data[2] }
35 pub fn d_mut(&mut self) -> &mut U { &mut self.data[3] }
36}
37
38impl<U: Clone> Moebius<U> {
39 pub fn a(&self) -> U { self.data[0].clone() }
40 pub fn b(&self) -> U { self.data[1].clone() }
41 pub fn c(&self) -> U { self.data[2].clone() }
42 pub fn d(&self) -> U { self.data[3].clone() }
43}
44
45impl<U: Zero + One> Identity for Moebius<U> {
46 fn identity() -> Self {
47 Self::new(U::one(), U::zero(), U::zero(), U::one())
48 }
49}
50
51impl<U> Chain<U> for Moebius<U> where U: Add<Output=U> + Mul<Output=U> + Div<Output=U> + Clone {
52 fn chain(self, other: Self) -> Self {
53 Self::new(
54 self.a()*other.a() + self.b()*other.c(),
55 self.a()*other.b() + self.b()*other.d(),
56 self.c()*other.a() + self.d()*other.c(),
57 self.c()*other.b() + self.d()*other.d(),
58 )
59 }
60}
61
62impl<U> Transform<U> for Moebius<U> where U: Add<Output=U> + Mul<Output=U> + Div<Output=U> + Clone {
63 fn apply(&self, x: U) -> U {
64 (self.a()*x.clone() + self.b())/(self.c()*x + self.d())
65 }
66}
67impl<T: Algebra + Clone, U: Algebra<T> + Clone> Transform<Construct<T, Construct<T, U>>> for Moebius<Construct<T, U>> {
68 fn apply(&self, x: Construct<T, Construct<T, U>>) -> Construct<T, Construct<T, U>> {
69 (self.a()*x.clone() + self.b())/(self.c()*x + self.d())
70 }
71}
72
73impl<U: Neg<Output=U> + Mul<Output=U> + Div<Output=U> + Sub<Output=U> + Clone> Moebius<U> {
74 pub fn det(&self) -> U {
75 self.a()*self.d() - self.b()*self.c()
76 }
77 pub fn normalize(mut self) -> Self {
78 let det = self.det();
79 self.data.iter_mut().for_each(|x| *x = x.clone() / det.clone());
80 self
81 }
82}
83
84impl<T: Algebra + Clone> Deriv<Complex<T>> for Moebius<Complex<T>> {
85 fn deriv(&self, p: Complex<T>) -> Complex<T> {
86 let u: Complex<T> = self.a() * p.clone() + self.b();
87 let d: Complex<T> = self.c() * p + self.d();
88 return (self.a() * d.clone() - u * self.c()) / (d.clone() * d);
89 }
90}
91
92impl<T: NumCast + Algebra + Dot<Output=T> + Clone> DerivDir<Quaternion<T>> for Moebius<Complex<T>> {
93 fn deriv_dir(&self, p: Quaternion<T>, v: Quaternion<T>) -> Quaternion<T> {
94 let u = self.a() * p.clone() + self.b();
95 let d = self.c() * p + self.d();
96 let d2 = d.clone().abs_sqr();
97 let g1 = (self.a() * v.clone()) / d.clone();
98 let g21 = (self.c() * v.clone()).conj();
99 let g22 = d.clone().conj() * (d.dot(self.c() * v) * T::from(2).unwrap() / d2.clone());
100 let g2 = u * ((g21 - g22) / d2);
101 return g1 + g2;
102 }
103}