41 Star 214 Fork 64

黑影/goNum

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
InterpHermiteFunc_test.go 6.34 KB
一键复制 编辑 原始数据 按行查看 历史
黑影 提交于 2019-03-01 10:10 . update comments
// InterpHermiteFunc_test
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-8
版本 : 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_test
import (
"testing"
"github.com/chfenger/goNum"
)
//求解lj(x)
func ljx_InterpHermiteFunc(A goNum.Matrix, j int) goNum.Matrix {
Bljx := goNum.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 := goNum.ZeroMatrix(i+2, 1) //实际i+2行
CB := goNum.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 := goNum.ZeroMatrix(i+1, 1) //实际i+1行
CB := goNum.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 goNum.Matrix, j int) goNum.Matrix {
ljx := ljx_InterpHermiteFunc(A, j) //n+1 rows
BA := goNum.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 goNum.Matrix, j int) (goNum.Matrix, goNum.Matrix) {
var temp0 float64
ljx2 := ljx2_InterpHermiteFunc(A, j) //2n+1 rows
alphajx := goNum.ZeroMatrix(ljx2.Rows+1, 1) //2n+2 rows
betajx := goNum.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 goNum.Matrix) (goNum.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 := goNum.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
}
func BenchmarkInterpHermiteFunc(b *testing.B) {
//2.4x^3+1.5x^2+0.3x-1.63
A26 := goNum.NewMatrix(4, 3, []float64{-10.0, -2254.63, 690.3,
-4.0, -132.43, 103.5,
4.0, 177.17, 127.5,
10.0, 2551.37, 750.3})
// A27 := goNum.NewMatrix(3, 3, []float64{0.0, 0.0, 1.0,
// 1.0, 1.0, 1.0,
// 2.0, 2.0, 1.0})
for i := 0; i < b.N; i++ {
InterpHermiteFunc(A26)
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/chfenger/goNum.git
[email protected]:chfenger/goNum.git
chfenger
goNum
goNum
master

搜索帮助