zlartg function

void zlartg(
  1. Complex f,
  2. Complex g,
  3. Box<double> c,
  4. Box<Complex> s,
  5. Box<Complex> r,
)

Implementation

void zlartg(
  final Complex f,
  final Complex g,
  final Box<double> c,
  final Box<Complex> s,
  final Box<Complex> r,
) {
  const zero = dzero;
  const one = done;
  final safmin = dsafmin;
  final safmax = dsafmax;
  double d, f1, f2, g1, g2, h2, u, v, w, rtmin, rtmax;
  Complex fs, gs;

  rtmin = sqrt(safmin);

  if (g == Complex.zero) {
    c.value = one;
    s.value = Complex.zero;
    r.value = f;
  } else if (f == Complex.zero) {
    c.value = zero;
    if (g.real == zero) {
      r.value = g.imaginary.abs().toComplex();
      s.value = g.conjugate() / r.value;
    } else if (g.imaginary == zero) {
      r.value = g.real.abs().toComplex();
      s.value = g.conjugate() / r.value;
    } else {
      g1 = max(g.real.abs(), g.imaginary.abs());
      rtmax = sqrt(safmax / 2);
      if (g1 > rtmin && g1 < rtmax) {
        // Use unscaled algorithm
        //
        //    The following two lines can be replaced by `d = abs( g )`.
        //    This algorithm do not use the intrinsic complex abs.

        g2 = g.cabsSq();
        d = sqrt(g2);
        s.value = g.conjugate() / d.toComplex();
        r.value = d.toComplex();
      } else {
        // Use scaled algorithm

        u = min(safmax, max(safmin, g1));
        gs = g / u.toComplex();
        // The following two lines can be replaced by `d = abs( gs )`.
        // This algorithm do not use the intrinsic complex abs.
        g2 = gs.cabsSq();
        d = sqrt(g2);
        s.value = gs.conjugate() / d.toComplex();
        r.value = (d * u).toComplex();
      }
    }
  } else {
    f1 = max(f.real.abs(), f.imaginary.abs());
    g1 = max(g.real.abs(), g.imaginary.abs());
    rtmax = sqrt(safmax / 4);
    if (f1 > rtmin && f1 < rtmax && g1 > rtmin && g1 < rtmax) {
      // Use unscaled algorithm

      f2 = f.cabsSq();
      g2 = g.cabsSq();
      h2 = f2 + g2;
      // safmin <= f2 <= h2 <= safmax
      if (f2 >= h2 * safmin) {
        // safmin <= f2/h2 <= 1, and h2/f2 is finite
        c.value = sqrt(f2 / h2);
        r.value = f / c.value.toComplex();
        rtmax *= 2;
        if (f2 > rtmin && h2 < rtmax) {
          // safmin <= sqrt( f2*h2 ) <= safmax
          s.value = g.conjugate() * (f / sqrt(f2 * h2).toComplex());
        } else {
          s.value = g.conjugate() * (r.value / h2.toComplex());
        }
      } else {
        // f2/h2 <= safmin may be subnormal, and h2/f2 may overflow.
        // Moreover,
        //  safmin <= f2*f2 * safmax < f2 * h2 < h2*h2 * safmin <= safmax,
        //  sqrt(safmin) <= sqrt(f2 * h2) <= sqrt(safmax).
        // Also,
        //  g2 >> f2, which means that h2 = g2.
        d = sqrt(f2 * h2);
        c.value = f2 / d;
        if (c.value >= safmin) {
          r.value = f / c.value.toComplex();
        } else {
          // f2 / sqrt(f2 * h2) < safmin, {
          //  sqrt(safmin) <= f2 * sqrt(safmax) <= h2 / sqrt(f2 * h2) <= h2 * (safmin / f2) <= h2 <= safmax
          r.value = f * (h2 / d).toComplex();
        }
        s.value = g.conjugate() * (f / d.toComplex());
      }
    } else {
      // Use scaled algorithm

      u = min(safmax, max(safmin, max(f1, g1)));
      gs = g / u.toComplex();
      g2 = gs.cabsSq();
      if (f1 / u < rtmin) {
        // f is not well-scaled when scaled by g1.
        // Use a different scaling for f.

        v = min(safmax, max(safmin, f1));
        w = v / u;
        fs = f / v.toComplex();
        f2 = fs.cabsSq();
        h2 = f2 * pow(w, 2) + g2;
      } else {
        // Otherwise use the same scaling for f and g.

        w = one;
        fs = f / u.toComplex();
        f2 = fs.cabsSq();
        h2 = f2 + g2;
      }
      // safmin <= f2 <= h2 <= safmax
      if (f2 >= h2 * safmin) {
        // safmin <= f2/h2 <= 1, and h2/f2 is finite
        c.value = sqrt(f2 / h2);
        r.value = fs / c.value.toComplex();
        rtmax *= 2;
        if (f2 > rtmin && h2 < rtmax) {
          // safmin <= sqrt( f2*h2 ) <= safmax
          s.value = gs.conjugate() * (fs / sqrt(f2 * h2).toComplex());
        } else {
          s.value = gs.conjugate() * (r.value / h2.toComplex());
        }
      } else {
        // f2/h2 <= safmin may be subnormal, and h2/f2 may overflow.
        // Moreover,
        //  safmin <= f2*f2 * safmax < f2 * h2 < h2*h2 * safmin <= safmax,
        //  sqrt(safmin) <= sqrt(f2 * h2) <= sqrt(safmax).
        // Also,
        //  g2 >> f2, which means that h2 = g2.
        d = sqrt(f2 * h2);
        c.value = f2 / d;
        if (c.value >= safmin) {
          r.value = fs / c.value.toComplex();
        } else {
          // f2 / sqrt(f2 * h2) < safmin, {
          //  sqrt(safmin) <= f2 * sqrt(safmax) <= h2 / sqrt(f2 * h2) <= h2 * (safmin / f2) <= h2 <= safmax
          r.value = fs * (h2 / d).toComplex();
        }
        s.value = gs.conjugate() * (fs / d.toComplex());
      }
      // Rescale c and r
      c.value *= w;
      r.value *= u.toComplex();
    }
  }
}