Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / slasv2.c
diff --git a/3rdparty/lapack/slasv2.c b/3rdparty/lapack/slasv2.c
new file mode 100644 (file)
index 0000000..3b88738
--- /dev/null
@@ -0,0 +1,260 @@
+#include "clapack.h"
+
+/* Table of constant values */
+
+static real c_b3 = 2.f;
+static real c_b4 = 1.f;
+
+/* Subroutine */ int slasv2_(real *f, real *g, real *h__, real *ssmin, real *
+       ssmax, real *snr, real *csr, real *snl, real *csl)
+{
+    /* System generated locals */
+    real r__1;
+
+    /* Builtin functions */
+    double sqrt(doublereal), r_sign(real *, real *);
+
+    /* Local variables */
+    real a, d__, l, m, r__, s, t, fa, ga, ha, ft, gt, ht, mm, tt, clt, crt, 
+           slt, srt;
+    integer pmax;
+    real temp;
+    logical swap;
+    real tsign;
+    logical gasmal;
+    extern doublereal slamch_(char *);
+
+
+/*  -- LAPACK auxiliary routine (version 3.1) -- */
+/*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
+/*     November 2006 */
+
+/*     .. Scalar Arguments .. */
+/*     .. */
+
+/*  Purpose */
+/*  ======= */
+
+/*  SLASV2 computes the singular value decomposition of a 2-by-2 */
+/*  triangular matrix */
+/*     [  F   G  ] */
+/*     [  0   H  ]. */
+/*  On return, abs(SSMAX) is the larger singular value, abs(SSMIN) is the */
+/*  smaller singular value, and (CSL,SNL) and (CSR,SNR) are the left and */
+/*  right singular vectors for abs(SSMAX), giving the decomposition */
+
+/*     [ CSL  SNL ] [  F   G  ] [ CSR -SNR ]  =  [ SSMAX   0   ] */
+/*     [-SNL  CSL ] [  0   H  ] [ SNR  CSR ]     [  0    SSMIN ]. */
+
+/*  Arguments */
+/*  ========= */
+
+/*  F       (input) REAL */
+/*          The (1,1) element of the 2-by-2 matrix. */
+
+/*  G       (input) REAL */
+/*          The (1,2) element of the 2-by-2 matrix. */
+
+/*  H       (input) REAL */
+/*          The (2,2) element of the 2-by-2 matrix. */
+
+/*  SSMIN   (output) REAL */
+/*          abs(SSMIN) is the smaller singular value. */
+
+/*  SSMAX   (output) REAL */
+/*          abs(SSMAX) is the larger singular value. */
+
+/*  SNL     (output) REAL */
+/*  CSL     (output) REAL */
+/*          The vector (CSL, SNL) is a unit left singular vector for the */
+/*          singular value abs(SSMAX). */
+
+/*  SNR     (output) REAL */
+/*  CSR     (output) REAL */
+/*          The vector (CSR, SNR) is a unit right singular vector for the */
+/*          singular value abs(SSMAX). */
+
+/*  Further Details */
+/*  =============== */
+
+/*  Any input parameter may be aliased with any output parameter. */
+
+/*  Barring over/underflow and assuming a guard digit in subtraction, all */
+/*  output quantities are correct to within a few units in the last */
+/*  place (ulps). */
+
+/*  In IEEE arithmetic, the code works correctly if one matrix element is */
+/*  infinite. */
+
+/*  Overflow will not occur unless the largest singular value itself */
+/*  overflows or is within a few ulps of overflow. (On machines with */
+/*  partial overflow, like the Cray, overflow may occur if the largest */
+/*  singular value is within a factor of 2 of overflow.) */
+
+/*  Underflow is harmless if underflow is gradual. Otherwise, results */
+/*  may correspond to a matrix modified by perturbations of size near */
+/*  the underflow threshold. */
+
+/* ===================================================================== */
+
+/*     .. Parameters .. */
+/*     .. */
+/*     .. Local Scalars .. */
+/*     .. */
+/*     .. Intrinsic Functions .. */
+/*     .. */
+/*     .. External Functions .. */
+/*     .. */
+/*     .. Executable Statements .. */
+
+    ft = *f;
+    fa = dabs(ft);
+    ht = *h__;
+    ha = dabs(*h__);
+
+/*     PMAX points to the maximum absolute element of matrix */
+/*       PMAX = 1 if F largest in absolute values */
+/*       PMAX = 2 if G largest in absolute values */
+/*       PMAX = 3 if H largest in absolute values */
+
+    pmax = 1;
+    swap = ha > fa;
+    if (swap) {
+       pmax = 3;
+       temp = ft;
+       ft = ht;
+       ht = temp;
+       temp = fa;
+       fa = ha;
+       ha = temp;
+
+/*        Now FA .ge. HA */
+
+    }
+    gt = *g;
+    ga = dabs(gt);
+    if (ga == 0.f) {
+
+/*        Diagonal matrix */
+
+       *ssmin = ha;
+       *ssmax = fa;
+       clt = 1.f;
+       crt = 1.f;
+       slt = 0.f;
+       srt = 0.f;
+    } else {
+       gasmal = TRUE_;
+       if (ga > fa) {
+           pmax = 2;
+           if (fa / ga < slamch_("EPS")) {
+
+/*              Case of very large GA */
+
+               gasmal = FALSE_;
+               *ssmax = ga;
+               if (ha > 1.f) {
+                   *ssmin = fa / (ga / ha);
+               } else {
+                   *ssmin = fa / ga * ha;
+               }
+               clt = 1.f;
+               slt = ht / gt;
+               srt = 1.f;
+               crt = ft / gt;
+           }
+       }
+       if (gasmal) {
+
+/*           Normal case */
+
+           d__ = fa - ha;
+           if (d__ == fa) {
+
+/*              Copes with infinite F or H */
+
+               l = 1.f;
+           } else {
+               l = d__ / fa;
+           }
+
+/*           Note that 0 .le. L .le. 1 */
+
+           m = gt / ft;
+
+/*           Note that abs(M) .le. 1/macheps */
+
+           t = 2.f - l;
+
+/*           Note that T .ge. 1 */
+
+           mm = m * m;
+           tt = t * t;
+           s = sqrt(tt + mm);
+
+/*           Note that 1 .le. S .le. 1 + 1/macheps */
+
+           if (l == 0.f) {
+               r__ = dabs(m);
+           } else {
+               r__ = sqrt(l * l + mm);
+           }
+
+/*           Note that 0 .le. R .le. 1 + 1/macheps */
+
+           a = (s + r__) * .5f;
+
+/*           Note that 1 .le. A .le. 1 + abs(M) */
+
+           *ssmin = ha / a;
+           *ssmax = fa * a;
+           if (mm == 0.f) {
+
+/*              Note that M is very tiny */
+
+               if (l == 0.f) {
+                   t = r_sign(&c_b3, &ft) * r_sign(&c_b4, &gt);
+               } else {
+                   t = gt / r_sign(&d__, &ft) + m / t;
+               }
+           } else {
+               t = (m / (s + t) + m / (r__ + l)) * (a + 1.f);
+           }
+           l = sqrt(t * t + 4.f);
+           crt = 2.f / l;
+           srt = t / l;
+           clt = (crt + srt * m) / a;
+           slt = ht / ft * srt / a;
+       }
+    }
+    if (swap) {
+       *csl = srt;
+       *snl = crt;
+       *csr = slt;
+       *snr = clt;
+    } else {
+       *csl = clt;
+       *snl = slt;
+       *csr = crt;
+       *snr = srt;
+    }
+
+/*     Correct signs of SSMAX and SSMIN */
+
+    if (pmax == 1) {
+       tsign = r_sign(&c_b4, csr) * r_sign(&c_b4, csl) * r_sign(&c_b4, f);
+    }
+    if (pmax == 2) {
+       tsign = r_sign(&c_b4, snr) * r_sign(&c_b4, csl) * r_sign(&c_b4, g);
+    }
+    if (pmax == 3) {
+       tsign = r_sign(&c_b4, snr) * r_sign(&c_b4, snl) * r_sign(&c_b4, h__);
+    }
+    *ssmax = r_sign(ssmax, &tsign);
+    r__1 = tsign * r_sign(&c_b4, f) * r_sign(&c_b4, h__);
+    *ssmin = r_sign(ssmin, &r__1);
+    return 0;
+
+/*     End of SLASV2 */
+
+} /* slasv2_ */