96{
97 long double *coeffs = NULL;
98 long double complex *s0 = NULL;
99 unsigned int degree = 0;
100 unsigned int n, i;
101
102 if (argc < 2)
103 {
104 printf(
105 "Please pass the coefficients of the polynomial as commandline "
106 "arguments.\n");
107 return 0;
108 }
109
110 degree = argc - 1;
111 coeffs = (
long double *)
malloc(
112 degree * sizeof(long double));
113 s0 = (
long double complex *)
malloc(
114 (degree - 1) *
115 sizeof(long double complex));
116
117
118 srand(time(NULL));
119
120 if (!coeffs || !s0)
121 {
122 perror("Unable to allocate memory!");
123 if (coeffs)
125 if (s0)
127 return EXIT_FAILURE;
128 }
129
130#if defined(DEBUG) || !defined(NDEBUG)
131
132
133
134 FILE *log_file = fopen("durand_kerner.log.csv", "wt");
135 if (!log_file)
136 {
137 perror("Unable to create a storage log file!");
140 return EXIT_FAILURE;
141 }
142 fprintf(log_file, "iter#,");
143#endif
144
145 printf("Computing the roots for:\n\t");
146 for (n = 0; n < degree; n++)
147 {
148 coeffs[n] = strtod(argv[n + 1], NULL);
149 if (n < degree - 1 && coeffs[n] != 0)
150 printf("(%Lg) x^%d + ", coeffs[n], degree - n - 1);
151 else if (coeffs[n] != 0)
152 printf("(%Lg) x^%d = 0\n", coeffs[n], degree - n - 1);
153
154 double tmp;
155 if (n > 0)
156 coeffs[n] /= tmp;
157
158 else
159 {
160 tmp = coeffs[0];
161 coeffs[0] = 1;
162 }
163
164
165 if (n < degree - 1)
166 {
167 s0[n] = (long double)rand() + (long double)rand() * I;
168#if defined(DEBUG) || !defined(NDEBUG)
169 fprintf(log_file, "root_%d,", n);
170#endif
171 }
172 }
173
174#if defined(DEBUG) || !defined(NDEBUG)
175 fprintf(log_file, "avg. correction");
176 fprintf(log_file, "\n0,");
177 for (n = 0; n < degree - 1; n++)
179#endif
180
181 double tol_condition = 1;
182 unsigned long iter = 0;
183
184 clock_t end_time, start_time = clock();
186 {
187 long double complex delta = 0;
188 tol_condition = 0;
189 iter++;
190
191#if defined(DEBUG) || !defined(NDEBUG)
192 fprintf(log_file, "\n%ld,", iter);
193#endif
194
195 for (n = 0; n < degree - 1; n++)
196 {
197 long double complex numerator =
199 long double complex denominator = 1.0;
200 for (i = 0; i < degree - 1; i++)
201 if (i != n)
202 denominator *= s0[n] - s0[i];
203
204 delta = numerator / denominator;
205
206 if (isnan(cabsl(delta)) || isinf(cabsl(delta)))
207 {
208 printf("\n\nOverflow/underrun error - got value = %Lg",
209 cabsl(delta));
210 goto end;
211 }
212
213 s0[n] -= delta;
214
215 tol_condition = fmaxl(tol_condition, fabsl(cabsl(delta)));
216
217#if defined(DEBUG) || !defined(NDEBUG)
219#endif
220 }
221
222
223#if defined(DEBUG) || !defined(NDEBUG)
224 if (iter % 500 == 0)
225 {
226 printf("Iter: %lu\t", iter);
227 for (n = 0; n < degree - 1; n++) printf(
"\t%s",
complex_str(s0[n]));
228 printf("\t\tabsolute average change: %.4g\n", tol_condition);
229 }
230
231 fprintf(log_file, "%.4g", tol_condition);
232#endif
233 }
234end:
235
236 end_time = clock();
237
238#if defined(DEBUG) || !defined(NDEBUG)
239 fclose(log_file);
240#endif
241
242 printf("\nIterations: %lu\n", iter);
243 for (n = 0; n < degree - 1; n++) printf(
"\t%s\n",
complex_str(s0[n]));
244 printf("absolute average change: %.4g\n", tol_condition);
245 printf("Time taken: %.4g sec\n",
246 (end_time - start_time) / (double)CLOCKS_PER_SEC);
247
250
251 return 0;
252}
char check_termination(long double delta)
check for termination condition
Definition durand_kerner_roots.c:83
long double complex poly_function(long double *coeffs, unsigned int degree, long double complex x)
Evaluate the value of a polynomial with given coefficients.
Definition durand_kerner_roots.c:50
const char * complex_str(long double complex x)
create a textual form of complex number
Definition durand_kerner_roots.c:66
#define malloc(bytes)
This macro replace the standard malloc function with malloc_dbg.
Definition malloc_dbg.h:18
#define free(ptr)
This macro replace the standard free function with free_dbg.
Definition malloc_dbg.h:26