1 /*
2 
3 Copyright (C) 2008-2009 Evgeni A. Nurminski <nurmi@dvo.ru>
4 Copyright (C) 2008-2009 Pete Gonzalez <pgonzalez@bluel.com>
5 
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING.  If not, see
18 <https://www.gnu.org/licenses/>.
19 
20 */
21 
22 #ifdef _MSC_VER
23 #define _CRT_SECURE_NO_WARNINGS  // disable spurious warnings
24 #define _USE_MATH_DEFINES // for math.h
25 #endif
26 
27 #include "cl2bp_lib.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <math.h>
33 #include <string.h>
34 
35 #include <stdexcept>
36 
37 #define BIG_NUMBER 100000
38 
39 //-----------------------------------------------------------------------------------------------------------
40 #ifdef CL2BP_LOGGING
log_printf(const char * format,...)41 static void log_printf(const char *format, ...) {
42   va_list argptr;
43   va_start(argptr, format);
44 
45   char buf[20*1024];
46   if (vsnprintf(buf,20*1024-1,format,argptr) == -1) {
47     strcpy(buf, "#ERROR#");
48   }
49   va_end(argptr);
50 
51   cl2bp_log(buf);
52 }
53 #else
54 #define log_printf(...)  ((void)0)   // don't log anything (for a big speed improvement)
55 #endif
56 
57 //-----------------------------------------------------------------------------------------------------------
local_max(const MallocArray<double> & x,int n,MallocArray<int> & ix)58 static int local_max(const MallocArray<double>& x, int n, MallocArray<int>& ix) {
59   int i, mx;
60 
61   mx = 0;
62 
63   MallocArray<double> xx(n+2);
64 
65   xx[0] = xx[n + 1] = -BIG_NUMBER;
66   for ( i = 1; i <= n; i++)
67     xx[i] = x[i - 1];
68   for ( i = 0; i < n; i++ ) {
69     (((xx[i] <  xx[i + 1]) && (xx[i + 1] >  xx[i + 2])) ||
70      ((xx[i] <  xx[i + 1]) && (xx[i + 1] >= xx[i + 2])) ||
71      ((xx[i] <= xx[i + 1]) && (xx[i + 1] >  xx[i + 2])) )
72     && ( ix[mx++] = i );
73   }
74   return mx;
75 }
76 
77 //-----------------------------------------------------------------------------------------------------------
solvps(MallocArray<double> & a,MallocArray<double> & b,int n,void (* cancel_handler)(void *),void * cancel_state)78 static int solvps(MallocArray<double>& a, MallocArray<double>& b, int n,
79   void (*cancel_handler)(void *), void *cancel_state) {
80 
81   double t;
82   int j, k;
83   int a_p;
84   int a_q;
85   int a_r;
86   int a_s;
87 
88   // In empirical tests, 2% to 6% of the execution time was spent in solvps()
89   if (cancel_handler) cancel_handler(cancel_state);
90 
91   for (j = 0, a_p = 0; j < n; ++j, a_p += n+1) {
92     for (a_q = j*n; a_q < a_p; ++a_q)
93       a[a_p] -= a[a_q] * a[a_q];
94     if (a[a_p] <= 0.)
95       return -1;
96     a[a_p] = sqrt(a[a_p]);
97     for (k = j + 1, a_q = a_p + n; k < n; ++k, a_q += n) {
98       for (a_r = j*n, a_s = k*n, t = 0.; a_r < a_p;)
99         t += a[a_r++] * a[a_s++];
100       a[a_q] -= t;
101       a[a_q] /= a[a_p];
102     }
103   }
104   for (j = 0, a_p = 0; j < n; ++j, a_p += n+1) {
105     for (k = 0, a_q = j*n; k < j;)
106       b[j] -=b [k++] * a[a_q++];
107     b[j] /= a[a_p];
108   }
109   for (j = n - 1, a_p = n*n - 1; j >= 0; --j, a_p -= n + 1) {
110     for (k = j + 1, a_q = a_p + n; k < n; a_q += n)
111       b[j] -= b[k++]* a[a_q];
112     b[j] /= a[a_p];
113   }
114   return 0;
115 }
116 
117 //-----------------------------------------------------------------------------------------------------------
rmmult(MallocArray<double> & rm,const MallocArray<double> & a,const MallocArray<double> & b,int n,int m,int l,void (* cancel_handler)(void *),void * cancel_state)118 static void rmmult(MallocArray<double>& rm, const MallocArray<double>& a, const MallocArray<double>& b,
119   int n, int m, int l,
120   void (*cancel_handler)(void *), void *cancel_state) {
121 
122   double z;
123   int i,j,k;
124   int b_p; // index into b
125   int a_p; // index into a
126   int rm_start = 0;  // index into rm
127   int rm_q; // index into rm
128 
129   MallocArray<double> q0(m);
130   for (i = 0; i < l ; ++i, ++rm_start) {
131     // In empirical tests, 87% to 95% of the execution time was spent in rmmult()
132     if (cancel_handler) cancel_handler(cancel_state);
133     for (k = 0, b_p = i; k < m; b_p += l)
134       q0[k++] = b[b_p];
135     for (j = 0, a_p = 0, rm_q = rm_start; j < n; ++j, rm_q += l) {
136       for (k = 0, z = 0.; k < m;)
137         z += a[a_p++] * q0[k++];
138       rm[rm_q]=z;
139     }
140   }
141 }
142 
143 //-----------------------------------------------------------------------------------------------------------
mattr(MallocArray<double> & a,const MallocArray<double> & b,int m,int n)144 static void mattr(MallocArray<double>& a, const MallocArray<double>& b, int m, int n) {
145   int i, j;
146   int b_p;
147   int a_p = 0;
148   int b_start = 0;
149   for (i = 0; i < n; ++i, ++b_start)
150     for ( j = 0, b_p = b_start; j < m; ++j, b_p += n )
151       a[a_p++] = b[b_p];
152 }
153 
154 //-----------------------------------------------------------------------------------------------------------
calcAx(MallocArray<double> & Ax,int m,int L)155 static void calcAx(MallocArray<double>& Ax, int m, int L) {
156   double r = M_SQRT2, pi = M_PI;
157   int i, j;
158 
159   Ax.resize((L+1)*(m + 1));
160 
161   for ( i = 0; i <= L; i++)
162     for ( j = 0; j <= m; j++)
163       Ax[i*(m+1) + j] = cos(i*j*pi/L);
164   for ( i = 0; i < (L+1)*(m+1); i += m + 1 )
165     Ax[i] /= r;
166 }
167 
168 //-----------------------------------------------------------------------------------------------------------
169 #ifdef CL2BP_LOGGING
L2error(const MallocArray<double> & x,const MallocArray<double> & w,int L,double w1,double w2)170 static double L2error(const MallocArray<double>& x, const MallocArray<double>& w, int L, double w1, double w2) {
171   double xx, ww, sumerr, pi = M_PI;
172   int i;
173   for ( i = 0, sumerr = 0; i < L + 1; i++ ) {
174     ww = w[i];
175     xx = x[i];
176     sumerr += ( ww < w1*pi || ww > w2*pi ) ?  xx*xx : (1 - xx)*(1 - xx);
177   }
178   return sumerr;
179 }
180 #endif // CL2BP_LOGGING
181 //-----------------------------------------------------------------------------------------------------------
CHerror(double * wmin,const MallocArray<double> & x,const MallocArray<double> & w,int L,double w1,double w2)182 static double CHerror(double *wmin, const MallocArray<double>& x, const MallocArray<double>& w,
183   int L, double w1, double w2) {
184 
185   double xx, ww, err, errmax;
186   int i;
187   errmax = -1;
188   *wmin = 0;
189   for ( i = 0; i < L + 1; i++ ) {
190     ww = w[i];
191     xx = x[i];
192     err = (( ww < w1 ) || (ww > w2 )) ?  fabs(xx) : fabs(1 - xx);
193     if ( err > errmax ) {
194       errmax = err;
195       *wmin = ww;
196     }
197   }
198   return errmax;
199 }
200 
201 //-----------------------------------------------------------------------------------------------------------
Ggen(MallocArray<double> & G,int m,const MallocArray<double> & w,const MallocArray<int> & kmax,int l_kmax,const MallocArray<int> & kmin,int l_kmin)202 static void Ggen(MallocArray<double>& G, int m, const MallocArray<double>& w, const MallocArray<int>& kmax,
203   int l_kmax, const MallocArray<int>& kmin, int l_kmin) {
204 
205   G.resize((l_kmax + l_kmin)*(m + 1));
206 
207   int nsys, i, j;
208   double r = M_SQRT2;
209 
210   nsys = l_kmax + l_kmin;
211   for ( i = 0; i < l_kmax; i++)
212     for ( j = 0; j <= m; j++)
213       G[i*(m+1) + j] = cos(w[kmax[i]]*j);
214   for ( i = l_kmax; i < nsys; i++)
215     for ( j = 0; j <= m; j++)
216       G[i*(m+1) + j] = -cos(w[kmin[i - l_kmax]]*j);
217   for ( i = 0; i < nsys*(m+1); i += m+1 )
218     G[i] /= r;
219 }
220 
221 //-----------------------------------------------------------------------------------------------------------
cl2bp(MallocArray<double> & h,int m,double w1,double w2,double up[3],double lo[3],int L,double eps,int mit,void (* cancel_handler)(void *),void * cancel_state)222 bool cl2bp(MallocArray<double>& h, int m, double w1, double w2, double up[3], double lo[3], int L,
223   double eps, int mit, void (*cancel_handler)(void *), void *cancel_state) {
224 
225   // Ensure sane values for input parameters
226   if (m < 2 || m > 5000)
227     throw std::invalid_argument("cl2bp: The m count must be between 2 and 5000");
228 
229   if (w1 < 0 || w1 > w2 || w2 > 2*M_PI)
230     throw std::invalid_argument("cl2bp: The cutoffs must be in the range 0 < w1 < w2 < 2*pi");
231 
232   // Z is allocated as Z(2*L-1-2*m)
233   if (L <= m)
234     throw std::invalid_argument("cl2bp: The \"gridsize\" parameter must be larger than \"m\"");
235 
236   double r = M_SQRT2;
237   double pi = M_PI;
238   double wmin, ww, xw;
239   int q1, q2, q3, i, iter = 0;
240   int off, neg;
241 
242   int ik;
243   int l_kmax;
244   int l_kmin;
245   int l_okmax;
246   int l_okmin;
247   double uvo = 0, lvo = 0;
248 
249   double err, diff_up, diff_lo;
250   double erru, erro;
251   int iup, ilo;
252 
253   int nsys, j;
254 
255   int imin = BIG_NUMBER;
256   double umin;
257 
258   int k1 = -1, k2 = -1, ak1, ak2;
259   double cerr;
260 
261   h.resize(2*m+1);
262 
263   bool converged = true;
264 
265   MallocArray<double> x0(L+1);
266   MallocArray<double> x1(L+1);
267   MallocArray<double> xx(L+1);
268   MallocArray<double> xm1(L+1);
269   MallocArray<double> w(L+1);
270   MallocArray<double> u(L+1);
271   MallocArray<double> l(L+1);
272   MallocArray<double> a(L+1);
273   MallocArray<double> c(L+1);
274   MallocArray<int> kmax(L+1);
275   MallocArray<int> kmin(L+1);
276   l_kmax  = l_kmin = 0;
277 
278   MallocArray<int> okmin(L+1);
279   MallocArray<int> okmax(L+1);
280   l_okmax = l_okmin = 0;
281   MallocArray<double> rhs(m+2);
282   MallocArray<double> mu(2*(L+1));
283 
284   for ( i = 0; i <= L; i++ )
285     w[i] = i*pi/L;
286 
287   MallocArray<double> Z(2*L-1-2*m);
288 
289   q1 = (int)floor(L*w1/pi);
290   q2 = (int)floor(L*(w2-w1)/pi);
291   q3 = L + 1 - q1 - q2;
292 
293   off = 0;
294   for ( i = 0; i < q1; i++) {
295     u[i] = up[0];
296     l[i] = lo[0];
297   }
298   off += i;
299   for ( i = 0; i < q2; i++) {
300     u[off + i] = up[1];
301     l[off + i] = lo[1];
302   }
303   off += i;
304   for ( i = 0; i < q3; i++) {
305     u[off + i] = up[2];
306     l[off + i] = lo[2];
307   }
308 
309 
310   c[0] = (w2-w1)*r;
311   for ( i = 1; i <= m; i++)
312     c[i] =  2*(sin(w2*i)-sin(w1*i))/i;
313   for ( i = 0; i <= m; i++) {
314     c[i] /=  pi;
315     a[i] = c[i];
316   }
317   log_printf("\nInitial approximation. Unconstrained L2 filter coefficients.\n");
318   log_printf("=============================================================\n");
319 
320   log_printf("\nZero order term %8.3lf\n", a[0]);
321   for ( i = 1; i <= m; i++) {
322     log_printf("%4d %8.3lf", i, a[i]);
323     if (i - 8*(i/8) == 0)
324       log_printf("\n");
325   }
326   log_printf("\n");
327 
328   // Precalculate Ax
329   MallocArray<double> Ax;
330   calcAx(Ax, m, L);
331 
332   //calcA(x0, a, m, L);
333   rmmult(x0, Ax, a, L + 1, m + 1, 1, cancel_handler, cancel_state);
334 
335   err = CHerror(&wmin, x0, w, L, w1, w2);
336   log_printf("\nChebyshev err %12.4e (%11.5e)  <> L2 err %12.4e\n", err, wmin/pi, L2error(x0, w, L, w1, w2)/(L+1));
337   for (iter = 1; ; iter++) {
338     log_printf("\n:::::: Iteration %3d :::::::::::\n", iter);
339 
340     if ( (uvo > eps*2) || (lvo > eps*2) ) {
341       log_printf("\nXXX Take care of old errors: uvo lvo %12.3e %12.3e", uvo, lvo);
342       if( k1 >= 0 ) log_printf(" k1 %3d(%d)", k1, okmax[k1]);
343       if( k2 >= 0 ) log_printf(" k2 %3d(%d)", k2, okmin[k2]);
344       log_printf("\n");
345 
346       if ( uvo > lvo ) {
347         kmax[l_kmax] = okmax[k1];
348         l_kmax++;
349         l_okmax--;
350         for (i = k1; i < l_okmax; i++)
351           okmax[i] = okmax[i + 1];
352       } else {
353         kmin[l_kmin] = okmin[k2];
354         l_kmin++;
355         l_okmin--;
356         for (i = k2; i < l_okmin; i++)
357           okmin[i] = okmin[i + 1];
358       }
359       nsys = l_kmax + l_kmin;
360 
361       /*
362         for (i = 0; i < l_kmax; i++)
363           log_printf("i %3d kmax %3d mu %12.4e\n",
364              i, kmax[i], mu[i]);
365         log_printf("\n");
366         for (i = 0; i < l_kmin; i++)
367           log_printf("i %3d kmin %3d mu %12.4e\n",
368              i, kmin[i], mu[i + l_kmax]);
369         log_printf("\n\n");
370       */
371     } else {
372 
373       //calcA(x1, a, m, L);
374       rmmult(x1, Ax, a, L + 1, m + 1, 1, cancel_handler, cancel_state);
375 
376 
377       for ( i = 0; i < l_kmax; i++)
378         okmax[i] = kmax[i];
379       for ( i = 0; i < l_kmin; i++)
380         okmin[i] = kmin[i];
381       l_okmax = l_kmax;
382       l_okmin = l_kmin;
383 
384       l_kmax = local_max(x1, L + 1, kmax);
385 
386 
387       for ( i = 0; i < L + 1; i++)
388         xm1[i] = -x1[i];
389       l_kmin = local_max(xm1, L + 1, kmin);
390 
391       log_printf("\nSignificant deviations from the ideal filter. Levels:");
392       log_printf(" %8.2e %8.2e %8.2e (lo)", lo[0], lo[1], lo[2]);
393       log_printf(" %8.2e %8.2e %8.2e (up)", up[0], up[1], up[2]);
394       log_printf("\n");
395 
396       for ( i = 0, ik = 0; i < l_kmax; i++) {
397         j = kmax[i];
398         if ( x1[j] > u[j] - 10*eps ) {
399           kmax[ik] = j;
400           ik++;
401         }
402       }
403       l_kmax = ik;
404 
405       log_printf("overshoots = %d\n", l_kmax);
406       for ( i = 0; i < l_kmax; i++) {
407         j = kmax[i];
408         ww = w[j];
409         xw = x1[j];
410         err = (w1 < ww && ww < w2) ? xw - 1 : xw;
411         log_printf(" i = %3d kmax = %3d xw = %12.5e err = %10.3e u = %12.4e max = %9.2e\n",
412                i, j, xw, err, u[j], xw - u[j]);
413       }
414 
415       for ( i = 0, ik = 0; i < l_kmin; i++) {
416         j = kmin[i];
417         if ( x1[j] < l[j] + 10*eps ) {
418           kmin[ik] = j;
419           ik++;
420         }
421       }
422       l_kmin = ik;
423 
424       log_printf("undershoots = %d\n", l_kmin);
425       for ( i = 0; i < l_kmin; i++) {
426         j = kmin[i];
427         ww = w[j];
428         xw = -xm1[j];
429         err =(w1 < ww && ww < w2) ? xw - 1 : xw;
430         log_printf(" i = %3d kmin = %3d xw = %12.5e err = %10.3e l = %12.4e min = %9.2e\n",
431                i, j, xw, err, l[j], xw - l[j]);
432       }
433 
434       err = erru = erro = diff_up = diff_lo = 0;
435       iup = ilo = 0;
436       for ( i = 0; i < l_kmax; i++) {
437         ik = kmax[i];
438         diff_up = x1[ik] - u[ik];
439         if ( diff_up > erru ) {
440           erru = diff_up;
441           iup = i;
442         }
443       }
444       for ( i = 0; i < l_kmin; i++) {
445         ik = kmin[i];
446         diff_lo = l[ik] - x1[ik];
447         if ( diff_lo > erro ) {
448           erro = diff_lo;
449           ilo = i;
450         }
451       }
452       err = erro > erru ? erro : erru;
453       log_printf("erru = %14.6e iup = %4d kmax = %4d ", erru, iup, kmax[iup]);
454       log_printf("erro = %14.6e ilo = %4d kmin = %4d\n", erro, ilo, kmin[ilo]);
455 #ifndef CL2BP_LOGGING
456       static_cast<void>(iup);
457 #endif
458 
459       if ( err < eps )
460         break;
461     }
462 
463 
464     nsys = l_kmax + l_kmin;
465 
466     MallocArray<double> G(nsys*(m + 1));
467     MallocArray<double> GT(nsys*(m + 1));
468     MallocArray<double> GG(nsys*nsys);
469 
470     for ( i = 0; i < l_kmax; i++)
471       for ( j = 0; j <= m; j++)
472         G[i*(m+1) + j] = cos(w[kmax[i]]*j);
473     for ( i = l_kmax; i < nsys; i++)
474       for ( j = 0; j <= m; j++)
475         G[i*(m+1) + j] = -cos(w[kmin[i - l_kmax]]*j);
476     for ( i = 0; i < nsys*(m+1); i += m+1 )
477       G[i] /= r;
478     mattr(GT, G, nsys, m + 1);
479     rmmult(GG, G, GT, nsys, m + 1, nsys, cancel_handler, cancel_state);
480 
481 
482     rmmult(rhs, G, c, nsys, m + 1, 1, cancel_handler, cancel_state);
483     for ( i = 0; i < nsys; i++)
484       if ( i < l_kmax )
485         rhs[i] -= u[kmax[i]];
486       else
487         rhs[i] += l[kmin[i - l_kmax]];
488 
489     for ( i = 0; i < nsys; ++i)
490       mu[i] = rhs[i];
491 
492     solvps(GG, mu, nsys, cancel_handler, cancel_state);
493     log_printf("\nXXX KT-system with %d equations resolved.\n", nsys);
494     for ( i = 0, neg = 0; i < nsys; i++)
495       if ( mu[i] < 0 ) neg++;
496     log_printf("\nTotal number of negative multipliers = %3d\n\n", neg);
497     while (neg) {
498 
499 
500       umin = BIG_NUMBER;
501       for ( i = 0, j = 0; i < nsys; i++) {
502         if ( mu[i] >= 0 ) continue;
503         j++;
504         if ( mu[i] < umin ) {
505           imin = i;
506           umin = mu[i];
507         }
508       }
509 
510       if ( umin > 0 )
511         break;
512       log_printf(" neg = %3d of %3d imin = %3d mu-min = %12.4e\n", j, nsys, imin, umin);
513 
514       for ( i = imin; i < nsys - 1; i++) {
515         rhs[i] = rhs[i + 1];
516         for ( j = 0; j <= m; j++)
517           G[i*(m + 1) + j] =  G[(i + 1)*(m + 1) + j];
518       }
519 
520       if ( imin < l_kmax ) {
521         for ( i = imin; i < l_kmax - 1; i++)
522           kmax[i] = kmax[i + 1];
523         l_kmax--;
524       } else {
525         for ( i = imin; i < nsys - 1; i++)
526           kmin[i - l_kmax] = kmin[i - l_kmax + 1];
527         l_kmin--;
528       }
529 
530       --nsys;
531 
532       mattr(GT, G, nsys, m + 1);
533       rmmult(GG, G, GT, nsys, m + 1, nsys, cancel_handler, cancel_state);
534       for ( i = 0; i < nsys; ++i)
535         mu[i] = rhs[i];
536       solvps(GG, mu, nsys, cancel_handler, cancel_state);
537     }
538 
539     MallocArray<double> da(m + 1);
540     MallocArray<double> zd(nsys);
541 
542     rmmult(da, GT, mu, m + 1, nsys, 1, cancel_handler, cancel_state);
543     for ( i = 0; i <= m; i++)
544       a[i] = c[i] - da[i];
545     rmmult(zd, G, a, nsys, m + 1, 1, cancel_handler, cancel_state);
546 
547     MallocArray<double> zz(l_okmax + l_okmin);
548     Ggen(G, m, w, okmax, l_okmax, okmin, l_okmin);
549     rmmult(zz, G, a, l_okmax + l_okmin, m + 1, 1, cancel_handler, cancel_state);
550     uvo = lvo = eps;
551     k1 = k2 = -1;
552     ak1 = ak2 = -1;
553     if (l_okmax + l_okmin > 0)
554       log_printf("\nErrors on the previous set of freqs\n\n");
555     for (i = 0; i < l_okmax; i++) {
556       j = okmax[i];
557       cerr = zz[i] - u[j];
558       log_printf(" i %2d j %3d u %12.4e Ga %12.4e cerr %12.4e\n",
559              i, j, u[j], zz[i], cerr);
560       if ( cerr > uvo ) {
561         uvo = cerr;
562         k1 = i;
563         ak1 = j;
564       }
565     }
566     cerr = 0;
567     for (i = 0; i < l_okmin; i++) {
568       j = okmin[i];
569       cerr = l[j] + zz[i + l_okmax];
570       log_printf(" i %2d j %3d l %12.4e Ga %12.4e cerr %12.4e\n",
571              i, j, l[j], zz[i + l_okmax], cerr);
572       if ( cerr > lvo ) {
573         lvo = cerr;
574         k2 = i, ak2 = j;
575       }
576     }
577     if ( l_okmax + l_okmin > 0 ) {
578       log_printf("\n uvo = %12.4e k1 = %4d (%3d) ", uvo, k1, ak1);
579       log_printf("  lvo = %12.4e k2 = %4d (%3d) ", lvo, k2, ak2);
580       log_printf(" maxerr = %12.4e\n", uvo > lvo ? uvo : lvo);
581 #ifndef CL2BP_LOGGING
582       static_cast<void>(ak1);
583 #endif
584     }
585 
586     log_printf("\nConstrained L2 band filter coefficients.\n");
587     log_printf("=====================================\n");
588 
589 #ifdef CL2BP_LOGGING
590     log_printf("\nZero order term %8.3lf\n", a[0]);
591     for ( i = 1; i <= m; i++) {
592       log_printf("%4d %8.3lf", i, a[i]);
593       if (i - 8*(i/8) == 0)
594         log_printf("\n");
595     }
596     log_printf("\n");
597 #endif
598 
599     //calcA(xx, a, m, L);
600     rmmult(xx, Ax, a, L + 1, m + 1, 1, cancel_handler, cancel_state);
601 
602     if ( iter >= mit ) {
603       log_printf("Maximum iterations reached\n");
604       converged = false;
605     }
606   }
607   for (i = 0; i < m; i++) {
608     h[i] = a[m - i]/2;
609     h[m + i + 1] = a[i + 1]/2;
610   }
611   h[m] = a[0]*r/2;
612 
613   return converged;
614 }
615