gonum.org/v1/gonum@v0.14.0/blas/gonum/level1cmplx128.go (about)

     1  // Copyright ©2017 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 gonum
     6  
     7  import (
     8  	"math"
     9  
    10  	"gonum.org/v1/gonum/blas"
    11  	"gonum.org/v1/gonum/internal/asm/c128"
    12  )
    13  
    14  var _ blas.Complex128Level1 = Implementation{}
    15  
    16  // Dzasum returns the sum of the absolute values of the elements of x
    17  //
    18  //	\sum_i |Re(x[i])| + |Im(x[i])|
    19  //
    20  // Dzasum returns 0 if incX is negative.
    21  func (Implementation) Dzasum(n int, x []complex128, incX int) float64 {
    22  	if n < 0 {
    23  		panic(nLT0)
    24  	}
    25  	if incX < 1 {
    26  		if incX == 0 {
    27  			panic(zeroIncX)
    28  		}
    29  		return 0
    30  	}
    31  	var sum float64
    32  	if incX == 1 {
    33  		if len(x) < n {
    34  			panic(shortX)
    35  		}
    36  		for _, v := range x[:n] {
    37  			sum += dcabs1(v)
    38  		}
    39  		return sum
    40  	}
    41  	if (n-1)*incX >= len(x) {
    42  		panic(shortX)
    43  	}
    44  	for i := 0; i < n; i++ {
    45  		v := x[i*incX]
    46  		sum += dcabs1(v)
    47  	}
    48  	return sum
    49  }
    50  
    51  // Dznrm2 computes the Euclidean norm of the complex vector x,
    52  //
    53  //	‖x‖_2 = sqrt(\sum_i x[i] * conj(x[i])).
    54  //
    55  // This function returns 0 if incX is negative.
    56  func (Implementation) Dznrm2(n int, x []complex128, incX int) float64 {
    57  	if incX < 1 {
    58  		if incX == 0 {
    59  			panic(zeroIncX)
    60  		}
    61  		return 0
    62  	}
    63  	if n < 1 {
    64  		if n == 0 {
    65  			return 0
    66  		}
    67  		panic(nLT0)
    68  	}
    69  	if (n-1)*incX >= len(x) {
    70  		panic(shortX)
    71  	}
    72  	var (
    73  		scale float64
    74  		ssq   float64 = 1
    75  	)
    76  	if incX == 1 {
    77  		for _, v := range x[:n] {
    78  			re, im := math.Abs(real(v)), math.Abs(imag(v))
    79  			if re != 0 {
    80  				if re > scale {
    81  					ssq = 1 + ssq*(scale/re)*(scale/re)
    82  					scale = re
    83  				} else {
    84  					ssq += (re / scale) * (re / scale)
    85  				}
    86  			}
    87  			if im != 0 {
    88  				if im > scale {
    89  					ssq = 1 + ssq*(scale/im)*(scale/im)
    90  					scale = im
    91  				} else {
    92  					ssq += (im / scale) * (im / scale)
    93  				}
    94  			}
    95  		}
    96  		if math.IsInf(scale, 1) {
    97  			return math.Inf(1)
    98  		}
    99  		return scale * math.Sqrt(ssq)
   100  	}
   101  	for ix := 0; ix < n*incX; ix += incX {
   102  		re, im := math.Abs(real(x[ix])), math.Abs(imag(x[ix]))
   103  		if re != 0 {
   104  			if re > scale {
   105  				ssq = 1 + ssq*(scale/re)*(scale/re)
   106  				scale = re
   107  			} else {
   108  				ssq += (re / scale) * (re / scale)
   109  			}
   110  		}
   111  		if im != 0 {
   112  			if im > scale {
   113  				ssq = 1 + ssq*(scale/im)*(scale/im)
   114  				scale = im
   115  			} else {
   116  				ssq += (im / scale) * (im / scale)
   117  			}
   118  		}
   119  	}
   120  	if math.IsInf(scale, 1) {
   121  		return math.Inf(1)
   122  	}
   123  	return scale * math.Sqrt(ssq)
   124  }
   125  
   126  // Izamax returns the index of the first element of x having largest |Re(·)|+|Im(·)|.
   127  // Izamax returns -1 if n is 0 or incX is negative.
   128  func (Implementation) Izamax(n int, x []complex128, incX int) int {
   129  	if incX < 1 {
   130  		if incX == 0 {
   131  			panic(zeroIncX)
   132  		}
   133  		// Return invalid index.
   134  		return -1
   135  	}
   136  	if n < 1 {
   137  		if n == 0 {
   138  			// Return invalid index.
   139  			return -1
   140  		}
   141  		panic(nLT0)
   142  	}
   143  	if len(x) <= (n-1)*incX {
   144  		panic(shortX)
   145  	}
   146  	idx := 0
   147  	max := dcabs1(x[0])
   148  	if incX == 1 {
   149  		for i, v := range x[1:n] {
   150  			absV := dcabs1(v)
   151  			if absV > max {
   152  				max = absV
   153  				idx = i + 1
   154  			}
   155  		}
   156  		return idx
   157  	}
   158  	ix := incX
   159  	for i := 1; i < n; i++ {
   160  		absV := dcabs1(x[ix])
   161  		if absV > max {
   162  			max = absV
   163  			idx = i
   164  		}
   165  		ix += incX
   166  	}
   167  	return idx
   168  }
   169  
   170  // Zaxpy adds alpha times x to y:
   171  //
   172  //	y[i] += alpha * x[i] for all i
   173  func (Implementation) Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) {
   174  	if incX == 0 {
   175  		panic(zeroIncX)
   176  	}
   177  	if incY == 0 {
   178  		panic(zeroIncY)
   179  	}
   180  	if n < 1 {
   181  		if n == 0 {
   182  			return
   183  		}
   184  		panic(nLT0)
   185  	}
   186  	if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
   187  		panic(shortX)
   188  	}
   189  	if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
   190  		panic(shortY)
   191  	}
   192  	if alpha == 0 {
   193  		return
   194  	}
   195  	if incX == 1 && incY == 1 {
   196  		c128.AxpyUnitary(alpha, x[:n], y[:n])
   197  		return
   198  	}
   199  	var ix, iy int
   200  	if incX < 0 {
   201  		ix = (1 - n) * incX
   202  	}
   203  	if incY < 0 {
   204  		iy = (1 - n) * incY
   205  	}
   206  	c128.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))
   207  }
   208  
   209  // Zcopy copies the vector x to vector y.
   210  func (Implementation) Zcopy(n int, x []complex128, incX int, y []complex128, incY int) {
   211  	if incX == 0 {
   212  		panic(zeroIncX)
   213  	}
   214  	if incY == 0 {
   215  		panic(zeroIncY)
   216  	}
   217  	if n < 1 {
   218  		if n == 0 {
   219  			return
   220  		}
   221  		panic(nLT0)
   222  	}
   223  	if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
   224  		panic(shortX)
   225  	}
   226  	if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
   227  		panic(shortY)
   228  	}
   229  	if incX == 1 && incY == 1 {
   230  		copy(y[:n], x[:n])
   231  		return
   232  	}
   233  	var ix, iy int
   234  	if incX < 0 {
   235  		ix = (-n + 1) * incX
   236  	}
   237  	if incY < 0 {
   238  		iy = (-n + 1) * incY
   239  	}
   240  	for i := 0; i < n; i++ {
   241  		y[iy] = x[ix]
   242  		ix += incX
   243  		iy += incY
   244  	}
   245  }
   246  
   247  // Zdotc computes the dot product
   248  //
   249  //	xᴴ · y
   250  //
   251  // of two complex vectors x and y.
   252  func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, incY int) complex128 {
   253  	if incX == 0 {
   254  		panic(zeroIncX)
   255  	}
   256  	if incY == 0 {
   257  		panic(zeroIncY)
   258  	}
   259  	if n <= 0 {
   260  		if n == 0 {
   261  			return 0
   262  		}
   263  		panic(nLT0)
   264  	}
   265  	if incX == 1 && incY == 1 {
   266  		if len(x) < n {
   267  			panic(shortX)
   268  		}
   269  		if len(y) < n {
   270  			panic(shortY)
   271  		}
   272  		return c128.DotcUnitary(x[:n], y[:n])
   273  	}
   274  	var ix, iy int
   275  	if incX < 0 {
   276  		ix = (-n + 1) * incX
   277  	}
   278  	if incY < 0 {
   279  		iy = (-n + 1) * incY
   280  	}
   281  	if ix >= len(x) || (n-1)*incX >= len(x) {
   282  		panic(shortX)
   283  	}
   284  	if iy >= len(y) || (n-1)*incY >= len(y) {
   285  		panic(shortY)
   286  	}
   287  	return c128.DotcInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))
   288  }
   289  
   290  // Zdotu computes the dot product
   291  //
   292  //	xᵀ · y
   293  //
   294  // of two complex vectors x and y.
   295  func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, incY int) complex128 {
   296  	if incX == 0 {
   297  		panic(zeroIncX)
   298  	}
   299  	if incY == 0 {
   300  		panic(zeroIncY)
   301  	}
   302  	if n <= 0 {
   303  		if n == 0 {
   304  			return 0
   305  		}
   306  		panic(nLT0)
   307  	}
   308  	if incX == 1 && incY == 1 {
   309  		if len(x) < n {
   310  			panic(shortX)
   311  		}
   312  		if len(y) < n {
   313  			panic(shortY)
   314  		}
   315  		return c128.DotuUnitary(x[:n], y[:n])
   316  	}
   317  	var ix, iy int
   318  	if incX < 0 {
   319  		ix = (-n + 1) * incX
   320  	}
   321  	if incY < 0 {
   322  		iy = (-n + 1) * incY
   323  	}
   324  	if ix >= len(x) || (n-1)*incX >= len(x) {
   325  		panic(shortX)
   326  	}
   327  	if iy >= len(y) || (n-1)*incY >= len(y) {
   328  		panic(shortY)
   329  	}
   330  	return c128.DotuInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))
   331  }
   332  
   333  // Zdscal scales the vector x by a real scalar alpha.
   334  // Zdscal has no effect if incX < 0.
   335  func (Implementation) Zdscal(n int, alpha float64, x []complex128, incX int) {
   336  	if incX < 1 {
   337  		if incX == 0 {
   338  			panic(zeroIncX)
   339  		}
   340  		return
   341  	}
   342  	if (n-1)*incX >= len(x) {
   343  		panic(shortX)
   344  	}
   345  	if n < 1 {
   346  		if n == 0 {
   347  			return
   348  		}
   349  		panic(nLT0)
   350  	}
   351  	if alpha == 0 {
   352  		if incX == 1 {
   353  			x = x[:n]
   354  			for i := range x {
   355  				x[i] = 0
   356  			}
   357  			return
   358  		}
   359  		for ix := 0; ix < n*incX; ix += incX {
   360  			x[ix] = 0
   361  		}
   362  		return
   363  	}
   364  	if incX == 1 {
   365  		x = x[:n]
   366  		for i, v := range x {
   367  			x[i] = complex(alpha*real(v), alpha*imag(v))
   368  		}
   369  		return
   370  	}
   371  	for ix := 0; ix < n*incX; ix += incX {
   372  		v := x[ix]
   373  		x[ix] = complex(alpha*real(v), alpha*imag(v))
   374  	}
   375  }
   376  
   377  // Zscal scales the vector x by a complex scalar alpha.
   378  // Zscal has no effect if incX < 0.
   379  func (Implementation) Zscal(n int, alpha complex128, x []complex128, incX int) {
   380  	if incX < 1 {
   381  		if incX == 0 {
   382  			panic(zeroIncX)
   383  		}
   384  		return
   385  	}
   386  	if (n-1)*incX >= len(x) {
   387  		panic(shortX)
   388  	}
   389  	if n < 1 {
   390  		if n == 0 {
   391  			return
   392  		}
   393  		panic(nLT0)
   394  	}
   395  	if alpha == 0 {
   396  		if incX == 1 {
   397  			x = x[:n]
   398  			for i := range x {
   399  				x[i] = 0
   400  			}
   401  			return
   402  		}
   403  		for ix := 0; ix < n*incX; ix += incX {
   404  			x[ix] = 0
   405  		}
   406  		return
   407  	}
   408  	if incX == 1 {
   409  		c128.ScalUnitary(alpha, x[:n])
   410  		return
   411  	}
   412  	c128.ScalInc(alpha, x, uintptr(n), uintptr(incX))
   413  }
   414  
   415  // Zswap exchanges the elements of two complex vectors x and y.
   416  func (Implementation) Zswap(n int, x []complex128, incX int, y []complex128, incY int) {
   417  	if incX == 0 {
   418  		panic(zeroIncX)
   419  	}
   420  	if incY == 0 {
   421  		panic(zeroIncY)
   422  	}
   423  	if n < 1 {
   424  		if n == 0 {
   425  			return
   426  		}
   427  		panic(nLT0)
   428  	}
   429  	if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
   430  		panic(shortX)
   431  	}
   432  	if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
   433  		panic(shortY)
   434  	}
   435  	if incX == 1 && incY == 1 {
   436  		x = x[:n]
   437  		for i, v := range x {
   438  			x[i], y[i] = y[i], v
   439  		}
   440  		return
   441  	}
   442  	var ix, iy int
   443  	if incX < 0 {
   444  		ix = (-n + 1) * incX
   445  	}
   446  	if incY < 0 {
   447  		iy = (-n + 1) * incY
   448  	}
   449  	for i := 0; i < n; i++ {
   450  		x[ix], y[iy] = y[iy], x[ix]
   451  		ix += incX
   452  		iy += incY
   453  	}
   454  }