Go version
go1.25.0
Output of go env
in your module/workspace:
-
What did you do?
See https://github.com/gonum/gonum/issues/2053
What did you see happen?
Test failed.
What did you expect to see?
Test passed.
I'm not sure if this is a bug, but I revert 43b7e670401401b2e7536b4931df8b29a25994c7 and test passed.
Comment From: wdvxdr1123
cc @jake-ciolek @randall77
Comment From: cuonglm
It seems to me that the failure tests because gonum is testing equality bit by bit.
For normal floating point arithmetic x*y+z
, the result of x*y
is rounded before adding to z
. While FMA231(z x y)
will only do the rounding with the final result.
Maybe gonum should change the test to allow small tolerance?
Comment From: randall77
This is allowed by the spec. gonum must either disable FMA at appropriate locations using float64
casts, or tolerate some variance.
It looks like gonum already uses different golden result files for arm64, which has had FMA for a while.
As far as disabling FMA using float64
casts, this set seems to work (not that I am recommending it as a solution):
diff --git a/blas/gonum/level2float64.go b/blas/gonum/level2float64.go
index 19b9c7e1..234d7ed5 100644
--- a/blas/gonum/level2float64.go
+++ b/blas/gonum/level2float64.go
@@ -753,7 +753,7 @@ func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda
jy := ky + (i+1)*incY
atmp := a[i*lda+i+1 : i*lda+n]
for _, v := range atmp {
- sum += x[jx] * v
+ sum += float64(x[jx] * v)
y[jy] += xv * v
jx += incX
jy += incY
@@ -1765,7 +1765,7 @@ func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, inc
yi := y[iy]
atmp := a[i*lda:]
for j := i; j < n; j++ {
- atmp[j] += alpha * (xi*y[jy] + x[jx]*yi)
+ atmp[j] += alpha * (float64(xi*y[jy]) + float64(x[jx]*yi))
jx += incX
jy += incY
}
diff --git a/graph/layout/eades.go b/graph/layout/eades.go
index bc14a51e..ce31593a 100644
--- a/graph/layout/eades.go
+++ b/graph/layout/eades.go
@@ -144,6 +144,7 @@ func (u *EadesR2) Update(g graph.Graph, layout LayoutR2) bool {
if math.Hypot(f.X, f.Y) > 1e-12 {
updated = true
}
+ f.X, f.Y = float64(f.X), float64(f.Y)
u.forces[xidx] = r2.Add(u.forces[xidx], f)
u.forces[yidx] = r2.Sub(u.forces[yidx], f)
}
diff --git a/lapack/gonum/dlartg.go b/lapack/gonum/dlartg.go
index 93416c6f..e38f31c3 100644
--- a/lapack/gonum/dlartg.go
+++ b/lapack/gonum/dlartg.go
@@ -52,7 +52,7 @@ func (impl Implementation) Dlartg(f, g float64) (cs, sn, r float64) {
f1 := math.Abs(f)
if rtmin < f1 && f1 < rtmax && rtmin < g1 && g1 < rtmax {
- d := math.Sqrt(f*f + g*g)
+ d := math.Sqrt(float64(f*f) + float64(g*g))
cs = f1 / d
r = math.Copysign(d, f)
sn = g / r
diff --git a/lapack/gonum/dsteqr.go b/lapack/gonum/dsteqr.go
index d6c7861a..ffecf58f 100644
--- a/lapack/gonum/dsteqr.go
+++ b/lapack/gonum/dsteqr.go
@@ -243,8 +243,8 @@ func (impl Implementation) Dsteqr(compz lapack.EVComp, n int, d, e, z []float64,
e[i+1] = r
}
g = d[i+1] - p
- r = (d[i]-g)*s + 2*c*b
- p = s * r
+ r = float64((d[i]-g)*s) + float64(2*c*b)
+ p = float64(s * r)
d[i+1] = g + p
g = c*r - b
@@ -329,7 +329,7 @@ func (impl Implementation) Dsteqr(compz lapack.EVComp, n int, d, e, z []float64,
}
g = d[i] - p
r = (d[i+1]-g)*s + 2*c*b
- p = s * r
+ p = float64(s * r)
d[i] = g + p
g = c*r - b
diff --git a/mat/dense_arithmetic.go b/mat/dense_arithmetic.go
index 259ee13d..97898069 100644
--- a/mat/dense_arithmetic.go
+++ b/mat/dense_arithmetic.go
@@ -450,7 +450,7 @@ func (m *Dense) Mul(a, b Matrix) {
for c := 0; c < bc; c++ {
var v float64
for i, e := range row {
- v += e * b.At(i, c)
+ v += float64(e * b.At(i, c))
}
m.mat.Data[r*m.mat.Stride+c] = v
}