mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 07:06:54 +08:00
94 lines
1.8 KiB
Go
94 lines
1.8 KiB
Go
// Copyright ©2019 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build !amd64 || noasm || gccgo || safe
|
|
// +build !amd64 noasm gccgo safe
|
|
|
|
package f64
|
|
|
|
import "math"
|
|
|
|
// L2NormUnitary returns the L2-norm of x.
|
|
func L2NormUnitary(x []float64) (norm float64) {
|
|
var scale float64
|
|
sumSquares := 1.0
|
|
for _, v := range x {
|
|
if v == 0 {
|
|
continue
|
|
}
|
|
absxi := math.Abs(v)
|
|
if math.IsNaN(absxi) {
|
|
return math.NaN()
|
|
}
|
|
if scale < absxi {
|
|
s := scale / absxi
|
|
sumSquares = 1 + sumSquares*s*s
|
|
scale = absxi
|
|
} else {
|
|
s := absxi / scale
|
|
sumSquares += s * s
|
|
}
|
|
}
|
|
if math.IsInf(scale, 1) {
|
|
return math.Inf(1)
|
|
}
|
|
return scale * math.Sqrt(sumSquares)
|
|
}
|
|
|
|
// L2NormInc returns the L2-norm of x.
|
|
func L2NormInc(x []float64, n, incX uintptr) (norm float64) {
|
|
var scale float64
|
|
sumSquares := 1.0
|
|
for ix := uintptr(0); ix < n*incX; ix += incX {
|
|
val := x[ix]
|
|
if val == 0 {
|
|
continue
|
|
}
|
|
absxi := math.Abs(val)
|
|
if math.IsNaN(absxi) {
|
|
return math.NaN()
|
|
}
|
|
if scale < absxi {
|
|
s := scale / absxi
|
|
sumSquares = 1 + sumSquares*s*s
|
|
scale = absxi
|
|
} else {
|
|
s := absxi / scale
|
|
sumSquares += s * s
|
|
}
|
|
}
|
|
if math.IsInf(scale, 1) {
|
|
return math.Inf(1)
|
|
}
|
|
return scale * math.Sqrt(sumSquares)
|
|
}
|
|
|
|
// L2DistanceUnitary returns the L2-norm of x-y.
|
|
func L2DistanceUnitary(x, y []float64) (norm float64) {
|
|
var scale float64
|
|
sumSquares := 1.0
|
|
for i, v := range x {
|
|
v -= y[i]
|
|
if v == 0 {
|
|
continue
|
|
}
|
|
absxi := math.Abs(v)
|
|
if math.IsNaN(absxi) {
|
|
return math.NaN()
|
|
}
|
|
if scale < absxi {
|
|
s := scale / absxi
|
|
sumSquares = 1 + sumSquares*s*s
|
|
scale = absxi
|
|
} else {
|
|
s := absxi / scale
|
|
sumSquares += s * s
|
|
}
|
|
}
|
|
if math.IsInf(scale, 1) {
|
|
return math.Inf(1)
|
|
}
|
|
return scale * math.Sqrt(sumSquares)
|
|
}
|