1 // Copyright ©2015 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.
10 "gonum.org/v1/gonum/blas"
11 "gonum.org/v1/gonum/internal/asm/f64"
14 var _ blas.Float64Level1 = Implementation{}
16 // Dnrm2 computes the Euclidean norm of a vector,
17 // sqrt(\sum_i x[i] * x[i]).
18 // This function returns 0 if incX is negative.
19 func (Implementation) Dnrm2(n int, x []float64, incX int) float64 {
26 if incX > 0 && (n-1)*incX >= len(x) {
42 sumSquares float64 = 1
51 if math.IsNaN(absxi) {
55 sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi)
58 sumSquares = sumSquares + (absxi/scale)*(absxi/scale)
61 if math.IsInf(scale, 1) {
64 return scale * math.Sqrt(sumSquares)
66 for ix := 0; ix < n*incX; ix += incX {
71 absxi := math.Abs(val)
72 if math.IsNaN(absxi) {
76 sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi)
79 sumSquares = sumSquares + (absxi/scale)*(absxi/scale)
82 if math.IsInf(scale, 1) {
85 return scale * math.Sqrt(sumSquares)
88 // Dasum computes the sum of the absolute values of the elements of x.
90 // Dasum returns 0 if incX is negative.
91 func (Implementation) Dasum(n int, x []float64, incX int) float64 {
102 if incX > 0 && (n-1)*incX >= len(x) {
107 for _, v := range x {
112 for i := 0; i < n; i++ {
113 sum += math.Abs(x[i*incX])
118 // Idamax returns the index of an element of x with the largest absolute value.
119 // If there are multiple such indices the earliest is returned.
120 // Idamax returns -1 if n == 0.
121 func (Implementation) Idamax(n int, x []float64, incX int) int {
128 if incX > 0 && (n-1)*incX >= len(x) {
136 return -1 // Netlib returns invalid index when n == 0
143 max := math.Abs(x[0])
145 for i, v := range x[:n] {
155 for i := 1; i < n; i++ {
167 // Dswap exchanges the elements of two vectors.
168 // x[i], y[i] = y[i], x[i] for all i
169 func (Implementation) Dswap(n int, x []float64, incX int, y []float64, incY int) {
182 if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
185 if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
188 if incX == 1 && incY == 1 {
190 for i, v := range x {
202 for i := 0; i < n; i++ {
203 x[ix], y[iy] = y[iy], x[ix]
209 // Dcopy copies the elements of x into the elements of y.
210 // y[i] = x[i] for all i
211 func (Implementation) Dcopy(n int, x []float64, incX int, y []float64, incY int) {
224 if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
227 if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
230 if incX == 1 && incY == 1 {
241 for i := 0; i < n; i++ {
248 // Daxpy adds alpha times x to y
249 // y[i] += alpha * x[i] for all i
250 func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) {
263 if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
266 if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
272 if incX == 1 && incY == 1 {
273 f64.AxpyUnitary(alpha, x[:n], y[:n])
283 f64.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))
286 // Drotg computes the plane rotation
288 // | c s | | a | | r |
289 // | -s c | * | b | = | 0 |
293 // c = a/r, the cosine of the plane rotation
294 // s = b/r, the sine of the plane rotation
296 // NOTE: There is a discrepancy between the refence implementation and the BLAS
297 // technical manual regarding the sign for r when a or b are zero.
298 // Drotg agrees with the definition in the manual and other
299 // common BLAS implementations.
300 func (Implementation) Drotg(a, b float64) (c, s, r, z float64) {
301 if b == 0 && a == 0 {
309 r = math.Copysign(r, a)
311 r = math.Copysign(r, b)
317 } else if c != 0 { // r == 0 case handled above
325 // Drotmg computes the modified Givens rotation. See
326 // http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html
328 func (Implementation) Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, rd2, rx1 float64) {
329 var p1, p2, q1, q2, u float64
334 rgamsq = 5.9604645e-8
338 p.Flag = blas.Rescaling
344 p.Flag = blas.Identity
354 absQ1 := math.Abs(q1)
355 absQ2 := math.Abs(q2)
357 if absQ1 < absQ2 && q2 < 0 {
358 p.Flag = blas.Rescaling
363 p.Flag = blas.Diagonal
366 u = 1 + p.H[0]*p.H[3]
367 rd1, rd2 = d2/u, d1/u
372 // Now we know that d1 != 0, and d2 != 0. If d2 == 0, it would be caught
373 // when p2 == 0, and if d1 == 0, then it is caught above
378 u = 1 - p.H[2]*p.H[1]
382 p.Flag = blas.OffDiagonal
383 // u must be greater than zero because |q1| > |q2|, so check from netlib
385 // This is left in for ease of comparison with complex routines
392 p.Flag = blas.Diagonal
395 u = 1 + p.H[0]*p.H[3]
401 for rd1 <= rgamsq || rd1 >= gamsq {
402 if p.Flag == blas.OffDiagonal {
405 p.Flag = blas.Rescaling
406 } else if p.Flag == blas.Diagonal {
409 p.Flag = blas.Rescaling
424 for math.Abs(rd2) <= rgamsq || math.Abs(rd2) >= gamsq {
425 if p.Flag == blas.OffDiagonal {
428 p.Flag = blas.Rescaling
429 } else if p.Flag == blas.Diagonal {
432 p.Flag = blas.Rescaling
434 if math.Abs(rd2) <= rgamsq {
447 // Drot applies a plane transformation.
448 // x[i] = c * x[i] + s * y[i]
449 // y[i] = c * y[i] - s * x[i]
450 func (Implementation) Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) {
463 if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
466 if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
469 if incX == 1 && incY == 1 {
471 for i, vx := range x {
473 x[i], y[i] = c*vx+s*vy, c*vy-s*vx
484 for i := 0; i < n; i++ {
487 x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx
493 // Drotm applies the modified Givens rotation to the 2×n matrix.
494 func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) {
507 if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) {
510 if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) {
514 var h11, h12, h21, h22 float64
524 case blas.OffDiagonal:
541 if incX == 1 && incY == 1 {
543 for i, vx := range x {
545 x[i], y[i] = vx*h11+vy*h12, vx*h21+vy*h22
549 for i := 0; i < n; i++ {
552 x[ix], y[iy] = vx*h11+vy*h12, vx*h21+vy*h22
558 // Dscal scales x by alpha.
560 // Dscal has no effect if incX < 0.
561 func (Implementation) Dscal(n int, alpha float64, x []float64, incX int) {
568 if (n-1)*incX >= len(x) {
585 for ix := 0; ix < n*incX; ix += incX {
591 f64.ScalUnitary(alpha, x[:n])
594 f64.ScalInc(alpha, x, uintptr(n), uintptr(incX))