changeset 20626:9fb8133288e8

chol: Support chol(a, "lower") for complex float types (bug #34850) * fCmplxCHOL.cc, fCmplxCHOL.h (FloatComplexCHOL::init, chol2inv_internal): Add is_upper parameter, propagate to underlying library functions. * fCMatrix.cc (FloatComplexMatrix::inverse): Use new argument. * chol.cc (Fchol): Likewise. This adds float complex support that was omitted in cset 5ce959c55cc0.
author Mike Miller <mtmiller@octave.org>
date Wed, 14 Oct 2015 21:31:22 -0400
parents 974b218e7292
children ec003232f7aa
files libinterp/dldfcn/chol.cc liboctave/array/fCMatrix.cc liboctave/numeric/fCmplxCHOL.cc liboctave/numeric/fCmplxCHOL.h
diffstat 4 files changed, 54 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/chol.cc	Sat Sep 26 19:25:03 2015 +0200
+++ b/libinterp/dldfcn/chol.cc	Wed Oct 14 21:31:22 2015 -0400
@@ -271,18 +271,12 @@
           octave_idx_type info;
 
           FloatComplexCHOL fact;
-          if (LLt)
-            fact = FloatComplexCHOL (m.transpose (), info);
-          else
-            fact = FloatComplexCHOL (m, info);
+          fact = FloatComplexCHOL (m, info, LLt != true);
 
           if (nargout == 2 || info == 0)
             {
               retval(1) = info;
-              if (LLt)
-                retval(0) = get_chol_l (fact);
-              else
-                retval(0) = get_chol_r (fact);
+              retval(0) = get_chol (fact);
             }
           else
             error ("chol: input matrix must be positive definite");
--- a/liboctave/array/fCMatrix.cc	Sat Sep 26 19:25:03 2015 +0200
+++ b/liboctave/array/fCMatrix.cc	Wed Oct 14 21:31:22 2015 -0400
@@ -1199,7 +1199,7 @@
     {
       if (mattype.is_hermitian ())
         {
-          FloatComplexCHOL chol (*this, info, calc_cond);
+          FloatComplexCHOL chol (*this, info, true, calc_cond);
           if (info == 0)
             {
               if (calc_cond)
--- a/liboctave/numeric/fCmplxCHOL.cc	Sat Sep 26 19:25:03 2015 +0200
+++ b/liboctave/numeric/fCmplxCHOL.cc	Wed Oct 14 21:31:22 2015 -0400
@@ -86,7 +86,7 @@
 }
 
 octave_idx_type
-FloatComplexCHOL::init (const FloatComplexMatrix& a, bool calc_cond)
+FloatComplexCHOL::init (const FloatComplexMatrix& a, bool upper, bool calc_cond)
 {
   octave_idx_type a_nr = a.rows ();
   octave_idx_type a_nc = a.cols ();
@@ -101,14 +101,25 @@
   octave_idx_type n = a_nc;
   octave_idx_type info;
 
+  is_upper = upper;
+
   chol_mat.clear (n, n);
-  for (octave_idx_type j = 0; j < n; j++)
-    {
-      for (octave_idx_type i = 0; i <= j; i++)
-        chol_mat.xelem (i, j) = a(i, j);
-      for (octave_idx_type i = j+1; i < n; i++)
-        chol_mat.xelem (i, j) = 0.0f;
-    }
+  if (is_upper)
+    for (octave_idx_type j = 0; j < n; j++)
+      {
+        for (octave_idx_type i = 0; i <= j; i++)
+          chol_mat.xelem (i, j) = a(i, j);
+        for (octave_idx_type i = j+1; i < n; i++)
+          chol_mat.xelem (i, j) = 0.0f;
+      }
+  else
+    for (octave_idx_type j = 0; j < n; j++)
+      {
+        for (octave_idx_type i = 0; i < j; i++)
+          chol_mat.xelem (i, j) = 0.0f;
+        for (octave_idx_type i = j; i < n; i++)
+          chol_mat.xelem (i, j) = a(i, j);
+      }
   FloatComplex *h = chol_mat.fortran_vec ();
 
   // Calculate the norm of the matrix, for later use.
@@ -116,8 +127,12 @@
   if (calc_cond)
     anorm = xnorm (a, 1);
 
-  F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info
-                             F77_CHAR_ARG_LEN (1)));
+  if (is_upper)
+    F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info
+                               F77_CHAR_ARG_LEN (1)));
+  else
+    F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, n, info
+                               F77_CHAR_ARG_LEN (1)));
 
   xrcond = 0.0;
   if (info > 0)
@@ -143,7 +158,7 @@
 }
 
 static FloatComplexMatrix
-chol2inv_internal (const FloatComplexMatrix& r)
+chol2inv_internal (const FloatComplexMatrix& r, bool is_upper = true)
 {
   FloatComplexMatrix retval;
 
@@ -157,17 +172,27 @@
 
       FloatComplexMatrix tmp = r;
 
-      F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                                 tmp.fortran_vec (), n, info
-                                 F77_CHAR_ARG_LEN (1)));
+      if (is_upper)
+        F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
+                                   tmp.fortran_vec (), n, info
+                                   F77_CHAR_ARG_LEN (1)));
+      else
+        F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
+                                   tmp.fortran_vec (), n, info
+                                   F77_CHAR_ARG_LEN (1)));
 
       // If someone thinks of a more graceful way of doing this (or
       // faster for that matter :-)), please let me know!
 
       if (n > 1)
-        for (octave_idx_type j = 0; j < r_nc; j++)
-          for (octave_idx_type i = j+1; i < r_nr; i++)
-            tmp.xelem (i, j) = std::conj (tmp.xelem (j, i));
+        if (is_upper)
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (i, j) = tmp.xelem (j, i);
+        else
+          for (octave_idx_type j = 0; j < r_nc; j++)
+            for (octave_idx_type i = j+1; i < r_nr; i++)
+              tmp.xelem (j, i) = tmp.xelem (i, j);
 
       retval = tmp;
     }
@@ -181,7 +206,7 @@
 FloatComplexMatrix
 FloatComplexCHOL::inverse (void) const
 {
-  return chol2inv_internal (chol_mat);
+  return chol2inv_internal (chol_mat, is_upper);
 }
 
 void
--- a/liboctave/numeric/fCmplxCHOL.h	Sat Sep 26 19:25:03 2015 +0200
+++ b/liboctave/numeric/fCmplxCHOL.h	Wed Oct 14 21:31:22 2015 -0400
@@ -37,17 +37,18 @@
 
   FloatComplexCHOL (void) : chol_mat (), xrcond (0) { }
 
-  FloatComplexCHOL (const FloatComplexMatrix& a, bool calc_cond = false)
+  FloatComplexCHOL (const FloatComplexMatrix& a, bool upper = true,
+                    bool calc_cond = false)
     : chol_mat (), xrcond (0)
   {
-    init (a, calc_cond);
+    init (a, upper, calc_cond);
   }
 
   FloatComplexCHOL (const FloatComplexMatrix& a, octave_idx_type& info,
-                    bool calc_cond = false)
+                    bool upper = true, bool calc_cond = false)
     : chol_mat (), xrcond (0)
   {
-    info = init (a, calc_cond);
+    info = init (a, upper, calc_cond);
   }
 
   FloatComplexCHOL (const FloatComplexCHOL& a)
@@ -92,7 +93,9 @@
 
   float xrcond;
 
-  octave_idx_type init (const FloatComplexMatrix& a, bool calc_cond);
+  bool is_upper;
+
+  octave_idx_type init (const FloatComplexMatrix& a, bool upper, bool calc_cond);
 };
 
 FloatComplexMatrix OCTAVE_API chol2inv (const FloatComplexMatrix& r);