github.com/gopherd/gonum@v0.0.4/internal/asm/f64/l2norm_noasm.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  //go:build !amd64 || noasm || gccgo || safe
     6  // +build !amd64 noasm gccgo safe
     7  
     8  package f64
     9  
    10  import "math"
    11  
    12  // L2NormUnitary returns the L2-norm of x.
    13  func L2NormUnitary(x []float64) (norm float64) {
    14  	var scale float64
    15  	sumSquares := 1.0
    16  	for _, v := range x {
    17  		if v == 0 {
    18  			continue
    19  		}
    20  		absxi := math.Abs(v)
    21  		if math.IsNaN(absxi) {
    22  			return math.NaN()
    23  		}
    24  		if scale < absxi {
    25  			s := scale / absxi
    26  			sumSquares = 1 + sumSquares*s*s
    27  			scale = absxi
    28  		} else {
    29  			s := absxi / scale
    30  			sumSquares += s * s
    31  		}
    32  	}
    33  	if math.IsInf(scale, 1) {
    34  		return math.Inf(1)
    35  	}
    36  	return scale * math.Sqrt(sumSquares)
    37  }
    38  
    39  // L2NormInc returns the L2-norm of x.
    40  func L2NormInc(x []float64, n, incX uintptr) (norm float64) {
    41  	var scale float64
    42  	sumSquares := 1.0
    43  	for ix := uintptr(0); ix < n*incX; ix += incX {
    44  		val := x[ix]
    45  		if val == 0 {
    46  			continue
    47  		}
    48  		absxi := math.Abs(val)
    49  		if math.IsNaN(absxi) {
    50  			return math.NaN()
    51  		}
    52  		if scale < absxi {
    53  			s := scale / absxi
    54  			sumSquares = 1 + sumSquares*s*s
    55  			scale = absxi
    56  		} else {
    57  			s := absxi / scale
    58  			sumSquares += s * s
    59  		}
    60  	}
    61  	if math.IsInf(scale, 1) {
    62  		return math.Inf(1)
    63  	}
    64  	return scale * math.Sqrt(sumSquares)
    65  }
    66  
    67  // L2DistanceUnitary returns the L2-norm of x-y.
    68  func L2DistanceUnitary(x, y []float64) (norm float64) {
    69  	var scale float64
    70  	sumSquares := 1.0
    71  	for i, v := range x {
    72  		v -= y[i]
    73  		if v == 0 {
    74  			continue
    75  		}
    76  		absxi := math.Abs(v)
    77  		if math.IsNaN(absxi) {
    78  			return math.NaN()
    79  		}
    80  		if scale < absxi {
    81  			s := scale / absxi
    82  			sumSquares = 1 + sumSquares*s*s
    83  			scale = absxi
    84  		} else {
    85  			s := absxi / scale
    86  			sumSquares += s * s
    87  		}
    88  	}
    89  	if math.IsInf(scale, 1) {
    90  		return math.Inf(1)
    91  	}
    92  	return scale * math.Sqrt(sumSquares)
    93  }