Task: Chebyshev coefficients

C: #include <stdio.h>
#include <string.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

double test_func(double x)
{
	
	return cos(x);
}


double map(double x, double min_x, double max_x, double min_to, double max_to)
{
	return (x - min_x)/(max_x - min_x)*(max_to - min_to) + min_to;
}

void cheb_coef(double (*func)(double), int n, double min, double max, double *coef)
{
	memset(coef, 0, sizeof(double) * n);
	for (int i = 0; i < n; i++) {
		double f = func(map(cos(M_PI*(i + .5f)/n), -1, 1, min, max))*2/n;
		for (int j = 0; j < n; j++)
			coef[j] += f*cos(M_PI*j*(i + .5f)/n);
	}
}



double cheb_approx(double x, int n, double min, double max, double *coef)
{
	double a = 1, b = map(x, min, max, -1, 1), c;
	double res = coef[0]/2 + coef[1]*b;

	x = 2*b;
	for (int i = 2; i < n; a = b, b = c, i++)
		
		res += coef[i]*(c = x*b - a);

	return res;
}

int main(void)
{
#define N 10
	double c[N], min = 0, max = 1;
	cheb_coef(test_func, N, min, max, c);

	printf("Coefficients:");
	for (int i = 0; i < N; i++)
		printf(" %lg", c[i]);

	puts("\n\nApproximation:\n   x           func(x)     approx      diff");
	for (int i = 0; i <= 20; i++) {
		double x = map(i, 0, 20, min, max);
		double f = test_func(x);
		double approx = cheb_approx(x, N, min, max, c);

		printf("% 10.8lf % 10.8lf % 10.8lf % 4.1le\n",
			x, f, approx, approx - f);
	}

	return 0;
}



C#: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chebyshev {
    class Program {
        struct ChebyshevApprox {
            public readonly List<double> coeffs;
            public readonly Tuple<double, double> domain;

            public ChebyshevApprox(Func<double, double> func, int n, Tuple<double, double> domain) {
                coeffs = ChebCoef(func, n, domain);
                this.domain = domain;
            }

            public double Call(double x) {
                return ChebEval(coeffs, domain, x);
            }
        }

        static double AffineRemap(Tuple<double, double> from, double x, Tuple<double, double> to) {
            return to.Item1 + (x - from.Item1) * (to.Item2 - to.Item1) / (from.Item2 - from.Item1);
        }

        static List<double> ChebCoef(List<double> fVals) {
            int n = fVals.Count;
            double theta = Math.PI / n;
            List<double> retval = new List<double>();
            for (int i = 0; i < n; i++) {
                retval.Add(0.0);
            }
            for (int ii = 0; ii < n; ii++) {
                double f = fVals[ii] * 2.0 / n;
                double phi = (ii + 0.5) * theta;
                double c1 = Math.Cos(phi);
                double s1 = Math.Sin(phi);
                double c = 1.0;
                double s = 0.0;
                for (int j = 0; j < n; j++) {
                    retval[j] += f * c;
                    
                    double cNext = c * c1 - s * s1;
                    s = c * s1 + s * c1;
                    c = cNext;
                }
            }
            return retval;
        }

        static List<double> ChebCoef(Func<double, double> func, int n, Tuple<double, double> domain) {
            double remap(double x) {
                return AffineRemap(new Tuple<double, double>(-1.0, 1.0), x, domain);
            }
            double theta = Math.PI / n;
            List<double> fVals = new List<double>();
            for (int i = 0; i < n; i++) {
                fVals.Add(0.0);
            }
            for (int ii = 0; ii < n; ii++) {
                fVals[ii] = func(remap(Math.Cos((ii + 0.5) * theta)));
            }
            return ChebCoef(fVals);
        }

        static double ChebEval(List<double> coef, double x) {
            double a = 1.0;
            double b = x;
            double c;
            double retval = 0.5 * coef[0] + b * coef[1];
            var it = coef.GetEnumerator();
            it.MoveNext();
            it.MoveNext();
            while (it.MoveNext()) {
                double pc = it.Current;
                c = 2.0 * b * x - a;
                retval += pc * c;
                a = b;
                b = c;
            }
            return retval;
        }

        static double ChebEval(List<double> coef, Tuple<double, double> domain, double x) {
            return ChebEval(coef, AffineRemap(domain, x, new Tuple<double, double>(-1.0, 1.0)));
        }

        static void Main() {
            const int N = 10;
            ChebyshevApprox fApprox = new ChebyshevApprox(Math.Cos, N, new Tuple<double, double>(0.0, 1.0));
            Console.WriteLine("Coefficients: ");
            foreach (var c in fApprox.coeffs) {
                Console.WriteLine("\t{0: 0.00000000000000;-0.00000000000000;zero}", c);
            }

            Console.WriteLine("\nApproximation:\n    x       func(x)        approx      diff");
            const int nX = 20;
            const int min = 0;
            const int max = 1;
            for (int i = 0; i < nX; i++) {
                double x = AffineRemap(new Tuple<double, double>(0, nX), i, new Tuple<double, double>(min, max));
                double f = Math.Cos(x);
                double approx = fApprox.Call(x);
                Console.WriteLine("{0:0.000} {1:0.00000000000000} {2:0.00000000000000} {3:E}", x, f, approx, approx - f);
            }
        }
    }
}