github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/native/dlasq6.go (about) 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. 4 5 package native 6 7 import "math" 8 9 // Dlasq6 computes one dqd transform in ping-pong form with protection against 10 // overflow and underflow. z has length at least 4*(n0+1) and holds the qd array. 11 // i0 is the zero-based first index. 12 // n0 is the zero-based last index. 13 // 14 // Dlasq6 is an internal routine. It is exported for testing purposes. 15 func (impl Implementation) Dlasq6(i0, n0 int, z []float64, pp int) (dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { 16 if len(z) < 4*(n0+1) { 17 panic(badZ) 18 } 19 if n0-i0-1 <= 0 { 20 return dmin, dmin1, dmin2, dn, dnm1, dnm2 21 } 22 safmin := dlamchS 23 j4 := 4*(i0+1) + pp - 4 // -4 rather than -3 for zero indexing 24 emin := z[j4+4] 25 d := z[j4] 26 dmin = d 27 if pp == 0 { 28 for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { 29 j4 := j4loop - 1 // Translate back to zero-indexed. 30 z[j4-2] = d + z[j4-1] 31 if z[j4-2] == 0 { 32 z[j4] = 0 33 d = z[j4+1] 34 dmin = d 35 emin = 0 36 } else if safmin*z[j4+1] < z[j4-2] && safmin*z[j4-2] < z[j4+1] { 37 tmp := z[j4+1] / z[j4-2] 38 z[j4] = z[j4-1] * tmp 39 d *= tmp 40 } else { 41 z[j4] = z[j4+1] * (z[j4-1] / z[j4-2]) 42 d = z[j4+1] * (d / z[j4-2]) 43 } 44 dmin = math.Min(dmin, d) 45 emin = math.Min(emin, z[j4]) 46 } 47 } else { 48 for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { 49 j4 := j4loop - 1 50 z[j4-3] = d + z[j4] 51 if z[j4-3] == 0 { 52 z[j4-1] = 0 53 d = z[j4+2] 54 dmin = d 55 emin = 0 56 } else if safmin*z[j4+2] < z[j4-3] && safmin*z[j4-3] < z[j4+2] { 57 tmp := z[j4+2] / z[j4-3] 58 z[j4-1] = z[j4] * tmp 59 d *= tmp 60 } else { 61 z[j4-1] = z[j4+2] * (z[j4] / z[j4-3]) 62 d = z[j4+2] * (d / z[j4-3]) 63 } 64 dmin = math.Min(dmin, d) 65 emin = math.Min(emin, z[j4-1]) 66 } 67 } 68 // Unroll last two steps. 69 dnm2 = d 70 dmin2 = dmin 71 j4 = 4*(n0-1) - pp - 1 72 j4p2 := j4 + 2*pp - 1 73 z[j4-2] = dnm2 + z[j4p2] 74 if z[j4-2] == 0 { 75 z[j4] = 0 76 dnm1 = z[j4p2+2] 77 dmin = dnm1 78 emin = 0 79 } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { 80 tmp := z[j4p2+2] / z[j4-2] 81 z[j4] = z[j4p2] * tmp 82 dnm1 = dnm2 * tmp 83 } else { 84 z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) 85 dnm1 = z[j4p2+2] * (dnm2 / z[j4-2]) 86 } 87 dmin = math.Min(dmin, dnm1) 88 dmin1 = dmin 89 j4 += 4 90 j4p2 = j4 + 2*pp - 1 91 z[j4-2] = dnm1 + z[j4p2] 92 if z[j4-2] == 0 { 93 z[j4] = 0 94 dn = z[j4p2+2] 95 dmin = dn 96 emin = 0 97 } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { 98 tmp := z[j4p2+2] / z[j4-2] 99 z[j4] = z[j4p2] * tmp 100 dn = dnm1 * tmp 101 } else { 102 z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) 103 dn = z[j4p2+2] * (dnm1 / z[j4-2]) 104 } 105 dmin = math.Min(dmin, dn) 106 z[j4+2] = dn 107 z[4*(n0+1)-pp-1] = emin 108 return dmin, dmin1, dmin2, dn, dnm1, dnm2 109 }