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 }