Another update from ingydotnet^djgoku
This commit is contained in:
parent
91df62d461
commit
948b86eafa
7604 changed files with 108452 additions and 22726 deletions
|
|
@ -39,35 +39,35 @@ var methods = []method{
|
|||
}
|
||||
|
||||
func rectLeft(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
x0 := t.lower
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
// x1-x0 better than r/nf.
|
||||
// (with r/nf, the represenation error accumulates)
|
||||
parts[i] = t.f(x0) * (x1 - x0)
|
||||
a.add(t.f(x0) * (x1 - x0))
|
||||
x0 = x1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func rectRight(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
x0 := t.lower
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
parts[i] = t.f(x1) * (x1 - x0)
|
||||
a.add(t.f(x1) * (x1 - x0))
|
||||
x0 = x1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func rectMid(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
// there's a tiny gloss in the x1-x0 trick here. the correct way
|
||||
|
|
@ -77,80 +77,72 @@ func rectMid(t spec) float64 {
|
|||
// reuse the midpoint x's, knowing that they will average out just
|
||||
// as well. we just need one extra point, so we use lower-.5.
|
||||
x0 := t.lower - .5*r/nf
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + (float64(i)+.5)*r/nf
|
||||
parts[i] = t.f(x1) * (x1 - x0)
|
||||
a.add(t.f(x1) * (x1 - x0))
|
||||
x0 = x1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func trap(t spec) float64 {
|
||||
parts := make([]float64, t.n)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
x0 := t.lower
|
||||
f0 := t.f(x0)
|
||||
for i := range parts {
|
||||
for i := 0; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
f1 := t.f(x1)
|
||||
parts[i] = (f0 + f1) * .5 * (x1 - x0)
|
||||
a.add((f0 + f1) * .5 * (x1 - x0))
|
||||
x0, f0 = x1, f1
|
||||
}
|
||||
return sum(parts)
|
||||
return a.total()
|
||||
}
|
||||
|
||||
func simpson(t spec) float64 {
|
||||
parts := make([]float64, 2*t.n+1)
|
||||
var a adder
|
||||
r := t.upper - t.lower
|
||||
nf := float64(t.n)
|
||||
// similar to the rectangle midpoint logic explained above,
|
||||
// we play a little loose with the values used for dx and dx0.
|
||||
dx0 := r / nf
|
||||
parts[0] = t.f(t.lower) * dx0
|
||||
parts[1] = t.f(t.lower+dx0*.5) * dx0 * 4
|
||||
a.add(t.f(t.lower) * dx0)
|
||||
a.add(t.f(t.lower+dx0*.5) * dx0 * 4)
|
||||
x0 := t.lower + dx0
|
||||
for i := 1; i < t.n; i++ {
|
||||
x1 := t.lower + float64(i+1)*r/nf
|
||||
xmid := (x0 + x1) * .5
|
||||
dx := x1 - x0
|
||||
parts[2*i] = t.f(x0) * dx * 2
|
||||
parts[2*i+1] = t.f(xmid) * dx * 4
|
||||
a.add(t.f(x0) * dx * 2)
|
||||
a.add(t.f(xmid) * dx * 4)
|
||||
x0 = x1
|
||||
}
|
||||
parts[2*t.n] = t.f(t.upper) * dx0
|
||||
return sum(parts) / 6
|
||||
a.add(t.f(t.upper) * dx0)
|
||||
return a.total() / 6
|
||||
}
|
||||
|
||||
// sum a list of numbers avoiding loss of precision
|
||||
func sum(v []float64) float64 {
|
||||
if len(v) == 0 {
|
||||
return 0
|
||||
var a adder
|
||||
for _, e := range v {
|
||||
a.add(e)
|
||||
}
|
||||
var parts []float64
|
||||
for _, x := range v {
|
||||
var i int
|
||||
for _, p := range parts {
|
||||
sum := p + x
|
||||
var err float64
|
||||
if math.Abs(x) < math.Abs(p) {
|
||||
err = x - (sum - p)
|
||||
} else {
|
||||
err = p - (sum - x)
|
||||
}
|
||||
if err != 0 {
|
||||
parts[i] = err
|
||||
i++
|
||||
}
|
||||
x = sum
|
||||
}
|
||||
parts = append(parts[:i], x)
|
||||
}
|
||||
var sum float64
|
||||
for _, x := range parts {
|
||||
sum += x
|
||||
}
|
||||
return sum
|
||||
return a.total()
|
||||
}
|
||||
|
||||
type adder struct {
|
||||
sum, e float64
|
||||
}
|
||||
|
||||
func (a *adder) total() float64 {
|
||||
return a.sum + a.e
|
||||
}
|
||||
|
||||
func (a *adder) add(x float64) {
|
||||
sum := a.sum + x
|
||||
e := sum - a.sum
|
||||
a.e += a.sum - (sum - e) + (x - e)
|
||||
a.sum = sum
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue