176 lines
5.8 KiB
Go
176 lines
5.8 KiB
Go
// InterpHermiteFunc
|
||
/*
|
||
------------------------------------------------------
|
||
作者 : Black Ghost
|
||
日期 : 2018-12-7
|
||
版本 : 0.0.0
|
||
------------------------------------------------------
|
||
计算不高于2n+1次Hermite插值方程,拟合n+1个函数值数据
|
||
点和对应的n+1个一阶导数点
|
||
满阶插值,即阶数不高于2n+1
|
||
理论:
|
||
n
|
||
H2n+1(x) = Sum (alphaj(x)*yj+betaj(x)*mj)
|
||
j=0
|
||
|
||
yj, mj分别为函数值和一阶导数值
|
||
|
||
n 1
|
||
alphaj(x) = (1-2(x-xj)*Sum -------)lj^2(x)
|
||
k=0,k!=j xj-xk
|
||
|
||
betaj(x) = (x-xj)lj^2(x)
|
||
|
||
(x-x0)(x-x1)...(x-xn)
|
||
lj(x) = --------------------------, (被减数不含xj项)
|
||
(xj-x0)(xj-x1)...(xj-xn)
|
||
|
||
参考 李信真, 车刚明, 欧阳洁, 等. 计算方法. 西北工业大学
|
||
出版社, 2000, pp 111-113.
|
||
------------------------------------------------------
|
||
输入 :
|
||
A 数据点矩阵,(n+1)x3,第一列xi;第二列yi;第三列y'i
|
||
输出 :
|
||
B 插值方程系数结果,从前到后对应从0到2n+1阶,(2n+2)x1
|
||
err 解出标志:false-未解出或达到步数上限;
|
||
true-全部解出
|
||
------------------------------------------------------
|
||
*/
|
||
|
||
package goNum
|
||
|
||
//求解lj(x)
|
||
func ljx_InterpHermiteFunc(A Matrix, j int) Matrix {
|
||
Bljx := ZeroMatrix(A.Rows, 1) //出去j,加常数项总共n+1
|
||
xj := A.GetFromMatrix(j, 0)
|
||
// j!=0
|
||
temp0 := (xj - A.GetFromMatrix(0, 0)) //x0
|
||
Bljx.Data[0] = -1.0 * A.GetFromMatrix(0, 0)
|
||
Bljx.Data[1] = 1.0
|
||
// j==0
|
||
if j == 0 {
|
||
temp0 = (xj - A.GetFromMatrix(1, 0)) //x1
|
||
Bljx.Data[0] = -1.0 * A.GetFromMatrix(1, 0)
|
||
}
|
||
//其它
|
||
for i := 1; i < A.Rows; i++ {
|
||
if (i != j) && (((j == 0) && (i > 1)) || (j > 0)) {
|
||
if i < j {
|
||
CA := ZeroMatrix(i+2, 1) //实际i+2行
|
||
CB := ZeroMatrix(i+2, 1) //实际i+1行
|
||
//先用x乘以之前每一项,相当于给每一项提升一阶,i+1
|
||
//再用-xi乘以B的每一有效项,i+1
|
||
CB.Data[0] = -1.0 * A.GetFromMatrix(i, 0) * Bljx.Data[0]
|
||
for ii := 1; ii < i+1; ii++ {
|
||
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
|
||
CA.Data[ii] = Bljx.Data[ii-1]
|
||
CB.Data[ii] = -1.0 * A.GetFromMatrix(i, 0) * Bljx.Data[ii]
|
||
}
|
||
CA.Data[i+1] = Bljx.Data[i]
|
||
//同阶相加赋予B
|
||
for ii := 0; ii < i+2; ii++ {
|
||
Bljx.Data[ii] = CA.Data[ii] + CB.Data[ii]
|
||
}
|
||
} else { //i>j
|
||
CA := ZeroMatrix(i+1, 1) //实际i+1行
|
||
CB := ZeroMatrix(i+1, 1) //实际i行
|
||
//先用x乘以之前每一项,相当于给每一项提升一阶,i+1
|
||
//再用-xi乘以B的每一有效项,i
|
||
CB.Data[0] = -1.0 * A.GetFromMatrix(i, 0) * Bljx.Data[0]
|
||
for ii := 1; ii < i; ii++ {
|
||
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
|
||
CA.Data[ii] = Bljx.Data[ii-1]
|
||
CB.Data[ii] = -1.0 * A.GetFromMatrix(i, 0) * Bljx.Data[ii]
|
||
}
|
||
CA.Data[i] = Bljx.Data[i-1]
|
||
//同阶相加赋予B
|
||
for ii := 0; ii < i+1; ii++ {
|
||
Bljx.Data[ii] = CA.Data[ii] + CB.Data[ii]
|
||
}
|
||
}
|
||
temp0 = temp0 * (xj - A.GetFromMatrix(i, 0))
|
||
}
|
||
}
|
||
for i := 0; i < Bljx.Rows; i++ {
|
||
Bljx.Data[i] = Bljx.Data[i] / temp0
|
||
}
|
||
return Bljx
|
||
}
|
||
|
||
//求解ljx^2
|
||
func ljx2_InterpHermiteFunc(A Matrix, j int) Matrix {
|
||
ljx := ljx_InterpHermiteFunc(A, j) //n+1 rows
|
||
BA := ZeroMatrix(2*ljx.Rows-1, 1) //2n+1 rows
|
||
for i := ljx.Rows - 1; i >= 0; i-- {
|
||
for j := ljx.Rows - 1; j >= 0; j-- {
|
||
BA.Data[i+j] = BA.Data[i+j] + ljx.Data[i]*ljx.Data[j]
|
||
}
|
||
}
|
||
return BA
|
||
}
|
||
|
||
//求解alphajx和betajx,合并是为了减少对ljx2_InterpHermiteFunc的调用
|
||
func alphabetajx_InterpHermiteFunc(A Matrix, j int) (Matrix, Matrix) {
|
||
var temp0 float64
|
||
ljx2 := ljx2_InterpHermiteFunc(A, j) //2n+1 rows
|
||
alphajx := ZeroMatrix(ljx2.Rows+1, 1) //2n+2 rows
|
||
betajx := ZeroMatrix(ljx2.Rows+1, 1) //2n+2 rows
|
||
xj := A.GetFromMatrix(j, 0)
|
||
|
||
//计算alphajx中的求和
|
||
for k := 0; k < A.Rows; k++ {
|
||
if k != j {
|
||
temp0 += 1.0 / (xj - A.GetFromMatrix(k, 0))
|
||
}
|
||
}
|
||
temp0 = 2.0 * temp0
|
||
|
||
//alphajx = (temp0*xj+1 - temp0*x) * ljx2
|
||
//betajx = (x-xj) * ljx2
|
||
//2n+1阶,2n+2行
|
||
alphajx.Data[alphajx.Rows-1] = -1.0 * temp0 * ljx2.Data[ljx2.Rows-1]
|
||
betajx.Data[betajx.Rows-1] = ljx2.Data[ljx2.Rows-1]
|
||
//其它非零阶, alphajx.Rows-2 == betajx.Rows-2 == ljx2.Rows-1
|
||
for i := alphajx.Rows - 2; i > 0; i-- {
|
||
alphajx.Data[i] = (temp0*xj+1.0)*ljx2.Data[i] - 1.0*temp0*ljx2.Data[i-1]
|
||
betajx.Data[i] = -1.0*xj*ljx2.Data[i] + ljx2.Data[i-1]
|
||
}
|
||
//零阶
|
||
alphajx.Data[0] = (temp0*xj + 1.0) * ljx2.Data[0]
|
||
betajx.Data[0] = -1.0 * xj * ljx2.Data[0]
|
||
|
||
return alphajx, betajx
|
||
}
|
||
|
||
// InterpHermiteFunc 计算不高于2n+1次Hermite插值方程,拟合n+1个函数值数据点和对应的n+1个一阶导数点
|
||
func InterpHermiteFunc(A Matrix) (Matrix, bool) {
|
||
/*
|
||
计算不高于2n+1次Hermite插值方程,拟合n+1个函数值数据点和对应的n+1个一阶导数点
|
||
输入 :
|
||
A 数据点矩阵,(n+1)x3,第一列xi;第二列yi;第三列y'i
|
||
输出 :
|
||
B 插值方程系数结果,从前到后对应从0到2n+1阶,(2n+2)x1
|
||
err 解出标志:false-未解出或达到步数上限;
|
||
true-全部解出
|
||
*/
|
||
//判断A列数是否为3
|
||
if A.Columns != 3 {
|
||
panic("Error in goNum.InterpHermite: give me xi, yi and y'i")
|
||
}
|
||
|
||
var err bool = false
|
||
n := A.Rows - 1
|
||
BA := ZeroMatrix(2*n+2, 1)
|
||
|
||
for j := 0; j <= n; j++ {
|
||
alphajx, betajx := alphabetajx_InterpHermiteFunc(A, j)
|
||
for i := 0; i < alphajx.Rows; i++ {
|
||
BA.Data[i] = BA.Data[i] + alphajx.Data[i]*A.GetFromMatrix(j, 1)
|
||
BA.Data[i] = BA.Data[i] + betajx.Data[i]*A.GetFromMatrix(j, 2)
|
||
}
|
||
}
|
||
|
||
err = true
|
||
return BA, err
|
||
}
|