11//! Core CORDIC iteration implementations.
22//!
3- //! The CORDIC algorithm operates in two modes, each with two directions :
3+ //! CORDIC vectoring mode drives y toward zero while accumulating angles :
44//!
5- //! | Mode | Rotation (z → 0) | Vectoring (y → 0) |
6- //! |------|------------------|------------------ -|
7- //! | Circular | sin, cos | atan |
8- //! | Hyperbolic | sinh, cosh | atanh, ln |
5+ //! | Mode | Vectoring (y → 0) |
6+ //! |------|-------------------|
7+ //! | Circular | atan |
8+ //! | Hyperbolic | atanh, ln |
99//!
1010//! # Algorithm
1111//!
2222//! - angle[i] = atan(2^-i) for circular, atanh(2^-i) for hyperbolic
2323
2424use crate :: tables:: hyperbolic:: needs_repeat;
25- use crate :: tables:: {
26- ATAN_TABLE , ATANH_TABLE , CIRCULAR_GAIN_INV , HYPERBOLIC_GAIN , HYPERBOLIC_GAIN_INV ,
27- } ;
25+ use crate :: tables:: { ATAN_TABLE , ATANH_TABLE } ;
2826use crate :: traits:: CordicNumber ;
2927
3028/// Table lookup for CORDIC iteration.
@@ -43,83 +41,6 @@ const fn table_lookup(table: &[i64; 64], index: u32) -> i64 {
4341 table[ index as usize ]
4442}
4543
46- /// Returns the CORDIC scale factor (1/K ≈ 0.6073).
47- ///
48- /// Pre-multiply initial vectors by this to compensate for CORDIC gain.
49- #[ inline]
50- #[ must_use]
51- pub fn cordic_scale_factor < T : CordicNumber > ( ) -> T {
52- T :: from_i1f63 ( CIRCULAR_GAIN_INV )
53- }
54-
55- /// Returns the hyperbolic gain factor (`K_h` ≈ 0.8282).
56- ///
57- /// After hyperbolic CORDIC iterations, results are scaled by `1/K_h`.
58- /// To compensate, divide by `K_h` (or multiply by `1/K_h`).
59- #[ inline]
60- #[ must_use]
61- pub fn hyperbolic_gain < T : CordicNumber > ( ) -> T {
62- T :: from_i1f63 ( HYPERBOLIC_GAIN )
63- }
64-
65- /// Returns the inverse hyperbolic gain factor (`1/K_h` ≈ 1.2075).
66- ///
67- /// Pre-multiply initial vectors by this to compensate for hyperbolic CORDIC gain.
68- /// This uses a precomputed constant, avoiding runtime division.
69- #[ inline]
70- #[ must_use]
71- pub fn hyperbolic_gain_inv < T : CordicNumber > ( ) -> T {
72- T :: from_i2f62 ( HYPERBOLIC_GAIN_INV )
73- }
74-
75- /// Performs circular CORDIC in rotation mode.
76- ///
77- /// Given an initial vector (x, y) and angle z, rotates the vector by angle z.
78- /// After iteration:
79- /// - x ≈ K * (x₀ * cos(z₀) - y₀ * sin(z₀))
80- /// - y ≈ K * (y₀ * cos(z₀) + x₀ * sin(z₀))
81- /// - z ≈ 0
82- ///
83- /// Where K is the circular gain factor (~1.6468).
84- ///
85- /// # Arguments
86- ///
87- /// * `x` - Initial x coordinate
88- /// * `y` - Initial y coordinate
89- /// * `z` - Angle to rotate by (in radians)
90- ///
91- /// # Returns
92- ///
93- /// Tuple of (x, y, z) after CORDIC iterations.
94- ///
95- /// # Note
96- ///
97- /// The input angle should be in the range [-1.74, 1.74] radians for
98- /// convergence. Use argument reduction for larger angles.
99- #[ must_use]
100- pub fn circular_rotation < T : CordicNumber > ( mut x : T , mut y : T , mut z : T ) -> ( T , T , T ) {
101- let zero = T :: zero ( ) ;
102- let iterations = T :: frac_bits ( ) . min ( 62 ) ;
103-
104- for i in 0 ..iterations {
105- let angle = T :: from_i1f63 ( table_lookup ( & ATAN_TABLE , i) ) ;
106-
107- if z >= zero {
108- let x_new = x. saturating_sub ( y >> i) ;
109- y = y. saturating_add ( x >> i) ;
110- x = x_new;
111- z -= angle;
112- } else {
113- let x_new = x. saturating_add ( y >> i) ;
114- y = y. saturating_sub ( x >> i) ;
115- x = x_new;
116- z += angle;
117- }
118- }
119-
120- ( x, y, z)
121- }
122-
12344/// Performs circular CORDIC in vectoring mode.
12445///
12546/// Given an initial vector (x, y), rotates it until y ≈ 0.
@@ -167,76 +88,6 @@ pub fn circular_vectoring<T: CordicNumber>(mut x: T, mut y: T, mut z: T) -> (T,
16788 ( x, y, z)
16889}
16990
170- /// Performs hyperbolic CORDIC in rotation mode.
171- ///
172- /// Given initial values (x, y, z), performs hyperbolic pseudo-rotations
173- /// to drive z toward zero.
174- ///
175- /// After iteration:
176- /// - x ≈ `K_h` * (x₀ * cosh(z₀) + y₀ * sinh(z₀))
177- /// - y ≈ `K_h` * (y₀ * cosh(z₀) + x₀ * sinh(z₀))
178- /// - z ≈ 0
179- ///
180- /// Where `K_h` is the hyperbolic gain factor (~1.2075).
181- ///
182- /// # Arguments
183- ///
184- /// * `x` - Initial x value
185- /// * `y` - Initial y value
186- /// * `z` - Hyperbolic angle to "rotate" by
187- ///
188- /// # Returns
189- ///
190- /// Tuple of (x, y, z) after CORDIC iterations.
191- ///
192- /// # Note
193- ///
194- /// - Hyperbolic CORDIC starts at i=1 (not i=0)
195- /// - Certain iterations must be repeated for convergence
196- /// - Input z should be in range [-1.12, 1.12] for convergence
197- #[ must_use]
198- pub fn hyperbolic_rotation < T : CordicNumber > ( mut x : T , mut y : T , mut z : T ) -> ( T , T , T ) {
199- let zero = T :: zero ( ) ;
200- // Use frac_bits iterations, capped at 54 for table bounds.
201- let max_iterations = T :: frac_bits ( ) . min ( 54 ) ;
202-
203- let mut i: u32 = 1 ; // Hyperbolic starts at i=1
204- let mut iteration_count: u32 = 0 ;
205- let mut repeated = false ;
206-
207- while iteration_count < max_iterations && i < 64 {
208- let table_index = i. saturating_sub ( 1 ) ;
209- let angle = T :: from_i1f63 ( table_lookup ( & ATANH_TABLE , table_index) ) ;
210-
211- if z >= zero {
212- // "Rotate" in positive direction
213- let x_new = x. saturating_add ( y >> i) ;
214- y = y. saturating_add ( x >> i) ;
215- x = x_new;
216- z -= angle;
217- } else {
218- // "Rotate" in negative direction
219- let x_new = x. saturating_sub ( y >> i) ;
220- y = y. saturating_sub ( x >> i) ;
221- x = x_new;
222- z += angle;
223- }
224-
225- iteration_count += 1 ;
226-
227- // Handle repetition for convergence
228- if needs_repeat ( i) && !repeated {
229- repeated = true ;
230- // Don't increment i, repeat this iteration
231- } else {
232- repeated = false ;
233- i += 1 ;
234- }
235- }
236-
237- ( x, y, z)
238- }
239-
24091/// Performs hyperbolic CORDIC in vectoring mode.
24192///
24293/// Drives y toward zero while accumulating the hyperbolic angle.
0 commit comments