github.com/gopherd/gonum@v0.0.4/internal/asm/f32/l2norm.go (about)

     1  // Copyright ©2019 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package f32
     6  
     7  import "github.com/gopherd/gonum/internal/math32"
     8  
     9  // L2NormUnitary is the level 2 norm of x.
    10  func L2NormUnitary(x []float32) (sum float32) {
    11  	var scale float32
    12  	var sumSquares float32 = 1
    13  	for _, v := range x {
    14  		if v == 0 {
    15  			continue
    16  		}
    17  		absxi := math32.Abs(v)
    18  		if math32.IsNaN(absxi) {
    19  			return math32.NaN()
    20  		}
    21  		if scale < absxi {
    22  			s := scale / absxi
    23  			sumSquares = 1 + sumSquares*s*s
    24  			scale = absxi
    25  		} else {
    26  			s := absxi / scale
    27  			sumSquares += s * s
    28  		}
    29  	}
    30  	if math32.IsInf(scale, 1) {
    31  		return math32.Inf(1)
    32  	}
    33  	return scale * math32.Sqrt(sumSquares)
    34  }
    35  
    36  // L2NormInc is the level 2 norm of x.
    37  func L2NormInc(x []float32, n, incX uintptr) (sum float32) {
    38  	var scale float32
    39  	var sumSquares float32 = 1
    40  	for ix := uintptr(0); ix < n*incX; ix += incX {
    41  		val := x[ix]
    42  		if val == 0 {
    43  			continue
    44  		}
    45  		absxi := math32.Abs(val)
    46  		if math32.IsNaN(absxi) {
    47  			return math32.NaN()
    48  		}
    49  		if scale < absxi {
    50  			s := scale / absxi
    51  			sumSquares = 1 + sumSquares*s*s
    52  			scale = absxi
    53  		} else {
    54  			s := absxi / scale
    55  			sumSquares += s * s
    56  		}
    57  	}
    58  	if math32.IsInf(scale, 1) {
    59  		return math32.Inf(1)
    60  	}
    61  	return scale * math32.Sqrt(sumSquares)
    62  }
    63  
    64  // L2DistanceUnitary is the L2 norm of x-y.
    65  func L2DistanceUnitary(x, y []float32) (sum float32) {
    66  	var scale float32
    67  	var sumSquares float32 = 1
    68  	for i, v := range x {
    69  		v -= y[i]
    70  		if v == 0 {
    71  			continue
    72  		}
    73  		absxi := math32.Abs(v)
    74  		if math32.IsNaN(absxi) {
    75  			return math32.NaN()
    76  		}
    77  		if scale < absxi {
    78  			s := scale / absxi
    79  			sumSquares = 1 + sumSquares*s*s
    80  			scale = absxi
    81  		} else {
    82  			s := absxi / scale
    83  			sumSquares += s * s
    84  		}
    85  	}
    86  	if math32.IsInf(scale, 1) {
    87  		return math32.Inf(1)
    88  	}
    89  	return scale * math32.Sqrt(sumSquares)
    90  }