changeset 32770:ed5e61fc7a4f bytecode-interpreter

maint: Merge default to bytecode-interpreter
author Arun Giridhar <arungiridhar@gmail.com>
date Wed, 17 Jan 2024 14:28:58 -0500
parents adf0b68212e1 (current diff) d7ff09ba5303 (diff)
children 80f7aec2c1c6
files
diffstat 2 files changed, 116 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/sqrtm.cc	Tue Jan 16 20:38:58 2024 -0500
+++ b/libinterp/corefcn/sqrtm.cc	Wed Jan 17 14:28:58 2024 -0500
@@ -40,51 +40,94 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-template <typename Matrix>
+template <typename T>
 static void
-sqrtm_utri_inplace (Matrix& T)
+sqrtm_utri_inplace (T& m)
 {
-  typedef typename Matrix::element_type element_type;
+  typedef typename T::element_type element_type;
+  typedef typename T::real_matrix_type real_matrix_type;
+  typedef typename T::real_elt_type real_elt_type;
 
   const element_type zero = element_type ();
 
   bool singular = false;
+  bool diagonal = true;
 
-  // The following code is equivalent to this triple loop:
-  //
-  //   n = rows (T);
-  //   for j = 1:n
-  //     T(j,j) = sqrt (T(j,j));
-  //     for i = j-1:-1:1
-  //       if T(i,j) != 0
-  //         T(i,j) /= (T(i,i) + T(j,j));
-  //       endif
-  //       k = 1:i-1;
-  //       T(k,j) -= T(k,i) * T(i,j);
-  //     endfor
-  //   endfor
-  //
-  // this is an in-place, cache-aligned variant of the code
-  // given in Higham's paper.
+  // The Schur matrix of Hermitian matrices is diagonal.
+  // check for off-diagonal elements above tolerance
+  const octave_idx_type n = m.rows ();
+  real_matrix_type abs_m = m.abs ();
+
+  real_elt_type max_abs_diag = 0;
+  for (octave_idx_type i = 0; i < n; i++)
+    max_abs_diag = std::max (max_abs_diag, abs_m(i,i));
+
+  const real_elt_type tol = n * max_abs_diag
+                            * std::numeric_limits<real_elt_type>::epsilon ();
+
+   for (octave_idx_type j = 0; j < n; j++)
+     {
+       for (octave_idx_type i = j-1; i >= 0; i--)
+         {
+          if (abs_m(i,j) > tol)
+            {
+              diagonal = false;
+              break;
+            }
+        }
+      if (! diagonal)
+        break;
+    }
 
-  const octave_idx_type n = T.rows ();
-  element_type *Tp = T.rwdata ();
-  for (octave_idx_type j = 0; j < n; j++)
+  element_type *mp = m.fortran_vec ();
+  if (diagonal)
+    {
+      // shortcut for diagonal Schur matrices
+      for (octave_idx_type i = 0; i < n; i++)
+        {
+          octave_idx_type idx_diag = i*(n+1);
+          if (mp[idx_diag] != zero)
+            mp[idx_diag] = sqrt (mp[idx_diag]);
+          else
+            singular = true;
+        }
+    }
+  else
     {
-      element_type *colj = Tp + n*j;
-      if (colj[j] != zero)
-        colj[j] = sqrt (colj[j]);
-      else
-        singular = true;
+      // The following code is equivalent to this triple loop:
+      //
+      //   n = rows (m);
+      //   for j = 1:n
+      //     m(j,j) = sqrt (m(j,j));
+      //     for i = j-1:-1:1
+      //       if m(i,j) != 0
+      //         m(i,j) /= (m(i,i) + m(j,j));
+      //       endif
+      //       k = 1:i-1;
+      //       m(k,j) -= m(k,i) * m(i,j);
+      //     endfor
+      //   endfor
+      //
+      // this is an in-place, cache-aligned variant of the code
+      // given in Higham's paper.
 
-      for (octave_idx_type i = j-1; i >= 0; i--)
+      for (octave_idx_type j = 0; j < n; j++)
         {
-          const element_type *coli = Tp + n*i;
-          if (colj[i] != zero)
-            colj[i] /= (coli[i] + colj[j]);
-          const element_type colji = colj[i];
-          for (octave_idx_type k = 0; k < i; k++)
-            colj[k] -= coli[k] * colji;
+          element_type *colj = mp + n*j;
+          if (colj[j] != zero)
+            colj[j] = sqrt (colj[j]);
+          else
+            singular = true;
+
+          for (octave_idx_type i = j-1; i >= 0; i--)
+            {
+              const element_type *coli = mp + n*i;
+              if (colj[i] != zero)
+                colj[i] /= (coli[i] + colj[j]);
+              const element_type colji = colj[i];
+              for (octave_idx_type k = 0; k < i; k++)
+                colj[k] -= coli[k] * colji;
+            }
         }
     }
 
@@ -186,11 +229,11 @@
                 x = schur_fact.schur_matrix ();
                 u = schur_fact.unitary_schur_matrix ();
               }
-            while (0); // schur no longer needed.
+            while (0);  // schur_fact no longer needed.
 
             sqrtm_utri_inplace (x);
 
-            x = u * x; // original x no longer needed.
+            x = u * x;  // original x no longer needed.
             ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);
 
             if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)
--- a/libinterp/parse-tree/oct-parse.yy	Tue Jan 16 20:38:58 2024 -0500
+++ b/libinterp/parse-tree/oct-parse.yy	Wed Jan 17 14:28:58 2024 -0500
@@ -5498,34 +5498,6 @@
     m_lexer.m_allow_command_syntax = false;
   }
 
-  // FIXME: this function partially duplicates do_dbtype in debug.cc.
-  static std::string
-  get_file_line (const std::string& name, int line)
-  {
-    // NAME should be an absolute file name and the file should exist.
-
-    std::ifstream fs = sys::ifstream (name.c_str (), std::ios::in);
-
-    std::string text;
-
-    if (fs)
-      {
-        int i = 1;
-
-        do
-          {
-            if (! std::getline (fs, text))
-              {
-                text = "";
-                break;
-              }
-          }
-        while (i++ < line);
-      }
-
-    return text;
-  }
-
   void
   base_parser::bison_error (const std::string& str)
   {
@@ -5543,56 +5515,51 @@
   {
     std::ostringstream output_buf;
 
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
-        || m_lexer.m_reading_classdef_file)
-      output_buf << "parse error near line " << err_line
-                 << " of file " << m_lexer.m_fcn_file_full_name;
-    else
-      output_buf << "parse error:";
-
-    if (str != "parse error")
-      output_buf << "\n\n  " << str;
-
-    output_buf << "\n\n";
-
-    std::string curr_line;
-
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
-        || m_lexer.m_reading_classdef_file)
-      curr_line = get_file_line (m_lexer.m_fcn_file_full_name, err_line);
-    else
-      curr_line = m_lexer.m_current_input_line;
+    bool in_file = (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
+                    || m_lexer.m_reading_classdef_file);
 
     // Adjust the error column for display because it is 1-based in the
     // lexer for easier reporting.
     err_col--;
 
-    if (! curr_line.empty ())
+    if (in_file)
+      {
+        output_buf << str
+                   << " near line " << err_line << ", column " << err_col << "\n"
+                   << "error: called from\n"
+                   << "    " << m_lexer.m_fcn_file_name
+                   << " at line " << err_line << " column " << err_col << "\n";
+      }
+    else
       {
-        // FIXME: we could do better if we just cached lines from the
-        // input file in a list.  See also functions for managing input
-        // buffers in lex.ll.
-
-        std::size_t len = curr_line.length ();
-
-        if (curr_line[len-1] == '\n')
-          curr_line.resize (len-1);
-
-        // Print the line, maybe with a pointer near the error token.
-
-        output_buf << ">>> " << curr_line << "\n";
-
-        if (err_col == 0)
-          err_col = len;
-
-        for (int i = 0; i < err_col + 3; i++)
-          output_buf << " ";
-
-        output_buf << "^";
+        // On command line, point directly to error
+        output_buf << str << "\n\n";
+        std::string curr_line = m_lexer.m_current_input_line;
+
+        if (! curr_line.empty ())
+          {
+            // FIXME: we could do better if we just cached lines from the
+            // input file in a list.  See also functions for managing input
+            // buffers in lex.ll.
+            std::size_t len = curr_line.length ();
+
+            if (curr_line[len-1] == '\n')
+              curr_line.resize (len-1);
+
+            // Print the line, maybe with a pointer near the error token.
+            output_buf << ">>> " << curr_line << "\n";
+
+            if (err_col == 0)
+              err_col = len;
+
+            for (int i = 0; i < err_col + 3; i++)
+              output_buf << " ";
+
+            output_buf << "^" << "\n";
+          }
+
       }
 
-    output_buf << "\n";
-
     m_parse_error_msg = output_buf.str ();
   }