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