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