#include #include #include #include #include #include #include #include // Constructor AlgRemezGeneral::AlgRemezGeneral(double lower, double upper, long precision, bigfloat (*f)(bigfloat x, void *data), void *data): f(f), data(data), prec(precision), apstrt(lower), apend(upper), apwidt(upper - lower), n(0), d(0), pow_n(0), pow_d(0) { bigfloat::setDefaultPrecision(prec); std::cout<<"Approximation bounds are ["< tolerance) { if (iter++ % report_freq==0) std::cout<<"Iteration " <= tolerance ); search(); } int sign; double error = (double)getErr(mm[0],&sign); std::cout<<"Converged at "<= 0; i--) yn = x * yn + (num_pows[i] != -1 ? param[c--] : bigfloat(0l)); c = n+d; bigfloat yd = 1l; //Highest degree coefficient is 1.0 for (int i = pow_d-1; i >= 0; i--) yd = x * yd + (den_pows[i] != -1 ? param[c--] : bigfloat(0l)); return(yn/yd); } // Compute size and sign of the approximation error at x bigfloat AlgRemezGeneral::getErr(bigfloat x, int *sign) const{ bigfloat f = func(x); bigfloat e = approx(x) - f; if (f != 0) e /= f; if (e < (bigfloat)0.0) { *sign = -1; e = -e; } else *sign = 1; return(e); } // Solve the system AX=B int AlgRemezGeneral::simq(){ int ip, ipj, ipk, ipn; int idxpiv; int kp, kp1, kpk, kpn; int nip, nkp; bigfloat em, q, rownrm, big, size, pivot, sum; bigfloat *aa; bigfloat *X = param.data(); int n = neq; int nm1 = n - 1; // Initialize IPS and X int ij = 0; for (int i = 0; i < n; i++) { IPS[i] = i; rownrm = 0.0; for(int j = 0; j < n; j++) { q = abs_bf(A[ij]); if(rownrm < q) rownrm = q; ++ij; } if (rownrm == (bigfloat)0l) { std::cout<<"simq rownrm=0\n"; return(1); } X[i] = (bigfloat)1.0 / rownrm; } for (int k = 0; k < nm1; k++) { big = 0.0; idxpiv = 0; for (int i = k; i < n; i++) { ip = IPS[i]; ipk = n*ip + k; size = abs_bf(A[ipk]) * X[ip]; if (size > big) { big = size; idxpiv = i; } } if (big == (bigfloat)0l) { std::cout<<"simq big=0\n"; return(2); } if (idxpiv != k) { int j = IPS[k]; IPS[k] = IPS[idxpiv]; IPS[idxpiv] = j; } kp = IPS[k]; kpk = n*kp + k; pivot = A[kpk]; kp1 = k+1; for (int i = kp1; i < n; i++) { ip = IPS[i]; ipk = n*ip + k; em = -A[ipk] / pivot; A[ipk] = -em; nip = n*ip; nkp = n*kp; aa = A.data()+nkp+kp1; for (int j = kp1; j < n; j++) { ipj = nip + j; A[ipj] = A[ipj] + em * *aa++; } } } kpn = n * IPS[n-1] + n - 1; // last element of IPS[n] th row if (A[kpn] == (bigfloat)0l) { std::cout<<"simq A[kpn]=0\n"; return(3); } ip = IPS[0]; X[0] = B[ip]; for (int i = 1; i < n; i++) { ip = IPS[i]; ipj = n * ip; sum = 0.0; for (int j = 0; j < i; j++) { sum += A[ipj] * X[j]; ++ipj; } X[i] = B[ip] - sum; } ipn = n * IPS[n-1] + n - 1; X[n-1] = X[n-1] / A[ipn]; for (int iback = 1; iback < n; iback++) { //i goes (n-1),...,1 int i = nm1 - iback; ip = IPS[i]; nip = n*ip; sum = 0.0; aa = A.data()+nip+i+1; for (int j= i + 1; j < n; j++) sum += *aa++ * X[j]; X[i] = (X[i] - sum) / A[nip+i]; } return(0); } void AlgRemezGeneral::csv(std::ostream & os) const{ os << "Numerator" << std::endl; for(int i=0;i<=pow_n;i++){ os << getCoeffNum(i) << "*x^" << i; if(i!=pow_n) os << " + "; } os << std::endl; os << "Denominator" << std::endl; for(int i=0;i<=pow_d;i++){ os << getCoeffDen(i) << "*x^" << i; if(i!=pow_d) os << " + "; } os << std::endl; //For a true minimax solution the errors should all be equal and the signs should oscillate +-+-+- etc int sign; os << "Errors at maxima: coordinate, error, (sign)" << std::endl; for(int i=0;i