@@ -8,7 +8,7 @@ use std::mem::swap;
88pub struct SeriesApproximation {
99 pub current_iteration : usize ,
1010 maximum_iteration : usize ,
11- delta_pixel : FloatExtended ,
11+ delta_pixel_square : FloatExtended ,
1212 z : ComplexArbitrary ,
1313 c : ComplexArbitrary ,
1414 pub order : usize ,
@@ -22,7 +22,7 @@ pub struct SeriesApproximation {
2222}
2323
2424impl SeriesApproximation {
25- pub fn new ( c : ComplexArbitrary , order : usize , maximum_iteration : usize , delta_pixel : FloatExtended , delta_top_left : ComplexExtended ) -> Self {
25+ pub fn new ( c : ComplexArbitrary , order : usize , maximum_iteration : usize , delta_pixel_square : FloatExtended , delta_top_left : ComplexExtended ) -> Self {
2626 let mut coefficients = vec ! [ ComplexExtended :: new2( 0.0 , 0.0 , 0 ) ; order as usize + 1 ] ;
2727
2828 coefficients[ 0 ] = to_extended ( & c) ;
@@ -32,7 +32,7 @@ impl SeriesApproximation {
3232 SeriesApproximation {
3333 current_iteration : 1 ,
3434 maximum_iteration,
35- delta_pixel ,
35+ delta_pixel_square ,
3636 z : c. clone ( ) ,
3737 c,
3838 order,
@@ -61,9 +61,9 @@ impl SeriesApproximation {
6161
6262 // Calculate the new coefficents
6363 for k in 2 ..=self . order {
64- let mut sum = ComplexExtended :: new2 ( 0.0 , 0.0 , 0 ) ;
64+ let mut sum = self . coefficients [ 0 ] * self . coefficients [ k ] ;
6565
66- for j in 0 ..=( ( k - 1 ) / 2 ) {
66+ for j in 1 ..=( ( k - 1 ) / 2 ) {
6767 sum += self . coefficients [ j] * self . coefficients [ k - j] ;
6868 }
6969 sum *= 2.0 ;
@@ -80,33 +80,31 @@ impl SeriesApproximation {
8080 // this section takes about half of the time
8181 for i in 0 ..self . original_probes . len ( ) {
8282 // step the probe points using perturbation
83- self . current_probes [ i] = self . coefficients [ 0 ] * self . current_probes [ i] * 2.0 + self . current_probes [ i] * self . current_probes [ i] + self . original_probes [ i] ;
83+ self . current_probes [ i] = self . current_probes [ i] * ( self . coefficients [ 0 ] * 2.0 + self . current_probes [ i] ) ;
84+ self . current_probes [ i] += self . original_probes [ i] ;
85+
86+ // TODO this probably does not need to be done every iteration
8487 self . current_probes [ i] . reduce ( ) ;
8588
8689 // get the new approximations
87- let mut series_probe = ComplexExtended :: new2 ( 0.0 , 0.0 , 0 ) ;
88- let mut derivative_probe = ComplexExtended :: new2 ( 0.0 , 0.0 , 0 ) ;
90+ let mut series_probe = self . next_coefficients [ 1 ] * self . approximation_probes [ i ] [ 0 ] ;
91+ let mut derivative_probe = self . next_coefficients [ 1 ] * self . approximation_probes_derivative [ i ] [ 0 ] ;
8992
90- for k in 1 ..=self . order {
93+ for k in 2 ..=self . order {
9194 series_probe += self . next_coefficients [ k] * self . approximation_probes [ i] [ k - 1 ] ;
92- derivative_probe += self . next_coefficients [ k] * self . approximation_probes_derivative [ i] [ k - 1 ] * k as f64 ;
93-
94- if k % 16 == 0 {
95- series_probe. reduce ( ) ;
96- derivative_probe. reduce ( ) ;
97- }
95+ derivative_probe += self . next_coefficients [ k] * self . approximation_probes_derivative [ i] [ k - 1 ] ;
9896 } ;
9997
100- let relative_error = ( self . current_probes [ i] - series_probe) . norm ( ) ;
101- let mut derivative = derivative_probe. norm ( ) ;
98+ let relative_error = ( self . current_probes [ i] - series_probe) . norm_square ( ) ;
99+ let mut derivative = derivative_probe. norm_square ( ) ;
102100
103101 // Check to make sure that the derivative is greater than or equal to 1
104102 if derivative. to_float ( ) < 1.0 {
105103 derivative = FloatExtended :: new ( 1.0 , 0 ) ;
106104 }
107105
108106 // Check that the error over the derivative is less than the pixel spacing
109- if relative_error / derivative > self . delta_pixel {
107+ if relative_error / derivative > self . delta_pixel_square {
110108 self . z -= & self . c ;
111109 self . z . sqrt_mut ( ) ;
112110 return false ;
@@ -138,24 +136,23 @@ impl SeriesApproximation {
138136 self . original_probes . push ( delta_probe) ;
139137 self . current_probes . push ( delta_probe) ;
140138
141- let mut delta_probe_n = Vec :: with_capacity ( self . order + 1 ) ;
142- let mut delta_probe_n_derivative = Vec :: with_capacity ( self . order + 1 ) ;
139+ let mut delta_probe_n = delta_probe;
140+
141+ let mut delta_probe_n_2 = Vec :: with_capacity ( self . order + 1 ) ;
142+ let mut delta_probe_n_derivative_2 = Vec :: with_capacity ( self . order + 1 ) ;
143143
144144 // The first element will be 1, in order for the derivative to be calculated
145- delta_probe_n . push ( delta_probe ) ;
146- delta_probe_n_derivative . push ( ComplexExtended :: new2 ( 1.0 , 0.0 , 0 ) ) ;
145+ delta_probe_n_2 . push ( delta_probe_n ) ;
146+ delta_probe_n_derivative_2 . push ( ComplexExtended :: new2 ( 1.0 , 0.0 , 0 ) ) ;
147147
148148 for i in 1 ..=self . order {
149- let mut delta_probe1 = delta_probe_n[ i - 1 ] * delta_probe;
150- let mut delta_probe2 = delta_probe_n_derivative[ i - 1 ] * delta_probe;
151- delta_probe1. reduce ( ) ;
152- delta_probe2. reduce ( ) ;
153- delta_probe_n. push ( delta_probe1) ;
154- delta_probe_n_derivative. push ( delta_probe2) ;
149+ delta_probe_n_derivative_2. push ( delta_probe_n * ( i + 1 ) as f64 ) ;
150+ delta_probe_n *= delta_probe;
151+ delta_probe_n_2. push ( delta_probe_n) ;
155152 }
156153
157- self . approximation_probes . push ( delta_probe_n ) ;
158- self . approximation_probes_derivative . push ( delta_probe_n_derivative ) ;
154+ self . approximation_probes . push ( delta_probe_n_2 ) ;
155+ self . approximation_probes_derivative . push ( delta_probe_n_derivative_2 ) ;
159156 }
160157
161158 // Get the current reference, and the current number of iterations done
@@ -181,31 +178,43 @@ impl SeriesApproximation {
181178 }
182179
183180 pub fn evaluate ( & self , point_delta : ComplexExtended ) -> ComplexExtended {
184- let mut approximation = self . coefficients [ 1 ] * point_delta;
185- let mut original_point_n = point_delta * point_delta;
181+ // 1907 ms packing opus 4K
182+ // Horner's rule
183+ let mut approximation = self . coefficients [ self . order ] ;
186184
187- for k in 2 ..=self . order {
188- approximation += self . coefficients [ k] * original_point_n;
189- original_point_n *= point_delta;
190-
191- if k % 16 == 0 {
192- approximation. reduce ( ) ;
193- original_point_n. reduce ( ) ;
194- }
195- } ;
185+ for k in ( 1 ..=( self . order - 1 ) ) . rev ( ) {
186+ approximation *= point_delta;
187+ approximation += self . coefficients [ k] ;
188+ }
196189
190+ approximation *= point_delta;
191+ approximation. reduce ( ) ;
197192 approximation
198193 }
199194
200- // pub fn evaluate_derivative(&self, point_delta: ComplexFixed<f64> ) -> ComplexFixed<f64> {
195+ // pub fn evaluate_derivative(&self, point_delta: ComplexExtended ) -> FloatExtended {
201196 // let mut original_point_derivative_n = ComplexExtended::new(1.0, 0, 0.0, 0);
202197 // let mut approximation_derivative = ComplexExtended::new(0.0, 0, 0.0, 0);
203- //
198+
204199 // for k in 1..=self.order {
205200 // approximation_derivative += k as f64 * self.coefficients[k] * original_point_derivative_n;
206201 // original_point_derivative_n *= ComplexExtended::new(point_delta.re, 0, point_delta.im, 0);
207202 // };
208- //
203+
209204 // approximation_derivative.to_float()
205+
206+
207+ // let mut approximation_derivative = self.coefficients[self.order] * self.order as f64;
208+
209+ // for k in (1..=(self.order - 1)).rev() {
210+ // approximation *= point_delta;
211+ // approximation += self.coefficients[k] * k as f64;
212+ // }
213+
214+ // approximation *= point_delta;
215+ // approximation.reduce();
216+ // approximation
217+
218+
210219 // }
211220}
0 commit comments