Annotation of rpl/lapack/blas/zrotg.f90, revision 1.1
1.1 ! bertrand 1: !> \brief \b ZROTG generates a Givens rotation with real cosine and complex sine.
! 2: !
! 3: ! =========== DOCUMENTATION ===========
! 4: !
! 5: ! Online html documentation available at
! 6: ! http://www.netlib.org/lapack/explore-html/
! 7: !
! 8: ! Definition:
! 9: ! ===========
! 10: !
! 11: ! ZROTG constructs a plane rotation
! 12: ! [ c s ] [ a ] = [ r ]
! 13: ! [ -conjg(s) c ] [ b ] [ 0 ]
! 14: ! where c is real, s is complex, and c**2 + conjg(s)*s = 1.
! 15: !
! 16: !> \par Purpose:
! 17: ! =============
! 18: !>
! 19: !> \verbatim
! 20: !>
! 21: !> The computation uses the formulas
! 22: !> |x| = sqrt( Re(x)**2 + Im(x)**2 )
! 23: !> sgn(x) = x / |x| if x /= 0
! 24: !> = 1 if x = 0
! 25: !> c = |a| / sqrt(|a|**2 + |b|**2)
! 26: !> s = sgn(a) * conjg(b) / sqrt(|a|**2 + |b|**2)
! 27: !> r = sgn(a)*sqrt(|a|**2 + |b|**2)
! 28: !> When a and b are real and r /= 0, the formulas simplify to
! 29: !> c = a / r
! 30: !> s = b / r
! 31: !> the same as in DROTG when |a| > |b|. When |b| >= |a|, the
! 32: !> sign of c and s will be different from those computed by DROTG
! 33: !> if the signs of a and b are not the same.
! 34: !>
! 35: !> \endverbatim
! 36: !
! 37: ! Arguments:
! 38: ! ==========
! 39: !
! 40: !> \param[in,out] A
! 41: !> \verbatim
! 42: !> A is DOUBLE COMPLEX
! 43: !> On entry, the scalar a.
! 44: !> On exit, the scalar r.
! 45: !> \endverbatim
! 46: !>
! 47: !> \param[in] B
! 48: !> \verbatim
! 49: !> B is DOUBLE COMPLEX
! 50: !> The scalar b.
! 51: !> \endverbatim
! 52: !>
! 53: !> \param[out] C
! 54: !> \verbatim
! 55: !> C is DOUBLE PRECISION
! 56: !> The scalar c.
! 57: !> \endverbatim
! 58: !>
! 59: !> \param[out] S
! 60: !> \verbatim
! 61: !> S is DOUBLE COMPLEX
! 62: !> The scalar s.
! 63: !> \endverbatim
! 64: !
! 65: ! Authors:
! 66: ! ========
! 67: !
! 68: !> \author Weslley Pereira, University of Colorado Denver, USA
! 69: !
! 70: !> \date December 2021
! 71: !
! 72: !> \ingroup single_blas_level1
! 73: !
! 74: !> \par Further Details:
! 75: ! =====================
! 76: !>
! 77: !> \verbatim
! 78: !>
! 79: !> Based on the algorithm from
! 80: !>
! 81: !> Anderson E. (2017)
! 82: !> Algorithm 978: Safe Scaling in the Level 1 BLAS
! 83: !> ACM Trans Math Softw 44:1--28
! 84: !> https://doi.org/10.1145/3061665
! 85: !>
! 86: !> \endverbatim
! 87: !
! 88: ! =====================================================================
! 89: subroutine ZROTG( a, b, c, s )
! 90: integer, parameter :: wp = kind(1.d0)
! 91: !
! 92: ! -- Reference BLAS level1 routine --
! 93: ! -- Reference BLAS is a software package provided by Univ. of Tennessee, --
! 94: ! -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 95: !
! 96: ! .. Constants ..
! 97: real(wp), parameter :: zero = 0.0_wp
! 98: real(wp), parameter :: one = 1.0_wp
! 99: complex(wp), parameter :: czero = 0.0_wp
! 100: ! ..
! 101: ! .. Scaling constants ..
! 102: real(wp), parameter :: safmin = real(radix(0._wp),wp)**max( &
! 103: minexponent(0._wp)-1, &
! 104: 1-maxexponent(0._wp) &
! 105: )
! 106: real(wp), parameter :: safmax = real(radix(0._wp),wp)**max( &
! 107: 1-minexponent(0._wp), &
! 108: maxexponent(0._wp)-1 &
! 109: )
! 110: real(wp), parameter :: rtmin = sqrt( safmin )
! 111: ! ..
! 112: ! .. Scalar Arguments ..
! 113: real(wp) :: c
! 114: complex(wp) :: a, b, s
! 115: ! ..
! 116: ! .. Local Scalars ..
! 117: real(wp) :: d, f1, f2, g1, g2, h2, u, v, w, rtmax
! 118: complex(wp) :: f, fs, g, gs, r, t
! 119: ! ..
! 120: ! .. Intrinsic Functions ..
! 121: intrinsic :: abs, aimag, conjg, max, min, real, sqrt
! 122: ! ..
! 123: ! .. Statement Functions ..
! 124: real(wp) :: ABSSQ
! 125: ! ..
! 126: ! .. Statement Function definitions ..
! 127: ABSSQ( t ) = real( t )**2 + aimag( t )**2
! 128: ! ..
! 129: ! .. Executable Statements ..
! 130: !
! 131: f = a
! 132: g = b
! 133: if( g == czero ) then
! 134: c = one
! 135: s = czero
! 136: r = f
! 137: else if( f == czero ) then
! 138: c = zero
! 139: if( real(g) == zero ) then
! 140: r = abs(aimag(g))
! 141: s = conjg( g ) / r
! 142: elseif( aimag(g) == zero ) then
! 143: r = abs(real(g))
! 144: s = conjg( g ) / r
! 145: else
! 146: g1 = max( abs(real(g)), abs(aimag(g)) )
! 147: rtmax = sqrt( safmax/2 )
! 148: if( g1 > rtmin .and. g1 < rtmax ) then
! 149: !
! 150: ! Use unscaled algorithm
! 151: !
! 152: ! The following two lines can be replaced by `d = abs( g )`.
! 153: ! This algorithm do not use the intrinsic complex abs.
! 154: g2 = ABSSQ( g )
! 155: d = sqrt( g2 )
! 156: s = conjg( g ) / d
! 157: r = d
! 158: else
! 159: !
! 160: ! Use scaled algorithm
! 161: !
! 162: u = min( safmax, max( safmin, g1 ) )
! 163: gs = g / u
! 164: ! The following two lines can be replaced by `d = abs( gs )`.
! 165: ! This algorithm do not use the intrinsic complex abs.
! 166: g2 = ABSSQ( gs )
! 167: d = sqrt( g2 )
! 168: s = conjg( gs ) / d
! 169: r = d*u
! 170: end if
! 171: end if
! 172: else
! 173: f1 = max( abs(real(f)), abs(aimag(f)) )
! 174: g1 = max( abs(real(g)), abs(aimag(g)) )
! 175: rtmax = sqrt( safmax/4 )
! 176: if( f1 > rtmin .and. f1 < rtmax .and. &
! 177: g1 > rtmin .and. g1 < rtmax ) then
! 178: !
! 179: ! Use unscaled algorithm
! 180: !
! 181: f2 = ABSSQ( f )
! 182: g2 = ABSSQ( g )
! 183: h2 = f2 + g2
! 184: ! safmin <= f2 <= h2 <= safmax
! 185: if( f2 >= h2 * safmin ) then
! 186: ! safmin <= f2/h2 <= 1, and h2/f2 is finite
! 187: c = sqrt( f2 / h2 )
! 188: r = f / c
! 189: rtmax = rtmax * 2
! 190: if( f2 > rtmin .and. h2 < rtmax ) then
! 191: ! safmin <= sqrt( f2*h2 ) <= safmax
! 192: s = conjg( g ) * ( f / sqrt( f2*h2 ) )
! 193: else
! 194: s = conjg( g ) * ( r / h2 )
! 195: end if
! 196: else
! 197: ! f2/h2 <= safmin may be subnormal, and h2/f2 may overflow.
! 198: ! Moreover,
! 199: ! safmin <= f2*f2 * safmax < f2 * h2 < h2*h2 * safmin <= safmax,
! 200: ! sqrt(safmin) <= sqrt(f2 * h2) <= sqrt(safmax).
! 201: ! Also,
! 202: ! g2 >> f2, which means that h2 = g2.
! 203: d = sqrt( f2 * h2 )
! 204: c = f2 / d
! 205: if( c >= safmin ) then
! 206: r = f / c
! 207: else
! 208: ! f2 / sqrt(f2 * h2) < safmin, then
! 209: ! sqrt(safmin) <= f2 * sqrt(safmax) <= h2 / sqrt(f2 * h2) <= h2 * (safmin / f2) <= h2 <= safmax
! 210: r = f * ( h2 / d )
! 211: end if
! 212: s = conjg( g ) * ( f / d )
! 213: end if
! 214: else
! 215: !
! 216: ! Use scaled algorithm
! 217: !
! 218: u = min( safmax, max( safmin, f1, g1 ) )
! 219: gs = g / u
! 220: g2 = ABSSQ( gs )
! 221: if( f1 / u < rtmin ) then
! 222: !
! 223: ! f is not well-scaled when scaled by g1.
! 224: ! Use a different scaling for f.
! 225: !
! 226: v = min( safmax, max( safmin, f1 ) )
! 227: w = v / u
! 228: fs = f / v
! 229: f2 = ABSSQ( fs )
! 230: h2 = f2*w**2 + g2
! 231: else
! 232: !
! 233: ! Otherwise use the same scaling for f and g.
! 234: !
! 235: w = one
! 236: fs = f / u
! 237: f2 = ABSSQ( fs )
! 238: h2 = f2 + g2
! 239: end if
! 240: ! safmin <= f2 <= h2 <= safmax
! 241: if( f2 >= h2 * safmin ) then
! 242: ! safmin <= f2/h2 <= 1, and h2/f2 is finite
! 243: c = sqrt( f2 / h2 )
! 244: r = fs / c
! 245: rtmax = rtmax * 2
! 246: if( f2 > rtmin .and. h2 < rtmax ) then
! 247: ! safmin <= sqrt( f2*h2 ) <= safmax
! 248: s = conjg( gs ) * ( fs / sqrt( f2*h2 ) )
! 249: else
! 250: s = conjg( gs ) * ( r / h2 )
! 251: end if
! 252: else
! 253: ! f2/h2 <= safmin may be subnormal, and h2/f2 may overflow.
! 254: ! Moreover,
! 255: ! safmin <= f2*f2 * safmax < f2 * h2 < h2*h2 * safmin <= safmax,
! 256: ! sqrt(safmin) <= sqrt(f2 * h2) <= sqrt(safmax).
! 257: ! Also,
! 258: ! g2 >> f2, which means that h2 = g2.
! 259: d = sqrt( f2 * h2 )
! 260: c = f2 / d
! 261: if( c >= safmin ) then
! 262: r = fs / c
! 263: else
! 264: ! f2 / sqrt(f2 * h2) < safmin, then
! 265: ! sqrt(safmin) <= f2 * sqrt(safmax) <= h2 / sqrt(f2 * h2) <= h2 * (safmin / f2) <= h2 <= safmax
! 266: r = fs * ( h2 / d )
! 267: end if
! 268: s = conjg( gs ) * ( fs / d )
! 269: end if
! 270: ! Rescale c and r
! 271: c = c * w
! 272: r = r * u
! 273: end if
! 274: end if
! 275: a = r
! 276: return
! 277: end subroutine
CVSweb interface <joel.bertrand@systella.fr>