1 文本格式
using System;
namespace Legalsoft.Truffer
{
/// <summary>
/// Chebyshev approximation
/// </summary>
public class Chebyshev
{
private int n { get; set; }
private int m { get; set; }
private double[] c { get; set; }
private double a { get; set; }
private double b { get; set; }
public Chebyshev(double[] cc, double aa, double bb)
{
this.n = cc.Length;
this.m = n;
this.c = Globals.CopyFrom(cc);
this.a = aa;
this.b = bb;
}
public Chebyshev(double[] d)
{
this.n = d.Length;
this.m = n;
this.c = new double[n];
this.a = -1.0;
this.b = 1.0;
c[n - 1] = d[n - 1];
c[n - 2] = 2.0 * d[n - 2];
for (int j = n - 3; j >= 0; j--)
{
c[j] = 2.0 * d[j] + c[j + 2];
for (int i = j + 1; i < n - 2; i++)
{
c[i] = (c[i] + c[i + 2]) / 2;
}
c[n - 2] /= 2;
c[n - 1] /= 2;
}
}
/*
public Chebyshev(UniVarRealValueFun func, double aa, double bb)
{
new this(func, aa, bb, 50);
}
*/
/// <summary>
/// Inverse of routine polycofs in Chebyshev: Given an array of polynomial
/// coefficients d[0..n - 1], construct an equivalent Chebyshev object.
/// </summary>
/// <param name="func"></param>
/// <param name="aa"></param>
/// <param name="bb"></param>
/// <param name="nn"></param>
public Chebyshev(UniVarRealValueFun func, double aa, double bb, int nn = 50)
{
this.n = nn;
this.m = nn;
this.c = new double[n];
this.a = aa;
this.b = bb;
double[] f = new double[n];
double bma = 0.5 * (b - a);
double bpa = 0.5 * (b + a);
for (int k = 0; k < n; k++)
{
double y = Math.Cos(Math.PI * (k + 0.5) / n);
f[k] = func.funk(y * bma + bpa);
}
double fac = 2.0 / n;
for (int j = 0; j < n; j++)
{
double sum = 0.0;
for (int k = 0; k < n; k++)
{
sum += f[k] * Math.Cos(Math.PI * j * (k + 0.5) / n);
}
c[j] = fac * sum;
}
}
public double eval(double x, int m)
{
double d = 0.0;
double dd = 0.0;
if ((x - a) * (x - b) > 0.0)
{
throw new Exception("x not in range in Chebyshev::eval");
}
double y = (2.0 * x - a - b) / (b - a);
double y2 = 2.0 * (y);
for (int j = m - 1; j > 0; j--)
{
double sv = d;
d = y2 * d - dd + c[j];
dd = sv;
}
return y * d - dd + 0.5 * c[0];
}
public double[] getc()
{
return c;
}
/// <summary>
/// Return a new Chebyshev object that approximates the derivative of the
/// existing function over the same range[a, b].
/// </summary>
/// <returns></returns>
public Chebyshev derivative()
{
double[] cder = new double[n];
cder[n - 1] = 0.0;
cder[n - 2] = 2 * (n - 1) * c[n - 1];
for (int j = n - 2; j > 0; j--)
{
cder[j - 1] = cder[j + 1] + 2 * j * c[j];
}
double con = 2.0 / (b - a);
for (int j = 0; j < n; j++)
{
cder[j] *= con;
}
return new Chebyshev(cder, a, b);
}
/// <summary>
/// Return a new Chebyshev object that approximates the indefinite integral of
/// the existing function over the same range[a, b]. The constant of
/// integration is set so that the integral vanishes at a.
/// </summary>
/// <returns></returns>
public Chebyshev integral()
{
double sum = 0.0;
double fac = 1.0;
double[] cint = new double[n];
double con = 0.25 * (b - a);
for (int j = 1; j < n - 1; j++)
{
cint[j] = con * (c[j - 1] - c[j + 1]) / j;
sum += fac * cint[j];
fac = -fac;
}
cint[n - 1] = con * c[n - 2] / (n - 1);
sum += fac * cint[n - 1];
cint[0] = 2.0 * sum;
return new Chebyshev(cint, a, b);
}
/// <summary>
/// Polynomial coefficients from a Chebyshev fit.Given a coefficient array
/// c[0..n-1], this routine returns a coefficient array d[0..n-1] such that
/// sum(k= 0, n-1)dky^k = sum(k= 0, n-1)Tk(y)-c0/2. The method is Clenshaw's
/// recurrence(5.8.11), but now applied algebraically rather than arithmetically.
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public double[] polycofs(int m)
{
double[] d = new double[m];
double[] dd = new double[m];
for (int j = 0; j < m; j++)
{
d[j] = 0.0;
dd[j] = 0.0;
}
d[0] = c[m - 1];
for (int j = m - 2; j > 0; j--)
{
for (int k = m - j; k > 0; k--)
{
double s1v = d[k];
d[k] = 2.0 * d[k - 1] - dd[k];
dd[k] = s1v;
}
double s2v = d[0];
d[0] = -dd[0] + c[j];
dd[0] = s2v;
}
for (int j = m - 1; j > 0; j--)
{
d[j] = d[j - 1] - dd[j];
}
d[0] = -dd[0] + 0.5 * c[0];
return d;
}
public int setm(double thresh)
{
while (m > 1 && Math.Abs(c[m - 1]) < thresh)
{
m--;
}
return m;
}
public double get(double x)
{
return eval(x, m);
}
public double[] polycofs()
{
return polycofs(m);
}
public static void pcshft(double a, double b, double[] d)
{
int n = d.Length;
double cnst = 2.0 / (b - a);
double fac = cnst;
for (int j = 1; j < n; j++)
{
d[j] *= fac;
fac *= cnst;
}
cnst = 0.5 * (a + b);
for (int j = 0; j <= n - 2; j++)
{
for (int k = n - 2; k >= j; k--)
{
d[k] -= cnst * d[k + 1];
}
}
}
public static void ipcshft(double a, double b, double[] d)
{
pcshft(-(2.0 + b + a) / (b - a), (2.0 - b - a) / (b - a), d);
}
}
}
2 代码格式
cs
using System;
namespace Legalsoft.Truffer
{
/// <summary>
/// Chebyshev approximation
/// </summary>
public class Chebyshev
{
private int n { get; set; }
private int m { get; set; }
private double[] c { get; set; }
private double a { get; set; }
private double b { get; set; }
public Chebyshev(double[] cc, double aa, double bb)
{
this.n = cc.Length;
this.m = n;
this.c = Globals.CopyFrom(cc);
this.a = aa;
this.b = bb;
}
public Chebyshev(double[] d)
{
this.n = d.Length;
this.m = n;
this.c = new double[n];
this.a = -1.0;
this.b = 1.0;
c[n - 1] = d[n - 1];
c[n - 2] = 2.0 * d[n - 2];
for (int j = n - 3; j >= 0; j--)
{
c[j] = 2.0 * d[j] + c[j + 2];
for (int i = j + 1; i < n - 2; i++)
{
c[i] = (c[i] + c[i + 2]) / 2;
}
c[n - 2] /= 2;
c[n - 1] /= 2;
}
}
/*
public Chebyshev(UniVarRealValueFun func, double aa, double bb)
{
new this(func, aa, bb, 50);
}
*/
/// <summary>
/// Inverse of routine polycofs in Chebyshev: Given an array of polynomial
/// coefficients d[0..n - 1], construct an equivalent Chebyshev object.
/// </summary>
/// <param name="func"></param>
/// <param name="aa"></param>
/// <param name="bb"></param>
/// <param name="nn"></param>
public Chebyshev(UniVarRealValueFun func, double aa, double bb, int nn = 50)
{
this.n = nn;
this.m = nn;
this.c = new double[n];
this.a = aa;
this.b = bb;
double[] f = new double[n];
double bma = 0.5 * (b - a);
double bpa = 0.5 * (b + a);
for (int k = 0; k < n; k++)
{
double y = Math.Cos(Math.PI * (k + 0.5) / n);
f[k] = func.funk(y * bma + bpa);
}
double fac = 2.0 / n;
for (int j = 0; j < n; j++)
{
double sum = 0.0;
for (int k = 0; k < n; k++)
{
sum += f[k] * Math.Cos(Math.PI * j * (k + 0.5) / n);
}
c[j] = fac * sum;
}
}
public double eval(double x, int m)
{
double d = 0.0;
double dd = 0.0;
if ((x - a) * (x - b) > 0.0)
{
throw new Exception("x not in range in Chebyshev::eval");
}
double y = (2.0 * x - a - b) / (b - a);
double y2 = 2.0 * (y);
for (int j = m - 1; j > 0; j--)
{
double sv = d;
d = y2 * d - dd + c[j];
dd = sv;
}
return y * d - dd + 0.5 * c[0];
}
public double[] getc()
{
return c;
}
/// <summary>
/// Return a new Chebyshev object that approximates the derivative of the
/// existing function over the same range[a, b].
/// </summary>
/// <returns></returns>
public Chebyshev derivative()
{
double[] cder = new double[n];
cder[n - 1] = 0.0;
cder[n - 2] = 2 * (n - 1) * c[n - 1];
for (int j = n - 2; j > 0; j--)
{
cder[j - 1] = cder[j + 1] + 2 * j * c[j];
}
double con = 2.0 / (b - a);
for (int j = 0; j < n; j++)
{
cder[j] *= con;
}
return new Chebyshev(cder, a, b);
}
/// <summary>
/// Return a new Chebyshev object that approximates the indefinite integral of
/// the existing function over the same range[a, b]. The constant of
/// integration is set so that the integral vanishes at a.
/// </summary>
/// <returns></returns>
public Chebyshev integral()
{
double sum = 0.0;
double fac = 1.0;
double[] cint = new double[n];
double con = 0.25 * (b - a);
for (int j = 1; j < n - 1; j++)
{
cint[j] = con * (c[j - 1] - c[j + 1]) / j;
sum += fac * cint[j];
fac = -fac;
}
cint[n - 1] = con * c[n - 2] / (n - 1);
sum += fac * cint[n - 1];
cint[0] = 2.0 * sum;
return new Chebyshev(cint, a, b);
}
/// <summary>
/// Polynomial coefficients from a Chebyshev fit.Given a coefficient array
/// c[0..n-1], this routine returns a coefficient array d[0..n-1] such that
/// sum(k= 0, n-1)dky^k = sum(k= 0, n-1)Tk(y)-c0/2. The method is Clenshaw's
/// recurrence(5.8.11), but now applied algebraically rather than arithmetically.
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public double[] polycofs(int m)
{
double[] d = new double[m];
double[] dd = new double[m];
for (int j = 0; j < m; j++)
{
d[j] = 0.0;
dd[j] = 0.0;
}
d[0] = c[m - 1];
for (int j = m - 2; j > 0; j--)
{
for (int k = m - j; k > 0; k--)
{
double s1v = d[k];
d[k] = 2.0 * d[k - 1] - dd[k];
dd[k] = s1v;
}
double s2v = d[0];
d[0] = -dd[0] + c[j];
dd[0] = s2v;
}
for (int j = m - 1; j > 0; j--)
{
d[j] = d[j - 1] - dd[j];
}
d[0] = -dd[0] + 0.5 * c[0];
return d;
}
public int setm(double thresh)
{
while (m > 1 && Math.Abs(c[m - 1]) < thresh)
{
m--;
}
return m;
}
public double get(double x)
{
return eval(x, m);
}
public double[] polycofs()
{
return polycofs(m);
}
public static void pcshft(double a, double b, double[] d)
{
int n = d.Length;
double cnst = 2.0 / (b - a);
double fac = cnst;
for (int j = 1; j < n; j++)
{
d[j] *= fac;
fac *= cnst;
}
cnst = 0.5 * (a + b);
for (int j = 0; j <= n - 2; j++)
{
for (int k = n - 2; k >= j; k--)
{
d[k] -= cnst * d[k + 1];
}
}
}
public static void ipcshft(double a, double b, double[] d)
{
pcshft(-(2.0 + b + a) / (b - a), (2.0 - b - a) / (b - a), d);
}
}
}