システムを使用する;
namespace Legalsoft.Truffer
{ /// <summary> /// チェビシェフ近似 /// </summary> public class Chebyshev { private int n { get; セット; プライベート int m {取得; セット; プライベート ダブル[] c {取得; セット; プライベート ダブルa {取得; セット; プライベート ダブルb {取得; セット; }
public Chebyshev(double[] cc, double aa, double bb)
{ this.n = cc.Length; これ.m = n; this.c = Globals.CopyFrom(cc); this.a = aa; これ.b = bb; }
public Chebyshev(double[] d)
{ this.n = d.Length; これ.m = n; this.c = 新しい 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); } */ /// <概要>
/// チェビシェフのルーチンの Polycof の逆: /// 多項式係数 d[0..n - 1] の配列を指定して
、同等のチェビシェフ オブジェクトを構築します。
/// </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; これ.m = nn; this.c = 新しい double[n]; this.a = aa; これ.b = bb;
double[] f = 新しい double[n];
ダブル bma = 0.5 * (b - a);
ダブル 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); ダブル ファク = 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 * 合計;
}
}
public double eval(double x, int m)
{ double d = 0.0; ダブル dd = 0.0;
if ((x - a) * (x - b) > 0.0)
{ throw new Exception("x が Chebyshev::eval の範囲内にありません"); double y = (2.0 * x - a - b) / (b - a); ダブル y2 = 2.0 * (y); for (int j = m - 1; j > 0; j--) { double sv = d; d = y2 * d - dd + c[j]; dd = SV; y * d - dd + 0.5 * c[0] を返します 。 }
public double[] getc()
{ return c; }
/// <summary> /// 同じ範囲 [a, b] にわたる既存の関数
の導関数を近似する新しいチェビシェフ オブジェクトを返します。 /// /// </summary> /// <returns></returns> public チェビシェフ デリバティブ() { 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]; ダブルコン = 2.0 / (b - a); for (int j = 0; j < n; j++) {
cder[j] *= con; 新しいチェビシェフ(cder, a, b)を返します
。 }
/// <summary> /// 同じ範囲 [a, b] にわたる既存の関数
の不定積分を近似する新しい Chebyshev オブジェクトを返します。 ///
/// 積分の定数は、
積分が a で消えるように設定されます。
/// </summary>
/// <returns></returns>
public Chebyshevintegral()
{ double sum = 0.0; ダブルファク = 1.0; double[] cint = 新しい double[n]; ダブルコン = 0.25 * (b - a); for (int j = 1; j < n - 1; j++) { cint[j] = con * (c[j - 1] - c[j + 1]) / j;
合計 += fac * cint[j];
fac = -fac;
cint[n - 1] = con * c [
n - 2] / (n - 1);
合計 += fac * cint[n - 1];
ベルト[0] = 2.0 * 合計;
新しいチェビシェフ(cint, a, b)を返します;
}
/// <summary>
/// チェビシェフ フィットからの多項式係数。係数配列
/// c[0..n-1] を指定すると、このルーチンは次のような係数配列 d[0..n-1] を返します。
/// sum(k= 0, n-1)dky^k = sum(k= 0, n-1)Tk(y)-c0/2。この方法は Clenshaw の
/// recursion(5.8.11) ですが、現在は算術ではなく代数的に適用されています。
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public double[] Polycofs(int m)
{ double[] d = new double[ m]; double[] dd = 新しい 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; ダブル 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];
dを返します。
}
public int setm(double thresh)
{ while (m > 1 && Math.Abs(c[m - 1]) < thresh) { m--; 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; ダブル cnst = 2.0 / (b - a); ダブルファク = 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) ; }
}
}