Grid 0.7.0
Remez.cc
Go to the documentation of this file.
1/*
2
3 Mike Clark - 25th May 2005
4
5 alg_remez.C
6
7 AlgRemez is an implementation of the Remez algorithm, which in this
8 case is used for generating the optimal nth root rational
9 approximation.
10
11 Note this class requires the gnu multiprecision (GNU MP) library.
12
13*/
14
15#include<math.h>
16#include<stdio.h>
17#include<stdlib.h>
18#include<string>
19#include<iostream>
20#include<iomanip>
21#include<cassert>
22
24
25// Constructor
26AlgRemez::AlgRemez(double lower, double upper, long precision)
27{
28 prec = precision;
30
31 apstrt = lower;
32 apend = upper;
34
35 std::cout<<"Approximation bounds are ["<<apstrt<<","<<apend<<"]\n";
36 std::cout<<"Precision of arithmetic is "<<precision<<std::endl;
37
38 alloc = 0;
39 n = 0;
40 d = 0;
41
42 foundRoots = 0;
43
44 // Only require the approximation spread to be less than 1 ulp
45 tolerance = 1e-15;
46}
47
48// Destructor
50{
51 if (alloc) {
52 delete [] param;
53 delete [] roots;
54 delete [] poles;
55 delete [] xx;
56 delete [] mm;
57 delete [] a_power;
58 delete [] a;
59 }
60}
61
62// Free memory and reallocate as necessary
63void AlgRemez::allocate(int num_degree, int den_degree)
64{
65 // Arrays have previously been allocated, deallocate first, then allocate
66 if (alloc) {
67 delete [] param;
68 delete [] roots;
69 delete [] poles;
70 delete [] xx;
71 delete [] mm;
72 }
73
74 // Note use of new and delete in memory allocation - cannot run on qcdsp
75 param = new bigfloat[num_degree+den_degree+1];
76 roots = new bigfloat[num_degree];
77 poles = new bigfloat[den_degree];
78 xx = new bigfloat[num_degree+den_degree+3];
79 mm = new bigfloat[num_degree+den_degree+2];
80
81 if (!alloc) {
82 // The coefficients of the sum in the exponential
83 a = new bigfloat[SUM_MAX];
84 a_power = new int[SUM_MAX];
85 }
86
87 alloc = 1;
88}
89
90// Reset the bounds of the approximation
91void AlgRemez::setBounds(double lower, double upper)
92{
93 apstrt = lower;
94 apend = upper;
96}
97
98// Generate the rational approximation x^(pnum/pden)
99double AlgRemez::generateApprox(int degree, unsigned long pnum,
100 unsigned long pden)
101{
102 return generateApprox(degree, degree, pnum, pden);
103}
104
105double AlgRemez::generateApprox(int num_degree, int den_degree,
106 unsigned long pnum, unsigned long pden)
107{
108 double *a_param = 0;
109 int *a_pow = 0;
110 return generateApprox(num_degree, den_degree, pnum, pden, 0, a_param, a_pow);
111}
112
113// Generate the rational approximation x^(pnum/pden)
114double AlgRemez::generateApprox(int num_degree, int den_degree,
115 unsigned long pnum, unsigned long pden,
116 int a_len, double *a_param, int *a_pow)
117{
118 std::cout<<"Degree of the approximation is ("<<num_degree<<","<<den_degree<<")\n";
119 std::cout<<"Approximating the function x^("<<pnum<<"/"<<pden<<")\n";
120
121 // Reallocate arrays, since degree has changed
122 if (num_degree != n || den_degree != d) allocate(num_degree,den_degree);
123
124 assert(a_len<=SUM_MAX);
125
126 step = new bigfloat[num_degree+den_degree+2];
127
128 a_length = a_len;
129 for (int j=0; j<a_len; j++) {
130 a[j]= a_param[j];
131 a_power[j] = a_pow[j];
132 }
133
134 power_num = pnum;
135 power_den = pden;
136 spread = 1.0e37;
137 iter = 0;
138
139 n = num_degree;
140 d = den_degree;
141 neq = n + d + 1;
142
143 initialGuess();
144 stpini(step);
145
146 while (spread > tolerance) { //iterate until convergance
147
148 if (iter++%100==0)
149 std::cout<<"Iteration " <<iter-1<<" spread "<<(double)spread<<" delta "<<(double)delta<<std::endl;
150
151 equations();
152 if (delta < tolerance) {
153 std::cout<<"Delta too small, try increasing precision\n";
154 assert(0);
155 };
156 assert( delta>= tolerance);
157
158 search(step);
159 }
160
161 int sign;
162 double error = (double)getErr(mm[0],&sign);
163 std::cout<<"Converged at "<<iter<<" iterations; error = "<<error<<std::endl;
164
165 // Once the approximation has been generated, calculate the roots
166 if(!root()) {
167 std::cout<<"Root finding failed\n";
168 } else {
169 foundRoots = 1;
170 }
171
172 delete [] step;
173
174 // Return the maximum error in the approximation
175 return error;
176}
177
178// Return the partial fraction expansion of the approximation x^(pnum/pden)
179int AlgRemez::getPFE(double *Res, double *Pole, double *Norm) {
180
181 if (n!=d) {
182 std::cout<<"Cannot handle case: Numerator degree neq Denominator degree\n";
183 return 0;
184 }
185
186 if (!alloc) {
187 std::cout<<"Approximation not yet generated\n";
188 return 0;
189 }
190
191 if (!foundRoots) {
192 std::cout<<"Roots not found, so PFE cannot be taken\n";
193 return 0;
194 }
195
196 bigfloat *r = new bigfloat[n];
197 bigfloat *p = new bigfloat[d];
198
199 for (int i=0; i<n; i++) r[i] = roots[i];
200 for (int i=0; i<d; i++) p[i] = poles[i];
201
202 // Perform a partial fraction expansion
203 pfe(r, p, norm);
204
205 // Convert to double and return
206 *Norm = (double)norm;
207 for (int i=0; i<n; i++) Res[i] = (double)r[i];
208 for (int i=0; i<d; i++) Pole[i] = (double)p[i];
209
210 delete [] r;
211 delete [] p;
212
213 // Where the smallest shift is located
214 return 0;
215}
216
217// Return the partial fraction expansion of the approximation x^(-pnum/pden)
218int AlgRemez::getIPFE(double *Res, double *Pole, double *Norm) {
219
220 if (n!=d) {
221 std::cout<<"Cannot handle case: Numerator degree neq Denominator degree\n";
222 return 0;
223 }
224
225 if (!alloc) {
226 std::cout<<"Approximation not yet generated\n";
227 return 0;
228 }
229
230 if (!foundRoots) {
231 std::cout<<"Roots not found, so PFE cannot be taken\n";
232 return 0;
233 }
234
235 bigfloat *r = new bigfloat[d];
236 bigfloat *p = new bigfloat[n];
237
238 // Want the inverse function
239 for (int i=0; i<n; i++) {
240 r[i] = poles[i];
241 p[i] = roots[i];
242 }
243
244 // Perform a partial fraction expansion
245 pfe(r, p, (bigfloat)1l/norm);
246
247 // Convert to double and return
248 *Norm = (double)((bigfloat)1l/(norm));
249 for (int i=0; i<n; i++) {
250 Res[i] = (double)r[i];
251 Pole[i] = (double)p[i];
252 }
253
254 delete [] r;
255 delete [] p;
256
257 // Where the smallest shift is located
258 return 0;
259}
260
261// Initial values of maximal and minimal errors
263
264 // Supply initial guesses for solution points
265 long ncheb = neq; // Degree of Chebyshev error estimate
266 bigfloat a, r;
267
268 // Find ncheb+1 extrema of Chebyshev polynomial
269
270 a = ncheb;
271 mm[0] = apstrt;
272 for (long i = 1; i < ncheb; i++) {
273 r = 0.5 * (1 - cos((M_PI * i)/(double) a));
274 //r *= sqrt_bf(r);
275 r = (exp((double)r)-1.0)/(exp(1.0)-1.0);
276 mm[i] = apstrt + r * apwidt;
277 }
278 mm[ncheb] = apend;
279
280 a = 2.0 * ncheb;
281 for (long i = 0; i <= ncheb; i++) {
282 r = 0.5 * (1 - cos(M_PI * (2*i+1)/(double) a));
283 //r *= sqrt_bf(r); // Squeeze to low end of interval
284 r = (exp((double)r)-1.0)/(exp(1.0)-1.0);
285 xx[i] = apstrt + r * apwidt;
286 }
287}
288
289// Initialise step sizes
291 xx[neq+1] = apend;
292 delta = 0.25;
293 step[0] = xx[0] - apstrt;
294 for (int i = 1; i < neq; i++) step[i] = xx[i] - xx[i-1];
295 step[neq] = step[neq-1];
296}
297
298// Search for error maxima and minima
300 bigfloat a, q, xm, ym, xn, yn, xx0, xx1;
301 int i, meq, emsign, ensign, steps;
302
303 meq = neq + 1;
304 bigfloat *yy = new bigfloat[meq];
305
306 bigfloat eclose = 1.0e30;
307 bigfloat farther = 0l;
308
309 xx0 = apstrt;
310
311 for (i = 0; i < meq; i++) {
312 steps = 0;
313 xx1 = xx[i]; // Next zero
314 if (i == meq-1) xx1 = apend;
315 xm = mm[i];
316 ym = getErr(xm,&emsign);
317 q = step[i];
318 xn = xm + q;
319 if (xn < xx0 || xn >= xx1) { // Cannot skip over adjacent boundaries
320 q = -q;
321 xn = xm;
322 yn = ym;
323 ensign = emsign;
324 } else {
325 yn = getErr(xn,&ensign);
326 if (yn < ym) {
327 q = -q;
328 xn = xm;
329 yn = ym;
330 ensign = emsign;
331 }
332 }
333
334 while(yn >= ym) { // March until error becomes smaller.
335 if (++steps > 10) break;
336 ym = yn;
337 xm = xn;
338 emsign = ensign;
339 a = xm + q;
340 if (a == xm || a <= xx0 || a >= xx1) break;// Must not skip over the zeros either side.
341 xn = a;
342 yn = getErr(xn,&ensign);
343 }
344
345 mm[i] = xm; // Position of maximum
346 yy[i] = ym; // Value of maximum
347
348 if (eclose > ym) eclose = ym;
349 if (farther < ym) farther = ym;
350
351 xx0 = xx1; // Walk to next zero.
352 } // end of search loop
353
354 q = (farther - eclose); // Decrease step size if error spread increased
355 if (eclose != 0.0) q /= eclose; // Relative error spread
356 if (q >= spread) delta *= 0.5; // Spread is increasing; decrease step size
357 spread = q;
358
359 for (i = 0; i < neq; i++) {
360 q = yy[i+1];
361 if (q != 0.0) q = yy[i] / q - (bigfloat)1l;
362 else q = 0.0625;
363 if (q > (bigfloat)0.25) q = 0.25;
364 q *= mm[i+1] - mm[i];
365 step[i] = q * delta;
366 }
367 step[neq] = step[neq-1];
368
369 for (i = 0; i < neq; i++) { // Insert new locations for the zeros.
370 xm = xx[i] - step[i];
371 if (xm <= apstrt) continue;
372 if (xm >= apend) continue;
373 if (xm <= mm[i]) xm = (bigfloat)0.5 * (mm[i] + xx[i]);
374 if (xm >= mm[i+1]) xm = (bigfloat)0.5 * (mm[i+1] + xx[i]);
375 xx[i] = xm;
376 }
377
378 delete [] yy;
379}
380
381// Solve the equations
383 bigfloat x, y, z;
384 int i, j, ip;
385 bigfloat *aa;
386
387 bigfloat *AA = new bigfloat[(neq)*(neq)];
388 bigfloat *BB = new bigfloat[neq];
389
390 for (i = 0; i < neq; i++) { // set up the equations for solution by simq()
391 ip = neq * i; // offset to 1st element of this row of matrix
392 x = xx[i]; // the guess for this row
393 y = func(x); // right-hand-side vector
394
395 z = (bigfloat)1l;
396 aa = AA+ip;
397 for (j = 0; j <= n; j++) {
398 *aa++ = z;
399 z *= x;
400 }
401
402 z = (bigfloat)1l;
403 for (j = 0; j < d; j++) {
404 *aa++ = -y * z;
405 z *= x;
406 }
407 BB[i] = y * z; // Right hand side vector
408 }
409
410 // Solve the simultaneous linear equations.
411 if (simq(AA, BB, param, neq)) {
412 std::cout<<"simq failed\n";
413 exit(0);
414 }
415
416 delete [] AA;
417 delete [] BB;
418
419}
420
421// Evaluate the rational form P(x)/Q(x) using coefficients
422// from the solution vector param
424 bigfloat yn, yd;
425 int i;
426
427 // Work backwards toward the constant term.
428 yn = param[n]; // Highest order numerator coefficient
429 for (i = n-1; i >= 0; i--) yn = x * yn + param[i];
430 yd = x + param[n+d]; // Highest degree coefficient = 1.0
431 for (i = n+d-1; i > n; i--) yd = x * yd + param[i];
432
433 return(yn/yd);
434}
435
436// Compute size and sign of the approximation error at x
438 bigfloat e, f;
439
440 f = func(x);
441 e = approx(x) - f;
442 if (f != 0) e /= f;
443 if (e < (bigfloat)0.0) {
444 *sign = -1;
445 e = -e;
446 }
447 else *sign = 1;
448
449 return(e);
450}
451
452// Calculate function required for the approximation.
454
456 bigfloat y;
457
458 if (x == (bigfloat)1.0) y = (bigfloat)1.0;
459 else y = pow_bf(x,z);
460
461 if (a_length > 0) {
462 bigfloat sum = 0l;
463 for (int j=0; j<a_length; j++) sum += a[j]*pow_bf(x,a_power[j]);
464 return y * exp_bf(sum);
465 } else {
466 return y;
467 }
468
469}
470
471// Solve the system AX=B
473
474 int i, j, ij, ip, ipj, ipk, ipn;
475 int idxpiv, iback;
476 int k, kp, kp1, kpk, kpn;
477 int nip, nkp, nm1;
478 bigfloat em, q, rownrm, big, size, pivot, sum;
479 bigfloat *aa;
480
481 // simq() work vector
482 int *IPS = new int[(neq) * sizeof(int)];
483
484 nm1 = n - 1;
485 // Initialize IPS and X
486
487 ij = 0;
488 for (i = 0; i < n; i++) {
489 IPS[i] = i;
490 rownrm = 0.0;
491 for(j = 0; j < n; j++) {
492 q = abs_bf(A[ij]);
493 if(rownrm < q) rownrm = q;
494 ++ij;
495 }
496 if (rownrm == (bigfloat)0l) {
497 std::cout<<"simq rownrm=0\n";
498 delete [] IPS;
499 return(1);
500 }
501 X[i] = (bigfloat)1.0 / rownrm;
502 }
503
504 for (k = 0; k < nm1; k++) {
505 big = 0.0;
506 idxpiv = 0;
507
508 for (i = k; i < n; i++) {
509 ip = IPS[i];
510 ipk = n*ip + k;
511 size = abs_bf(A[ipk]) * X[ip];
512 if (size > big) {
513 big = size;
514 idxpiv = i;
515 }
516 }
517
518 if (big == (bigfloat)0l) {
519 std::cout<<"simq big=0\n";
520 delete [] IPS;
521 return(2);
522 }
523 if (idxpiv != k) {
524 j = IPS[k];
525 IPS[k] = IPS[idxpiv];
526 IPS[idxpiv] = j;
527 }
528 kp = IPS[k];
529 kpk = n*kp + k;
530 pivot = A[kpk];
531 kp1 = k+1;
532 for (i = kp1; i < n; i++) {
533 ip = IPS[i];
534 ipk = n*ip + k;
535 em = -A[ipk] / pivot;
536 A[ipk] = -em;
537 nip = n*ip;
538 nkp = n*kp;
539 aa = A+nkp+kp1;
540 for (j = kp1; j < n; j++) {
541 ipj = nip + j;
542 A[ipj] = A[ipj] + em * *aa++;
543 }
544 }
545 }
546 kpn = n * IPS[n-1] + n - 1; // last element of IPS[n] th row
547 if (A[kpn] == (bigfloat)0l) {
548 std::cout<<"simq A[kpn]=0\n";
549 delete [] IPS;
550 return(3);
551 }
552
553
554 ip = IPS[0];
555 X[0] = B[ip];
556 for (i = 1; i < n; i++) {
557 ip = IPS[i];
558 ipj = n * ip;
559 sum = 0.0;
560 for (j = 0; j < i; j++) {
561 sum += A[ipj] * X[j];
562 ++ipj;
563 }
564 X[i] = B[ip] - sum;
565 }
566
567 ipn = n * IPS[n-1] + n - 1;
568 X[n-1] = X[n-1] / A[ipn];
569
570 for (iback = 1; iback < n; iback++) {
571 //i goes (n-1),...,1
572 i = nm1 - iback;
573 ip = IPS[i];
574 nip = n*ip;
575 sum = 0.0;
576 aa = A+nip+i+1;
577 for (j= i + 1; j < n; j++)
578 sum += *aa++ * X[j];
579 X[i] = (X[i] - sum) / A[nip+i];
580 }
581
582 delete [] IPS;
583 return(0);
584}
585
586// Calculate the roots of the approximation
588
589 long i,j;
590 bigfloat x,dx=0.05;
591 bigfloat upper=1, lower=-100000;
592 bigfloat tol = 1e-20;
593
594 bigfloat *poly = new bigfloat[neq+1];
595
596 // First find the numerator roots
597 for (i=0; i<=n; i++) poly[i] = param[i];
598
599 for (i=n-1; i>=0; i--) {
600 roots[i] = rtnewt(poly,i+1,lower,upper,tol);
601 if (roots[i] == 0.0) {
602 std::cout<<"Failure to converge on root "<<i+1<<"/"<<n<<"\n";
603 return 0;
604 }
605 poly[0] = -poly[0]/roots[i];
606 for (j=1; j<=i; j++) poly[j] = (poly[j-1] - poly[j])/roots[i];
607 }
608
609 // Now find the denominator roots
610 poly[d] = 1l;
611 for (i=0; i<d; i++) poly[i] = param[n+1+i];
612
613 for (i=d-1; i>=0; i--) {
614 poles[i]=rtnewt(poly,i+1,lower,upper,tol);
615 if (poles[i] == 0.0) {
616 std::cout<<"Failure to converge on pole "<<i+1<<"/"<<d<<"\n";
617 return 0;
618 }
619 poly[0] = -poly[0]/poles[i];
620 for (j=1; j<=i; j++) poly[j] = (poly[j-1] - poly[j])/poles[i];
621 }
622
623 norm = param[n];
624
625 delete [] poly;
626
627 return 1;
628}
629
630// Evaluate the polynomial
632 bigfloat f = poly[size];
633 for (int i=size-1; i>=0; i--) f = f*x + poly[i];
634 return f;
635}
636
637// Evaluate the differential of the polynomial
639 bigfloat df = (bigfloat)size*poly[size];
640 for (int i=size-1; i>0; i--) df = df*x + (bigfloat)i*poly[i];
641 return df;
642}
643
644
645// Newton's method to calculate roots
647 bigfloat x2, bigfloat xacc) {
648 int j;
649 bigfloat df, dx, f, rtn;
650
651 rtn=(bigfloat)0.5*(x1+x2);
652 for (j=1; j<=JMAX;j++) {
653 f = polyEval(rtn, poly, i);
654 df = polyDiff(rtn, poly, i);
655 dx = f/df;
656 rtn -= dx;
657 if (abs_bf(dx) < xacc) return rtn;
658 }
659 std::cout<<"Maximum number of iterations exceeded in rtnewt\n";
660 return 0.0;
661}
662
663// Evaluate the partial fraction expansion of the rational function
664// with res roots and poles poles. Result is overwritten on input
665// arrays.
667 int i,j,small;
668 bigfloat temp;
669 bigfloat *numerator = new bigfloat[n];
670 bigfloat *denominator = new bigfloat[d];
671
672 // Construct the polynomials explicitly
673 for (i=1; i<n; i++) {
674 numerator[i] = 0l;
675 denominator[i] = 0l;
676 }
677 numerator[0]=1l;
678 denominator[0]=1l;
679
680 for (j=0; j<n; j++) {
681 for (i=n-1; i>=0; i--) {
682 numerator[i] *= -res[j];
683 denominator[i] *= -poles[j];
684 if (i>0) {
685 numerator[i] += numerator[i-1];
686 denominator[i] += denominator[i-1];
687 }
688 }
689 }
690
691 // Convert to proper fraction form.
692 // Fraction is now in the form 1 + n/d, where O(n)+1=O(d)
693 for (i=0; i<n; i++) numerator[i] -= denominator[i];
694
695 // Find the residues of the partial fraction expansion and absorb the
696 // coefficients.
697 for (i=0; i<n; i++) {
698 res[i] = 0l;
699 for (j=n-1; j>=0; j--) {
700 res[i] = poles[i]*res[i]+numerator[j];
701 }
702 for (j=n-1; j>=0; j--) {
703 if (i!=j) res[i] /= poles[i]-poles[j];
704 }
705 res[i] *= norm;
706 }
707
708 // res now holds the residues
709 j = 0;
710 for (i=0; i<n; i++) poles[i] = -poles[i];
711
712 // Move the ordering of the poles from smallest to largest
713 for (j=0; j<n; j++) {
714 small = j;
715 for (i=j+1; i<n; i++) {
716 if (poles[i] < poles[small]) small = i;
717 }
718 if (small != j) {
719 temp = poles[small];
720 poles[small] = poles[j];
721 poles[j] = temp;
722 temp = res[small];
723 res[small] = res[j];
724 res[j] = temp;
725 }
726 }
727
728 delete [] numerator;
729 delete [] denominator;
730}
731
732double AlgRemez::evaluateApprox(double x) {
733 return (double)approx((bigfloat)x);
734}
735
737 return 1.0/(double)approx((bigfloat)x);
738}
739
740double AlgRemez::evaluateFunc(double x) {
741 return (double)func((bigfloat)x);
742}
743
745 return 1.0/(double)func((bigfloat)x);
746}
747
748void AlgRemez::csv(std::ostream & os)
749{
750 double lambda_low = apstrt;
751 double lambda_high= apend;
752 for (double x=lambda_low; x<lambda_high; x*=1.05) {
753 double f = evaluateFunc(x);
754 double r = evaluateApprox(x);
755 os<< x<<","<<r<<","<<f<<","<<r-f<<std::endl;
756 }
757 return;
758}
759
accelerator_inline Grid_simd< S, V > cos(const Grid_simd< S, V > &r)
accelerator_inline Grid_simd< S, V > exp(const Grid_simd< S, V > &r)
B
vobj::scalar_object sum(const vobj *arg, Integer osites)
#define SUM_MAX
Definition Remez.h:28
#define JMAX
Definition Remez.h:27
#define M_PI
Definition Zolotarev.cc:41
void initialGuess()
Definition Remez.cc:262
bigfloat func(bigfloat x)
Definition Remez.cc:453
void pfe(bigfloat *res, bigfloat *poles, bigfloat norm)
Definition Remez.cc:666
int getPFE(double *res, double *pole, double *norm)
Definition Remez.cc:179
bigfloat tolerance
Definition Remez.h:67
unsigned long power_num
Definition Remez.h:55
bigfloat apend
Definition Remez.h:52
int iter
Definition Remez.h:65
int alloc
Definition Remez.h:59
int root()
Definition Remez.cc:587
bigfloat apwidt
Definition Remez.h:52
void allocate(int num_degree, int den_degree)
Definition Remez.cc:63
int n
Definition Remez.h:49
int d
Definition Remez.h:49
bigfloat * xx
Definition Remez.h:66
bigfloat norm
Definition Remez.h:46
void csv(std::ostream &os)
Definition Remez.cc:748
void equations()
Definition Remez.cc:382
bigfloat delta
Definition Remez.h:67
int foundRoots
Definition Remez.h:62
void search(bigfloat *step)
Definition Remez.cc:299
bigfloat polyDiff(bigfloat x, bigfloat *poly, long size)
Definition Remez.cc:638
bigfloat * a
Definition Remez.h:70
AlgRemez(double lower, double upper, long prec)
Definition Remez.cc:26
bigfloat * param
Definition Remez.h:45
double evaluateApprox(double x)
Definition Remez.cc:732
int a_length
Definition Remez.h:72
unsigned long power_den
Definition Remez.h:56
bigfloat rtnewt(bigfloat *poly, long i, bigfloat x1, bigfloat x2, bigfloat xacc)
Definition Remez.cc:646
int neq
Definition Remez.h:75
double evaluateInverseFunc(double x)
Definition Remez.cc:744
double generateApprox(int num_degree, int den_degree, unsigned long power_num, unsigned long power_den, int a_len, double *a_param, int *a_pow)
Definition Remez.cc:114
bigfloat * step
Definition Remez.h:66
bigfloat apstrt
Definition Remez.h:52
double evaluateFunc(double x)
Definition Remez.cc:740
virtual ~AlgRemez()
Definition Remez.cc:49
int getIPFE(double *res, double *pole, double *norm)
Definition Remez.cc:218
int simq(bigfloat *A, bigfloat *B, bigfloat *X, int n)
Definition Remez.cc:472
bigfloat polyEval(bigfloat x, bigfloat *poly, long size)
Definition Remez.cc:631
long prec
Definition Remez.h:78
bigfloat spread
Definition Remez.h:67
int * a_power
Definition Remez.h:71
bigfloat * roots
Definition Remez.h:45
bigfloat * mm
Definition Remez.h:66
void setBounds(double lower, double upper)
Definition Remez.cc:91
bigfloat getErr(bigfloat x, int *sign)
Definition Remez.cc:437
void stpini(bigfloat *step)
Definition Remez.cc:290
double evaluateInverseApprox(double x)
Definition Remez.cc:736
bigfloat approx(bigfloat x)
Definition Remez.cc:423
bigfloat * poles
Definition Remez.h:45
static void setDefaultPrecision(unsigned long dprec)
Definition bigfloat.h:37