Init(
            double a,
            double b,
            IList <double> x
            )
        {
            if (null == x)
            {
                throw new ArgumentNullException("x");
            }

            if (x.Count < 1)
            {
                throw new ArgumentOutOfRangeException("x");
            }

            if (b <= a)
            {
                throw new ArgumentOutOfRangeException("b");
            }

            _transformSummand = -0.5 * (a + b);
            _transformFactor  = 2.0 / (b - a);

            // trigonometric recurrence
            double a0    = 0.0;
            double delta = Math.PI / (x.Count - 1);
            double alpha = Math.Sin(delta / 2);

            alpha = 2 * alpha * alpha;
            double beta = Math.Sin(delta);

            double ca   = Math.Cos(a0);
            double sa   = Math.Sin(a0);
            double sign = 1.0;

            // construct chebyshev points and barycentric weights
            double[] t = new double[x.Count];
            double[] w = new double[x.Count];
            t[0] = ca;
            w[0] = 0.5;

            for (int i = 1; i < t.Length; i++)
            {
                double temps = sa - (alpha * sa - beta * ca);
                double tempc = ca - (alpha * ca + beta * sa);
                sa   = temps;
                ca   = tempc;
                sign = -sign;
                t[i] = ca;
                w[i] = sign;
            }

            w[w.Length - 1] *= 0.5;

            _barycentric.Init(t, x, w);
        }
        Init(
            double a,
            double b,
            IList <double> x
            )
        {
            if (null == x)
            {
                throw new ArgumentNullException("x");
            }

            if (x.Count < 1)
            {
                throw new ArgumentOutOfRangeException("x");
            }

            if (b <= a)
            {
                throw new ArgumentOutOfRangeException("b");
            }

            // construct equidistant points
            double[] t = new double[x.Count];
            t[0] = a;
            double step = (b - a) / (t.Length - 1);

            for (int i = 1; i < t.Length; i++)
            {
                t[i] = t[i - 1] + step;
            }

            // construct barycentric weights
            double[] w = new double[x.Count];
            w[0] = 1.0;
            for (int i = 1; i < w.Length; i++)
            {
                w[i] = -(w[i - 1] * (w.Length - i)) / i;
            }

            _barycentric.Init(t, x, w);
        }
        Init(
            IList <double> t,
            IList <double> x,
            int order
            )
        {
            if (null == t)
            {
                throw new ArgumentNullException("t");
            }

            if (null == x)
            {
                throw new ArgumentNullException("x");
            }

            if (t.Count < 1)
            {
                throw new ArgumentOutOfRangeException("t");
            }

            if (t.Count != x.Count)
            {
                throw new ArgumentException(Properties.Resources.ArgumentVectorsSameLengths);
            }

            if (0 > order || t.Count < order)
            {
                throw new ArgumentOutOfRangeException("order");
            }

            double[] ww = new double[x.Count];
            double[] tt = new double[t.Count];
            t.CopyTo(tt, 0);

            // order: odd -> negative, even -> positive
            double sign = ((order & 0x1) == 0x1) ? -1.0 : 1.0;

            // init permutation vector
            int[] perm = new int[ww.Length];
            for (int i = 0; i < perm.Length; i++)
            {
                perm[i] = i;
            }

            // sort and update permutation vector
            for (int i = 0; i < perm.Length - 1; i++)
            {
                for (int j = i + 1; j < perm.Length; j++)
                {
                    if (tt[j] < tt[i])
                    {
                        double s = tt[i];
                        tt[i] = tt[j];
                        tt[j] = s;
                        int k = perm[i];
                        perm[i] = perm[j];
                        perm[j] = k;
                    }
                }
            }

            // compute barycentric weights
            for (int k = 0; k < ww.Length; k++)
            {
                // Wk
                double s = 0;
                for (int i = Math.Max(k - order, 0); i <= Math.Min(k, ww.Length - 1 - order); i++)
                {
                    double v = 1;
                    for (int j = i; j <= i + order; j++)
                    {
                        if (j != k)
                        {
                            v = v / Math.Abs(tt[k] - tt[j]);
                        }
                    }

                    s = s + v;
                }

                ww[k] = sign * s;
                sign  = -sign;
            }

            // reorder back to original order, based on the permutation vector.
            double[] w = new double[ww.Length];
            for (int i = 0; i < w.Length; i++)
            {
                w[perm[i]] = ww[i];
            }

            _barycentric.Init(t, x, w);
        }