@@ -46,88 +46,85 @@ impl SeriesApproximation {
4646 }
4747 }
4848
49- pub fn step ( & mut self ) -> bool {
50- self . z . square_mut ( ) ;
51- self . z += & self . c ;
52-
53- let z_fixed = to_fixed ( & self . z ) ;
54-
55- if z_fixed. re . abs ( ) < 1e-300 && z_fixed. im . abs ( ) < 1e-300 {
56- println ! ( "found slow at: {}" , self . current_iteration) ;
57- }
49+ pub fn run ( & mut self ) {
50+ self . add_probe ( ComplexExtended :: new2 ( self . delta_top_left . mantissa . re , self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
51+ self . add_probe ( ComplexExtended :: new2 ( self . delta_top_left . mantissa . re , -self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
52+ self . add_probe ( ComplexExtended :: new2 ( -self . delta_top_left . mantissa . re , self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
53+ self . add_probe ( ComplexExtended :: new2 ( -self . delta_top_left . mantissa . re , -self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
5854
59- self . next_coefficients [ 0 ] = to_extended ( & self . z ) ;
60- self . next_coefficients [ 1 ] = self . coefficients [ 0 ] * self . coefficients [ 1 ] * 2.0 + ComplexExtended :: new2 ( 1.0 , 0.0 , 0 ) ;
55+ let add_value = ComplexExtended :: new2 ( 1.0 , 0.0 , 0 ) ;
6156
62- // Calculate the new coefficents
63- for k in 2 ..=self . order {
64- let mut sum = self . coefficients [ 0 ] * self . coefficients [ k] ;
57+ // Can be changed later into a better loop - this function could also return some more information
58+ while self . current_iteration < self . maximum_iteration {
59+ self . z . square_mut ( ) ;
60+ self . z += & self . c ;
6561
66- for j in 1 ..=( ( k - 1 ) / 2 ) {
67- sum += self . coefficients [ j] * self . coefficients [ k - j] ;
68- }
69- sum *= 2.0 ;
62+ let z_fixed = to_fixed ( & self . z ) ;
7063
71- // If even, we include the mid term as well
72- if k % 2 == 0 {
73- sum += self . coefficients [ k / 2 ] * self . coefficients [ k / 2 ] ;
64+ if z_fixed. re . abs ( ) < 1e-300 && z_fixed. im . abs ( ) < 1e-300 {
65+ println ! ( "found slow at: {}" , self . current_iteration) ;
7466 }
7567
76- sum. reduce ( ) ;
77- self . next_coefficients [ k] = sum;
78- }
79-
80- // this section takes about half of the time
81- for i in 0 ..self . original_probes . len ( ) {
82- // step the probe points using perturbation
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
87- self . current_probes [ i] . reduce ( ) ;
88-
89- // get the new approximations
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 ] ;
68+ self . next_coefficients [ 0 ] = to_extended ( & self . z ) ;
69+ self . next_coefficients [ 1 ] = self . coefficients [ 0 ] * self . coefficients [ 1 ] * 2.0 + add_value;
9270
71+ // Calculate the new coefficents
9372 for k in 2 ..=self . order {
94- series_probe += self . next_coefficients [ k] * self . approximation_probes [ i] [ k - 1 ] ;
95- derivative_probe += self . next_coefficients [ k] * self . approximation_probes_derivative [ i] [ k - 1 ] ;
96- } ;
73+ let mut sum = self . coefficients [ 0 ] * self . coefficients [ k] ;
9774
98- let relative_error = ( self . current_probes [ i] - series_probe) . norm_square ( ) ;
99- let mut derivative = derivative_probe. norm_square ( ) ;
75+ for j in 1 ..=( ( k - 1 ) / 2 ) {
76+ sum += self . coefficients [ j] * self . coefficients [ k - j] ;
77+ }
78+ sum *= 2.0 ;
10079
101- // Check to make sure that the derivative is greater than or equal to 1
102- if derivative . to_float ( ) < 1. 0 {
103- derivative = FloatExtended :: new ( 1.0 , 0 ) ;
104- }
80+ // If even, we include the mid term as well
81+ if k % 2 == 0 {
82+ sum += self . coefficients [ k / 2 ] * self . coefficients [ k / 2 ] ;
83+ }
10584
106- // Check that the error over the derivative is less than the pixel spacing
107- if relative_error / derivative > self . delta_pixel_square {
108- self . z -= & self . c ;
109- self . z . sqrt_mut ( ) ;
110- return false ;
85+ sum. reduce ( ) ;
86+ self . next_coefficients [ k] = sum;
11187 }
112- }
11388
114- // If the approximation is valid, continue
115- self . current_iteration += 1 ;
116-
117- // Swap the two coefficients buffers
118- swap ( & mut self . coefficients , & mut self . next_coefficients ) ;
119- self . current_iteration < self . maximum_iteration
120- }
89+ // this section takes about half of the time
90+ for i in 0 ..self . original_probes . len ( ) {
91+ // step the probe points using perturbation
92+ self . current_probes [ i] = self . current_probes [ i] * ( self . coefficients [ 0 ] * 2.0 + self . current_probes [ i] ) ;
93+ self . current_probes [ i] += self . original_probes [ i] ;
94+
95+ // TODO this probably does not need to be done every iteration
96+ self . current_probes [ i] . reduce ( ) ;
97+
98+ // get the new approximations
99+ let mut series_probe = self . next_coefficients [ 1 ] * self . approximation_probes [ i] [ 0 ] ;
100+ let mut derivative_probe = self . next_coefficients [ 1 ] * self . approximation_probes_derivative [ i] [ 0 ] ;
101+
102+ for k in 2 ..=self . order {
103+ series_probe += self . next_coefficients [ k] * self . approximation_probes [ i] [ k - 1 ] ;
104+ derivative_probe += self . next_coefficients [ k] * self . approximation_probes_derivative [ i] [ k - 1 ] ;
105+ } ;
106+
107+ let relative_error = ( self . current_probes [ i] - series_probe) . norm_square ( ) ;
108+ let mut derivative = derivative_probe. norm_square ( ) ;
109+
110+ // Check to make sure that the derivative is greater than or equal to 1
111+ if derivative. to_float ( ) < 1.0 {
112+ derivative = FloatExtended :: new ( 1.0 , 0 ) ;
113+ }
114+
115+ // Check that the error over the derivative is less than the pixel spacing
116+ if relative_error / derivative > self . delta_pixel_square {
117+ self . z -= & self . c ;
118+ self . z . sqrt_mut ( ) ;
119+ return ;
120+ }
121+ }
121122
122- pub fn run ( & mut self ) {
123- self . add_probe ( ComplexExtended :: new2 ( self . delta_top_left . mantissa . re , self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
124- self . add_probe ( ComplexExtended :: new2 ( self . delta_top_left . mantissa . re , -self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
125- self . add_probe ( ComplexExtended :: new2 ( -self . delta_top_left . mantissa . re , self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
126- self . add_probe ( ComplexExtended :: new2 ( -self . delta_top_left . mantissa . re , -self . delta_top_left . mantissa . im , self . delta_top_left . exponent ) ) ;
123+ // If the approximation is valid, continue
124+ self . current_iteration += 1 ;
127125
128- // Can be changed later into a better loop - this function could also return some more information
129- while self . step ( ) {
130- continue ;
126+ // Swap the two coefficients buffers
127+ swap ( & mut self . coefficients , & mut self . next_coefficients ) ;
131128 }
132129 }
133130
0 commit comments