forked from chfenger/goNum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
InterpLagrangeFunc_test.go
155 lines (140 loc) · 4.62 KB
/
InterpLagrangeFunc_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// InterpLagrangeFunc_test
/*
------------------------------------------------------
作者 : Black Ghost
日期 : 2018-12-4
版本 : 0.0.0
------------------------------------------------------
求解n次拉格朗日Lagrange插值方程系数,拟合n+1个数据点
满阶插值,即阶数为给定点数-1(因不能确定非满阶时所选取的
插值点是否合理)
理论:
n omega0n+1(x)
Ln(x) = Sum(----------------------)
k=0 (x-xk)*omega1n+1(xk)
n
omega0n+1(x) = Prod(x-xi)
i=0
n
omega1n+1(xk) = Prod (xk-xi)
i=0,i!=k
参考 李信真, 车刚明, 欧阳洁, 等. 计算方法. 西北工业大学
出版社, 2000, pp 94-100.
------------------------------------------------------
输入 :
A 数据点矩阵,(n+1)x2,第一列xi;第二列yi
输出 :
B 插值系数矩阵,(n+1)x1,0~n
err 解出标志:false-未解出或达到步数上限;
true-全部解出
------------------------------------------------------
*/
package goNum_test
import (
"testing"
"github.com/chfenger/goNum"
)
//计算分母
func omega1_InterpLagrangeFunc(A goNum.Matrix, k, n int) float64 {
var sol float64 = 1.0
for i := 0; i <= n; i++ {
if i != k {
sol = sol * (A.GetFromMatrix(k, 0) - A.GetFromMatrix(i, 0))
}
}
return sol
}
//计算分子并由高阶到低阶排序
func omega0_InterpLagrangeFunc(A goNum.Matrix, k, n int) goNum.Matrix {
B := goNum.ZeroMatrix(n+1, 1)
//第零阶 x-x0
if k == 0 { //如果k==0,则从x1循环
B.SetMatrix(0, 0, -1.0*A.GetFromMatrix(1, 0))
B.SetMatrix(1, 0, 1.0)
}
if k > 0 { //如果k>0,则从x0循环
B.SetMatrix(0, 0, -1.0*A.GetFromMatrix(0, 0))
B.SetMatrix(1, 0, 1.0)
}
//其他i!=k阶
for i := 1; i <= n; i++ {
if (i != k) && ((k > 0) || ((k == 0) && (i > 1))) {
if k < i {
CA := goNum.ZeroMatrix(i+1, 1) //实际i+1行
CB := goNum.ZeroMatrix(i+1, 1) //实际i行
//先用x乘以之前每一项,相当于给每一项提升一阶,i+1
for ii := 1; ii < i+1; ii++ {
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
CA.Data[ii] = B.Data[ii-1]
}
//再用-xi乘以B的每一有效项,i
for ii := 0; ii < i; ii++ {
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
CB.Data[ii] = -1.0 * A.GetFromMatrix(i, 0) * B.Data[ii]
}
//同阶相加赋予B
for ii := 0; ii < i+1; ii++ {
B.Data[ii] = CA.Data[ii] + CB.Data[ii]
}
} else { // k > i
CA := goNum.ZeroMatrix(i+2, 1) //实际i+2行
CB := goNum.ZeroMatrix(i+2, 1) //实际i+1行
//先用x乘以之前每一项,相当于给每一项提升一阶,i+1
for ii := 1; ii < i+2; ii++ {
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
CA.Data[ii] = B.Data[ii-1]
}
//再用-xi乘以B的每一有效项,i+1
for ii := 0; ii < i+1; ii++ {
//单列可以这样,否则只能用SetMatrix和GetFromMatrix方法
CB.Data[ii] = -1.0 * A.GetFromMatrix(i, 0) * B.Data[ii]
}
//同阶相加赋予B
for ii := 0; ii < i+2; ii++ {
B.Data[ii] = CA.Data[ii] + CB.Data[ii]
}
}
}
}
return B
}
// InterpLagrangeFunc 求解n次拉格朗日Lagrange插值方程系数,拟合n+1个数据点
func InterpLagrangeFunc(A goNum.Matrix) (goNum.Matrix, bool) {
/*
求解n次拉格朗日Lagrange插值方程系数,拟合n+1个数据点
输入 :
A 数据点矩阵,(n+1)x2,第一列xi;第二列yi
输出 :
B 插值系数矩阵,(n+1)x1
err 解出标志:false-未解出或达到步数上限;
true-全部解出
*/
//阶数
n := A.Rows - 1
B := goNum.ZeroMatrix(n+1, 1) //最终系数矩阵
var err bool = false
//计算系数矩阵
for k := 0; k <= n; k++ {
//1. 计算分母和系数乘积
temp0 := A.GetFromMatrix(k, 1) / omega1_InterpLagrangeFunc(A, k, n)
//2. 计算分子并乘以上一步的结果,由高阶到低阶排序
temp1 := omega0_InterpLagrangeFunc(A, k, n)
for i := 0; i < temp1.Rows; i++ {
temp1.Data[i] = temp1.Data[i] * temp0
}
//3. 累加
for i := 0; i < B.Rows; i++ {
B.Data[i] += temp1.Data[i]
}
}
err = true
return B, err
}
func BenchmarkInterpLagrangeFunc(b *testing.B) {
A23 := goNum.NewMatrix(3, 2, []float64{0.0, 1.0,
1.0, 2.0,
2.0, 3.0})
for i := 0; i < b.N; i++ {
InterpLagrangeFunc(A23)
}
}