# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1470242637 -7200
#      Wed Aug 03 18:43:57 2016 +0200
# Node ID 94ccec9b749d28727066d7216b8df30071076c7c
# Parent  46b67f1569b58c7ce95a357b51afb710b279a8aa
part of java sources: added doxygen comments,
simplified code without really changing behavior,
just strengthened declaration of Throwables.

diff -r 46b67f1569b5 -r 94ccec9b749d scripts/java/org/octave/ClassHelper.java
--- a/scripts/java/org/octave/ClassHelper.java	Wed Aug 03 04:55:05 2016 +0100
+++ b/scripts/java/org/octave/ClassHelper.java	Wed Aug 03 18:43:57 2016 +0200
@@ -22,124 +22,276 @@
 
 package org.octave;
 
-import java.lang.reflect.*;
+import java.net.URL;
+import java.net.URISyntaxException;
+import java.net.MalformedURLException;
 
+import java.io.File;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+//! Collection of methods being the core of the octave functions
+//! forming Octave's Java Interface.
+//!
+//! @arg
+//! #addClassPath(String) used by @file javaaddpath.m defining @c javaaddpath.
+//! @arg
+//! #removeClassPath(String) used by @file javarmpath.m defining @c javarmpath.
+//! @arg
+//! #getClassPath() used by @file javaclasspath.m defining @c javaclasspath
+//! to obtain the dynamic classpath.
+//! @arg
+//! #getMethods(String), #getMethods(Object) and #getMethods(Class)
+//! used by @file methods.m defining @c methods.
+//! @arg
+//! #getFields(Class), #getFields(String) and #getFields(Object)
+//! used by @file fieldnames.m defining @c fieldnames.
+//! @arg
+//! #invokeMethod(Object, String, Object[], Class[]) and
+//! #invokeStaticMethod(String, String, Object[], Class[])
+//! used by <code>javaMethod</code> defined in @file ov-java.cc
+//! defining @c javaMethod.
+//! @arg
+//! #invokeConstructor(String, Object[], Class[])
+//! used by @c javaObject defined in @file ov-java.cc
+//! defining @c javaObject.
+//! @arg
+//! #getField(Object, String), #getStaticField(String, String)
+//! used by @c __java_get__ defined in @file ov-java.cc
+//! used by @file java_get.m defining @c java_get.
+//! @arg
+//! #setField(Object, String, Object), #setStaticField(String, String, Object)
+//! used by @c __java_set__ defined in @file ov-java.cc
+//! used by @file java_set.m defining @c java_set.
+//! @arg
+//! #arraySubsref(Object, int[][]), #arraySubsasgn(Object, int[][], Object)
+//! defining read and write access
+//! through operators <code>.</code> and <code>(...)</code>
+//! @arg
+//! #createArray(Object, int[])
+//! used by @file javaArray.m defining @c javaArray.
 public class ClassHelper
 {
+  //! The loader for the dynamic classpath 
+  //! delegating to the loader for the static classpath. 
   private static OctClassLoader loader;
 
   static
   {
-    ClassLoader l = ClassHelper.class.getClassLoader ();
-    loader = (l instanceof OctClassLoader ? (OctClassLoader) l :
-              new OctClassLoader (l));
+    loader = octClsLoader();
   }
 
+  //! Returns either the class loader of this class
+  //! or creates an @ref OctClassLoader
+  //! with the former classloader as parent.
+  private static OctClassLoader octClsLoader() {
+    ClassLoader l = ClassHelper.class.getClassLoader ();
+    return l instanceof OctClassLoader 
+      ? (OctClassLoader) l 
+      : new OctClassLoader (l);
+  }
 
-  /**
-   * Add the given path to the classpath.
-   * @param name String - path to addd to the classpath
-   * @return boolean - true if the given path exists and was added to the classpath.
-   * @throws Exception
-   */
-  public static boolean addClassPath (String name)
-    throws Exception
+  //! Add the given path @c path to the (dynamic) classpath.
+  //! Used by @file javaaddpath.m only.
+  //!
+  //! @param path 
+  //!    path to add to the classpath.
+  //!    This could be e.g. (examples for Unix)
+  //!    <code>/home/charles</code>, <code>~/Octave</code>
+  //!    or <code>../Software</code>.
+  //! @return 
+  //!    whether the given path exists and was thus added to the classpath.
+  //! @throws MalformedURLException
+  //!    if conversion from URI representing @c path to URL fails. 
+  //!    This should not occur if @c path points to a file.
+  public static boolean addClassPath (String path)
+    throws MalformedURLException
+  {
+    File f = new File (path);
+    if (f.exists ())
+      {
+//        loader.addClassPath (path);
+        // file2url may throw MalformedURLException
+        loader.addURL (file2url(f));
+        return true;
+      }
+    return false;
+  }
+
+  //! Remove the given path @c path from the (dynamic) classpath,
+  //! even if it occurs more than once.
+  //! Used by @file javarmpath.m only.
+  //!
+  //! @param path
+  //!    path to remove from classpath.
+  //! @return
+  //!    whether the given path existed in the classpath before it was removed.
+  //! @throws MalformedURLException
+  //!    if conversion from URI representing @c path to URL fails.
+  //!    This should not occur if @c path points to a file.
+    public static boolean removeClassPath (String path)
+    throws MalformedURLException
   {
     boolean found = false;
-    java.io.File f = new java.io.File (name);
-    if (f.exists ())
-      {
-        loader.addClassPath (name);
-        found = true;
-      }
-    return (found);
-  }
+    // file2url may throw MalformedURLException
+    URL urlToRemove = file2url (new File (path));
+    // save urls in current class path
+    URL[] urls = loader.getURLs ();
 
+    // create a completely new class loader
+    // because URLClassLoader has no removeClassPath() method
+    // FIXME: does not work if ClassHelper.class.getClassLoader()
+    // is already an instance of OctClassLoader which seems true.
+    loader = octClsLoader();
 
-  // new -MH-
-  /**
-   *
-   * @param name String - path to remove from classpath.
-   * @return boolean - true if the given path existed in the classpath before it was removed.
-   * @throws Exception
-   */
-  public static boolean removeClassPath (String name)
-    throws Exception
-  {
-    boolean found = false;
-    java.io.File f = new java.io.File (name);
-    java.net.URL urlToRemove = f.toURI ().toURL ();
-    // save urls in current class path
-    java.net.URL[] urls = loader.getURLs ();
-
-    // create a completely new class loader because java.net.URLClassLoader has no removeClassPath() method
-    ClassLoader l = ClassHelper.class.getClassLoader ();
-    loader = (l instanceof OctClassLoader ? (OctClassLoader) l :
-              new OctClassLoader (l));
-
-    // add the previous urls back, except for the one
+    // add the previous urls back to loader, except for urlToRemove
     for (int i = 0; i < urls.length; i++)
       {
-        java.net.URL url = urls[i];
-        if (!url.equals (urlToRemove))
-          {
-            loader.addURL (url);
-          }
-        else
+        URL url = urls[i];
+        if (url.equals (urlToRemove))
           {
             // path to remove
             found = true;
           }
-      }
+        else
+          {
+            // path to be re-added
+            loader.addURL (url);
+          }
+       }
 
-    return (found);
+    return found;
   }
 
-
-  public static String getClassPath ()
+  //! Return the current dynamic classpath.
+  //! Used by @file javaclasspath.m only.
+  //!
+  //! @return
+  //!    the current dynamic classpath.
+  //!    as a string, separated by the path separator
+  //!    determined by System::getProperty(String).
+  //! @throws URISyntaxException
+  //!    if one of the URLs of the classpath is no URI.
+  //!    This should not occur,
+  //!    because the URLs of #loader come from filenames.
+  public static String getClassPath () throws URISyntaxException
   {
     StringBuffer buf = new StringBuffer ();
     String pathSep = System.getProperty ("path.separator");
-    java.net.URL[] urls = loader.getURLs ();
+    URL[] urls = loader.getURLs ();
 
     for (int i = 0; i < urls.length; i++)
       {
-        try
+        if (i > 0)
           {
-            java.io.File f = new java.io.File (urls[i].toURI ());
-            if (buf.length () > 0)
-              {
-                buf.append (pathSep);
-              }
-            buf.append (f.toString ());
+            buf.append (pathSep);
           }
-        catch (java.net.URISyntaxException ex)
-          {}
+        // url2file may throw URISyntaxException
+        buf.append (url2file(urls[i]).toString ());
       }
     return buf.toString ();
   }
 
+  //! Convert an URL into an according file.
+  //!
+  //! @param url
+  //!    the URL to be converted.
+  //!    This shall be with protocol @c file.
+  //! @throws URISyntaxException
+  //!    If the URL is not an URI.
+  //!    For URLs with protocol @c file, this cannot occur.
+  //! @see ::getClassPath()
+  private static File url2file(URL url) throws URISyntaxException
+  {
+    // toURI() may throw URISyntaxException
+    return new File (url.toURI ());
+  }
+
+  //! Convert a file into an according URL.
+  //!
+  //! @param file
+  //!    the file to be converted.
+  //!    This could be e.g. (examples for Unix)
+  //!    <code>/home/charles</code>, <code>~/Octave</code>
+  //!    or <code>../Software</code>.
+  //! @return
+  //!    For the above input the return is
+  //!    <code>file:/home/charles</code>,
+  //!    <code>file:/home/charles/curr/~/Octave</code>
+  //!    and <code>file:/home/charles/curr/../Software</code>,
+  //!    where <code>/home/charles/curr</code>
+  //!    is the current working directory.
+  //! @throws MalformedURLException
+  //!    With the input specified above, this shall not occur
+  //!    because the intermediate URI has the form
+  //!    For URLs referring to a file, this canot occur.
+  //! @see ::addClassPath(String)
+  //! @see ::removeClassPath(String)
+  private static URL file2url(File file) throws MalformedURLException
+  {
+    // toURL() may throw MalformedURLException
+    return file.toURI ().toURL ();
+  }
+
 
   // new -MH-
-  // return list of methods for given class name
+  //! Return a list of public methods
+  //! of the class with the given class name @c classname
+  //! loaded with #loader.
+  //! This method is based on ::getMethods(Class).
+  //! Used by @file methods.m only.
+  //!
+  //! @param classname
+  //!    the name of the class under consideration.
+  //! @return
+  //!    see ::getMethods(Class).
+  //! @throws ClassNotFoundException
+  //!    if #loader cannot find a class with name @c classname.
   public static String getMethods (String classname)
     throws ClassNotFoundException
   {
-    return (getMethods (Class.forName (classname)));
+    return getMethods (Class.forName (classname));
+    // FIXME: ****
+    //return getMethods (Class.forName (classname, true, loader));
   }
 
 
   // new -MH-
-  // return list of methods for given class instance
+  //! Return a list of public methods
+  //! of the class of the instance @c obj.
+  //! Used by @file methods.m only.
+  //!
+  //! @param obj
+  //!    the object under consideration. This shall not be @c null.
+  //! @throws ClassNotFoundException
+  //!    if #loader cannot find @c obj's class.
+  //!    Since all objects are created by reflection
+  //!    from classes loaded by #loader, this shall not happen.
   public static String getMethods (Object obj)
     throws ClassNotFoundException
   {
-    return (getMethods (obj.getClass ()));
+    return getMethods (obj.getClass ());
   }
 
 
   // new -MH-
-  // return list of methods for given class
+  //! Return list of public
+  //! methods for given class @c klass.
+  //! This method is based on Class::getMethods().
+  //! To obtain all methods, one could use Class::getDeclaredMethods()
+  //! iterating over class and superclasses.
+  //! Used internally and by @file methods.m only.
+  //!
+  //! @param klass
+  //!    the class under consideration.
+  //! @return
+  //!    the list of methods for given class @c klass as a string, 
+  //!    the signatures of the methods separated by <code>;</code>.
   public static String getMethods (Class klass)
   {
     StringBuffer sb = new StringBuffer ();
@@ -149,13 +301,16 @@
       {
         if (i > 0)
           {
-            sb.append (";");
+            sb.append (';');
           }
+
+        // Return type and name 
         sb.append (theMethod[i].getReturnType ().getCanonicalName ());
-        sb.append (" ");
+        sb.append (' ');
         sb.append (theMethod[i].getName ());
-        sb.append ("(");
 
+        // parameter list 
+        sb.append ('(');
         Class theParameter[] = theMethod[i].getParameterTypes ();
         for (int j = 0; j < theParameter.length; j++)
           {
@@ -165,29 +320,40 @@
               }
             sb.append (theParameter[j].getCanonicalName ());
           }
-        sb.append (")");
+        sb.append (')');
 
+        // exceptions 
         Class theExceptions[] = theMethod[i].getExceptionTypes ();
         if (theExceptions.length > 0)
           {
             sb.append (" throws ");
-            for (int j = 0; j < theExceptions.length; j++)
+            sb.append (theExceptions[0].getCanonicalName ());
+             for (int j = 1; j < theExceptions.length; j++)
               {
-                if (j > 0)
-                  {
-                    sb.append (", ");
-                  }
+                sb.append (", ");
                 sb.append (theExceptions[j].getCanonicalName ());
               }
           }
       }
 
-    return (sb.toString ());
+    return sb.toString ();
   }
 
 
   // new -MH-
-  // return list of fields for given class
+  //! Return a list of all accessible public fields
+  //! of the given class @c klass.
+  //! This method is based on Class::getFields().
+  //! To obtain all fields, one could use Class::getDeclaredFields()
+  //! iterating over class and superclasses.
+  //! Used internally and by @file fieldnames.m only.
+  //!
+  //! @param klass
+  //!    the class under consideration.
+  //! @return 
+  //!    the list of names of accessible public fields
+  //!    of the given class @c klass
+  //!    as a string, separated by <code>;</code>.
   public static String getFields (Class klass)
   {
     StringBuffer sb = new StringBuffer ();
@@ -197,40 +363,78 @@
       {
         if (i > 0)
           {
-            sb.append (";");
+            sb.append (';');
           }
         sb.append (theField[i].getName ());
       }
 
-    return (sb.toString ());
+    return sb.toString ();
   }
 
 
   // new -MH-
-  // return list of fields for given class name
+  //! Return a list of all accessible public fields
+  //! of the class with the given class name @c classname
+  //! loaded with #loader.
+  //! This method is based on ::getFields(Class).
+  //! Used by @file fieldnames.m only.
+  //!
+  //! @param classname
+  //!    the name of the class under consideration.
+  //! @return
+  //!    see ::getFields(Class).
+  //! @throws ClassNotFoundException
+  //!    if #loader cannot find a class with name @c classname.
   public static String getFields (String classname)
     throws ClassNotFoundException
   {
-    return (getFields (Class.forName (classname)));
+    return getFields (Class.forName (classname));
+//    return getFields (Class.forName (classname, true, loader));
   }
 
 
   // new -MH-
-  // return list of fields for given class instance
+  //! Return a list of all accessible public fields
+  //! of class of the instance @c obj.
+  //! This method is based on ::getFields(Class).
+  //! Used by @file fieldnames.m only.
+  //!
+  //! @param obj
+  //!    the object under consideration. This shall not be @c null.
+  //! @throws ClassNotFoundException
+  //!    if #loader cannot find @c obj's class.
+  //!    Since all objects are created by reflection
+  //!    from classes loaded by #loader, this shall not happen.
   public static String getFields (Object obj)
     throws ClassNotFoundException
   {
     return (getFields (obj.getClass ()));
   }
 
-
-  public static Method findMethod (Class cls, String name, Class[] argTypes)
+  //! Return the first method in class @c cls
+  //! with name @c name and parameter types @c argTypes
+  //! or @c null if no such method is found.
+  //! Note that if there are more than one method fitting the criteria,
+  //! an arbitrary one is returned, and there is no notification,
+  //! that the solution is not unique.
+  //!
+  //! @param cls
+  //!    the class of the method.
+  //! @param name
+  //!    the name of the method.
+  //! @param argTypes
+  //!    the argument types of the method.
+  //! @return
+  //!    a method in class @c cls
+  //!    with name @c name and parameter types @c argTypes
+  //!    or @c null if no such method exists.
+  private static Method findMethod (Class cls, String name, Class[] argTypes)
   {
     try
       {
         return cls.getMethod (name, argTypes);
       }
-    catch (Exception e)
+    catch (NoSuchMethodException e)
       {
         Method[] mList = cls.getMethods ();
         Method m;
@@ -248,14 +452,28 @@
       }
   }
 
-
-  public static Constructor findConstructor (Class cls, Class[] argTypes)
+  //! Return the first constructor in class @c cls
+  //! with parameter types @c argTypes
+  //! or @c null if no such constructor is found.
+  //! Note that if there are more than one constructor fitting the criteria,
+  //! an arbitrary one is returned, and there is no notification,
+  //! that the solution is not unique.
+  //!
+  //! @param cls
+  //!    the class of the constructor.
+  //! @param argTypes
+  //!    the argument types of the constructor.
+  //! @return
+  //!    a constructor in class @c cls
+  //!    with parameter types @c argTypes
+  //!    or @c null if no such constructor exists.
+  private static Constructor findConstructor (Class cls, Class[] argTypes)
   {
     try
       {
         return cls.getConstructor (argTypes);
       }
-    catch (Exception e)
+    catch (NoSuchMethodException e)
       {
         Constructor[] cList = cls.getConstructors ();
         //System.out.println("# constructors: " + cList.length);
@@ -274,148 +492,211 @@
       }
   }
 
-
-  private static Object invokeMethod (Method m, Object target, Object[] args)
-    throws Exception
+  //! Invoke method @c mthd on the object @c target with arguments @c args. 
+  //!
+  //! @param mthd
+  //!    the method to be invoked.
+  //! @param target
+  //!    the object @c mthd may be invoked on.
+  //!    For static methods this may be @c null.
+  //!    The type must fit the method.
+  //! @param args
+  //!    the arguments to invoke @c mthd with.
+  //! @return
+  //!    the return value of method @c mthd
+  //!    if applied to @c target with arguments @c args.
+  //!    For static methods, @c target is ignored.
+  //!    If @c mthd has return type @c void,
+  //!    this method returns @c null.
+  //!    If  @c mthd has other primitive return type,
+  //!    this is boxed to obtain an object before return.
+  //! @throws InvocationTargetException
+  //!    if invocation of the underlying method throws an exception.
+  //! @throws IllegalAccessException
+  //!    if this Method object is enforcing Java language access control
+  //!    and the underlying method is inaccessible.
+  //! @see ::invokeMethod(Object, String, Object[], Class[])
+  private static Object invokeMethod (Method mthd, Object target, Object[] args)
+    throws InvocationTargetException, IllegalAccessException
   {
-    try
+    //if (Modifier.isPublic(mthd.getModifiers()))
+    try 
       {
-        return m.invoke (target, args);
+        // may throw InvocationTargetException, 
+        // but no IllegalAccessException
+        return mthd.invoke (target, args);
       }
     catch (IllegalAccessException ex)
       {
-        String mName = m.getName ();
-        Class[] pTypes = m.getParameterTypes ();
-        Class currClass = target.getClass ();
-
-        while (currClass != null)
+        // FIXME: is this really wanted? 
+        String mName   = mthd.getName ();
+        Class[] pTypes = mthd.getParameterTypes ();
+ 
+        // search in target class and in superclasses. 
+        for (Class currClass = target.getClass ();
+             currClass != null; 
+             currClass = currClass.getSuperclass ())
           {
             try
               {
+                //  may throw NoSuchMethodException
                 Method meth = currClass.getMethod (mName, pTypes);
-                if (!meth.equals (m))
+                if (!meth.equals (mthd))
                   {
+                    // may throw InvocationTargetException, 
+                    // IllegalAccessException
                     return meth.invoke (target, args);
                   }
               }
-            catch (NoSuchMethodException ex2)
-              {}
-            catch (IllegalAccessException ex2)
-              {}
+            catch (NoSuchMethodException ex2) // NOPMD
+              {
+                // empty catch is really ok: just go on searching 
+              }
 
+            // FIXME: I am pretty sure, that this finds no further methods 
+            // and shall thus be removed (ER). 
             Class[] ifaceList = currClass.getInterfaces ();
             for (int i = 0; i < ifaceList.length; i++)
               {
                 try
                   {
+                    //  may throw NoSuchMethodException
                     Method meth = ifaceList[i].getMethod (mName, pTypes);
+                    // may throw InvocationTargetException
                     return meth.invoke (target, args);
                   }
-                catch (NoSuchMethodException ex2)
-                  {}
-                catch (IllegalAccessException ex2)
-                  {}
-              }
+                catch (NoSuchMethodException ex2) // NOPMD
+                  {
+                    // empty catch is really ok: just go on searching 
+                  }
+              } // for 
+          } // for 
+        // throws IllegalAccessException 
+        throw ex;
+     } // catch IllegalAccessException 
+  }
 
-            currClass = currClass.getSuperclass ();
-          }
 
-        throw ex;
+  // Used internally and by 
+  // #do_javaMethod(void*, std::string&, octave_value_list&) 
+  // in <code>ov-java.cc</code> only. 
+  // getField(Object, String)
+  public static Object invokeMethod (Object target, 
+                                     String name,
+                                     Object[] args, 
+                                     Class[] argTypes)
+    throws Throwable
+  {
+    Method m = findMethod (target.getClass (), name, argTypes);
+    if (m == null)
+      {
+        throw new NoSuchMethodException (name);
+      }
+
+    try
+      {
+        Object result = invokeMethod (m, target,
+                                      castArguments (args, argTypes,
+                                                     m.getParameterTypes ()));
+        return result;
+      }
+    catch (InvocationTargetException ex)
+      {
+        throw ex.getCause ();
+      }
+
+  }
+
+  // using loader 
+  // Used internally and by @file ov-java.cc only. 
+  // getStaticField(String, String)
+  public static Object invokeStaticMethod (String cls, 
+                                           String name,
+                                           Object[] args, 
+                                           Class[] argTypes)
+    throws ClassNotFoundException, 
+    NoSuchMethodException, 
+    IllegalAccessException, 
+    Throwable
+  {
+    // forName may throw ClassNotFoundException 
+    Method m = findMethod (Class.forName (cls, true, loader), 
+                           name,
+                           argTypes);
+    if (m == null)
+      {
+        throw new NoSuchMethodException (name);
+      }
+
+    try
+      {
+        // may throw IllegalAccessException, InvocationTargetException
+        Object result = m.invoke (null,
+                                  castArguments (args, argTypes,
+                                                 m.getParameterTypes ()));
+        return result;
+      }
+    catch (InvocationTargetException ex)
+      {
+        // may throw general Throwable 
+        throw ex.getCause ();
       }
   }
 
-
-  public static Object invokeMethod (Object target, String name,
-                                     Object[] args, Class[] argTypes)
-    throws Throwable
-  {
-    Method m = findMethod (target.getClass (), name, argTypes);
-    if (m != null)
-      {
-        try
-          {
-            Object result = invokeMethod (m, target,
-                                          castArguments (args, argTypes,
-                                                         m.getParameterTypes ()));
-            return result;
-          }
-        catch (InvocationTargetException ex)
-          {
-            throw ex.getCause ();
-          }
-      }
-    else
-      {
-        throw new NoSuchMethodException (name);
-      }
-  }
-
-
-  public static Object invokeStaticMethod (String cls, String name,
-                                           Object[] args, Class[] argTypes)
-    throws Throwable
-  {
-    Method m = findMethod (Class.forName (cls, true, loader), name,
-                           argTypes);
-    if (m != null)
-      {
-        try
-          {
-            Object result = m.invoke (null,
-                                      castArguments (args, argTypes,
-                                                     m.getParameterTypes ()));
-            return result;
-          }
-        catch (InvocationTargetException ex)
-          {
-            throw ex.getCause ();
-          }
-      }
-    else
-      {
-        throw new NoSuchMethodException (name);
-      }
-  }
-
-
-  public static Object invokeConstructor (String cls, Object[] args,
+  // using loader 
+  // Used @file ov-java.cc only. 
+  public static Object invokeConstructor (String cls, 
+                                          Object[] args,
                                           Class[] argTypes)
     throws Throwable
   {
     Constructor c = findConstructor (Class.forName (cls, true, loader),
                                      argTypes);
-    if (c != null)
-      {
-        try
-          {
-            Object result = c.newInstance (castArguments (args, argTypes,
-                                                          c.getParameterTypes ()));
-            return result;
-          }
-        catch (InvocationTargetException ex)
-          {
-            throw ex.getCause ();
-          }
-      }
-    else
+    if (c == null)
       {
         throw new NoSuchMethodException (cls);
       }
+
+    try
+      {
+        return c.newInstance (castArguments (args, argTypes,
+                                             c.getParameterTypes ()));
+      }
+    catch (InvocationTargetException ex)
+      {
+        throw ex.getCause ();
+      }
+
   }
 
-
+  //! Return the value of the field with name @c name
+  //! of object @c target.
+  //! Used by @file ov-java.cc only.
+  //!
+  //! @param target
+  //!    an object to query a field which shall not be @c null.
+  //! @param name
+  //!    the name of the field of @c target 
+  //!    which shall not be @c null. 
+  //! @throws NoSuchFieldException 
+  //!    if @c target has no field with the given name.
+  //! @throws IllegalAccessException
+  //!    if the field @c name of object @c target is not accessible. 
   public static Object getField (Object target, String name)
-    throws Throwable
+    throws NoSuchFieldException, IllegalAccessException, Throwable
   {
     try
       {
-        Field f = target.getClass ().getField (name);
-        return f.get (target);
+        // getField may throw NoSuchFieldException 
+        //   if a field with the specified name is not found.
+        // get may throw IllegalAccessException
+        return target.getClass ().getField (name).get (target);
       }
     catch (NoSuchFieldException ex)
       {
         try
           {
+            // may throw Throwable if so does method name() 
             return invokeMethod (target, name, new Object[0], new Class[0]);
           }
         catch (NoSuchMethodException ex2)
@@ -425,17 +706,24 @@
       }
   }
 
-
+  // based on loader 
+  // Used by @file ov-java.cc only. 
   public static Object getStaticField (String cls, String name)
-    throws Throwable
+    throws ClassNotFoundException, 
+    NoSuchFieldException, 
+    IllegalAccessException, 
+    Throwable
   {
     try
       {
-        Field f = Class.forName (cls, true, loader).getField (name);
-        return f.get (null);
+        // getField may throw NoSuchFieldException 
+        //   if a field with the specified name is not found.
+        // get may throw IllegalAccessException
+        return Class.forName (cls, true, loader).getField (name).get (null);
       }
     catch (NoSuchFieldException ex)
       {
+        // FIXME: is this really appropriate? 
         try
           {
             return invokeStaticMethod (cls, name, new Object[0], new Class[0]);
@@ -447,19 +735,25 @@
       }
   }
 
-
+  // Used by @file ov-java.cc only. 
   public static void setField (Object target, String name, Object value)
-    throws Exception
+    throws NoSuchFieldException, IllegalAccessException
   {
+    // getField may throw NoSuchFieldException
     Field f = target.getClass ().getField (name);
+    // set may throw IllegalAccessException 
     f.set (target, castArgument (value, value.getClass (), f.getType ()));
   }
 
-
+  // based on loader 
+  // Used by @file ov-java.cc only. 
   public static void setStaticField (String cls, String name, Object value)
-    throws Exception
+    throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException
   {
+    // forName may throw ClassNotFoundException 
+    // getField may throw NoSuchFieldException
     Field f = Class.forName (cls, true, loader).getField (name);
+    // set may throw IllegalAccessException 
     f.set (null, castArgument (value, value.getClass (), f.getType ()));
   }
 
@@ -497,18 +791,21 @@
     //System.out.println("isCallableFrom: "+expCls.getCanonicalName() + " <=? " + argCls.getCanonicalName());
     if (argCls == null)
       {
-        return!expCls.isPrimitive ();
+        return !expCls.isPrimitive ();
       }
-    else if (expCls.isAssignableFrom (argCls))
+
+    if (expCls.isAssignableFrom (argCls))
       {
         return true;
       }
-    else if ((isNumberClass (expCls) || isBooleanClass (expCls))
+
+    if ((isNumberClass (expCls) || isBooleanClass (expCls))
              && isNumberClass (argCls))
       {
         return true;
       }
-    else if (isCharClass (expCls) && argCls.equals (Character.class))
+
+   if (isCharClass (expCls) && argCls.equals (Character.class))
       {
         /*
           modified into a more strict check to avoid char to string matching
@@ -519,7 +816,8 @@
         */
         return true;
       }
-    else if (isStringClass (expCls) && argCls.equals (String.class))
+
+    if (expCls.equals (String.class) && argCls.equals (String.class))
       {
         /*
           added for strict String to String matching
@@ -531,63 +829,57 @@
         */
         return true;
       }
-    else if (expCls.isArray () && argCls.isArray ()
+
+    if (expCls.isArray () && argCls.isArray ()
              && isCallableFrom (expCls.getComponentType (),
                                 argCls.getComponentType ()))
       {
         return true;
       }
-    else if (expCls.equals (Object.class) && argCls.isPrimitive ())
-      {
-        return true;
-      }
-    else
-      {
-        return false;
-      }
+    
+    return expCls.equals (Object.class) && argCls.isPrimitive ();
+
   }
 
 
   private static boolean isNumberClass (Class cls)
   {
-    return (cls.equals (Integer.TYPE) || cls.equals (Integer.class)
-            || cls.equals (Short.TYPE) || cls.equals (Short.class)
-            || cls.equals (Long.TYPE) || cls.equals (Long.class)
-            || cls.equals (Float.TYPE) || cls.equals (Float.class)
-            || cls.equals (Double.TYPE) || cls.equals (Double.class));
+    // FIXME: seems as if Byte is missing. 
+    return cls.equals (Short.TYPE  ) || cls.equals (Short.class  )
+      ||   cls.equals (Integer.TYPE) || cls.equals (Integer.class)
+      ||   cls.equals (Long.TYPE   ) || cls.equals (Long.class   )
+      ||   cls.equals (Float.TYPE  ) || cls.equals (Float.class  )
+      ||   cls.equals (Double.TYPE ) || cls.equals (Double.class );
   }
 
 
   private static boolean isBooleanClass (Class cls)
   {
-    return (cls.equals (Boolean.class) || cls.equals (Boolean.TYPE));
+    return cls.equals (Boolean.class) || cls.equals (Boolean.TYPE);
   }
 
 
   private static boolean isCharClass (Class cls)
   {
-    return (cls.equals (Character.class) || cls.equals (Character.TYPE));
+    return cls.equals (Character.class) || cls.equals (Character.TYPE);
   }
 
 
-  /**
-   * Check whether the supplied class is a String class.
-   *
-   * Added for more strict char/string mathicng of method signatures
-   * Date: 28-08-2010
-   * Author: Martin Hepperle
-   * @param cls Class - the class to check
-   * @return boolean - true if clas is of class java.lang.String
-   */
-  private static boolean isStringClass (Class cls)
-  {
-    return (
-            cls.equals (String.class)
-            );
-  }
+  //   //  * Check whether the supplied class is a String class.
+  //  *
+  //  * Added for more strict char/string matching of method signatures
+  //  * Date: 28-08-2010
+  //  * Author: Martin Hepperle
+  //  * @param cls Class - the class to check
+  //  * @return boolean - true if clas is of class java.lang.String
+  //   // private static boolean isStringClass (Class cls)
+  // {
+  //   return cls.equals (String.class);
+  // }
 
 
-  private static Object[] castArguments (Object[] args, Class[] argTypes,
+  private static Object[] castArguments (Object[] args, 
+                                         Class[] argTypes,
                                          Class[] expTypes)
   {
     for (int i = 0; i < args.length; i++)
@@ -597,43 +889,51 @@
     return args;
   }
 
-
+  // FIXME: simply null if no success. 
+  // To be analyzed: isn't type just obj.getClass()? 
   private static Object castArgument (Object obj, Class type, Class expType)
   {
-    // System.out.println("expType:"+expType.getCanonicalName() + " <= type:" + type.getCanonicalName());
     if (type == null || expType.isAssignableFrom (type))
       {
         return obj;
       }
-    else if (isNumberClass (expType))
+    if (isNumberClass (expType))
       {
+        Number num = (Number)obj;
+        // FIXME: what if obj is null? 
+        // FIXME: seems as if Byte is missing as in isNumberClass 
+        if (expType.equals (Short.TYPE) || expType.equals (Short.class))
+          {
+            return Short  .valueOf(num. shortValue());
+          }
         if (expType.equals (Integer.TYPE) || expType.equals (Integer.class))
           {
-            return new Integer (((Number) obj).intValue ());
+            return Integer.valueOf(num.   intValue());
           }
-        else if (expType.equals (Double.TYPE) || expType.equals (Double.class))
+        if (expType.equals (Long.TYPE) || expType.equals (Long.class))
           {
-            return new Double (((Number) obj).doubleValue ());
+            return Long   .valueOf(num.  longValue());
           }
-        else if (expType.equals (Short.TYPE) || expType.equals (Short.class))
+        if (expType.equals (Float.TYPE) || expType.equals (Float.class))
           {
-            return new Short (((Number) obj).shortValue ());
+            return Float  .valueOf(num. floatValue());
           }
-        else if (expType.equals (Long.TYPE) || expType.equals (Long.class))
+        if (expType.equals (Double.TYPE) || expType.equals (Double.class))
           {
-            return new Long (((Number) obj).longValue ());
+            return Double .valueOf(num.doubleValue());
           }
-        else if (expType.equals (Float.TYPE) || expType.equals (Float.class))
-          {
-            return new Float (((Number) obj).floatValue ());
-          }
+        throw new IllegalStateException
+          ("Missing branch for byte? found "+expType);
       }
-    else if (isBooleanClass (expType))
+    if (isBooleanClass (expType))
       {
-        return new Boolean (((Number) obj).intValue () != 0);
+        // FIXME: what if obj is null? 
+        // FIXME: why is obj a Number here?? 
+        return Boolean.valueOf(((Number) obj).intValue () != 0);
       }
-    else if (isCharClass (expType))
+    if (isCharClass (expType))
       {
+        // FIXME: what if obj is null? 
         String s = obj.toString ();
         if (s.length () != 1)
           {
@@ -641,22 +941,37 @@
           }
         return new Character (s.charAt (0));
       }
-    else if (expType.isArray () && type.isArray ())
+    if (expType.isArray () && type.isArray ())
       {
-        return castArray (obj, type.getComponentType (),
+        // ensure that cast allows obj==null
+        return castArray (obj, 
+                          type   .getComponentType (),
                           expType.getComponentType ());
       }
-    else if (type.isPrimitive ())
+    if (type.isPrimitive ())
       {
+        // FIXME: appropriate?
         return obj;
       }
     return null;
   }
 
-
-  private static Object castArray (Object obj, Class elemType,
+  //! Cast the given array @c obj componentwise
+  //! from class @c elemType to @c elemExpType.
+  //!
+  //! @param obj
+  //!    the instance of an array.
+  //! @param elemType
+  //!    @c obj's class
+  //! @param elemExpType
+  //!    the target class to cast the entries of @c obj.
+  //! @throws IllegalArgumentException
+  //!    if obj is no array instance.
+  private static Object castArray (Object obj, 
+                                   Class elemType,
                                    Class elemExpType)
   {
+    // throws IllegalArgumentException if obj is not an array instance
     int len = Array.getLength (obj);
     Object result = Array.newInstance (elemExpType, len);
     for (int i = 0; i < len; i++)
@@ -668,68 +983,83 @@
   }
 
 
+  //! Return the mathematical dimension of @c cls. 
+  //! This is 0 if @c cls no array type or if @c null. 
   private static int getArrayClassNDims (Class cls)
   {
-    if (cls != null && cls.isArray ())
+    int res = 0;
+    while (cls != null && cls.isArray ()) 
       {
-        return (1 + getArrayClassNDims (cls.getComponentType ()));
+        res++;
+        cls = cls.getComponentType ();
       }
-    else
-      {
-        return 0;
-      }
+    return res;
+
+    // if (cls != null && cls.isArray ())
+    //   {
+    //     return (1 + getArrayClassNDims (cls.getComponentType ()));
+    //   }
+    // else
+    //   {
+    //     return 0;
+    //   }
   }
 
-
+  //! Return the innermost component type of @c cls. 
   private static Class getArrayElemClass (Class cls)
   {
-    if (cls.isArray ())
+
+    while (cls.isArray ()) 
       {
-        return getArrayElemClass (cls.getComponentType ());
+        cls = cls.getComponentType ();
       }
-    else
-      {
-        return cls;
-      }
+    return cls;
+
+
+    // if (cls.isArray ())
+    //   {
+    //     return getArrayElemClass (cls.getComponentType ());
+    //   }
+    // else
+    //   {
+    //     return cls;
+    //   }
   }
 
 
-  private static Object getArrayElements (Object array, int[][] idx,
+  private static Object getArrayElements (Object array, 
+                                          int[][] idx,
                                           int offset,
                                           int ndims, Class elemType)
   {
     if (offset >= ndims)
       {
         Object elem = Array.get (array, idx[offset][0]);
+        return (offset < idx.length - 1)
+          ? getArrayElements (elem, idx, offset + 1, ndims, elemType)
+          : elem;
+      }
+
+    Class compType = elemType.getComponentType ();
+    Object retval = Array.newInstance (compType, idx[offset].length);
+    for (int i = 0; i < idx[offset].length; i++)
+      {
+        Object elem = Array.get (array, idx[offset][i]);
         if (offset < idx.length - 1)
           {
-            return getArrayElements (elem, idx, offset + 1, ndims, elemType);
+            elem = getArrayElements (elem, idx, offset + 1, ndims, compType);
           }
-        else
-          {
-            return elem;
-          }
+        Array.set (retval, i, elem);
       }
-    else
-      {
-        Class compType = elemType.getComponentType ();
-        Object retval = Array.newInstance (compType, idx[offset].length);
-        for (int i = 0; i < idx[offset].length; i++)
-          {
-            Object elem = Array.get (array, idx[offset][i]);
-            if (offset < idx.length - 1)
-              {
-                elem = getArrayElements (elem, idx, offset + 1, ndims, compType);
-              }
-            Array.set (retval, i, elem);
-          }
-        return retval;
-      }
+    return retval;
+
   }
 
-
-  public static Object arraySubsref (Object obj, int[][] idx)
-    throws Exception
+  // Used by 
+  // #get_array_elements(JNIEnv*, jobject, octave_value_list&) 
+  // in @file ov-java.cc only and is recursive. 
+  //PMD: has an NPath complexity of 582
+  public static Object arraySubsref (Object obj, int[][] idx) // NOPMD
   {
     if (!obj.getClass ().isArray ())
       {
@@ -754,69 +1084,71 @@
             return retval;
           }
       }
-    else
+
+
+    int[] dims = new int[idx.length];
+    for (int i = 0; i < idx.length; i++)
       {
-        int[] dims = new int[idx.length];
-        for (int i = 0; i < idx.length; i++)
+        dims[i] = idx[i].length;
+      }
+
+    if (dims.length != getArrayClassNDims (obj.getClass ()))
+      {
+        throw new IllegalArgumentException ("index size mismatch");
+      }
+
+    /* resolve leading singletons */
+    Object theObj = obj;
+    int offset = 0;
+    while (dims[offset] == 1)
+      {
+        theObj = Array.get (theObj, idx[offset][0]);
+        offset = offset + 1;
+        if (offset >= dims.length)
           {
-            dims[i] = idx[i].length;
+            return theObj;
           }
+      }
+    if (offset > 0)
+      {
+        int[][] new_idx = new int[idx.length - offset][];
+        System.arraycopy (idx, offset, new_idx, 0, idx.length - offset);
+        return arraySubsref (theObj, new_idx);
+      }
 
-        if (dims.length != getArrayClassNDims (obj.getClass ()))
-          {
-            throw new IllegalArgumentException ("index size mismatch");
-          }
+    /* chop trailing singletons */
+    int ndims = dims.length;
+    while (ndims > 1 && dims[ndims - 1] == 1)
+      {
+        ndims--;
+      }
 
-        /* resolve leading singletons */
-        Object theObj = obj;
-        int offset = 0;
-        while (dims[offset] == 1)
-          {
-            theObj = Array.get (theObj, idx[offset][0]);
-            offset = offset + 1;
-            if (offset >= dims.length)
-              {
-                return theObj;
-              }
-          }
-        if (offset > 0)
-          {
-            int[][] new_idx = new int[idx.length - offset][];
-            System.arraycopy (idx, offset, new_idx, 0, idx.length - offset);
-            return arraySubsref (theObj, new_idx);
-          }
+    /* create result array */
+    Class elemClass = theObj.getClass ();
+    for (int i = 0; i <= (dims.length - ndims); i++)
+      {
+        elemClass = elemClass.getComponentType ();
+      }
+    Object retval = Array.newInstance (elemClass, dims[0]);
 
-        /* chop trailing singletons */
-        int ndims = dims.length;
-        while (ndims > 1 && dims[ndims - 1] == 1)
-          {
-            ndims--;
-          }
+    /* fill-in array */
+    for (int i = 0; i < idx[0].length; i++)
+      {
+        Object elem = getArrayElements (Array.get (theObj, idx[0][i]),
+                                        idx, 1, ndims, elemClass);
+        Array.set (retval, i, elem);
+      }
 
-        /* create result array */
-        Class elemClass = theObj.getClass ();
-        for (int i = 0; i <= (dims.length - ndims); i++)
-          {
-            elemClass = elemClass.getComponentType ();
-          }
-        Object retval = Array.newInstance (elemClass, dims[0]);
+    return retval;
 
-        /* fill-in array */
-        for (int i = 0; i < idx[0].length; i++)
-          {
-            Object elem = getArrayElements (Array.get (theObj, idx[0][i]),
-                                            idx, 1, ndims, elemClass);
-            Array.set (retval, i, elem);
-          }
-
-        return retval;
-      }
   }
 
 
-  private static Object setArrayElements (Object array, int[][] idx,
-                                          int offset, int ndims, Object rhs)
-    throws Exception
+  private static Object setArrayElements (Object array,
+                                          int[][] idx,
+                                          int offset, 
+                                          int ndims, 
+                                          Object rhs)
   {
     if (offset >= ndims)
       {
@@ -831,27 +1163,28 @@
           }
         return array;
       }
-    else
+
+    for (int i = 0; i < idx[offset].length; i++)
       {
-        for (int i = 0; i < idx[offset].length; i++)
+        if (offset < idx.length - 1)
           {
-            if (offset < idx.length - 1)
-              {
-                setArrayElements (Array.get (array, idx[offset][i]), idx,
-                                  offset + 1, ndims, Array.get (rhs, i));
-              }
-            else
-              {
-                Array.set (array, idx[offset][i], Array.get (rhs, i));
-              }
+            setArrayElements (Array.get (array, idx[offset][i]), idx,
+                              offset + 1, ndims, Array.get (rhs, i));
           }
-        return array;
+        else
+          {
+            Array.set (array, idx[offset][i], Array.get (rhs, i));
+          }
       }
+    return array;
   }
 
-
-  public static Object arraySubsasgn (Object obj, int[][] idx, Object rhs)
-    throws Exception
+  // PMD: has an NPath complexity of 294
+  // return value seems superfluous. 
+  // Used by @file ov-java.cc only and is recursive. 
+  public static Object arraySubsasgn (Object obj, // NOPMD
+                                      int[][] idx, 
+                                      Object rhs) 
   {
     if (!obj.getClass ().isArray ())
       {
@@ -862,67 +1195,95 @@
       {
         if (idx[0].length == 1)
           {
+            // throws IllegalArgumentException if obj is not an array 
             Array.set (obj, idx[0][0], rhs);
           }
         else
           {
             for (int i = 0; i < idx[0].length; i++)
               {
+                // throws IllegalArgumentException if obj is not an array 
                 Array.set (obj, idx[0][i], Array.get (rhs, i));
               }
           }
         return obj;
       }
-    else
+
+
+    int[] dims = new int[idx.length];
+    for (int i = 0; i < idx.length; i++)
       {
-        int[] dims = new int[idx.length];
-        for (int i = 0; i < idx.length; i++)
-          {
-            dims[i] = idx[i].length;
-          }
+        dims[i] = idx[i].length;
+      }
 
-        if (dims.length != getArrayClassNDims (obj.getClass ()))
-          {
-            throw new IllegalArgumentException ("index size mismatch");
-          }
+    if (dims.length != getArrayClassNDims (obj.getClass ()))
+      {
+        throw new IllegalArgumentException ("index size mismatch");
+      }
 
-        /* resolve leading singletons */
-        Object theObj = obj;
-        int offset = 0;
-        while (dims[offset] == 1 && offset < (dims.length - 1))
-          {
-            theObj = Array.get (theObj, idx[offset][0]);
-            offset = offset + 1;
-          }
-        if (offset > 0)
-          {
-            int[][] new_idx = new int[idx.length - offset][];
-            System.arraycopy (idx, offset, new_idx, 0, idx.length - offset);
-            arraySubsasgn (theObj, new_idx, rhs);
-            return obj;
-          }
-
-        /* chop trailing singletons */
-        int ndims = dims.length;
-        while (ndims > 1 && dims[ndims - 1] == 1)
-          {
-            ndims--;
-          }
-
-        for (int i = 0; i < idx[0].length; i++)
-          {
-            setArrayElements (Array.get (theObj, idx[0][i]), idx, 1, ndims,
-                              Array.get (rhs, i));
-          }
-
+    /* resolve leading singletons */
+    Object theObj = obj;
+    int offset = 0;
+    while (dims[offset] == 1 && offset < (dims.length - 1))
+      {
+        theObj = Array.get (theObj, idx[offset][0]);
+        offset = offset + 1;
+      }
+    if (offset > 0)
+      {
+        int[][] new_idx = new int[idx.length - offset][];
+        System.arraycopy (idx, offset, new_idx, 0, idx.length - offset);
+        arraySubsasgn (theObj, new_idx, rhs);
         return obj;
       }
+
+    /* chop trailing singletons */
+    int ndims = dims.length;
+    while (ndims > 1 && dims[ndims - 1] == 1)
+      {
+        ndims--;
+      }
+
+    for (int i = 0; i < idx[0].length; i++)
+      {
+        setArrayElements (Array.get (theObj, idx[0][i]), idx, 1, ndims,
+                          Array.get (rhs, i));
+      }
+
+    return obj;
   }
 
-
+  //! Return an array with entry type given by @c cls
+  //! with dimensions given by @c dims.
+  //! The class may be given directly as a @ref Class object
+  //! or as a string via its name.
+  //! Used by @c javaArray only.
+  //!
+  //! @param cls
+  //!    the atomic component class given as a class object or as a string.
+  //!    If given as a string, the class is loaded via #loader.
+  //! @param dims
+  //!    the dimensions which shall be non-negative but less than 256.
+  //! @return
+  //!    an array with the given component type.
+  //!    If @c cls is a string, the class is loaded by #loader.
+  //! @throws ClassNotFoundException
+  //!    if @c cls is a string representing a class name
+  //!    and if #loader could not find the according class.
+  // based on loader but only partially. 
+  // used by javaArray.m
   public static Object createArray (Object cls, int[] dims)
-    throws Exception
+    throws ClassNotFoundException
   {
+    // FIXME: seems as if used in javaArray.m only.  
+    // Then more appropriate seems split into two methods: 
+    // one with cls is a Class other one with cls is a String 
+    // FIXME: if a class is given directly, 
+    // it is not guaranteed, that this is loaded via #loader 
+    // So this shall be fixed. 
+    // Typically, different usages are treated in m file invoking error 
+    // in the last else branch. 
+    // This would be appropriate here also. 
     Class theClass;
     if (cls instanceof Class)
       {
@@ -930,6 +1291,7 @@
       }
     else if (cls instanceof String)
       {
+        // may throw ClassNotFoundException
         theClass = Class.forName ((String) cls, true, loader);
       }
     else
@@ -942,9 +1304,9 @@
   }
 
 
-  public static Object createArray (Object cls, int length)
-    throws Exception
-  {
-    return createArray (cls, new int[] {length});
-  }
+  // public static Object createArray (Object cls, int length)
+  //   throws ClassNotFoundException
+  // {
+  //   return createArray (cls, new int[] {length});
+  // }
 }
diff -r 46b67f1569b5 -r 94ccec9b749d scripts/java/org/octave/OctClassLoader.java
--- a/scripts/java/org/octave/OctClassLoader.java	Wed Aug 03 04:55:05 2016 +0100
+++ b/scripts/java/org/octave/OctClassLoader.java	Wed Aug 03 18:43:57 2016 +0200
@@ -24,16 +24,31 @@
 
 import java.io.File;
 
-public class OctClassLoader extends java.net.URLClassLoader
+import java.net.URL;
+import java.net.URLClassLoader;
+
+//! The system class loader for a Java virtual machines (JVM)
+//! created by Octave
+//! (see method <code>initialize_jvm</code> in <code>ov-java.cc</code>).
+//! This is used to load all classes from the dynamic class path.
+//! It is also used to load classes from the static class path
+//! delegating class loading to the parent classloader.
+//! <p>
+//! Class @ref ClassHelper uses @ref OctClassLoader to load classes
+//! for calling constructors and static methods
+//! and for accessing static fields.
+//! To add an entry of the classpath, invoke ::addURL(URL)
+//! whereas to remove an entry, a new classloader is created.
+public class OctClassLoader extends URLClassLoader
 {
   public OctClassLoader ()
   {
-    super (new java.net.URL[0]);
+    super (new URL[0]);
   }
 
   public OctClassLoader (ClassLoader parent)
   {
-    super (new java.net.URL[0], parent);
+    super (new URL[0], parent);
   }
 
   protected Class findClass (String name) throws ClassNotFoundException
@@ -47,27 +62,30 @@
     // Look dynamically into java.library.path, because Sun VM does
     // not do it (seems to cache initial java.library.path instead)
 
-    String[] paths = System.getProperty ("java.library.path").split (File.pathSeparator);
+    String[] paths = System.getProperty ("java.library.path")
+      .split (File.pathSeparator);
 
     libname = System.mapLibraryName (libname);
     for (int i = 0; i < paths.length; i++)
       {
         File f = new File (paths[i], libname);
         if (f.exists ())
-          return f.getAbsolutePath ();
+          {
+            return f.getAbsolutePath ();
+          }
       }
 
     return null;
   }
 
-  public void addClassPath (String name) throws Exception
-  {
-    java.io.File f = new java.io.File (name);
-    addURL (f.toURI ().toURL ());
-  }
+  // public void addClassPath (String name) throws MalformedURLException
+  // {
+  //   File f = new File (name);
+  //   addURL (f.toURI ().toURL ());
+  // }
 
   // new -MH-
-  public void addURL (java.net.URL url)
+  public void addURL (URL url)
   {
     super.addURL (url);
   }
# HG changeset patch
# User Mike Miller <mtmiller@octave.org>
# Date 1470244000 25200
#      Wed Aug 03 10:06:40 2016 -0700
# Node ID 2dcabdf6d08886057f0eda634b74325be31c2dec
# Parent  46b67f1569b58c7ce95a357b51afb710b279a8aa
Doxyfile.in: enable Java conditional code segments for doxygen

* Doxyfile.in (PREDEFINED): Add HAVE_JAVA to the list.

diff -r 46b67f1569b5 -r 2dcabdf6d088 doc/doxyhtml/Doxyfile.in
--- a/doc/doxyhtml/Doxyfile.in	Wed Aug 03 04:55:05 2016 +0100
+++ b/doc/doxyhtml/Doxyfile.in	Wed Aug 03 10:06:40 2016 -0700
@@ -222,6 +222,7 @@
              HAVE_FREETYPE=1        \
              HAVE_GLPK=1            \
              HAVE_HDF5=1            \
+             HAVE_JAVA=1            \
              HAVE_LLVM=1            \
              HAVE_MAGICK=1          \
              HAVE_OPENGL=1          \
# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1470244259 25200
#      Wed Aug 03 10:10:59 2016 -0700
# Node ID f094186125d3b887f7d8b167f528193493764e8a
# Parent  2dcabdf6d08886057f0eda634b74325be31c2dec
Only convert specific Java numeric objects to double for Matlab compatibility (bug #48013)

* ov-java.cc (is_auto_convertible_number): New function to test for numeric
object type.  (box): Use it to determine whether to return object's doubleValue.
Add doxygen documentation.

diff -r 2dcabdf6d088 -r f094186125d3 libinterp/octave-value/ov-java.cc
--- a/libinterp/octave-value/ov-java.cc	Wed Aug 03 10:06:40 2016 -0700
+++ b/libinterp/octave-value/ov-java.cc	Wed Aug 03 10:10:59 2016 -0700
@@ -1075,6 +1075,59 @@
 
 #define TO_JAVA(obj) dynamic_cast<octave_java*> ((obj).internal_rep ())
 
+//! Return whether @c jobj shall be automatically converted to an Octave
+//! numeric value.
+//!
+//! If @c jobj is an instance of any of the numeric wrapper classes @c Byte,
+//! @c Integer, @c Long, @c Short, @c Float, or @c Double, then it will be
+//! converted using the @c java.lang.Number.doubleValue() method.
+//!
+//! @param jobj Java object being returned to Octave
+//! @return @c true if @c jobj shall be converted into a numeric value
+//!         automatically, @c false otherwise
+static bool
+is_auto_convertible_number (JNIEnv *jni_env, jobject jobj)
+{
+  jclass_ref cls (jni_env);
+  cls = jni_env->FindClass ("java/lang/Double");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Float");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Byte");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Short");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Integer");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Long");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+
+  return false;
+}
+
+//! Convert the Java object pointed to by @c jobj_arg with class @c jcls_arg
+//! to an Octave value.
+//!
+//! @param jni_env JNI environment pointer
+//! @param jobj_arg pointer to a Java object
+//! @param jcls_arg optional pointer to the Java class of @c jobj_arg
+//! @return
+//!   @arg numeric value as a @c double if @c jobj_arg is of type @c Byte,
+//!     @c Short, @c Integer, @c Long, @c Float or @c Double
+//!   @arg logical value if @c jobj_arg is of type @c Boolean
+//!   @arg string value if @c jobj_arg is of type @c Character or @c String
+//!   @arg Octave array of numeric, logical, or char type if @c jobj_arg is
+//!     a Java array of primitive types
+//!   @arg Octave matrix if @c jobj_arg is of type @c org.octave.Matrix and
+//!     #Vjava_matrix_autoconversion is enabled
+//!   @arg Octave object if @c jobj_arg is of type @c org.octave.OctaveReference
+//!   @arg @c octave_java object wrapping the Java object otherwise
 static octave_value
 box (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg)
 {
@@ -1090,10 +1143,12 @@
 
   while (retval.is_undefined ())
     {
-      // Convert a scalar of any numeric class (byte, short, integer, long,
-      // float, double) to a double value.  Matlab does the same thing.
+      // Convert a scalar of any numeric class wrapping a primitive class
+      // (byte, short, integer, long, float, double) to a double value.
+      // Test whether java.lang.Number before testing for each type.
       cls = jni_env->FindClass ("java/lang/Number");
-      if (jni_env->IsInstanceOf (jobj, cls))
+      if (jni_env->IsInstanceOf (jobj, cls)
+          && is_auto_convertible_number (jni_env, jobj))
         {
           jmethodID m = jni_env->GetMethodID (cls, "doubleValue", "()D");
           retval = jni_env->CallDoubleMethod (jobj, m);
# HG changeset patch
# User Mike Miller <mtmiller@octave.org>
# Date 1470245021 25200
#      Wed Aug 03 10:23:41 2016 -0700
# Node ID 2f301a30aeedcc36a3358d59f3090c5b7e071f15
# Parent  f094186125d3b887f7d8b167f528193493764e8a
Add tests for Java numeric type conversion (bug #48013)

* ov-java.cc: Add %!tests for conversion of specific Java types to Octave
numeric types.

diff -r f094186125d3 -r 2f301a30aeed libinterp/octave-value/ov-java.cc
--- a/libinterp/octave-value/ov-java.cc	Wed Aug 03 10:10:59 2016 -0700
+++ b/libinterp/octave-value/ov-java.cc	Wed Aug 03 10:23:41 2016 -0700
@@ -3127,6 +3127,17 @@
 %! assert (class (javaObject ("java.lang.Long",    uint64 (1))), "java.lang.Long");
 %! assert (class (javaObject ("java.lang.Long",     int64 (1))), "java.lang.Long");
 
+## Test for automatic conversion of specific numeric classes (bug #48013)
+%!testif HAVE_JAVA
+%! assert (javaMethod ("valueOf", "java.lang.Byte",     int8 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Short",   int16 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Integer", int32 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Long",    int64 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Float",  single (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Double", double (1)), 1)
+%! assert (class (javaMethod ("valueOf", "java.math.BigDecimal", double (1))), "java.math.BigDecimal")
+%! assert (class (javaMethod ("valueOf", "java.math.BigInteger",  int64 (1))), "java.math.BigInteger")
+
 ## Automatic conversion from string cell array into String[] (bug #45290)
 %!testif HAVE_JAVA
 %! assert (javaMethod ("binarySearch", "java.util.Arrays", {"aaa", "bbb", "ccc", "zzz"}, "aaa"), 0);
# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1470248025 -7200
#      Wed Aug 03 20:13:45 2016 +0200
# Node ID a23bea7936e47cceed2765e90e4b069d2d729b6e
# Parent  94ccec9b749d28727066d7216b8df30071076c7c
# Parent  2f301a30aeedcc36a3358d59f3090c5b7e071f15
merge

diff -r 94ccec9b749d -r a23bea7936e4 doc/doxyhtml/Doxyfile.in
--- a/doc/doxyhtml/Doxyfile.in	Wed Aug 03 18:43:57 2016 +0200
+++ b/doc/doxyhtml/Doxyfile.in	Wed Aug 03 20:13:45 2016 +0200
@@ -222,6 +222,7 @@
              HAVE_FREETYPE=1        \
              HAVE_GLPK=1            \
              HAVE_HDF5=1            \
+             HAVE_JAVA=1            \
              HAVE_LLVM=1            \
              HAVE_MAGICK=1          \
              HAVE_OPENGL=1          \
diff -r 94ccec9b749d -r a23bea7936e4 libinterp/octave-value/ov-java.cc
--- a/libinterp/octave-value/ov-java.cc	Wed Aug 03 18:43:57 2016 +0200
+++ b/libinterp/octave-value/ov-java.cc	Wed Aug 03 20:13:45 2016 +0200
@@ -1075,6 +1075,59 @@
 
 #define TO_JAVA(obj) dynamic_cast<octave_java*> ((obj).internal_rep ())
 
+//! Return whether @c jobj shall be automatically converted to an Octave
+//! numeric value.
+//!
+//! If @c jobj is an instance of any of the numeric wrapper classes @c Byte,
+//! @c Integer, @c Long, @c Short, @c Float, or @c Double, then it will be
+//! converted using the @c java.lang.Number.doubleValue() method.
+//!
+//! @param jobj Java object being returned to Octave
+//! @return @c true if @c jobj shall be converted into a numeric value
+//!         automatically, @c false otherwise
+static bool
+is_auto_convertible_number (JNIEnv *jni_env, jobject jobj)
+{
+  jclass_ref cls (jni_env);
+  cls = jni_env->FindClass ("java/lang/Double");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Float");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Byte");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Short");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Integer");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+  cls = jni_env->FindClass ("java/lang/Long");
+  if (jni_env->IsInstanceOf (jobj, cls))
+    return true;
+
+  return false;
+}
+
+//! Convert the Java object pointed to by @c jobj_arg with class @c jcls_arg
+//! to an Octave value.
+//!
+//! @param jni_env JNI environment pointer
+//! @param jobj_arg pointer to a Java object
+//! @param jcls_arg optional pointer to the Java class of @c jobj_arg
+//! @return
+//!   @arg numeric value as a @c double if @c jobj_arg is of type @c Byte,
+//!     @c Short, @c Integer, @c Long, @c Float or @c Double
+//!   @arg logical value if @c jobj_arg is of type @c Boolean
+//!   @arg string value if @c jobj_arg is of type @c Character or @c String
+//!   @arg Octave array of numeric, logical, or char type if @c jobj_arg is
+//!     a Java array of primitive types
+//!   @arg Octave matrix if @c jobj_arg is of type @c org.octave.Matrix and
+//!     #Vjava_matrix_autoconversion is enabled
+//!   @arg Octave object if @c jobj_arg is of type @c org.octave.OctaveReference
+//!   @arg @c octave_java object wrapping the Java object otherwise
 static octave_value
 box (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg)
 {
@@ -1090,10 +1143,12 @@
 
   while (retval.is_undefined ())
     {
-      // Convert a scalar of any numeric class (byte, short, integer, long,
-      // float, double) to a double value.  Matlab does the same thing.
+      // Convert a scalar of any numeric class wrapping a primitive class
+      // (byte, short, integer, long, float, double) to a double value.
+      // Test whether java.lang.Number before testing for each type.
       cls = jni_env->FindClass ("java/lang/Number");
-      if (jni_env->IsInstanceOf (jobj, cls))
+      if (jni_env->IsInstanceOf (jobj, cls)
+          && is_auto_convertible_number (jni_env, jobj))
         {
           jmethodID m = jni_env->GetMethodID (cls, "doubleValue", "()D");
           retval = jni_env->CallDoubleMethod (jobj, m);
@@ -3072,6 +3127,17 @@
 %! assert (class (javaObject ("java.lang.Long",    uint64 (1))), "java.lang.Long");
 %! assert (class (javaObject ("java.lang.Long",     int64 (1))), "java.lang.Long");
 
+## Test for automatic conversion of specific numeric classes (bug #48013)
+%!testif HAVE_JAVA
+%! assert (javaMethod ("valueOf", "java.lang.Byte",     int8 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Short",   int16 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Integer", int32 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Long",    int64 (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Float",  single (1)), 1)
+%! assert (javaMethod ("valueOf", "java.lang.Double", double (1)), 1)
+%! assert (class (javaMethod ("valueOf", "java.math.BigDecimal", double (1))), "java.math.BigDecimal")
+%! assert (class (javaMethod ("valueOf", "java.math.BigInteger",  int64 (1))), "java.math.BigInteger")
+
 ## Automatic conversion from string cell array into String[] (bug #45290)
 %!testif HAVE_JAVA
 %! assert (javaMethod ("binarySearch", "java.util.Arrays", {"aaa", "bbb", "ccc", "zzz"}, "aaa"), 0);
# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1470258074 -7200
#      Wed Aug 03 23:01:14 2016 +0200
# Node ID fafe2c4289d968a900af8611cc614aa29fadcc24
# Parent  a23bea7936e47cceed2765e90e4b069d2d729b6e
just reformatting to make source more readable,
e.g. kept line lengths.

diff -r a23bea7936e4 -r fafe2c4289d9 libinterp/octave-value/ov-java.cc
--- a/libinterp/octave-value/ov-java.cc	Wed Aug 03 20:13:45 2016 +0200
+++ b/libinterp/octave-value/ov-java.cc	Wed Aug 03 23:01:14 2016 +0200
@@ -818,15 +818,21 @@
             {
               jclass_ref syscls (jni_env,
                                  jni_env->FindClass ("java/lang/System"));
-              jmethodID mID = jni_env->GetStaticMethodID (syscls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
-              jstring_ref js (jni_env, jni_env->NewStringUTF ("octave.class.loader"));
-              js = reinterpret_cast<jstring> (jni_env->CallStaticObjectMethod (syscls, mID, jstring (js)));
+              jmethodID mID = jni_env->GetStaticMethodID 
+                (syscls, 
+                 "getProperty", 
+                 "(Ljava/lang/String;)Ljava/lang/String;");
+              jstring_ref js (jni_env, 
+                              jni_env->NewStringUTF ("octave.class.loader"));
+              js = reinterpret_cast<jstring> (jni_env->CallStaticObjectMethod 
+                                              (syscls, mID, jstring (js)));
               class_loader = jstring_to_string (jni_env, jstring (js));
               std::replace (class_loader.begin (), class_loader.end (),
                             '.', '/');
             }
 
-          jclass_ref uicls (jni_env, jni_env->FindClass (class_loader.c_str ()));
+          jclass_ref uicls (jni_env, 
+                            jni_env->FindClass (class_loader.c_str ()));
 
           if (! uicls)
             {
@@ -835,27 +841,39 @@
               // Try the netbeans way
               std::replace (class_loader.begin (), class_loader.end (),
                             '/', '.');
-              jclass_ref jcls2 (jni_env, jni_env->FindClass ("org/openide/util/Lookup"));
-              jmethodID mID = jni_env->GetStaticMethodID (jcls2, "getDefault", "()Lorg/openide/util/Lookup;");
-              jobject_ref lObj (jni_env, jni_env->CallStaticObjectMethod (jcls2, mID));
+              jclass_ref jcls2 (jni_env, 
+                                jni_env->FindClass ("org/openide/util/Lookup"));
+              jmethodID mID = jni_env->GetStaticMethodID 
+                (jcls2, "getDefault", "()Lorg/openide/util/Lookup;");
+              jobject_ref lObj (jni_env, 
+                                jni_env->CallStaticObjectMethod (jcls2, mID));
               mID = jni_env->GetMethodID (jcls2, "lookup",
                                           "(Ljava/lang/Class;)Ljava/lang/Object;");
-              jclass_ref cLoaderCls (jni_env, jni_env->FindClass ("java/lang/ClassLoader"));
-              jobject_ref cLoader (jni_env, jni_env->CallObjectMethod (lObj, mID, jclass (cLoaderCls)));
-              mID = jni_env->GetMethodID (cLoaderCls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
-              jstring_ref js (jni_env, jni_env->NewStringUTF (class_loader.c_str ()));
-              uicls = reinterpret_cast<jclass> (jni_env->CallObjectMethod (cLoader, mID, jstring (js)));
+              jclass_ref cLoaderCls (jni_env, 
+                                     jni_env->FindClass ("java/lang/ClassLoader"));
+              jobject_ref cLoader (jni_env, 
+                                   jni_env->CallObjectMethod 
+                                   (lObj, mID, jclass (cLoaderCls)));
+              mID = jni_env->GetMethodID (cLoaderCls, "loadClass", 
+                                          "(Ljava/lang/String;)Ljava/lang/Class;");
+              jstring_ref js (jni_env, 
+                              jni_env->NewStringUTF (class_loader.c_str ()));
+              uicls = reinterpret_cast<jclass> 
+                (jni_env->CallObjectMethod (cLoader, mID, jstring (js)));
             }
 
           if (uicls)
-            uiClass = reinterpret_cast<jclass> (jni_env->NewGlobalRef (jclass (uicls)));
+            uiClass = reinterpret_cast<jclass> 
+              (jni_env->NewGlobalRef (jclass (uicls)));
         }
 
       if (uiClass)
         {
-          jmethodID mID = jni_env->GetStaticMethodID (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+          jmethodID mID = jni_env->GetStaticMethodID 
+            (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
           jstring_ref js (jni_env, jni_env->NewStringUTF (name));
-          jcls = reinterpret_cast<jclass> (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js)));
+          jcls = reinterpret_cast<jclass> 
+            (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js)));
         }
     }
 
@@ -869,7 +887,9 @@
   jclass_ref jcls (jni_env, jni_env->GetObjectClass (obj));
   jclass_ref ccls (jni_env, jni_env->GetObjectClass (jcls));
   jmethodID isArray_ID = jni_env->GetMethodID (ccls, "isArray", "()Z");
-  jmethodID getComponentType_ID = jni_env->GetMethodID (ccls, "getComponentType", "()Ljava/lang/Class;");
+  jmethodID getComponentType_ID = jni_env->GetMethodID (ccls, 
+                                                        "getComponentType", 
+                                                        "()Ljava/lang/Class;");
 
   dim_vector dv (1, 1);
   int idx = 0;
@@ -881,8 +901,12 @@
       if (idx >= dv.ndims ())
         dv.resize (idx+1);
       dv(idx) = len;
-      jcls = reinterpret_cast<jclass> (jni_env->CallObjectMethod (jcls, getComponentType_ID));
-      jobj = (len > 0 ? reinterpret_cast<jobjectArray> (jni_env->GetObjectArrayElement (jobj, 0)) : 0);
+      jcls = reinterpret_cast<jclass> 
+        (jni_env->CallObjectMethod (jcls, getComponentType_ID));
+      jobj = len > 0 
+        ? reinterpret_cast<jobjectArray> (jni_env->GetObjectArrayElement (jobj,
+                                                                          0)) 
+        : 0;
       idx++;
     }
 
@@ -896,7 +920,9 @@
 {
   jclass_ref ocls (jni_env, jni_env->FindClass ("[I"));
   jobjectArray retval = jni_env->NewObjectArray (idx.length (), ocls, 0);
-
+ // Here retval has the same length as idx 
+
+  // Fill in entries of idx into retval 
   for (int i = 0; i < idx.length (); i++)
     try
       {
@@ -904,10 +930,13 @@
 
         jintArray_ref i_array (jni_env, jni_env->NewIntArray (v.length ()));
         jint *buf = jni_env->GetIntArrayElements (i_array, 0);
-
+        // Here, buf points to the beginning of i_array  
+
+        // Copy v to buf 
         for (int k = 0; k < v.length (); k++)
           buf[k] = v(k);
 
+        // set retval[i]=i_array 
         jni_env->ReleaseIntArrayElements (i_array, buf, 0);
         jni_env->SetObjectArrayElement (retval, i, i_array);
 
@@ -931,9 +960,14 @@
   jobject_ref resObj (jni_env);
   jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));
 
-  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
-  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsref", "(Ljava/lang/Object;[[I)Ljava/lang/Object;");
-  resObj = jni_env->CallStaticObjectMethod (helperClass, mID, jobj, jobject (java_idx));
+  jclass_ref helperClass (jni_env, 
+                          find_octave_class (jni_env, 
+                                             "org/octave/ClassHelper"));
+  jmethodID mID = jni_env
+    ->GetStaticMethodID (helperClass, "arraySubsref", 
+                         "(Ljava/lang/Object;[[I)Ljava/lang/Object;");
+  resObj = jni_env->CallStaticObjectMethod 
+    (helperClass, mID, jobj, jobject (java_idx));
 
   if (resObj)
     retval = box (jni_env, resObj);
@@ -958,11 +992,13 @@
 
   if (unbox (jni_env, rhs, rhsObj, rhsCls))
     {
-      jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
+      jclass_ref helperClass (jni_env, 
+                              find_octave_class (jni_env, 
+                                                 "org/octave/ClassHelper"));
       jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsasgn",
-          "(Ljava/lang/Object;[[ILjava/lang/Object;)Ljava/lang/Object;");
-      resObj = jni_env->CallStaticObjectMethod (helperClass, mID,
-          jobj, jobject (java_idx), jobject (rhsObj));
+          "(Ljava/lang/Object;[[ILjava/lang/Object;)" "Ljava/lang/Object;");
+      resObj = jni_env->CallStaticObjectMethod 
+        (helperClass, mID, jobj, jobject (java_idx), jobject (rhsObj));
     }
 
   if (resObj)
@@ -986,28 +1022,43 @@
     {
       jclass_ref cls (jni_env, jni_env->GetObjectClass (jobj));
       jclass_ref ccls (jni_env, jni_env->GetObjectClass (cls));
-      jmethodID getMethods_ID = jni_env->GetMethodID (ccls, "getMethods", "()[Ljava/lang/reflect/Method;");
-      jmethodID getFields_ID = jni_env->GetMethodID (ccls, "getFields", "()[Ljava/lang/reflect/Field;");
-      jobjectArray_ref mList (jni_env, reinterpret_cast<jobjectArray> (jni_env->CallObjectMethod (cls, getMethods_ID)));
-      jobjectArray_ref fList (jni_env, reinterpret_cast<jobjectArray> (jni_env->CallObjectMethod (cls, getFields_ID)));
+      jmethodID getMethods_ID = jni_env->GetMethodID 
+        (ccls, "getMethods", "()[Ljava/lang/reflect/Method;");
+      jmethodID getFields_ID = jni_env->GetMethodID 
+        (ccls, "getFields", "()[Ljava/lang/reflect/Field;");
+      jobjectArray_ref mList (jni_env, 
+                              reinterpret_cast<jobjectArray> 
+                              (jni_env->CallObjectMethod (cls, getMethods_ID)));
+      jobjectArray_ref fList (jni_env, 
+                              reinterpret_cast<jobjectArray> 
+                              (jni_env->CallObjectMethod (cls, getFields_ID)));
       int mLen = jni_env->GetArrayLength (mList);
       int fLen = jni_env->GetArrayLength (fList);
-      jclass_ref mCls (jni_env, jni_env->FindClass ("java/lang/reflect/Method"));
-      jclass_ref fCls (jni_env, jni_env->FindClass ("java/lang/reflect/Field"));
-      jmethodID m_getName_ID = jni_env->GetMethodID (mCls, "getName", "()Ljava/lang/String;");
-      jmethodID f_getName_ID = jni_env->GetMethodID (fCls, "getName", "()Ljava/lang/String;");
+      jclass_ref mCls (jni_env, 
+                       jni_env->FindClass ("java/lang/reflect/Method"));
+      jclass_ref fCls (jni_env, 
+                       jni_env->FindClass ("java/lang/reflect/Field"));
+      jmethodID m_getName_ID = jni_env->GetMethodID (mCls, "getName", 
+                                                     "()Ljava/lang/String;");
+      jmethodID f_getName_ID = jni_env->GetMethodID (fCls, "getName", 
+                                                     "()Ljava/lang/String;");
 
       for (int i = 0; i < mLen; i++)
         {
           jobject_ref meth (jni_env, jni_env->GetObjectArrayElement (mList, i));
-          jstring_ref methName (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (meth, m_getName_ID)));
+          jstring_ref methName (jni_env, reinterpret_cast<jstring> 
+                                (jni_env->CallObjectMethod (meth, m_getName_ID)));
           name_list.push_back (jstring_to_string (jni_env, methName));
         }
 
       for (int i = 0; i < fLen; i++)
         {
-          jobject_ref field (jni_env, jni_env->GetObjectArrayElement (fList, i));
-          jstring_ref fieldName (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (field, f_getName_ID)));
+          jobject_ref field (jni_env, 
+                             jni_env->GetObjectArrayElement (fList, i));
+          jstring_ref fieldName (jni_env, 
+                                 reinterpret_cast<jstring> 
+                                 (jni_env->CallObjectMethod 
+                                  (field, f_getName_ID)));
           name_list.push_back (jstring_to_string (jni_env, fieldName));
         }
 
@@ -1042,7 +1093,9 @@
 
               for (int i = 0; i < len; i++)
                 {
-                  jstring_ref js (jni_env, reinterpret_cast<jstring> (jni_env->GetObjectArrayElement (array, i)));
+                  jstring_ref js (jni_env, 
+                                  reinterpret_cast<jstring> 
+                                  (jni_env->GetObjectArrayElement (array, i)));
 
                   if (js)
                     c(i) = octave_value (jstring_to_string (jni_env, js), type);
@@ -1055,8 +1108,11 @@
           else
             {
               cls = jni_env->FindClass ("java/lang/Object");
-              jmethodID mID = jni_env->GetMethodID (cls, "toString", "()Ljava/lang/String;");
-              jstring_ref js (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (java_object, mID)));
+              jmethodID mID = jni_env->GetMethodID (cls, "toString", 
+                                                    "()Ljava/lang/String;");
+              jstring_ref js (jni_env, 
+                              reinterpret_cast<jstring> 
+                              (jni_env->CallObjectMethod (java_object, mID)));
 
               if (js)
                 retval = octave_value (jstring_to_string (jni_env, js), type);
@@ -1210,7 +1266,9 @@
           if (jni_env->IsInstanceOf (jobj, cls))
             {
               jmethodID mID = jni_env->GetMethodID (cls, "getDims", "()[I");
-              jintArray_ref iv (jni_env, reinterpret_cast<jintArray> (jni_env->CallObjectMethod (jobj, mID)));
+              jintArray_ref iv (jni_env, 
+                                reinterpret_cast<jintArray> 
+                                (jni_env->CallObjectMethod (jobj, mID)));
               jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0);
               dim_vector dims;
               dims.resize (jni_env->GetArrayLength (jintArray (iv)));
@@ -1219,8 +1277,11 @@
                 dims(i) = iv_data[i];
 
               jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);
-              mID = jni_env->GetMethodID (cls, "getClassName", "()Ljava/lang/String;");
-              jstring_ref js (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (jobj, mID)));
+              mID = jni_env->GetMethodID (cls, "getClassName", 
+                                          "()Ljava/lang/String;");
+              jstring_ref js (jni_env, 
+                              reinterpret_cast<jstring> 
+                              (jni_env->CallObjectMethod (jobj, mID)));
 
               std::string s = jstring_to_string (jni_env, js);
 
@@ -1228,8 +1289,12 @@
                 {
                   NDArray m (dims);
                   mID = jni_env->GetMethodID (cls, "toDouble", "()[D");
-                  jdoubleArray_ref dv (jni_env, reinterpret_cast<jdoubleArray> (jni_env->CallObjectMethod (jobj, mID)));
-                  jni_env->GetDoubleArrayRegion (dv, 0, m.numel (), m.fortran_vec ());
+                  jdoubleArray_ref dv (jni_env, 
+                                       reinterpret_cast<jdoubleArray> 
+                                       (jni_env->CallObjectMethod (jobj, mID)));
+                  jni_env->GetDoubleArrayRegion (dv, 0, 
+                                                 m.numel (), 
+                                                 m.fortran_vec ());
                   retval = m;
                   break;
                 }
@@ -1239,8 +1304,13 @@
                     {
                       uint8NDArray m (dims);
                       mID = jni_env->GetMethodID (cls, "toByte", "()[B");
-                      jbyteArray_ref dv (jni_env, reinterpret_cast<jbyteArray> (jni_env->CallObjectMethod (jobj, mID)));
-                      jni_env->GetByteArrayRegion (dv, 0, m.numel (), reinterpret_cast<jbyte *> (m.fortran_vec ()));
+                      jbyteArray_ref dv (jni_env, 
+                                         reinterpret_cast<jbyteArray> 
+                                         (jni_env->CallObjectMethod (jobj, 
+                                                                     mID)));
+                      jni_env->GetByteArrayRegion (dv, 0, m.numel (), 
+                                                   reinterpret_cast<jbyte *> 
+                                                   (m.fortran_vec ()));
                       retval = m;
                       break;
                     }
@@ -1248,8 +1318,13 @@
                     {
                       int8NDArray m (dims);
                       mID = jni_env->GetMethodID (cls, "toByte", "()[B");
-                      jbyteArray_ref dv (jni_env, reinterpret_cast<jbyteArray> (jni_env->CallObjectMethod (jobj, mID)));
-                      jni_env->GetByteArrayRegion (dv, 0, m.numel (), reinterpret_cast<jbyte *> (m.fortran_vec ()));
+                      jbyteArray_ref dv (jni_env, 
+                                         reinterpret_cast<jbyteArray> 
+                                         (jni_env->CallObjectMethod (jobj, 
+                                                                     mID)));
+                      jni_env->GetByteArrayRegion (dv, 0, m.numel (), 
+                                                   reinterpret_cast<jbyte *> 
+                                                   (m.fortran_vec ()));
                       retval = m;
                       break;
                     }
@@ -1269,8 +1344,13 @@
                     {
                       int32NDArray m (dims);
                       mID = jni_env->GetMethodID (cls, "toInt", "()[I");
-                      jintArray_ref dv (jni_env, reinterpret_cast<jintArray> (jni_env->CallObjectMethod (jobj, mID)));
-                      jni_env->GetIntArrayRegion (dv, 0, m.numel (), reinterpret_cast<jint *> (m.fortran_vec ()));
+                      jintArray_ref dv (jni_env, 
+                                        reinterpret_cast<jintArray> 
+                                        (jni_env->CallObjectMethod (jobj, 
+                                                                    mID)));
+                      jni_env->GetIntArrayRegion (dv, 0, m.numel (), 
+                                                  reinterpret_cast<jint *> 
+                                                  (m.fortran_vec ()));
                       retval = m;
                       break;
                     }
@@ -1287,7 +1367,6 @@
 
           if (it != octave_ref_map.end ())
             retval = it->second;
-
           break;
         }
 
@@ -1350,14 +1429,17 @@
                   for (int r = 0; r < rows; r++)
                     {
                       jdoubleArray_ref row (jni_env,
-                                            reinterpret_cast<jdoubleArray> (jni_env->GetObjectArrayElement (jarr, r)));
+                                            reinterpret_cast<jdoubleArray> 
+                                            (jni_env->GetObjectArrayElement 
+                                             (jarr, r)));
 
                       if (m.is_empty ())
                         {
                           cols = jni_env->GetArrayLength (row);
                           m.resize (cols, rows);
                         }
-                      jni_env->GetDoubleArrayRegion (row, 0, cols, m.fortran_vec () + r * cols);
+                      jni_env->GetDoubleArrayRegion 
+                        (row, 0, cols, m.fortran_vec () + r * cols);
                     }
                   retval = m.transpose ();
                 }
@@ -1379,7 +1461,8 @@
               for (int i = 0; i < len; i++)
                 {
                   jstring_ref js (jni_env,
-                                  reinterpret_cast<jstring> (jni_env->GetObjectArrayElement (jarr, i)));
+                                  reinterpret_cast<jstring> 
+                                  (jni_env->GetObjectArrayElement (jarr, i)));
                   m(i) = jstring_to_string (jni_env, js);
                 }
 
@@ -1426,7 +1509,8 @@
 
       for (octave_idx_type i = 0; i < n; i++)
         {
-          jstring_ref jstr (jni_env, jni_env->NewStringUTF (str_arr(i).c_str ()));
+          jstring_ref jstr (jni_env, jni_env->NewStringUTF 
+                            (str_arr(i).c_str ()));
           jni_env->SetObjectArrayElement (array, i, jstr);
         }
 
@@ -1538,9 +1622,11 @@
       jcls = jni_env->GetObjectClass (jobj);
     }
   else if (Vjava_matrix_autoconversion
-           && (val.is_matrix_type () || val.is_range ()) && val.is_real_type ())
+           && (val.is_matrix_type () || val.is_range ()) 
+           && val.is_real_type ())
     {
-      jclass_ref mcls (jni_env, find_octave_class (jni_env, "org/octave/Matrix"));
+      jclass_ref mcls (jni_env, find_octave_class (jni_env, 
+                                                   "org/octave/Matrix"));
       dim_vector dims = val.dims ();
       jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.ndims ()));
       jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0);
@@ -1566,9 +1652,11 @@
           int8NDArray m = val.int8_array_value ();
           jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));
           jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),
-                                       reinterpret_cast<jbyte *> (m.fortran_vec ()));
+                                       reinterpret_cast<jbyte *> 
+                                       (m.fortran_vec ()));
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
-          jobj = jni_env->NewObject (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
+          jobj = jni_env->NewObject 
+            (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
           jcls = jni_env->GetObjectClass (jobj);
         }
       else if (val.is_uint8_type ())
@@ -1576,9 +1664,11 @@
           uint8NDArray m = val.uint8_array_value ();
           jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));
           jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),
-                                       reinterpret_cast<jbyte *> (m.fortran_vec ()));
+                                       reinterpret_cast<jbyte *> 
+                                       (m.fortran_vec ()));
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
-          jobj = jni_env->NewObject (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
+          jobj = jni_env->NewObject 
+            (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
           jcls = jni_env->GetObjectClass (jobj);
         }
       else if (val.is_int32_type ())
@@ -1586,15 +1676,18 @@
           int32NDArray m = val.int32_array_value ();
           jintArray_ref v (jni_env, jni_env->NewIntArray (m.numel ()));
           jni_env->SetIntArrayRegion (jintArray (v), 0, m.numel (),
-                                      reinterpret_cast<jint *> (m.fortran_vec ()));
+                                      reinterpret_cast<jint *> 
+                                      (m.fortran_vec ()));
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([I[I)V");
-          jobj = jni_env->NewObject (jclass (mcls), mID, jintArray (v), jintArray (iv));
+          jobj = jni_env->NewObject 
+            (jclass (mcls), mID, jintArray (v), jintArray (iv));
           jcls = jni_env->GetObjectClass (jobj);
         }
       else
         {
           found = false;
-          error ("cannot convert matrix of type '%s'", val.class_name ().c_str ());
+          error ("cannot convert matrix of type '%s'", 
+                 val.class_name ().c_str ());
         }
     }
   else
@@ -1648,7 +1741,8 @@
   if (jni_env)
     {
       jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/Thread"));
-      jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread", "()Ljava/lang/Thread;");
+      jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread", 
+                                                  "()Ljava/lang/Thread;");
       jobject_ref jthread (jni_env, jni_env->CallStaticObjectMethod (cls, mID));
 
       if (jthread)
@@ -1671,8 +1765,10 @@
 
   if (current_env)
     {
-      jclass_ref cls (current_env, find_octave_class (current_env, "org/octave/Octave"));
-      jmethodID mID = current_env->GetStaticMethodID (cls, "checkPendingAction", "()V");
+      jclass_ref cls (current_env, find_octave_class (current_env, 
+                                                      "org/octave/Octave"));
+      jmethodID mID = current_env->GetStaticMethodID 
+        (cls, "checkPendingAction", "()V");
       current_env->CallStaticVoidMethod (cls, mID);
 
       octave_set_default_fpucw ();
@@ -1896,7 +1992,8 @@
 
     case '(':
       if (current_env)
-        retval = get_array_elements (current_env, TO_JOBJECT (to_java ()), idx.front ());
+        retval = get_array_elements 
+          (current_env, TO_JOBJECT (to_java ()), idx.front ());
       break;
 
     default:
@@ -1984,7 +2081,8 @@
     case '(':
       if (current_env)
         {
-          set_array_elements (current_env, TO_JOBJECT (to_java ()), idx.front (), rhs);
+          set_array_elements (current_env, TO_JOBJECT (to_java ()), 
+                              idx.front (), rhs);
 
           count++;
           retval = octave_value (this);
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470338427 -3600
#      Thu Aug 04 20:20:27 2016 +0100
# Node ID 469c817eb2560e93208a10b267c35c4bccd46bf3
# Parent  2f301a30aeedcc36a3358d59f3090c5b7e071f15
svd: reduce code duplication with more use of template and macro.

* liboctave/numeric/svd.cc, liboctave/numeric/svd.h: remove unused
constructor with reference for int (info).  This allows to move all
of the constructor into a single template, so remove init().  Two
new methods, gesvd and gesdd, are fully specialized but the main
hunck of code are the long list of arguments.  Scope type and drive
enums to the svd class for clarity, and rename member names.  Add
a new member for the drive used.
* libinterp/corefcn/svd.cc: fix typenames for the svd enums which
are now scoped.
* CMatrix.cc, dMatrix.cc, fCMatrix.cc, fMatrix.cc: fix typenames
for the svd enums which are now scoped.

diff -r 2f301a30aeed -r 469c817eb256 libinterp/corefcn/svd.cc
--- a/libinterp/corefcn/svd.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/libinterp/corefcn/svd.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -37,19 +37,19 @@
 static std::string Vsvd_driver = "gesvd";
 
 template <typename T>
-static typename svd<T>::type
+static typename svd<T>::Type
 svd_type (int nargin, int nargout)
 {
   return ((nargout == 0 || nargout == 1)
-          ? svd<T>::sigma_only
-          : (nargin == 2) ? svd<T>::economy : svd<T>::std);
+          ? svd<T>::Type::sigma_only
+          : (nargin == 2) ? svd<T>::Type::economy : svd<T>::Type::std);
 }
 
 template <typename T>
-static typename svd<T>::driver
+static typename svd<T>::Driver
 svd_driver (void)
 {
-  return Vsvd_driver == "gesvd" ? svd<T>::GESVD : svd<T>::GESDD;
+  return Vsvd_driver == "gesvd" ? svd<T>::Driver::GESVD : svd<T>::Driver::GESDD;
 }
 
 DEFUN (svd, args, nargout,
diff -r 2f301a30aeed -r 469c817eb256 liboctave/array/CMatrix.cc
--- a/liboctave/array/CMatrix.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/array/CMatrix.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -1139,7 +1139,7 @@
 {
   ComplexMatrix retval;
 
-  svd<ComplexMatrix> result (*this, svd<ComplexMatrix>::economy);
+  svd<ComplexMatrix> result (*this, svd<ComplexMatrix>::Type::economy);
 
   DiagMatrix S = result.singular_values ();
   ComplexMatrix U = result.left_singular_matrix ();
diff -r 2f301a30aeed -r 469c817eb256 liboctave/array/dMatrix.cc
--- a/liboctave/array/dMatrix.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/array/dMatrix.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -823,7 +823,7 @@
 Matrix
 Matrix::pseudo_inverse (double tol) const
 {
-  svd<Matrix> result (*this, svd<Matrix>::economy);
+  svd<Matrix> result (*this, svd<Matrix>::Type::economy);
 
   DiagMatrix S = result.singular_values ();
   Matrix U = result.left_singular_matrix ();
diff -r 2f301a30aeed -r 469c817eb256 liboctave/array/fCMatrix.cc
--- a/liboctave/array/fCMatrix.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/array/fCMatrix.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -1144,7 +1144,7 @@
 {
   FloatComplexMatrix retval;
 
-  svd<FloatComplexMatrix> result (*this, svd<FloatComplexMatrix>::economy);
+  svd<FloatComplexMatrix> result (*this, svd<FloatComplexMatrix>::Type::economy);
 
   FloatDiagMatrix S = result.singular_values ();
   FloatComplexMatrix U = result.left_singular_matrix ();
diff -r 2f301a30aeed -r 469c817eb256 liboctave/array/fMatrix.cc
--- a/liboctave/array/fMatrix.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/array/fMatrix.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -830,7 +830,7 @@
 FloatMatrix
 FloatMatrix::pseudo_inverse (float tol) const
 {
-  svd<FloatMatrix> result (*this, svd<FloatMatrix>::economy);
+  svd<FloatMatrix> result (*this, svd<FloatMatrix>::Type::economy);
 
   FloatDiagMatrix S = result.singular_values ();
   FloatMatrix U = result.left_singular_matrix ();
diff -r 2f301a30aeed -r 469c817eb256 liboctave/numeric/oct-norm.cc
--- a/liboctave/numeric/oct-norm.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/numeric/oct-norm.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -485,7 +485,7 @@
   R res = 0;
   if (p == 2)
     {
-      svd<MatrixT> fact (m, svd<MatrixT>::sigma_only);
+      svd<MatrixT> fact (m, svd<MatrixT>::Type::sigma_only);
       res = fact.singular_values () (0,0);
     }
   else if (p == 1)
diff -r 2f301a30aeed -r 469c817eb256 liboctave/numeric/svd.cc
--- a/liboctave/numeric/svd.cc	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/numeric/svd.cc	Thu Aug 04 20:20:27 2016 +0100
@@ -1,5 +1,6 @@
 /*
 
+Copyright (C) 2016 Carnë Draug
 Copyright (C) 1994-2015 John W. Eaton
 
 This file is part of Octave.
@@ -24,7 +25,10 @@
 #  include "config.h"
 #endif
 
+#include "svd.h"
+
 #include <cassert>
+#include <algorithm>
 
 #include "CMatrix.h"
 #include "dDiagMatrix.h"
@@ -35,7 +39,6 @@
 #include "fMatrix.h"
 #include "lo-error.h"
 #include "oct-locbuf.h"
-#include "svd.h"
 
 extern "C"
 {
@@ -128,7 +131,7 @@
 T
 svd<T>::left_singular_matrix (void) const
 {
-  if (type_computed == svd::sigma_only)
+  if (type == svd::Type::sigma_only)
     (*current_liboctave_error_handler)
       ("svd: U not computed because type == svd::sigma_only");
 
@@ -139,65 +142,270 @@
 T
 svd<T>::right_singular_matrix (void) const
 {
-  if (type_computed == svd::sigma_only)
+  if (type == svd::Type::sigma_only)
     (*current_liboctave_error_handler)
       ("svd: V not computed because type == svd::sigma_only");
 
   return right_sm;
 }
 
-template <typename T>
-octave_idx_type
-svd<T>::empty_init (octave_idx_type nr, octave_idx_type nc, svd::type svd_type)
+
+// GESVD specializations
+
+#define GESVD_REAL_STEP(f, F)                                 \
+  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1),            \
+                   F77_CONST_CHAR_ARG2 (&jobv, 1),            \
+                   m, n, tmp_data, m1, s_vec, u, m1, vt,      \
+                   nrow_vt1, work.fortran_vec (), lwork, info \
+                   F77_CHAR_ARG_LEN (1)                       \
+                   F77_CHAR_ARG_LEN (1)))
+
+#define GESVD_COMPLEX_STEP(f, F, CMPLX_ARG)           \
+  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1),    \
+                   F77_CONST_CHAR_ARG2 (&jobv, 1),    \
+                   m, n, CMPLX_ARG (tmp_data),        \
+                   m1, s_vec, CMPLX_ARG (u), m1,      \
+                   CMPLX_ARG (vt), nrow_vt1,          \
+                   CMPLX_ARG (work.fortran_vec ()),   \
+                   lwork, rwork.fortran_vec (), info  \
+                   F77_CHAR_ARG_LEN (1)               \
+                   F77_CHAR_ARG_LEN (1)))
+
+// DGESVD
+template<>
+void
+svd<Matrix>::gesvd (char& jobu, char& jobv, octave_idx_type m,
+                    octave_idx_type n, double* tmp_data, octave_idx_type m1,
+                    double* s_vec, double* u, double* vt,
+                    octave_idx_type nrow_vt1, Matrix& work,
+                    octave_idx_type& lwork, octave_idx_type& info)
 {
-  assert (nr == 0 || nc == 0);
+  GESVD_REAL_STEP (dgesvd, DGESVD);
 
-  static typename T::element_type zero (0);
-  static typename T::element_type one (1);
+  lwork = static_cast<octave_idx_type> (work(0));
+  work.resize (lwork, 1);
 
-  switch (svd_type)
-    {
-    case svd::std:
-      left_sm = T (nr, nr, zero);
-      for (octave_idx_type i = 0; i < nr; i++)
-        left_sm.xelem (i, i) = one;
-      sigma = DM_T (nr, nc);
-      right_sm = T (nc, nc, zero);
-      for (octave_idx_type i = 0; i < nc; i++)
-        right_sm.xelem (i, i) = one;
-      break;
-
-    case svd::economy:
-      left_sm = T (nr, 0, zero);
-      sigma = DM_T (0, 0);
-      right_sm = T (0, nc, zero);
-      break;
-
-    case svd::sigma_only:
-    default:
-      sigma = DM_T (0, 1);
-      break;
-    }
-
-  return 0;
+  GESVD_REAL_STEP (dgesvd, DGESVD);
 }
 
-// Specializations.
+// SGESVD
+template<>
+void
+svd<FloatMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m,
+                         octave_idx_type n, float* tmp_data,
+                         octave_idx_type m1, float* s_vec, float* u, float* vt,
+                         octave_idx_type nrow_vt1, FloatMatrix& work,
+                         octave_idx_type& lwork, octave_idx_type& info)
+{
+  GESVD_REAL_STEP (sgesvd, SGESVD);
 
-template <>
-octave_idx_type
-svd<Matrix>::init (const Matrix& a, svd::type svd_type, svd::driver svd_driver)
+  lwork = static_cast<octave_idx_type> (work(0));
+  work.resize (lwork, 1);
+
+  GESVD_REAL_STEP (sgesvd, SGESVD);
+}
+
+// ZGESVD
+template<>
+void
+svd<ComplexMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m,
+                           octave_idx_type n, Complex* tmp_data,
+                           octave_idx_type m1, double* s_vec, Complex* u,
+                           Complex* vt, octave_idx_type nrow_vt1,
+                           ComplexMatrix& work,
+                           octave_idx_type& lwork, octave_idx_type& info)
 {
-  octave_idx_type info = 0;
+  Matrix rwork (5 * std::max (m, n), 1);
+
+  GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG);
+
+  lwork = static_cast<octave_idx_type> (work(0).real ());
+  work.resize (lwork, 1);
+
+  GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG);
+}
+
+// CGESVD
+template<>
+void
+svd<FloatComplexMatrix>::gesvd (char& jobu, char& jobv,
+                                octave_idx_type m, octave_idx_type n,
+                                FloatComplex* tmp_data, octave_idx_type m1,
+                                float* s_vec, FloatComplex* u,
+                                FloatComplex* vt, octave_idx_type nrow_vt1,
+                                FloatComplexMatrix& work,
+                                octave_idx_type& lwork, octave_idx_type& info)
+{
+  FloatMatrix rwork (5 * std::max (m, n), 1);
+
+  GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG);
+
+  lwork = static_cast<octave_idx_type> (work(0).real ());
+  work.resize (lwork, 1);
+
+  GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG);
+}
+
+#undef GESVD_REAL_STEP
+#undef GESVD_COMPLEX_STEP
+
+
+// GESDD specializations
+
+#define GESDD_REAL_STEP(f, F)                                       \
+  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1),                  \
+                   m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,  \
+                   work.fortran_vec (), lwork, iwork, info          \
+                   F77_CHAR_ARG_LEN (1)))
+
+#define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG)                 \
+  F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), m, n,    \
+                   CMPLX_ARG (tmp_data), m1,                \
+                   s_vec, CMPLX_ARG (u), m1,                \
+                   CMPLX_ARG (vt), nrow_vt1,                \
+                   CMPLX_ARG (work.fortran_vec ()), lwork,  \
+                   rwork.fortran_vec (), iwork, info        \
+                   F77_CHAR_ARG_LEN (1)))
+
+// DGESDD
+template<>
+void
+svd<Matrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n,
+                    double* tmp_data, octave_idx_type m1,
+                    double* s_vec, double* u,
+                    double* vt, octave_idx_type nrow_vt1,
+                    Matrix& work, octave_idx_type& lwork,
+                    octave_idx_type* iwork, octave_idx_type& info)
+{
+  GESDD_REAL_STEP (dgesdd, DGESDD);
+
+  lwork = static_cast<octave_idx_type> (work(0));
+  work.resize (lwork, 1);
+
+  GESDD_REAL_STEP (dgesdd, DGESDD);
+}
+
+// SGESDD
+template<>
+void
+svd<FloatMatrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n,
+                         float* tmp_data, octave_idx_type m1,
+                         float* s_vec, float* u,
+                         float* vt, octave_idx_type nrow_vt1,
+                         FloatMatrix& work, octave_idx_type& lwork,
+                         octave_idx_type* iwork, octave_idx_type& info)
+{
+  GESDD_REAL_STEP (sgesdd, SGESDD);
+
+  lwork = static_cast<octave_idx_type> (work(0));
+  work.resize (lwork, 1);
+
+  GESDD_REAL_STEP (sgesdd, SGESDD);
+}
+
+// ZGESDD
+template<>
+void
+svd<ComplexMatrix>::gesdd (char& jobz, octave_idx_type m, octave_idx_type n,
+                           Complex* tmp_data, octave_idx_type m1,
+                           double* s_vec, Complex* u,
+                           Complex* vt, octave_idx_type nrow_vt1,
+                           ComplexMatrix& work, octave_idx_type& lwork,
+                           octave_idx_type* iwork, octave_idx_type& info)
+{
+
+  octave_idx_type min_mn = std::min (m, n);
+
+  octave_idx_type lrwork;
+  if (jobz == 'N')
+    lrwork = 7*min_mn;
+  else
+    lrwork = 5*min_mn*min_mn + 5*min_mn;
+  Matrix rwork (lrwork, 1);
+
+
+  GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG);
+
+  lwork = static_cast<octave_idx_type> (work(0).real ());
+  work.resize (lwork, 1);
+
+  GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG);
+}
+
+// CGESDD
+template<>
+void
+svd<FloatComplexMatrix>::gesdd (char& jobz, octave_idx_type m,
+                                octave_idx_type n,
+                                FloatComplex* tmp_data, octave_idx_type m1,
+                                float* s_vec, FloatComplex* u,
+                                FloatComplex* vt, octave_idx_type nrow_vt1,
+                                FloatComplexMatrix& work,
+                                octave_idx_type& lwork, octave_idx_type* iwork,
+                                octave_idx_type& info)
+{
+  octave_idx_type min_mn = std::min (m, n);
+  octave_idx_type max_mn = std::max (m, n);
+
+  octave_idx_type lrwork;
+  if (jobz == 'N')
+    lrwork = 5*min_mn;
+  else
+    lrwork = min_mn * std::max (5*min_mn+7, 2*max_mn+2*min_mn+1);
+  FloatMatrix rwork (lrwork, 1);
+
+  GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG);
+
+  lwork = static_cast<octave_idx_type> (work(0).real ());
+  work.resize (lwork, 1);
+
+  GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG);
+}
+
+#undef GESDD_REAL_STEP
+#undef GESDD_COMPLEX_STEP
+
+
+template<typename T>
+svd<T>::svd (const T& a, svd::Type type,
+             svd::Driver driver)
+  : type (type), driver (driver), left_sm (), sigma (), right_sm ()
+{
+  octave_idx_type info;
 
   octave_idx_type m = a.rows ();
   octave_idx_type n = a.cols ();
 
   if (m == 0 || n == 0)
-    return empty_init (m, n, svd_type);
+    {
+      switch (type)
+        {
+        case svd::Type::std:
+          left_sm = T (m, m, 0);
+          for (octave_idx_type i = 0; i < m; i++)
+            left_sm.xelem (i, i) = 1;
+          sigma = DM_T (m, n);
+          right_sm = T (n, n, 0);
+          for (octave_idx_type i = 0; i < n; i++)
+            right_sm.xelem (i, i) = 1;
+          break;
 
-  Matrix atmp = a;
-  double *tmp_data = atmp.fortran_vec ();
+        case svd::Type::economy:
+          left_sm = T (m, 0, 0);
+          sigma = DM_T (0, 0);
+          right_sm = T (0, n, 0);
+          break;
+
+        case svd::Type::sigma_only:
+        default:
+          sigma = DM_T (0, 1);
+          break;
+        }
+      return;
+    }
+
+  T atmp = a;
+  P* tmp_data = atmp.fortran_vec ();
 
   octave_idx_type min_mn = m < n ? m : n;
 
@@ -209,14 +417,14 @@
   octave_idx_type nrow_s = m;
   octave_idx_type ncol_s = n;
 
-  switch (svd_type)
+  switch (type)
     {
-    case svd::economy:
+    case svd::Type::economy:
       jobu = jobv = 'S';
       ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
       break;
 
-    case svd::sigma_only:
+    case svd::Type::sigma_only:
 
       // Note:  for this case, both jobu and jobv should be 'N', but
       // there seems to be a bug in dgesvd from Lapack V2.0.  To
@@ -234,481 +442,46 @@
       break;
     }
 
-  type_computed = svd_type;
-
   if (! (jobu == 'N' || jobu == 'O'))
     left_sm.resize (m, ncol_u);
 
-  double *u = left_sm.fortran_vec ();
+  P* u = left_sm.fortran_vec ();
 
   sigma.resize (nrow_s, ncol_s);
-  double *s_vec = sigma.fortran_vec ();
+  DM_P* s_vec = sigma.fortran_vec ();
 
   if (! (jobv == 'N' || jobv == 'O'))
     right_sm.resize (nrow_vt, n);
 
-  double *vt = right_sm.fortran_vec ();
+  P* vt = right_sm.fortran_vec ();
 
-  // Query DGESVD for the correct dimension of WORK.
+  // Query _GESVD for the correct dimension of WORK.
 
   octave_idx_type lwork = -1;
 
-  Array<double> work (dim_vector (1, 1));
+  T work (1, 1);
 
-  octave_idx_type one = 1;
-  octave_idx_type m1 = std::max (m, one);
-  octave_idx_type nrow_vt1 = std::max (nrow_vt, one);
+  octave_idx_type m1 = std::max (m, 1);
+  octave_idx_type nrow_vt1 = std::max (nrow_vt, 1);
 
-  if (svd_driver == svd::GESVD)
-    {
-      F77_XFCN (dgesvd, DGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt,
-                                 nrow_vt1, work.fortran_vec (), lwork, info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0));
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (dgesvd, DGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt,
-                                 nrow_vt1, work.fortran_vec (), lwork, info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-
-    }
-  else if (svd_driver == svd::GESDD)
+  if (driver == svd::Driver::GESVD)
+    gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
+           work, lwork, info);
+  else if (driver == svd::Driver::GESDD)
     {
       assert (jobu == jobv);
       char jobz = jobu;
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn);
 
-      F77_XFCN (dgesdd, DGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,
-                                 work.fortran_vec (), lwork, iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
+      OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8 * std::min (m, n));
 
-      lwork = static_cast<octave_idx_type> (work(0));
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (dgesdd, DGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,
-                                 work.fortran_vec (), lwork, iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-
+      gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
+             work, lwork, iwork, info);
     }
   else
     abort ();
 
   if (! (jobv == 'N' || jobv == 'O'))
     right_sm = right_sm.transpose ();
-
-  return info;
-}
-
-template <>
-octave_idx_type
-svd<FloatMatrix>::init (const FloatMatrix& a, svd::type svd_type,
-                        svd::driver svd_driver)
-{
-  octave_idx_type info;
-
-  octave_idx_type m = a.rows ();
-  octave_idx_type n = a.cols ();
-
-  if (m == 0 || n == 0)
-    return empty_init (m, n, svd_type);
-
-  FloatMatrix atmp = a;
-  float *tmp_data = atmp.fortran_vec ();
-
-  octave_idx_type min_mn = m < n ? m : n;
-
-  char jobu = 'A';
-  char jobv = 'A';
-
-  octave_idx_type ncol_u = m;
-  octave_idx_type nrow_vt = n;
-  octave_idx_type nrow_s = m;
-  octave_idx_type ncol_s = n;
-
-  switch (svd_type)
-    {
-    case svd::economy:
-      jobu = jobv = 'S';
-      ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
-      break;
-
-    case svd::sigma_only:
-
-      // Note:  for this case, both jobu and jobv should be 'N', but
-      // there seems to be a bug in dgesvd from Lapack V2.0.  To
-      // demonstrate the bug, set both jobu and jobv to 'N' and find
-      // the singular values of [eye(3), eye(3)].  The result is
-      // [-sqrt(2), -sqrt(2), -sqrt(2)].
-      //
-      // For Lapack 3.0, this problem seems to be fixed.
-
-      jobu = jobv = 'N';
-      ncol_u = nrow_vt = 1;
-      break;
-
-    default:
-      break;
-    }
-
-  type_computed = svd_type;
-
-  if (! (jobu == 'N' || jobu == 'O'))
-    left_sm.resize (m, ncol_u);
-
-  float *u = left_sm.fortran_vec ();
-
-  sigma.resize (nrow_s, ncol_s);
-  float *s_vec = sigma.fortran_vec ();
-
-  if (! (jobv == 'N' || jobv == 'O'))
-    right_sm.resize (nrow_vt, n);
-
-  float *vt = right_sm.fortran_vec ();
-
-  // Query SGESVD for the correct dimension of WORK.
-
-  octave_idx_type lwork = -1;
-
-  Array<float> work (dim_vector (1, 1));
-
-  octave_idx_type one = 1;
-  octave_idx_type m1 = std::max (m, one);
-  octave_idx_type nrow_vt1 = std::max (nrow_vt, one);
-
-  if (svd_driver == svd::GESVD)
-    {
-      F77_XFCN (sgesvd, SGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt,
-                                 nrow_vt1, work.fortran_vec (), lwork, info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0));
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (sgesvd, SGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt,
-                                 nrow_vt1, work.fortran_vec (), lwork, info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-
-    }
-  else if (svd_driver == svd::GESDD)
-    {
-      assert (jobu == jobv);
-      char jobz = jobu;
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn);
-
-      F77_XFCN (sgesdd, SGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,
-                                 work.fortran_vec (), lwork, iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0));
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (sgesdd, SGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,
-                                 work.fortran_vec (), lwork, iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-
-    }
-  else
-    abort ();
-
-  if (! (jobv == 'N' || jobv == 'O'))
-    right_sm = right_sm.transpose ();
-
-  return info;
-}
-
-template <>
-octave_idx_type
-svd<ComplexMatrix>::init (const ComplexMatrix& a, svd::type svd_type,
-                          svd::driver svd_driver)
-{
-  octave_idx_type info;
-
-  octave_idx_type m = a.rows ();
-  octave_idx_type n = a.cols ();
-
-  if (m == 0 || n == 0)
-    return empty_init (m, n, svd_type);
-
-  ComplexMatrix atmp = a;
-  Complex *tmp_data = atmp.fortran_vec ();
-
-  octave_idx_type min_mn = m < n ? m : n;
-  octave_idx_type max_mn = m > n ? m : n;
-
-  char jobu = 'A';
-  char jobv = 'A';
-
-  octave_idx_type ncol_u = m;
-  octave_idx_type nrow_vt = n;
-  octave_idx_type nrow_s = m;
-  octave_idx_type ncol_s = n;
-
-  switch (svd_type)
-    {
-    case svd::economy:
-      jobu = jobv = 'S';
-      ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
-      break;
-
-    case svd::sigma_only:
-
-      // Note:  for this case, both jobu and jobv should be 'N', but
-      // there seems to be a bug in dgesvd from Lapack V2.0.  To
-      // demonstrate the bug, set both jobu and jobv to 'N' and find
-      // the singular values of [eye(3), eye(3)].  The result is
-      // [-sqrt(2), -sqrt(2), -sqrt(2)].
-      //
-      // For Lapack 3.0, this problem seems to be fixed.
-
-      jobu = jobv = 'N';
-      ncol_u = nrow_vt = 1;
-      break;
-
-    default:
-      break;
-    }
-
-  type_computed = svd_type;
-
-  if (! (jobu == 'N' || jobu == 'O'))
-    left_sm.resize (m, ncol_u);
-
-  Complex *u = left_sm.fortran_vec ();
-
-  sigma.resize (nrow_s, ncol_s);
-  double *s_vec = sigma.fortran_vec ();
-
-  if (! (jobv == 'N' || jobv == 'O'))
-    right_sm.resize (nrow_vt, n);
-
-  Complex *vt = right_sm.fortran_vec ();
-
-  // Query ZGESVD for the correct dimension of WORK.
-
-  octave_idx_type lwork = -1;
-
-  Array<Complex> work (dim_vector (1, 1));
-
-  octave_idx_type one = 1;
-  octave_idx_type m1 = std::max (m, one);
-  octave_idx_type nrow_vt1 = std::max (nrow_vt, one);
-
-  if (svd_driver == svd::GESVD)
-    {
-      octave_idx_type lrwork = 5*max_mn;
-      Array<double> rwork (dim_vector (lrwork, 1));
-
-      F77_XFCN (zgesvd, ZGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, F77_DBLE_CMPLX_ARG (tmp_data), m1, s_vec, F77_DBLE_CMPLX_ARG (u), m1, F77_DBLE_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_DBLE_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0).real ());
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (zgesvd, ZGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, F77_DBLE_CMPLX_ARG (tmp_data), m1, s_vec, F77_DBLE_CMPLX_ARG (u), m1, F77_DBLE_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_DBLE_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-    }
-  else if (svd_driver == svd::GESDD)
-    {
-      assert (jobu == jobv);
-      char jobz = jobu;
-
-      octave_idx_type lrwork;
-      if (jobz == 'N')
-        lrwork = 7*min_mn;
-      else
-        lrwork = 5*min_mn*min_mn + 5*min_mn;
-      Array<double> rwork (dim_vector (lrwork, 1));
-
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn);
-
-      F77_XFCN (zgesdd, ZGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, F77_DBLE_CMPLX_ARG (tmp_data), m1, s_vec, F77_DBLE_CMPLX_ARG (u), m1, F77_DBLE_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_DBLE_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0).real ());
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (zgesdd, ZGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, F77_DBLE_CMPLX_ARG (tmp_data), m1, s_vec, F77_DBLE_CMPLX_ARG (u), m1, F77_DBLE_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_DBLE_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-    }
-  else
-    abort ();
-
-  if (! (jobv == 'N' || jobv == 'O'))
-    right_sm = right_sm.hermitian ();
-
-  return info;
-}
-
-template <>
-octave_idx_type
-svd<FloatComplexMatrix>::init (const FloatComplexMatrix& a, svd::type svd_type,
-                              svd::driver svd_driver)
-{
-  octave_idx_type info;
-
-  octave_idx_type m = a.rows ();
-  octave_idx_type n = a.cols ();
-
-  if (m == 0 || n == 0)
-    return empty_init (m, n, svd_type);
-
-  FloatComplexMatrix atmp = a;
-  FloatComplex *tmp_data = atmp.fortran_vec ();
-
-  octave_idx_type min_mn = m < n ? m : n;
-  octave_idx_type max_mn = m > n ? m : n;
-
-  char jobu = 'A';
-  char jobv = 'A';
-
-  octave_idx_type ncol_u = m;
-  octave_idx_type nrow_vt = n;
-  octave_idx_type nrow_s = m;
-  octave_idx_type ncol_s = n;
-
-  switch (svd_type)
-    {
-    case svd::economy:
-      jobu = jobv = 'S';
-      ncol_u = nrow_vt = nrow_s = ncol_s = min_mn;
-      break;
-
-    case svd::sigma_only:
-
-      // Note:  for this case, both jobu and jobv should be 'N', but
-      // there seems to be a bug in dgesvd from Lapack V2.0.  To
-      // demonstrate the bug, set both jobu and jobv to 'N' and find
-      // the singular values of [eye(3), eye(3)].  The result is
-      // [-sqrt(2), -sqrt(2), -sqrt(2)].
-      //
-      // For Lapack 3.0, this problem seems to be fixed.
-
-      jobu = jobv = 'N';
-      ncol_u = nrow_vt = 1;
-      break;
-
-    default:
-      break;
-    }
-
-  type_computed = svd_type;
-
-  if (! (jobu == 'N' || jobu == 'O'))
-    left_sm.resize (m, ncol_u);
-
-  FloatComplex *u = left_sm.fortran_vec ();
-
-  sigma.resize (nrow_s, ncol_s);
-  float *s_vec = sigma.fortran_vec ();
-
-  if (! (jobv == 'N' || jobv == 'O'))
-    right_sm.resize (nrow_vt, n);
-
-  FloatComplex *vt = right_sm.fortran_vec ();
-
-  // Query CGESVD for the correct dimension of WORK.
-
-  octave_idx_type lwork = -1;
-
-  Array<FloatComplex> work (dim_vector (1, 1));
-
-  octave_idx_type one = 1;
-  octave_idx_type m1 = std::max (m, one);
-  octave_idx_type nrow_vt1 = std::max (nrow_vt, one);
-
-  if (svd_driver == svd::GESVD)
-    {
-      octave_idx_type lrwork = 5*max_mn;
-      Array<float> rwork (dim_vector (lrwork, 1));
-
-      F77_XFCN (cgesvd, CGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, F77_CMPLX_ARG (tmp_data), m1, s_vec, F77_CMPLX_ARG (u), m1, F77_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0).real ());
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (cgesvd, CGESVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                                 F77_CONST_CHAR_ARG2 (&jobv, 1),
-                                 m, n, F77_CMPLX_ARG (tmp_data), m1, s_vec, F77_CMPLX_ARG (u), m1, F77_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), info
-                                 F77_CHAR_ARG_LEN (1)
-                                 F77_CHAR_ARG_LEN (1)));
-    }
-  else if (svd_driver == svd::GESDD)
-    {
-      assert (jobu == jobv);
-      char jobz = jobu;
-
-      octave_idx_type lrwork;
-      if (jobz == 'N')
-        lrwork = 5*min_mn;
-      else
-        lrwork = min_mn * std::max (5*min_mn+7, 2*max_mn+2*min_mn+1);
-      Array<float> rwork (dim_vector (lrwork, 1));
-
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8*min_mn);
-
-      F77_XFCN (cgesdd, CGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, F77_CMPLX_ARG (tmp_data), m1, s_vec, F77_CMPLX_ARG (u), m1, F77_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-
-      lwork = static_cast<octave_idx_type> (work(0).real ());
-      work.resize (dim_vector (lwork, 1));
-
-      F77_XFCN (cgesdd, CGESDD, (F77_CONST_CHAR_ARG2 (&jobz, 1),
-                                 m, n, F77_CMPLX_ARG (tmp_data), m1, s_vec, F77_CMPLX_ARG (u), m1, F77_CMPLX_ARG (vt),
-                                 nrow_vt1, F77_CMPLX_ARG (work.fortran_vec ()), lwork,
-                                 rwork.fortran_vec (), iwork, info
-                                 F77_CHAR_ARG_LEN (1)));
-    }
-  else
-    abort ();
-
-  if (! (jobv == 'N' || jobv == 'O'))
-    right_sm = right_sm.hermitian ();
-
-  return info;
 }
 
 // Instantiations we need.
diff -r 2f301a30aeed -r 469c817eb256 liboctave/numeric/svd.h
--- a/liboctave/numeric/svd.h	Wed Aug 03 10:23:41 2016 -0700
+++ b/liboctave/numeric/svd.h	Thu Aug 04 20:20:27 2016 +0100
@@ -1,5 +1,6 @@
 /*
 
+Copyright (C) 2016 Carnë Draug
 Copyright (C) 1994-2015 John W. Eaton
 
 This file is part of Octave.
@@ -35,49 +36,40 @@
 
   typedef typename T::real_diag_matrix_type DM_T;
 
-  enum type
+  enum class Type
   {
     std,
     economy,
     sigma_only
   };
 
-  enum driver
+  enum class Driver
   {
     GESVD,
     GESDD
   };
 
   svd (void)
-    : type_computed (), left_sm (), sigma (), right_sm ()
+    : type (), driver (), left_sm (), sigma (), right_sm ()
   { }
 
-  svd (const T& a, type svd_type = svd::std, driver svd_driver = svd::GESVD)
-    : type_computed (), left_sm (), sigma (), right_sm ()
-  {
-    init (a, svd_type, svd_driver);
-  }
-
-  svd (const T& a, octave_idx_type& info, type svd_type = svd::std,
-       driver svd_driver = svd::GESVD)
-    : type_computed (), left_sm (), sigma (), right_sm ()
-  {
-    info = init (a, svd_type, svd_driver);
-  }
+  svd (const T& a, svd::Type type = svd::Type::std,
+       svd::Driver driver = svd::Driver::GESVD);
 
   svd (const svd& a)
-    : type_computed (a.type_computed), left_sm (a.left_sm),
-      sigma (a.sigma), right_sm (a.right_sm)
+    : type (a.type), driver (a.driver), left_sm (a.left_sm), sigma (a.sigma),
+      right_sm (a.right_sm)
   { }
 
   svd& operator = (const svd& a)
   {
     if (this != &a)
       {
-        type_computed = a.type_computed;
+        type = a.type;
         left_sm = a.left_sm;
         sigma = a.sigma;
         right_sm = a.right_sm;
+        driver = a.driver;
       }
 
     return *this;
@@ -93,17 +85,26 @@
 
 private:
 
-  svd::type type_computed;
+  typedef typename T::element_type P;
+  typedef typename DM_T::element_type DM_P;
+
+  svd::Type type;
+  svd::Driver driver;
 
   T left_sm;
   DM_T sigma;
   T right_sm;
 
-  octave_idx_type
-  init (const T& a, type svd_type, driver svd_driver);
+  void gesvd (char& jobu, char& jobv, octave_idx_type m, octave_idx_type n,
+              P* tmp_data, octave_idx_type m1, DM_P* s_vec, P* u, P* vt,
+              octave_idx_type nrow_vt1, T& work, octave_idx_type& lwork,
+              octave_idx_type& info);
 
-  octave_idx_type
-  empty_init (octave_idx_type nr, octave_idx_type nc, type svd_type);
+  void gesdd (char& jobz, octave_idx_type m, octave_idx_type n,
+              P* tmp_data, octave_idx_type m1, DM_P* s_vec, P* u, P* vt,
+              octave_idx_type nrow_vt1, T& work, octave_idx_type& lwork,
+              octave_idx_type* iwork, octave_idx_type& info);
+
 };
 
 #endif
# HG changeset patch
# User John Donoghue <john.donoghue@ieee.org>
# Date 1468789410 14400
#      Sun Jul 17 17:03:30 2016 -0400
# Node ID 8a456af24e6b58fafe997623696b2d69779d9582
# Parent  469c817eb2560e93208a10b267c35c4bccd46bf3
provide single function to get OpenGL renderer info

* scripts/plot/util/__opengl_info__.m: New file.

* scripts/plot/util/module.mk: Update.

diff -r 469c817eb256 -r 8a456af24e6b scripts/plot/util/__opengl_info__.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/util/__opengl_info__.m	Sun Jul 17 17:03:30 2016 -0400
@@ -0,0 +1,121 @@
+## Copyright (C) 2016 John Donoghue <john.donoghue@ieee.org>
+##
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} __opengl_info__
+## @deftypefnx {Function File} {@var{retval} =} __opengl_info__ ()
+##
+## Get OpenGL driver information.
+##
+## If no output values are requested, display information about the
+## OpenGL subsystem.  If an output is requested, return the information
+## in a structure.
+##
+## Fields in the structure are:
+## @table @asis
+## @item version
+## OpenGL Driver version string
+## @item vendor
+## OpenGL Driver vendor string
+## @item renderer
+## OpenGL renderer string
+## @item extensions
+## List of enabled extensions for the OpenGL driver.
+## @end table
+##
+## @example
+## glinfo = __opengl_info__ ();
+## @end example
+##
+## @end deftypefn
+
+function retval = __opengl_info__ ()
+
+  # currently we only handle a single argument
+  if (nargin != 0)
+    print_usage ();
+  endif
+
+  [info, msg] = gl_info ();
+
+  if (isempty (msg))
+    if (nargout == 0)
+      printf ("version    = %s\n", info.version);
+      printf ("vendor     = %s\n", info.vendor);
+      printf ("renderer   = %s\n", info.renderer);
+      printf ("extensions =\n");
+      printf ("  %s\n", info.extensions{:});
+    else
+      retval = info;
+    endif
+  else
+    warning (msg);
+  endif
+
+endfunction
+
+function info = fig_gl_info (h)
+  info = [];
+  if (ishandle (h) && strcmp (get (h, "renderer"), "opengl"))
+    vers = get (h, "__gl_version__");
+    vend = get (h, "__gl_vendor__");
+    rend = get (h, "__gl_renderer__");
+    exts = get (h, "__gl_extensions__");
+    if (! isempty (vend))
+      info.version = vers;
+      info.vendor = vend;
+      info.renderer = rend;
+      info.extensions = strsplit (strtrim (exts));
+    endif
+  endif
+endfunction
+
+function [info, msg] = gl_info ()
+  info = [];
+  msg = "";
+
+  ## If we have any open figures, take a look for any OpenGL info.
+
+  figs = findall (0, "type", "figure");
+
+  for i = 1:numel (figs)
+    if (isempty (info))
+      info = fig_gl_info (figs(i));
+      if (! isempty (info))
+        break
+      endif
+    endif
+  endfor
+
+  ## If no info yet, try open a figure brifly to get the info.
+
+  if (isempty (info))
+    h = figure ("position", [0,0,1,1], "toolbar", "none", "menubar", "none");
+    waitfor (h, "timeout", 1);
+    info = fig_gl_info (h);
+    close (h);
+  endif
+
+  if (isempty (info))
+    msg = "__opengl_info__: can not obtain OpenGL information";
+  endif
+
+endfunction
+
+
+%!xtest
+%! a = __opengl_info__ ();
+%! assert (! isempty (a))
+%! assert (isfield (a, "version"))
diff -r 469c817eb256 -r 8a456af24e6b scripts/plot/util/module.mk
--- a/scripts/plot/util/module.mk	Thu Aug 04 20:20:27 2016 +0100
+++ b/scripts/plot/util/module.mk	Sun Jul 17 17:03:30 2016 -0400
@@ -24,6 +24,13 @@
 
 scripts_plot_util_FCN_FILES = \
   scripts/plot/util/__actual_axis_position__.m \
+  scripts/plot/util/__default_plot_options__.m \
+  scripts/plot/util/__gnuplot_drawnow__.m \
+  scripts/plot/util/__next_line_color__.m \
+  scripts/plot/util/__next_line_style__.m \
+  scripts/plot/util/__opengl_info__.m \
+  scripts/plot/util/__plt_get_axis_arg__.m \
+  scripts/plot/util/__pltopt__.m \
   scripts/plot/util/allchild.m \
   scripts/plot/util/ancestor.m \
   scripts/plot/util/axes.m \
@@ -33,7 +40,6 @@
   scripts/plot/util/closereq.m \
   scripts/plot/util/colstyle.m \
   scripts/plot/util/copyobj.m \
-  scripts/plot/util/__default_plot_options__.m \
   scripts/plot/util/figure.m \
   scripts/plot/util/findall.m \
   scripts/plot/util/findfigs.m \
@@ -45,7 +51,6 @@
   scripts/plot/util/gcf.m \
   scripts/plot/util/gco.m \
   scripts/plot/util/ginput.m \
-  scripts/plot/util/__gnuplot_drawnow__.m \
   scripts/plot/util/graphics_toolkit.m \
   scripts/plot/util/hdl2struct.m \
   scripts/plot/util/hggroup.m \
@@ -63,15 +68,11 @@
   scripts/plot/util/meshgrid.m \
   scripts/plot/util/ndgrid.m \
   scripts/plot/util/newplot.m \
-  scripts/plot/util/__next_line_color__.m \
-  scripts/plot/util/__next_line_style__.m \
   scripts/plot/util/pan.m \
-  scripts/plot/util/__plt_get_axis_arg__.m \
-  scripts/plot/util/__pltopt__.m \
+  scripts/plot/util/print.m \
   scripts/plot/util/printd.m \
-  scripts/plot/util/print.m \
+  scripts/plot/util/refresh.m \
   scripts/plot/util/refreshdata.m \
-  scripts/plot/util/refresh.m \
   scripts/plot/util/rotate.m \
   scripts/plot/util/rotate3d.m \
   scripts/plot/util/saveas.m \
# HG changeset patch
# User mfasi <mogrob.sanit@gmail.com>
# Date 1455757032 -39600
#      Thu Feb 18 11:57:12 2016 +1100
# Node ID 21684fa513ce0abb8131080dd724c42fffd98725
# Parent  8a456af24e6b58fafe997623696b2d69779d9582
Return C = Q'*B not Q when qr has two arguments (bug #41567, bug #46912)

* qr.cc (Fqr): For full case, explicitly calculate Q.  Add 8 tests.

diff -r 8a456af24e6b -r 21684fa513ce libinterp/dldfcn/qr.cc
--- a/libinterp/dldfcn/qr.cc	Sun Jul 17 17:03:30 2016 -0400
+++ b/libinterp/dldfcn/qr.cc	Thu Feb 18 11:57:12 2016 +1100
@@ -214,29 +214,33 @@
   if (arg_is_empty < 0)
     return retval;
 
+  bool economy = false;
+  bool is_cmplx = false;
+  bool b_mat = false;
+  int have_b = 0;
+
+  if (arg.is_complex_type ())
+    is_cmplx = true;
+  if (nargin > 1)
+    {
+      have_b = 1;
+      if (args(nargin-1).is_scalar_type ())
+        {
+          int val = args(nargin-1).int_value ();
+          if (val == 0)
+            {
+              economy = true;
+              have_b = (nargin > 2 ? 2 : 0);
+            }
+        }
+      else if (args(nargin-1).is_matrix_type ())
+          b_mat = true;
+      if (have_b > 0 && args(have_b).is_complex_type ())
+        is_cmplx = true;
+    }
+
   if (arg.is_sparse_type ())
     {
-      bool economy = false;
-      bool is_cmplx = false;
-      int have_b = 0;
-
-      if (arg.is_complex_type ())
-        is_cmplx = true;
-      if (nargin > 1)
-        {
-          have_b = 1;
-          if (args(nargin-1).is_scalar_type ())
-            {
-              int val = args(nargin-1).int_value ();
-              if (val == 0)
-                {
-                  economy = true;
-                  have_b = (nargin > 2 ? 2 : 0);
-                }
-            }
-          if (have_b > 0 && args(have_b).is_complex_type ())
-            is_cmplx = true;
-        }
 
       if (is_cmplx)
         {
@@ -295,6 +299,15 @@
                   {
                     qr<FloatMatrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
+                    if (b_mat)
+                      {
+                        if (is_cmplx)
+                          retval(0) = fact.Q ().transpose ()
+                                      * args(1).float_complex_matrix_value ();
+                        else
+                          retval(0) = fact.Q ().transpose ()
+                                      * args(1).float_matrix_value ();
+                      }
                   }
                   break;
 
@@ -331,6 +344,9 @@
                   {
                     qr<FloatComplexMatrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
+                    if (b_mat)
+                      retval (0) = conj (fact.Q ().transpose ())
+                                   * args(1).float_complex_matrix_value ();
                   }
                   break;
 
@@ -368,6 +384,15 @@
                   {
                     qr<Matrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
+                    if (b_mat)
+                      {
+                        if (is_cmplx)
+                          retval(0) = fact.Q ().transpose ()
+                                      * args(1).complex_matrix_value ();
+                        else
+                          retval(0) = fact.Q ().transpose ()
+                                      * args(1).matrix_value ();
+                      }
                   }
                   break;
 
@@ -403,6 +428,9 @@
                   {
                     qr<ComplexMatrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
+                    if (b_mat)
+                      retval (0) = conj (fact.Q ().transpose ())
+                                   * args(1).complex_matrix_value ();
                   }
                   break;
 
@@ -438,6 +466,15 @@
 %!test
 %! a = [0, 2, 1; 2, 1, 2];
 %!
+%! [q, r] = qr (a);
+%! [qe, re] = qr (a, 0);
+%!
+%! assert (q * r, a, sqrt (eps));
+%! assert (qe * re, a, sqrt (eps));
+
+%!test
+%! a = [0, 2, 1; 2, 1, 2];
+%!
 %! [q, r, p] = qr (a);  # FIXME: not giving right dimensions.
 %! [qe, re, pe] = qr (a, 0);
 %!
@@ -462,6 +499,46 @@
 %! assert (q * r, a * p, sqrt (eps));
 %! assert (qe * re, a(:, pe), sqrt (eps));
 
+%!test
+%! a = [0, 2, 1; 2, 1, 2; 3, 1, 2];
+%! b = [1, 3, 2; 1, 1, 0; 3, 0, 2];
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps));
+%! assert (q'*b, c, sqrt (eps));
+
+%!test
+%! a = [0, 2, i; 2, 1, 2; 3, 1, 2];
+%! b = [1, 3, 2; 1, i, 0; 3, 0, 2];
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps));
+%! assert (q'*b, c, sqrt (eps));
+
+%!test
+%! a = [0, 2, i; 2, 1, 2; 3, 1, 2];
+%! b = [1, 3, 2; 1, 1, 0; 3, 0, 2];
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps));
+%! assert (q'*b, c, sqrt (eps));
+
+%!test
+%! a = [0, 2, 1; 2, 1, 2; 3, 1, 2];
+%! b = [1, 3, 2; 1, i, 0; 3, 0, 2];
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps));
+%! assert (q'*b, c, sqrt (eps));
+
 %!error qr ()
 %!error qr ([1, 2; 3, 4], 0, 2)
 
@@ -575,6 +652,46 @@
 %! assert (q * r, a * p, sqrt (eps ("single")));
 %! assert (qe * re, a(:, pe), sqrt (eps ("single")));
 
+%!test
+%! a = single([0, 2, 1; 2, 1, 2; 3, 1, 2]);
+%! b = single([1, 3, 2; 1, 1, 0; 3, 0, 2]);
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps ("single")));
+%! assert (q'*b, c, sqrt (eps ("single")));
+
+%!test
+%! a = single([0, 2, i; 2, 1, 2; 3, 1, 2]);
+%! b = single([1, 3, 2; 1, i, 0; 3, 0, 2]);
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps ("single")));
+%! assert (q'*b, c, sqrt (eps ("single")));
+
+%!test
+%! a = single([0, 2, i; 2, 1, 2; 3, 1, 2]);
+%! b = single([1, 3, 2; 1, 1, 0; 3, 0, 2]);
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps));
+%! assert (q'*b, c, sqrt (eps));
+
+%!test
+%! a = single([0, 2, 1; 2, 1, 2; 3, 1, 2]);
+%! b = single([1, 3, 2; 1, i, 0; 3, 0, 2]);
+%!
+%! [q, r] = qr (a);
+%! [c, re] = qr (a, b);
+%!
+%! assert (r, re, sqrt (eps ("single")));
+%! assert (q'*b, c, sqrt (eps ("single")));
+
 %!error qr ()
 %!error qr ([1, 2; 3, 4], 0, 2)
 
# HG changeset patch
# User Lachlan Andrew <lachlanbis@gmail.com>
# Date 1467878668 -36000
#      Thu Jul 07 18:04:28 2016 +1000
# Node ID 99454a60bf5e33ba6e5f684fe7b3ad79ea2eb9ea
# Parent  21684fa513ce0abb8131080dd724c42fffd98725
Reconcile qr docs with behaviour.  Fix qr(A,B,complex(0)). (bug #46912)

* qr.cc (Fqr): Update docstring.
  Change have_b to boolean, so B is always taken from the second position;
  previously qr(A,B,complex(0)) would take B=complex(0).
  Accept options 'vector' and 'matrix'.
  Make diagnostics more informative.

* qr.cc (Fqrinsert): Change x in docstring block matrices to X and U.

diff -r 21684fa513ce -r 99454a60bf5e libinterp/dldfcn/qr.cc
--- a/libinterp/dldfcn/qr.cc	Thu Feb 18 11:57:12 2016 +1100
+++ b/libinterp/dldfcn/qr.cc	Thu Jul 07 18:04:28 2016 +1000
@@ -75,13 +75,25 @@
 
 DEFUN_DLD (qr, args, nargout,
            doc: /* -*- texinfo -*-
-@deftypefn  {} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A})
-@deftypefnx {} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A}, '0')
+@deftypefn  {} {[@var{Q}, @var{R}] =} qr (@var{A})
+@deftypefnx {} {[@var{Q}, @var{R}, @var{P}] =} qr (@var{A}) # non-sparse A
+@deftypefnx {} {@var{X} =} qr (@var{A})
+@deftypefnx {} {@var{R} =} qr (@var{A})  # sparse A
 @deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})
-@deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B}, '0')
+@deftypefnx {} {[...] =} qr (..., 0)
+@deftypefnx {} {[...] =} qr (..., 'vector')
+@deftypefnx {} {[...] =} qr (..., 'matrix')
 @cindex QR factorization
 Compute the QR@tie{}factorization of @var{A}, using standard @sc{lapack}
 subroutines.
+The QR@tie{}factorization is
+@tex
+$QR = A$ where $Q$ is an orthogonal matrix and $R$ is upper triangular.
+@end tex
+@ifnottex
+@code{@var{Q} * @var{R} = @var{A}} where @var{Q} is an orthogonal matrix and
+@var{R} is upper triangular.
+@end ifnottex
 
 For example, given the matrix @code{@var{A} = [1, 2; 3, 4]},
 
@@ -127,18 +139,14 @@
 @ifnottex
 @var{A}
 @end ifnottex
-is a tall, thin matrix).  The QR@tie{}factorization is
-@tex
-$QR = A$ where $Q$ is an orthogonal matrix and $R$ is upper triangular.
-@end tex
-@ifnottex
-@code{@var{Q} * @var{R} = @var{A}} where @var{Q} is an orthogonal matrix and
-@var{R} is upper triangular.
-@end ifnottex
+is a tall, thin matrix).
 
-If given a second argument of @qcode{'0'}, @code{qr} returns an
-economy-sized QR@tie{}factorization, omitting zero rows of @var{R} and the
-corresponding columns of @var{Q}.
+If only a single return value is requested, then it is either @var{R} if
+@var{A} is sparse, or @var{X} such that @code{@var{R} = triu (@var{X})} if
+@var{A} is full.
+(Note: Unlike most commands, the single return value is not
+the first return value when multiple are requested.)
+
 
 If the matrix @var{A} is full, the permuted QR@tie{}factorization
 @code{[@var{Q}, @var{R}, @var{P}] = qr (@var{A})} forms the
@@ -176,17 +184,15 @@
 @code{[@var{Q}, @var{R}, @var{P}] = qr (@var{A})} factorization allows the
 construction of an orthogonal basis of @code{span (A)}.
 
-If the matrix @var{A} is sparse, then compute the sparse
-QR@tie{}factorization of @var{A}, using @sc{CSparse}.  As the matrix @var{Q}
-is in general a full matrix, this function returns the @var{Q}-less
-factorization @var{R} of @var{A}, such that
+If the matrix @var{A} is sparse, then the sparse QR@tie{}factorization
+of @var{A} is computed using @sc{CSparse}.
+As the matrix @var{Q} is in general a full matrix,
+it is recommended to request only one return value,
+which is the @var{Q}-less factorization @var{R} of @var{A}, such that
 @code{@var{R} = chol (@var{A}' * @var{A})}.
 
-If the final argument is the scalar @code{0} and the number of rows is
-larger than the number of columns, then an economy factorization is
-returned.  That is @var{R} will have only @code{size (@var{A},1)} rows.
-
-If an additional matrix @var{B} is supplied, then @code{qr} returns
+If an additional matrix @var{B} is supplied and two return values are
+requested, then @code{qr} returns
 @var{C}, where @code{@var{C} = @var{Q}' * @var{B}}.  This allows the
 least squares approximation of @code{@var{A} \ @var{B}} to be calculated
 as
@@ -197,12 +203,22 @@
 x = @var{R} \ @var{C}
 @end group
 @end example
+
+If the final argument is the scalar 0 and the number of rows is larger
+than the number of columns, then an 'economy' factorization is returned,
+omitting zeroes of @var{R} and the corresponding columns of @var{Q}.
+That is, @var{R} will have only @code{size (@var{A},1)} rows.
+In this case, @var{P} is a vector rather than a matrix.
+
+If the final argument is the string 'vector' then @var{P} is a permutation
+vector instead of a permutation matrix.
+
 @seealso{chol, hess, lu, qz, schur, svd, qrupdate, qrinsert, qrdelete, qrshift}
 @end deftypefn */)
 {
   int nargin = args.length ();
 
-  if (nargin < 1 || nargin > (args(0).is_sparse_type () ? 3 : 2))
+  if (nargin < 1 || nargin > 3)
     print_usage ();
 
   octave_value_list retval;
@@ -216,42 +232,59 @@
 
   bool economy = false;
   bool is_cmplx = false;
-  bool b_mat = false;
-  int have_b = 0;
+  bool have_b = 0;
+  bool vector_p = 0;
 
   if (arg.is_complex_type ())
     is_cmplx = true;
   if (nargin > 1)
     {
-      have_b = 1;
+      have_b = true;
       if (args(nargin-1).is_scalar_type ())
         {
           int val = args(nargin-1).int_value ();
           if (val == 0)
             {
               economy = true;
-              have_b = (nargin > 2 ? 2 : 0);
+              have_b = (nargin > 2);
             }
+          else if (nargin == 3)   // argument 3 should be 0 or a string
+            print_usage ();
         }
-      else if (args(nargin-1).is_matrix_type ())
-          b_mat = true;
-      if (have_b > 0 && args(have_b).is_complex_type ())
+      else if (args(nargin-1).is_string ())
+        {
+          if (args(nargin-1).string_value () == "vector")
+            vector_p = true;
+          else if (args(nargin-1).string_value () != "matrix")
+            error ("qr: type for P must be 'matrix' or 'vector', not %s",
+                   args(nargin-1).string_value ().c_str ());
+          have_b = (nargin > 2);
+        }
+      else if (! args(nargin-1).is_matrix_type ())
+        err_wrong_type_arg ("qr", args(nargin-1));
+      else if (nargin == 3)   // should be caught by is_scalar_type or is_string
+        print_usage ();
+
+      if (have_b && args(1).is_complex_type ())
         is_cmplx = true;
     }
 
   if (arg.is_sparse_type ())
     {
+      if (nargout > 2)
+        error ("qr: Permutation output is not supported for sparse input");
 
       if (is_cmplx)
         {
           sparse_qr<SparseComplexMatrix> q (arg.sparse_complex_matrix_value ());
 
-          if (have_b > 0)
+          if (have_b)
             {
-              retval = ovl (q.C (args(have_b).complex_matrix_value ()),
+              retval = ovl (q.C (args(1).complex_matrix_value ()),
                             q.R (economy));
               if (arg.rows () < arg.columns ())
-                warning ("qr: non minimum norm solution for under-determined problem");
+                warning ("qr: non minimum norm solution for under-determined "
+                         "problem %dx%d", arg.rows (), arg.columns ());
             }
           else if (nargout > 1)
             retval = ovl (q.Q (), q.R (economy));
@@ -262,11 +295,12 @@
         {
           sparse_qr<SparseMatrix> q (arg.sparse_matrix_value ());
 
-          if (have_b > 0)
+          if (have_b)
             {
-              retval = ovl (q.C (args(have_b).matrix_value ()), q.R (economy));
-              if (args(0).rows () < args(0).columns ())
-                warning ("qr: non minimum norm solution for under-determined problem");
+              retval = ovl (q.C (args(1).matrix_value ()), q.R (economy));
+              if (arg.rows () < arg.columns ())
+                warning ("qr: non minimum norm solution for under-determined "
+                         "problem %dx%d", arg.rows (), arg.columns ());
             }
           else if (nargout > 1)
             retval = ovl (q.Q (), q.R (economy));
@@ -299,7 +333,7 @@
                   {
                     qr<FloatMatrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
-                    if (b_mat)
+                    if (have_b)
                       {
                         if (is_cmplx)
                           retval(0) = fact.Q ().transpose ()
@@ -315,7 +349,7 @@
                   {
                     qrp<FloatMatrix> fact (m, type);
 
-                    if (type == qr<FloatMatrix>::economy)
+                    if (type == qr<FloatMatrix>::economy || vector_p)
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
                     else
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -344,7 +378,7 @@
                   {
                     qr<FloatComplexMatrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
-                    if (b_mat)
+                    if (have_b)
                       retval (0) = conj (fact.Q ().transpose ())
                                    * args(1).float_complex_matrix_value ();
                   }
@@ -353,7 +387,7 @@
                 default:
                   {
                     qrp<FloatComplexMatrix> fact (m, type);
-                    if (type == qr<FloatComplexMatrix>::economy)
+                    if (type == qr<FloatComplexMatrix>::economy || vector_p)
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
                     else
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -384,7 +418,7 @@
                   {
                     qr<Matrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
-                    if (b_mat)
+                    if (have_b)
                       {
                         if (is_cmplx)
                           retval(0) = fact.Q ().transpose ()
@@ -399,7 +433,7 @@
                 default:
                   {
                     qrp<Matrix> fact (m, type);
-                    if (type == qr<Matrix>::economy)
+                    if (type == qr<Matrix>::economy || vector_p)
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
                     else
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -428,7 +462,7 @@
                   {
                     qr<ComplexMatrix> fact (m, type);
                     retval = ovl (fact.Q (), get_qr_r (fact));
-                    if (b_mat)
+                    if (have_b)
                       retval (0) = conj (fact.Q ().transpose ())
                                    * args(1).complex_matrix_value ();
                   }
@@ -437,7 +471,7 @@
                 default:
                   {
                     qrp<ComplexMatrix> fact (m, type);
-                    if (type == qr<ComplexMatrix>::economy)
+                    if (type == qr<ComplexMatrix>::economy || vector_p)
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.Pvec ());
                     else
                       retval = ovl (fact.Q (), get_qr_r (fact), fact.P ());
@@ -1206,11 +1240,11 @@
 Given a QR@tie{}factorization of a real or complex matrix
 @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and
 @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization of
-@w{[A(:,1:j-1) A(:,j+1:n)]}, i.e., @var{A} with one column deleted
-(if @var{orient} is @qcode{"col"}), or the QR@tie{}factorization of
-@w{[A(1:j-1,:);A(j+1:n,:)]}, i.e., @var{A} with one row deleted (if
-@var{orient} is @qcode{"row"}).
-
+@w{[A(:,1:j-1), U, A(:,j:n)]},
+where @var{u} is a column vector to be inserted into @var{A}
+(if @var{orient} is @qcode{\"col\"}),
+or the QR@tie{}factorization of @w{[A(1:j-1,:);X;A(:,j:n)]},
+where @var{x} is a row @var{orient} is @qcode{"row"}).
 The default value of @var{orient} is @qcode{"col"}.
 
 If @var{orient} is @qcode{"col"}, @var{j} may be an index vector
# HG changeset patch
# User Michael C. Grant <mcg@cvxr.com>
# Date 1393009232 21600
#      Fri Feb 21 13:00:32 2014 -0600
# Node ID 83963bad5e7d906541c56c8d6a4914ebbf7f1653
# Parent  99454a60bf5e33ba6e5f684fe7b3ad79ea2eb9ea
improvements to Qt & OpenGL linking on the Mac (bug #41574)

* configure.ac: Remove -Wl, prefixes from "-framework Carbon".
* acinclude.m4: Remove -Wl, prefixes from "-framework OpenGL".

diff -r 99454a60bf5e -r 83963bad5e7d configure.ac
--- a/configure.ac	Thu Jul 07 18:04:28 2016 +1000
+++ b/configure.ac	Fri Feb 21 13:00:32 2014 -0600
@@ -1230,8 +1230,8 @@
 if test $have_framework_carbon = yes; then
   AC_DEFINE(HAVE_FRAMEWORK_CARBON, 1,
     [Define to 1 if framework CARBON is available.])
-  CARBON_LIBS="-Wl,-framework -Wl,Carbon"
-  AC_MSG_NOTICE([adding -Wl,-framework -Wl,Carbon to CARBON_LIBS])
+  CARBON_LIBS="-framework Carbon"
+  AC_MSG_NOTICE([adding -framework Carbon to CARBON_LIBS])
   AC_SUBST(CARBON_LIBS)
 fi
 
diff -r 99454a60bf5e -r 83963bad5e7d m4/acinclude.m4
--- a/m4/acinclude.m4	Thu Jul 07 18:04:28 2016 +1000
+++ b/m4/acinclude.m4	Fri Feb 21 13:00:32 2014 -0600
@@ -1015,8 +1015,8 @@
   if test $have_framework_opengl = yes; then
     AC_DEFINE(HAVE_FRAMEWORK_OPENGL, 1,
       [Define to 1 if framework OPENGL is available.])
-    OPENGL_LIBS="-Wl,-framework -Wl,OpenGL"
-    AC_MSG_NOTICE([adding -Wl,-framework -Wl,OpenGL to OPENGL_LIBS])
+    OPENGL_LIBS="-framework OpenGL"
+    AC_MSG_NOTICE([adding -framework OpenGL to OPENGL_LIBS])
     OCTAVE_CHECK_FUNC_GLUTESSCALLBACK_THREEDOTS
   else
     case $canonical_host_type in
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470424149 -3600
#      Fri Aug 05 20:09:09 2016 +0100
# Node ID cfa684a0539da407b92c417a9be1c69f9cedcf33
# Parent  83963bad5e7d906541c56c8d6a4914ebbf7f1653
qr.cc: make use of Texinfo macro @dots instead of ... (bug #46912)

diff -r 83963bad5e7d -r cfa684a0539d libinterp/dldfcn/qr.cc
--- a/libinterp/dldfcn/qr.cc	Fri Feb 21 13:00:32 2014 -0600
+++ b/libinterp/dldfcn/qr.cc	Fri Aug 05 20:09:09 2016 +0100
@@ -80,9 +80,9 @@
 @deftypefnx {} {@var{X} =} qr (@var{A})
 @deftypefnx {} {@var{R} =} qr (@var{A})  # sparse A
 @deftypefnx {} {[@var{C}, @var{R}] =} qr (@var{A}, @var{B})
-@deftypefnx {} {[...] =} qr (..., 0)
-@deftypefnx {} {[...] =} qr (..., 'vector')
-@deftypefnx {} {[...] =} qr (..., 'matrix')
+@deftypefnx {} {[@dots{}] =} qr (@dots{}, 0)
+@deftypefnx {} {[@dots{}] =} qr (@dots{}, 'vector')
+@deftypefnx {} {[@dots{}] =} qr (@dots{}, 'matrix')
 @cindex QR factorization
 Compute the QR@tie{}factorization of @var{A}, using standard @sc{lapack}
 subroutines.
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470431052 -3600
#      Fri Aug 05 22:04:12 2016 +0100
# Node ID 30eefd9ddb48071b40271262d16a4f926fae42e6
# Parent  cfa684a0539da407b92c417a9be1c69f9cedcf33
prepad, postpad: do nothing wen input is already of the right size.

diff -r cfa684a0539d -r 30eefd9ddb48 scripts/general/postpad.m
--- a/scripts/general/postpad.m	Fri Aug 05 20:09:09 2016 +0100
+++ b/scripts/general/postpad.m	Fri Aug 05 22:04:12 2016 +0100
@@ -73,7 +73,15 @@
 
   d = sz(dim);
 
-  if (d >= l)
+  if (d == l)
+    ## This optimization makes sense because the function is used to match
+    ## the length between two vectors not knowing a priori is larger, and
+    ## allow for:
+    ##    ml = max (numel (v1), numel (v2));
+    ##    v1 = postpad (v1, ml);
+    ##    v2 = postpad (v2, ml);
+    y = x;
+  elseif (d >= l)
     idx = repmat ({':'}, nd, 1);
     idx{dim} = 1:l;
     y = x(idx{:});
@@ -93,6 +101,10 @@
 %!assert (postpad ([1;2], 2, 2, 3), reshape ([1;2;2;2], 2, 1, 2))
 %!assert (postpad ([1,2], 2, 2, 3), reshape ([1,2,2,2], 1, 2, 2))
 
+%!assert (postpad ([1 2], 2), [1 2])
+%!assert (postpad ([1; 2], 2), [1; 2])
+%!assert (postpad ([1; 2], 2, 3, 2), [1 3; 2 3])
+
 %! ## Test with string concatenation (bug #44162)
 %!assert (postpad ("Octave", 16, "x"), "Octavexxxxxxxxxx")
 %!assert (postpad ("Octave", 4), "Octa")
diff -r cfa684a0539d -r 30eefd9ddb48 scripts/general/prepad.m
--- a/scripts/general/prepad.m	Fri Aug 05 20:09:09 2016 +0100
+++ b/scripts/general/prepad.m	Fri Aug 05 22:04:12 2016 +0100
@@ -73,7 +73,15 @@
 
   d = sz(dim);
 
-  if (d >= l)
+  if (d == l)
+    ## This optimization makes sense because the function is used to match
+    ## the length between two vectors not knowing a priori is larger, and
+    ## allow for:
+    ##    ml = max (numel (v1), numel (v2));
+    ##    v1 = prepad (v1, ml);
+    ##    v2 = prepad (v2, ml);
+    y = x;
+  elseif (d >= l)
     idx = repmat ({':'}, nd, 1);
     idx{dim} = d-l+1:d;
     y = x(idx{:});
@@ -91,6 +99,10 @@
 %!assert (prepad ([1,2], 4, 2), [2,2,1,2])
 %!assert (prepad ([1;2], 4, 2), [2;2;1;2])
 
+%!assert (prepad ([1 2], 2), [1 2])
+%!assert (prepad ([1; 2], 2), [1; 2])
+%!assert (prepad ([1; 2], 2, 3, 2), [3 1; 3 2])
+
 %!assert (prepad ([1,2], 2, 2, 1), [2,2;1,2])
 
 %!assert (prepad ([1,2], 2, 2, 3), reshape ([2,2,1,2], 1, 2, 2))
# HG changeset patch
# User Sahil Badyal <sbadyals@gmail.com>
# Date 1424969154 -19800
#      Thu Feb 26 22:15:54 2015 +0530
# Node ID 6065bd58db2be0a849d9bcec621dccf64ac6fdd1
# Parent  30eefd9ddb48071b40271262d16a4f926fae42e6
use contribute/donate consistently in GUI (bug #44335)

* main-window.h, main-window.cc (main_window::open_contribute_page):
Link to contribute.html instead of donate.html
(main_window::open_donate_page): New function.

diff -r 30eefd9ddb48 -r 6065bd58db2b libgui/src/main-window.cc
--- a/libgui/src/main-window.cc	Fri Aug 05 22:04:12 2016 +0100
+++ b/libgui/src/main-window.cc	Thu Feb 26 22:15:54 2015 +0530
@@ -636,16 +636,16 @@
 void
 main_window::open_contribute_page (void)
 {
+  QDesktopServices::openUrl (QUrl ("http://octave.org/contribute.html"));
+}
+
+void
+main_window::open_donate_page (void)
+{
   QDesktopServices::openUrl (QUrl ("http://octave.org/donate.html"));
 }
 
 void
-main_window::open_developer_page (void)
-{
-  QDesktopServices::openUrl (QUrl ("http://octave.org/get-involved.html"));
-}
-
-void
 main_window::process_settings_dialog_request (const QString& desired_tab)
 {
   if (_settings_dlg)  // _settings_dlg is a guarded pointer!
@@ -1995,10 +1995,10 @@
             tr ("Share Code"), SLOT (open_agora_page ()));
 
   _contribute_action = add_action (help_menu, QIcon (),
-            tr ("Contribute to Octave"), SLOT (open_contribute_page ()));
+            tr ("Contribute"), SLOT (open_contribute_page ()));
 
   _developer_action = add_action (help_menu, QIcon (),
-            tr ("Octave Developer Resources"), SLOT (open_developer_page ()));
+            tr ("Donate to Octave"), SLOT (open_donate_page ()));
 
   help_menu->addSeparator ();
 
diff -r 30eefd9ddb48 -r 6065bd58db2b libgui/src/main-window.h
--- a/libgui/src/main-window.h	Fri Aug 05 22:04:12 2016 +0100
+++ b/libgui/src/main-window.h	Thu Feb 26 22:15:54 2015 +0530
@@ -133,7 +133,7 @@
   void open_octave_packages_page (void);
   void open_agora_page (void);
   void open_contribute_page (void);
-  void open_developer_page (void);
+  void open_donate_page (void);
   void process_settings_dialog_request (const QString& desired_tab
                                                          = QString ());
 
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470453307 -3600
#      Sat Aug 06 04:15:07 2016 +0100
# Node ID 2b487dbe419d00f76274328cf0e688e5bafcc21b
# Parent  6065bd58db2be0a849d9bcec621dccf64ac6fdd1
dim-vector.h (ndims): do not return a reference to the rep.

* dim-vector.h (ndims): this methods was only made public recently
with dcee67d28570 and is not used anywhere else.  It would expose
the rep for no gain, so always return the int by copy.
* dim-vector.cc: access the ndims on rep directly.

diff -r 6065bd58db2b -r 2b487dbe419d liboctave/array/dim-vector.cc
--- a/liboctave/array/dim-vector.cc	Thu Feb 26 22:15:54 2015 +0530
+++ b/liboctave/array/dim-vector.cc	Sat Aug 06 04:15:07 2016 +0100
@@ -63,7 +63,7 @@
   if (j == 1)
     rep[1] = 1;
 
-  ndims () = j > 2 ? j : 2;
+  rep[-1] = j > 2 ? j : 2;
 }
 
 std::string
diff -r 6065bd58db2b -r 2b487dbe419d liboctave/array/dim-vector.h
--- a/liboctave/array/dim-vector.h	Thu Feb 26 22:15:54 2015 +0530
+++ b/liboctave/array/dim-vector.h	Sat Aug 06 04:15:07 2016 +0100
@@ -243,7 +243,7 @@
         do
           l--;
         while (l > 2 && rep[l-1] == 1);
-        ndims () = l;
+        rep[-1] = l;
       }
   }
 
@@ -303,7 +303,7 @@
       elements in the dim_vector including trailing singetons.  It is also
       the number of dimensions an Array with this dim_vector would have.
   */
-  octave_idx_type& ndims (void) const { return rep[-1]; }
+  octave_idx_type ndims (void) const { return rep[-1]; }
 
   //! Number of dimensions.
   //! Synonymous with ndims().
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470457114 -3600
#      Sat Aug 06 05:18:34 2016 +0100
# Node ID 1723063e65f3b7598f3e5a690f0e85025cca3eb0
# Parent  2b487dbe419d00f76274328cf0e688e5bafcc21b
dim-vector: add missing, and remove unecessary, #includes.

diff -r 2b487dbe419d -r 1723063e65f3 liboctave/array/dim-vector.cc
--- a/liboctave/array/dim-vector.cc	Sat Aug 06 04:15:07 2016 +0100
+++ b/liboctave/array/dim-vector.cc	Sat Aug 06 05:18:34 2016 +0100
@@ -25,7 +25,10 @@
 #  include "config.h"
 #endif
 
-#include <iostream>
+#include <sstream>
+#include <limits>
+#include <string>
+#include <new>
 
 #include "dim-vector.h"
 
diff -r 2b487dbe419d -r 1723063e65f3 liboctave/array/dim-vector.h
--- a/liboctave/array/dim-vector.h	Sat Aug 06 04:15:07 2016 +0100
+++ b/liboctave/array/dim-vector.h	Sat Aug 06 05:18:34 2016 +0100
@@ -27,9 +27,7 @@
 #include "octave-config.h"
 
 #include <cassert>
-#include <limits>
 
-#include <sstream>
 #include <string>
 
 #include "lo-error.h"
# HG changeset patch
# User Lachlan Andrew <lachlanbis@gmail.com>
# Date 1470523640 -3600
#      Sat Aug 06 23:47:20 2016 +0100
# Node ID 0ff3bd7d2750d4a1c4e7b21f9e84564f50353114
# Parent  1723063e65f3b7598f3e5a690f0e85025cca3eb0
mahalanobis: alternative for performance improvement (bug #45877)

diff -r 1723063e65f3 -r 0ff3bd7d2750 scripts/deprecated/mahalanobis.m
--- a/scripts/deprecated/mahalanobis.m	Sat Aug 06 05:18:34 2016 +0100
+++ b/scripts/deprecated/mahalanobis.m	Sat Aug 06 23:47:20 2016 +0100
@@ -76,13 +76,10 @@
 
   w = (x' * x + y' * y) / (xr + yr - 2);
 
-  winv = inv (w);
-
-  retval = (xm - ym) * winv * (xm - ym)';
+  retval = sumsq ((xm - ym) / chol (w));
 
 endfunction
 
-
 ## Test input validation
 %!error mahalanobis ()
 %!error mahalanobis (1, 2, 3)
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470539898 -3600
#      Sun Aug 07 04:18:18 2016 +0100
# Node ID a4551d2b5da5f73599e4a8a34c9fbe400db95618
# Parent  1723063e65f3b7598f3e5a690f0e85025cca3eb0
repmat.m: add test for input with zero length dimensions.

diff -r 1723063e65f3 -r a4551d2b5da5 scripts/general/repmat.m
--- a/scripts/general/repmat.m	Sat Aug 06 05:18:34 2016 +0100
+++ b/scripts/general/repmat.m	Sun Aug 07 04:18:18 2016 +0100
@@ -204,6 +204,9 @@
 %!assert (size (repmat (1, [0, 1])), [0, 1])
 %!assert (size (repmat (1, [0, 5])), [0, 5])
 
+%!assert (size (repmat (ones (0, 3), [2 3])), [0 9])
+%!assert (size (repmat (ones (0, 0, 3), [2 3])), [0 0 3])
+
 %!shared x
 %! x = struct ("a", [], "b", []);
 %!assert (size (repmat (x, [1, 0])), [1, 0])
@@ -217,4 +220,3 @@
 %!assert (size (repmat ({1}, [0, 5])), [0, 5])
 
 %!error (size (repmat (".", -1, -1)))
-
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470540074 -3600
#      Sun Aug 07 04:21:14 2016 +0100
# Node ID f99c0b8cb67bdef50be6f7384e1d7e1c9f8de95b
# Parent  0ff3bd7d2750d4a1c4e7b21f9e84564f50353114
# Parent  a4551d2b5da5f73599e4a8a34c9fbe400db95618
maint: merge away accidental head.

diff -r 0ff3bd7d2750 -r f99c0b8cb67b scripts/general/repmat.m
--- a/scripts/general/repmat.m	Sat Aug 06 23:47:20 2016 +0100
+++ b/scripts/general/repmat.m	Sun Aug 07 04:21:14 2016 +0100
@@ -204,6 +204,9 @@
 %!assert (size (repmat (1, [0, 1])), [0, 1])
 %!assert (size (repmat (1, [0, 5])), [0, 5])
 
+%!assert (size (repmat (ones (0, 3), [2 3])), [0 9])
+%!assert (size (repmat (ones (0, 0, 3), [2 3])), [0 0 3])
+
 %!shared x
 %! x = struct ("a", [], "b", []);
 %!assert (size (repmat (x, [1, 0])), [1, 0])
@@ -217,4 +220,3 @@
 %!assert (size (repmat ({1}, [0, 5])), [0, 5])
 
 %!error (size (repmat (".", -1, -1)))
-
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470595180 -3600
#      Sun Aug 07 19:39:40 2016 +0100
# Node ID 3ac380d46d5481f9e423d070a6da58d7a7214662
# Parent  f99c0b8cb67bdef50be6f7384e1d7e1c9f8de95b
chol: make option passed as string case insensitive.

* libinterp/dldfcn/chol.cc: make comparison of strings for options case
insensitive.  Add tests.  Add missing include for <string> which is used
elsewhere in the file.

diff -r f99c0b8cb67b -r 3ac380d46d54 libinterp/dldfcn/chol.cc
--- a/libinterp/dldfcn/chol.cc	Sun Aug 07 04:21:14 2016 +0100
+++ b/libinterp/dldfcn/chol.cc	Sun Aug 07 19:39:40 2016 +0100
@@ -26,11 +26,14 @@
 #  include "config.h"
 #endif
 
+#include <string>
+
 #include "chol.h"
 #include "sparse-chol.h"
 #include "oct-spparms.h"
 #include "sparse-util.h"
 
+#include "caseless-str.h"
 #include "ov-re-sparse.h"
 #include "ov-cx-sparse.h"
 #include "defun-dld.h"
@@ -160,13 +163,13 @@
   int n = 1;
   while (n < nargin)
     {
-      std::string tmp = args(n++).xstring_value ("chol: optional arguments must be strings");
+      caseless_str tmp = args(n++).xstring_value ("chol: optional arguments must be strings");
 
-      if (tmp == "vector")
+      if (tmp.compare ("vector"))
         vecout = true;
-      else if (tmp == "lower")
+      else if (tmp.compare ("lower"))
         LLt = true;
-      else if (tmp == "upper")
+      else if (tmp.compare ("upper"))
         LLt = false;
       else
         error ("chol: optional argument must be one of \"vector\", \"lower\", or \"upper\"");
@@ -313,6 +316,16 @@
 /*
 %!assert (chol ([2, 1; 1, 1]), [sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)], sqrt (eps))
 %!assert (chol (single ([2, 1; 1, 1])), single ([sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)]), sqrt (eps ("single")))
+
+%!assert (chol ([2, 1; 1, 1], "upper"), [sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)],
+%!        sqrt (eps))
+%!assert (chol ([2, 1; 1, 1], "lower"), [sqrt(2), 0; 1/sqrt(2), 1/sqrt(2)],
+%!        sqrt (eps))
+
+%!assert (chol ([2, 1; 1, 1], "lower"), chol ([2, 1; 1, 1], "LoweR"))
+%!assert (chol ([2, 1; 1, 1], "upper"), chol ([2, 1; 1, 1], "Upper"))
+%!assert (chol ([2, 1; 1, 1], "vector"), chol ([2, 1; 1, 1], "VECTOR"))
+
 %!testif HAVE_CHOLMOD
 %! ## Bug #42587
 %! A = sparse ([1 0 8;0 1 8;8 8 1]);
# HG changeset patch
# User Rik <rik@octave.org>
# Date 1470617623 25200
#      Sun Aug 07 17:53:43 2016 -0700
# Node ID 6bb0f32d22a55ff23a3e9e866becc3b68d700a90
# Parent  3ac380d46d5481f9e423d070a6da58d7a7214662
axis.m: Clean up formatting in %!error tests.

* axis.m: Clean up formatting in %!error tests.

diff -r 3ac380d46d54 -r 6bb0f32d22a5 scripts/plot/appearance/axis.m
--- a/scripts/plot/appearance/axis.m	Sun Aug 07 19:39:40 2016 +0100
+++ b/scripts/plot/appearance/axis.m	Sun Aug 07 17:53:43 2016 -0700
@@ -645,16 +645,16 @@
 
 ## Even on errors, axis can display a figure.
 
-%!error<LIMITS vector must have .* elements>
-%! hf= figure ("visible", "off");
+%!error <LIMITS vector must have .* elements>
+%! hf = figure ("visible", "off");
 %! unwind_protect
 %!   axis (1:5)
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
 
-%!error<expecting no args, or a numeric vector with .* elements>
-%! hf= figure ("visible", "off");
+%!error <expecting no args, or a numeric vector with .* elements>
+%! hf = figure ("visible", "off");
 %! unwind_protect
 %!   axis ({1,2})
 %! unwind_protect_cleanup
# HG changeset patch
# User Andreas Weber <andy.weber.aw@gmail.com>
# Date 1470634229 -7200
#      Mon Aug 08 07:30:29 2016 +0200
# Node ID 6f1887b237d559c68cb381c37805eb4bc92b2fbd
# Parent  6bb0f32d22a55ff23a3e9e866becc3b68d700a90
compare_plot_demos.m: Fix default path on Windows (Bug #48717)

diff -r 6bb0f32d22a5 -r 6f1887b237d5 scripts/testfun/private/compare_plot_demos.m
--- a/scripts/testfun/private/compare_plot_demos.m	Sun Aug 07 17:53:43 2016 -0700
+++ b/scripts/testfun/private/compare_plot_demos.m	Mon Aug 08 07:30:29 2016 +0200
@@ -46,7 +46,8 @@
 function compare_plot_demos (varargin)
 
   arg.toolkits = available_graphics_toolkits ();
-  arg.directories = {"plot/appearance", "plot/draw", "plot/util", "image"};
+  arg.directories = fullfile ("plot", {"appearance", "draw", "util"});
+  arg.directories(end + 1) = "image";
   arg.fmt = "png";
   arg.fcn_file = "dump_plot_demos.m";
   arg.replace_images = false;
# HG changeset patch
# User Andreas Weber <andy.weber.aw@gmail.com>
# Date 1470634597 -7200
#      Mon Aug 08 07:36:37 2016 +0200
# Node ID a8a9c275e12d39e00b304cead620662d1cd66dff
# Parent  6f1887b237d559c68cb381c37805eb4bc92b2fbd
dump_demos: remove duplicate default args

The default args for directories, print format and so on
are already set in compare_plot_demos.m which should be used to
call dump_demos.m

diff -r 6f1887b237d5 -r a8a9c275e12d scripts/testfun/private/dump_demos.m
--- a/scripts/testfun/private/dump_demos.m	Mon Aug 08 07:30:29 2016 +0200
+++ b/scripts/testfun/private/dump_demos.m	Mon Aug 08 07:36:37 2016 +0200
@@ -17,28 +17,12 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {} {} dump_demos ()
-## @deftypefnx {} {} dump_demos (@var{dirs})
-## @deftypefnx {} {} dump_demos (@var{dirs}, @var{mfile})
-## @deftypefnx {} {} dump_demos (@var{dirs}, @var{mfile}, @var{fmt})
+## @deftypefn {} {} dump_demos (@var{dirs}, @var{mfile}, @var{fmt})
 ## Produce a script, with the name specified by @var{mfile}, containing
 ## the demos in the directories, @var{dirs}.  The demos are assumed to produce
 ## graphical output, whose renderings are saved with the specified format,
 ## @var{fmt}.
 ##
-## The defaults for each input are;
-##
-## @table @var
-##   @item @var{dirs}
-##   @code{@{"plot/appearance", "plot/draw", "plot/util", "image"@}}
-##
-##   @item @var{mfile}
-##   @qcode{"dump.m"}
-##
-##   @item @var{fmt}
-##   @qcode{"png"}
-## @end table
-##
 ## For example, to produce PNG output for all demos of the functions
 ## in the plot directory;
 ##
@@ -50,9 +34,9 @@
 
 ## Author: Søren Hauberg  <soren@hauberg.org>
 
-function dump_demos (dirs={"plot/appearance", "plot/draw", "plot/util", "image"}, output="dump_plot_demos.m", fmt="png")
+function dump_demos (dirs, output, fmt)
 
-  if (nargin > 3)
+  if (nargin != 3)
     print_usage ();
   endif
 
# HG changeset patch
# User Rik <rik@octave.org>
# Date 1470682986 25200
#      Mon Aug 08 12:03:06 2016 -0700
# Node ID fddc5604d1fa2c8157b4c5391e96427380c9d5b1
# Parent  a8a9c275e12d39e00b304cead620662d1cd66dff
__opengl_info__.m: Tide code and fix to work with fltk toolkit.

* __opengl_info__.m: Remove type specifier "Function File" from @deftypefn
macro.  Use '##' as prefix for full-line comments.  Eliminate extra checks
for "isempty (info)" in for loop.  Loop directly over available graphics
handles rather than over index to graphics handle list.  Draw an axes object
on blank figure in order to force FLTK toolkit to populate OpenGL fields.
Use drawnow() rather than a 1 second waitfor() delay in order to force
graphics system to populate OpenGL fields.

diff -r a8a9c275e12d -r fddc5604d1fa scripts/plot/util/__opengl_info__.m
--- a/scripts/plot/util/__opengl_info__.m	Mon Aug 08 07:36:37 2016 +0200
+++ b/scripts/plot/util/__opengl_info__.m	Mon Aug 08 12:03:06 2016 -0700
@@ -14,8 +14,8 @@
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} __opengl_info__
-## @deftypefnx {Function File} {@var{retval} =} __opengl_info__ ()
+## @deftypefn  {} {} __opengl_info__
+## @deftypefnx {} {@var{retval} =} __opengl_info__ ()
 ##
 ## Get OpenGL driver information.
 ##
@@ -24,13 +24,17 @@
 ## in a structure.
 ##
 ## Fields in the structure are:
+##
 ## @table @asis
 ## @item version
 ## OpenGL Driver version string
+##
 ## @item vendor
 ## OpenGL Driver vendor string
+##
 ## @item renderer
 ## OpenGL renderer string
+##
 ## @item extensions
 ## List of enabled extensions for the OpenGL driver.
 ## @end table
@@ -43,14 +47,16 @@
 
 function retval = __opengl_info__ ()
 
-  # currently we only handle a single argument
+  ## currently we only handle a single argument
   if (nargin != 0)
     print_usage ();
   endif
 
   [info, msg] = gl_info ();
 
-  if (isempty (msg))
+  if (! isempty (msg))
+    warning (msg);
+  else
     if (nargout == 0)
       printf ("version    = %s\n", info.version);
       printf ("vendor     = %s\n", info.vendor);
@@ -60,14 +66,13 @@
     else
       retval = info;
     endif
-  else
-    warning (msg);
   endif
 
 endfunction
 
 function info = fig_gl_info (h)
   info = [];
+
   if (ishandle (h) && strcmp (get (h, "renderer"), "opengl"))
     vers = get (h, "__gl_version__");
     vend = get (h, "__gl_vendor__");
@@ -87,23 +92,21 @@
   msg = "";
 
   ## If we have any open figures, take a look for any OpenGL info.
-
   figs = findall (0, "type", "figure");
 
-  for i = 1:numel (figs)
-    if (isempty (info))
-      info = fig_gl_info (figs(i));
-      if (! isempty (info))
-        break
-      endif
+  for hf = figs.'
+    info = fig_gl_info (hf);
+    if (! isempty (info))
+      break;
     endif
   endfor
 
-  ## If no info yet, try open a figure brifly to get the info.
-
+  ## If no info yet, try open a figure to get the info.
   if (isempty (info))
+    ## Need to create a figure, place an OpenGL object, and force drawing.
     h = figure ("position", [0,0,1,1], "toolbar", "none", "menubar", "none");
-    waitfor (h, "timeout", 1);
+    hax = axes ();
+    drawnow ();
     info = fig_gl_info (h);
     close (h);
   endif
@@ -119,3 +122,4 @@
 %! a = __opengl_info__ ();
 %! assert (! isempty (a))
 %! assert (isfield (a, "version"))
+
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470685572 -3600
#      Mon Aug 08 20:46:12 2016 +0100
# Node ID 8a50ab960ae64ccbef653f8e0d9aeff89230fea6
# Parent  fddc5604d1fa2c8157b4c5391e96427380c9d5b1
dim-vector.h: remove duplicated code.

diff -r fddc5604d1fa -r 8a50ab960ae6 liboctave/array/dim-vector.h
--- a/liboctave/array/dim-vector.h	Mon Aug 08 12:03:06 2016 -0700
+++ b/liboctave/array/dim-vector.h	Mon Aug 08 20:46:12 2016 +0100
@@ -111,10 +111,7 @@
   {
     int l = ndims ();
 
-    octave_idx_type *r = new octave_idx_type [l + 2];
-
-    *r++ = 1;
-    *r++ = l;
+    octave_idx_type* r = newrep (l);
 
     for (int i = 0; i < l; i++)
       r[i] = rep[i];
@@ -131,16 +128,13 @@
     if (n < 2)
       n = 2;
 
-    octave_idx_type *r = new octave_idx_type [n + 2];
-
-    *r++ = 1;
-    *r++ = n;
+    octave_idx_type* r = newrep (n);
 
     if (l > n)
       l = n;
 
-    int j;
-    for (j = 0; j < l; j++)
+    int j = 0;
+    for (; j < l; j++)
       r[j] = rep[j];
     for (; j < n; j++)
       r[j] = fill_value;
@@ -474,19 +468,11 @@
     return def;
   }
 
-  //! Compute a linear index from an index tuple.
+  //! Linear index from an index tuple.
+  octave_idx_type compute_index (const octave_idx_type* idx) const
+  { return compute_index (idx, ndims ()); }
 
-  octave_idx_type compute_index (const octave_idx_type *idx) const
-  {
-    octave_idx_type k = 0;
-    for (int i = ndims () - 1; i >= 0; i--)
-      k = rep[i] * k + idx[i];
-
-    return k;
-  }
-
-  //! Ditto, but the tuple may be incomplete (nidx < length ()).
-
+  //! Linear index from an incomplete index tuple (nidx < length ()).
   octave_idx_type compute_index (const octave_idx_type *idx, int nidx) const
   {
     octave_idx_type k = 0;
# HG changeset patch
# User Lachlan Andrew <lachlanbis@gmail.com>
# Date 1455185205 -39600
#      Thu Feb 11 21:06:45 2016 +1100
# Node ID cf18d6e791a140b7df0dd32b32354d975c5554a1
# Parent  8a50ab960ae64ccbef653f8e0d9aeff89230fea6
Prevent Octave:language-extension from becoming an error (bug #44336).

* error.cc (Fwarning): Explicitly set Octave:language-extension=off
  when setting warning ("error", "all").

diff -r 8a50ab960ae6 -r cf18d6e791a1 libinterp/corefcn/error.cc
--- a/libinterp/corefcn/error.cc	Mon Aug 08 20:46:12 2016 +0100
+++ b/libinterp/corefcn/error.cc	Thu Feb 11 21:06:45 2016 +1100
@@ -1562,45 +1562,26 @@
               // If "all" is explicitly given as ID.
 
               octave_map tmp;
+              int is_error = (arg1 == "error");
 
-              Cell id (1, 1);
-              Cell st (1, 1);
+              Cell id (1, 1 + 2*is_error);
+              Cell st (1, 1 + 2*is_error);
 
               id(0) = arg2;
               st(0) = arg1;
 
               // Since internal Octave functions are not compatible,
-              // turning all warnings into errors should leave the state of
-              // Octave:language-extension alone.
+              // and "all"=="error" causes any "on" to throw an error,
+              // turning all warnings into errors should disable
+              // Octave:language-extension.
 
-              if (arg1 == "error" && warning_options.contains ("identifier"))
+              if (is_error)
                 {
-                  octave_idx_type n = 1;
+                  id(1) = "Octave:language-extension";
+                  st(1) = "off";
 
-                  Cell tid = warning_options.contents ("identifier");
-                  Cell tst = warning_options.contents ("state");
-
-                  for (octave_idx_type i = 0; i < tid.numel (); i++)
-                    {
-                      octave_value vid = tid(i);
-
-                      if (vid.is_string ())
-                        {
-                          std::string key = vid.string_value ();
-
-                          if (key == "Octave:language-extension"
-                              || key == "Octave:single-quote-string")
-                            {
-                              id.resize (dim_vector (1, n+1));
-                              st.resize (dim_vector (1, n+1));
-
-                              id(n) = tid(i);
-                              st(n) = tst(i);
-
-                              n++;
-                            }
-                        }
-                    }
+                  id(2) = "Octave:single-quote-string";
+                  st(2) = "off";
                 }
 
               tmp.assign ("identifier", id);
# HG changeset patch
# User Lachlan Andrew <lachlanbis@gmail.com>
# Date 1456550196 -39600
#      Sat Feb 27 16:16:36 2016 +1100
# Node ID 20e0c0b8820c9c4094f018b54426e2b258c07654
# Parent  cf18d6e791a140b7df0dd32b32354d975c5554a1
Allow sequential quadratic programs with infeasible QPs (bug #36015).

* qp.m: Use conformant sizes of temporary C and lower bound in call to glpk.

* glpk.m: State size of A if its size doesn't match C and lb.

* sqp.m: If the QP was infeasible, restore lambda to the correct size.

diff -r cf18d6e791a1 -r 20e0c0b8820c scripts/optimization/glpk.m
--- a/scripts/optimization/glpk.m	Thu Feb 11 21:06:45 2016 +1100
+++ b/scripts/optimization/glpk.m	Sat Feb 27 16:16:36 2016 +1100
@@ -498,9 +498,13 @@
   if (isempty (A))
     error ("glpk: A cannot be an empty matrix");
   endif
+  if (! isreal (A))
+    error ("glpk: A must be real valued, not %s", typeinfo (A));
+  endif
   [nc, nxa] = size (A);
-  if (! isreal (A) || nxa != nx)
-    error ("glpk: A must be a real valued %d by %d matrix", nc, nx);
+  if (nxa != nx)
+    error ("glpk: A must be %d by %d, not %d by %d",
+           nc, nx, rows(A), columns(A));
   endif
 
   ## 3) RHS
diff -r cf18d6e791a1 -r 20e0c0b8820c scripts/optimization/qp.m
--- a/scripts/optimization/qp.m	Thu Feb 11 21:06:45 2016 +1100
+++ b/scripts/optimization/qp.m	Sat Feb 27 16:16:36 2016 +1100
@@ -373,8 +373,8 @@
             Atmp = [Ain, gamma];
             btmp = bin;
           endif
-          ctmp = [zeros(n-n_eq, 1); ones(n_in, 1)];
-          lb = [-Inf(n-n_eq,1); zeros(n_in,1)];
+          ctmp = [zeros(n, 1); ones(n_in, 1)];
+          lb = [-Inf(n,1); zeros(n_in,1)];
           ub = [];
           ctype = repmat ("L", n_in, 1);
           [P, dummy, status] = glpk (ctmp, Atmp, btmp, lb, ub, ctype);
diff -r cf18d6e791a1 -r 20e0c0b8820c scripts/optimization/sqp.m
--- a/scripts/optimization/sqp.m	Thu Feb 11 21:06:45 2016 +1100
+++ b/scripts/optimization/sqp.m	Sat Feb 27 16:16:36 2016 +1100
@@ -408,6 +408,7 @@
     g = -ce;
     d = -ci;
 
+    old_lambda = lambda;
     [p, obj_qp, INFO, lambda] = qp (x, B, c, F, g, [], [], d, C,
                                     Inf (size (d)));
 
@@ -425,6 +426,7 @@
                  INFO.solveiter);
       case 6
         warning (id, "sqp: QP subproblem is infeasible");
+        lambda = old_lambda;  # The return value was size 0x0 in this case.
     endswitch
 
     ## Choose mu such that p is a descent direction for the chosen
# HG changeset patch
# User Rik <rik@octave.org>
# Date 1470694863 25200
#      Mon Aug 08 15:21:03 2016 -0700
# Node ID 42456fc9bf6c0217fe855d64fc25b98fac86c32b
# Parent  20e0c0b8820c9c4094f018b54426e2b258c07654
glpk.m: Style fixes for cset 20e0c0b8820c.

* glpk.m: Use space between function name and opening parenthesis.

diff -r 20e0c0b8820c -r 42456fc9bf6c scripts/optimization/glpk.m
--- a/scripts/optimization/glpk.m	Sat Feb 27 16:16:36 2016 +1100
+++ b/scripts/optimization/glpk.m	Mon Aug 08 15:21:03 2016 -0700
@@ -504,7 +504,7 @@
   [nc, nxa] = size (A);
   if (nxa != nx)
     error ("glpk: A must be %d by %d, not %d by %d",
-           nc, nx, rows(A), columns(A));
+           nc, nx, rows (A), columns (A));
   endif
 
   ## 3) RHS
# HG changeset patch
# User Lachlan Andrew <lachlanbis@gmail.com>
# Date 1467275426 -36000
#      Thu Jun 30 18:30:26 2016 +1000
# Node ID 9a0e30e24b9bc943a92e33adbafe0c123e2d6b2a
# Parent  42456fc9bf6c0217fe855d64fc25b98fac86c32b
Calculate cov as Matlab does, not as its conjugate (bug #48315).

* NEWS: Announce change.

* cov.m: Remove "conj" from calculation of output.  Update compatibility note
to explain what Matlab actually does.

diff -r 42456fc9bf6c -r 9a0e30e24b9b NEWS
--- a/NEWS	Mon Aug 08 15:21:03 2016 -0700
+++ b/NEWS	Thu Jun 30 18:30:26 2016 +1000
@@ -1,8 +1,6 @@
 Summary of important user-visible changes for version 4.2:
 ---------------------------------------------------------
 
- ** condest now works with a normest1 compatible syntax.
-
  ** The parser has been extended to accept, but ignore, underscore
     characters in numbers.  This facilitates writing more legible code
     by using '_' as a thousands separator or to group nibbles into bytes
@@ -30,7 +28,7 @@
     to the old command "hold all" and was made for Matlab compatibility.
     Existing code *may* produce differently colored plots if it did not
     specify the color for a plot and relied on each new plot having the
-    the default first color in the "ColorOrder" property.
+    default first color in the "ColorOrder" property.
 
  ** When starting, Octave now looks in the function path for a file
     startup.m and executes any commands found there.  This change was
@@ -64,6 +62,12 @@
     compatible with Matlab releases newer than 2011.  In addition,
     Octave no longer supports matrix inputs for A or B.
 
+ ** The cov function now returns the complex conjugate of the result
+    from previous versions of Octave.  This change was made for
+    compatibility with Matlab.
+
+ ** condest now works with a normest1 compatible syntax.
+
  ** The griddata function no longer plots the interpolated mesh if no
     output argument is requested, instead the vector or array of
     interpolated values is always returned for Matlab compatibility.
diff -r 42456fc9bf6c -r 9a0e30e24b9b scripts/statistics/base/cov.m
--- a/scripts/statistics/base/cov.m	Mon Aug 08 15:21:03 2016 -0700
+++ b/scripts/statistics/base/cov.m	Thu Jun 30 18:30:26 2016 +1000
@@ -56,11 +56,13 @@
 ##   normalize with @math{N}, this provides the second moment around the mean
 ## @end table
 ##
-## Compatibility Note:: Octave always computes the covariance matrix.
-## For two inputs, however, @sc{matlab} will calculate
-## @code{cov (@var{x}(:), @var{y}(:))} whenever the number of elements in
-## @var{x} and @var{y} are equal.  This will result in a scalar rather than
-## a matrix output.  Code relying on this odd definition will need to be
+## Compatibility Note:: Octave always treats rows of @var{x} and @var{y}
+## as multivariate random variables.
+## For two inputs, however, @sc{matlab} treats @var{x} and @var{y} as two
+## univariate distributions regardless of their shapes, and will calculate
+## @code{cov ([@var{x}(:), @var{y}(:)])} whenever the number of elements in
+## @var{x} and @var{y} are equal.  This will result in a 2x2 matrix.
+## Code relying on @sc{Matlab}'s definition will need to be
 ## changed when running in Octave.
 ## @seealso{corr}
 ## @end deftypefn
@@ -108,7 +110,7 @@
 
   if (nargin == 1 || isscalar (y))
     x = center (x, 1);
-    c = conj (x' * x / (n - 1 + opt));
+    c = x' * x / (n - 1 + opt);
   else
     if (isrow (y))
       y = y.';
@@ -118,7 +120,7 @@
     endif
     x = center (x, 1);
     y = center (y, 1);
-    c = conj (x' * y / (n - 1 + opt));
+    c = x' * y / (n - 1 + opt);
   endif
 
 endfunction
# HG changeset patch
# User Lachlan Andrew <lachlanbis@gmail.com>
# Date 1465724302 -36000
#      Sun Jun 12 19:38:22 2016 +1000
# Node ID ab139f0733b92e8c482cfd52e862e3d01ea573b2
# Parent  9a0e30e24b9bc943a92e33adbafe0c123e2d6b2a
Document that "help OPERATOR" needs quotes around OPERATOR (bug #39349).

* help.m (help, do_list_operators): State that quotes are required.

* comma.m, paren.m, semicolon.m: Move do deprecated/ directory
from help directory.

* scripts/deprecated/module.mk: Add comma.m, paren.m, semicolon.m
to deprecated directory.

* scripts/help/module.mk: Remove comma.m, paren.m, semicolon.m
from help directory.

diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/deprecated/comma.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/comma.m	Sun Jun 12 19:38:22 2016 +1000
@@ -0,0 +1,28 @@
+## Copyright (C) 1995-2015 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {} ,
+## Array index, function argument, or command separator.
+## @seealso{semicolon}
+## @end deftypefn
+
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/deprecated/module.mk
--- a/scripts/deprecated/module.mk	Thu Jun 30 18:30:26 2016 +1000
+++ b/scripts/deprecated/module.mk	Sun Jun 12 19:38:22 2016 +1000
@@ -3,6 +3,7 @@
 scripts_deprecated_FCN_FILES = \
   scripts/deprecated/bicubic.m \
   scripts/deprecated/bitmax.m \
+  scripts/deprecated/comma.m \
   scripts/deprecated/delaunay3.m \
   scripts/deprecated/dump_prefs.m \
   scripts/deprecated/find_dir_in_path.m \
@@ -20,8 +21,10 @@
   scripts/deprecated/octave_config_info.m \
   scripts/deprecated/octave_tmp_file_name.m \
   scripts/deprecated/onenormest.m \
+  scripts/deprecated/paren.m \
   scripts/deprecated/playaudio.m \
   scripts/deprecated/saveaudio.m \
+  scripts/deprecated/semicolon.m \
   scripts/deprecated/setaudio.m \
   scripts/deprecated/sleep.m \
   scripts/deprecated/syl.m \
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/deprecated/paren.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/paren.m	Sun Jun 12 19:38:22 2016 +1000
@@ -0,0 +1,28 @@
+## Copyright (C) 1996-2015 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {} (
+## @deftypefnx {} {} )
+## Array index or function argument delimeter.
+## @end deftypefn
+
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/deprecated/semicolon.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/semicolon.m	Sun Jun 12 19:38:22 2016 +1000
@@ -0,0 +1,28 @@
+## Copyright (C) 1995-2015 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {} ;
+## Array row or command separator.
+## @seealso{comma}
+## @end deftypefn
+
+
+## Mark file as being tested.  No real test needed for a documentation .m file
+%!assert (1)
+
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/help/comma.m
--- a/scripts/help/comma.m	Thu Jun 30 18:30:26 2016 +1000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-## Copyright (C) 1995-2015 John W. Eaton
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} ,
-## Array index, function argument, or command separator.
-## @seealso{semicolon}
-## @end deftypefn
-
-
-## Mark file as being tested.  No real test needed for a documentation .m file
-%!assert (1)
-
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/help/help.m
--- a/scripts/help/help.m	Thu Jun 30 18:30:26 2016 +1000
+++ b/scripts/help/help.m	Sun Jun 12 19:38:22 2016 +1000
@@ -33,13 +33,13 @@
 ## Given the single argument @code{.}, list all operators available in the
 ## current session of Octave.
 ##
-## If invoked without any arguments, @code{help} display instructions on how to
-## access help from the command line.
+## If invoked without any arguments, @code{help} displays instructions on how
+## to access help from the command line.
 ##
-## The help command can provide information about most operators, for example
-## @code{help +}, but not the comma and semicolon characters which are used
-## by the Octave interpreter as command separators.  For help on either of
-## these type @kbd{help comma} or @kbd{help semicolon}.
+## The help command can provide information about most operators, but
+## @var{name} must be enclosed by single or double quotes to prevent
+## the Octave interpreter from acting on @var{name}.  For example,
+## @code{help "+"} displays help on the addition operator.
 ## @seealso{doc, lookfor, which, info}
 ## @end deftypefn
 
@@ -53,10 +53,10 @@
     help NAME\n\
 \n\
   (replace NAME with the name of the command or function you would\n\
-  like to learn more about).\n\
+  like to learn more about; for an operator, enclose NAME in quotes).\n\
 \n\
-  For a more detailed introduction to GNU Octave, please consult the\n\
-  manual.  To read the manual from the prompt type\n\
+  For a more detailed introduction to GNU Octave, consult the manual.\n\
+  The manual may be read from the prompt by typing\n\
 \n\
     doc\n\
 \n\
@@ -130,8 +130,10 @@
 endfunction
 
 function retval = do_list_operators ()
-  retval = sprintf ("*** operators:\n\n%s\n\n",
-                    list_in_columns (__operators__ ()));
+  retval = sprintf ("*** operators:\n\n%s\n%s\n\n",
+                    list_in_columns (__operators__ ()),
+                    ["To obtain help on an operator, type\n"...
+                     "      help \"NAME\"   or   help 'NAME'"]);
 endfunction
 
 function retval = do_list_functions ()
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/help/module.mk
--- a/scripts/help/module.mk	Thu Jun 30 18:30:26 2016 +1000
+++ b/scripts/help/module.mk	Sun Jun 12 19:38:22 2016 +1000
@@ -11,16 +11,13 @@
   scripts/help/__makeinfo__.m \
   scripts/help/__unimplemented__.m \
   scripts/help/ans.m \
-  scripts/help/comma.m \
   scripts/help/doc.m \
   scripts/help/doc_cache_create.m \
   scripts/help/get_first_help_sentence.m \
   scripts/help/error_ids.m \
   scripts/help/help.m \
   scripts/help/lookfor.m \
-  scripts/help/paren.m \
   scripts/help/print_usage.m \
-  scripts/help/semicolon.m \
   scripts/help/type.m \
   scripts/help/warning_ids.m \
   scripts/help/which.m
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/help/paren.m
--- a/scripts/help/paren.m	Thu Jun 30 18:30:26 2016 +1000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-## Copyright (C) 1996-2015 John W. Eaton
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {} {} (
-## @deftypefnx {} {} )
-## Array index or function argument delimeter.
-## @end deftypefn
-
-
-## Mark file as being tested.  No real test needed for a documentation .m file
-%!assert (1)
-
diff -r 9a0e30e24b9b -r ab139f0733b9 scripts/help/semicolon.m
--- a/scripts/help/semicolon.m	Thu Jun 30 18:30:26 2016 +1000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-## Copyright (C) 1995-2015 John W. Eaton
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} ;
-## Array row or command separator.
-## @seealso{comma}
-## @end deftypefn
-
-
-## Mark file as being tested.  No real test needed for a documentation .m file
-%!assert (1)
-
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470698496 -3600
#      Tue Aug 09 00:21:36 2016 +0100
# Node ID 4afe3705ea753511669b015220a42c3354353080
# Parent  ab139f0733b92e8c482cfd52e862e3d01ea573b2
svd: do not shadow member variables with local variables.

* liboctave/numeric/svd.cc, liboctave/numeric/svd.h: there was no issue
with current code because member variables never change after construction.
Still, it's not good practice and the compilers will warn about it.

diff -r ab139f0733b9 -r 4afe3705ea75 liboctave/numeric/svd.cc
--- a/liboctave/numeric/svd.cc	Sun Jun 12 19:38:22 2016 +1000
+++ b/liboctave/numeric/svd.cc	Tue Aug 09 00:21:36 2016 +0100
@@ -131,7 +131,7 @@
 T
 svd<T>::left_singular_matrix (void) const
 {
-  if (type == svd::Type::sigma_only)
+  if (m_type == svd::Type::sigma_only)
     (*current_liboctave_error_handler)
       ("svd: U not computed because type == svd::sigma_only");
 
@@ -142,7 +142,7 @@
 T
 svd<T>::right_singular_matrix (void) const
 {
-  if (type == svd::Type::sigma_only)
+  if (m_type == svd::Type::sigma_only)
     (*current_liboctave_error_handler)
       ("svd: V not computed because type == svd::sigma_only");
 
@@ -369,7 +369,7 @@
 template<typename T>
 svd<T>::svd (const T& a, svd::Type type,
              svd::Driver driver)
-  : type (type), driver (driver), left_sm (), sigma (), right_sm ()
+  : m_type (type), m_driver (driver), left_sm (), sigma (), right_sm ()
 {
   octave_idx_type info;
 
@@ -378,7 +378,7 @@
 
   if (m == 0 || n == 0)
     {
-      switch (type)
+      switch (m_type)
         {
         case svd::Type::std:
           left_sm = T (m, m, 0);
@@ -417,7 +417,7 @@
   octave_idx_type nrow_s = m;
   octave_idx_type ncol_s = n;
 
-  switch (type)
+  switch (m_type)
     {
     case svd::Type::economy:
       jobu = jobv = 'S';
@@ -464,10 +464,10 @@
   octave_idx_type m1 = std::max (m, 1);
   octave_idx_type nrow_vt1 = std::max (nrow_vt, 1);
 
-  if (driver == svd::Driver::GESVD)
+  if (m_driver == svd::Driver::GESVD)
     gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
            work, lwork, info);
-  else if (driver == svd::Driver::GESDD)
+  else if (m_driver == svd::Driver::GESDD)
     {
       assert (jobu == jobv);
       char jobz = jobu;
diff -r ab139f0733b9 -r 4afe3705ea75 liboctave/numeric/svd.h
--- a/liboctave/numeric/svd.h	Sun Jun 12 19:38:22 2016 +1000
+++ b/liboctave/numeric/svd.h	Tue Aug 09 00:21:36 2016 +0100
@@ -50,26 +50,26 @@
   };
 
   svd (void)
-    : type (), driver (), left_sm (), sigma (), right_sm ()
+    : m_type (), m_driver (), left_sm (), sigma (), right_sm ()
   { }
 
   svd (const T& a, svd::Type type = svd::Type::std,
        svd::Driver driver = svd::Driver::GESVD);
 
   svd (const svd& a)
-    : type (a.type), driver (a.driver), left_sm (a.left_sm), sigma (a.sigma),
-      right_sm (a.right_sm)
+    : m_type (a.m_type), m_driver (a.m_driver), left_sm (a.left_sm),
+      sigma (a.sigma), right_sm (a.right_sm)
   { }
 
   svd& operator = (const svd& a)
   {
     if (this != &a)
       {
-        type = a.type;
+        m_type = a.m_type;
         left_sm = a.left_sm;
         sigma = a.sigma;
         right_sm = a.right_sm;
-        driver = a.driver;
+        m_driver = a.m_driver;
       }
 
     return *this;
@@ -88,8 +88,8 @@
   typedef typename T::element_type P;
   typedef typename DM_T::element_type DM_P;
 
-  svd::Type type;
-  svd::Driver driver;
+  svd::Type m_type;
+  svd::Driver m_driver;
 
   T left_sm;
   DM_T sigma;
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470712495 -3600
#      Tue Aug 09 04:14:55 2016 +0100
# Node ID 22c2bd4405441a0c5be66b65f23b2b9578240add
# Parent  4afe3705ea753511669b015220a42c3354353080
chol: return permutation vector as row vector instead of column vector.

* libinterp/dldfcn/chol.cc: add tests for the vector option.  Also error
if there's a "vector" option but input was not sparse.  Existing test
for case sensitivity was also useless, since change is on the 3rd argument.
* liboctave/numeric/sparse-chol.cc, liboctave/numeric/sparse-chol.h: use
RowVector instead of ColumnVector for permutation vector, for Matlab
compatibility.

diff -r 4afe3705ea75 -r 22c2bd440544 libinterp/dldfcn/chol.cc
--- a/libinterp/dldfcn/chol.cc	Tue Aug 09 00:21:36 2016 +0100
+++ b/libinterp/dldfcn/chol.cc	Tue Aug 09 04:14:55 2016 +0100
@@ -249,6 +249,8 @@
     }
   else if (arg.is_single_type ())
     {
+      if (vecout)
+        error ("chol: A must be sparse for the \"vector\" option");
       if (arg.is_real_type ())
         {
           FloatMatrix m = arg.float_matrix_value ();
@@ -280,6 +282,8 @@
     }
   else
     {
+      if (vecout)
+        error ("chol: A must be sparse for the \"vector\" option");
       if (arg.is_real_type ())
         {
           Matrix m = arg.matrix_value ();
@@ -324,7 +328,25 @@
 
 %!assert (chol ([2, 1; 1, 1], "lower"), chol ([2, 1; 1, 1], "LoweR"))
 %!assert (chol ([2, 1; 1, 1], "upper"), chol ([2, 1; 1, 1], "Upper"))
-%!assert (chol ([2, 1; 1, 1], "vector"), chol ([2, 1; 1, 1], "VECTOR"))
+
+## Check the "vector" option which only affects the 3rd argument and
+## is only valid for sparse input.
+%!test
+%! a = sparse ([2 1; 1 1]);
+%! r = sparse ([sqrt(2), 1/sqrt(2); 0, 1/sqrt(2)]);
+%! [rd, pd, qd] = chol (a);
+%! [rv, pv, qv] = chol (a, "vector");
+%! assert (r, rd, eps)
+%! assert (r, rv, eps)
+%! assert (pd, 0)
+%! assert (pd, pv)
+%! assert (qd, sparse (eye (2)))
+%! assert (qv, [1 2])
+%!
+%! [rv, pv, qv] = chol (a, "Vector"); # check case sensitivity
+%! assert (r, rv, eps)
+%! assert (pd, pv)
+%! assert (qv, [1 2])
 
 %!testif HAVE_CHOLMOD
 %! ## Bug #42587
@@ -338,6 +360,7 @@
 %!error <optional arguments must be strings> chol (1, 2)
 %!error <optional argument must be one of "vector", "lower"> chol (1, "foobar")
 %!error <matrix A must be sparse> [L,p,Q] = chol ([1, 2; 3, 4])
+%!error <A must be sparse> [L, p] = chol ([1, 2; 3, 4], "vector")
 */
 
 DEFUN_DLD (cholinv, args, ,
diff -r 4afe3705ea75 -r 22c2bd440544 liboctave/numeric/sparse-chol.cc
--- a/liboctave/numeric/sparse-chol.cc	Tue Aug 09 00:21:36 2016 +0100
+++ b/liboctave/numeric/sparse-chol.cc	Tue Aug 09 04:14:55 2016 +0100
@@ -92,7 +92,7 @@
 #endif
   }
 
-  ColumnVector perm (void) const { return perms + 1; }
+  RowVector perm (void) const { return perms + 1; }
 
   SparseMatrix Q (void) const;
 
@@ -108,7 +108,7 @@
 
   octave_idx_type minor_p;
 
-  ColumnVector perms;
+  RowVector perms;
 
   double cond;
 
@@ -474,7 +474,7 @@
 }
 
 template <typename chol_type>
-ColumnVector
+RowVector
 sparse_chol<chol_type>::perm (void) const
 {
   return rep->perm ();
@@ -511,7 +511,7 @@
 
   cholmod_sparse *m = rep->L ();
   octave_idx_type n = m->ncol;
-  ColumnVector perms = rep->perm ();
+  RowVector perms = rep->perm ();
   double rcond2;
   octave_idx_type info;
   MatrixType mattype (MatrixType::Upper);
diff -r 4afe3705ea75 -r 22c2bd440544 liboctave/numeric/sparse-chol.h
--- a/liboctave/numeric/sparse-chol.h	Tue Aug 09 00:21:36 2016 +0100
+++ b/liboctave/numeric/sparse-chol.h	Tue Aug 09 04:14:55 2016 +0100
@@ -28,7 +28,7 @@
 #include "octave-config.h"
 
 #include "CSparse.h"
-#include "dColVector.h"
+#include "dRowVector.h"
 #include "dSparse.h"
 
 // If the sparse matrix classes become templated on the element type
@@ -65,7 +65,7 @@
 
   octave_idx_type P (void) const;
 
-  ColumnVector perm (void) const;
+  RowVector perm (void) const;
 
   SparseMatrix Q (void) const;
 
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470753632 -3600
#      Tue Aug 09 15:40:32 2016 +0100
# Node ID e43199618777c4860fd39c4b48878ddb0097c963
# Parent  22c2bd4405441a0c5be66b65f23b2b9578240add
liboctave/numeric/svd.h: remove unused #include <iosfwd>.

diff -r 22c2bd440544 -r e43199618777 liboctave/numeric/svd.h
--- a/liboctave/numeric/svd.h	Tue Aug 09 04:14:55 2016 +0100
+++ b/liboctave/numeric/svd.h	Tue Aug 09 15:40:32 2016 +0100
@@ -26,8 +26,6 @@
 
 #include "octave-config.h"
 
-#include <iosfwd>
-
 template <typename T>
 class
 svd
# HG changeset patch
# User Markus Muetzel <markus.muetzel@gmx.de>
# Date 1468864179 -7200
#      Mon Jul 18 19:49:39 2016 +0200
# Node ID 01ba6ebc52e475ee602c824ca31abc45eaaf6c7f
# Parent  e43199618777c4860fd39c4b48878ddb0097c963
Add function "reducevolume" (patch #8856).

* scripts/plot/draw/reducevolume.m: New function.

* scripts/plot/draw/module.mk: Add to build system.

* __unimplemented__.m: Remove "reducevolume" from list.

* NEWS: Announce new function.

* doc/interpreter/plot.txi: Add to documentation.

* scripts/plot/draw/isosurface.m: Add "reducevolume" to @seealso.

diff -r e43199618777 -r 01ba6ebc52e4 NEWS
--- a/NEWS	Tue Aug 09 15:40:32 2016 +0100
+++ b/NEWS	Mon Jul 18 19:49:39 2016 +0200
@@ -123,6 +123,7 @@
       padecoef
       psi
       rad2deg
+      reducevolume
       uibuttongroup
 
  ** Deprecated functions.
diff -r e43199618777 -r 01ba6ebc52e4 doc/interpreter/plot.txi
--- a/doc/interpreter/plot.txi	Tue Aug 09 15:40:32 2016 +0100
+++ b/doc/interpreter/plot.txi	Mon Jul 18 19:49:39 2016 +0200
@@ -386,6 +386,8 @@
 
 @DOCSTRING(smooth3)
 
+@DOCSTRING(reducevolume)
+
 @DOCSTRING(shrinkfaces)
 
 @DOCSTRING(diffuse)
diff -r e43199618777 -r 01ba6ebc52e4 scripts/help/__unimplemented__.m
--- a/scripts/help/__unimplemented__.m	Tue Aug 09 15:40:32 2016 +0100
+++ b/scripts/help/__unimplemented__.m	Mon Jul 18 19:49:39 2016 +0200
@@ -787,7 +787,6 @@
   "rbbox",
   "readtable",
   "reducepatch",
-  "reducevolume",
   "remove",
   "removecats",
   "renamecats",
diff -r e43199618777 -r 01ba6ebc52e4 scripts/plot/draw/isosurface.m
--- a/scripts/plot/draw/isosurface.m	Tue Aug 09 15:40:32 2016 +0100
+++ b/scripts/plot/draw/isosurface.m	Mon Jul 18 19:49:39 2016 +0200
@@ -133,7 +133,7 @@
 ## light ("Position", [1 1 5]);
 ## @end smallexample
 ##
-## @seealso{isonormals, isocolors, smooth3}
+## @seealso{isonormals, isocolors, smooth3, reducevolume}
 ## @end deftypefn
 
 ## Author: Martin Helm <martin@mhelm.de>
diff -r e43199618777 -r 01ba6ebc52e4 scripts/plot/draw/module.mk
--- a/scripts/plot/draw/module.mk	Tue Aug 09 15:40:32 2016 +0100
+++ b/scripts/plot/draw/module.mk	Mon Jul 18 19:49:39 2016 +0200
@@ -72,6 +72,7 @@
   scripts/plot/draw/quiver3.m \
   scripts/plot/draw/quiver.m \
   scripts/plot/draw/rectangle.m \
+  scripts/plot/draw/reducevolume.m \
   scripts/plot/draw/ribbon.m \
   scripts/plot/draw/rose.m \
   scripts/plot/draw/scatter3.m \
diff -r e43199618777 -r 01ba6ebc52e4 scripts/plot/draw/reducevolume.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/reducevolume.m	Mon Jul 18 19:49:39 2016 +0200
@@ -0,0 +1,286 @@
+## Copyright (C) 2016 Markus Muetzel
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {[@var{nx}, @var{ny}, @var{nz}, @var{nv}] =} reducevolume (@var{v}, @var{r})
+## @deftypefnx {} {[@var{nx}, @var{ny}, @var{nz}, @var{nv}] =} reducevolume (@var{x}, @var{y}, @var{z}, @var{v}, @var{r})
+## @deftypefnx {} {@var{nv} =} reducevolume (@dots{})
+##
+## Reduce the volume of the dataset in @var{v} according to the values in
+## @var{r}.
+##
+## @var{v} is a matrix that is non-singleton in the first 3 dimensions.
+##
+## @var{r} can either be a vector of 3 elements representing the reduction
+## factors in the x-, y-, and z-directions or a scalar, in which case the same
+## reduction factor is used in all three dimensions.
+##
+## @code{reducevolume} reduces the number of elements of @var{v} by taking
+## only every @var{r}-th element in the respective dimension.
+##
+## Optionally, @var{x}, @var{y}, and @var{z} can be supplied to represent the
+## set of coordinates of @var{v}.  They can either be matrices of the same size
+## as @var{v} or vectors with sizes according to the dimensions of @var{v}, in
+## which case they are expanded to matrices (@pxref{XREFmeshgrid,,meshgrid}).
+##
+## If @code{reducevolume} is called with two arguments then @var{x}, @var{y},
+## and @var{z} are assumed to match the respective indices of @var{v}.
+##
+## The reduced matrix is returned in @var{nv}.
+##
+## Optionally, the reduced set of coordinates are returned in @var{nx},
+## @var{ny}, and @var{nz}, respectively.
+##
+## Examples:
+##
+## @example
+## @group
+## @var{v} = reshape (1:6*8*4, [6 8 4]);
+## @var{nv} = reducevolume (@var{v}, [4 3 2]);
+## @end group
+## @end example
+##
+## @example
+## @group
+## @var{v} = reshape (1:6*8*4, [6 8 4]);
+## @var{x} = 1:3:24;  @var{y} = -14:5:11;  @var{z} = linspace (16, 18, 4);
+## [@var{nx}, @var{ny}, @var{nz}, @var{nv}] = reducevolume (@var{x}, @var{y}, @var{z}, @var{v}, [4 3 2]);
+## @end group
+## @end example
+##
+## @seealso{isosurface, isonormals}
+## @end deftypefn
+
+## Author: mmuetzel
+
+function [nx, ny, nz, nv] = reducevolume (varargin)
+
+  if (nargin < 2 || nargin > 5)
+    print_usage ();
+  endif
+
+  [x, y, z, v, r] = __get_check_reducevolume_args__ (nargout, varargin{:});
+
+  [nx, ny, nz, nv] = __reducevolume__ (x, y, z, v, r);
+
+  if (nargout <= 1)
+    nx = nv;
+  endif
+
+endfunction
+
+function [x, y, z, v, r] = __get_check_reducevolume_args__ (naout, varargin)
+
+  x = y = z = [];
+
+  switch (nargin)
+    case 3
+      v = varargin{1};
+      r = varargin{2};
+
+    case 6
+      if (naout == 4)
+        x = varargin{1};
+        y = varargin{2};
+        z = varargin{3};
+      endif
+      v = varargin{4};
+      r = varargin{5};
+
+    otherwise
+      error ("reducevolume: incorrect number of arguments");
+
+  endswitch
+
+  ## Check reduction values R
+  if (isscalar (r))
+    r = [r, r, r];
+  elseif (numel (r) != 3)
+    error (["reducevolume: reduction value R must be a scalar or " ...
+            "a vector of length 3"]);
+  endif
+
+  if (any (r < 1 | r != fix (r)))
+    error ("reducevolume: reduction values R must be positive integers");
+  endif
+
+  ## Check dimensions of data
+  if (ndims (v) < 3)
+    error ("reducevolume: data V must have at least 3 dimensions");
+  endif
+
+  v_sz = size (v);
+  if (any (v_sz(1:3) < 2))
+    error ("reducevolume: data must be a non-singleton 3-dimensional matrix");
+  endif
+
+  if (naout == 4)
+    if (isempty (x))
+      x = 1:size (v, 2);
+    endif
+    if (isempty (y))
+      y = 1:size (v, 1);
+    endif
+    if (isempty (z))
+      z = 1:size (v, 3);
+    endif
+
+    ## check x
+    if (isvector (x) && length (x) == v_sz(2))
+      x = repmat (x(:)', [v_sz(1) 1 v_sz(3)]);
+    elseif (! size_equal (v, x))
+      error ("reducevolume: X must match the size of data V");
+    endif
+
+    ## check y
+    if (isvector (y) && length (y) == v_sz(1))
+      y = repmat (y(:), [1 v_sz(2) v_sz(3)]);
+    elseif (! size_equal (v, y))
+      error ("reducevolume: Y must match the size of data V");
+    endif
+
+    ## check z
+    if (isvector (z) && length (z) == v_sz(3))
+      z = repmat (reshape (z(:), [1 1 length(z)]), ...
+                  [v_sz(1) v_sz(2) 1]);
+    elseif (! size_equal (v, z))
+      error ("reducevolume: Z must match the size of data V");
+    endif
+
+  endif
+
+endfunction
+
+function [nx, ny, nz, nv] = __reducevolume__ (x, y, z, v, r)
+
+  v_sz = size (v);
+  nv = v(1:r(2):end, 1:r(1):end, 1:r(3):end, :);
+  nv_sz = size (nv);
+  if (length (nv_sz) < 3 || min (nv_sz) < 2)
+    error ("reducevolume: reduction value R is too high");
+  endif
+  if (length (v_sz) > 3)
+    nv = reshape (nv, [nv_sz(1:3) v_sz(4:end)]);
+  endif
+
+  if (isempty (x))
+    nx = ny = nz = [];
+  else
+    nx = x(1:r(2):end, 1:r(1):end, 1:r(3):end);
+    ny = y(1:r(2):end, 1:r(1):end, 1:r(3):end);
+    nz = z(1:r(2):end, 1:r(1):end, 1:r(3):end);
+  endif
+
+endfunction
+
+
+%!shared v, x, y, z, xx, yy, zz
+%! v = reshape (1:6*8*4, [6 8 4]);
+%! x = 1:3:22;  y = -14:5:11;  z = linspace (16, 18, 4);
+%! [xx, yy, zz] = meshgrid (x, y, z);
+
+## two inputs, one output
+%!test
+%! nv = reducevolume (v, [4 3 2]);
+%! nv_expected = [1 25; 4 28];  nv_expected(:,:,2) = [97 121; 100 124]; 
+%! assert (nv, nv_expected);
+
+## two inputs, four outputs
+%!test
+%! [nx, ny, nz, nv] = reducevolume (v, [4 3 2]);
+%! nx_expected(1:2,1,1:2) = 1;  nx_expected(:,2,:) = 5;
+%! ny_expected(1,1:2,1:2) = 1;  ny_expected(2,:,:) = 4;
+%! nz_expected(1:2,1:2,1) = 1;  nz_expected(:,:,2) = 3;
+%! nv_expected = [1 25; 4 28];  nv_expected(:,:,2) = [97 121; 100 124]; 
+%! assert (nx, nx_expected);
+%! assert (ny, ny_expected);
+%! assert (nz, nz_expected);
+%! assert (nv, nv_expected);
+
+## five inputs, one output
+%!test
+%! nv = reducevolume (x, y, z, v, [4 3 2]);
+%! nv_expected = [1 25; 4 28];  nv_expected(:,:,2) = [97 121; 100 124]; 
+%! assert (nv, nv_expected);
+
+## five inputs, four outputs (coordinates are vectors)
+%!test
+%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);
+%! nx_expected(1:2,1,1:2) = x(1); nx_expected(:,2,:) = x(5);
+%! ny_expected(1,1:2,1:2) = y(1); ny_expected(2,:,:) = y(4);
+%! nz_expected(1:2,1:2,1) = z(1); nz_expected(:,:,2) = z(3);
+%! nv_expected = [1 25; 4 28]; nv_expected(:,:,2) = [97 121; 100 124]; 
+%! assert (nx, nx_expected);
+%! assert (ny, ny_expected);
+%! assert (nz, nz_expected);
+%! assert (nv, nv_expected);
+
+## five inputs, four outputs (coordinates are matrices)
+%!test
+%! [nx, ny, nz, nv] = reducevolume (xx, yy, zz, v, [4 3 2]);
+%! nx_expected(1:2,1,1:2) = x(1); nx_expected(:,2,:) = x(5);
+%! ny_expected(1,1:2,1:2) = y(1); ny_expected(2,:,:) = y(4);
+%! nz_expected(1:2,1:2,1) = z(1); nz_expected(:,:,2) = z(3);
+%! nv_expected = [1 25; 4 28]; nv_expected(:,:,2) = [97 121; 100 124]; 
+%! assert (nx, nx_expected);
+%! assert (ny, ny_expected);
+%! assert (nz, nz_expected);
+%! assert (nv, nv_expected);
+
+## five inputs, four outputs (coordinates are matrices, R is scalar)
+%!test
+%! [nx, ny, nz, nv] = reducevolume (xx, yy, zz, v, 3);
+%! nx_expected(1:2,1,1:2) = x(1); nx_expected(:,2,:) = x(4);
+%! nx_expected(:,3,:) = x(7);
+%! ny_expected(1,1:3,1:2) = y(1); ny_expected(2,:,:) = y(4);
+%! nz_expected(1:2,1:3,1) = z(1); nz_expected(:,:,2) = z(4);
+%! nv_expected = [1 19 37; 4 22 40];
+%! nv_expected(:,:,2) = [145 163 181; 148 166 184]; 
+%! assert (nx, nx_expected);
+%! assert (ny, ny_expected);
+%! assert (nz, nz_expected);
+%! assert (nv, nv_expected);
+
+## Test for each error
+%!test
+%!error reducevolume ()
+%!error reducevolume (1)
+%!error reducevolume (1,2,3,4,5,6)
+%!error <incorrect number of arguments> reducevolume (1, 2, 3)
+%!error <R must be a scalar or a vector of length 3> reducevolume (v, [])
+%!error <R must be a scalar or a vector of length 3> reducevolume (v, [1 2])
+%!error <reduction values R must be positive integers> reducevolume (v, 0)
+%!error <reduction values R must be positive integers> reducevolume (v, 1.5)
+%!error <data V must have at least 3 dimensions>
+%! v = reshape(1:6*8, [6 8]);
+%! [nv] = reducevolume (v, [4 3 2]);
+%!error <data must be a non-singleton 3-dimensional matrix>
+%! v = reshape(1:6*8, [6 1 8]);
+%! nv = reducevolume (v, [4 3 2]);
+%!error <X must match the size of data V>
+%! x = 1:2:24;
+%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);
+%!error <Y must match the size of data V>
+%! y = -14:6:11;
+%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);
+%!error <Z must match the size of data V>
+%! z = linspace (16, 18, 5);
+%! [nx, ny, nz, nv] = reducevolume (x, y, z, v, [4 3 2]);
+%!error <reduction value R is too high> [nv] = reducevolume (v, 5)
+%!error <reduction value R is too high> [nv] = reducevolume (v, [4 7 2])
+
# HG changeset patch
# User Rik <rik@octave.org>
# Date 1470766178 25200
#      Tue Aug 09 11:09:38 2016 -0700
# Node ID a8fd02bc895b4672f7d95133b6856a93b7495d37
# Parent  01ba6ebc52e475ee602c824ca31abc45eaaf6c7f
Overhaul isosurface.m and associated functions.

* isosurface.m: Rewrite docstring and examples.  Don't validate nargout.
Wrap long lines to < 80 characters.  Use names from docstring in code.
Use "EdgeColor", "none" for Matlab compatibility, but preserve exception
for gnuplot.  Use blank lines between case statements for readability.
Update demo #2 to properly show annotation textbox.  Rewrite %!error
tests.

* __calc_isovalue_from_data__.m: Give private function a docstring.
Use '_' in numbers as thousands separator for readability.  Wrap
long lines to < 80 characters.

* __unite_shared_vertices__.m: Reformat docstring.  Use rows() rather
than size (XXX, 1).  Wrap long lines to < 80 characters.  Use space
after function name and before parenthesis.

diff -r 01ba6ebc52e4 -r a8fd02bc895b scripts/plot/draw/isosurface.m
--- a/scripts/plot/draw/isosurface.m	Mon Jul 18 19:49:39 2016 +0200
+++ b/scripts/plot/draw/isosurface.m	Tue Aug 09 11:09:38 2016 -0700
@@ -17,58 +17,65 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {} {[@var{fv}] =} isosurface (@var{val}, @var{iso})
-## @deftypefnx {} {[@var{fv}] =} isosurface (@var{val})
-## @deftypefnx {} {[@var{fv}] =} isosurface (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso})
-## @deftypefnx {} {[@var{fv}] =} isosurface (@var{x}, @var{y}, @var{z}, @var{val})
-## @deftypefnx {} {[@var{fvc}] =} isosurface (@dots{}, @var{col})
-## @deftypefnx {} {[@var{fv}] =} isosurface (@dots{}, "noshare")
-## @deftypefnx {} {[@var{fv}] =} isosurface (@dots{}, "verbose")
+## @deftypefn  {} {@var{fv} =} isosurface (@var{v}, @var{isoval})
+## @deftypefnx {} {@var{fv} =} isosurface (@var{v})
+## @deftypefnx {} {@var{fv} =} isosurface (@var{x}, @var{y}, @var{z}, @var{v}, @var{isoval})
+## @deftypefnx {} {@var{fv} =} isosurface (@var{x}, @var{y}, @var{z}, @var{v})
+## @deftypefnx {} {@var{fvc} =} isosurface (@dots{}, @var{col})
+## @deftypefnx {} {@var{fv} =} isosurface (@dots{}, "noshare")
+## @deftypefnx {} {@var{fv} =} isosurface (@dots{}, "verbose")
 ## @deftypefnx {} {[@var{f}, @var{v}] =} isosurface (@dots{})
 ## @deftypefnx {} {[@var{f}, @var{v}, @var{c}] =} isosurface (@dots{})
 ## @deftypefnx {} {} isosurface (@dots{})
 ##
-## Calculate isosurface of 3-D data.
+## Calculate isosurface of 3-D volume data.
 ##
-## If called with one output argument and the first input argument
-## @var{val} is a three-dimensional array that contains the data of an
-## isosurface geometry and the second input argument @var{iso} keeps the
-## isovalue as a scalar value then return a structure array @var{fv}
-## that contains the fields @var{faces} and @var{vertices} at computed
-## points @command{[x, y, z] = meshgrid (1:l, 1:m, 1:n)}. The output
-## argument @var{fv} can directly be taken as an input argument for the
-## @command{patch} function.
+## An isosurface connects points with the same value and is analogous to a
+## contour plot, but in three dimensions.
 ##
-## If @var{iso} is omitted or empty, a "good" value for an isosurface is
-## determined from @var{val}.
+## The input argument @var{v} is a three-dimensional array that contains data
+## sampled over a volume.
 ##
-## If called with further input arguments @var{x}, @var{y} and @var{z}
-## which are three--dimensional arrays with the same size as @var{val} or
-## vectors with lengths corresponding to the dimensions of @var{val}, then the
-## volume data is taken at those given points. If @var{x}, @var{y} or @var{z}
-## are empty, the grid corresponds to the indices in the respective direction
-## (see @command{meshgrid}).
+## The input @var{isoval} is a scalar that specifies the value for the
+## isosurface.  If @var{isoval} is omitted or empty, a @qcode{"good"} value
+## for an isosurface is determined from @var{v}.
 ##
-## If called with the input argument @var{col} which is a
-## three-dimensional array of the same size as @var{val}, take
-## those values for the interpolation of coloring the isosurface
-## geometry. In this case, the structure array @var{fv} has the additional field
+## When called with a single output argument @code{isosurface} returns a
+## structure array @var{fv} that contains the fields @var{faces} and
+## @var{vertices} computed at the points
+## @code{[@var{x}, @var{y}, @var{z}] = meshgrid (1:l, 1:m, 1:n)} where
+## @code{[l, m, n] = size (@var{v})}.  The output @var{fv} can be
+## used directly as input to the @code{patch} function.
+##
+## If called with additional input arguments @var{x}, @var{y}, and @var{z}
+## that are three-dimensional arrays with the same size as @var{v} or
+## vectors with lengths corresponding to the dimensions of @var{v}, then the
+## volume data is taken at the specified points.  If @var{x}, @var{y}, or
+## @var{z} are empty, the grid corresponds to the indices (@code{1:n}) in
+## the respective direction (@pxref{XREFmeshgrid,,meshgrid}).
+##
+## The optional input argument @var{col}, which is a three-dimensional array
+## of the same size as @var{v}, specifies coloring of the isosurface.  The
+## color data is interpolated, as necessary, to match @var{isoval}.  The
+## output structure array, in this case, has the additional field
 ## @var{facevertexcdata}.
 ##
-## If given the string input argument @qcode{"noshare"}, vertices might be
-## returned multiple times for different faces. The default behavior is to
-## search vertices shared by adjacent faces with @command{unique} which might be
+## If given the string input argument @qcode{"noshare"}, vertices may be
+## returned multiple times for different faces.  The default behavior is to
+## eliminate vertices shared by adjacent faces with @code{unique} which may be
 ## time consuming.
-## The string input argument @qcode{"verbose"} is only for compatibility and
-## has no effect.
-## The string input arguments must be passed after the other arguments.
+##
+## The string input argument @qcode{"verbose"} is supported for @sc{matlab}
+## compatibility, but has no effect.
+##
+## Any string arguments must be passed after the other arguments.
 ##
 ## If called with two or three output arguments, return the information about
-## the faces @var{f}, vertices @var{v} and color data @var{c} as separate arrays
-## instead of a single structure array.
+## the faces @var{f}, vertices @var{v}, and color data @var{c} as separate
+## arrays instead of a single structure array.
 ##
 ## If called with no output argument, the isosurface geometry is directly
-## processed with the @command{patch} command and a light object is added to
+## plotted with the @code{patch} command and a light object is added to
 ## the axes if not yet present.
 ##
 ## For example,
@@ -76,16 +83,15 @@
 ## @example
 ## @group
 ## [x, y, z] = meshgrid (1:5, 1:5, 1:5);
-## val = rand (5, 5, 5);
-## isosurface (x, y, z, val, .5);
+## v = rand (5, 5, 5);
+## isosurface (x, y, z, v, .5);
 ## @end group
 ## @end example
 ##
 ## @noindent
 ## will directly draw a random isosurface geometry in a graphics window.
 ##
-## Another example for an isosurface geometry with different additional
-## coloring
+## An example of an isosurface geometry with different additional coloring:
 ## @c Set example in small font to prevent overfull line
 ##
 ## @smallexample
@@ -93,42 +99,38 @@
 ## iso = .4;  # Change isovalue to .1 to display a sphere
 ## lin = linspace (0, 2, N);
 ## [x, y, z] = meshgrid (lin, lin, lin);
-## val = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
-## figure (); # Open another figure window
+## v = abs ((x-.5).^2 + (y-.5).^2 + (z-.5).^2);
+## figure ();
 ##
 ## subplot (2,2,1); view (-38, 20);
-## [f, v] = isosurface (x, y, z, val, iso);
-## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode", "manual", ...
-##           "PlotBoxAspectRatio", [1 1 1]);
-## isonormals (x, y, z, val, p)
+## [f, vert] = isosurface (x, y, z, v, iso);
+## p = patch ("Faces", f, "Vertices", vert, "EdgeColor", "none");
+## pbaspect ([1 1 1]);
+## isonormals (x, y, z, v, p)
 ## set (p, "FaceColor", "green", "FaceLighting", "gouraud");
 ## light ("Position", [1 1 5]);
 ##
 ## subplot (2,2,2); view (-38, 20);
-## p = patch ("Faces", f, "Vertices", v, "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode", "manual", ...
-##           "PlotBoxAspectRatio", [1 1 1]);
-## isonormals (x, y, z, val, p)
+## p = patch ("Faces", f, "Vertices", vert, "EdgeColor", "blue");
+## pbaspect ([1 1 1]);
+## isonormals (x, y, z, v, p)
 ## set (p, "FaceColor", "none", "EdgeLighting", "gouraud");
 ## light ("Position", [1 1 5]);
 ##
 ## subplot (2,2,3); view (-38, 20);
-## [f, v, c] = isosurface (x, y, z, val, iso, y);
-## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, ...
+## [f, vert, c] = isosurface (x, y, z, v, iso, y);
+## p = patch ("Faces", f, "Vertices", vert, "FaceVertexCData", c, ...
 ##            "FaceColor", "interp", "EdgeColor", "none");
-## set (gca, "PlotBoxAspectRatioMode", "manual", ...
-##           "PlotBoxAspectRatio", [1 1 1]);
-## isonormals (x, y, z, val, p)
+## pbaspect ([1 1 1]);
+## isonormals (x, y, z, v, p)
 ## set (p, "FaceLighting", "gouraud");
 ## light ("Position", [1 1 5]);
 ##
 ## subplot (2,2,4); view (-38, 20);
-## p = patch ("Faces", f, "Vertices", v, "FaceVertexCData", c, ...
+## p = patch ("Faces", f, "Vertices", vert, "FaceVertexCData", c, ...
 ##            "FaceColor", "interp", "EdgeColor", "blue");
-## set (gca, "PlotBoxAspectRatioMode", "manual", ...
-##           "PlotBoxAspectRatio", [1 1 1]);
-## isonormals (x, y, z, val, p)
+## pbaspect ([1 1 1]);
+## isonormals (x, y, z, v, p)
 ## set (p, "FaceLighting", "gouraud");
 ## light ("Position", [1 1 5]);
 ## @end smallexample
@@ -143,29 +145,31 @@
 
 function varargout = isosurface (varargin)
 
-  if (nargin < 1 || nargin > 8 || nargout > 3)
+  if (nargin < 1 || nargin > 8)
     print_usage ();
   endif
 
-  [x, y, z, val, iso, colors, noshare, verbose] = __get_check_isosurface_args__ (nargout, varargin{:});
+  [x, y, z, v, isoval, colors, noshare, verbose] = ...
+      __get_check_isosurface_args__ (nargout, varargin{:});
 
   calc_colors = ! isempty (colors);
   if (calc_colors)
     [fvc.faces, fvc.vertices, fvc.facevertexcdata] = ...
-      __marching_cube__ (x, y, z, val, iso, colors);
+        __marching_cube__ (x, y, z, v, isoval, colors);
   else
-    [fvc.faces, fvc.vertices] = __marching_cube__ (x, y, z, val, iso);
+    [fvc.faces, fvc.vertices] = __marching_cube__ (x, y, z, v, isoval);
   endif
 
   if (isempty (fvc.vertices) || isempty (fvc.faces))
     warning ("isosurface: triangulation is empty");
   endif
 
-  if (!noshare)
-    [fvc.faces, fvc.vertices, J] = __unite_shared_vertices__ (fvc.faces, fvc.vertices);
+  if (! noshare)
+    [fvc.faces, fvc.vertices, J] = __unite_shared_vertices__ (fvc.faces,
+                                                              fvc.vertices);
 
     if (calc_colors)
-      fvc.facevertexcdata(J) = []; # share very close vertices
+      fvc.facevertexcdata(J) = [];  # share very close vertices
     endif
   endif
 
@@ -175,42 +179,47 @@
       if (calc_colors)
         fc = fvc.facevertexcdata;
       else
-        fc = iso;
+        fc = isoval;
       endif
-      ## FIXME: Matlab uses "EdgeColor", "none". But that would look odd
-      ##        with gnuplot.
+      ## Matlab uses "EdgeColor", "none", but that looks odd in gnuplot.
+      hax = gca ();
+      if (strcmp (get (gcf, "__graphics_toolkit__"), "gnuplot"))
+        ec = "k";
+      else
+        ec = "none";
+      endif
       pa = patch ("Faces", fvc.faces, "Vertices", fvc.vertices,
                   "FaceVertexCData", fc,
-                  "FaceColor", "flat", "EdgeColor", "k",
+                  "FaceColor", "flat", "EdgeColor", ec,
                   "FaceLighting", "gouraud");
-      hax = gca ();
       if (! ishold ())
         set (hax, "View", [-37.5, 30], "Box", "off");
       endif
-      isonormals (x, y, z, val, pa);
+      isonormals (x, y, z, v, pa);
       lights = findobj (hax, "Type", "light");
       if (isempty (lights))
         ## FIXME: Matlab seems to use camlight (patch #9014) here
         light ();
       endif
+
     case 1
       varargout = {fvc};
+
     case 2
       varargout = {fvc.faces, fvc.vertices};
-    otherwise ## 3
+
+    otherwise  # 3 args or more
       varargout = {fvc.faces, fvc.vertices, fvc.facevertexcdata};
+
   endswitch
 
 endfunction
 
-function [x, y, z, data, iso, colors, noshare, verbose] = __get_check_isosurface_args__ (nout, varargin)
-## get arguments from input and check values
-
-  x = [];
-  y = [];
-  z = [];
-  data = [];
-  iso = [];
+function [x, y, z, v, isoval, colors, noshare, verbose] = __get_check_isosurface_args__ (nout, varargin)
+  ## get arguments from input and check values
+  x = y = z = [];
+  v = [];
+  isoval = [];
   colors = [];
 
   ## default values
@@ -219,121 +228,132 @@
 
   nin = length (varargin);
   num_string_inputs = 0;
+
+  ## check whether last 2 input arguments are strings and assign parameters
   for i_arg = (nin:-1:nin-1)
-    ## check whether last maximum 2 input arguments are strings and assign parameters
-    if (!ischar (varargin{i_arg}) || i_arg < 1)
-      ## string arguments must be at the end
-      break
-    end
+    if (! ischar (varargin{i_arg}) || i_arg < 1)
+      break;  # no string arguments at end, exit checking
+    endif
     switch (tolower (varargin{i_arg}))
       case {"v", "verbose"}
         verbose = true;
         num_string_inputs++;
+
       case {"n", "noshare"}
         noshare = true;
         num_string_inputs++;
+
       otherwise
-        error ("isosurface: parameter '%s' not supported", varargin{i_arg})
+        error ("isosurface: parameter '%s' not supported", varargin{i_arg});
+
     endswitch
   endfor
 
   ## assign arguments
   switch (nin - num_string_inputs)
-    case 1 ## isosurface (val, ...)
-      data = varargin{1};
-    case 2 ## isosurface (val, iso, ...) or isosurface (val, col, ...)
-      data = varargin{1};
+    case 1  # isosurface (v, ...)
+      v = varargin{1};
+
+    case 2  # isosurface (v, isoval, ...) or isosurface (v, col, ...)
+      v = varargin{1};
       if (isscalar (varargin{2}) || isempty (varargin{2}))
-        iso = varargin{2};
+        isoval = varargin{2};
       else
         colors = varargin{2};
       endif
-    case 3 ## isosurface (val, iso, col, ...)
-      data = varargin{1};
-      iso = varargin{2};
+
+    case 3  # isosurface (v, isoval, col, ...)
+      v = varargin{1};
+      isoval = varargin{2};
       colors = varargin{3};
-    case 4 ## isosurface (x, y, z, val, ...)
+
+    case 4  # isosurface (x, y, z, v, ...)
       x = varargin{1};
       y = varargin{2};
       z = varargin{3};
-      data = varargin{4};
-    case 5 ## isosurface (x, y, z, val, iso, ...) or isosurface (x, y, z, val, col, ...)
+      v = varargin{4};
+
+    case 5  # isosurface (x, y, z, v, isoval, ...) or
+            # isosurface (x, y, z, v, col, ...)
       x = varargin{1};
       y = varargin{2};
       z = varargin{3};
-      data = varargin{4};
+      v = varargin{4};
       if (isscalar (varargin{5}) || isempty (varargin{5}))
-        iso = varargin{5};
+        isoval = varargin{5};
       else
         colors = varargin{5};
       endif
-    case 6 ## isosurface (x, y, z, val, iso, col, ...)
+
+    case 6  # isosurface (x, y, z, v, isoval, col, ...)
       x = varargin{1};
       y = varargin{2};
       z = varargin{3};
-      data = varargin{4};
-      iso = varargin{5};
+      v = varargin{4};
+      isoval = varargin{5};
       colors = varargin{6};
+
     otherwise
-      error ("isosurface: wrong number of input arguments")
+      error ("isosurface: incorrect number of input arguments")
+
   endswitch
 
-  ## check dimensions of data
-  data_size = size (data);
-  if (ndims (data) != 3 || any (data_size(1:3) < 2))
-    error ("isosurface: VAL must be a non-singleton 3-dimensional matrix");
+  ## check dimensions of v
+  v_sz = size (v);
+  if (ndims (v) != 3 || any (v_sz(1:3) < 2))
+    error ("isosurface: V must be a non-singleton 3-dimensional matrix");
   endif
 
   if (isempty (x))
-    x = 1:size (data, 2);
+    x = 1:size (v, 2);
   endif
   if (isempty (y))
-    y = 1:size (data, 1);
+    y = 1:size (v, 1);
   endif
   if (isempty (z))
-    z = 1:size (data, 3);
+    z = 1:size (v, 3);
   endif
 
   ## check x
-  if (isvector (x) && length (x) == data_size(2))
-    x = repmat (x(:)', [data_size(1) 1 data_size(3)]);
-  elseif (! size_equal (data, x))
-    error ("isosurface: X must match the size of VAL");
+  if (isvector (x) && length (x) == v_sz(2))
+    x = repmat (x(:)', [v_sz(1) 1 v_sz(3)]);
+  elseif (! size_equal (v, x))
+    error ("isosurface: X must match the size of V");
   endif
 
   ## check y
-  if (isvector (y) && length (y) == data_size(1))
-    y = repmat (y(:), [1 data_size(2) data_size(3)]);
-  elseif (! size_equal (data, y))
-    error ("isosurface: Y must match the size of VAL");
+  if (isvector (y) && length (y) == v_sz(1))
+    y = repmat (y(:), [1 v_sz(2) v_sz(3)]);
+  elseif (! size_equal (v, y))
+    error ("isosurface: Y must match the size of V");
   endif
 
   ## check z
-  if (isvector (z) && length (z) == data_size(3))
-    z = repmat (reshape (z(:), [1 1 length(z)]), [data_size(1) data_size(2) 1]);
-  elseif (! size_equal (data, z))
-    error ("isosurface: Z must match the size of VAL");
+  if (isvector (z) && length (z) == v_sz(3))
+    z = repmat (reshape (z(:), [1 1 length(z)]), [v_sz(1) v_sz(2) 1]);
+  elseif (! size_equal (v, z))
+    error ("isosurface: Z must match the size of V");
   endif
 
-  ## check iso
-  if (isempty (iso))
-    ## calculate "good" iso value from data
-    iso = __calc_isovalue_from_data__ (data);
+  ## check isoval
+  if (isempty (isoval))
+    ## calculate "good" isoval value from v
+    isoval = __calc_isovalue_from_data__ (v);
   endif
 
-  if ~isscalar (iso)
-    error ("isosurface: ISO must be a scalar")
+  if (! isscalar (isoval))
+    error ("isosurface: ISOVAL must be a scalar")
   endif
 
   ## check colors
   if (! isempty (colors))
-    if (! size_equal (data, colors))
-      error ("isosurface: COL must match the size of VAL")
+    if (! size_equal (v, colors))
+      error ("isosurface: COL must match the size of V")
     endif
     if (nout == 2)
       warning ("isosurface: colors will be calculated, but no output argument to receive it.");
     endif
-  elseif (nout == 3)
+  elseif (nout >= 3)
     error ("isosurface: COL must be passed to return C")
   endif
 
@@ -343,30 +363,30 @@
 %!demo
 %! clf;
 %! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);
-%! val = x.^2 + y.^2 + z.^2;
-%! isosurface (x, y, z, val, 3);
-%! isosurface (x, y, z, val, 5);
+%! v = x.^2 + y.^2 + z.^2;
+%! isosurface (x, y, z, v, 3);
+%! isosurface (x, y, z, v, 5);
 %! axis equal;
-%! title ('isosurfaces of two nested spheres');
+%! title ("isosurfaces of two nested spheres");
 
 %!demo
 %! x = 0:2;
 %! y = 0:3;
 %! z = 0:1;
-%! [xx, yy, zz]  = meshgrid (x, y, z);
-%! val        = [0, 0, 0; 0, 0, 0; 0, 0, 1; 0, 0, 1];
-%! val(:,:,2) = [0, 0, 0; 0, 0, 1; 0, 1, 2; 0, 1, 2];
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! v        = [0, 0, 0; 0, 0, 0; 0, 0, 1; 0, 0, 1];
+%! v(:,:,2) = [0, 0, 0; 0, 0, 1; 0, 1, 2; 0, 1, 2];
 %! iso = 0.8;
 %% three arguments, no output
 %! figure;
-%! subplot (2, 2, 1); isosurface (val, iso, yy); view(3)
+%! subplot (2, 2, 1); isosurface (v, iso, yy); view(3)
 %% six arguments, no output (x, y, z are vectors)
-%! subplot (2, 2, 2); isosurface (x, y, z, val, iso, yy); view (3)
+%! subplot (2, 2, 2); isosurface (x, y, z, v, iso, yy); view (3)
 %% six arguments, no output (x, y, z are matrices)
-%! subplot (2, 2, 3); isosurface (xx, yy, zz, val, iso, yy); view (3)
+%! subplot (2, 2, 3); isosurface (xx, yy, zz, v, iso, yy); view (3)
 %% six arguments, no output (mixed x, y, z) and option "noshare"
-%! subplot (2, 2, 4); isosurface (x, yy, z, val, iso, yy, "noshare"); view (3)
-%! annotation("textbox", [0 0.95 1 0.1], ...
+%! subplot (2, 2, 4); isosurface (x, yy, z, v, iso, yy, "noshare"); view (3)
+%! annotation ("textbox", [0.01 0.93 1 0.1], ...
 %!    "String", ["Apart from the first plot having a different scale, " ...
 %!               "all four plots must look the same.\n" ...
 %!               "The last plot might have different colors but must have " ...
@@ -496,25 +516,46 @@
 %! assert (size (fvc.facevertexcdata), [7 1]);
 
 ## test for each error and warning
-%!test
-%!error <X must match the size of VAL> x = 1:2:24; fvc = isosurface (x, y, z, val, iso);
-%!error <Y must match the size of VAL> y = -14:6:11; fvc = isosurface (x, y, z, val, iso);
-%!error <Z must match the size of VAL> z = linspace (16, 18, 5); fvc = isosurface (x, y, z, val, iso);
-%!error <X must match the size of VAL> x = 1:2:24; [xx, yy, zz] = meshgrid (x, y, z); fvc = isosurface (xx, yy, zz, val, iso);
-%!error <X must match the size of VAL> y = -14:6:11; [xx, yy, zz] = meshgrid (x, y, z); fvc = isosurface (xx, yy, zz, val, iso);
-%!error <X must match the size of VAL> z = linspace (16, 18, 3); [xx, yy, zz] = meshgrid (x, y, z); fvc = isosurface (xx, yy, zz, val, iso);
-%!error <VAL must be a non-singleton 3-dimensional matrix> val = reshape(1:6*8, [6 8]); fvc = isosurface (val, iso);
-%!error <VAL must be a non-singleton 3-dimensional matrix> val = reshape(1:6*8, [6 1 8]); fvc = isosurface (val, iso);
-%!error <ISO must be a scalar> fvc = isosurface (val, [iso iso], yy);
-%!error <COL must match the size of VAL> fvc = isosurface (val, [iso iso]);
-%!warning <colors will be calculated, but no output argument to receive it.> [f, v] = isosurface (val, iso, yy);
-%!error <COL must be passed to return C> [f, v, c] = isosurface (val, iso);
-%!error <Invalid call to isosurface> fvc = isosurface ();
-%!error <Invalid call to isosurface> [f, v, c, a] = isosurface (val, iso);
-%!error <wrong number of input arguments> fvc = isosurface (xx, yy, zz, val, iso, yy, 5);
-%!error <parameter 'test_string' not supported> fvc = isosurface (val, iso, "test_string");
+%!error isosurface ()
+%!error isosurface (1,2,3,4,5,6,7,8,9)
+%!error <parameter 'foobar' not supported>
+%! fvc = isosurface (val, iso, "foobar");
+%!error <incorrect number of input arguments>
+%! fvc = isosurface (xx, yy, zz, val, iso, yy, 5);
+%!error <V must be a non-singleton 3-dimensional matrix>
+%! v = reshape (1:6*8, [6 8]);
+%! fvc = isosurface (v, iso);
+%!error <V must be a non-singleton 3-dimensional matrix>
+%! v = reshape(1:6*8, [6 1 8]); fvc = isosurface (v, iso);
+%!error <X must match the size of V>
+%! x = 1:2:24;
+%! fvc = isosurface (x, y, z, val, iso);
+%!error <Y must match the size of V>
+%! y = -14:6:11;
+%! fvc = isosurface (x, y, z, val, iso);
+%!error <Z must match the size of V>
+%! z = linspace (16, 18, 5);
+%! fvc = isosurface (x, y, z, val, iso);
+%!error <X must match the size of V>
+%! x = 1:2:24;
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! fvc = isosurface (xx, yy, zz, val, iso);
+%!error <X must match the size of V>
+%! y = -14:6:11;
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! fvc = isosurface (xx, yy, zz, val, iso);
+%!error <X must match the size of V>
+%! z = linspace (16, 18, 3);
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! fvc = isosurface (xx, yy, zz, val, iso);
+%!error <ISOVAL must be a scalar> fvc = isosurface (val, [iso iso], yy)
+%!error <COL must match the size of V> fvc = isosurface (val, [iso iso]);
+%!error <COL must be passed to return C> [f, v, c] = isosurface (val, iso)
+%!warning <colors will be calculated, but no output argument to receive it.>
+%! [f, v] = isosurface (val, iso, yy);
 
 ## test for __calc_isovalue_from_data__
 ## FIXME: private function cannot be tested, unless bug #38776 is resolved.
 %!xtest
 %! assert (__calc_isovalue_from_data__ (1:5), 3.02);
+
diff -r 01ba6ebc52e4 -r a8fd02bc895b scripts/plot/draw/private/__calc_isovalue_from_data__.m
--- a/scripts/plot/draw/private/__calc_isovalue_from_data__.m	Mon Jul 18 19:49:39 2016 +0200
+++ b/scripts/plot/draw/private/__calc_isovalue_from_data__.m	Tue Aug 09 11:09:38 2016 -0700
@@ -19,23 +19,21 @@
 ## Undocumented internal function.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{iso} =} __calc_isovalue_from_data__ (@var{data})
-## Undocumented internal function.
+## @deftypefn {} {@var{isoval} =} __calc_isovalue_from_data__ (@var{data})
+## Calculate a "good" iso value from histogram of data.
 ## @end deftypefn
 
-## calculate a "good" iso value from histogram of data
 ## called from isocaps, isosurface
 
+function isoval = __calc_isovalue_from_data__ (data)
 
-function iso = __calc_isovalue_from_data__ (data)
-
-  ## use a maximum of 10000-20000 samples to limit run-time of hist
+  ## use a maximum of 10,000-20,000 samples to limit runtime of hist
   step = 1;
-  data_numel = numel (data);
-  if (data_numel > 20000)
-    step = floor (data_numel / 10000);
+  ndata = numel (data);
+  if (ndata > 20_000)
+    step = floor (ndata / 10_000);
     data = data(1:step:end);
-    data_numel = numel (data);
+    ndata = numel (data);
   endif
 
   num_bins = 100;
@@ -43,18 +41,20 @@
 
   ## if one of the first two bins contains more than 10 times the count as
   ## compared to equally distributed data, remove both (zero-padded + noise)
-  if (any (bin_count(1:2) > 10 * (data_numel / num_bins)))
+  if (any (bin_count(1:2) > 10 * (ndata / num_bins)))
     bin_count(1:2) = [];
     bin_centers(1:2) = [];
   endif
 
-  ## if bins have low counts, remove them (but keep them if we would loose more than 90 % of bins)
+  ## if bins have low counts, remove them (but keep them if we would lose
+  ## more than 90% of bins)
   bins_to_remove = find (bin_count < max (bin_count)/50);
-  if length (bins_to_remove) < .9 * num_bins
+  if (length (bins_to_remove) < .9 * num_bins)
     bin_centers(bins_to_remove) = [];
   endif
 
   ## select middle bar of histogram with previous conditions
-  iso = bin_centers(floor (length (bin_centers) / 2));
+  isoval = bin_centers(floor (numel (bin_centers) / 2));
 
 endfunction
+
diff -r 01ba6ebc52e4 -r a8fd02bc895b scripts/plot/draw/private/__unite_shared_vertices__.m
--- a/scripts/plot/draw/private/__unite_shared_vertices__.m	Mon Jul 18 19:49:39 2016 +0200
+++ b/scripts/plot/draw/private/__unite_shared_vertices__.m	Tue Aug 09 11:09:38 2016 -0700
@@ -19,12 +19,12 @@
 ## -*- texinfo -*-
 ## @deftypefn {} {[@var{faces}, @var{vertices}, @var{J}] =} __unite_shared_vertices__ (@var{faces}, @var{vertices})
 ##
-## Detect and unite shared vertices in patches
+## Detect and unite shared vertices in patches.
 ##
-## Vertices of neighboring faces are detected and united to shared vertices. For
-## this, the mutual squared distances between all vertices are calculated. If
-## all coordinates are closer than @command{2 * eps (max (abs (vertices(:))))},
-## the vertices are united to one.
+## Vertices of neighboring faces are detected and united to shared vertices.
+## For this, the mutual squared distances between all vertices are
+## calculated.  If all coordinates are closer than
+## @code{2 * eps (max (abs (vertices(:))))}, the vertices are united to one.
 ##
 ## @var{J} holds the indices of the deleted vertices.
 ##
@@ -34,26 +34,31 @@
 ## Author: mmuetzel
 
 function [faces, vertices, J] = __unite_shared_vertices__ (faces, vertices)
-  ### unite shared vertices
 
   J = [];
+
   ## Calculate the mutual differences of all vertex coordinates
   close_points = zeros (0, 2);
-  num_vertices = size (vertices, 1);
+  num_vertices = rows (vertices);
   skip_point = false (num_vertices, 1);
+  ## FIXME: Can this be vectorized in some way to increase performance?
+  ##        Regardless, should probably allocate close_points to be the
+  ##        same size as the number of vertices and then truncate the
+  ##        array at the end of the calculation.  Extending an array
+  ##        involves a copy operation every time.
   for (i_point1 = 1:num_vertices - 1)
     if (skip_point(i_point1))
       ## points already detected as duplicates can be skipped
-      continue
+      continue;
     endif
 
     diff = vertices(i_point1,:) - vertices(i_point1 + 1:end,:);
-    is_close_point = all (abs (diff) <= sqrt(3) * eps * ...
+    is_close_point = all (abs (diff) <= sqrt (3) * eps * ...
         (max (abs (vertices(i_point1,:)), abs (vertices(i_point1 + 1:end,:)))), 2);
 
     if (any (is_close_point))
       close_points_idx = find (is_close_point) + i_point1;
-      new_close_points_num = size (close_points_idx, 1);
+      new_close_points_num = rows (close_points_idx);
       close_points(end + 1:end + new_close_points_num,1) = i_point1;
       close_points(end - new_close_points_num + 1:end,2) = close_points_idx;
       skip_point(close_points_idx) = true;
@@ -76,11 +81,12 @@
     faces = sort (faces, 2);
     faces = unique (faces, "rows");
 
-    ## eliminate faces with zero area
-    is_zero_area = (faces(:,1) == faces(:,2)) | (faces(:,2) == faces(:,3)); # vertices in faces are sorted
-    faces = faces(!is_zero_area,:);
+    ## eliminate faces with zero area.  Vertices in faces are sorted.
+    is_zero_area = (faces(:,1) == faces(:,2)) | (faces(:,2) == faces(:,3));
+    faces = faces(! is_zero_area, :);
 
     J = close_points(:,2);
   endif
 
 endfunction
+
# HG changeset patch
# User John W. Eaton <jwe@octave.org>
# Date 1470698549 14400
#      Mon Aug 08 19:22:29 2016 -0400
# Node ID 60faa7c85e3186b9fbc750e0907f602a226a9d15
# Parent  a8fd02bc895b4672f7d95133b6856a93b7495d37
don't use -Wshadow for GCC 4

* configure.ac: Omit -Wshadow from list of extra warning flags when
using GCC 4.

diff -r a8fd02bc895b -r 60faa7c85e31 configure.ac
--- a/configure.ac	Tue Aug 09 11:09:38 2016 -0700
+++ b/configure.ac	Mon Aug 08 19:22:29 2016 -0400
@@ -2718,17 +2718,25 @@
 fi
 AM_CONDITIONAL([AMCOND_BUILD_DOCS], [test $ENABLE_DOCS = yes])
 
+case "$GCC_VERSION" in
+  *4*)
+  ;;
+  *)
+    GCC_WSHADOW_OPTION=-Wshadow
+  ;;
+esac
+
 ### Maybe add -Wall, -W, and -Wshadow to compiler flags now that we're
 ### done feature testing.
 
-GCC_EXTRA_FLAGS="-Wall -W -Wshadow -Wformat -Wpointer-arith -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings -Wcast-align -Wcast-qual"
-GXX_EXTRA_FLAGS="-Wall -W -Wshadow -Wold-style-cast -Wformat -Wpointer-arith -Wwrite-strings -Wcast-align -Wcast-qual"
+GCC_EXTRA_FLAGS="-Wall -W $GCC_WSHADOW_OPTION -Wformat -Wpointer-arith -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings -Wcast-align -Wcast-qual"
+GXX_EXTRA_FLAGS="-Wall -W $GCC_WSHADOW_OPTION -Wold-style-cast -Wformat -Wpointer-arith -Wwrite-strings -Wcast-align -Wcast-qual"
 
 try_extra_warning_flags=yes
 
 AC_ARG_ENABLE([extra-warning-flags],
   [AS_HELP_STRING([--disable-extra-warning-flags],
-    [don't add -Wall, -W, -Wshadow, and -Wold-style-cast options to CFLAGS and CXXFLAGS])],
+    [don't add -Wall, -W, -Wformat, -Wold-style-cast, and other warning options to CFLAGS and CXXFLAGS])],
   [if test "$enableval" = no; then
      try_extra_warning_flags=no
    fi],
# HG changeset patch
# User John W. Eaton <jwe@octave.org>
# Date 1470768112 14400
#      Tue Aug 09 14:41:52 2016 -0400
# Node ID 66dd260512a441f9ed70c5ab13fc296f4b8153bb
# Parent  60faa7c85e3186b9fbc750e0907f602a226a9d15
allow configure to select Qt version

* Makefile.am (AM_FFLAGS): Include FPICFLAG in definition.
(AM_CFLAGS): Include CPICFLAG in definition.
(AM_CXXFLAGS): Include CXXPICFLAG in definition.

* libgui/module.mk: Use MOCFLAGS, UICFLAGS, RCCFLAGS, and
LRELEASEFLAGS in MOC, UIC, RCC, and LRELEASE commands.

* acinclude.m4: Add CXXPICFLAG to CXXFLAGS in Qt tests.
(OCTAVE_CHECK_QSCINTILLA_VERSION): Rename from
OCTAVE_CHECK_VERSION_2_6_0.
(OCTAVE_CHECK_QT_VERSION, OCTAVE_CHECK_QT): New macros extracted from
configure.ac.

* configure.ac: Move checks for shared vs. static libraries earlier in
file.  Allow checking for multiple versions of Qt libraries.  Report
MOC, UIC, RCC, and LRELEASE in summary.

diff -r 60faa7c85e31 -r 66dd260512a4 Makefile.am
--- a/Makefile.am	Mon Aug 08 19:22:29 2016 -0400
+++ b/Makefile.am	Tue Aug 09 14:41:52 2016 -0400
@@ -38,11 +38,11 @@
 
 # Fortran compiler flags.
 
-AM_FFLAGS = @FFLAGS@
+AM_FFLAGS = ${FPICFLAG} @FFLAGS@
 
 # C compiler flags.
 
-AM_CFLAGS = ${XTRA_CFLAGS}
+AM_CFLAGS = ${CPICFLAG} ${XTRA_CFLAGS}
 
 # ifeq (${INCLUDE_DEPS},no)
 #   omit_deps = true;
@@ -50,7 +50,7 @@
 
 # C++ compiler flags.
 
-AM_CXXFLAGS = ${XTRA_CXXFLAGS}
+AM_CXXFLAGS = ${CXXPICFLAG} ${XTRA_CXXFLAGS}
 
 FFTW_XCPPFLAGS = @FFTW_XCPPFLAGS@
 FFTW_XLDFLAGS = @FFTW_XLDFLAGS@
diff -r 60faa7c85e31 -r 66dd260512a4 configure.ac
--- a/configure.ac	Mon Aug 08 19:22:29 2016 -0400
+++ b/configure.ac	Tue Aug 09 14:41:52 2016 -0400
@@ -484,1173 +484,6 @@
 AC_SUBST(DEPEND_FLAGS)
 AC_SUBST(DEPEND_EXTRA_SED_PATTERN)
 
-### Check for pthread library
-
-AX_PTHREAD
-## Include pthread libs and flags early in case other tests need them.
-## They seem to be required for the OpenGL tests on Debian systems.
-LIBS="$PTHREAD_LIBS $LIBS"
-XTRA_CFLAGS="$XTRA_CFLAGS $PTHREAD_CFLAGS"
-XTRA_CXXFLAGS="$XTRA_CXXFLAGS $PTHREAD_CFLAGS"
-## Set these for any other tests that may require them.  They will be
-## reset before output files are generated.
-CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
-
-### Test whether the compiler supports OpenMP.  This is enabled by default
-### now to allow the option of using OpenMP in loadable modules.
-
-ENABLE_OPENMP=no
-check_for_openmp=yes
-AC_ARG_ENABLE([openmp],
-  [AS_HELP_STRING([--disable-openmp],
-    [disable OpenMP SMP multi-threading])],
-  [if test "$enableval" = no; then check_for_openmp=no; fi], [])
-if test $check_for_openmp = yes; then
-  AC_LANG_PUSH(C)
-  AX_OPENMP([XTRA_CFLAGS="$XTRA_CFLAGS $OPENMP_CFLAGS"; ENABLE_OPENMP=yes], [])
-  AC_LANG_POP(C)
-  AC_LANG_PUSH(C++)
-  AX_OPENMP([XTRA_CXXFLAGS="$XTRA_CXXFLAGS $OPENMP_CXXFLAGS"; ENABLE_OPENMP=yes], [])
-  AC_LANG_POP(C++)
-fi
-
-## Set these for any other tests that may require them.  They will be
-## reset before output files are generated.
-CFLAGS="$CFLAGS $OPENMP_CFLAGS"
-CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS"
-
-dnl Define here since it is skipped if the first argument to
-dnl AX_OPENMP is not empty.
-if test $ENABLE_OPENMP = yes; then
-  AC_CHECK_HEADERS([omp.h])
-  AC_CHECK_FUNCS([omp_get_num_threads])
-  AC_DEFINE(OCTAVE_ENABLE_OPENMP, 1, [Define if OpenMP is enabled])
-fi
-
-### When compiling math for x87, problems may arise in some code comparing
-### floating-point intermediate results.  The root cause is the extra precision
-### (~80 bits) of x87 co-processor registers versus the IEEE standard 64 bits.
-### Generally, storing the result in a local volatile variable forces a
-### truncation back to 64 bits, but it also degrades performance.
-### However, this performance degradation is very minimal, if indeed measurable.
-### Therefore, it has been enabled for all platforms and compilers.
-### Reported bugs indicate that --enable-float-truncate is required for MinGW
-### and Cygwin platforms and for GCC compilers >= 5.0.  It should not be
-### necessary for non-x87 targets or when using modern SSE math.
-ENABLE_FLOAT_TRUNCATE=yes
-AC_ARG_ENABLE([float-truncate],
-  [AS_HELP_STRING([--disable-float-truncate],
-    [truncate intermediate FP results])],
-  [if test "$enableval" = no; then ENABLE_FLOAT_TRUNCATE=no; fi], [])
-if test $ENABLE_FLOAT_TRUNCATE = yes; then
-  AC_DEFINE(OCTAVE_ENABLE_FLOAT_TRUNCATE, 1,
-    [Define to 1 if you need to truncate intermediate FP results.])
-fi
-
-### Determine extra CFLAGS that may be necessary for Octave.
-
-## On Intel systems with gcc, we may need to compile with -mieee-fp
-## to get full support for IEEE floating point.
-##
-## On Alpha/OSF systems, we need -mieee.
-
-ieee_fp_flag=
-case $canonical_host_type in
-  i[[3456789]]86-*-*)
-    if test "$GCC" = yes; then
-      OCTAVE_CC_FLAG([-mieee-fp], [
-        ieee_fp_flag=-mieee-fp
-        XTRA_CFLAGS="$XTRA_CFLAGS -mieee-fp"
-        AC_MSG_NOTICE([adding -mieee-fp to XTRA_CFLAGS])])
-    fi
-    if test "$GXX" = yes; then
-      OCTAVE_CXX_FLAG([-mieee-fp], [
-        ieee_fp_flag=-mieee-fp
-        XTRA_CXXFLAGS="$XTRA_CXXFLAGS -mieee-fp"
-        AC_MSG_NOTICE([adding -mieee-fp to XTRA_CXXFLAGS])])
-    fi
-  ;;
-  alpha*-*-*)
-    if test "$GCC" = yes; then
-      OCTAVE_CC_FLAG([-mieee], [
-        ieee_fp_flag=-mieee
-        XTRA_CFLAGS="$XTRA_CFLAGS -mieee"
-        AC_MSG_NOTICE([adding -mieee to XTRA_CFLAGS])])
-    else
-      OCTAVE_CC_FLAG([-ieee], [
-        ieee_fp_flag=-ieee
-        XTRA_CFLAGS="$XTRA_CFLAGS -ieee"
-        AC_MSG_NOTICE([adding -ieee to XTRA_CFLAGS])])
-    fi
-    if test "$GXX" = yes; then
-      OCTAVE_CXX_FLAG([-mieee], [
-        ieee_fp_flag=-mieee
-        XTRA_CXXFLAGS="$XTRA_CXXFLAGS -mieee"
-        AC_MSG_NOTICE([adding -mieee to XTRA_CXXFLAGS])])
-    else
-      OCTAVE_CXX_FLAG([-ieee], [
-        ieee_fp_flag=-ieee
-        XTRA_CXXFLAGS="$XTRA_CXXFLAGS -ieee"
-        AC_MSG_NOTICE([adding -ieee to XTRA_CXXFLAGS])])
-    fi
-  ;;
-  *ibm-aix4*)
-    OCTAVE_CC_FLAG([-mminimal-toc], [
-      XTRA_CFLAGS="$XTRA_CFLAGS -mminimal-toc"])
-
-    OCTAVE_CXX_FLAG([-mminimal-toc], [
-      XTRA_CXXFLAGS="$XTRA_CXXFLAGS -mminimal-toc"])
-  ;;
-esac
-
-AC_SUBST(XTRA_CFLAGS)
-AC_SUBST(XTRA_CXXFLAGS)
-
-### Defaults for cross compiling.  BUILD_CC and BUILD_CXX are
-### the compilers that we use for building tools on the build system.
-### For now, we assume that the only cross compiling we can do is
-### with gcc on a Unixy system, but the dedicated hacker can override these.
-
-if test "$cross_compiling" = yes; then
-  BUILD_CC="gcc"
-  BUILD_CFLAGS="-O2 -g"
-  BUILD_CXX="g++"
-  BUILD_CXXFLAGS="-O2 -g"
-  BUILD_LDFLAGS=""
-  BUILD_EXEEXT=""
-else
-  BUILD_CC="${CC}"
-  BUILD_CFLAGS="${CFLAGS}"
-  BUILD_CXX="${CXX}"
-  BUILD_CXXFLAGS="${CXXFLAGS}"
-  BUILD_LDFLAGS="${LDFLAGS}"
-  BUILD_EXEEXT="${EXEEXT}"
-fi
-
-AC_ARG_VAR([BUILD_CC],
-  [build system C compiler (used if cross compiling)])
-AC_ARG_VAR([BUILD_CFLAGS],
-  [build system C compiler flags (used if cross compiling)])
-AC_ARG_VAR([BUILD_CXX],
-  [build system C++ compiler (used if cross compiling)])
-AC_ARG_VAR([BUILD_CXXFLAGS],
-  [build system C++ compiler flags (used if cross compiling)])
-AC_ARG_VAR([BUILD_LDFLAGS],
-  [build system C++ compiler link flags (used if cross compiling)])
-AC_ARG_VAR([BUILD_EXEEXT],
-  [build system executable extension (used if cross compiling)])
-
-
-### Look for math library.  If found, this will add -lm to LIBS.
-
-dnl Keep this check before the check for the Fortran compiler,
-dnl in case -lm is needed to compile Fortran programs.
-AC_CHECK_LIB(m, sin)
-
-### Determine the Fortran compiler and how to invoke it
-
-## Prefer gfortran, but the user's F77 environment variable will override.
-AC_PROG_F77([gfortran])
-if test -z "$F77"; then
-  ## No gfortran found, search for any other installed compiler.
-  AC_PROG_F77
-fi
-if test "$F77" = g77; then
-  AC_MSG_ERROR([g77 is not a supported Fortran compiler.  Select another compiler by setting the environment variable F77 and re-running configure.])
-fi
-
-AC_MSG_CHECKING([whether a usable Fortran compiler was found])
-if test -n "$F77"; then
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-  AC_MSG_ERROR([A Fortran compiler is required])
-fi
-
-AC_F77_LIBRARY_LDFLAGS
-AC_F77_DUMMY_MAIN
-AC_F77_WRAPPERS
-
-F77_TOLOWER=yes
-F77_APPEND_UNDERSCORE=yes
-F77_APPEND_EXTRA_UNDERSCORE=yes
-
-case $ac_cv_f77_mangling in
-  "upper case") F77_TOLOWER=no ;;
-esac
-case $ac_cv_f77_mangling in
-  "no underscore") F77_APPEND_UNDERSCORE=no ;;
-esac
-case $ac_cv_f77_mangling in
-  "no extra underscore") F77_APPEND_EXTRA_UNDERSCORE=no ;;
-esac
-
-case $canonical_host_type in
-  i[[3456789]]86-*-*)
-    if test $ac_cv_f77_compiler_gnu = yes; then
-      OCTAVE_F77_FLAG([-mieee-fp])
-    fi
-  ;;
-  alpha*-*-*)
-    if test $ac_cv_f77_compiler_gnu = yes; then
-      OCTAVE_F77_FLAG([-mieee])
-    else
-      OCTAVE_F77_FLAG([-ieee])
-      OCTAVE_F77_FLAG([-fpe1])
-    fi
-  ;;
-  powerpc-apple-machten*)
-    FFLAGS=
-  ;;
-esac
-
-if test $ac_cv_f77_compiler_gnu = yes; then
-  FORTRAN_CALLING_CONVENTION=gfortran
-else
-  FORTRAN_CALLING_CONVENTION=unknown
-fi
-AC_ARG_ENABLE([fortran-calling-convention],
-  [AS_HELP_STRING([--enable-fortran-calling-convention=OPTION],
-    [Select C++ to Fortran calling convention.  "gfortran" should be detected automatically.  Other options are "cray", "visual-fortran", or "f2c".])],
-  [FORTRAN_CALLING_CONVENTION="$enableval"], [])
-
-case "$FORTRAN_CALLING_CONVENTION" in
-  gfortran)
-    AC_DEFINE(F77_USES_GFORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the gfortran calling convention.])
-  ;;
-  cray)
-    AC_DEFINE(F77_USES_CRAY_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Cray Fortran calling convention.])
-  ;;
-  visual-fortran)
-    AC_DEFINE(F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Visual Fortran calling convention.])
-  ;;
-  f2c)
-    AC_DEFINE(F77_USES_F2C_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the f2c calling convention.])
-  ;;
-  *)
-    AC_MSG_ERROR([to build Octave, the C++ to Fortran calling convention must be known.])
-  ;;
-esac
-
-if test -n "$FFLAGS"; then
-  AC_MSG_NOTICE([defining FFLAGS to be $FFLAGS])
-fi
-
-AC_SUBST(F77_TOLOWER)
-AC_SUBST(F77_APPEND_UNDERSCORE)
-AC_SUBST(F77_APPEND_EXTRA_UNDERSCORE)
-
-if test -z "$F77"; then
-  AC_MSG_ERROR([to build Octave, you must have a compatible Fortran compiler or wrapper script for f2c that functions as a Fortran compiler installed and in your path.  See the file INSTALL for more information.])
-fi
-
-OCTAVE_CHECK_FUNC_FORTRAN_ISNAN
-F77_ISNAN_MACRO=
-if test $octave_cv_func_fortran_isnan = no; then
-  AC_MSG_NOTICE([substituting ISNAN(X) with X.NE.X in Fortran sources])
-  F77_ISNAN_MACRO="s|ISNAN(\(@<:@^)@:>@*\))|(\1.NE.\1)|"
-fi
-AC_SUBST(F77_ISNAN_MACRO)
-
-OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER
-if test $octave_cv_sizeof_fortran_integer = no; then
-  if test $ENABLE_64 = yes; then
-    case $F77 in
-      *gfortran*)
-        case $F77_INTEGER_8_FLAG in
-          *-fdefault-integer-8*)
-          ;;
-          *)
-            case $FFLAGS in
-              *-fdefault-integer-8*)
-                AC_MSG_NOTICE([setting -fdefault-integer-8 in F77_INTEGER_8_FLAG instead of FFLAGS])
-                FFLAGS=`echo $FFLAGS | $SED 's/-fdefault-integer-8//g'`
-                F77_INTEGER_8_FLAG="-fdefault-integer-8"
-              ;;
-              *)
-                AC_MSG_NOTICE([adding -fdefault-integer-8 to F77_INTEGER_8_FLAG])
-                F77_INTEGER_8_FLAG="-fdefault-integer-8"
-                ## Invalidate the cache and try again.
-                $as_unset octave_cv_sizeof_fortran_integer
-              ;;
-            esac
-          ;;
-        esac
-      ;;
-    esac
-    if test -z "$octave_cv_sizeof_fortran_integer"; then
-      OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER
-    fi
-    if test $octave_cv_sizeof_fortran_integer = no; then
-      AC_MSG_ERROR([to build Octave with 64-bit indexing support your Fortran compiler must have an option for setting the default integer size to 8 bytes.  See the file INSTALL for more information.])
-    fi
-  else
-    AC_MSG_ERROR([your Fortran compiler must have an option to make integers the same size as octave_idx_type ($OCTAVE_IDX_TYPE).  See the file INSTALL for more information.])
-  fi
-fi
-AC_SUBST(F77_INTEGER_8_FLAG)
-
-OCTAVE_F77_FLAG([-ffloat-store], [
-  AC_MSG_RESULT([setting F77_FLOAT_STORE_FLAG to -ffloat-store])
-  F77_FLOAT_STORE_FLAG=-ffloat-store
-  AC_SUBST(F77_FLOAT_STORE_FLAG)
-])
-
-### Check for the Qhull library
-
-OCTAVE_CHECK_LIB(qhull, QHull,
-  [Qhull library not found.  This will result in loss of functionality of some geometry functions.],
-  [libqhull/libqhull.h qhull/libqhull.h libqhull.h qhull/qhull.h qhull.h],
-  [qh_qhull], [], [],
-  [warn_qhull=
-  OCTAVE_CHECK_QHULL_VERSION
-  OCTAVE_CHECK_LIB_QHULL_OK(
-    [AC_DEFINE(HAVE_QHULL, 1, [Define to 1 if Qhull is available.])],
-    [warn_qhull="Qhull library found, but does not seem to work properly.  This will result in loss of functionality of some geometry functions.  Please try recompiling the library with -fno-strict-aliasing."])])
-
-### Check for PCRE regex library.
-
-PCRE_LIBS=
-
-pcre_fail_msg="to build Octave, you must have the PCRE library and header files installed"
-
-AC_CHECK_HEADERS([pcre.h pcre/pcre.h])
-
-AC_CACHE_CHECK([whether pcre.h defines the macros we need],
-  [ac_cv_pcre_h_macros_present],
-  [AC_EGREP_CPP([PCRE_HAS_MACROS_WE_NEED], [
-    #if defined (HAVE_PCRE_H)
-    # include <pcre.h>
-    #elif defined (HAVE_PCRE_PCRE_H)
-    # include <pcre/pcre.h>
-    #error "NO PCRE HEADER"
-    #endif
-    #if defined (PCRE_INFO_NAMECOUNT) \
-      && defined (PCRE_INFO_NAMEENTRYSIZE) \
-      && defined (PCRE_INFO_NAMETABLE)
-      PCRE_HAS_MACROS_WE_NEED
-    #endif],
-    ac_cv_pcre_h_macros_present=yes, ac_cv_pcre_h_macros_present=no)])
-
-if test $ac_cv_pcre_h_macros_present = yes; then
-  ## check for pcre-config, and if so, get build variables
-  AC_CHECK_PROG(HAVE_PCRE_CONFIG, pcre-config, [yes], [no])
-  if test $HAVE_PCRE_CONFIG = yes; then
-    PCRE_CPPFLAGS=`pcre-config --cflags`
-    PCRE_LIBS=`pcre-config --libs`
-  else
-    PCRE_LIBS="-lpcre"
-  fi
-  save_LIBS="$LIBS"
-  LIBS="$PCRE_LIBS $LIBS"
-  AC_CHECK_FUNCS([pcre_compile],
-    [AC_SUBST(PCRE_CPPFLAGS)
-     AC_SUBST(PCRE_LIBS)],
-    [AC_MSG_ERROR([$pcre_fail_msg])])
-  LIBS="$save_LIBS"
-else
-  AC_MSG_ERROR([$pcre_fail_msg])
-fi
-
-### Check for ZLIB library.
-
-OCTAVE_CHECK_LIB(z, ZLIB,
-  [ZLIB library not found.  Octave will not be able to save or load compressed data files or HDF5 files.],
-  [zlib.h], [gzclearerr])
-
-### Also define HAVE_ZLIB if libz is found.
-if test -z "$warn_z"; then
-  AC_DEFINE(HAVE_ZLIB, 1, [Define to 1 if ZLIB is available.])
-fi
-
-
-### Check for BZIP2 library.
-
-OCTAVE_CHECK_LIB(bz2, BZIP2,
-  [BZIP2 library not found.  Octave will not be able to compress or decompress bzip2 files.],
-  [bzlib.h], [BZ2_bzCompressInit])
-
-
-### Check for the LLVM library
-
-ENABLE_JIT=no
-AC_ARG_ENABLE([jit],
-  [AS_HELP_STRING([--enable-jit],
-    [(EXPERIMENTAL) enable JIT compiler])],
-  [if test "$enableval" = yes; then ENABLE_JIT=yes; fi], [])
-
-LLVM_CXXFLAGS=
-LLVM_CPPFLAGS=
-LLVM_LDFLAGS=
-LLVM_LIBS=
-
-if test $ENABLE_JIT = yes; then
-
-  ## Find llvm-config program from environment variable or by searching
-  AC_ARG_VAR([LLVM_CONFIG], [path to llvm-config utility])
-  AC_CHECK_PROG([LLVM_CONFIG], llvm-config, llvm-config, [])
-
-  if test -z "$LLVM_CONFIG"; then
-    warn_llvm="llvm-config utility not found.  JIT compiler is disabled."
-  else
-    dnl Preset warning message in case compile fails
-    warn_llvm="LLVM was not found or is to old.  JIT compiler is disabled."
-
-    save_CPPFLAGS="$CPPFLAGS"
-    save_CXXFLAGS="$CXXFLAGS"
-    save_LDFLAGS="$LDFLAGS"
-
-    ## Use -isystem if available because we don't want to see warnings in LLVM
-    LLVM_INCLUDE_FLAG=-I
-    OCTAVE_CC_FLAG([-isystem .], [
-      LLVM_INCLUDE_FLAG=-isystem
-      AC_MSG_NOTICE([using -isystem for LLVM headers])])
-
-    dnl Use -isystem so we don't get warnings from llvm headers
-    LLVM_CPPFLAGS="$LLVM_INCLUDE_FLAG `$LLVM_CONFIG --includedir`"
-    LLVM_CXXFLAGS=
-    LLVM_LDFLAGS="-L`$LLVM_CONFIG --libdir`"
-
-
-    LDFLAGS="$LDFLAGS $LLVM_LDFLAGS"
-    LLVM_SO=LLVM-`$LLVM_CONFIG --version`
-    AC_CHECK_LIB([$LLVM_SO], [LLVMBuildAdd], [LLVM_LIBS="-l$LLVM_SO"], [LLVM_LIBS=`$LLVM_CONFIG --libs`])
-
-    dnl
-    dnl Define some extra flags that LLVM requires in order to include headers.
-    dnl Ideally we should get these from llvm-config, but llvm-config isn't
-    dnl very helpful.
-    dnl
-    CPPFLAGS="-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS $LLVM_CPPFLAGS $CPPFLAGS"
-    CXXFLAGS="$LLVM_CXXFLAGS $CXXFLAGS"
-    AC_LANG_PUSH(C++)
-    AC_CHECK_HEADER([llvm/Support/TargetSelect.h], [warn_llvm=""])
-
-    have_function_h=no
-    AC_CHECK_HEADERS([llvm/IR/Function.h llvm/Function.h],
-                     [have_function_h=yes; break])
-    if test $have_function_h = no; then
-      warn_llvm="Missing LLVM file Function.h.  JIT compiler is disabled."
-    fi
-    have_irbuilder_h=no
-    AC_CHECK_HEADERS([llvm/Support/IRBuilder.h llvm/IR/IRBuilder.h \
-                      llvm/IRBuilder.h], [have_irbuilder_h=yes; break])
-    if test $have_irbuilder_h = no; then
-      warn_llvm="Missing LLVM file IRBuilder.h.  JIT compiler is disabled."
-    fi
-    have_llvm_data_h=no
-    AC_CHECK_HEADERS([llvm/Target/TargetData.h llvm/IR/DataLayout.h \
-                      llvm/DataLayout.h], [have_llvm_data_h=yes; break])
-    if test $have_llvm_data_h = no; then
-      warn_llvm="Missing LLVM file TargetData.h.  JIT compiler is disabled."
-    fi
-
-    AC_CHECK_HEADERS([llvm/IR/Verifier.h])
-
-    OCTAVE_LLVM_FUNCTION_ADDATTRIBUTE_API
-    OCTAVE_LLVM_FUNCTION_ADDFNATTR_API
-    OCTAVE_LLVM_CALLINST_ADDATTRIBUTE_API
-    OCTAVE_LLVM_RAW_FD_OSTREAM_API
-    OCTAVE_LLVM_LEGACY_PASSMANAGER_API
-    AC_LANG_POP(C++)
-    CPPFLAGS="$save_CPPFLAGS"
-    CXXFLAGS="$save_CXXFLAGS"
-    LDFLAGS="$save_LDFLAGS"
-  fi
-
-  if test -z "$warn_llvm"; then
-    AC_DEFINE(HAVE_LLVM, 1, [Define to 1 if LLVM is available.])
-  else
-    ENABLE_JIT=no
-    LLVM_CPPFLAGS=
-    LLVM_CXXFLAGS=
-    LLVM_LDFLAGS=
-    LLVM_LIBS=
-    OCTAVE_CONFIGURE_WARNING([warn_llvm])
-  fi
-dnl FIXME: Re-instate when JIT is enabled by default
-dnl else
-dnl   ## JIT build disabled
-dnl   warn_llvm="JIT compiler disabled, some performance loss for loops"
-dnl   OCTAVE_CONFIGURE_WARNING([warn_llvm])
-fi
-if test $ENABLE_JIT; then
-  AC_DEFINE(ENABLE_JIT, 1, [Define to 1 to enable JIT compiler.])
-fi
-
-AC_SUBST(LLVM_CPPFLAGS)
-AC_SUBST(LLVM_CXXFLAGS)
-AC_SUBST(LLVM_LDFLAGS)
-AC_SUBST(LLVM_LIBS)
-AM_CONDITIONAL([AMCOND_HAVE_LLVM], [test -z "$warn_llvm"])
-
-### Check for HDF5 library.
-
-save_CPPFLAGS="$CPPFLAGS"
-save_LIBS="$LIBS"
-CPPFLAGS="$Z_CPPFLAGS $CPPFLAGS"
-LIBS="$Z_LDFLAGS $Z_LIBS $LIBS"
-OCTAVE_CHECK_LIB(hdf5, HDF5,
-  [HDF5 library not found.  Octave will not be able to save or load HDF5 data files.],
-  [hdf5.h], [H5Gget_num_objs], [], [],
-  [warn_hdf5=
-   OCTAVE_CHECK_HDF5_HAS_VER_16_API
-   AC_DEFINE(HAVE_HDF5, 1,
-     [Define to 1 if HDF5 is available and newer than version 1.6.])
-   if test $have_msvc = yes; then
-     OCTAVE_CHECK_LIB_HDF5_DLL
-   fi
-  ])
-CPPFLAGS="$save_CPPFLAGS"
-LIBS="$save_LIBS"
-
-dnl Should we check for this now, or wait until some version of
-dnl HDF5 actually supports this feature?
-have_hdf5_int2float_conversions=no
-if test $have_hdf5_int2float_conversions = yes; then
-  AC_DEFINE(HAVE_HDF5_INT2FLOAT_CONVERSIONS, 1,
-    [Define to 1 if/when HDF5 supports automatic conversion between integer and floating-point binary data.])
-fi
-
-### Check for FFTW library.  Default to Fortran FFTPACK if it is not available.
-
-## Check for FFTW header and library.
-OCTAVE_CHECK_LIB(fftw3, FFTW3,
-  [FFTW3 library not found.  The slower FFTPACK library will be used instead.],
-  [fftw3.h], [fftw_plan_dft_1d])
-
-OCTAVE_CHECK_LIB(fftw3f, FFTW3F,
-  [FFTW3F library not found.  The slower FFTPACK library will be used instead.],
-  [fftw3.h], [fftwf_plan_dft_1d])
-
-## Check command line for the option to disable multi-threaded FFTW
-build_fftw_threads=yes
-AC_ARG_ENABLE([fftw-threads],
-  [AS_HELP_STRING([--disable-fftw-threads],
-    [disable Multi-threaded FFTW])],
-  [if test "$enableval" = no; then
-     build_fftw_threads=no
-   fi],
-  [])
-
-## Octave is currently unable to use FFTW unless
-## both float and double versions are available.
-
-AM_CONDITIONAL([AMCOND_HAVE_FFTW],
-  [test -n "$FFTW3_LIBS" && test -n "$FFTW3F_LIBS"])
-
-if test -n "$FFTW3_LIBS" && test -n "$FFTW3F_LIBS"; then
-  AC_DEFINE(HAVE_FFTW, 1, [Define if you have both FFTW3 and FFTW3F libraries.])
-else
-  ## --without-fftw3 given, or one of the FFTW3 libs not installed.
-  ## Don't check for FFTW threads as this is now pointless.
-  build_fftw_threads=no
-fi
-
-## Check for the multithreaded FFTW library.
-## Fallback to singlethreaded if not found or disabled
-if test $build_fftw_threads = yes; then
-  OCTAVE_CHECK_FFTW_THREADS(fftw3, fftw_plan_with_nthreads)
-  OCTAVE_CHECK_FFTW_THREADS(fftw3f, fftwf_plan_with_nthreads)
-fi
-
-## Subdirectory of liboctave/cruft to build if FFTW is not found.
-FFT_DIR="fftpack"
-AC_SUBST(FFT_DIR)
-
-### Check for GLPK library and header.
-
-save_CPPFLAGS="$CPPFLAGS"
-save_LIBS="$LIBS"
-CPPFLAGS="$Z_CPPFLAGS $CPPFLAGS"
-LIBS="$Z_LDFLAGS $Z_LIBS $LIBS"
-OCTAVE_CHECK_LIB(glpk, GLPK,
-  [GLPK library not found.  The glpk function for solving linear programs will be disabled.],
-  [glpk/glpk.h glpk.h], [glp_simplex], [], [],
-  [warn_glpk=
-   OCTAVE_CHECK_LIB_GLPK_OK(
-    [AC_DEFINE(HAVE_GLPK, 1, [Define to 1 if GLPK is available.])],
-    [warn_glpk="GLPK library found, but does not seem to work properly; disabling glpk function"])])
-LIBS="$save_LIBS"
-CPPFLAGS="$save_CPPFLAGS"
-
-### Checks for cURL header and library.
-
-save_CPPFLAGS="$CPPFLAGS"
-save_LIBS="$LIBS"
-CPPFLAGS="$Z_CPPFLAGS $CPPFLAGS"
-LIBS="$Z_LDFLAGS $Z_LIBS $LIBS"
-OCTAVE_CHECK_LIB(curl, cURL,
-  [cURL library not found.  The ftp objects, urlread and urlwrite functions will be disabled.],
-  [curl/curl.h], [curl_easy_escape])
-if test -z "$warn_curl"; then
-  ## Additional check on cURL library that was found
-  AC_CACHE_CHECK([for CURLOPT_DIRLISTONLY in curl/curl.h],
-    [octave_cv_curl_has_curlopt_dirlistonly],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-      #include <curl/curl.h>
-      ]], [[
-      curl_easy_setopt ((CURL*)NULL, CURLOPT_DIRLISTONLY, 0);
-      ]])],
-      [octave_cv_curl_has_curlopt_dirlistonly=yes],
-      [octave_cv_curl_has_curlopt_dirlistonly=no])
-    ])
-  if test $octave_cv_curl_has_curlopt_dirlistonly = no; then
-    AC_DEFINE(CURLOPT_DIRLISTONLY, CURLOPT_FTPLISTONLY,
-      [Define to the legacy option name if using an older version of cURL.])
-  fi
-fi
-LIBS="$save_LIBS"
-CPPFLAGS="$save_CPPFLAGS"
-
-### Check for sndfile
-
-OCTAVE_CHECK_LIB(sndfile, sndfile,
-  [sndfile library not found.  The audioinfo, audioread, and audiowrite functions will be disabled.],
-  [sndfile.h], [sf_open],
-  [], [don't use sndfile library, disable audio file I/O],
-  [warn_sndfile=
-   OCTAVE_CHECK_LIB_SNDFILE_OK(
-    [AC_DEFINE(HAVE_SNDFILE, 1, [Define to 1 if sndfile is available.])],
-    [warn_sndfile="sndfile library found, but does not seem to work properly; disabling audio file I/O functions"])])
-
-### Check for PortAudio
-
-OCTAVE_CHECK_LIB(portaudio, PortAudio,
-  [PortAudio library not found.  The audioplayer, audiorecorder, and audiodevinfo functions will be disabled.],
-  [portaudio.h], [Pa_Initialize],
-  [], [don't use PortAudio library, disable audio playback and recording],
-  [], [portaudio-2.0])
-
-### Check for either of Graphics/ImageMagick++ libraries
-
-check_magick=yes
-use_magick=no
-AC_ARG_WITH([magick],
-  [AS_HELP_STRING([--with-magick=LIB],
-    [select library to use for image I/O (options: GraphicsMagick(default) or ImageMagick)])],
-  [if test x"$withval" = xno; then
-     check_magick=no
-     warn_magick_disabled="--without-magick specified.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."
-     OCTAVE_CONFIGURE_WARNING([warn_magick_disabled])
-   else
-     magick="$withval"
-   fi], [magick="GraphicsMagick"])
-
-if test $check_magick = yes; then
-
-  MAGICK_CPPFLAGS=
-  MAGICK_LDFLAGS=
-  MAGICK_LIBS=
-
-  PKG_CHECK_EXISTS([$magick++], [
-    ## Make sure we only get -I, -L, and -l flags.  Some Graphics/ImageMagick++
-    ## packages add extra flags that are useful when building
-    ## Graphics/ImageMagick++ extentions.  These extra flags break the
-    ## Octave build.
-    MAGICK_CPPFLAGS=`$PKG_CONFIG --cflags-only-I $magick++`
-    MAGICK_LDFLAGS=`$PKG_CONFIG --libs-only-L $magick++`
-    MAGICK_LIBS=`$PKG_CONFIG --libs-only-l $magick++`
-
-    warn_magick="$magick++ library fails tests.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."
-
-    save_CPPFLAGS="$CPPFLAGS"
-    save_LIBS="$LIBS"
-    CPPFLAGS="$MAGICK_CPPFLAGS $CPPFLAGS"
-    LIBS="$MAGICK_LDFLAGS $MAGICK_LIBS $LIBS"
-    AC_LANG_PUSH(C++)
-    AC_CHECK_HEADER([Magick++.h], [
-      AC_CACHE_CHECK([for Magick::ColorRGB in Magick++.h],
-        [octave_cv_func_magick_colorrgb],
-        [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
-          #include <Magick++.h>
-          ]], [[
-          Magick::ColorRGB c;
-          ]])],
-          octave_cv_func_magick_colorrgb=yes,
-          octave_cv_func_magick_colorrgb=no)
-        ])
-      if test $octave_cv_func_magick_colorrgb = yes; then
-        use_magick=yes
-        warn_magick=
-      fi
-    ])
-    AC_LANG_POP(C++)
-    CPPFLAGS="$save_CPPFLAGS"
-    LIBS="$save_LIBS"
-
-    AC_CHECK_FUNCS([setlocale], [],
-      [use_magick=no
-       warn_magick="$magick++ requires setlocale function.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."])
-  ],
-  [use_magick=no
-   warn_magick="$magick++ library not found.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."])
-fi
-
-if test $use_magick = yes; then
-  AC_DEFINE(HAVE_MAGICK, 1,
-    [Define to 1 if Graphics/ImageMagick++ is available.])
-else
-  if test -n "$warn_magick"; then
-    OCTAVE_CONFIGURE_WARNING([warn_magick])
-  fi
-  MAGICK_CPPFLAGS=
-  MAGICK_LDFLAGS=
-  MAGICK_LIBS=
-fi
-AC_SUBST(MAGICK_CPPFLAGS)
-AC_SUBST(MAGICK_LDFLAGS)
-AC_SUBST(MAGICK_LIBS)
-
-### Check for X11 libraries
-
-AC_PATH_X
-if test "$have_x" = yes; then
-  AC_DEFINE(HAVE_X_WINDOWS, 1, [Define to 1 if you have X11.])
-
-  if test "$x_includes" != "NONE"; then
-    X11_INCFLAGS="$x_includes"
-  fi
-  AC_SUBST(X11_INCFLAGS)
-
-  if test -z "$x_libraries"; then
-    AC_CHECK_LIB([X11], XrmInitialize, [X11_LIBS="-lX11"], [X11_LIBS=])
-  elif test "$x_libraries" != "NONE"; then
-    AC_CHECK_LIB([X11], XrmInitialize,
-      [X11_LIBS="-L$x_libraries -lX11"], [X11_LIBS=], "-L$x_libraries")
-  fi
-  AC_SUBST(X11_LIBS)
-fi
-
-### Check for the Carbon framework on MacOSX systems
-OCTAVE_HAVE_FRAMEWORK([Carbon],
-  [[#include <Carbon/Carbon.h>]], [[CGMainDisplayID ()]],
-  [have_framework_carbon=yes], [have_framework_carbon=no])
-if test $have_framework_carbon = yes; then
-  AC_DEFINE(HAVE_FRAMEWORK_CARBON, 1,
-    [Define to 1 if framework CARBON is available.])
-  CARBON_LIBS="-framework Carbon"
-  AC_MSG_NOTICE([adding -framework Carbon to CARBON_LIBS])
-  AC_SUBST(CARBON_LIBS)
-fi
-
-### Check for list of libraries needed for OpenGL graphics renderer.
-
-check_opengl=yes
-AC_ARG_WITH([opengl],
-  [AS_HELP_STRING([--without-opengl],
-    [don't use OpenGL libraries, disable OpenGL graphics])],
-  [if test x"$withval" = xno; then
-     check_opengl=no
-     warn_opengl_disabled="--without-opengl specified.  OpenGL graphics will be disabled."
-     OCTAVE_CONFIGURE_WARNING([warn_opengl_disabled])
-   fi])
-
-## Check for OpenGL library
-if test $check_opengl = yes; then
-  OCTAVE_CHECK_LIB_OPENGL
-  if test -z "$OPENGL_LIBS"; then
-    warn_opengl_libs="OpenGL libs (GL and GLU) not found.  OpgnGL graphics will be disabled."
-    OCTAVE_CONFIGURE_WARNING([warn_opengl_libs])
-  fi
-fi
-
-## Check for FreeType 2 library
-
-warn_freetype=""
-PKG_CHECK_MODULES([FT2], [freetype2], [
-  min_ft2_version=9.03
-  AC_MSG_CHECKING([for FreeType2 version >= $min_ft2_version])
-  $PKG_CONFIG freetype2 --atleast-version=$min_ft2_version
-  ac_status=$?
-  if test "$ac_status" = 0; then
-    AC_MSG_RESULT(yes)
-    AC_DEFINE(HAVE_FREETYPE, 1, [Define to 1 if you have Freetype library.])
-    save_LIBS="$LIBS"
-    LIBS="$FT2_LIBS $LIBS"
-    AC_CHECK_FUNCS([FT_Reference_Face])
-    LIBS="$save_LIBS"
-  else
-    AC_MSG_RESULT(no)
-    warn_freetype="FreeType library >= 9.03 not found.  OpenGL graphics will not be fully functional."
-  fi])
-
-if test -n "$warn_freetype"; then
-  OCTAVE_CONFIGURE_WARNING([warn_freetype])
-else
-  FT2_CPPFLAGS="$FT2_CFLAGS"
-  ## Alias CPPFLAGS to CFLAGS.  This is closer to the true meaning
-  ## of `pkg-config --cflags` output.
-  FT2_CPPFLAGS="$FT2_CFLAGS"
-  AC_SUBST(FT2_CPPFLAGS)
-fi
-
-## Check for Xft library (when using X11)
-
-warn_xft=""
-if test "$have_x" = yes; then
-  PKG_CHECK_MODULES(XFT, [xft],
-    [AC_DEFINE(HAVE_XFT, 1, [Define to 1 if Xft is present.])],
-    [warn_xft="Xft library not found.  OpenGL graphics will not be fully functional."])
-fi
-
-if test -n "$warn_xft"; then
-  OCTAVE_CONFIGURE_WARNING([warn_xft])
-fi
-
-## Check for fontconfig library
-
-warn_fontconfig=""
-PKG_CHECK_MODULES(FONTCONFIG, [fontconfig],
-  [AC_DEFINE(HAVE_FONTCONFIG, 1, [Define to 1 if fontconfig is present.])],
-  [warn_fontconfig="Fontconfig library not found.  OpenGL graphics will not be fully functional."])
-
-if test -n "$warn_fontconfig"; then
-  OCTAVE_CONFIGURE_WARNING([warn_fontconfig])
-else
-  FONTCONFIG_CPPFLAGS="$FONTCONFIG_CFLAGS"
-  ## Alias CPPFLAGS to CFLAGS.  This is closer to the true meaning
-  ## of `pkg-config --cflags` output.
-  FONTCONFIG_CPPFLAGS="$FONTCONFIG_CFLAGS"
-  AC_SUBST(FONTCONFIG_CPPFLAGS)
-fi
-
-## Check for OSMesa which is needed for offscreen rendering with OpenGL
-## FIXME: Check for version >= 9.0.0
-OCTAVE_CHECK_LIB(OSMesa, OSMesa,
-  [OSMesa library not found.  Offscreen rendering with OpenGL will be disabled.],
-  [osmesa.h GL/osmesa.h], [OSMesaCreateContext])
-
-## Check for gl2ps which is required for printing with OpenGL graphics
-
-AC_CHECK_HEADERS([gl2ps.h],
-  [GL2PS_LIBS="-lgl2ps"],
-  [warn_gl2ps="gl2ps library not found.  Printing of OpenGL graphics will be disabled."])
-
-if test -n "$warn_gl2ps"; then
-  OCTAVE_CONFIGURE_WARNING([warn_gl2ps])
-fi
-
-AC_SUBST(GL2PS_LIBS)
-
-### GUI/Qt related tests.
-
-QT_CPPFLAGS=
-QT_LDFLAGS=
-QT_LIBS=
-
-check_qt=yes
-build_qt_gui=no
-build_qt_graphics=no
-use_qscintilla=no
-win32_terminal=no
-
-AC_ARG_WITH([qt],
-  [AS_HELP_STRING([--without-qt], [don't use Qt libraries; disable Qt GUI])],
-  [if test x"$withval" = xno; then
-     check_qt=no;
-     warn_qt_disabled="--without-qt specified.  The Qt GUI will be disabled."
-     OCTAVE_CONFIGURE_WARNING([warn_qt_disabled])
-   fi])
-
-if test $check_qt = yes; then
-
-  warn_qt_libraries=""
-  ## Check for Qt libraries
-  QT_MODULES="QtCore QtGui QtNetwork QtOpenGL"
-  PKG_CHECK_MODULES(QT, [$QT_MODULES],
-    [],
-    [check_qt=no
-     warn_qt_libraries="Qt libraries not found; disabling Qt GUI"])
-
-  if test -n "$warn_qt_libraries"; then
-    OCTAVE_CONFIGURE_WARNING([warn_qt_libraries])
-  fi
-
-  if test $check_qt = yes; then
-    ## Retrieve Qt compilation and linker flags
-    QT_CPPFLAGS="`$PKG_CONFIG --cflags-only-I $QT_MODULES`"
-    QT_LDFLAGS="`$PKG_CONFIG --libs-only-L $QT_MODULES`"
-    QT_LIBS="`$PKG_CONFIG --libs-only-l $QT_MODULES`"
-
-    case $host_os in
-      *darwin*)
-        ## Qt might be installed in framework
-        if test -z "$QT_LIBS"; then
-          QT_LDFLAGS="`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\n' | $GREP -e '-F' | uniq | tr '\n' ' '`"
-          QT_LIBS="`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\n' | $GREP -v -e '-F' | uniq | tr '\n' ' '`"
-          ## Enabling link_all_deps works around libtool's imperfect handling
-          ## of the -F flag
-          AM_CONDITIONAL([AMCOND_LINK_ALL_DEPS],
-                         [test $link_all_deps = yes || test -n "$QT_LDFLAGS"])
-        fi
-      ;;
-    esac
-
-    ## Check for Qt4
-    if ! `$PKG_CONFIG --atleast-version=4.0.0 QtCore`; then
-      check_qt=no
-      warn_qt_version="Qt >= 4.0.0 not found; disabling Qt GUI"
-      OCTAVE_CONFIGURE_WARNING([warn_qt_version])
-    fi
-  fi
-
-  if test $check_qt = yes; then
-    warn_qt_tools=""
-    AC_CHECK_TOOLS(MOC, [moc-qt4 moc])
-    AC_CHECK_TOOLS(UIC, [uic-qt4 uic])
-    AC_CHECK_TOOLS(RCC, [rcc-qt4 rcc])
-    AC_CHECK_TOOLS(LRELEASE, [lrelease-qt4 lrelease])
-
-    if test -n "$MOC" && test -n "$UIC" && test -n "$RCC" && test -n "$LRELEASE"; then
-      AC_DEFINE(HAVE_QT, 1,
-        [Define to 1 if Qt is available (libraries, developer header files, utility programs (moc, uic, rcc, and lrelease))])
-    else
-      warn_qt_tools="Qt utility programs moc, uic, rcc, and lrelease not found; disabling Qt GUI"
-      check_qt=no
-      OCTAVE_CONFIGURE_WARNING([warn_qt_tools])
-    fi
-  fi
-
-  if test $check_qt = yes; then
-    warn_qt_setlocale=""
-    AC_CHECK_FUNCS([setlocale], [],
-      [check_qt=no
-       warn_qt_setlocale="setlocale not found; disabling Qt GUI"])
-
-    if test -n "$warn_qt_setlocale"; then
-      OCTAVE_CONFIGURE_WARNING([warn_qt_setlocale])
-    fi
-  fi
-
-  if test $check_qt = yes; then
-    warn_qt_setvbuf=""
-    warn_qt_lib_fcns=""
-    case $host_os in
-      mingw* | msdosmsvc*)
-        AC_CHECK_FUNCS([setvbuf], [win32_terminal=yes],
-          [check_qt=no
-           warn_qt_setvbuf="setvbuf not found; disabling Qt GUI"])
-
-        if test -n "$warn_qt_setvbuf"; then
-          OCTAVE_CONFIGURE_WARNING([warn_qt_setvbuf])
-        fi
-      ;;
-      *)
-        AC_CHECK_HEADERS([pty.h libutil.h util.h])
-        AC_SEARCH_LIBS([openpty], [util],
-          [AC_DEFINE(HAVE_OPENPTY, [], [Define whether openpty exists])])
-        AC_CHECK_FUNCS([chmod chown ftruncate mmap munmap], [],
-          [check_qt=no
-           warn_qt_lib_fcns="At least one of chmod, chown, ftruncate, mmap, and munmap not found; disabling Qt GUI"])
-
-        if test -n "$warn_qt_lib_fcns"; then
-          OCTAVE_CONFIGURE_WARNING([warn_qt_lib_fcns])
-        fi
-      ;;
-    esac
-  fi
-
-  if test $check_qt = yes; then
-    OCTAVE_CHECK_FUNC_QABSTRACTITEMMODEL_BEGINRESETMODEL
-
-    if test $octave_cv_func_qabstractitemmodel_beginresetmodel = no; then
-      check_qt=no
-      warn_qt_abstract_item_model="QAbstractItemModel::beginResetModel not found; disabling Qt GUI"
-      OCTAVE_CONFIGURE_WARNING([warn_qt_abstract_item_model])
-    fi
-  fi
-
-  if test $check_qt = yes; then
-    ## We have what we need to build the Qt GUI.  The remaining
-    ## checks below are for optional features related to the Qt GUI.
-    build_qt_gui=yes
-  fi
-
-  if test $check_qt = yes; then
-    OCTAVE_CHECK_QFONT_MONOSPACE
-    OCTAVE_CHECK_QFONT_FORCE_INTEGER_METRICS
-    OCTAVE_CHECK_FUNC_QTABWIDGET_SETMOVABLE
-
-    if test -n "$OPENGL_LIBS"; then
-      OCTAVE_CHECK_QT_OPENGL_OK([build_qt_graphics=yes],
-        [warn_qt_opengl="Qt does not work with the OpenGL libs (GL and GLU); disabling OpenGL graphics with Qt GUI"])
-
-      if test -n "$warn_qt_opengl"; then
-        OCTAVE_CONFIGURE_WARNING([warn_qt_opengl])
-      fi
-
-      if test $build_qt_graphics = yes; then
-        AC_DEFINE(HAVE_QT_GRAPHICS, 1, [Define to 1 if Qt works with OpenGL libs (GL and GLU)])
-      fi
-    fi
-
-    ## Check for Qscintilla library which is used in the Qt GUI editor.
-    AC_CACHE_CHECK([whether Qscintilla library is installed],
-      [octave_cv_lib_qscintilla],
-      [save_CPPFLAGS="$CPPFLAGS"
-      save_LDFLAGS="$LDFLAGS"
-      save_LIBS="$LIBS"
-      CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
-      LDFLAGS="$QT_LDFLAGS $LDFLAGS"
-      LIBS="$QT_LIBS -lqscintilla2"
-      AC_LANG_PUSH(C++)
-      AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-        #include <Qsci/qscilexersql.h>
-        ]], [[
-        QsciLexerSQL sqlLexer(0);
-        ]])],
-        octave_cv_lib_qscintilla=yes,
-        octave_cv_lib_qscintilla=no)
-      CPPFLAGS="$save_CPPFLAGS"
-      LDFLAGS="$save_LDFLAGS"
-      LIBS="$save_LIBS"
-      AC_LANG_POP([C++])
-    ])
-
-    if test $octave_cv_lib_qscintilla = no; then
-      warn_qscintilla="Qscintilla library not found; disabling built-in Qt GUI editor"
-      OCTAVE_CONFIGURE_WARNING([warn_qscintilla])
-    else
-      ## Let's assume Qscintilla library is at the same location as
-      ## other regular Qt libraries.
-      QT_LIBS="$QT_LIBS -lqscintilla2"
-      OCTAVE_CHECK_VERSION_2_6_0
-      AC_DEFINE(HAVE_QSCINTILLA, 1,
-        [Define to 1 if the QScintilla library and header files are available])
-
-      save_CPPFLAGS="$CPPFLAGS"
-      CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
-      AC_LANG_PUSH(C++)
-      AC_CHECK_HEADERS([Qsci/qscilexeroctave.h Qsci/qscilexermatlab.h])
-      AC_LANG_POP(C++)
-      CPPFLAGS="$save_CPPFLAGS"
-
-      OCTAVE_CHECK_FUNC_SETPLACEHOLDERTEXT
-      OCTAVE_CHECK_FUNC_QSCI_FINDSELECTION
-      use_qscintilla=yes
-    fi
-  fi
-fi
-
-AC_SUBST(QT_CPPFLAGS)
-AC_SUBST(QT_LDFLAGS)
-AC_SUBST(QT_LIBS)
-
-AM_CONDITIONAL([AMCOND_BUILD_QT_GUI], [test $build_qt_gui = yes])
-AM_CONDITIONAL([AMCOND_BUILD_QT_GRAPHICS], [test $build_qt_graphics = yes])
-AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test $use_qscintilla = yes])
-AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes])
-
-## Check for FLTK (www.fltk.org) library
-
-check_fltk=yes
-build_fltk_graphics=no
-
-AC_ARG_WITH([fltk],
-  [AS_HELP_STRING([--without-fltk],
-    [don't use FLTK libraries, disable OpenGL graphics with FLTK widgets])],
-  [if test x"$withval" = xno; then
-     check_fltk=no
-     warn_fltk="--without-fltk specified.  FLTK widgets will be disabled."
-     OCTAVE_CONFIGURE_WARNING([warn_fltk])
-   fi])
-
-FLTK_CPPFLAGS=
-FLTK_LDFLAGS=
-FLTK_LIBS=
-
-if test $check_fltk = yes; then
-  AC_ARG_WITH([fltk-prefix],
-    [AS_HELP_STRING([--with-fltk-prefix=PFX],
-      [prefix where FLTK is installed (optional)])],
-    [fltk_prefix="$withval"],
-    [fltk_prefix=""])
-
-  AC_ARG_WITH([fltk-exec-prefix],
-    [AS_HELP_STRING([--with-fltk-exec-prefix=PFX],
-      [exec prefix where FLTK is installed (optional)])],
-    [fltk_exec_prefix="$withval"],
-    [fltk_exec_prefix=""])
-
-  if test "x$fltk_exec_prefix" != x; then
-    fltk_args="$fltk_args --exec-prefix=$fltk_exec_prefix"
-    if test "x${FLTK_CONFIG+set}" != xset ; then
-      FLTK_CONFIG="$fltk_exec_prefix/bin/fltk-config"
-    fi
-  fi
-
-  if test "x$fltk_prefix" != x; then
-    fltk_args="$fltk_args --prefix=$fltk_prefix"
-    if test x${FLTK_CONFIG+set} != xset ; then
-      FLTK_CONFIG="$fltk_prefix/bin/fltk-config"
-    fi
-  fi
-
-  AC_PATH_PROG([FLTK_CONFIG], [fltk-config], [no])
-
-  warn_fltk_config=""
-  warn_fltk_opengl=""
-
-  if test "$FLTK_CONFIG" = no; then
-    warn_fltk_config="FLTK config script not found.  Native graphics will be disabled."
-    OCTAVE_CONFIGURE_WARNING([warn_fltk_config])
-  else
-    ## Only include -I options in FLTK_CPPFLAGS
-    fltk_cflags=`$FLTK_CONFIG $fltkconf_args --use-gl --cflags`
-    for fltk_option in $fltk_cflags; do
-      case $fltk_option in
-        -I*)
-          FLTK_CPPFLAGS="$FLTK_CPPFLAGS $fltk_option"
-        ;;
-      esac
-    done
-    FLTK_LDFLAGS=`$FLTK_CONFIG $fltkconf_args --use-gl --ldflags`
-
-    case $host_os in
-      mingw*)
-        FLTK_LDFLAGS=`echo $FLTK_LDFLAGS | $SED -e 's/-mwindows//g'`
-      ;;
-    esac
-    AC_LANG_PUSH(C++)
-    AC_CACHE_CHECK([for OpenGL support in FLTK],
-      [octave_cv_fltk_opengl_support],
-      [save_CPPFLAGS="$CPPFLAGS"
-      CPPFLAGS="$CFLAGS $FLTK_CPPFLAGS"
-      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-        #include <FL/gl.h>
-        ]], [[
-        int nothing = 0;
-        ]])],
-        octave_cv_fltk_opengl_support=yes,
-        octave_cv_fltk_opengl_support=no)
-      CPPFLAGS="$save_CPPFLAGS"
-      ])
-    if test $octave_cv_fltk_opengl_support = no; then
-      warn_fltk_opengl="FLTK does not have OpenGL support.  OpenGL graphics with FLTK widgets will be disabled."
-    else
-      build_fltk_graphics=yes
-      AC_DEFINE(HAVE_FLTK, 1, [Define to 1 if FLTK is available.])
-    fi
-    AC_LANG_POP(C++)
-
-    if test -n "$warn_fltk_opengl"; then
-      OCTAVE_CONFIGURE_WARNING([warn_fltk_opengl])
-    fi
-  fi
-fi
-
-AC_SUBST(FLTK_CPPFLAGS)
-AC_SUBST(FLTK_LDFLAGS)
-AC_SUBST(FLTK_LIBS)
-
-if test $build_qt_graphics = no && test $build_fltk_graphics = no; then
-  opengl_graphics=no
-else
-  opengl_graphics=yes
-fi
-
 ### Start determination of shared vs. static libraries
 
 ## Use -static if compiling on Alpha OSF/1 1.3 systems.
@@ -1695,285 +528,6 @@
 fi
 AC_SUBST(XTRA_CRUFT_SH_LDFLAGS)
 
-### Check for BLAS and LAPACK libraries:
-
-## Need to adjust FFLAGS to include correct integer size.
-save_FFLAGS="$FFLAGS"
-FFLAGS="$FFLAGS $F77_INTEGER_8_FLAG"
-
-AX_BLAS_WITH_F77_FUNC([:], [:],
-  [ax_blas_ok=yes
-  AC_MSG_CHECKING([BLAS can be called from Fortran])
-  AC_MSG_RESULT([yes assumed for cross compilation])])
-AX_LAPACK([:], [:])
-
-## Restore FFLAGS.
-FFLAGS="$save_FFLAGS"
-
-## If necessary, try again with -ff2c in FFLAGS
-if test $ax_blas_ok = no; then
-  save_FFLAGS="$FFLAGS"
-  FFLAGS="-ff2c $FFLAGS $F77_INTEGER_8_FLAG"
-
-  AX_BLAS_WITH_F77_FUNC([:], [:])
-  AX_LAPACK([:], [:])
-
-  ## Restore FFLAGS, with -ff2c if that was helpful
-
-  if test $ax_blas_ok = yes; then
-    FFLAGS="-ff2c $save_FFLAGS"
-  else
-    FFLAGS="$save_FFLAGS"
-  fi
-fi
-
-## On OSX, try again with a wrapper library (without -ff2c!)
-if test $ax_blas_ok = no; then
-  case $host_os in
-    darwin*)
-      ## test if wrapper functions help
-      octave_blaswrap_save_CFLAGS="$CFLAGS"
-      CFLAGS="$CFLAGS -DUSE_BLASWRAP"
-      AC_LANG_PUSH(C)
-      AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
-          #include "liboctave/cruft/misc/blaswrap.c"
-        ]])],
-        [mv conftest.$ac_objext blaswrap.$ac_objext
-         octave_blaswrap_save_BLAS_LIBS="$BLAS_LIBS"
-         BLAS_LIBS="blaswrap.$ac_objext -framework vecLib"
-
-         save_FFLAGS="$FFLAGS"
-         FFLAGS="$FFLAGS $F77_INTEGER_8_FLAG"
-
-         AX_BLAS_WITH_F77_FUNC([:], [:])
-         AX_LAPACK([:], [:])
-
-         ## Restore FFLAGS.
-         FFLAGS="$save_FFLAGS"
-
-         ## remove temp file
-         rm -f blaswrap.$ac_objext],
-        [AC_MSG_FAILURE([cannot compile liboctave/cruft/misc/blaswrap.c])])
-      AC_LANG_POP(C)
-      CFLAGS="$octave_blaswrap_save_CFLAGS"
-
-      if test $ax_blas_ok = no; then
-        BLAS_LIBS="$octave_blaswrap_save_BLAS_LIBS"
-      else
-        ## wrapper in cruft, remove from BLAS_LIBS
-        BLAS_LIBS=`echo $BLAS_LIBS | $SED -e 's/blaswrap.[[^ ]]* //g'`
-        AC_DEFINE(USE_BLASWRAP, 1,
-          [Define to 1 if BLAS functions need to be wrapped (potentially needed for 64-bit OSX only).])
-      fi
-    ;;
-  esac
-fi
-
-if test $ax_blas_ok = no; then
-  if test $ENABLE_64 = yes && test $ax_blas_integer_size_ok = no; then
-    ## Attempt to be more informative.
-    AC_MSG_ERROR([BLAS doesn't seem to support 64-bit integers.  This is incompatible with --enable-64.])
-  else
-    AC_MSG_ERROR([A BLAS library was detected but found incompatible with your Fortran 77 compiler settings.])
-  fi
-fi
-
-if test $ax_blas_ok = no || test $ax_lapack_ok = no; then
-  AC_MSG_ERROR([BLAS and LAPACK libraries are required])
-fi
-
-### Check for the qrupdate library
-
-## No need to adjust FFLAGS because only link is attempted.
-## Must supply proper LIBS, however.
-save_LIBS="$LIBS"
-LIBS="$LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS"
-OCTAVE_CHECK_LIB(qrupdate, qrupdate,
-  [qrupdate not found.  The QR & Cholesky updating functions will be slow.],
-  [],
-  [sqr1up],
-  [Fortran 77], [don't use qrupdate, disable QR & Cholesky updating functions])
-
-## Additional check to see if qrupdate lib found supports LU updates
-if test -z "$warn_qrupdate"; then
-  AC_CACHE_CHECK([for slup1up in $QRUPDATE_LIBS],
-    [octave_cv_func_slup1up],
-    [LIBS="$LIBS $QRUPDATE_LIBS"
-    AC_LANG_PUSH([Fortran 77])
-    AC_LINK_IFELSE([AC_LANG_CALL([], [slup1up])],
-      octave_cv_func_slup1up=yes, octave_cv_func_slup1up=no)
-    AC_LANG_POP([Fortran 77])
-  ])
-  if test $octave_cv_func_slup1up = yes; then
-    AC_DEFINE(HAVE_QRUPDATE_LUU, 1, [Define to 1 if qrupdate supports LU updates.])
-  fi
-fi
-LIBS="$save_LIBS"
-
-if test $ENABLE_64 = yes; then
-  CHOLMOD_TAG="_l_"
-  CXSPARSE_TAG="_dl_"
-  UMFPACK_TAG="_zl_"
-else
-  CHOLMOD_TAG="_"
-  CXSPARSE_TAG="_di_"
-  UMFPACK_TAG="_zi_"
-fi
-
-### Check for AMD library
-
-OCTAVE_CHECK_LIB(amd, AMD,
-  [AMD library not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/amd.h ufsparse/amd.h amd/amd.h amd.h],
-  [amd_postorder],
-  [], [don't use AMD library, disable some sparse matrix functionality])
-
-### Check for CAMD library
-
-OCTAVE_CHECK_LIB(camd, CAMD,
-  [CAMD library not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/camd.h ufsparse/camd.h camd/camd.h camd.h],
-  [camd_postorder],
-  [], [don't use CAMD library, disable some sparse matrix functionality])
-
-### Check for COLAMD library
-
-OCTAVE_CHECK_LIB(colamd, COLAMD,
-  [COLAMD library not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/colamd.h ufsparse/colamd.h colamd/colamd.h colamd.h],
-  [colamd],
-  [], [don't use COLAMD library, disable some sparse matrix functionality])
-
-### Check for CCOLAMD library
-
-OCTAVE_CHECK_LIB(ccolamd, CCOLAMD,
-  [CCOLAMD library not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/ccolamd.h ufsparse/ccolamd.h ccolamd/ccolamd.h ccolamd.h],
-  [ccolamd],
-  [], [don't use CCOLAMD library, disable some sparse matrix functionality])
-
-### Check for CHOLMOD library.
-### If your cholmod library requires cblas, then you will need to
-### configure with --with-cholmod="-lcholmod -lcblas".
-
-save_LIBS="$LIBS"
-LIBS="$COLAMD_LDFLAGS $COLAMD_LIBS $AMD_LDFLAGS $AMD_LIBS $LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS"
-OCTAVE_CHECK_LIB(cholmod, CHOLMOD,
-  [CHOLMOD library not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/cholmod.h ufsparse/cholmod.h cholmod/cholmod.h cholmod.h],
-  [cholmod${CHOLMOD_TAG}start],
-  [], [don't use CHOLMOD library, disable some sparse matrix functionality])
-LIBS="$save_LIBS"
-
-### Check for CXSparse library
-
-OCTAVE_CHECK_LIB(cxsparse, CXSparse,
-  [CXSparse library not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/cs.h ufsparse/cs.h cxsparse/cs.h cs.h],
-  [cs${CXSPARSE_TAG}sqr],
-  [C++], [don't use CXSparse library, disable some sparse matrix functionality])
-
-## Additional check for CXSparse version >= 2.2
-if test $octave_cv_lib_cxsparse = yes; then
-  OCTAVE_CHECK_CXSPARSE_VERSION_OK
-  if test $octave_cv_cxsparse_version_ok = no; then
-    AC_MSG_ERROR([CXSparse library is too old (< version 2.2).  Upgrade CXSparse (SuiteSparse) or configure Octave with --disable-cxsparse"])
-  fi
-fi
-
-### Check for UMFPACK library.
-
-save_LIBS="$LIBS"
-save_CPPFLAGS="$CPPFLAGS"
-LIBS="$AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS"
-CPPFLAGS="$AMD_CPPFLAGS $CPPFLAGS"
-OCTAVE_CHECK_LIB([umfpack], UMFPACK,
-  [UMFPACK not found.  This will result in some lack of functionality for sparse matrices.],
-  [suitesparse/umfpack.h ufsparse/umfpack.h umfpack/umfpack.h umfpack.h],
-  [umfpack${UMFPACK_TAG}get_determinant],
-  [], [don't use UMFPACK, disable some sparse matrix functionality])
-CPPFLAGS="$save_CPPFLAGS"
-LIBS="$save_LIBS"
-
-if test -z "$UMFPACK_LIBS"; then
-  ## Invalidate the cache and try again with -lcblas.
-  $as_unset ac_cv_lib_umfpack_umfpack${UMFPACK_TAG}get_determinant
-  $as_unset octave_cv_lib_umfpack
-  save_LIBS="$LIBS"
-  LIBS="-lcblas $AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS"
-  OCTAVE_CHECK_LIB([umfpack], UMFPACK,
-    [UMFPACK not found.  This will result in some lack of functionality for sparse matrices.],
-    [suitesparse/umfpack.h ufsparse/umfpack.h umfpack/umfpack.h umfpack.h],
-    [umfpack${UMFPACK_TAG}get_determinant],
-    [], [don't use UMFPACK, disable some sparse matrix functionality])
-  if test -n "$UMFPACK_LIBS"; then
-    UMFPACK_LIBS="$UMFPACK_LIBS -lcblas"
-  fi
-  LIBS="$save_LIBS"
-fi
-
-## Test features of the installed UMFPACK library
-
-if test -n "$UMFPACK_LIBS"; then
-  ## SuiteSparse >= 4.0 needs additional link library for SuiteSparse_time
-  save_CPPFLAGS="$CPPFLAGS"
-  save_LIBS="$LIBS";
-  CPPFLAGS="$UMFPACK_CPPFLAGS $AMD_CPPFLAGS $CPPFLAGS"
-  LIBS="$UMFPACK_LIBS $AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS"
-  xtra_libs=
-  OCTAVE_UMFPACK_NEED_SUITESPARSE_TIME
-  if test $STATIC_LIBS = yes || test $octave_cv_umfpack_need_suitesparse_time = yes; then
-    AC_CHECK_LIB([rt], [clock_gettime], [xtra_libs="-lrt"], [xtra_libs=])
-    ## FIXME: This library list is only accurate for Linux, Mac OS X.
-    ##        Possibly need other library names for MinGW, Cygwin.
-    AC_SEARCH_LIBS([SuiteSparse_time],
-                   [suitesparseconfig SuiteSparse],
-                   [], [], [$xtra_libs])
-    case $ac_cv_search_SuiteSparse_time in
-      -l*)
-        UMFPACK_LIBS="$UMFPACK_LIBS $ac_cv_search_SuiteSparse_time"
-      ;;
-      no)
-        UMFPACK_LIBS=
-        AC_MSG_WARN([UMFPACK library found but is missing SuiteSparse_time functionality.])
-        AC_MSG_WARN([UMFPACK library will be disabled.])
-      ;;
-    esac
-  fi
-  LIBS="$save_LIBS"
-  CPPFLAGS="$save_CPPFLAGS"
-
-  ## Check for UMFPACK separately split complex matrix and RHS.
-  if test -n "$UMFPACK_LIBS"; then
-    save_CPPFLAGS="$CPPFLAGS"
-    save_LIBS="$LIBS";
-    CPPFLAGS="$UMFPACK_CPPFLAGS $AMD_CPPFLAGS $CPPFLAGS"
-    LIBS="$UMFPACK_LIBS $CHOLMOD_LDFLAGS $CHOLMOD_LIBS $AMD_LDFLAGS $AMD_LIBS $COLAMD_LDFLAGS $COLAMD_LIBS $LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS $xtra_libs"
-    OCTAVE_UMFPACK_SEPARATE_SPLIT
-    LIBS="$save_LIBS"
-    CPPFLAGS="$save_CPPFLAGS"
-  fi
-fi
-
-### Check for ARPACK library.
-
-save_LIBS="$LIBS"
-LIBS="$LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS"
-OCTAVE_CHECK_LIB([arpack], ARPACK,
-  [ARPACK not found.  The eigs function will be disabled.],
-  [],
-  [dseupd],
-  [Fortran 77], [don't use the ARPACK library, disable eigs function],
-  [warn_arpack=
-   OCTAVE_CHECK_LIB_ARPACK_OK(
-     [AC_DEFINE(HAVE_ARPACK, 1, [Define to 1 if ARPACK is available.])],
-     [warn_arpack="ARPACK library found, but does not seem to work properly; disabling eigs function"])])
-LIBS="$save_LIBS"
-
-### Check for readline library.
-
-OCTAVE_ENABLE_READLINE
-
 ### Enable dynamic linking.  --enable-shared implies this, so
 ### --enable-dl is only need if you are only building static libraries
 ### and want to try dynamic linking too (works on some systems, for
@@ -2346,6 +900,1263 @@
 AC_SUBST(MKOCTFILE_LD_CXX)
 AC_SUBST(MKOCTFILE_RANLIB)
 
+### Check for pthread library
+
+AX_PTHREAD
+## Include pthread libs and flags early in case other tests need them.
+## They seem to be required for the OpenGL tests on Debian systems.
+LIBS="$PTHREAD_LIBS $LIBS"
+XTRA_CFLAGS="$XTRA_CFLAGS $PTHREAD_CFLAGS"
+XTRA_CXXFLAGS="$XTRA_CXXFLAGS $PTHREAD_CFLAGS"
+## Set these for any other tests that may require them.  They will be
+## reset before output files are generated.
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
+
+### Test whether the compiler supports OpenMP.  This is enabled by default
+### now to allow the option of using OpenMP in loadable modules.
+
+ENABLE_OPENMP=no
+check_for_openmp=yes
+AC_ARG_ENABLE([openmp],
+  [AS_HELP_STRING([--disable-openmp],
+    [disable OpenMP SMP multi-threading])],
+  [if test "$enableval" = no; then check_for_openmp=no; fi], [])
+if test $check_for_openmp = yes; then
+  AC_LANG_PUSH(C)
+  AX_OPENMP([XTRA_CFLAGS="$XTRA_CFLAGS $OPENMP_CFLAGS"; ENABLE_OPENMP=yes], [])
+  AC_LANG_POP(C)
+  AC_LANG_PUSH(C++)
+  AX_OPENMP([XTRA_CXXFLAGS="$XTRA_CXXFLAGS $OPENMP_CXXFLAGS"; ENABLE_OPENMP=yes], [])
+  AC_LANG_POP(C++)
+fi
+
+## Set these for any other tests that may require them.  They will be
+## reset before output files are generated.
+CFLAGS="$CFLAGS $OPENMP_CFLAGS"
+CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS"
+
+dnl Define here since it is skipped if the first argument to
+dnl AX_OPENMP is not empty.
+if test $ENABLE_OPENMP = yes; then
+  AC_CHECK_HEADERS([omp.h])
+  AC_CHECK_FUNCS([omp_get_num_threads])
+  AC_DEFINE(OCTAVE_ENABLE_OPENMP, 1, [Define if OpenMP is enabled])
+fi
+
+### When compiling math for x87, problems may arise in some code comparing
+### floating-point intermediate results.  The root cause is the extra precision
+### (~80 bits) of x87 co-processor registers versus the IEEE standard 64 bits.
+### Generally, storing the result in a local volatile variable forces a
+### truncation back to 64 bits, but it also degrades performance.
+### However, this performance degradation is very minimal, if indeed measurable.
+### Therefore, it has been enabled for all platforms and compilers.
+### Reported bugs indicate that --enable-float-truncate is required for MinGW
+### and Cygwin platforms and for GCC compilers >= 5.0.  It should not be
+### necessary for non-x87 targets or when using modern SSE math.
+ENABLE_FLOAT_TRUNCATE=yes
+AC_ARG_ENABLE([float-truncate],
+  [AS_HELP_STRING([--disable-float-truncate],
+    [truncate intermediate FP results])],
+  [if test "$enableval" = no; then ENABLE_FLOAT_TRUNCATE=no; fi], [])
+if test $ENABLE_FLOAT_TRUNCATE = yes; then
+  AC_DEFINE(OCTAVE_ENABLE_FLOAT_TRUNCATE, 1,
+    [Define to 1 if you need to truncate intermediate FP results.])
+fi
+
+### Determine extra CFLAGS that may be necessary for Octave.
+
+## On Intel systems with gcc, we may need to compile with -mieee-fp
+## to get full support for IEEE floating point.
+##
+## On Alpha/OSF systems, we need -mieee.
+
+ieee_fp_flag=
+case $canonical_host_type in
+  i[[3456789]]86-*-*)
+    if test "$GCC" = yes; then
+      OCTAVE_CC_FLAG([-mieee-fp], [
+        ieee_fp_flag=-mieee-fp
+        XTRA_CFLAGS="$XTRA_CFLAGS -mieee-fp"
+        AC_MSG_NOTICE([adding -mieee-fp to XTRA_CFLAGS])])
+    fi
+    if test "$GXX" = yes; then
+      OCTAVE_CXX_FLAG([-mieee-fp], [
+        ieee_fp_flag=-mieee-fp
+        XTRA_CXXFLAGS="$XTRA_CXXFLAGS -mieee-fp"
+        AC_MSG_NOTICE([adding -mieee-fp to XTRA_CXXFLAGS])])
+    fi
+  ;;
+  alpha*-*-*)
+    if test "$GCC" = yes; then
+      OCTAVE_CC_FLAG([-mieee], [
+        ieee_fp_flag=-mieee
+        XTRA_CFLAGS="$XTRA_CFLAGS -mieee"
+        AC_MSG_NOTICE([adding -mieee to XTRA_CFLAGS])])
+    else
+      OCTAVE_CC_FLAG([-ieee], [
+        ieee_fp_flag=-ieee
+        XTRA_CFLAGS="$XTRA_CFLAGS -ieee"
+        AC_MSG_NOTICE([adding -ieee to XTRA_CFLAGS])])
+    fi
+    if test "$GXX" = yes; then
+      OCTAVE_CXX_FLAG([-mieee], [
+        ieee_fp_flag=-mieee
+        XTRA_CXXFLAGS="$XTRA_CXXFLAGS -mieee"
+        AC_MSG_NOTICE([adding -mieee to XTRA_CXXFLAGS])])
+    else
+      OCTAVE_CXX_FLAG([-ieee], [
+        ieee_fp_flag=-ieee
+        XTRA_CXXFLAGS="$XTRA_CXXFLAGS -ieee"
+        AC_MSG_NOTICE([adding -ieee to XTRA_CXXFLAGS])])
+    fi
+  ;;
+  *ibm-aix4*)
+    OCTAVE_CC_FLAG([-mminimal-toc], [
+      XTRA_CFLAGS="$XTRA_CFLAGS -mminimal-toc"])
+
+    OCTAVE_CXX_FLAG([-mminimal-toc], [
+      XTRA_CXXFLAGS="$XTRA_CXXFLAGS -mminimal-toc"])
+  ;;
+esac
+
+AC_SUBST(XTRA_CFLAGS)
+AC_SUBST(XTRA_CXXFLAGS)
+
+### Defaults for cross compiling.  BUILD_CC and BUILD_CXX are
+### the compilers that we use for building tools on the build system.
+### For now, we assume that the only cross compiling we can do is
+### with gcc on a Unixy system, but the dedicated hacker can override these.
+
+if test "$cross_compiling" = yes; then
+  BUILD_CC="gcc"
+  BUILD_CFLAGS="-O2 -g"
+  BUILD_CXX="g++"
+  BUILD_CXXFLAGS="-O2 -g"
+  BUILD_LDFLAGS=""
+  BUILD_EXEEXT=""
+else
+  BUILD_CC="${CC}"
+  BUILD_CFLAGS="${CFLAGS}"
+  BUILD_CXX="${CXX}"
+  BUILD_CXXFLAGS="${CXXFLAGS}"
+  BUILD_LDFLAGS="${LDFLAGS}"
+  BUILD_EXEEXT="${EXEEXT}"
+fi
+
+AC_ARG_VAR([BUILD_CC],
+  [build system C compiler (used if cross compiling)])
+AC_ARG_VAR([BUILD_CFLAGS],
+  [build system C compiler flags (used if cross compiling)])
+AC_ARG_VAR([BUILD_CXX],
+  [build system C++ compiler (used if cross compiling)])
+AC_ARG_VAR([BUILD_CXXFLAGS],
+  [build system C++ compiler flags (used if cross compiling)])
+AC_ARG_VAR([BUILD_LDFLAGS],
+  [build system C++ compiler link flags (used if cross compiling)])
+AC_ARG_VAR([BUILD_EXEEXT],
+  [build system executable extension (used if cross compiling)])
+
+
+### Look for math library.  If found, this will add -lm to LIBS.
+
+dnl Keep this check before the check for the Fortran compiler,
+dnl in case -lm is needed to compile Fortran programs.
+AC_CHECK_LIB(m, sin)
+
+### Determine the Fortran compiler and how to invoke it
+
+## Prefer gfortran, but the user's F77 environment variable will override.
+AC_PROG_F77([gfortran])
+if test -z "$F77"; then
+  ## No gfortran found, search for any other installed compiler.
+  AC_PROG_F77
+fi
+if test "$F77" = g77; then
+  AC_MSG_ERROR([g77 is not a supported Fortran compiler.  Select another compiler by setting the environment variable F77 and re-running configure.])
+fi
+
+AC_MSG_CHECKING([whether a usable Fortran compiler was found])
+if test -n "$F77"; then
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+  AC_MSG_ERROR([A Fortran compiler is required])
+fi
+
+AC_F77_LIBRARY_LDFLAGS
+AC_F77_DUMMY_MAIN
+AC_F77_WRAPPERS
+
+F77_TOLOWER=yes
+F77_APPEND_UNDERSCORE=yes
+F77_APPEND_EXTRA_UNDERSCORE=yes
+
+case $ac_cv_f77_mangling in
+  "upper case") F77_TOLOWER=no ;;
+esac
+case $ac_cv_f77_mangling in
+  "no underscore") F77_APPEND_UNDERSCORE=no ;;
+esac
+case $ac_cv_f77_mangling in
+  "no extra underscore") F77_APPEND_EXTRA_UNDERSCORE=no ;;
+esac
+
+case $canonical_host_type in
+  i[[3456789]]86-*-*)
+    if test $ac_cv_f77_compiler_gnu = yes; then
+      OCTAVE_F77_FLAG([-mieee-fp])
+    fi
+  ;;
+  alpha*-*-*)
+    if test $ac_cv_f77_compiler_gnu = yes; then
+      OCTAVE_F77_FLAG([-mieee])
+    else
+      OCTAVE_F77_FLAG([-ieee])
+      OCTAVE_F77_FLAG([-fpe1])
+    fi
+  ;;
+  powerpc-apple-machten*)
+    FFLAGS=
+  ;;
+esac
+
+if test $ac_cv_f77_compiler_gnu = yes; then
+  FORTRAN_CALLING_CONVENTION=gfortran
+else
+  FORTRAN_CALLING_CONVENTION=unknown
+fi
+AC_ARG_ENABLE([fortran-calling-convention],
+  [AS_HELP_STRING([--enable-fortran-calling-convention=OPTION],
+    [Select C++ to Fortran calling convention.  "gfortran" should be detected automatically.  Other options are "cray", "visual-fortran", or "f2c".])],
+  [FORTRAN_CALLING_CONVENTION="$enableval"], [])
+
+case "$FORTRAN_CALLING_CONVENTION" in
+  gfortran)
+    AC_DEFINE(F77_USES_GFORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the gfortran calling convention.])
+  ;;
+  cray)
+    AC_DEFINE(F77_USES_CRAY_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Cray Fortran calling convention.])
+  ;;
+  visual-fortran)
+    AC_DEFINE(F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Visual Fortran calling convention.])
+  ;;
+  f2c)
+    AC_DEFINE(F77_USES_F2C_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the f2c calling convention.])
+  ;;
+  *)
+    AC_MSG_ERROR([to build Octave, the C++ to Fortran calling convention must be known.])
+  ;;
+esac
+
+if test -n "$FFLAGS"; then
+  AC_MSG_NOTICE([defining FFLAGS to be $FFLAGS])
+fi
+
+AC_SUBST(F77_TOLOWER)
+AC_SUBST(F77_APPEND_UNDERSCORE)
+AC_SUBST(F77_APPEND_EXTRA_UNDERSCORE)
+
+if test -z "$F77"; then
+  AC_MSG_ERROR([to build Octave, you must have a compatible Fortran compiler or wrapper script for f2c that functions as a Fortran compiler installed and in your path.  See the file INSTALL for more information.])
+fi
+
+OCTAVE_CHECK_FUNC_FORTRAN_ISNAN
+F77_ISNAN_MACRO=
+if test $octave_cv_func_fortran_isnan = no; then
+  AC_MSG_NOTICE([substituting ISNAN(X) with X.NE.X in Fortran sources])
+  F77_ISNAN_MACRO="s|ISNAN(\(@<:@^)@:>@*\))|(\1.NE.\1)|"
+fi
+AC_SUBST(F77_ISNAN_MACRO)
+
+OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER
+if test $octave_cv_sizeof_fortran_integer = no; then
+  if test $ENABLE_64 = yes; then
+    case $F77 in
+      *gfortran*)
+        case $F77_INTEGER_8_FLAG in
+          *-fdefault-integer-8*)
+          ;;
+          *)
+            case $FFLAGS in
+              *-fdefault-integer-8*)
+                AC_MSG_NOTICE([setting -fdefault-integer-8 in F77_INTEGER_8_FLAG instead of FFLAGS])
+                FFLAGS=`echo $FFLAGS | $SED 's/-fdefault-integer-8//g'`
+                F77_INTEGER_8_FLAG="-fdefault-integer-8"
+              ;;
+              *)
+                AC_MSG_NOTICE([adding -fdefault-integer-8 to F77_INTEGER_8_FLAG])
+                F77_INTEGER_8_FLAG="-fdefault-integer-8"
+                ## Invalidate the cache and try again.
+                $as_unset octave_cv_sizeof_fortran_integer
+              ;;
+            esac
+          ;;
+        esac
+      ;;
+    esac
+    if test -z "$octave_cv_sizeof_fortran_integer"; then
+      OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER
+    fi
+    if test $octave_cv_sizeof_fortran_integer = no; then
+      AC_MSG_ERROR([to build Octave with 64-bit indexing support your Fortran compiler must have an option for setting the default integer size to 8 bytes.  See the file INSTALL for more information.])
+    fi
+  else
+    AC_MSG_ERROR([your Fortran compiler must have an option to make integers the same size as octave_idx_type ($OCTAVE_IDX_TYPE).  See the file INSTALL for more information.])
+  fi
+fi
+AC_SUBST(F77_INTEGER_8_FLAG)
+
+OCTAVE_F77_FLAG([-ffloat-store], [
+  AC_MSG_RESULT([setting F77_FLOAT_STORE_FLAG to -ffloat-store])
+  F77_FLOAT_STORE_FLAG=-ffloat-store
+  AC_SUBST(F77_FLOAT_STORE_FLAG)
+])
+
+### Check for the Qhull library
+
+OCTAVE_CHECK_LIB(qhull, QHull,
+  [Qhull library not found.  This will result in loss of functionality of some geometry functions.],
+  [libqhull/libqhull.h qhull/libqhull.h libqhull.h qhull/qhull.h qhull.h],
+  [qh_qhull], [], [],
+  [warn_qhull=
+  OCTAVE_CHECK_QHULL_VERSION
+  OCTAVE_CHECK_LIB_QHULL_OK(
+    [AC_DEFINE(HAVE_QHULL, 1, [Define to 1 if Qhull is available.])],
+    [warn_qhull="Qhull library found, but does not seem to work properly.  This will result in loss of functionality of some geometry functions.  Please try recompiling the library with -fno-strict-aliasing."])])
+
+### Check for PCRE regex library.
+
+PCRE_LIBS=
+
+pcre_fail_msg="to build Octave, you must have the PCRE library and header files installed"
+
+AC_CHECK_HEADERS([pcre.h pcre/pcre.h])
+
+AC_CACHE_CHECK([whether pcre.h defines the macros we need],
+  [ac_cv_pcre_h_macros_present],
+  [AC_EGREP_CPP([PCRE_HAS_MACROS_WE_NEED], [
+    #if defined (HAVE_PCRE_H)
+    # include <pcre.h>
+    #elif defined (HAVE_PCRE_PCRE_H)
+    # include <pcre/pcre.h>
+    #error "NO PCRE HEADER"
+    #endif
+    #if defined (PCRE_INFO_NAMECOUNT) \
+      && defined (PCRE_INFO_NAMEENTRYSIZE) \
+      && defined (PCRE_INFO_NAMETABLE)
+      PCRE_HAS_MACROS_WE_NEED
+    #endif],
+    ac_cv_pcre_h_macros_present=yes, ac_cv_pcre_h_macros_present=no)])
+
+if test $ac_cv_pcre_h_macros_present = yes; then
+  ## check for pcre-config, and if so, get build variables
+  AC_CHECK_PROG(HAVE_PCRE_CONFIG, pcre-config, [yes], [no])
+  if test $HAVE_PCRE_CONFIG = yes; then
+    PCRE_CPPFLAGS=`pcre-config --cflags`
+    PCRE_LIBS=`pcre-config --libs`
+  else
+    PCRE_LIBS="-lpcre"
+  fi
+  save_LIBS="$LIBS"
+  LIBS="$PCRE_LIBS $LIBS"
+  AC_CHECK_FUNCS([pcre_compile],
+    [AC_SUBST(PCRE_CPPFLAGS)
+     AC_SUBST(PCRE_LIBS)],
+    [AC_MSG_ERROR([$pcre_fail_msg])])
+  LIBS="$save_LIBS"
+else
+  AC_MSG_ERROR([$pcre_fail_msg])
+fi
+
+### Check for ZLIB library.
+
+OCTAVE_CHECK_LIB(z, ZLIB,
+  [ZLIB library not found.  Octave will not be able to save or load compressed data files or HDF5 files.],
+  [zlib.h], [gzclearerr])
+
+### Also define HAVE_ZLIB if libz is found.
+if test -z "$warn_z"; then
+  AC_DEFINE(HAVE_ZLIB, 1, [Define to 1 if ZLIB is available.])
+fi
+
+
+### Check for BZIP2 library.
+
+OCTAVE_CHECK_LIB(bz2, BZIP2,
+  [BZIP2 library not found.  Octave will not be able to compress or decompress bzip2 files.],
+  [bzlib.h], [BZ2_bzCompressInit])
+
+
+### Check for the LLVM library
+
+ENABLE_JIT=no
+AC_ARG_ENABLE([jit],
+  [AS_HELP_STRING([--enable-jit],
+    [(EXPERIMENTAL) enable JIT compiler])],
+  [if test "$enableval" = yes; then ENABLE_JIT=yes; fi], [])
+
+LLVM_CXXFLAGS=
+LLVM_CPPFLAGS=
+LLVM_LDFLAGS=
+LLVM_LIBS=
+
+if test $ENABLE_JIT = yes; then
+
+  ## Find llvm-config program from environment variable or by searching
+  AC_ARG_VAR([LLVM_CONFIG], [path to llvm-config utility])
+  AC_CHECK_PROG([LLVM_CONFIG], llvm-config, llvm-config, [])
+
+  if test -z "$LLVM_CONFIG"; then
+    warn_llvm="llvm-config utility not found.  JIT compiler is disabled."
+  else
+    dnl Preset warning message in case compile fails
+    warn_llvm="LLVM was not found or is to old.  JIT compiler is disabled."
+
+    save_CPPFLAGS="$CPPFLAGS"
+    save_CXXFLAGS="$CXXFLAGS"
+    save_LDFLAGS="$LDFLAGS"
+
+    ## Use -isystem if available because we don't want to see warnings in LLVM
+    LLVM_INCLUDE_FLAG=-I
+    OCTAVE_CC_FLAG([-isystem .], [
+      LLVM_INCLUDE_FLAG=-isystem
+      AC_MSG_NOTICE([using -isystem for LLVM headers])])
+
+    dnl Use -isystem so we don't get warnings from llvm headers
+    LLVM_CPPFLAGS="$LLVM_INCLUDE_FLAG `$LLVM_CONFIG --includedir`"
+    LLVM_CXXFLAGS=
+    LLVM_LDFLAGS="-L`$LLVM_CONFIG --libdir`"
+
+
+    LDFLAGS="$LDFLAGS $LLVM_LDFLAGS"
+    LLVM_SO=LLVM-`$LLVM_CONFIG --version`
+    AC_CHECK_LIB([$LLVM_SO], [LLVMBuildAdd], [LLVM_LIBS="-l$LLVM_SO"], [LLVM_LIBS=`$LLVM_CONFIG --libs`])
+
+    dnl
+    dnl Define some extra flags that LLVM requires in order to include headers.
+    dnl Ideally we should get these from llvm-config, but llvm-config isn't
+    dnl very helpful.
+    dnl
+    CPPFLAGS="-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS $LLVM_CPPFLAGS $CPPFLAGS"
+    CXXFLAGS="$LLVM_CXXFLAGS $CXXFLAGS"
+    AC_LANG_PUSH(C++)
+    AC_CHECK_HEADER([llvm/Support/TargetSelect.h], [warn_llvm=""])
+
+    have_function_h=no
+    AC_CHECK_HEADERS([llvm/IR/Function.h llvm/Function.h],
+                     [have_function_h=yes; break])
+    if test $have_function_h = no; then
+      warn_llvm="Missing LLVM file Function.h.  JIT compiler is disabled."
+    fi
+    have_irbuilder_h=no
+    AC_CHECK_HEADERS([llvm/Support/IRBuilder.h llvm/IR/IRBuilder.h \
+                      llvm/IRBuilder.h], [have_irbuilder_h=yes; break])
+    if test $have_irbuilder_h = no; then
+      warn_llvm="Missing LLVM file IRBuilder.h.  JIT compiler is disabled."
+    fi
+    have_llvm_data_h=no
+    AC_CHECK_HEADERS([llvm/Target/TargetData.h llvm/IR/DataLayout.h \
+                      llvm/DataLayout.h], [have_llvm_data_h=yes; break])
+    if test $have_llvm_data_h = no; then
+      warn_llvm="Missing LLVM file TargetData.h.  JIT compiler is disabled."
+    fi
+
+    AC_CHECK_HEADERS([llvm/IR/Verifier.h])
+
+    OCTAVE_LLVM_FUNCTION_ADDATTRIBUTE_API
+    OCTAVE_LLVM_FUNCTION_ADDFNATTR_API
+    OCTAVE_LLVM_CALLINST_ADDATTRIBUTE_API
+    OCTAVE_LLVM_RAW_FD_OSTREAM_API
+    OCTAVE_LLVM_LEGACY_PASSMANAGER_API
+    AC_LANG_POP(C++)
+    CPPFLAGS="$save_CPPFLAGS"
+    CXXFLAGS="$save_CXXFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+  fi
+
+  if test -z "$warn_llvm"; then
+    AC_DEFINE(HAVE_LLVM, 1, [Define to 1 if LLVM is available.])
+  else
+    ENABLE_JIT=no
+    LLVM_CPPFLAGS=
+    LLVM_CXXFLAGS=
+    LLVM_LDFLAGS=
+    LLVM_LIBS=
+    OCTAVE_CONFIGURE_WARNING([warn_llvm])
+  fi
+dnl FIXME: Re-instate when JIT is enabled by default
+dnl else
+dnl   ## JIT build disabled
+dnl   warn_llvm="JIT compiler disabled, some performance loss for loops"
+dnl   OCTAVE_CONFIGURE_WARNING([warn_llvm])
+fi
+if test $ENABLE_JIT; then
+  AC_DEFINE(ENABLE_JIT, 1, [Define to 1 to enable JIT compiler.])
+fi
+
+AC_SUBST(LLVM_CPPFLAGS)
+AC_SUBST(LLVM_CXXFLAGS)
+AC_SUBST(LLVM_LDFLAGS)
+AC_SUBST(LLVM_LIBS)
+AM_CONDITIONAL([AMCOND_HAVE_LLVM], [test -z "$warn_llvm"])
+
+### Check for HDF5 library.
+
+save_CPPFLAGS="$CPPFLAGS"
+save_LIBS="$LIBS"
+CPPFLAGS="$Z_CPPFLAGS $CPPFLAGS"
+LIBS="$Z_LDFLAGS $Z_LIBS $LIBS"
+OCTAVE_CHECK_LIB(hdf5, HDF5,
+  [HDF5 library not found.  Octave will not be able to save or load HDF5 data files.],
+  [hdf5.h], [H5Gget_num_objs], [], [],
+  [warn_hdf5=
+   OCTAVE_CHECK_HDF5_HAS_VER_16_API
+   AC_DEFINE(HAVE_HDF5, 1,
+     [Define to 1 if HDF5 is available and newer than version 1.6.])
+   if test $have_msvc = yes; then
+     OCTAVE_CHECK_LIB_HDF5_DLL
+   fi
+  ])
+CPPFLAGS="$save_CPPFLAGS"
+LIBS="$save_LIBS"
+
+dnl Should we check for this now, or wait until some version of
+dnl HDF5 actually supports this feature?
+have_hdf5_int2float_conversions=no
+if test $have_hdf5_int2float_conversions = yes; then
+  AC_DEFINE(HAVE_HDF5_INT2FLOAT_CONVERSIONS, 1,
+    [Define to 1 if/when HDF5 supports automatic conversion between integer and floating-point binary data.])
+fi
+
+### Check for FFTW library.  Default to Fortran FFTPACK if it is not available.
+
+## Check for FFTW header and library.
+OCTAVE_CHECK_LIB(fftw3, FFTW3,
+  [FFTW3 library not found.  The slower FFTPACK library will be used instead.],
+  [fftw3.h], [fftw_plan_dft_1d])
+
+OCTAVE_CHECK_LIB(fftw3f, FFTW3F,
+  [FFTW3F library not found.  The slower FFTPACK library will be used instead.],
+  [fftw3.h], [fftwf_plan_dft_1d])
+
+## Check command line for the option to disable multi-threaded FFTW
+build_fftw_threads=yes
+AC_ARG_ENABLE([fftw-threads],
+  [AS_HELP_STRING([--disable-fftw-threads],
+    [disable Multi-threaded FFTW])],
+  [if test "$enableval" = no; then
+     build_fftw_threads=no
+   fi],
+  [])
+
+## Octave is currently unable to use FFTW unless
+## both float and double versions are available.
+
+AM_CONDITIONAL([AMCOND_HAVE_FFTW],
+  [test -n "$FFTW3_LIBS" && test -n "$FFTW3F_LIBS"])
+
+if test -n "$FFTW3_LIBS" && test -n "$FFTW3F_LIBS"; then
+  AC_DEFINE(HAVE_FFTW, 1, [Define if you have both FFTW3 and FFTW3F libraries.])
+else
+  ## --without-fftw3 given, or one of the FFTW3 libs not installed.
+  ## Don't check for FFTW threads as this is now pointless.
+  build_fftw_threads=no
+fi
+
+## Check for the multithreaded FFTW library.
+## Fallback to singlethreaded if not found or disabled
+if test $build_fftw_threads = yes; then
+  OCTAVE_CHECK_FFTW_THREADS(fftw3, fftw_plan_with_nthreads)
+  OCTAVE_CHECK_FFTW_THREADS(fftw3f, fftwf_plan_with_nthreads)
+fi
+
+## Subdirectory of liboctave/cruft to build if FFTW is not found.
+FFT_DIR="fftpack"
+AC_SUBST(FFT_DIR)
+
+### Check for GLPK library and header.
+
+save_CPPFLAGS="$CPPFLAGS"
+save_LIBS="$LIBS"
+CPPFLAGS="$Z_CPPFLAGS $CPPFLAGS"
+LIBS="$Z_LDFLAGS $Z_LIBS $LIBS"
+OCTAVE_CHECK_LIB(glpk, GLPK,
+  [GLPK library not found.  The glpk function for solving linear programs will be disabled.],
+  [glpk/glpk.h glpk.h], [glp_simplex], [], [],
+  [warn_glpk=
+   OCTAVE_CHECK_LIB_GLPK_OK(
+    [AC_DEFINE(HAVE_GLPK, 1, [Define to 1 if GLPK is available.])],
+    [warn_glpk="GLPK library found, but does not seem to work properly; disabling glpk function"])])
+LIBS="$save_LIBS"
+CPPFLAGS="$save_CPPFLAGS"
+
+### Checks for cURL header and library.
+
+save_CPPFLAGS="$CPPFLAGS"
+save_LIBS="$LIBS"
+CPPFLAGS="$Z_CPPFLAGS $CPPFLAGS"
+LIBS="$Z_LDFLAGS $Z_LIBS $LIBS"
+OCTAVE_CHECK_LIB(curl, cURL,
+  [cURL library not found.  The ftp objects, urlread and urlwrite functions will be disabled.],
+  [curl/curl.h], [curl_easy_escape])
+if test -z "$warn_curl"; then
+  ## Additional check on cURL library that was found
+  AC_CACHE_CHECK([for CURLOPT_DIRLISTONLY in curl/curl.h],
+    [octave_cv_curl_has_curlopt_dirlistonly],
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+      #include <curl/curl.h>
+      ]], [[
+      curl_easy_setopt ((CURL*)NULL, CURLOPT_DIRLISTONLY, 0);
+      ]])],
+      [octave_cv_curl_has_curlopt_dirlistonly=yes],
+      [octave_cv_curl_has_curlopt_dirlistonly=no])
+    ])
+  if test $octave_cv_curl_has_curlopt_dirlistonly = no; then
+    AC_DEFINE(CURLOPT_DIRLISTONLY, CURLOPT_FTPLISTONLY,
+      [Define to the legacy option name if using an older version of cURL.])
+  fi
+fi
+LIBS="$save_LIBS"
+CPPFLAGS="$save_CPPFLAGS"
+
+### Check for sndfile
+
+OCTAVE_CHECK_LIB(sndfile, sndfile,
+  [sndfile library not found.  The audioinfo, audioread, and audiowrite functions will be disabled.],
+  [sndfile.h], [sf_open],
+  [], [don't use sndfile library, disable audio file I/O],
+  [warn_sndfile=
+   OCTAVE_CHECK_LIB_SNDFILE_OK(
+    [AC_DEFINE(HAVE_SNDFILE, 1, [Define to 1 if sndfile is available.])],
+    [warn_sndfile="sndfile library found, but does not seem to work properly; disabling audio file I/O functions"])])
+
+### Check for PortAudio
+
+OCTAVE_CHECK_LIB(portaudio, PortAudio,
+  [PortAudio library not found.  The audioplayer, audiorecorder, and audiodevinfo functions will be disabled.],
+  [portaudio.h], [Pa_Initialize],
+  [], [don't use PortAudio library, disable audio playback and recording],
+  [], [portaudio-2.0])
+
+### Check for either of Graphics/ImageMagick++ libraries
+
+check_magick=yes
+use_magick=no
+AC_ARG_WITH([magick],
+  [AS_HELP_STRING([--with-magick=LIB],
+    [select library to use for image I/O (options: GraphicsMagick(default) or ImageMagick)])],
+  [if test x"$withval" = xno; then
+     check_magick=no
+     warn_magick_disabled="--without-magick specified.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."
+     OCTAVE_CONFIGURE_WARNING([warn_magick_disabled])
+   else
+     magick="$withval"
+   fi], [magick="GraphicsMagick"])
+
+if test $check_magick = yes; then
+
+  MAGICK_CPPFLAGS=
+  MAGICK_LDFLAGS=
+  MAGICK_LIBS=
+
+  PKG_CHECK_EXISTS([$magick++], [
+    ## Make sure we only get -I, -L, and -l flags.  Some Graphics/ImageMagick++
+    ## packages add extra flags that are useful when building
+    ## Graphics/ImageMagick++ extentions.  These extra flags break the
+    ## Octave build.
+    MAGICK_CPPFLAGS=`$PKG_CONFIG --cflags-only-I $magick++`
+    MAGICK_LDFLAGS=`$PKG_CONFIG --libs-only-L $magick++`
+    MAGICK_LIBS=`$PKG_CONFIG --libs-only-l $magick++`
+
+    warn_magick="$magick++ library fails tests.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."
+
+    save_CPPFLAGS="$CPPFLAGS"
+    save_LIBS="$LIBS"
+    CPPFLAGS="$MAGICK_CPPFLAGS $CPPFLAGS"
+    LIBS="$MAGICK_LDFLAGS $MAGICK_LIBS $LIBS"
+    AC_LANG_PUSH(C++)
+    AC_CHECK_HEADER([Magick++.h], [
+      AC_CACHE_CHECK([for Magick::ColorRGB in Magick++.h],
+        [octave_cv_func_magick_colorrgb],
+        [AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
+          #include <Magick++.h>
+          ]], [[
+          Magick::ColorRGB c;
+          ]])],
+          octave_cv_func_magick_colorrgb=yes,
+          octave_cv_func_magick_colorrgb=no)
+        ])
+      if test $octave_cv_func_magick_colorrgb = yes; then
+        use_magick=yes
+        warn_magick=
+      fi
+    ])
+    AC_LANG_POP(C++)
+    CPPFLAGS="$save_CPPFLAGS"
+    LIBS="$save_LIBS"
+
+    AC_CHECK_FUNCS([setlocale], [],
+      [use_magick=no
+       warn_magick="$magick++ requires setlocale function.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."])
+  ],
+  [use_magick=no
+   warn_magick="$magick++ library not found.  The imread, imwrite, and imfinfo functions for reading and writing image files will not be fully functional."])
+fi
+
+if test $use_magick = yes; then
+  AC_DEFINE(HAVE_MAGICK, 1,
+    [Define to 1 if Graphics/ImageMagick++ is available.])
+else
+  if test -n "$warn_magick"; then
+    OCTAVE_CONFIGURE_WARNING([warn_magick])
+  fi
+  MAGICK_CPPFLAGS=
+  MAGICK_LDFLAGS=
+  MAGICK_LIBS=
+fi
+AC_SUBST(MAGICK_CPPFLAGS)
+AC_SUBST(MAGICK_LDFLAGS)
+AC_SUBST(MAGICK_LIBS)
+
+### Check for X11 libraries
+
+AC_PATH_X
+if test "$have_x" = yes; then
+  AC_DEFINE(HAVE_X_WINDOWS, 1, [Define to 1 if you have X11.])
+
+  if test "$x_includes" != "NONE"; then
+    X11_INCFLAGS="$x_includes"
+  fi
+  AC_SUBST(X11_INCFLAGS)
+
+  if test -z "$x_libraries"; then
+    AC_CHECK_LIB([X11], XrmInitialize, [X11_LIBS="-lX11"], [X11_LIBS=])
+  elif test "$x_libraries" != "NONE"; then
+    AC_CHECK_LIB([X11], XrmInitialize,
+      [X11_LIBS="-L$x_libraries -lX11"], [X11_LIBS=], "-L$x_libraries")
+  fi
+  AC_SUBST(X11_LIBS)
+fi
+
+### Check for the Carbon framework on MacOSX systems
+OCTAVE_HAVE_FRAMEWORK([Carbon],
+  [[#include <Carbon/Carbon.h>]], [[CGMainDisplayID ()]],
+  [have_framework_carbon=yes], [have_framework_carbon=no])
+if test $have_framework_carbon = yes; then
+  AC_DEFINE(HAVE_FRAMEWORK_CARBON, 1,
+    [Define to 1 if framework CARBON is available.])
+  CARBON_LIBS="-framework Carbon"
+  AC_MSG_NOTICE([adding -framework Carbon to CARBON_LIBS])
+  AC_SUBST(CARBON_LIBS)
+fi
+
+### Check for list of libraries needed for OpenGL graphics renderer.
+
+check_opengl=yes
+AC_ARG_WITH([opengl],
+  [AS_HELP_STRING([--without-opengl],
+    [don't use OpenGL libraries, disable OpenGL graphics])],
+  [if test x"$withval" = xno; then
+     check_opengl=no
+     warn_opengl_disabled="--without-opengl specified.  OpenGL graphics will be disabled."
+     OCTAVE_CONFIGURE_WARNING([warn_opengl_disabled])
+   fi])
+
+## Check for OpenGL library
+if test $check_opengl = yes; then
+  OCTAVE_CHECK_LIB_OPENGL
+  if test -z "$OPENGL_LIBS"; then
+    warn_opengl_libs="OpenGL libs (GL and GLU) not found.  OpgnGL graphics will be disabled."
+    OCTAVE_CONFIGURE_WARNING([warn_opengl_libs])
+  fi
+fi
+
+## Check for FreeType 2 library
+
+warn_freetype=""
+PKG_CHECK_MODULES([FT2], [freetype2], [
+  min_ft2_version=9.03
+  AC_MSG_CHECKING([for FreeType2 version >= $min_ft2_version])
+  $PKG_CONFIG freetype2 --atleast-version=$min_ft2_version
+  ac_status=$?
+  if test "$ac_status" = 0; then
+    AC_MSG_RESULT(yes)
+    AC_DEFINE(HAVE_FREETYPE, 1, [Define to 1 if you have Freetype library.])
+    save_LIBS="$LIBS"
+    LIBS="$FT2_LIBS $LIBS"
+    AC_CHECK_FUNCS([FT_Reference_Face])
+    LIBS="$save_LIBS"
+  else
+    AC_MSG_RESULT(no)
+    warn_freetype="FreeType library >= 9.03 not found.  OpenGL graphics will not be fully functional."
+  fi])
+
+if test -n "$warn_freetype"; then
+  OCTAVE_CONFIGURE_WARNING([warn_freetype])
+else
+  FT2_CPPFLAGS="$FT2_CFLAGS"
+  ## Alias CPPFLAGS to CFLAGS.  This is closer to the true meaning
+  ## of `pkg-config --cflags` output.
+  FT2_CPPFLAGS="$FT2_CFLAGS"
+  AC_SUBST(FT2_CPPFLAGS)
+fi
+
+## Check for Xft library (when using X11)
+
+warn_xft=""
+if test "$have_x" = yes; then
+  PKG_CHECK_MODULES(XFT, [xft],
+    [AC_DEFINE(HAVE_XFT, 1, [Define to 1 if Xft is present.])],
+    [warn_xft="Xft library not found.  OpenGL graphics will not be fully functional."])
+fi
+
+if test -n "$warn_xft"; then
+  OCTAVE_CONFIGURE_WARNING([warn_xft])
+fi
+
+## Check for fontconfig library
+
+warn_fontconfig=""
+PKG_CHECK_MODULES(FONTCONFIG, [fontconfig],
+  [AC_DEFINE(HAVE_FONTCONFIG, 1, [Define to 1 if fontconfig is present.])],
+  [warn_fontconfig="Fontconfig library not found.  OpenGL graphics will not be fully functional."])
+
+if test -n "$warn_fontconfig"; then
+  OCTAVE_CONFIGURE_WARNING([warn_fontconfig])
+else
+  FONTCONFIG_CPPFLAGS="$FONTCONFIG_CFLAGS"
+  ## Alias CPPFLAGS to CFLAGS.  This is closer to the true meaning
+  ## of `pkg-config --cflags` output.
+  FONTCONFIG_CPPFLAGS="$FONTCONFIG_CFLAGS"
+  AC_SUBST(FONTCONFIG_CPPFLAGS)
+fi
+
+## Check for OSMesa which is needed for offscreen rendering with OpenGL
+## FIXME: Check for version >= 9.0.0
+OCTAVE_CHECK_LIB(OSMesa, OSMesa,
+  [OSMesa library not found.  Offscreen rendering with OpenGL will be disabled.],
+  [osmesa.h GL/osmesa.h], [OSMesaCreateContext])
+
+## Check for gl2ps which is required for printing with OpenGL graphics
+
+AC_CHECK_HEADERS([gl2ps.h],
+  [GL2PS_LIBS="-lgl2ps"],
+  [warn_gl2ps="gl2ps library not found.  Printing of OpenGL graphics will be disabled."])
+
+if test -n "$warn_gl2ps"; then
+  OCTAVE_CONFIGURE_WARNING([warn_gl2ps])
+fi
+
+AC_SUBST(GL2PS_LIBS)
+
+### GUI/Qt related tests.
+
+## Change to "5 4" once Octave works with both versions.
+QT_VERSIONS="4"
+check_qt=yes
+
+AC_ARG_WITH([qt],
+  [AS_HELP_STRING([--without-qt], [don't use Qt libraries; disable Qt GUI.  May also select Qt major version:  --with-qt=5])],
+  [if test x"$withval" = xno; then
+     check_qt=no;
+     warn_qt_disabled="--without-qt specified.  The Qt GUI will be disabled."
+     OCTAVE_CONFIGURE_WARNING([warn_qt_disabled])
+   elif test -n "$withval"; then
+     QT_VERSIONS="$withval"
+   fi])
+
+if test $check_qt = yes; then
+  OCTAVE_CHECK_QT([$QT_VERSIONS])
+fi
+
+## Check for FLTK (www.fltk.org) library
+
+check_fltk=yes
+build_fltk_graphics=no
+
+AC_ARG_WITH([fltk],
+  [AS_HELP_STRING([--without-fltk],
+    [don't use FLTK libraries, disable OpenGL graphics with FLTK widgets])],
+  [if test x"$withval" = xno; then
+     check_fltk=no
+     warn_fltk="--without-fltk specified.  FLTK widgets will be disabled."
+     OCTAVE_CONFIGURE_WARNING([warn_fltk])
+   fi])
+
+FLTK_CPPFLAGS=
+FLTK_LDFLAGS=
+FLTK_LIBS=
+
+if test $check_fltk = yes; then
+  AC_ARG_WITH([fltk-prefix],
+    [AS_HELP_STRING([--with-fltk-prefix=PFX],
+      [prefix where FLTK is installed (optional)])],
+    [fltk_prefix="$withval"],
+    [fltk_prefix=""])
+
+  AC_ARG_WITH([fltk-exec-prefix],
+    [AS_HELP_STRING([--with-fltk-exec-prefix=PFX],
+      [exec prefix where FLTK is installed (optional)])],
+    [fltk_exec_prefix="$withval"],
+    [fltk_exec_prefix=""])
+
+  if test "x$fltk_exec_prefix" != x; then
+    fltk_args="$fltk_args --exec-prefix=$fltk_exec_prefix"
+    if test "x${FLTK_CONFIG+set}" != xset ; then
+      FLTK_CONFIG="$fltk_exec_prefix/bin/fltk-config"
+    fi
+  fi
+
+  if test "x$fltk_prefix" != x; then
+    fltk_args="$fltk_args --prefix=$fltk_prefix"
+    if test x${FLTK_CONFIG+set} != xset ; then
+      FLTK_CONFIG="$fltk_prefix/bin/fltk-config"
+    fi
+  fi
+
+  AC_PATH_PROG([FLTK_CONFIG], [fltk-config], [no])
+
+  warn_fltk_config=""
+  warn_fltk_opengl=""
+
+  if test "$FLTK_CONFIG" = no; then
+    warn_fltk_config="FLTK config script not found.  Native graphics will be disabled."
+    OCTAVE_CONFIGURE_WARNING([warn_fltk_config])
+  else
+    ## Only include -I options in FLTK_CPPFLAGS
+    fltk_cflags=`$FLTK_CONFIG $fltkconf_args --use-gl --cflags`
+    for fltk_option in $fltk_cflags; do
+      case $fltk_option in
+        -I*)
+          FLTK_CPPFLAGS="$FLTK_CPPFLAGS $fltk_option"
+        ;;
+      esac
+    done
+    FLTK_LDFLAGS=`$FLTK_CONFIG $fltkconf_args --use-gl --ldflags`
+
+    case $host_os in
+      mingw*)
+        FLTK_LDFLAGS=`echo $FLTK_LDFLAGS | $SED -e 's/-mwindows//g'`
+      ;;
+    esac
+    AC_LANG_PUSH(C++)
+    AC_CACHE_CHECK([for OpenGL support in FLTK],
+      [octave_cv_fltk_opengl_support],
+      [save_CPPFLAGS="$CPPFLAGS"
+      CPPFLAGS="$CFLAGS $FLTK_CPPFLAGS"
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+        #include <FL/gl.h>
+        ]], [[
+        int nothing = 0;
+        ]])],
+        octave_cv_fltk_opengl_support=yes,
+        octave_cv_fltk_opengl_support=no)
+      CPPFLAGS="$save_CPPFLAGS"
+      ])
+    if test $octave_cv_fltk_opengl_support = no; then
+      warn_fltk_opengl="FLTK does not have OpenGL support.  OpenGL graphics with FLTK widgets will be disabled."
+    else
+      build_fltk_graphics=yes
+      AC_DEFINE(HAVE_FLTK, 1, [Define to 1 if FLTK is available.])
+    fi
+    AC_LANG_POP(C++)
+
+    if test -n "$warn_fltk_opengl"; then
+      OCTAVE_CONFIGURE_WARNING([warn_fltk_opengl])
+    fi
+  fi
+fi
+
+AC_SUBST(FLTK_CPPFLAGS)
+AC_SUBST(FLTK_LDFLAGS)
+AC_SUBST(FLTK_LIBS)
+
+if test $build_qt_graphics = no && test $build_fltk_graphics = no; then
+  opengl_graphics=no
+else
+  opengl_graphics=yes
+fi
+
+### Check for BLAS and LAPACK libraries:
+
+## Need to adjust FFLAGS to include correct integer size.
+save_FFLAGS="$FFLAGS"
+FFLAGS="$FFLAGS $F77_INTEGER_8_FLAG"
+
+AX_BLAS_WITH_F77_FUNC([:], [:],
+  [ax_blas_ok=yes
+  AC_MSG_CHECKING([BLAS can be called from Fortran])
+  AC_MSG_RESULT([yes assumed for cross compilation])])
+AX_LAPACK([:], [:])
+
+## Restore FFLAGS.
+FFLAGS="$save_FFLAGS"
+
+## If necessary, try again with -ff2c in FFLAGS
+if test $ax_blas_ok = no; then
+  save_FFLAGS="$FFLAGS"
+  FFLAGS="-ff2c $FFLAGS $F77_INTEGER_8_FLAG"
+
+  AX_BLAS_WITH_F77_FUNC([:], [:])
+  AX_LAPACK([:], [:])
+
+  ## Restore FFLAGS, with -ff2c if that was helpful
+
+  if test $ax_blas_ok = yes; then
+    FFLAGS="-ff2c $save_FFLAGS"
+  else
+    FFLAGS="$save_FFLAGS"
+  fi
+fi
+
+## On OSX, try again with a wrapper library (without -ff2c!)
+if test $ax_blas_ok = no; then
+  case $host_os in
+    darwin*)
+      ## test if wrapper functions help
+      octave_blaswrap_save_CFLAGS="$CFLAGS"
+      CFLAGS="$CFLAGS -DUSE_BLASWRAP"
+      AC_LANG_PUSH(C)
+      AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+          #include "liboctave/cruft/misc/blaswrap.c"
+        ]])],
+        [mv conftest.$ac_objext blaswrap.$ac_objext
+         octave_blaswrap_save_BLAS_LIBS="$BLAS_LIBS"
+         BLAS_LIBS="blaswrap.$ac_objext -framework vecLib"
+
+         save_FFLAGS="$FFLAGS"
+         FFLAGS="$FFLAGS $F77_INTEGER_8_FLAG"
+
+         AX_BLAS_WITH_F77_FUNC([:], [:])
+         AX_LAPACK([:], [:])
+
+         ## Restore FFLAGS.
+         FFLAGS="$save_FFLAGS"
+
+         ## remove temp file
+         rm -f blaswrap.$ac_objext],
+        [AC_MSG_FAILURE([cannot compile liboctave/cruft/misc/blaswrap.c])])
+      AC_LANG_POP(C)
+      CFLAGS="$octave_blaswrap_save_CFLAGS"
+
+      if test $ax_blas_ok = no; then
+        BLAS_LIBS="$octave_blaswrap_save_BLAS_LIBS"
+      else
+        ## wrapper in cruft, remove from BLAS_LIBS
+        BLAS_LIBS=`echo $BLAS_LIBS | $SED -e 's/blaswrap.[[^ ]]* //g'`
+        AC_DEFINE(USE_BLASWRAP, 1,
+          [Define to 1 if BLAS functions need to be wrapped (potentially needed for 64-bit OSX only).])
+      fi
+    ;;
+  esac
+fi
+
+if test $ax_blas_ok = no; then
+  if test $ENABLE_64 = yes && test $ax_blas_integer_size_ok = no; then
+    ## Attempt to be more informative.
+    AC_MSG_ERROR([BLAS doesn't seem to support 64-bit integers.  This is incompatible with --enable-64.])
+  else
+    AC_MSG_ERROR([A BLAS library was detected but found incompatible with your Fortran 77 compiler settings.])
+  fi
+fi
+
+if test $ax_blas_ok = no || test $ax_lapack_ok = no; then
+  AC_MSG_ERROR([BLAS and LAPACK libraries are required])
+fi
+
+### Check for the qrupdate library
+
+## No need to adjust FFLAGS because only link is attempted.
+## Must supply proper LIBS, however.
+save_LIBS="$LIBS"
+LIBS="$LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS"
+OCTAVE_CHECK_LIB(qrupdate, qrupdate,
+  [qrupdate not found.  The QR & Cholesky updating functions will be slow.],
+  [],
+  [sqr1up],
+  [Fortran 77], [don't use qrupdate, disable QR & Cholesky updating functions])
+
+## Additional check to see if qrupdate lib found supports LU updates
+if test -z "$warn_qrupdate"; then
+  AC_CACHE_CHECK([for slup1up in $QRUPDATE_LIBS],
+    [octave_cv_func_slup1up],
+    [LIBS="$LIBS $QRUPDATE_LIBS"
+    AC_LANG_PUSH([Fortran 77])
+    AC_LINK_IFELSE([AC_LANG_CALL([], [slup1up])],
+      octave_cv_func_slup1up=yes, octave_cv_func_slup1up=no)
+    AC_LANG_POP([Fortran 77])
+  ])
+  if test $octave_cv_func_slup1up = yes; then
+    AC_DEFINE(HAVE_QRUPDATE_LUU, 1, [Define to 1 if qrupdate supports LU updates.])
+  fi
+fi
+LIBS="$save_LIBS"
+
+if test $ENABLE_64 = yes; then
+  CHOLMOD_TAG="_l_"
+  CXSPARSE_TAG="_dl_"
+  UMFPACK_TAG="_zl_"
+else
+  CHOLMOD_TAG="_"
+  CXSPARSE_TAG="_di_"
+  UMFPACK_TAG="_zi_"
+fi
+
+### Check for AMD library
+
+OCTAVE_CHECK_LIB(amd, AMD,
+  [AMD library not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/amd.h ufsparse/amd.h amd/amd.h amd.h],
+  [amd_postorder],
+  [], [don't use AMD library, disable some sparse matrix functionality])
+
+### Check for CAMD library
+
+OCTAVE_CHECK_LIB(camd, CAMD,
+  [CAMD library not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/camd.h ufsparse/camd.h camd/camd.h camd.h],
+  [camd_postorder],
+  [], [don't use CAMD library, disable some sparse matrix functionality])
+
+### Check for COLAMD library
+
+OCTAVE_CHECK_LIB(colamd, COLAMD,
+  [COLAMD library not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/colamd.h ufsparse/colamd.h colamd/colamd.h colamd.h],
+  [colamd],
+  [], [don't use COLAMD library, disable some sparse matrix functionality])
+
+### Check for CCOLAMD library
+
+OCTAVE_CHECK_LIB(ccolamd, CCOLAMD,
+  [CCOLAMD library not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/ccolamd.h ufsparse/ccolamd.h ccolamd/ccolamd.h ccolamd.h],
+  [ccolamd],
+  [], [don't use CCOLAMD library, disable some sparse matrix functionality])
+
+### Check for CHOLMOD library.
+### If your cholmod library requires cblas, then you will need to
+### configure with --with-cholmod="-lcholmod -lcblas".
+
+save_LIBS="$LIBS"
+LIBS="$COLAMD_LDFLAGS $COLAMD_LIBS $AMD_LDFLAGS $AMD_LIBS $LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS"
+OCTAVE_CHECK_LIB(cholmod, CHOLMOD,
+  [CHOLMOD library not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/cholmod.h ufsparse/cholmod.h cholmod/cholmod.h cholmod.h],
+  [cholmod${CHOLMOD_TAG}start],
+  [], [don't use CHOLMOD library, disable some sparse matrix functionality])
+LIBS="$save_LIBS"
+
+### Check for CXSparse library
+
+OCTAVE_CHECK_LIB(cxsparse, CXSparse,
+  [CXSparse library not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/cs.h ufsparse/cs.h cxsparse/cs.h cs.h],
+  [cs${CXSPARSE_TAG}sqr],
+  [C++], [don't use CXSparse library, disable some sparse matrix functionality])
+
+## Additional check for CXSparse version >= 2.2
+if test $octave_cv_lib_cxsparse = yes; then
+  OCTAVE_CHECK_CXSPARSE_VERSION_OK
+  if test $octave_cv_cxsparse_version_ok = no; then
+    AC_MSG_ERROR([CXSparse library is too old (< version 2.2).  Upgrade CXSparse (SuiteSparse) or configure Octave with --disable-cxsparse"])
+  fi
+fi
+
+### Check for UMFPACK library.
+
+save_LIBS="$LIBS"
+save_CPPFLAGS="$CPPFLAGS"
+LIBS="$AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS"
+CPPFLAGS="$AMD_CPPFLAGS $CPPFLAGS"
+OCTAVE_CHECK_LIB([umfpack], UMFPACK,
+  [UMFPACK not found.  This will result in some lack of functionality for sparse matrices.],
+  [suitesparse/umfpack.h ufsparse/umfpack.h umfpack/umfpack.h umfpack.h],
+  [umfpack${UMFPACK_TAG}get_determinant],
+  [], [don't use UMFPACK, disable some sparse matrix functionality])
+CPPFLAGS="$save_CPPFLAGS"
+LIBS="$save_LIBS"
+
+if test -z "$UMFPACK_LIBS"; then
+  ## Invalidate the cache and try again with -lcblas.
+  $as_unset ac_cv_lib_umfpack_umfpack${UMFPACK_TAG}get_determinant
+  $as_unset octave_cv_lib_umfpack
+  save_LIBS="$LIBS"
+  LIBS="-lcblas $AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS"
+  OCTAVE_CHECK_LIB([umfpack], UMFPACK,
+    [UMFPACK not found.  This will result in some lack of functionality for sparse matrices.],
+    [suitesparse/umfpack.h ufsparse/umfpack.h umfpack/umfpack.h umfpack.h],
+    [umfpack${UMFPACK_TAG}get_determinant],
+    [], [don't use UMFPACK, disable some sparse matrix functionality])
+  if test -n "$UMFPACK_LIBS"; then
+    UMFPACK_LIBS="$UMFPACK_LIBS -lcblas"
+  fi
+  LIBS="$save_LIBS"
+fi
+
+## Test features of the installed UMFPACK library
+
+if test -n "$UMFPACK_LIBS"; then
+  ## SuiteSparse >= 4.0 needs additional link library for SuiteSparse_time
+  save_CPPFLAGS="$CPPFLAGS"
+  save_LIBS="$LIBS";
+  CPPFLAGS="$UMFPACK_CPPFLAGS $AMD_CPPFLAGS $CPPFLAGS"
+  LIBS="$UMFPACK_LIBS $AMD_LDFLAGS $AMD_LIBS $BLAS_LIBS $FLIBS $LIBS"
+  xtra_libs=
+  OCTAVE_UMFPACK_NEED_SUITESPARSE_TIME
+  if test $STATIC_LIBS = yes || test $octave_cv_umfpack_need_suitesparse_time = yes; then
+    AC_CHECK_LIB([rt], [clock_gettime], [xtra_libs="-lrt"], [xtra_libs=])
+    ## FIXME: This library list is only accurate for Linux, Mac OS X.
+    ##        Possibly need other library names for MinGW, Cygwin.
+    AC_SEARCH_LIBS([SuiteSparse_time],
+                   [suitesparseconfig SuiteSparse],
+                   [], [], [$xtra_libs])
+    case $ac_cv_search_SuiteSparse_time in
+      -l*)
+        UMFPACK_LIBS="$UMFPACK_LIBS $ac_cv_search_SuiteSparse_time"
+      ;;
+      no)
+        UMFPACK_LIBS=
+        AC_MSG_WARN([UMFPACK library found but is missing SuiteSparse_time functionality.])
+        AC_MSG_WARN([UMFPACK library will be disabled.])
+      ;;
+    esac
+  fi
+  LIBS="$save_LIBS"
+  CPPFLAGS="$save_CPPFLAGS"
+
+  ## Check for UMFPACK separately split complex matrix and RHS.
+  if test -n "$UMFPACK_LIBS"; then
+    save_CPPFLAGS="$CPPFLAGS"
+    save_LIBS="$LIBS";
+    CPPFLAGS="$UMFPACK_CPPFLAGS $AMD_CPPFLAGS $CPPFLAGS"
+    LIBS="$UMFPACK_LIBS $CHOLMOD_LDFLAGS $CHOLMOD_LIBS $AMD_LDFLAGS $AMD_LIBS $COLAMD_LDFLAGS $COLAMD_LIBS $LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS $xtra_libs"
+    OCTAVE_UMFPACK_SEPARATE_SPLIT
+    LIBS="$save_LIBS"
+    CPPFLAGS="$save_CPPFLAGS"
+  fi
+fi
+
+### Check for ARPACK library.
+
+save_LIBS="$LIBS"
+LIBS="$LAPACK_LIBS $BLAS_LIBS $FLIBS $LIBS"
+OCTAVE_CHECK_LIB([arpack], ARPACK,
+  [ARPACK not found.  The eigs function will be disabled.],
+  [],
+  [dseupd],
+  [Fortran 77], [don't use the ARPACK library, disable eigs function],
+  [warn_arpack=
+   OCTAVE_CHECK_LIB_ARPACK_OK(
+     [AC_DEFINE(HAVE_ARPACK, 1, [Define to 1 if ARPACK is available.])],
+     [warn_arpack="ARPACK library found, but does not seem to work properly; disabling eigs function"])])
+LIBS="$save_LIBS"
+
+### Check for readline library.
+
+OCTAVE_ENABLE_READLINE
+
 ### Check for existence of various libraries
 
 ## OS-specific test for dirent, opendir.
@@ -3456,6 +3267,10 @@
   Qt CPPFLAGS:                 $QT_CPPFLAGS
   Qt LDFLAGS:                  $QT_LDFLAGS
   Qt libraries:                $QT_LIBS
+  Qt moc:                      $MOC $MOCFLAGS
+  Qt uic:                      $UIC $UICFLAGS
+  Qt rcc:                      $RCC $RCCFLAGS
+  Qt lrelease:                 $LRELEASE $LRELEASEFLAGS
   READLINE libraries:          $READLINE_LIBS
   Sndfile CPPFLAGS:            $SNDFILE_CPPFLAGS
   Sndfile LDFLAGS:             $SNDFILE_LDFLAGS
diff -r 60faa7c85e31 -r 66dd260512a4 libgui/module.mk
--- a/libgui/module.mk	Mon Aug 08 19:22:29 2016 -0400
+++ b/libgui/module.mk	Tue Aug 09 14:41:52 2016 -0400
@@ -81,7 +81,7 @@
   ( echo "#if defined (HAVE_CONFIG_H)"; \
     echo '#  include "config.h"'; \
     echo "#endif"; \
-    $(MOC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MOC_OCTAVE_CPPFLAGS) $(MOC_CPPFLAGS) $(libgui_liboctgui_la_CPPFLAGS) $< ) > $@-t && \
+    $(MOC) $(MOCFLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MOC_OCTAVE_CPPFLAGS) $(MOC_CPPFLAGS) $(libgui_liboctgui_la_CPPFLAGS) $< ) > $@-t && \
   mv $@-t $@
 endef
 
@@ -94,7 +94,7 @@
     echo "#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)"; \
     echo "#pragma GCC diagnostic ignored \"-Wunused-variable\""; \
     echo "#endif"; \
-    $(RCC) -name $(@D) $< ) > $@-t && \
+    $(RCC) $(RCCFLAGS) -name $(@D) $< ) > $@-t && \
   mv $@-t $@
 endef
 
@@ -102,7 +102,7 @@
 	$(AM_V_GEN)$(moc-command)
 
 ui-%.h: %.ui
-	$(AM_V_GEN)$(UIC) -o $@ $<
+	$(AM_V_GEN)$(UIC) $(UICFLAGS) -o $@ $<
 
 qrc-%.cc: %.qrc
 	$(AM_V_GEN)$(rcc-command)
@@ -113,7 +113,7 @@
 am__v_lrelease_1 =
 
 %.qm: %.ts | libgui/languages/$(octave_dirstamp)
-	$(AM_V_GEN)$(LRELEASE) $(AM_V_lrelease) -qm $@ $<
+	$(AM_V_GEN)$(LRELEASE) $(LRELEASEFLAGS) $(AM_V_lrelease) -qm $@ $<
 
 DIRSTAMP_FILES += \
   libgui/languages/$(octave_dirstamp)
diff -r 60faa7c85e31 -r 66dd260512a4 m4/acinclude.m4
--- a/m4/acinclude.m4	Mon Aug 08 19:22:29 2016 -0400
+++ b/m4/acinclude.m4	Tue Aug 09 14:41:52 2016 -0400
@@ -189,7 +189,9 @@
     [octave_cv_cxsparse_version_ok],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
         #if defined (HAVE_SUITESPARSE_CS_H)
         #include <suitesparse/cs.h>
@@ -211,6 +213,7 @@
       octave_cv_cxsparse_version_ok=yes,
       octave_cv_cxsparse_version_ok=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_cxsparse_version_ok = yes; then
@@ -352,12 +355,14 @@
 dnl FIXME: This test uses a version number.  It potentially could
 dnl        be re-written to actually call the function, but is it worth it?
 dnl
-AC_DEFUN([OCTAVE_CHECK_VERSION_2_6_0], [
+AC_DEFUN([OCTAVE_CHECK_QSCINTILLA_VERSION], [
   AC_CACHE_CHECK([whether Qscintilla has version 2.6.0 or later],
     [octave_cv_version_2_6_0],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
         #include <Qsci/qsciglobal.h>
         ]], [[
@@ -368,6 +373,7 @@
       octave_cv_version_2_6_0=yes,
       octave_cv_version_2_6_0=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_version_2_6_0 = yes; then
@@ -433,7 +439,9 @@
     [octave_cv_decl_qfont_monospace],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
         #include <QFont>
         ]], [[
@@ -442,6 +450,7 @@
       octave_cv_decl_qfont_monospace=yes,
       octave_cv_decl_qfont_monospace=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_decl_qfont_monospace = yes; then
@@ -457,7 +466,9 @@
     [octave_cv_decl_qfont_force_integer_metrics],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
         #include <QFont>
         ]], [[
@@ -466,6 +477,7 @@
       octave_cv_decl_qfont_force_integer_metrics=yes,
       octave_cv_decl_qfont_force_integer_metrics=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_decl_qfont_force_integer_metrics = yes; then
@@ -483,7 +495,9 @@
     [octave_cv_func_setplaceholdertext],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
         #include <Qt/qglobal.h>
         ]], [[
@@ -494,6 +508,7 @@
       octave_cv_func_setplaceholdertext=yes,
       octave_cv_func_setplaceholdertext=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_func_setplaceholdertext = yes; then
@@ -511,7 +526,9 @@
     [octave_cv_func_qabstractitemmodel_beginresetmodel],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
         #include <QAbstractItemModel>
         class item_model : public QAbstractItemModel
@@ -537,6 +554,7 @@
       octave_cv_func_qabstractitemmodel_beginresetmodel=yes,
       octave_cv_func_qabstractitemmodel_beginresetmodel=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_func_qabstractitemmodel_beginresetmodel = yes; then
@@ -553,7 +571,9 @@
     [octave_cv_func_qtabwidget_setmovable],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
         #include <QTabWidget>
         class tab_widget : public QTabWidget
@@ -568,6 +588,7 @@
       octave_cv_func_qtabwidget_setmovable=yes,
       octave_cv_func_qtabwidget_setmovable=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_func_qtabwidget_setmovable = yes; then
@@ -584,7 +605,9 @@
     [octave_cv_func_qsci_findfirstinselection],
     [AC_LANG_PUSH(C++)
     ac_octave_save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+    ac_octave_save_CXXFLAGS="$CXXFLAGS"
+    CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+    CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
     AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
         #include <Qsci/qsciscintilla.h>
         class qsci : public QsciScintilla
@@ -600,6 +623,7 @@
       octave_cv_func_qsci_findfirstinselection=yes,
       octave_cv_func_qsci_findfirstinselection=no)
     CPPFLAGS="$ac_octave_save_CPPFLAGS"
+    CXXFLAGS="$ac_octave_save_CXXFLAGS"
     AC_LANG_POP(C++)
   ])
   if test $octave_cv_func_qsci_findfirstinselection = yes; then
@@ -1250,7 +1274,9 @@
     [octave_cv_qt_opengl_ok],
     [AC_LANG_PUSH(C++)
      ac_octave_save_CPPFLAGS="$CPPFLAGS"
-     CPPFLAGS="$QT_CPPFLAGS $CPPFLAGS"
+     ac_octave_save_CXXFLAGS="$CXXFLAGS"
+     CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+     CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
          #if HAVE_WINDOWS_H
          # include <windows.h>
@@ -1278,6 +1304,7 @@
        octave_cv_qt_opengl_ok=yes,
        octave_cv_qt_opengl_ok=no)
      CPPFLAGS="$ac_octave_save_CPPFLAGS"
+     CXXFLAGS="$ac_octave_save_CXXFLAGS"
      AC_LANG_POP(C++)
   ])
   if test $octave_cv_qt_opengl_ok = yes; then
@@ -1289,6 +1316,288 @@
   fi
 ])
 dnl
+dnl Check whether Qt VERSION is present, supports QtOpenGL and
+dnl QScintilla and will work for Octave.
+dnl
+dnl OCTAVE_CHECK_QT_VERSION(VERSION)
+dnl
+AC_DEFUN([OCTAVE_CHECK_QT_VERSION], [AC_MSG_CHECKING([Qt version $1])
+  QT_CPPFLAGS=
+  QT_LDFLAGS=
+  QT_LIBS=
+
+  qt_version="$1";
+
+  build_qt_gui=no
+  build_qt_graphics=no
+  use_qscintilla=no
+  win32_terminal=no
+
+  warn_qt_libraries=""
+  warn_qt_version=""
+  warn_qt_tools=""
+  warn_qt_setlocale=""
+  warn_qt_setvbuf=""
+  warn_qt_lib_fcns=""
+  warn_qt_abstract_item_model=""
+  warn_qt_opengl=""
+  warn_qscintilla=""
+
+  ## Check for Qt libraries
+  case "$qt_version" in
+    4)
+      QT_MODULES="QtCore QtGui QtNetwork QtOpenGL"
+      LIBQSCINTILLA=qscintilla2
+    ;;
+    5)
+      QT_MODULES="Qt5Core Qt5Gui Qt5Network Qt5OpenGL"
+      LIBQSCINTILLA=qt5scintilla2
+    ;;
+    *)
+      AC_MSG_ERROR([Unrecognized Qt version $qt_version])
+    ;;
+  esac
+
+  PKG_CHECK_MODULES(QT, [$QT_MODULES],
+    [],
+    [check_qt=no
+     warn_qt_libraries="Qt libraries not found; disabling Qt GUI"])
+
+  if test $check_qt = yes; then
+    ## Retrieve Qt compilation and linker flags
+    QT_CPPFLAGS="`$PKG_CONFIG --cflags-only-I $QT_MODULES`"
+    QT_LDFLAGS="`$PKG_CONFIG --libs-only-L $QT_MODULES`"
+    QT_LIBS="`$PKG_CONFIG --libs-only-l $QT_MODULES`"
+
+    case $host_os in
+      *darwin*)
+        ## Qt might be installed in framework
+        if test -z "$QT_LIBS"; then
+          QT_LDFLAGS="`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\n' | $GREP -e '-F' | uniq | tr '\n' ' '`"
+          QT_LIBS="`$PKG_CONFIG --libs-only-other $QT_MODULES | tr ' ' '\n' | $GREP -v -e '-F' | uniq | tr '\n' ' '`"
+          ## Enabling link_all_deps works around libtool's imperfect handling
+          ## of the -F flag
+          AM_CONDITIONAL([AMCOND_LINK_ALL_DEPS],
+                         [test $link_all_deps = yes || test -n "$QT_LDFLAGS"])
+        fi
+      ;;
+    esac
+
+    if test $qt_version = 4; then
+      ## Check for Qt4
+      if ! `$PKG_CONFIG --atleast-version=4.0.0 QtCore`; then
+        check_qt=no
+        warn_qt_version="Qt >= 4.0.0 not found; disabling Qt GUI"
+      fi
+    fi
+  fi
+
+  if test $check_qt = yes; then
+    AC_CHECK_TOOLS(MOC, [moc-qt$qt_version])
+    AC_CHECK_TOOLS(UIC, [uic-qt$qt_version])
+    AC_CHECK_TOOLS(RCC, [rcc-qt$qt_version])
+    AC_CHECK_TOOLS(LRELEASE, [lrelease-qt$qt_version])
+
+    if test -z "$MOC" || test -z "$UIC" || test -z "$RCC" || test -z "$LRELEASE"; then
+      AC_CHECK_TOOLS(QTCHOOSER, [qtchooser])
+
+      if test -z "$MOC"; then
+        AC_CHECK_TOOLS(MOC, [moc])
+        if test -n "$QTCHOOSER"; then
+          MOCFLAGS="-qt$qt_version"
+        fi
+      fi
+      if test -z "$UIC"; then
+        AC_CHECK_TOOLS(UIC, [uic])
+        if test -n "$QTCHOOSER"; then
+          UICFLAGS="-qt$qt_version"
+        fi
+      fi
+      if test -z "$RCC"; then
+        AC_CHECK_TOOLS(RCC, [rcc])
+        if test -n "$QTCHOOSER"; then
+          RCCFLAGS="-qt$qt_version"
+        fi
+      fi
+      if test -z "$LRELEASE"; then
+        AC_CHECK_TOOLS(LRELEASE, [lrelease])
+        if test -n "$QTCHOOSER"; then
+          LRELEASEFLAGS="-qt$qt_version"
+        fi
+      fi
+    fi
+
+    if test -n "$MOC" && test -n "$UIC" && test -n "$RCC" && test -n "$LRELEASE"; then
+      AC_DEFINE(HAVE_QT, 1,
+        [Define to 1 if Qt is available (libraries, developer header files, utility programs (moc, uic, rcc, and lrelease))])
+    else
+      warn_qt_tools="one or more of the Qt utility programs moc, uic, rcc, and lrelease not found; disabling Qt GUI"
+      check_qt=no
+    fi
+  fi
+
+  if test $check_qt = yes; then
+    AC_CHECK_FUNCS([setlocale], [],
+      [check_qt=no
+       warn_qt_setlocale="setlocale not found; disabling Qt GUI"])
+  fi
+
+  if test $check_qt = yes; then
+    case $host_os in
+      mingw* | msdosmsvc*)
+        AC_CHECK_FUNCS([setvbuf], [win32_terminal=yes],
+          [check_qt=no
+           warn_qt_setvbuf="setvbuf not found; disabling Qt GUI"])
+      ;;
+      *)
+        AC_CHECK_HEADERS([pty.h libutil.h util.h])
+        AC_SEARCH_LIBS([openpty], [util],
+          [AC_DEFINE(HAVE_OPENPTY, [], [Define whether openpty exists])])
+        AC_CHECK_FUNCS([chmod chown ftruncate mmap munmap], [],
+          [check_qt=no
+           warn_qt_lib_fcns="At least one of chmod, chown, ftruncate, mmap, and munmap not found; disabling Qt GUI"])
+      ;;
+    esac
+  fi
+
+  if test $check_qt = yes; then
+    OCTAVE_CHECK_FUNC_QABSTRACTITEMMODEL_BEGINRESETMODEL
+
+    if test $octave_cv_func_qabstractitemmodel_beginresetmodel = no; then
+      check_qt=no
+      warn_qt_abstract_item_model="QAbstractItemModel::beginResetModel not found; disabling Qt GUI"
+    fi
+  fi
+
+  if test $check_qt = yes; then
+    ## We have what we need to build the Qt GUI.  The remaining
+    ## checks below are for optional features related to the Qt GUI.
+    build_qt_gui=yes
+  fi
+
+  if test $check_qt = yes; then
+    OCTAVE_CHECK_QFONT_MONOSPACE
+    OCTAVE_CHECK_QFONT_FORCE_INTEGER_METRICS
+    OCTAVE_CHECK_FUNC_QTABWIDGET_SETMOVABLE
+
+    if test -n "$OPENGL_LIBS"; then
+      OCTAVE_CHECK_QT_OPENGL_OK([build_qt_graphics=yes],
+        [warn_qt_opengl="Qt does not work with the OpenGL libs (GL and GLU); disabling OpenGL graphics with Qt GUI"])
+
+      if test $build_qt_graphics = yes; then
+        AC_DEFINE(HAVE_QT_GRAPHICS, 1, [Define to 1 if Qt works with OpenGL libs (GL and GLU)])
+      fi
+    fi
+
+    ## Check for Qscintilla library which is used in the Qt GUI editor.
+    AC_CACHE_CHECK([whether Qscintilla library is installed],
+      [octave_cv_lib_qscintilla],
+      [save_CPPFLAGS="$CPPFLAGS"
+      save_CXXFLAGS="$CXXFLAGS"
+      save_LDFLAGS="$LDFLAGS"
+      save_LIBS="$LIBS"
+      CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+      CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
+      LDFLAGS="$QT_LDFLAGS $LDFLAGS"
+      LIBS="$QT_LIBS -l$LIBQSCINTILLA"
+      AC_LANG_PUSH(C++)
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+        #include <Qsci/qscilexersql.h>
+        ]], [[
+        QsciLexerSQL sqlLexer(0);
+        ]])],
+        octave_cv_lib_qscintilla=yes,
+        octave_cv_lib_qscintilla=no)
+      CPPFLAGS="$save_CPPFLAGS"
+      CXXFLAGS="$save_CXXFLAGS"
+      LDFLAGS="$save_LDFLAGS"
+      LIBS="$save_LIBS"
+      AC_LANG_POP([C++])
+    ])
+
+    if test $octave_cv_lib_qscintilla = no; then
+      warn_qscintilla="Qscintilla library not found; disabling built-in Qt GUI editor"
+    else
+      ## Let's assume Qscintilla library is at the same location as
+      ## other regular Qt libraries.
+      QT_LIBS="$QT_LIBS -l$LIBQSCINTILLA"
+      OCTAVE_CHECK_QSCINTILLA_VERSION
+      AC_DEFINE(HAVE_QSCINTILLA, 1,
+        [Define to 1 if the QScintilla library and header files are available])
+
+      save_CPPFLAGS="$CPPFLAGS"
+      save_CXXFLAGS="$CXXFLAGS"
+      CPPFLAGS="$QT_CPPFLAGS $CXXPICFLAG $CPPFLAGS"
+      CXXFLAGS="$CXXPICFLAG $CXXFLAGS"
+      AC_LANG_PUSH(C++)
+      AC_CHECK_HEADERS([Qsci/qscilexeroctave.h Qsci/qscilexermatlab.h])
+      AC_LANG_POP(C++)
+      CPPFLAGS="$save_CPPFLAGS"
+      CXXFLAGS="$save_CXXFLAGS"
+
+      OCTAVE_CHECK_FUNC_SETPLACEHOLDERTEXT
+      OCTAVE_CHECK_FUNC_QSCI_FINDSELECTION
+      use_qscintilla=yes
+    fi
+  fi
+  AC_SUBST(MOCFLAGS)
+  AC_SUBST(UICFLAGS)
+  AC_SUBST(RCCFLAGS)
+  AC_SUBST(LRELEASEFLAGS)
+  AC_SUBST(QT_CPPFLAGS)
+  AC_SUBST(QT_LDFLAGS)
+  AC_SUBST(QT_LIBS)
+])
+dnl
+dnl OCTAVE_CHECK_QT
+dnl
+AC_DEFUN([OCTAVE_CHECK_QT], [
+  octave_qt_versions="$1"
+  if test $check_qt = yes; then
+    for ver in $octave_qt_versions; do
+      OCTAVE_CHECK_QT_VERSION([$ver])
+      if test $build_qt_gui = yes; then
+        break
+      fi
+    done
+
+    if test $build_qt_gui = no; then
+      if test -n "$warn_qt_libraries"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qt_libraries])
+      fi
+      if test -n "$warn_qt_version"; then
+          OCTAVE_CONFIGURE_WARNING([warn_qt_version])
+      fi
+      if test -n "$warn_qt_tools"; then
+          OCTAVE_CONFIGURE_WARNING([warn_qt_tools])
+      fi
+      if test -n "$warn_qt_setlocale"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qt_setlocale])
+      fi
+      if test -n "$warn_qt_setvbuf"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qt_setvbuf])
+      fi
+      if test -n "$warn_qt_lib_fcns"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qt_lib_fcns])
+      fi
+      if test -n "$warn_qt_abstract_item_model"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qt_abstract_item_model])
+      fi
+      if test -n "$warn_qt_opengl"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qt_opengl])
+      fi
+      if test -n "$warn_qscintilla"; then
+        OCTAVE_CONFIGURE_WARNING([warn_qscintilla])
+      fi
+    fi
+  fi
+
+  AM_CONDITIONAL([AMCOND_BUILD_QT_GUI], [test $build_qt_gui = yes])
+  AM_CONDITIONAL([AMCOND_BUILD_QT_GRAPHICS], [test $build_qt_graphics = yes])
+  AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test $use_qscintilla = yes])
+  AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes])
+])
+dnl
 dnl Check if the default Fortran INTEGER is 64 bits wide.
 dnl
 AC_DEFUN([OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER], [
# HG changeset patch
# User Barbara Locsi <locsi.barbara@gmail.com>
# Date 1470289831 -7200
#      Thu Aug 04 07:50:31 2016 +0200
# Node ID 63b41167ef1efc33b2221df28d88f8d81ed4dcb3
# Parent  66dd260512a441f9ed70c5ab13fc296f4b8153bb
gsvd: new function imported from Octave-Forge linear-algebra package.

* libinterp/corefcn/gsvd.cc: New function to the interpreter. Imported
from the linear-algebra package.
* CmplxGSVD.cc, CmplxGSVD.h, dbleGSVD.cc, dbleGSVD.h: new classes
imported from the linear-algebra package to compute gsvd of Matrix
and ComplexMatrix.
* liboctave/operators/mx-defs.h, liboctave/operators/mx-ext.h: use new
classes.
* libinterp/corefcn/module.mk, liboctave/numeric/module.mk: Add to the
* scripts/help/__unimplemented__.m: Remove "gsvd" from list.
* doc/interpreter/linalg.txi: Add to manual.
build system.
* NEWS: Add function to list of new functions for 4.2.

diff -r 66dd260512a4 -r 63b41167ef1e NEWS
--- a/NEWS	Tue Aug 09 14:41:52 2016 -0400
+++ b/NEWS	Thu Aug 04 07:50:31 2016 +0200
@@ -113,6 +113,7 @@
       deg2rad
       dialog
       evalc
+      gsvd
       hash
       im2double
       localfunctions
diff -r 66dd260512a4 -r 63b41167ef1e doc/interpreter/linalg.txi
--- a/doc/interpreter/linalg.txi	Tue Aug 09 14:41:52 2016 -0400
+++ b/doc/interpreter/linalg.txi	Thu Aug 04 07:50:31 2016 +0200
@@ -108,6 +108,8 @@
 
 @DOCSTRING(givens)
 
+@DOCSTRING(gsvd)
+
 @DOCSTRING(planerot)
 
 @DOCSTRING(inv)
diff -r 66dd260512a4 -r 63b41167ef1e libinterp/corefcn/gsvd.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/gsvd.cc	Thu Aug 04 07:50:31 2016 +0200
@@ -0,0 +1,500 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006, 2010 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "defun.h"
+#include "error.h"
+#include "gripes.h"
+#include "pr-output.h"
+#include "utils.h"
+#include "ovl.h"
+
+#include "CmplxGSVD.h"
+#include "dbleGSVD.h"
+
+DEFUN (gsvd, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn {Loadable Function} {@var{s} =} gsvd (@var{a}, @var{b})
+@deftypefnx {Loadable Function} {[@var{u}, @var{v}, @var{c}, @var{s}, @var{x} [, @var{r}]] =} gsvd (@var{a}, @var{b})
+@cindex generalised singular value decomposition
+Compute the generalised singular value decomposition of (@var{a}, @var{b}):
+@iftex
+@tex
+$$
+ U^H A X = [I 0; 0 C] [0 R]
+ V^H B X = [0 S; 0 0] [0 R]
+ C*C + S*S = eye(columns(A))
+ I and 0 are padding matrices of suitable size
+ R is upper triangular
+$$
+@end tex
+@end iftex
+@ifinfo
+
+@example
+u' * a * x = [I 0; 0 c] * [0 r]
+v' * b * x = [0 s; 0 0] * [0 r]
+c * c + s * s = eye(columns(a))
+I and 0 are padding matrices of suitable size
+r is upper triangular
+@end example
+@end ifinfo
+
+The function @code{gsvd} normally returns the vector of generalised singular
+values
+@iftex
+@tex
+diag(C)./diag(S).
+@end tex
+@end iftex
+@ifinfo
+diag(r)./diag(s).
+@end ifinfo
+If asked for five return values, it computes
+@iftex
+@tex
+$U$, $V$, and $X$.
+@end tex
+@end iftex
+@ifinfo
+U, V, and X.
+@end ifinfo
+With a sixth output argument, it also returns
+@iftex
+@tex
+R,
+@end tex
+@end iftex
+@ifinfo
+r,
+@end ifinfo
+The common upper triangular right term. Other authors, like S. Van Huffel,
+define this transformation as the simulatenous diagonalisation of the
+input matrices, this can be achieved by multiplying 
+@iftex
+@tex
+X
+@end tex
+@end iftex
+@ifinfo
+x
+@end ifinfo
+by the inverse of
+@iftex
+@tex
+[I 0; 0 R].
+@end tex
+@end iftex
+@ifinfo
+[I 0; 0 r].
+@end ifinfo
+
+For example,
+
+@example
+gsvd (hilb (3), [1 2 3; 3 2 1])
+@end example
+
+@noindent
+returns
+
+@example
+ans =
+
+  0.1055705
+  0.0031759
+@end example
+
+@noindent
+and
+
+@example
+[u, v, c, s, x, r] = gsvd (hilb (3),  [1 2 3; 3 2 1])
+@end example
+
+@noindent
+returns
+
+@example
+u =
+
+  -0.965609   0.240893   0.097825
+  -0.241402  -0.690927  -0.681429
+  -0.096561  -0.681609   0.725317
+
+v =
+
+  -0.41974   0.90765
+  -0.90765  -0.41974
+
+c =
+
+   0.10499   0.00000
+   0.00000   0.00318
+
+s =
+   0.99447   0.00000
+   0.00000   0.99999
+x =
+
+   0.408248   0.902199   0.139179
+  -0.816497   0.429063  -0.386314
+   0.408248  -0.044073  -0.911806
+
+r =
+  -0.14093  -1.24345   0.43737
+   0.00000  -3.90043   2.57818
+   0.00000   0.00000  -2.52599
+
+@end example
+
+The code is a wrapper to the corresponding Lapack dggsvd and zggsvd routines.
+
+@end deftypefn */)
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+
+  if (nargin < 2 || nargin > 2 || (nargout > 1 && (nargout < 5 || nargout > 6)))
+    {
+      print_usage ();
+      return retval;
+    }
+
+  octave_value argA = args(0), argB = args(1);
+
+  octave_idx_type nr = argA.rows ();
+  octave_idx_type nc = argA.columns ();
+
+//  octave_idx_type  nn = argB.rows ();
+  octave_idx_type  np = argB.columns ();
+  
+  if (nr == 0 || nc == 0)
+    {
+      if (nargout == 5)
+          retval = ovl (identity_matrix (nc, nc), identity_matrix (nc, nc),
+                        Matrix (nr, nc), identity_matrix (nr, nr),
+                        identity_matrix (nr, nr));
+      else if (nargout == 6)
+          retval = ovl (identity_matrix (nc, nc), identity_matrix (nc, nc),
+                        Matrix (nr, nc), identity_matrix (nr, nr),
+                        identity_matrix (nr, nr),
+                        identity_matrix (nr, nr));
+      else
+        retval = ovl (Matrix (0, 1));
+    }
+  else
+    {
+      if ((nc != np))
+        {
+          print_usage ();
+          return retval;
+        }
+
+      GSVD::type type = ((nargout == 0 || nargout == 1)
+                        ? GSVD::sigma_only
+                        : (nargout > 5) ? GSVD::std : GSVD::economy );
+
+      if (argA.is_real_type () && argB.is_real_type ())
+        {
+          Matrix tmpA = argA.matrix_value ();
+          Matrix tmpB = argB.matrix_value ();
+
+          if (! error_state)
+            {
+              if (tmpA.any_element_is_inf_or_nan ())
+                {
+                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  return retval;
+                }
+              
+              if (tmpB.any_element_is_inf_or_nan ())
+                {
+                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  return retval;
+                }
+
+              GSVD result (tmpA, tmpB, type);
+
+              // DiagMatrix sigma = result.singular_values ();
+
+              if (nargout == 0 || nargout == 1)
+                {
+                  DiagMatrix sigA =  result.singular_values_A ();
+                  DiagMatrix sigB =  result.singular_values_B ();
+                  for (int i = sigA.rows() - 1; i >=0; i--)
+                    sigA.dgxelem(i) /= sigB.dgxelem(i);
+                  retval = ovl (sigA.diag());
+                }
+              else
+                { 
+                  if (nargout > 5)
+                    retval = ovl (result.left_singular_matrix_A (),
+                                  result.left_singular_matrix_B (),
+                                  result.singular_values_A (),
+                                  result.singular_values_B (),
+                                  result.right_singular_matrix (),
+                                  result.R_matrix ());
+                  else
+                    retval = ovl (result.left_singular_matrix_A (),
+                                  result.left_singular_matrix_B (),
+                                  result.singular_values_A (),
+                                  result.singular_values_B (),
+                                  result.right_singular_matrix ());
+                }
+            }
+        }
+      else if (argA.is_complex_type () || argB.is_complex_type ())
+        {
+          ComplexMatrix ctmpA = argA.complex_matrix_value ();
+          ComplexMatrix ctmpB = argB.complex_matrix_value ();
+
+          if (! error_state)
+            {
+              if (ctmpA.any_element_is_inf_or_nan ())
+                {
+                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  return retval;
+                }
+              if (ctmpB.any_element_is_inf_or_nan ())
+                {
+                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  return retval;
+                }
+
+              ComplexGSVD result (ctmpA, ctmpB, type);
+
+              // DiagMatrix sigma = result.singular_values ();
+
+              if (nargout == 0 || nargout == 1)
+                {
+                  DiagMatrix sigA =  result.singular_values_A ();
+                  DiagMatrix sigB =  result.singular_values_B ();
+                  for (int i = sigA.rows() - 1; i >=0; i--)
+                    sigA.dgxelem(i) /= sigB.dgxelem(i);
+                  retval = ovl (sigA.diag());
+                }
+              else
+                {
+                  if (nargout > 5)
+                    retval = ovl (result.left_singular_matrix_A (),
+                                  result.left_singular_matrix_B (),
+                                  result.singular_values_A (),
+                                  result.singular_values_B (),
+                                  result.right_singular_matrix (),
+                                  result.R_matrix ());
+                  else
+                    retval = ovl (result.left_singular_matrix_A (),
+                                  result.left_singular_matrix_B (),
+                                  result.singular_values_A (),
+                                  result.singular_values_B (),
+                                  result.right_singular_matrix ());
+                }
+            }
+        }
+      else
+        {
+          gripe_wrong_type_arg ("gsvd", argA);
+          gripe_wrong_type_arg ("gsvd", argB);
+          return retval;
+        }
+    }
+
+  return retval;
+}
+
+/*
+%# a few tests for gsvd.m
+%!shared A, A0, B, B0, U, V, C, S, X, R, D1, D2
+
+%! A0=randn(5, 3); B0=diag([1 2 4]);
+%! A = A0; B = B0;
+%! # disp('Full rank, 5x3 by 3x3 matrices');
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 3); D1(1:3, 1:3) = C;
+%! D2 = S;
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('A 5x3 full rank, B 3x3 rank deficient');
+%! B(2, 2) = 0;
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C;
+%! D2 = [zeros(2, 1) S; zeros(1, 3)];
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('A 5x3 rank deficient, B 3x3 full rank');
+%! B = B0;
+%! A(:, 3) = 2*A(:, 1) - A(:, 2);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 3); D1(1:3, 1:3) = C;
+%! D2 = S;
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp("A 5x3, B 3x3, [A' B'] rank deficient");
+%! B(:, 3) = 2*B(:, 1) - B(:, 2);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 2); D1(1:2, 1:2) = C;
+%! D2 = [S; zeros(1, 2)];
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*[zeros(2, 1) R]) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*[zeros(2, 1) R]) <= 1e-6)
+
+%! # now, A is 3x5
+%! A = A0.'; B0=diag([1 2 4 8 16]); B = B0;
+%! # disp('Full rank, 3x5 by 5x5 matrices');
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = [C zeros(3,2)];
+%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; 
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('A 5x3 full rank, B 5x5 rank deficient');
+%! B(2, 2) = 0;
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C;
+%! D2 = zeros(5, 5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye(2);
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('A 3x5 rank deficient, B 5x5 full rank');
+%! B = B0;
+%! A(3, :) = 2*A(1, :) - A(2, :);
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(3, 5); D1(1:3, 1:3) = C;
+%! D2 = zeros(5, 5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye(2);
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp("A 5x3, B 5x5, [A' B'] rank deficient");
+%! A = A0.'; B = B0.';
+%! A(:, 3) = 2*A(:, 1) - A(:, 2);
+%! B(:, 3) = 2*B(:, 1) - B(:, 2);
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R]=gsvd(A, B);
+%! D1 = zeros(3, 4); D1(1:3, 1:3) = C;
+%! D2 = eye(4); D2(1:3, 1:3) = S; D2(5,:) = 0;
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*[zeros(4, 1) R]) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*[zeros(4, 1) R]) <= 1e-6)
+
+%! A0 = A0 +j * randn(5, 3); B0 =  B0=diag([1 2 4]) + j*diag([4 -2 -1]);
+%! A = A0; B = B0;
+%! # disp('Complex: Full rank, 5x3 by 3x3 matrices');
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 3); D1(1:3, 1:3) = C;
+%! D2 = S;
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('Complex: A 5x3 full rank, B 3x3 rank deficient');
+%! B(2, 2) = 0;
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C;
+%! D2 = [zeros(2, 1) S; zeros(1, 3)];
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('Complex: A 5x3 rank deficient, B 3x3 full rank');
+%! B = B0;
+%! A(:, 3) = 2*A(:, 1) - A(:, 2);
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 3); D1(1:3, 1:3) = C;
+%! D2 = S;
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp("Complex: A 5x3, B 3x3, [A' B'] rank deficient");
+%! B(:, 3) = 2*B(:, 1) - B(:, 2);
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(5, 2); D1(1:2, 1:2) = C;
+%! D2 = [S; zeros(1, 2)];
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*[zeros(2, 1) R]) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*[zeros(2, 1) R]) <= 1e-6)
+
+%! # now, A is 3x5
+%! A = A0.'; B0=diag([1 2 4 8 16])+j*diag([-5 4 -3 2 -1]); 
+%! B = B0;
+%! # disp('Complex: Full rank, 3x5 by 5x5 matrices');
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = [C zeros(3,2)];
+%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; 
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('Complex: A 5x3 full rank, B 5x5 rank deficient');
+%! B(2, 2) = 0;
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C;
+%! D2 = zeros(5,5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye(2);
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp('Complex: A 3x5 rank deficient, B 5x5 full rank');
+%! B = B0;
+%! A(3, :) = 2*A(1, :) - A(2, :);
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R] = gsvd(A, B);
+%! D1 = zeros(3, 5); D1(1:3, 1:3) = C;
+%! D2 = zeros(5,5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye(2);
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*R) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*R) <= 1e-6)
+
+%! # disp("Complex: A 5x3, B 5x5, [A' B'] rank deficient");
+%! A = A0.'; B = B0.';
+%! A(:, 3) = 2*A(:, 1) - A(:, 2);
+%! B(:, 3) = 2*B(:, 1) - B(:, 2);
+%! # disp([rank(A) rank(B) rank([A' B'])]);
+%! [U, V, C, S, X, R]=gsvd(A, B);
+%! D1 = zeros(3, 4); D1(1:3, 1:3) = C;
+%! D2 = eye(4); D2(1:3, 1:3) = S; D2(5,:) = 0;
+%!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
+%!assert(norm((U'*A*X)-D1*[zeros(4, 1) R]) <= 1e-6)
+%!assert(norm((V'*B*X)-D2*[zeros(4, 1) R]) <= 1e-6)
+
+ */
diff -r 66dd260512a4 -r 63b41167ef1e libinterp/corefcn/module.mk
--- a/libinterp/corefcn/module.mk	Tue Aug 09 14:41:52 2016 -0400
+++ b/libinterp/corefcn/module.mk	Thu Aug 04 07:50:31 2016 +0200
@@ -173,6 +173,7 @@
   libinterp/corefcn/gl2ps-print.cc \
   libinterp/corefcn/graphics.cc \
   libinterp/corefcn/gripes.cc \
+  libinterp/corefcn/gsvd.cc \
   libinterp/corefcn/hash.cc \
   libinterp/corefcn/help.cc \
   libinterp/corefcn/hess.cc \
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/numeric/CmplxGSVD.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/numeric/CmplxGSVD.cc	Thu Aug 04 07:50:31 2016 +0200
@@ -0,0 +1,287 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "CmplxGSVD.h"
+#include "f77-fcn.h"
+#include "lo-error.h"
+
+
+/* 
+   uncomment those lines to monitor k and l
+   #include "oct-obj.h"
+   #include "pager.h"
+*/
+
+extern "C"
+{
+  F77_RET_T
+  F77_FUNC (zggsvd, ZGGSVD)  
+   (
+     F77_CONST_CHAR_ARG_DECL, 	// JOBU    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL, 	// JOBV    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL, 	// JOBQ    (input) CHARACTER*1
+     const octave_idx_type&,	// M       (input) INTEGER
+     const octave_idx_type&,	// N       (input) INTEGER
+     const octave_idx_type&,	// P       (input) INTEGER
+     octave_idx_type &, 	// K       (output) INTEGER
+     octave_idx_type &,		// L       (output) INTEGER
+     Complex*,			// A       (input/output) COMPLEX*16 array, dimension (LDA,N)
+     const octave_idx_type&, 	// LDA     (input) INTEGER
+     Complex*, 			// B       (input/output) COMPLEX*16 array, dimension (LDB,N)
+     const octave_idx_type&, 	// LDB     (input) INTEGER
+     double*, 			// ALPHA   (output) DOUBLE PRECISION array, dimension (N)
+     double*, 			// BETA    (output) DOUBLE PRECISION array, dimension (N)
+     Complex*,			// U       (output) COMPLEX*16 array, dimension (LDU,M)
+     const octave_idx_type&,	// LDU     (input) INTEGER 
+     Complex*, 			// V       (output) COMPLEX*16 array, dimension (LDV,P)
+     const octave_idx_type&,	// LDV     (input) INTEGER
+     Complex*,			// Q       (output) COMPLEX*16 array, dimension (LDQ,N) 
+     const octave_idx_type&,	// LDQ     (input) INTEGER
+     Complex*, 			// WORK    (workspace) COMPLEX*16 array
+     double*,			// RWORK   (workspace) DOUBLE PRECISION array
+     int*,	 		// IWORK   (workspace/output) INTEGER array, dimension (N)
+     octave_idx_type&		// INFO    (output)INTEGER
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     );
+}
+
+ComplexMatrix
+ComplexGSVD::left_singular_matrix_A (void) const
+{
+  if (type_computed == GSVD::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+	("CmplxGSVD: U not computed because type == GSVD::sigma_only");
+      return ComplexMatrix ();
+    }
+  else
+    return left_smA;
+}
+
+ComplexMatrix
+ComplexGSVD::left_singular_matrix_B (void) const
+{
+  if (type_computed == GSVD::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+	("CmplxGSVD: V not computed because type == GSVD::sigma_only");
+      return ComplexMatrix ();
+    }
+  else
+    return left_smB;
+}
+
+ComplexMatrix
+ComplexGSVD::right_singular_matrix (void) const
+{
+  if (type_computed == GSVD::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+	("CmplxGSVD: X not computed because type == GSVD::sigma_only");
+      return ComplexMatrix ();
+    }
+  else
+    return right_sm;
+}
+
+ComplexMatrix
+ComplexGSVD::R_matrix (void) const
+{
+  if (type_computed != GSVD::std)
+    {
+      (*current_liboctave_error_handler)
+	("CmplxGSVD: R not computed because type != GSVD::std");
+      return ComplexMatrix ();
+    }
+  else
+    return R;
+}
+
+octave_idx_type
+ComplexGSVD::init (const ComplexMatrix& a, const ComplexMatrix& b, 
+		   GSVD::type gsvd_type)
+{
+  octave_idx_type info;
+
+  octave_idx_type m = a.rows ();
+  octave_idx_type n = a.cols ();
+  octave_idx_type p = b.rows ();
+  
+  ComplexMatrix atmp = a;
+  Complex *tmp_dataA = atmp.fortran_vec ();
+  
+  ComplexMatrix btmp = b;
+  Complex *tmp_dataB = btmp.fortran_vec ();
+
+  // octave_idx_type min_mn = m < n ? m : n;
+
+  char jobu = 'U';
+  char jobv = 'V';
+  char jobq = 'Q';
+
+  octave_idx_type nrow_u = m;
+  octave_idx_type nrow_v = p;
+  octave_idx_type nrow_q = n;
+
+  octave_idx_type k, l;
+
+  switch (gsvd_type)
+    {
+
+    case GSVD::sigma_only:
+
+      // Note:  for this case, both jobu and jobv should be 'N', but
+      // there seems to be a bug in dgesvd from Lapack V2.0.  To
+      // demonstrate the bug, set both jobu and jobv to 'N' and find
+      // the singular values of [eye(3), eye(3)].  The result is
+      // [-sqrt(2), -sqrt(2), -sqrt(2)].
+      //
+      // For Lapack 3.0, this problem seems to be fixed.
+
+      jobu = 'N';
+      jobv = 'N';
+      jobq = 'N';
+      nrow_u = nrow_v = nrow_q = 1;
+      break;
+      
+    default:
+      break;
+    }
+
+  type_computed = gsvd_type;
+
+  if (! (jobu == 'N' || jobu == 'O')) {
+    left_smA.resize (nrow_u, m);
+  }
+  
+  Complex *u = left_smA.fortran_vec ();
+
+  if (! (jobv == 'N' || jobv == 'O')) {
+    left_smB.resize (nrow_v, p);
+  }
+
+  Complex *v = left_smB.fortran_vec ();
+
+  if (! (jobq == 'N' || jobq == 'O')) {
+    right_sm.resize (nrow_q, n);
+  }
+  Complex *q = right_sm.fortran_vec ();  
+  
+  octave_idx_type lwork = 3*n;
+  lwork = lwork > m ? lwork : m;
+  lwork = (lwork > p ? lwork : p) + n;
+
+  Array<Complex>  work (dim_vector (lwork, 1));
+  Array<double>   alpha (dim_vector (n, 1));
+  Array<double>   beta (dim_vector (n, 1));
+  Array<double>   rwork(dim_vector (2*n, 1));
+  Array<int>      iwork (dim_vector (n, 1));
+
+  F77_XFCN (zggsvd, ZGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
+			     F77_CONST_CHAR_ARG2 (&jobv, 1),
+			     F77_CONST_CHAR_ARG2 (&jobq, 1),
+			     m, n, p, k, l, tmp_dataA, m, 
+			     tmp_dataB, p, alpha.fortran_vec (),
+			     beta.fortran_vec (), u, nrow_u, 
+			     v, nrow_v, q, nrow_q, work.fortran_vec (), 
+			     rwork.fortran_vec (), iwork.fortran_vec (), 
+			     info
+			     F77_CHAR_ARG_LEN (1)
+			     F77_CHAR_ARG_LEN (1)
+			     F77_CHAR_ARG_LEN (1)));
+  
+  if (f77_exception_encountered)
+    (*current_liboctave_error_handler) ("unrecoverable error in zggsvd");
+
+  if (info < 0) {
+    (*current_liboctave_error_handler) ("zggsvd.f: argument %d illegal", -info);
+  }  else { 
+    if (info > 0) {
+      (*current_liboctave_error_handler) ("zggsvd.f: Jacobi-type procedure failed to converge."); 
+    } else {
+      octave_idx_type i, j;
+      
+      if (GSVD::std == gsvd_type) {
+	R.resize(k+l, k+l); 
+	int astart = n-k-l;
+	if (m - k - l >=  0) {
+	  int astart = n-k-l;
+	  /*
+	   *  R is stored in A(1:K+L,N-K-L+1:N)
+	   */
+	  for (i = 0; i < k+l; i++) 	    
+	    for (j = 0; j < k+l; j++)
+	      R.xelem(i, j) = atmp.xelem(i, astart + j); 
+	} else {  
+	  /*
+	   *    (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N), 
+	   *    ( 0  R22 R23 )
+	   */
+
+	   for (i = 0; i < m; i++)
+	     for (j = 0; j < k+l; j++)
+	       R.xelem(i, j) = atmp.xelem(i, astart + j);
+	   /*
+	    * and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
+	    */
+	   for (i = k+l-1; i >=m; i--) {
+	     for (j = 0; j < m; j++)
+	       R.xelem(i, j) = 0.0;
+	     for (j = m; j < k+l; j++)
+	       R.xelem(i, j) = btmp.xelem(i - k, astart + j);
+	   }
+	}
+      }
+      /*
+	uncomment this to monitor k and l
+	octave_value tmp;
+	octave_stdout << "CmplxGSVD k: "; 
+	tmp = k;
+	tmp.print(octave_stdout);
+	octave_stdout << "\n";
+	octave_stdout << "CmplxGSVD l: "; 
+	tmp = l;
+	tmp.print(octave_stdout);
+	octave_stdout << "\n";
+      */
+
+      if (m-k-l >= 0) { 
+	// Fills in C and S
+	sigmaA.resize (l, l);
+	sigmaB.resize (l, l);
+	for (i = 0; i < l; i++) {
+	  sigmaA.dgxelem(i) = alpha.elem(k+i);
+	  sigmaB.dgxelem(i) = beta.elem(k+i);
+	} 
+      } else {
+	// Fills in C and S
+	sigmaA.resize (m-k, m-k);
+	sigmaB.resize (m-k, m-k);
+	for (i = 0; i < m-k; i++) {
+	  sigmaA.dgxelem(i) = alpha.elem(k+i);
+	  sigmaB.dgxelem(i) = beta.elem(k+i);
+	}
+      }
+    }
+  }
+  return info;
+}
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/numeric/CmplxGSVD.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/numeric/CmplxGSVD.h	Thu Aug 04 07:50:31 2016 +0200
@@ -0,0 +1,94 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#if !defined (octave_ComplexGSVD_h)
+#define octave_ComplexGSVD_h 1
+
+#include "octave-config.h"
+
+#include <iosfwd>
+
+#include "dDiagMatrix.h"
+#include "CMatrix.h"
+#include "dbleGSVD.h"
+
+class
+ComplexGSVD
+{
+public:
+
+  ComplexGSVD (void) { }
+
+  ComplexGSVD (const ComplexMatrix& a, const ComplexMatrix& b,  
+           GSVD::type gsvd_type = GSVD::economy) 
+    { 
+      init (a, b, gsvd_type); 
+    }
+
+  ComplexGSVD (const ComplexMatrix& a, const ComplexMatrix& b, 
+           octave_idx_type& info, GSVD::type gsvd_type = GSVD::economy)
+    {
+      info = init (a, b, gsvd_type);
+    }
+
+  ComplexGSVD (const ComplexGSVD& a)
+    : type_computed (a.type_computed),
+      sigmaA (a.sigmaA), sigmaB (a.sigmaB), 
+      left_smA (a.left_smA), left_smB (a.left_smB), right_sm (a.right_sm),
+      R(a.R) { }
+
+  ComplexGSVD& operator = (const ComplexGSVD& a)
+    {
+      if (this != &a)
+    {
+      type_computed = a.type_computed;
+      sigmaA = a.sigmaA;
+      sigmaB = a.sigmaB;
+      left_smA = a.left_smA;
+      left_smB = a.left_smB;
+      right_sm = a.right_sm;
+      R = a.R;
+    }
+
+      return *this;
+    }
+
+  ~ComplexGSVD (void) { }
+
+  DiagMatrix singular_values_A (void) const { return sigmaA; }
+  DiagMatrix singular_values_B (void) const { return sigmaB; }
+
+  ComplexMatrix left_singular_matrix_A (void) const;
+  ComplexMatrix left_singular_matrix_B (void) const;
+
+  ComplexMatrix right_singular_matrix (void) const;
+  ComplexMatrix R_matrix (void) const;
+
+  friend std::ostream&  operator << (std::ostream& os, const ComplexGSVD& a);
+
+private:
+
+  GSVD::type type_computed;
+
+  DiagMatrix sigmaA, sigmaB;
+  ComplexMatrix left_smA, left_smB;
+  ComplexMatrix right_sm, R;
+
+  octave_idx_type init (const ComplexMatrix& a, const ComplexMatrix& b, 
+            GSVD::type gsvd_type = GSVD::economy);
+};
+
+#endif
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/numeric/dbleGSVD.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/numeric/dbleGSVD.cc	Thu Aug 04 07:50:31 2016 +0200
@@ -0,0 +1,293 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "dbleGSVD.h"
+#include "f77-fcn.h"
+#include "lo-error.h"
+
+/*
+   uncomment those lines to monitor k and l
+   #include "oct-obj.h"
+   #include "pager.h"
+*/
+
+extern "C"
+{
+  F77_RET_T
+  F77_FUNC (dggsvd, DGGSVD)
+   (
+     F77_CONST_CHAR_ARG_DECL,   // JOBU    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL,   // JOBV    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL,   // JOBQ    (input) CHARACTER*1
+     const octave_idx_type&,    // M       (input) INTEGER
+     const octave_idx_type&,    // N       (input) INTEGER
+     const octave_idx_type&,    // P       (input) INTEGER
+     octave_idx_type &,         // K       (output) INTEGER
+     octave_idx_type &,         // L       (output) INTEGER
+     double*,                   // A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+     const octave_idx_type&,    // LDA     (input) INTEGER
+     double*,                   // B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
+     const octave_idx_type&,    // LDB     (input) INTEGER
+     double*,                   // ALPHA   (output) DOUBLE PRECISION array, dimension (N)
+     double*,                   // BETA    (output) DOUBLE PRECISION array, dimension (N)
+     double*,                   // U       (output) DOUBLE PRECISION array, dimension (LDU,M)
+     const octave_idx_type&,    // LDU     (input) INTEGER
+     double*,                   // V       (output) DOUBLE PRECISION array, dimension (LDV,P)
+     const octave_idx_type&,    // LDV     (input) INTEGER
+     double*,                   // Q       (output) DOUBLE PRECISION array, dimension (LDQ,N)
+     const octave_idx_type&,    // LDQ     (input) INTEGER
+     double*,                   // WORK    (workspace) DOUBLE PRECISION array
+     int*,                      // IWORK   (workspace/output) INTEGER array, dimension (N)
+     octave_idx_type&           // INFO    (output)INTEGER
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     );
+}
+
+Matrix
+GSVD::left_singular_matrix_A (void) const
+{
+  if (type_computed == GSVD::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+        ("dbleGSVD: U not computed because type == GSVD::sigma_only");
+      return Matrix ();
+    }
+  else
+    return left_smA;
+}
+
+Matrix
+GSVD::left_singular_matrix_B (void) const
+{
+  if (type_computed == GSVD::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+        ("dbleGSVD: V not computed because type == GSVD::sigma_only");
+      return Matrix ();
+    }
+  else
+    return left_smB;
+}
+
+Matrix
+GSVD::right_singular_matrix (void) const
+{
+  if (type_computed == GSVD::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+        ("dbleGSVD: X not computed because type == GSVD::sigma_only");
+      return Matrix ();
+    }
+  else
+    return right_sm;
+}
+Matrix
+GSVD::R_matrix (void) const
+{
+  if (type_computed != GSVD::std)
+    {
+      (*current_liboctave_error_handler)
+        ("dbleGSVD: R not computed because type != GSVD::std");
+      return Matrix ();
+    }
+  else
+    return R;
+}
+
+octave_idx_type
+GSVD::init (const Matrix& a, const Matrix& b, GSVD::type gsvd_type)
+{
+  octave_idx_type info;
+
+  octave_idx_type m = a.rows ();
+  octave_idx_type n = a.cols ();
+  octave_idx_type p = b.rows ();
+  
+  Matrix atmp = a;
+  double *tmp_dataA = atmp.fortran_vec ();
+  
+  Matrix btmp = b;
+  double *tmp_dataB = btmp.fortran_vec ();
+
+  // octave_idx_type min_mn = m < n ? m : n;
+
+  char jobu = 'U';
+  char jobv = 'V';
+  char jobq = 'Q';
+
+  octave_idx_type nrow_u = m;
+  octave_idx_type nrow_v = p;
+  octave_idx_type nrow_q = n;
+
+  octave_idx_type k, l;
+
+  switch (gsvd_type)
+    {
+
+    case GSVD::sigma_only:
+
+      // Note:  for this case, both jobu and jobv should be 'N', but
+      // there seems to be a bug in dgesvd from Lapack V2.0.  To
+      // demonstrate the bug, set both jobu and jobv to 'N' and find
+      // the singular values of [eye(3), eye(3)].  The result is
+      // [-sqrt(2), -sqrt(2), -sqrt(2)].
+      //
+      // For Lapack 3.0, this problem seems to be fixed.
+
+      jobu = 'N';
+      jobv = 'N';
+      jobq = 'N';
+      nrow_u = nrow_v = nrow_q = 1;
+      break;
+      
+    default:
+      break;
+    }
+
+  type_computed = gsvd_type;
+
+  if (! (jobu == 'N' || jobu == 'O')) {
+    left_smA.resize (nrow_u, m);
+  }
+  
+  double *u = left_smA.fortran_vec ();
+
+  if (! (jobv == 'N' || jobv == 'O')) {
+    left_smB.resize (nrow_v, p);
+  }
+
+  double *v = left_smB.fortran_vec ();
+
+  if (! (jobq == 'N' || jobq == 'O')) {
+    right_sm.resize (nrow_q, n);
+  }
+  double *q = right_sm.fortran_vec ();
+  
+  octave_idx_type lwork = 3*n;
+  lwork = lwork > m ? lwork : m;
+  lwork = (lwork > p ? lwork : p) + n;
+
+  Array<double> work (dim_vector (lwork, 1));
+  Array<double> alpha (dim_vector (n, 1));
+  Array<double> beta (dim_vector (n, 1));
+  Array<int>    iwork (dim_vector (n, 1));
+
+  F77_XFCN (dggsvd, DGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
+                             F77_CONST_CHAR_ARG2 (&jobv, 1),
+                             F77_CONST_CHAR_ARG2 (&jobq, 1),
+                             m, n, p, k, l, tmp_dataA, m,
+                             tmp_dataB, p, alpha.fortran_vec (),
+                             beta.fortran_vec (), u, nrow_u,
+                             v, nrow_v, q, nrow_q, work.fortran_vec (),
+                             iwork.fortran_vec (), info
+                             F77_CHAR_ARG_LEN (1)
+                             F77_CHAR_ARG_LEN (1)
+                             F77_CHAR_ARG_LEN (1)));
+  
+  if (f77_exception_encountered)
+    (*current_liboctave_error_handler) ("unrecoverable error in dggsvd");
+ 
+  if (info < 0) {
+    (*current_liboctave_error_handler) ("dggsvd.f: argument %d illegal", -info);
+  } else {
+    if (info > 0) {
+      (*current_liboctave_error_handler) ("dggsvd.f: Jacobi-type procedure failed to converge.");
+    } else {
+      octave_idx_type i, j;
+      
+      if (GSVD::std == gsvd_type) {
+        R.resize(k+l, k+l);
+        int astart = n-k-l;
+        if (m - k - l >=  0) {
+          int astart = n-k-l;
+          /*
+           *  R is stored in A(1:K+L,N-K-L+1:N)
+           */
+          for (i = 0; i < k+l; i++)
+            for (j = 0; j < k+l; j++)
+              R.xelem(i, j) = atmp.xelem(i, astart + j);
+        } else {
+          /*
+           *    (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N),
+           *    ( 0  R22 R23 )
+           */
+
+           for (i = 0; i < m; i++)
+             for (j = 0; j < k+l; j++)
+               R.xelem(i, j) = atmp.xelem(i, astart + j);
+           /*
+            * and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
+            */
+           for (i = k+l-1; i >=m; i--) {
+             for (j = 0; j < m; j++)
+               R.xelem(i, j) = 0.0;
+             for (j = m; j < k+l; j++)
+               R.xelem(i, j) = btmp.xelem(i - k, astart + j);
+           }
+        }
+      }
+      /*
+        uncomment this to monitor k and l
+        octave_value tmp;
+        octave_stdout << "dbleGSVD k: ";
+        tmp = k;
+        tmp.print(octave_stdout);
+        octave_stdout << "\n";
+        octave_stdout << "dbleGSVD l: ";
+        tmp = l;
+        tmp.print(octave_stdout);
+        octave_stdout << "\n";
+      */
+
+      if (m-k-l >= 0) {
+        // Fills in C and S
+        sigmaA.resize (l, l);
+        sigmaB.resize (l, l);
+        for (i = 0; i < l; i++) {
+          sigmaA.dgxelem(i) = alpha.elem(k+i);
+          sigmaB.dgxelem(i) = beta.elem(k+i);
+        }
+      } else {
+        // Fills in C and S
+        sigmaA.resize (m-k, m-k);
+        sigmaB.resize (m-k, m-k);
+        for (i = 0; i < m-k; i++) {
+          sigmaA.dgxelem(i) = alpha.elem(k+i);
+          sigmaB.dgxelem(i) = beta.elem(k+i);
+        }
+      }
+    }
+  }
+  return info;
+}
+
+std::ostream&
+operator << (std::ostream& os, const GSVD& a)
+{
+  os << a.left_singular_matrix_A () << "\n";
+  os << a.left_singular_matrix_B () << "\n";
+  os << a.singular_values_A () << "\n";
+  os << a.singular_values_B () << "\n";
+  os << a.right_singular_matrix () << "\n";
+
+  return os;
+}
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/numeric/dbleGSVD.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/numeric/dbleGSVD.h	Thu Aug 04 07:50:31 2016 +0200
@@ -0,0 +1,91 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#if !defined (octave_GSVD_h)
+#define octave_GSVD_h 1
+
+#include "octave-config.h"
+
+#include "dDiagMatrix.h"
+#include "dMatrix.h"
+
+class
+GSVD
+{
+public:
+
+  enum type
+    {
+      std,
+      economy,
+      sigma_only
+    };
+
+  GSVD (void) : sigmaA (), sigmaB (), left_smA (), left_smB (), right_sm () { }
+  GSVD (const Matrix& a, const Matrix& b, type gsvd_type = GSVD::economy) { init (a, b, gsvd_type); }
+
+  GSVD (const Matrix& a, const Matrix& b, octave_idx_type& info, type gsvd_type = GSVD::economy)
+    {
+      info = init (a, b, gsvd_type);
+    }
+
+  GSVD (const GSVD& a)
+    : type_computed (a.type_computed),
+      sigmaA (a.sigmaA), sigmaB (a.sigmaB), 
+      left_smA (a.left_smA), left_smB (a.left_smB), right_sm (a.right_sm),
+      R(a.R) { }
+
+  GSVD& operator = (const GSVD& a)
+    {
+      if (this != &a)
+    {
+      type_computed = a.type_computed;
+      sigmaA = a.sigmaA;
+      sigmaB = a.sigmaB;
+      left_smA = a.left_smA;
+      left_smB = a.left_smB;
+      right_sm = a.right_sm;
+      R = a.R;
+    }
+
+      return *this;
+    }
+
+  ~GSVD (void) { }
+
+  DiagMatrix singular_values_A (void) const { return sigmaA; }
+  DiagMatrix singular_values_B (void) const { return sigmaB; }
+
+  Matrix left_singular_matrix_A (void) const;
+  Matrix left_singular_matrix_B (void) const;
+
+  Matrix right_singular_matrix (void) const;
+  Matrix R_matrix (void) const;
+
+  friend std::ostream&  operator << (std::ostream& os, const GSVD& a);
+
+private:
+
+  GSVD::type type_computed;
+
+  DiagMatrix sigmaA, sigmaB;
+  Matrix left_smA, left_smB;
+  Matrix right_sm, R;
+
+  octave_idx_type init (const Matrix& a, const Matrix& b, type gsvd_type = economy);
+};
+
+#endif
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/numeric/module.mk
--- a/liboctave/numeric/module.mk	Tue Aug 09 14:41:52 2016 -0400
+++ b/liboctave/numeric/module.mk	Thu Aug 04 07:50:31 2016 +0200
@@ -8,6 +8,7 @@
 LIBOCTAVE_OPT_IN = $(LIBOCTAVE_OPT_INC:.h=.in)
 
 NUMERIC_INC = \
+  liboctave/numeric/CmplxGSVD.h \
   liboctave/numeric/CollocWt.h \
   liboctave/numeric/DAE.h \
   liboctave/numeric/DAEFunc.h \
@@ -16,6 +17,7 @@
   liboctave/numeric/DASPK.h \
   liboctave/numeric/DASRT.h \
   liboctave/numeric/DASSL.h \
+  liboctave/numeric/dbleGSVD.h \
   liboctave/numeric/DET.h \
   liboctave/numeric/EIG.h \
   liboctave/numeric/LSODE.h \
@@ -56,10 +58,12 @@
   liboctave/numeric/svd.h
 
 NUMERIC_SRC = \
+  liboctave/numeric/CmplxGSVD.cc \
   liboctave/numeric/CollocWt.cc \
   liboctave/numeric/DASPK.cc \
   liboctave/numeric/DASRT.cc \
   liboctave/numeric/DASSL.cc \
+  liboctave/numeric/dbleGSVD.cc \
   liboctave/numeric/EIG.cc \
   liboctave/numeric/LSODE.cc \
   liboctave/numeric/ODES.cc \
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/operators/mx-defs.h
--- a/liboctave/operators/mx-defs.h	Tue Aug 09 14:41:52 2016 -0400
+++ b/liboctave/operators/mx-defs.h	Thu Aug 04 07:50:31 2016 +0200
@@ -66,6 +66,8 @@
 
 class EIG;
 
+class GSVD;
+
 template <typename T> class hess;
 
 template <typename T> class schur;
diff -r 66dd260512a4 -r 63b41167ef1e liboctave/operators/mx-ext.h
--- a/liboctave/operators/mx-ext.h	Tue Aug 09 14:41:52 2016 -0400
+++ b/liboctave/operators/mx-ext.h	Thu Aug 04 07:50:31 2016 +0200
@@ -57,6 +57,12 @@
 
 #include "EIG.h"
 
+// Result of a Generalized Singular Value Decomposition.
+
+#include "dbleGSVD.h"
+#include "CmplxGSVD.h"
+
+
 // Result of an LU decomposition.
 
 #include "lu.h"
diff -r 66dd260512a4 -r 63b41167ef1e scripts/help/__unimplemented__.m
--- a/scripts/help/__unimplemented__.m	Tue Aug 09 14:41:52 2016 -0400
+++ b/scripts/help/__unimplemented__.m	Thu Aug 04 07:50:31 2016 +0200
@@ -49,11 +49,6 @@
       txt = ["exifread is deprecated.  " ...
              "The functionality is available in the imfinfo function."];
 
-    case "gsvd"
-      txt = ["gsvd is not currently part of core Octave.  ", ...
-             "See the linear-algebra package at ", ...
-             "@url{http://octave.sourceforge.net/linear-algebra/}."];
-
     case "funm"
       txt = ["funm is not currently part of core Octave.  ", ...
              "See the linear-algebra package at ", ...
@@ -658,7 +653,6 @@
   "graph",
   "graymon",
   "griddedInterpolant",
-  "gsvd",
   "guide",
   "h5create",
   "h5disp",
# HG changeset patch
# User Barbara Locsi <locsi.barbara@gmail.com>
# Date 1470758531 -7200
#      Tue Aug 09 18:02:11 2016 +0200
# Node ID 065a443757239e4fd8f0bc79f0f02fe736d32748
# Parent  63b41167ef1efc33b2221df28d88f8d81ed4dcb3
gsvd: reduce code duplication with templates.

* CmplxGSVD.cc, CmplxGSVD.h, dbleGSVD.cc, dbleGSVD.h: Remove files for
no longer existing classes.  Replaced by gsvd template class.  This
classes never existed in an Octave release, this was freshly imported
from Octave Forge so backwards compatibility is not an issue.
* liboctave/numeric/gsvd.h, liboctave/numeric/gsvd.cc: New files for gsvd
class template generated from CmplxGSVD.cc, CmplxGSVD.h, dbleGSVD.cc, and
dbleGSVD.h and converted to template.  Removed unused << operator, unused
constructor with &info, and commented code.  Only instantiated for Matrix
and ComplexMatrix, providing interface to DGGSVD and ZGGSVD.
* liboctave/numeric/module.mk: Update.
* mx-defs.h, mx-ext.h: Use new classes.

diff -r 63b41167ef1e -r 065a44375723 libinterp/corefcn/gsvd.cc
--- a/libinterp/corefcn/gsvd.cc	Thu Aug 04 07:50:31 2016 +0200
+++ b/libinterp/corefcn/gsvd.cc	Tue Aug 09 18:02:11 2016 +0200
@@ -1,5 +1,6 @@
 // Copyright (C) 1996, 1997 John W. Eaton
 // Copyright (C) 2006, 2010 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+// Copyright (C) 2016 Barbara Lócsi
 //
 // This program is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free Software
@@ -25,8 +26,17 @@
 #include "utils.h"
 #include "ovl.h"
 
-#include "CmplxGSVD.h"
-#include "dbleGSVD.h"
+#include "gsvd.h"
+
+template <typename T>
+static typename gsvd<T>::Type
+gsvd_type (int nargout)
+{
+  return ((nargout == 0 || nargout == 1)
+         ? gsvd<T>::Type::sigma_only
+         : (nargout > 5) ? gsvd<T>::Type::std : gsvd<T>::Type::economy);
+}
+
 
 DEFUN (gsvd, args, nargout,
        doc: /* -*- texinfo -*-
@@ -86,7 +96,7 @@
 @end ifinfo
 The common upper triangular right term. Other authors, like S. Van Huffel,
 define this transformation as the simulatenous diagonalisation of the
-input matrices, this can be achieved by multiplying 
+input matrices, this can be achieved by multiplying
 @iftex
 @tex
 X
@@ -185,7 +195,7 @@
 
 //  octave_idx_type  nn = argB.rows ();
   octave_idx_type  np = argB.columns ();
-  
+
   if (nr == 0 || nc == 0)
     {
       if (nargout == 5)
@@ -208,10 +218,6 @@
           return retval;
         }
 
-      GSVD::type type = ((nargout == 0 || nargout == 1)
-                        ? GSVD::sigma_only
-                        : (nargout > 5) ? GSVD::std : GSVD::economy );
-
       if (argA.is_real_type () && argB.is_real_type ())
         {
           Matrix tmpA = argA.matrix_value ();
@@ -221,17 +227,17 @@
             {
               if (tmpA.any_element_is_inf_or_nan ())
                 {
-                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
-                  return retval;
-                }
-              
-              if (tmpB.any_element_is_inf_or_nan ())
-                {
-                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  error ("gsvd: cannot take gsvd of matrix containing Inf or NaN values");
                   return retval;
                 }
 
-              GSVD result (tmpA, tmpB, type);
+              if (tmpB.any_element_is_inf_or_nan ())
+                {
+                  error ("gsvd: cannot take gsvd of matrix containing Inf or NaN values");
+                  return retval;
+                }
+
+              gsvd<Matrix> result (tmpA, tmpB, gsvd_type<Matrix> (nargout));
 
               // DiagMatrix sigma = result.singular_values ();
 
@@ -244,7 +250,7 @@
                   retval = ovl (sigA.diag());
                 }
               else
-                { 
+                {
                   if (nargout > 5)
                     retval = ovl (result.left_singular_matrix_A (),
                                   result.left_singular_matrix_B (),
@@ -270,16 +276,16 @@
             {
               if (ctmpA.any_element_is_inf_or_nan ())
                 {
-                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  error ("gsvd: cannot take gsvd of matrix containing Inf or NaN values");
                   return retval;
                 }
               if (ctmpB.any_element_is_inf_or_nan ())
                 {
-                  error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values");
+                  error ("gsvd: cannot take gsvd of matrix containing Inf or NaN values");
                   return retval;
                 }
 
-              ComplexGSVD result (ctmpA, ctmpB, type);
+              gsvd<ComplexMatrix> result (ctmpA, ctmpB, gsvd_type<ComplexMatrix> (nargout));
 
               // DiagMatrix sigma = result.singular_values ();
 
@@ -370,7 +376,7 @@
 
 %! [U, V, C, S, X, R] = gsvd(A, B);
 %! D1 = [C zeros(3,2)];
-%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; 
+%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)];
 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
 %!assert(norm((U'*A*X)-D1*R) <= 1e-6)
 %!assert(norm((V'*B*X)-D2*R) <= 1e-6)
@@ -453,13 +459,13 @@
 %!assert(norm((V'*B*X)-D2*[zeros(2, 1) R]) <= 1e-6)
 
 %! # now, A is 3x5
-%! A = A0.'; B0=diag([1 2 4 8 16])+j*diag([-5 4 -3 2 -1]); 
+%! A = A0.'; B0=diag([1 2 4 8 16])+j*diag([-5 4 -3 2 -1]);
 %! B = B0;
 %! # disp('Complex: Full rank, 3x5 by 5x5 matrices');
 %! # disp([rank(A) rank(B) rank([A' B'])]);
 %! [U, V, C, S, X, R] = gsvd(A, B);
 %! D1 = [C zeros(3,2)];
-%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; 
+%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)];
 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6)
 %!assert(norm((U'*A*X)-D1*R) <= 1e-6)
 %!assert(norm((V'*B*X)-D2*R) <= 1e-6)
@@ -497,4 +503,4 @@
 %!assert(norm((U'*A*X)-D1*[zeros(4, 1) R]) <= 1e-6)
 %!assert(norm((V'*B*X)-D2*[zeros(4, 1) R]) <= 1e-6)
 
- */
+*/
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/CmplxGSVD.cc
--- a/liboctave/numeric/CmplxGSVD.cc	Thu Aug 04 07:50:31 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-// Copyright (C) 1996, 1997 John W. Eaton
-// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
-//
-// This program is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free Software
-// Foundation; either version 3 of the License, or (at your option) any later
-// version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-// details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, see <http://www.gnu.org/licenses/>.
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "CmplxGSVD.h"
-#include "f77-fcn.h"
-#include "lo-error.h"
-
-
-/* 
-   uncomment those lines to monitor k and l
-   #include "oct-obj.h"
-   #include "pager.h"
-*/
-
-extern "C"
-{
-  F77_RET_T
-  F77_FUNC (zggsvd, ZGGSVD)  
-   (
-     F77_CONST_CHAR_ARG_DECL, 	// JOBU    (input) CHARACTER*1
-     F77_CONST_CHAR_ARG_DECL, 	// JOBV    (input) CHARACTER*1
-     F77_CONST_CHAR_ARG_DECL, 	// JOBQ    (input) CHARACTER*1
-     const octave_idx_type&,	// M       (input) INTEGER
-     const octave_idx_type&,	// N       (input) INTEGER
-     const octave_idx_type&,	// P       (input) INTEGER
-     octave_idx_type &, 	// K       (output) INTEGER
-     octave_idx_type &,		// L       (output) INTEGER
-     Complex*,			// A       (input/output) COMPLEX*16 array, dimension (LDA,N)
-     const octave_idx_type&, 	// LDA     (input) INTEGER
-     Complex*, 			// B       (input/output) COMPLEX*16 array, dimension (LDB,N)
-     const octave_idx_type&, 	// LDB     (input) INTEGER
-     double*, 			// ALPHA   (output) DOUBLE PRECISION array, dimension (N)
-     double*, 			// BETA    (output) DOUBLE PRECISION array, dimension (N)
-     Complex*,			// U       (output) COMPLEX*16 array, dimension (LDU,M)
-     const octave_idx_type&,	// LDU     (input) INTEGER 
-     Complex*, 			// V       (output) COMPLEX*16 array, dimension (LDV,P)
-     const octave_idx_type&,	// LDV     (input) INTEGER
-     Complex*,			// Q       (output) COMPLEX*16 array, dimension (LDQ,N) 
-     const octave_idx_type&,	// LDQ     (input) INTEGER
-     Complex*, 			// WORK    (workspace) COMPLEX*16 array
-     double*,			// RWORK   (workspace) DOUBLE PRECISION array
-     int*,	 		// IWORK   (workspace/output) INTEGER array, dimension (N)
-     octave_idx_type&		// INFO    (output)INTEGER
-     F77_CHAR_ARG_LEN_DECL
-     F77_CHAR_ARG_LEN_DECL
-     F77_CHAR_ARG_LEN_DECL
-     );
-}
-
-ComplexMatrix
-ComplexGSVD::left_singular_matrix_A (void) const
-{
-  if (type_computed == GSVD::sigma_only)
-    {
-      (*current_liboctave_error_handler)
-	("CmplxGSVD: U not computed because type == GSVD::sigma_only");
-      return ComplexMatrix ();
-    }
-  else
-    return left_smA;
-}
-
-ComplexMatrix
-ComplexGSVD::left_singular_matrix_B (void) const
-{
-  if (type_computed == GSVD::sigma_only)
-    {
-      (*current_liboctave_error_handler)
-	("CmplxGSVD: V not computed because type == GSVD::sigma_only");
-      return ComplexMatrix ();
-    }
-  else
-    return left_smB;
-}
-
-ComplexMatrix
-ComplexGSVD::right_singular_matrix (void) const
-{
-  if (type_computed == GSVD::sigma_only)
-    {
-      (*current_liboctave_error_handler)
-	("CmplxGSVD: X not computed because type == GSVD::sigma_only");
-      return ComplexMatrix ();
-    }
-  else
-    return right_sm;
-}
-
-ComplexMatrix
-ComplexGSVD::R_matrix (void) const
-{
-  if (type_computed != GSVD::std)
-    {
-      (*current_liboctave_error_handler)
-	("CmplxGSVD: R not computed because type != GSVD::std");
-      return ComplexMatrix ();
-    }
-  else
-    return R;
-}
-
-octave_idx_type
-ComplexGSVD::init (const ComplexMatrix& a, const ComplexMatrix& b, 
-		   GSVD::type gsvd_type)
-{
-  octave_idx_type info;
-
-  octave_idx_type m = a.rows ();
-  octave_idx_type n = a.cols ();
-  octave_idx_type p = b.rows ();
-  
-  ComplexMatrix atmp = a;
-  Complex *tmp_dataA = atmp.fortran_vec ();
-  
-  ComplexMatrix btmp = b;
-  Complex *tmp_dataB = btmp.fortran_vec ();
-
-  // octave_idx_type min_mn = m < n ? m : n;
-
-  char jobu = 'U';
-  char jobv = 'V';
-  char jobq = 'Q';
-
-  octave_idx_type nrow_u = m;
-  octave_idx_type nrow_v = p;
-  octave_idx_type nrow_q = n;
-
-  octave_idx_type k, l;
-
-  switch (gsvd_type)
-    {
-
-    case GSVD::sigma_only:
-
-      // Note:  for this case, both jobu and jobv should be 'N', but
-      // there seems to be a bug in dgesvd from Lapack V2.0.  To
-      // demonstrate the bug, set both jobu and jobv to 'N' and find
-      // the singular values of [eye(3), eye(3)].  The result is
-      // [-sqrt(2), -sqrt(2), -sqrt(2)].
-      //
-      // For Lapack 3.0, this problem seems to be fixed.
-
-      jobu = 'N';
-      jobv = 'N';
-      jobq = 'N';
-      nrow_u = nrow_v = nrow_q = 1;
-      break;
-      
-    default:
-      break;
-    }
-
-  type_computed = gsvd_type;
-
-  if (! (jobu == 'N' || jobu == 'O')) {
-    left_smA.resize (nrow_u, m);
-  }
-  
-  Complex *u = left_smA.fortran_vec ();
-
-  if (! (jobv == 'N' || jobv == 'O')) {
-    left_smB.resize (nrow_v, p);
-  }
-
-  Complex *v = left_smB.fortran_vec ();
-
-  if (! (jobq == 'N' || jobq == 'O')) {
-    right_sm.resize (nrow_q, n);
-  }
-  Complex *q = right_sm.fortran_vec ();  
-  
-  octave_idx_type lwork = 3*n;
-  lwork = lwork > m ? lwork : m;
-  lwork = (lwork > p ? lwork : p) + n;
-
-  Array<Complex>  work (dim_vector (lwork, 1));
-  Array<double>   alpha (dim_vector (n, 1));
-  Array<double>   beta (dim_vector (n, 1));
-  Array<double>   rwork(dim_vector (2*n, 1));
-  Array<int>      iwork (dim_vector (n, 1));
-
-  F77_XFCN (zggsvd, ZGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-			     F77_CONST_CHAR_ARG2 (&jobv, 1),
-			     F77_CONST_CHAR_ARG2 (&jobq, 1),
-			     m, n, p, k, l, tmp_dataA, m, 
-			     tmp_dataB, p, alpha.fortran_vec (),
-			     beta.fortran_vec (), u, nrow_u, 
-			     v, nrow_v, q, nrow_q, work.fortran_vec (), 
-			     rwork.fortran_vec (), iwork.fortran_vec (), 
-			     info
-			     F77_CHAR_ARG_LEN (1)
-			     F77_CHAR_ARG_LEN (1)
-			     F77_CHAR_ARG_LEN (1)));
-  
-  if (f77_exception_encountered)
-    (*current_liboctave_error_handler) ("unrecoverable error in zggsvd");
-
-  if (info < 0) {
-    (*current_liboctave_error_handler) ("zggsvd.f: argument %d illegal", -info);
-  }  else { 
-    if (info > 0) {
-      (*current_liboctave_error_handler) ("zggsvd.f: Jacobi-type procedure failed to converge."); 
-    } else {
-      octave_idx_type i, j;
-      
-      if (GSVD::std == gsvd_type) {
-	R.resize(k+l, k+l); 
-	int astart = n-k-l;
-	if (m - k - l >=  0) {
-	  int astart = n-k-l;
-	  /*
-	   *  R is stored in A(1:K+L,N-K-L+1:N)
-	   */
-	  for (i = 0; i < k+l; i++) 	    
-	    for (j = 0; j < k+l; j++)
-	      R.xelem(i, j) = atmp.xelem(i, astart + j); 
-	} else {  
-	  /*
-	   *    (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N), 
-	   *    ( 0  R22 R23 )
-	   */
-
-	   for (i = 0; i < m; i++)
-	     for (j = 0; j < k+l; j++)
-	       R.xelem(i, j) = atmp.xelem(i, astart + j);
-	   /*
-	    * and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
-	    */
-	   for (i = k+l-1; i >=m; i--) {
-	     for (j = 0; j < m; j++)
-	       R.xelem(i, j) = 0.0;
-	     for (j = m; j < k+l; j++)
-	       R.xelem(i, j) = btmp.xelem(i - k, astart + j);
-	   }
-	}
-      }
-      /*
-	uncomment this to monitor k and l
-	octave_value tmp;
-	octave_stdout << "CmplxGSVD k: "; 
-	tmp = k;
-	tmp.print(octave_stdout);
-	octave_stdout << "\n";
-	octave_stdout << "CmplxGSVD l: "; 
-	tmp = l;
-	tmp.print(octave_stdout);
-	octave_stdout << "\n";
-      */
-
-      if (m-k-l >= 0) { 
-	// Fills in C and S
-	sigmaA.resize (l, l);
-	sigmaB.resize (l, l);
-	for (i = 0; i < l; i++) {
-	  sigmaA.dgxelem(i) = alpha.elem(k+i);
-	  sigmaB.dgxelem(i) = beta.elem(k+i);
-	} 
-      } else {
-	// Fills in C and S
-	sigmaA.resize (m-k, m-k);
-	sigmaB.resize (m-k, m-k);
-	for (i = 0; i < m-k; i++) {
-	  sigmaA.dgxelem(i) = alpha.elem(k+i);
-	  sigmaB.dgxelem(i) = beta.elem(k+i);
-	}
-      }
-    }
-  }
-  return info;
-}
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/CmplxGSVD.h
--- a/liboctave/numeric/CmplxGSVD.h	Thu Aug 04 07:50:31 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-// Copyright (C) 1996, 1997 John W. Eaton
-// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
-//
-// This program is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free Software
-// Foundation; either version 3 of the License, or (at your option) any later
-// version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-// details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, see <http://www.gnu.org/licenses/>.
-
-#if !defined (octave_ComplexGSVD_h)
-#define octave_ComplexGSVD_h 1
-
-#include "octave-config.h"
-
-#include <iosfwd>
-
-#include "dDiagMatrix.h"
-#include "CMatrix.h"
-#include "dbleGSVD.h"
-
-class
-ComplexGSVD
-{
-public:
-
-  ComplexGSVD (void) { }
-
-  ComplexGSVD (const ComplexMatrix& a, const ComplexMatrix& b,  
-           GSVD::type gsvd_type = GSVD::economy) 
-    { 
-      init (a, b, gsvd_type); 
-    }
-
-  ComplexGSVD (const ComplexMatrix& a, const ComplexMatrix& b, 
-           octave_idx_type& info, GSVD::type gsvd_type = GSVD::economy)
-    {
-      info = init (a, b, gsvd_type);
-    }
-
-  ComplexGSVD (const ComplexGSVD& a)
-    : type_computed (a.type_computed),
-      sigmaA (a.sigmaA), sigmaB (a.sigmaB), 
-      left_smA (a.left_smA), left_smB (a.left_smB), right_sm (a.right_sm),
-      R(a.R) { }
-
-  ComplexGSVD& operator = (const ComplexGSVD& a)
-    {
-      if (this != &a)
-    {
-      type_computed = a.type_computed;
-      sigmaA = a.sigmaA;
-      sigmaB = a.sigmaB;
-      left_smA = a.left_smA;
-      left_smB = a.left_smB;
-      right_sm = a.right_sm;
-      R = a.R;
-    }
-
-      return *this;
-    }
-
-  ~ComplexGSVD (void) { }
-
-  DiagMatrix singular_values_A (void) const { return sigmaA; }
-  DiagMatrix singular_values_B (void) const { return sigmaB; }
-
-  ComplexMatrix left_singular_matrix_A (void) const;
-  ComplexMatrix left_singular_matrix_B (void) const;
-
-  ComplexMatrix right_singular_matrix (void) const;
-  ComplexMatrix R_matrix (void) const;
-
-  friend std::ostream&  operator << (std::ostream& os, const ComplexGSVD& a);
-
-private:
-
-  GSVD::type type_computed;
-
-  DiagMatrix sigmaA, sigmaB;
-  ComplexMatrix left_smA, left_smB;
-  ComplexMatrix right_sm, R;
-
-  octave_idx_type init (const ComplexMatrix& a, const ComplexMatrix& b, 
-            GSVD::type gsvd_type = GSVD::economy);
-};
-
-#endif
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/dbleGSVD.cc
--- a/liboctave/numeric/dbleGSVD.cc	Thu Aug 04 07:50:31 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,293 +0,0 @@
-// Copyright (C) 1996, 1997 John W. Eaton
-// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
-//
-// This program is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free Software
-// Foundation; either version 3 of the License, or (at your option) any later
-// version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-// details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, see <http://www.gnu.org/licenses/>.
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "dbleGSVD.h"
-#include "f77-fcn.h"
-#include "lo-error.h"
-
-/*
-   uncomment those lines to monitor k and l
-   #include "oct-obj.h"
-   #include "pager.h"
-*/
-
-extern "C"
-{
-  F77_RET_T
-  F77_FUNC (dggsvd, DGGSVD)
-   (
-     F77_CONST_CHAR_ARG_DECL,   // JOBU    (input) CHARACTER*1
-     F77_CONST_CHAR_ARG_DECL,   // JOBV    (input) CHARACTER*1
-     F77_CONST_CHAR_ARG_DECL,   // JOBQ    (input) CHARACTER*1
-     const octave_idx_type&,    // M       (input) INTEGER
-     const octave_idx_type&,    // N       (input) INTEGER
-     const octave_idx_type&,    // P       (input) INTEGER
-     octave_idx_type &,         // K       (output) INTEGER
-     octave_idx_type &,         // L       (output) INTEGER
-     double*,                   // A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
-     const octave_idx_type&,    // LDA     (input) INTEGER
-     double*,                   // B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
-     const octave_idx_type&,    // LDB     (input) INTEGER
-     double*,                   // ALPHA   (output) DOUBLE PRECISION array, dimension (N)
-     double*,                   // BETA    (output) DOUBLE PRECISION array, dimension (N)
-     double*,                   // U       (output) DOUBLE PRECISION array, dimension (LDU,M)
-     const octave_idx_type&,    // LDU     (input) INTEGER
-     double*,                   // V       (output) DOUBLE PRECISION array, dimension (LDV,P)
-     const octave_idx_type&,    // LDV     (input) INTEGER
-     double*,                   // Q       (output) DOUBLE PRECISION array, dimension (LDQ,N)
-     const octave_idx_type&,    // LDQ     (input) INTEGER
-     double*,                   // WORK    (workspace) DOUBLE PRECISION array
-     int*,                      // IWORK   (workspace/output) INTEGER array, dimension (N)
-     octave_idx_type&           // INFO    (output)INTEGER
-     F77_CHAR_ARG_LEN_DECL
-     F77_CHAR_ARG_LEN_DECL
-     F77_CHAR_ARG_LEN_DECL
-     );
-}
-
-Matrix
-GSVD::left_singular_matrix_A (void) const
-{
-  if (type_computed == GSVD::sigma_only)
-    {
-      (*current_liboctave_error_handler)
-        ("dbleGSVD: U not computed because type == GSVD::sigma_only");
-      return Matrix ();
-    }
-  else
-    return left_smA;
-}
-
-Matrix
-GSVD::left_singular_matrix_B (void) const
-{
-  if (type_computed == GSVD::sigma_only)
-    {
-      (*current_liboctave_error_handler)
-        ("dbleGSVD: V not computed because type == GSVD::sigma_only");
-      return Matrix ();
-    }
-  else
-    return left_smB;
-}
-
-Matrix
-GSVD::right_singular_matrix (void) const
-{
-  if (type_computed == GSVD::sigma_only)
-    {
-      (*current_liboctave_error_handler)
-        ("dbleGSVD: X not computed because type == GSVD::sigma_only");
-      return Matrix ();
-    }
-  else
-    return right_sm;
-}
-Matrix
-GSVD::R_matrix (void) const
-{
-  if (type_computed != GSVD::std)
-    {
-      (*current_liboctave_error_handler)
-        ("dbleGSVD: R not computed because type != GSVD::std");
-      return Matrix ();
-    }
-  else
-    return R;
-}
-
-octave_idx_type
-GSVD::init (const Matrix& a, const Matrix& b, GSVD::type gsvd_type)
-{
-  octave_idx_type info;
-
-  octave_idx_type m = a.rows ();
-  octave_idx_type n = a.cols ();
-  octave_idx_type p = b.rows ();
-  
-  Matrix atmp = a;
-  double *tmp_dataA = atmp.fortran_vec ();
-  
-  Matrix btmp = b;
-  double *tmp_dataB = btmp.fortran_vec ();
-
-  // octave_idx_type min_mn = m < n ? m : n;
-
-  char jobu = 'U';
-  char jobv = 'V';
-  char jobq = 'Q';
-
-  octave_idx_type nrow_u = m;
-  octave_idx_type nrow_v = p;
-  octave_idx_type nrow_q = n;
-
-  octave_idx_type k, l;
-
-  switch (gsvd_type)
-    {
-
-    case GSVD::sigma_only:
-
-      // Note:  for this case, both jobu and jobv should be 'N', but
-      // there seems to be a bug in dgesvd from Lapack V2.0.  To
-      // demonstrate the bug, set both jobu and jobv to 'N' and find
-      // the singular values of [eye(3), eye(3)].  The result is
-      // [-sqrt(2), -sqrt(2), -sqrt(2)].
-      //
-      // For Lapack 3.0, this problem seems to be fixed.
-
-      jobu = 'N';
-      jobv = 'N';
-      jobq = 'N';
-      nrow_u = nrow_v = nrow_q = 1;
-      break;
-      
-    default:
-      break;
-    }
-
-  type_computed = gsvd_type;
-
-  if (! (jobu == 'N' || jobu == 'O')) {
-    left_smA.resize (nrow_u, m);
-  }
-  
-  double *u = left_smA.fortran_vec ();
-
-  if (! (jobv == 'N' || jobv == 'O')) {
-    left_smB.resize (nrow_v, p);
-  }
-
-  double *v = left_smB.fortran_vec ();
-
-  if (! (jobq == 'N' || jobq == 'O')) {
-    right_sm.resize (nrow_q, n);
-  }
-  double *q = right_sm.fortran_vec ();
-  
-  octave_idx_type lwork = 3*n;
-  lwork = lwork > m ? lwork : m;
-  lwork = (lwork > p ? lwork : p) + n;
-
-  Array<double> work (dim_vector (lwork, 1));
-  Array<double> alpha (dim_vector (n, 1));
-  Array<double> beta (dim_vector (n, 1));
-  Array<int>    iwork (dim_vector (n, 1));
-
-  F77_XFCN (dggsvd, DGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
-                             F77_CONST_CHAR_ARG2 (&jobv, 1),
-                             F77_CONST_CHAR_ARG2 (&jobq, 1),
-                             m, n, p, k, l, tmp_dataA, m,
-                             tmp_dataB, p, alpha.fortran_vec (),
-                             beta.fortran_vec (), u, nrow_u,
-                             v, nrow_v, q, nrow_q, work.fortran_vec (),
-                             iwork.fortran_vec (), info
-                             F77_CHAR_ARG_LEN (1)
-                             F77_CHAR_ARG_LEN (1)
-                             F77_CHAR_ARG_LEN (1)));
-  
-  if (f77_exception_encountered)
-    (*current_liboctave_error_handler) ("unrecoverable error in dggsvd");
- 
-  if (info < 0) {
-    (*current_liboctave_error_handler) ("dggsvd.f: argument %d illegal", -info);
-  } else {
-    if (info > 0) {
-      (*current_liboctave_error_handler) ("dggsvd.f: Jacobi-type procedure failed to converge.");
-    } else {
-      octave_idx_type i, j;
-      
-      if (GSVD::std == gsvd_type) {
-        R.resize(k+l, k+l);
-        int astart = n-k-l;
-        if (m - k - l >=  0) {
-          int astart = n-k-l;
-          /*
-           *  R is stored in A(1:K+L,N-K-L+1:N)
-           */
-          for (i = 0; i < k+l; i++)
-            for (j = 0; j < k+l; j++)
-              R.xelem(i, j) = atmp.xelem(i, astart + j);
-        } else {
-          /*
-           *    (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N),
-           *    ( 0  R22 R23 )
-           */
-
-           for (i = 0; i < m; i++)
-             for (j = 0; j < k+l; j++)
-               R.xelem(i, j) = atmp.xelem(i, astart + j);
-           /*
-            * and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
-            */
-           for (i = k+l-1; i >=m; i--) {
-             for (j = 0; j < m; j++)
-               R.xelem(i, j) = 0.0;
-             for (j = m; j < k+l; j++)
-               R.xelem(i, j) = btmp.xelem(i - k, astart + j);
-           }
-        }
-      }
-      /*
-        uncomment this to monitor k and l
-        octave_value tmp;
-        octave_stdout << "dbleGSVD k: ";
-        tmp = k;
-        tmp.print(octave_stdout);
-        octave_stdout << "\n";
-        octave_stdout << "dbleGSVD l: ";
-        tmp = l;
-        tmp.print(octave_stdout);
-        octave_stdout << "\n";
-      */
-
-      if (m-k-l >= 0) {
-        // Fills in C and S
-        sigmaA.resize (l, l);
-        sigmaB.resize (l, l);
-        for (i = 0; i < l; i++) {
-          sigmaA.dgxelem(i) = alpha.elem(k+i);
-          sigmaB.dgxelem(i) = beta.elem(k+i);
-        }
-      } else {
-        // Fills in C and S
-        sigmaA.resize (m-k, m-k);
-        sigmaB.resize (m-k, m-k);
-        for (i = 0; i < m-k; i++) {
-          sigmaA.dgxelem(i) = alpha.elem(k+i);
-          sigmaB.dgxelem(i) = beta.elem(k+i);
-        }
-      }
-    }
-  }
-  return info;
-}
-
-std::ostream&
-operator << (std::ostream& os, const GSVD& a)
-{
-  os << a.left_singular_matrix_A () << "\n";
-  os << a.left_singular_matrix_B () << "\n";
-  os << a.singular_values_A () << "\n";
-  os << a.singular_values_B () << "\n";
-  os << a.right_singular_matrix () << "\n";
-
-  return os;
-}
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/dbleGSVD.h
--- a/liboctave/numeric/dbleGSVD.h	Thu Aug 04 07:50:31 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-// Copyright (C) 1996, 1997 John W. Eaton
-// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
-//
-// This program is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free Software
-// Foundation; either version 3 of the License, or (at your option) any later
-// version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-// details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, see <http://www.gnu.org/licenses/>.
-
-#if !defined (octave_GSVD_h)
-#define octave_GSVD_h 1
-
-#include "octave-config.h"
-
-#include "dDiagMatrix.h"
-#include "dMatrix.h"
-
-class
-GSVD
-{
-public:
-
-  enum type
-    {
-      std,
-      economy,
-      sigma_only
-    };
-
-  GSVD (void) : sigmaA (), sigmaB (), left_smA (), left_smB (), right_sm () { }
-  GSVD (const Matrix& a, const Matrix& b, type gsvd_type = GSVD::economy) { init (a, b, gsvd_type); }
-
-  GSVD (const Matrix& a, const Matrix& b, octave_idx_type& info, type gsvd_type = GSVD::economy)
-    {
-      info = init (a, b, gsvd_type);
-    }
-
-  GSVD (const GSVD& a)
-    : type_computed (a.type_computed),
-      sigmaA (a.sigmaA), sigmaB (a.sigmaB), 
-      left_smA (a.left_smA), left_smB (a.left_smB), right_sm (a.right_sm),
-      R(a.R) { }
-
-  GSVD& operator = (const GSVD& a)
-    {
-      if (this != &a)
-    {
-      type_computed = a.type_computed;
-      sigmaA = a.sigmaA;
-      sigmaB = a.sigmaB;
-      left_smA = a.left_smA;
-      left_smB = a.left_smB;
-      right_sm = a.right_sm;
-      R = a.R;
-    }
-
-      return *this;
-    }
-
-  ~GSVD (void) { }
-
-  DiagMatrix singular_values_A (void) const { return sigmaA; }
-  DiagMatrix singular_values_B (void) const { return sigmaB; }
-
-  Matrix left_singular_matrix_A (void) const;
-  Matrix left_singular_matrix_B (void) const;
-
-  Matrix right_singular_matrix (void) const;
-  Matrix R_matrix (void) const;
-
-  friend std::ostream&  operator << (std::ostream& os, const GSVD& a);
-
-private:
-
-  GSVD::type type_computed;
-
-  DiagMatrix sigmaA, sigmaB;
-  Matrix left_smA, left_smB;
-  Matrix right_sm, R;
-
-  octave_idx_type init (const Matrix& a, const Matrix& b, type gsvd_type = economy);
-};
-
-#endif
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/gsvd.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/numeric/gsvd.cc	Tue Aug 09 18:02:11 2016 +0200
@@ -0,0 +1,357 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+// Copyright (C) 2016 Barbara Lócsi
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "gsvd.h"
+#include "f77-fcn.h"
+#include "lo-error.h"
+#include "CMatrix.h"
+#include "dDiagMatrix.h"
+#include "dMatrix.h"
+
+extern "C"
+{
+  F77_RET_T
+  F77_FUNC (dggsvd, DGGSVD)
+   (
+     F77_CONST_CHAR_ARG_DECL,   // JOBU    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL,   // JOBV    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL,   // JOBQ    (input) CHARACTER*1
+     const F77_INT&,            // M       (input) INTEGER
+     const F77_INT&,            // N       (input) INTEGER
+     const F77_INT&,            // P       (input) INTEGER
+     F77_INT &,                 // K       (output) INTEGER
+     F77_INT &,                 // L       (output) INTEGER
+     F77_DBLE*,                 // A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+     const F77_INT&,            // LDA     (input) INTEGER
+     F77_DBLE*,                 // B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
+     const F77_INT&,            // LDB     (input) INTEGER
+     F77_DBLE*,                 // ALPHA   (output) DOUBLE PRECISION array, dimension (N)
+     F77_DBLE*,                 // BETA    (output) DOUBLE PRECISION array, dimension (N)
+     F77_DBLE*,                 // U       (output) DOUBLE PRECISION array, dimension (LDU,M)
+     const F77_INT&,            // LDU     (input) INTEGER
+     F77_DBLE*,                 // V       (output) DOUBLE PRECISION array, dimension (LDV,P)
+     const F77_INT&,            // LDV     (input) INTEGER
+     F77_DBLE*,                 // Q       (output) DOUBLE PRECISION array, dimension (LDQ,N)
+     const F77_INT&,            // LDQ     (input) INTEGER
+     F77_DBLE*,                 // WORK    (workspace) DOUBLE PRECISION array
+     int*,                      // IWORK   (workspace/output) INTEGER array, dimension (N)
+     F77_INT&                   // INFO    (output)INTEGER
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     );
+
+  F77_RET_T
+  F77_FUNC (zggsvd, ZGGSVD)
+   (
+     F77_CONST_CHAR_ARG_DECL,   // JOBU    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL,   // JOBV    (input) CHARACTER*1
+     F77_CONST_CHAR_ARG_DECL,   // JOBQ    (input) CHARACTER*1
+     const F77_INT&,            // M       (input) INTEGER
+     const F77_INT&,            // N       (input) INTEGER
+     const F77_INT&,            // P       (input) INTEGER
+     F77_INT &,                 // K       (output) INTEGER
+     F77_INT &,                 // L       (output) INTEGER
+     F77_DBLE_CMPLX*,           // A       (input/output) COMPLEX*16 array, dimension (LDA,N)
+     const F77_INT&,            // LDA     (input) INTEGER
+     F77_DBLE_CMPLX*,           // B       (input/output) COMPLEX*16 array, dimension (LDB,N)
+     const F77_INT&,            // LDB     (input) INTEGER
+     F77_DBLE*,                 // ALPHA   (output) DOUBLE PRECISION array, dimension (N)
+     F77_DBLE*,                 // BETA    (output) DOUBLE PRECISION array, dimension (N)
+     F77_DBLE_CMPLX*,           // U       (output) COMPLEX*16 array, dimension (LDU,M)
+     const F77_INT&,            // LDU     (input) INTEGER
+     F77_DBLE_CMPLX*,           // V       (output) COMPLEX*16 array, dimension (LDV,P)
+     const F77_INT&,            // LDV     (input) INTEGER
+     F77_DBLE_CMPLX*,           // Q       (output) COMPLEX*16 array, dimension (LDQ,N)
+     const F77_INT&,            // LDQ     (input) INTEGER
+     F77_DBLE_CMPLX*,           // WORK    (workspace) COMPLEX*16 array
+     F77_DBLE*,                 // RWORK   (workspace) DOUBLE PRECISION array
+     int*,                      // IWORK   (workspace/output) INTEGER array, dimension (N)
+     F77_INT&                   // INFO    (output)INTEGER
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     F77_CHAR_ARG_LEN_DECL
+     );
+}
+
+template <>
+void
+gsvd<Matrix>::ggsvd (char& jobu, char& jobv, char& jobq, octave_idx_type m,
+                    octave_idx_type n, octave_idx_type p, octave_idx_type& k,
+                    octave_idx_type& l, double *tmp_dataA, octave_idx_type m1,
+                    double *tmp_dataB, octave_idx_type p1, Matrix& alpha,
+                    Matrix& beta, double *u, octave_idx_type nrow_u, double *v,
+                    octave_idx_type nrow_v, double *q, octave_idx_type nrow_q,
+                    Matrix& work, octave_idx_type* iwork, octave_idx_type& info)
+{
+  F77_XFCN (dggsvd, DGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
+                             F77_CONST_CHAR_ARG2 (&jobv, 1),
+                             F77_CONST_CHAR_ARG2 (&jobq, 1),
+                             m, n, p, k, l, tmp_dataA, m1,
+                             tmp_dataB, p1, alpha.fortran_vec (),
+                             beta.fortran_vec (), u, nrow_u,
+                             v, nrow_v, q, nrow_q, work.fortran_vec (),
+                             iwork, info
+                             F77_CHAR_ARG_LEN (1)
+                             F77_CHAR_ARG_LEN (1)
+                             F77_CHAR_ARG_LEN (1)));
+}
+
+
+template <>
+void
+gsvd<ComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,
+                            octave_idx_type m, octave_idx_type n,
+                            octave_idx_type p, octave_idx_type& k,
+                            octave_idx_type& l, Complex *tmp_dataA,
+                            octave_idx_type m1, Complex *tmp_dataB,
+                            octave_idx_type p1, Matrix& alpha,
+                            Matrix& beta, Complex *u, octave_idx_type nrow_u,
+                            Complex *v, octave_idx_type nrow_v, Complex *q,
+                            octave_idx_type nrow_q, ComplexMatrix& work,
+                            octave_idx_type* iwork, octave_idx_type& info)
+{
+  Matrix rwork(2*n, 1);
+  F77_XFCN (zggsvd, ZGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1),
+                             F77_CONST_CHAR_ARG2 (&jobv, 1),
+                             F77_CONST_CHAR_ARG2 (&jobq, 1),
+                             m, n, p, k, l, F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
+                             F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
+                             alpha.fortran_vec (), beta.fortran_vec (),
+                             F77_DBLE_CMPLX_ARG (u), nrow_u,
+                             F77_DBLE_CMPLX_ARG (v), nrow_v,
+                             F77_DBLE_CMPLX_ARG (q), nrow_q,
+                             F77_DBLE_CMPLX_ARG (work.fortran_vec ()),
+                             rwork.fortran_vec (), iwork, info
+                             F77_CHAR_ARG_LEN (1)
+                             F77_CHAR_ARG_LEN (1)
+                             F77_CHAR_ARG_LEN (1)));
+}
+
+template <typename T>
+T
+gsvd<T>::left_singular_matrix_A (void) const
+{
+  if (type == gsvd::Type::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+        ("gsvd: U not computed because type == gsvd::sigma_only");
+      return T ();
+    }
+  else
+    return left_smA;
+}
+
+template <typename T>
+T
+gsvd<T>::left_singular_matrix_B (void) const
+{
+  if (type == gsvd::Type::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+        ("gsvd: V not computed because type == gsvd::sigma_only");
+      return T ();
+    }
+  else
+    return left_smB;
+}
+
+template <typename T>
+T
+gsvd<T>::right_singular_matrix (void) const
+{
+  if (type == gsvd::Type::sigma_only)
+    {
+      (*current_liboctave_error_handler)
+        ("gsvd: X not computed because type == gsvd::sigma_only");
+      return T ();
+    }
+  else
+    return right_sm;
+}
+
+template <typename T>
+T
+gsvd<T>::R_matrix (void) const
+{
+  if (type != gsvd::Type::std)
+    {
+      (*current_liboctave_error_handler)
+        ("gsvd: R not computed because type != gsvd::std");
+      return T ();
+    }
+  else
+    return R;
+}
+
+template <typename T>
+gsvd<T>::gsvd (const T& a, const T& b, gsvd::Type gsvd_type)
+{
+  octave_idx_type info;
+
+  octave_idx_type m = a.rows ();
+  octave_idx_type n = a.cols ();
+  octave_idx_type p = b.rows ();
+
+  T atmp = a;
+  P *tmp_dataA = atmp.fortran_vec ();
+
+  T btmp = b;
+  P *tmp_dataB = btmp.fortran_vec ();
+
+  char jobu = 'U';
+  char jobv = 'V';
+  char jobq = 'Q';
+
+  octave_idx_type nrow_u = m;
+  octave_idx_type nrow_v = p;
+  octave_idx_type nrow_q = n;
+
+  octave_idx_type k, l;
+
+  switch (gsvd_type)
+    {
+      case gsvd<T>::Type::sigma_only:
+
+        // Note:  for this case, both jobu and jobv should be 'N', but
+        // there seems to be a bug in dgesvd from Lapack V2.0.  To
+        // demonstrate the bug, set both jobu and jobv to 'N' and find
+        // the singular values of [eye(3), eye(3)].  The result is
+        // [-sqrt(2), -sqrt(2), -sqrt(2)].
+        //
+        // For Lapack 3.0, this problem seems to be fixed.
+
+        jobu = 'N';
+        jobv = 'N';
+        jobq = 'N';
+        nrow_u = nrow_v = nrow_q = 1;
+        break;
+
+      default:
+        break;
+    }
+
+  type = gsvd_type;
+
+  if (! (jobu == 'N' || jobu == 'O'))
+    left_smA.resize (nrow_u, m);
+
+  P *u = left_smA.fortran_vec ();
+
+  if (! (jobv == 'N' || jobv == 'O'))
+    left_smB.resize (nrow_v, p);
+
+  P *v = left_smB.fortran_vec ();
+
+  if (! (jobq == 'N' || jobq == 'O'))
+    right_sm.resize (nrow_q, n);
+
+  P *q = right_sm.fortran_vec ();
+
+  octave_idx_type lwork = 3*n;
+  lwork = lwork > m ? lwork : m;
+  lwork = (lwork > p ? lwork : p) + n;
+
+  T work (lwork, 1);
+  Matrix alpha (n, 1);
+  Matrix beta (n, 1);
+
+  std::vector<octave_idx_type> iwork (n);
+
+  gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,
+                  tmp_dataA, m, tmp_dataB, p, alpha, beta, u,
+                  nrow_u, v, nrow_v, q, nrow_q, work, iwork.data (), info);
+
+  if (f77_exception_encountered)
+    (*current_liboctave_error_handler) ("unrecoverable error in *ggsvd");
+
+  if (info < 0)
+    (*current_liboctave_error_handler) ("*ggsvd.f: argument %d illegal", -info);
+  else
+    {
+      if (info > 0)
+        (*current_liboctave_error_handler)
+          ("*ggsvd.f: Jacobi-type procedure failed to converge.");
+      else
+        {
+          octave_idx_type i, j;
+
+          if (gsvd<T>::Type::std == gsvd_type)
+            {
+              R.resize(k+l, k+l);
+              int astart = n-k-l;
+              if (m - k - l >=  0)
+                {
+                  astart = n-k-l;
+                  // R is stored in A(1:K+L,N-K-L+1:N)
+                  for (i = 0; i < k+l; i++)
+                    for (j = 0; j < k+l; j++)
+                      R.xelem (i, j) = atmp.xelem (i, astart + j);
+                }
+              else
+                {
+                  // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N),
+                  // ( 0  R22 R23 )
+
+                   for (i = 0; i < m; i++)
+                     for (j = 0; j < k+l; j++)
+                       R.xelem (i, j) = atmp.xelem (i, astart + j);
+                   // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
+                   for (i = k+l-1; i >=m; i--) {
+                     for (j = 0; j < m; j++)
+                       R.xelem(i, j) = 0.0;
+                     for (j = m; j < k+l; j++)
+                       R.xelem (i, j) = btmp.xelem (i - k, astart + j);
+                   }
+                }
+            }
+
+          if (m-k-l >= 0)
+            {
+              // Fills in C and S
+              sigmaA.resize (l, l);
+              sigmaB.resize (l, l);
+              for (i = 0; i < l; i++)
+                {
+                  sigmaA.dgxelem(i) = alpha.elem(k+i);
+                  sigmaB.dgxelem(i) = beta.elem(k+i);
+                }
+            }
+          else
+            {
+              // Fills in C and S
+              sigmaA.resize (m-k, m-k);
+              sigmaB.resize (m-k, m-k);
+              for (i = 0; i < m-k; i++)
+                {
+                  sigmaA.dgxelem(i) = alpha.elem(k+i);
+                  sigmaB.dgxelem(i) = beta.elem(k+i);
+                }
+            }
+        }
+    }
+}
+
+// Instantiations we need.
+
+template class gsvd<Matrix>;
+
+template class gsvd<ComplexMatrix>;
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/gsvd.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/numeric/gsvd.h	Tue Aug 09 18:02:11 2016 +0200
@@ -0,0 +1,95 @@
+// Copyright (C) 1996, 1997 John W. Eaton
+// Copyright (C) 2006 Pascal Dupuis <Pascal.Dupuis@uclouvain.be>
+// Copyright (C) 2016 Barbara Lócsi
+//
+// This program is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, see <http://www.gnu.org/licenses/>.
+
+#if !defined (octave_gsvd_h)
+#define octave_gsvd_h 1
+
+#include "octave-config.h"
+
+#include "dDiagMatrix.h"
+#include "dMatrix.h"
+
+template <typename T>
+class
+gsvd
+{
+public:
+
+  enum class Type
+  {
+    std,
+    economy,
+    sigma_only
+  };
+
+  gsvd (void) : sigmaA (), sigmaB (), left_smA (), left_smB (), right_sm () { }
+
+  gsvd (const T& a, const T& b, gsvd::Type gsvd_type = gsvd<T>::Type::economy);
+
+  gsvd (const gsvd& a)
+    : type (a.type),
+      sigmaA (a.sigmaA), sigmaB (a.sigmaB),
+      left_smA (a.left_smA), left_smB (a.left_smB), right_sm (a.right_sm),
+      R(a.R) { }
+
+  gsvd& operator = (const gsvd& a)
+    {
+      if (this != &a)
+        {
+          type = a.type;
+          sigmaA = a.sigmaA;
+          sigmaB = a.sigmaB;
+          left_smA = a.left_smA;
+          left_smB = a.left_smB;
+          right_sm = a.right_sm;
+          R = a.R;
+        }
+
+      return *this;
+    }
+
+  ~gsvd (void) { }
+
+  DiagMatrix singular_values_A (void) const { return sigmaA; }
+  DiagMatrix singular_values_B (void) const { return sigmaB; }
+
+  T left_singular_matrix_A (void) const;
+  T left_singular_matrix_B (void) const;
+
+  T right_singular_matrix (void) const;
+  T R_matrix (void) const;
+
+private:
+
+  gsvd::Type type;
+
+  typedef typename T::element_type P;
+
+  DiagMatrix sigmaA, sigmaB;
+  T left_smA, left_smB;
+  T right_sm, R;
+
+  void ggsvd (char& jobu, char& jobv, char& jobq, octave_idx_type m,
+              octave_idx_type n, octave_idx_type p, octave_idx_type& k,
+              octave_idx_type& l, P *tmp_dataA, octave_idx_type m1,
+              P *tmp_dataB, octave_idx_type p1, Matrix& alpha, Matrix& beta,
+              P *u, octave_idx_type nrow_u, P *v, octave_idx_type nrow_v, P *q,
+              octave_idx_type nrow_q, T& work, octave_idx_type* iwork,
+              octave_idx_type& info);
+};
+
+#endif
diff -r 63b41167ef1e -r 065a44375723 liboctave/numeric/module.mk
--- a/liboctave/numeric/module.mk	Thu Aug 04 07:50:31 2016 +0200
+++ b/liboctave/numeric/module.mk	Tue Aug 09 18:02:11 2016 +0200
@@ -8,7 +8,6 @@
 LIBOCTAVE_OPT_IN = $(LIBOCTAVE_OPT_INC:.h=.in)
 
 NUMERIC_INC = \
-  liboctave/numeric/CmplxGSVD.h \
   liboctave/numeric/CollocWt.h \
   liboctave/numeric/DAE.h \
   liboctave/numeric/DAEFunc.h \
@@ -17,9 +16,9 @@
   liboctave/numeric/DASPK.h \
   liboctave/numeric/DASRT.h \
   liboctave/numeric/DASSL.h \
-  liboctave/numeric/dbleGSVD.h \
   liboctave/numeric/DET.h \
   liboctave/numeric/EIG.h \
+  liboctave/numeric/gsvd.h \
   liboctave/numeric/LSODE.h \
   liboctave/numeric/ODE.h \
   liboctave/numeric/ODEFunc.h \
@@ -58,13 +57,12 @@
   liboctave/numeric/svd.h
 
 NUMERIC_SRC = \
-  liboctave/numeric/CmplxGSVD.cc \
   liboctave/numeric/CollocWt.cc \
   liboctave/numeric/DASPK.cc \
   liboctave/numeric/DASRT.cc \
   liboctave/numeric/DASSL.cc \
-  liboctave/numeric/dbleGSVD.cc \
   liboctave/numeric/EIG.cc \
+  liboctave/numeric/gsvd.cc \
   liboctave/numeric/LSODE.cc \
   liboctave/numeric/ODES.cc \
   liboctave/numeric/Quad.cc \
diff -r 63b41167ef1e -r 065a44375723 liboctave/operators/mx-defs.h
--- a/liboctave/operators/mx-defs.h	Thu Aug 04 07:50:31 2016 +0200
+++ b/liboctave/operators/mx-defs.h	Tue Aug 09 18:02:11 2016 +0200
@@ -66,7 +66,7 @@
 
 class EIG;
 
-class GSVD;
+template <typename T> class gsvd;
 
 template <typename T> class hess;
 
diff -r 63b41167ef1e -r 065a44375723 liboctave/operators/mx-ext.h
--- a/liboctave/operators/mx-ext.h	Thu Aug 04 07:50:31 2016 +0200
+++ b/liboctave/operators/mx-ext.h	Tue Aug 09 18:02:11 2016 +0200
@@ -59,8 +59,7 @@
 
 // Result of a Generalized Singular Value Decomposition.
 
-#include "dbleGSVD.h"
-#include "CmplxGSVD.h"
+#include "gsvd.h"
 
 
 // Result of an LU decomposition.
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470774893 -3600
#      Tue Aug 09 21:34:53 2016 +0100
# Node ID 867b177af1fe0207c62f8cb12333f4437a1bc7c5
# Parent  065a443757239e4fd8f0bc79f0f02fe736d32748
gsvd: replace deprecated gripe_wrong_type_arg with err_wrong_type_arg.

diff -r 065a44375723 -r 867b177af1fe libinterp/corefcn/gsvd.cc
--- a/libinterp/corefcn/gsvd.cc	Tue Aug 09 18:02:11 2016 +0200
+++ b/libinterp/corefcn/gsvd.cc	Tue Aug 09 21:34:53 2016 +0100
@@ -317,8 +317,8 @@
         }
       else
         {
-          gripe_wrong_type_arg ("gsvd", argA);
-          gripe_wrong_type_arg ("gsvd", argB);
+          err_wrong_type_arg ("gsvd", argA);
+          err_wrong_type_arg ("gsvd", argB);
           return retval;
         }
     }
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470774983 -3600
#      Tue Aug 09 21:36:23 2016 +0100
# Node ID dfb49a84c0e4910d2ac4ecdc57f206d5729ca18c
# Parent  867b177af1fe0207c62f8cb12333f4437a1bc7c5
libinterp/corefcn/gsvd.cc: clean up #include's removing what's not needed.

diff -r 867b177af1fe -r dfb49a84c0e4 libinterp/corefcn/gsvd.cc
--- a/libinterp/corefcn/gsvd.cc	Tue Aug 09 21:34:53 2016 +0100
+++ b/libinterp/corefcn/gsvd.cc	Tue Aug 09 21:36:23 2016 +0100
@@ -19,14 +19,19 @@
 #  include <config.h>
 #endif
 
+#include "dMatrix.h"
+#include "CMatrix.h"
+#include "dDiagMatrix.h"
+#include "gsvd.h"
+
 #include "defun.h"
+#include "defun-int.h"
 #include "error.h"
-#include "gripes.h"
-#include "pr-output.h"
+#include "errwarn.h"
 #include "utils.h"
 #include "ovl.h"
+#include "ov.h"
 
-#include "gsvd.h"
 
 template <typename T>
 static typename gsvd<T>::Type
# HG changeset patch
# User Daniel J Sebald <daniel.sebald@ieee.org>
# Date 1469893089 18000
#      Sat Jul 30 10:38:09 2016 -0500
# Node ID f7b70f3a8fc17e71d2a435716f8f6cf9326e5db4
# Parent  dfb49a84c0e4910d2ac4ecdc57f206d5729ca18c
For gnuplot toolkit patch case, broadcast single color values (bug #48626).

* __gnuplot_draw_axes__.m: For the case of a "patch" object, if the color
  value is only one-dimensional, broadcast its value to the same dimension
  as the z-coordinate vector rather than use the z values.

diff -r dfb49a84c0e4 -r f7b70f3a8fc1 scripts/plot/util/private/__gnuplot_draw_axes__.m
--- a/scripts/plot/util/private/__gnuplot_draw_axes__.m	Tue Aug 09 21:36:23 2016 +0100
+++ b/scripts/plot/util/private/__gnuplot_draw_axes__.m	Sat Jul 30 10:38:09 2016 -0500
@@ -803,7 +803,9 @@
                 if (isnan (ccdat))
                   ccdat = (rows (cmap) + rows (addedcmap) + 1) * ones(3, 1);
                   addedcmap = [addedcmap; reshape(color, 1, 3)];
-                elseif (numel (ccdat) <= 1)
+                elseif (numel (ccdat) == 1)
+                  ccdat = ccdat * ones (size (zcol));
+                elseif (numel (ccdat) < 1)
                   ccdat = zcol;
                 endif
                 data{data_3d_idx} = [data{data_3d_idx}, ...
# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1470780450 25200
#      Tue Aug 09 15:07:30 2016 -0700
# Node ID 669fc8cf1fdd03df21539050ed9b0523bbfa1e6f
# Parent  f7b70f3a8fc17e71d2a435716f8f6cf9326e5db4
isosurface.m: Rework %!demos (bug #48626).

* isosurface.m: Add demo with one sphere for check of color range
computation in graphics toolkits.  Change to Matlab syntax in demo 3 and
rotate view.

diff -r f7b70f3a8fc1 -r 669fc8cf1fdd scripts/plot/draw/isosurface.m
--- a/scripts/plot/draw/isosurface.m	Sat Jul 30 10:38:09 2016 -0500
+++ b/scripts/plot/draw/isosurface.m	Tue Aug 09 15:07:30 2016 -0700
@@ -364,6 +364,14 @@
 %! clf;
 %! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);
 %! v = x.^2 + y.^2 + z.^2;
+%! isosurface (x, y, z, v, 1);
+%! axis equal;
+%! title ("isosurface of a sphere");
+
+%!demo
+%! clf;
+%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);
+%! v = x.^2 + y.^2 + z.^2;
 %! isosurface (x, y, z, v, 3);
 %! isosurface (x, y, z, v, 5);
 %! axis equal;
@@ -377,21 +385,38 @@
 %! v        = [0, 0, 0; 0, 0, 0; 0, 0, 1; 0, 0, 1];
 %! v(:,:,2) = [0, 0, 0; 0, 0, 1; 0, 1, 2; 0, 1, 2];
 %! iso = 0.8;
+%! clf;
 %% three arguments, no output
-%! figure;
-%! subplot (2, 2, 1); isosurface (v, iso, yy); view(3)
+%! subplot (2, 2, 1);
+%! fvc = isosurface (v, iso, yy);
+%! patch (fvc);
+%! shading faceted
+%! view (110, 40);
 %% six arguments, no output (x, y, z are vectors)
-%! subplot (2, 2, 2); isosurface (x, y, z, v, iso, yy); view (3)
+%! subplot (2, 2, 2);
+%! fvc = isosurface (x, y, z, v, iso, yy);
+%! patch (fvc);
+%! shading faceted
+%! view (110, 40);
 %% six arguments, no output (x, y, z are matrices)
-%! subplot (2, 2, 3); isosurface (xx, yy, zz, v, iso, yy); view (3)
+%! subplot (2, 2, 3);
+%! fvc = isosurface (xx, yy, zz, v, iso, yy);
+%! patch (fvc);
+%! shading faceted
+%! view (110, 40);
 %% six arguments, no output (mixed x, y, z) and option "noshare"
-%! subplot (2, 2, 4); isosurface (x, yy, z, v, iso, yy, "noshare"); view (3)
-%! annotation ("textbox", [0.01 0.93 1 0.1], ...
+%! subplot (2, 2, 4);
+%! fvc = isosurface (x, yy, z, v, iso, yy, "noshare");
+%! patch (fvc);
+%! shading faceted
+%! view (110, 40);
+%! annotation ("textbox", [0.1 0.9 0.9 0.1], ...
 %!    "String", ["Apart from the first plot having a different scale, " ...
-%!               "all four plots must look the same.\n" ...
+%!               "all four plots must look the same." 10 ...
 %!               "The last plot might have different colors but must have " ...
 %!               "the same shape."], ...
-%!    "HorizontalAlignment", "left");
+%!    "HorizontalAlignment", "left", ...
+%!    "FontSize", 12);
 
 %!shared x, y, z, xx, yy, zz, val, iso
 %! x = 0:2;
# HG changeset patch
# User Barbara Locsi <locsi.barbara@gmail.com>
# Date 1470505112 -7200
#      Sat Aug 06 19:38:32 2016 +0200
# Node ID 71d86e88589f72e7fc42388e1bc0fe02b13f1661
# Parent  669fc8cf1fdd03df21539050ed9b0523bbfa1e6f
chol2inv: fix support for sparse matrices by fixing MatrixType (bug #36437)

* liboctave/array/MatrixType.cc: a Banded matrix can also be Upper or Lower.
In such case, set type to Lower/Upper and not to Banded.  The check for
Banded matrix does not exist when input is non-sparse, which is why this
only affected sparse matrices.
* libinterp/dldfcn/chol.cc: add tests for sparse matrices.

diff -r 669fc8cf1fdd -r 71d86e88589f libinterp/dldfcn/chol.cc
--- a/libinterp/dldfcn/chol.cc	Tue Aug 09 15:07:30 2016 -0700
+++ b/libinterp/dldfcn/chol.cc	Sat Aug 06 19:38:32 2016 +0200
@@ -570,6 +570,35 @@
   return retval;
 }
 
+/*
+
+## Test for bug #36437
+%!function sparse_chol2inv (T, tol)
+%!  iT = inv (T);
+%!  ciT = chol2inv (chol (T));
+%!  assert (ciT, iT, tol);
+%!  assert (chol2inv (chol ( full (T))), ciT, tol*2);
+%!endfunction
+
+%!test
+%! A = gallery ("poisson", 3);
+%! sparse_chol2inv (A, eps);
+
+%!test
+%! n = 10;
+%! B = spdiags (ones (n, 1) * [1 2 1], [-1 0 1], n, n);
+%! sparse_chol2inv (B, eps*100);
+
+%!test
+%! C = gallery("tridiag", 5);
+%! sparse_chol2inv (C, eps*10);
+
+%!test
+%! D = gallery("wathen", 1, 1);
+%! sparse_chol2inv (D, eps*10^4);
+
+*/
+
 DEFUN_DLD (cholupdate, args, nargout,
            doc: /* -*- texinfo -*-
 @deftypefn {} {[@var{R1}, @var{info}] =} cholupdate (@var{R}, @var{u}, @var{op})
diff -r 669fc8cf1fdd -r 71d86e88589f liboctave/array/MatrixType.cc
--- a/liboctave/array/MatrixType.cc	Tue Aug 09 15:07:30 2016 -0700
+++ b/liboctave/array/MatrixType.cc	Sat Aug 06 19:38:32 2016 +0200
@@ -351,7 +351,9 @@
               else
                 dense = false;
             }
-          else if (upper_band == 0)
+
+          // If a matrix is Banded but also Upper/Lower, set to the latter.
+          if (upper_band == 0)
             typ = MatrixType::Lower;
           else if (lower_band == 0)
             typ = MatrixType::Upper;
@@ -668,7 +670,9 @@
               else
                 dense = false;
             }
-          else if (upper_band == 0)
+
+          // If a matrix is Banded but also Upper/Lower, set to the latter.
+          if (upper_band == 0)
             typ = MatrixType::Lower;
           else if (lower_band == 0)
             typ = MatrixType::Upper;
# HG changeset patch
# User Barbara Locsi <locsi.barbara@gmail.com>
# Date 1470781509 -3600
#      Tue Aug 09 23:25:09 2016 +0100
# Node ID 5417dad26a25df4fe354108b2a089b1dcc8568d7
# Parent  71d86e88589f72e7fc42388e1bc0fe02b13f1661
chol2inv: "inv (Y'*Y)" instead of "(inv(Y))' * inv(Y)" (bug #36437)

* liboctave/numeric/sparse-chol.cc (chol2inv): compute "inv (Y'*Y)"
instead of "(inv(Y))' * inv(Y)".

diff -r 71d86e88589f -r 5417dad26a25 liboctave/numeric/sparse-chol.cc
--- a/liboctave/numeric/sparse-chol.cc	Sat Aug 06 19:38:32 2016 +0200
+++ b/liboctave/numeric/sparse-chol.cc	Tue Aug 09 23:25:09 2016 +0100
@@ -546,21 +546,23 @@
   int typ = mattype.type (false);
   double rcond;
   octave_idx_type info;
-  chol_type rinv;
+  chol_type rtra, multip;
 
   if (typ == MatrixType::Upper)
     {
-      rinv = r.inverse (mattype, info, rcond, true, false);
-      retval = rinv.transpose () * rinv;
+      rtra = r.transpose ();
+      multip = (rtra*r);
     }
   else if (typ == MatrixType::Lower)
     {
-      rinv = r.transpose ().inverse (mattype, info, rcond, true, false);
-      retval = rinv.transpose () * rinv;
+      rtra = r.transpose ();
+      multip = (r*rtra);
     }
   else
     (*current_liboctave_error_handler) ("U must be a triangular matrix");
 
+  MatrixType mattypenew (multip);
+  retval = multip.inverse (mattypenew, info, rcond, true, false);
   return retval;
 }
 
# HG changeset patch
# User Markus Muetzel <markus.muetzel@gmx.de>
# Date 1468864474 -7200
#      Mon Jul 18 19:54:34 2016 +0200
# Node ID 654de580bdb38d76a8fe1a016c45395e8c271c74
# Parent  5417dad26a25df4fe354108b2a089b1dcc8568d7
Add function "reducepatch" (patch #8912)

* scripts/plot/draw/reducepatch.m: New function.

* scripts/plot/draw/module.mk: Add reducepath.m to build system.

* NEWS: Announce new function.

* isosurface.m: Add "reducepatch" to @seealso.

* __unimplemented__.m: Remove "reducepatch" from list.

* plot.txi: Add to documentation.

diff -r 5417dad26a25 -r 654de580bdb3 NEWS
--- a/NEWS	Tue Aug 09 23:25:09 2016 +0100
+++ b/NEWS	Mon Jul 18 19:54:34 2016 +0200
@@ -124,6 +124,7 @@
       padecoef
       psi
       rad2deg
+      reducepatch
       reducevolume
       uibuttongroup
 
diff -r 5417dad26a25 -r 654de580bdb3 doc/interpreter/plot.txi
--- a/doc/interpreter/plot.txi	Tue Aug 09 23:25:09 2016 +0100
+++ b/doc/interpreter/plot.txi	Mon Jul 18 19:54:34 2016 +0200
@@ -388,6 +388,8 @@
 
 @DOCSTRING(reducevolume)
 
+@DOCSTRING(reducepatch)
+
 @DOCSTRING(shrinkfaces)
 
 @DOCSTRING(diffuse)
diff -r 5417dad26a25 -r 654de580bdb3 scripts/help/__unimplemented__.m
--- a/scripts/help/__unimplemented__.m	Tue Aug 09 23:25:09 2016 +0100
+++ b/scripts/help/__unimplemented__.m	Mon Jul 18 19:54:34 2016 +0200
@@ -780,7 +780,6 @@
   "RandStream",
   "rbbox",
   "readtable",
-  "reducepatch",
   "remove",
   "removecats",
   "renamecats",
diff -r 5417dad26a25 -r 654de580bdb3 scripts/plot/draw/isosurface.m
--- a/scripts/plot/draw/isosurface.m	Tue Aug 09 23:25:09 2016 +0100
+++ b/scripts/plot/draw/isosurface.m	Mon Jul 18 19:54:34 2016 +0200
@@ -135,7 +135,7 @@
 ## light ("Position", [1 1 5]);
 ## @end smallexample
 ##
-## @seealso{isonormals, isocolors, smooth3, reducevolume}
+## @seealso{isonormals, isocolors, smooth3, reducevolume, reducepatch, patch}
 ## @end deftypefn
 
 ## Author: Martin Helm <martin@mhelm.de>
diff -r 5417dad26a25 -r 654de580bdb3 scripts/plot/draw/module.mk
--- a/scripts/plot/draw/module.mk	Tue Aug 09 23:25:09 2016 +0100
+++ b/scripts/plot/draw/module.mk	Mon Jul 18 19:54:34 2016 +0200
@@ -72,6 +72,7 @@
   scripts/plot/draw/quiver3.m \
   scripts/plot/draw/quiver.m \
   scripts/plot/draw/rectangle.m \
+  scripts/plot/draw/reducepatch.m \
   scripts/plot/draw/reducevolume.m \
   scripts/plot/draw/ribbon.m \
   scripts/plot/draw/rose.m \
diff -r 5417dad26a25 -r 654de580bdb3 scripts/plot/draw/reducepatch.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/reducepatch.m	Mon Jul 18 19:54:34 2016 +0200
@@ -0,0 +1,457 @@
+## Copyright (C) 2016 Markus Muetzel
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{reduced_fv} =} reducepatch (@var{fv})
+## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@var{faces}, @var{vertices})
+## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@var{patch_handle})
+## @deftypefnx {} {} reducepatch (@var{patch_handle})
+## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, @var{reduction_factor})
+## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, "fast")
+## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, "verbose")
+## @deftypefnx {} {[@var{reduced_faces}, @var{reduces_vertices}] =} reducepatch (@dots{})
+##
+## Reduce the number of faces and vertices in a surface or patch object while
+## retaining the overall shape of the patch.
+##
+## The input patch can be represented by a structure @var{fv} with the
+## fields @code{faces} and @code{vertices}, by two matrices @var{faces} and
+## @var{vertices} (see, e.g., the result of @code{isosurface}), or by a
+## handle to a patch object @var{patch_handle} (@pxref{XREFpatch,,patch}).
+##
+## The number of faces and vertices in the patch is reduced by iteratively
+## collapsing the shortest edge of the patch to its midpoint (as discussed,
+## e.g., here:
+## @url{http://libigl.github.io/libigl/tutorial/tutorial.html#meshdecimation}).
+##
+## Currently, only patches consisting of triangles are supported.  The
+## resulting patch also consists only of triangles.
+##
+## If @code{reducepatch} is called with a handle to a valid patch
+## @var{patch_handle}, and without any output arguments, then the given
+## patch is updated immediately.
+##
+## If the @var{reduction_factor} is omitted, the resulting structure
+## @var{reduced_fv} includes approximately 50% of the faces of the original
+## patch.  If @var{reduction_factor} is a fraction between 0 (excluded) and 1
+## (excluded), a patch with approximately the corresponding fraction of faces
+## is determined.
+## If @var{reduction_factor} is an integer greater than or equal to 1, the
+## resulting patch has approximately @var{reduction_factor} faces.  Depending
+## on the geometry of the patch, the resulting number of faces can differ from
+## the given value of @var{reduction_factor}.  This is especially true when
+## many shared vertices are detected.
+##
+## For the reduction, it is necessary that vertices of touching faces are
+## shared.  Shared vertices are detected automatically.  This detection can be
+## skipped by passing the optional string argument @qcode{"fast"}.
+##
+## With the optional string arguments @qcode{"verbose"}, additional status
+## messages are printed to the command window.
+##
+## Any string input arguments must be passed after all other arguments.
+##
+## If called with one output argument, the reduced faces and vertices are
+## returned in a structure @var{reduced_fv} with the fields @code{faces} and
+## @code{vertices} (see the one output option of @code{isosurface}).
+##
+## If called with two output arguments, the reduced faces and vertices are
+## returned in two separate matrices @var{reduced_faces} and
+## @var{reduced_vertices}.
+##
+## @seealso{isosurface, isonormals, reducevolume, patch}
+## @end deftypefn
+
+## Author: mmuetzel
+
+## FIXME: Convert faces to only triangles if necessary
+
+function varargout = reducepatch (varargin)
+
+  if (nargin < 1 || nargin > 5)
+    print_usage ();
+  endif
+
+  [faces, vertices, max_faces, patch_handle, fast, verbose] = ...
+                          __get_check_reducepatch_args__ (varargin{:});
+
+  if (verbose)
+    printf (["reducepatch: before reduction of faces:           ", ...
+             "%5d faces, %5d vertices\n"], rows (faces), rows (vertices));
+  endif
+
+  if (max_faces >= rows (faces))
+    faces_reduced = faces;
+    vertices_reduced = vertices;
+  else
+    if (! fast)
+      [faces, vertices] = __unite_shared_vertices__ (faces, vertices);
+
+      if (verbose)
+        printf (["reducepatch: after detection of shared vertices:  ", ...
+                 "%5d faces, %5d vertices\n"], rows (faces), rows (vertices));
+      endif
+    endif
+
+    [faces_reduced, vertices_reduced] = ...
+        __reducepatch__ (vertices, faces, max_faces, verbose);
+  endif
+
+  if (verbose)
+    printf (["reducepatch: after reduction of faces:            ", ...
+             "%5d faces, %5d vertices\n"],                         ...
+            rows (faces_reduced), rows (vertices_reduced));
+  endif
+
+  ## output
+  if (! isempty (patch_handle) && nargout == 0)
+    ## update patch object
+    set (patch_handle, "Faces", faces_reduced, "Vertices", vertices_reduced);
+  elseif (nargout == 2)  # faces, vertices
+    varargout{1} = faces_reduced;
+    varargout{2} = vertices_reduced;
+  else  # fv structure
+    varargout{1}.faces = faces_reduced;
+    varargout{1}.vertices = vertices_reduced;
+  endif
+
+endfunction
+
+## assign input parameters and check their validity
+function [faces, vertices, max_faces, patch_handle, fast, verbose] = ...
+              __get_check_reducepatch_args__ (varargin)
+
+  ## default values
+  faces = vertices = max_faces = patch_handle = [];
+  reduction_factor = 0.5;
+  fast = verbose = false;
+
+  num_string_inputs = 0;
+  ## check whether last 2 input arguments are strings and assign parameters
+  valid_vals = nargin:-1:nargin-1;
+  valid_vals(valid_vals < 1) = [];
+  for arg = varargin(valid_vals)
+    if (! ischar (arg{1}))
+      break;  # no string arguments at end, exit checking
+    endif
+    switch (tolower (arg{1}))
+      case {"f", "fast"}
+        fast = true;
+        num_string_inputs += 1;
+
+      case {"v", "verbose"}
+        verbose = true;
+        num_string_inputs += 1;
+
+      case ""
+        num_string_inputs++;
+        ## silently ignore empty strings
+
+      otherwise
+        error ("reducepatch: parameter '%s' not supported", arg{1});
+
+    endswitch
+  endfor
+
+  ## get faces and vertices
+  i_fv = 1;
+  arg1 = varargin{1};
+  if (isstruct (arg1))
+    if (all (isfield (arg1, {"vertices", "faces"})))
+      vertices = arg1.vertices;
+      faces = arg1.faces;
+    else
+      error (["reducepatch: struct FV must contain the fields ", ...
+              "'vertices' and 'faces'."]);
+    endif
+  elseif (isscalar (arg1))
+    patch_handle = arg1;
+    if (ishghandle (patch_handle, "patch"))
+      vertices = get (patch_handle, "Vertices");
+      faces = get (patch_handle, "Faces");
+    else
+      error ("reducepatch: PATCH_HANDLE must be a valid handle to a patch");
+    endif
+  elseif (ismatrix (arg1))
+    faces = arg1;
+    if (nargin - num_string_inputs > 1 && ismatrix (varargin{2}))
+      vertices = varargin{2};
+      i_fv = 2;
+    else
+      error (["reducepatch: If first argument is a matrix containing ", ...
+             "FACES, second argument must be a matrix containing VERTICES"]);
+    endif
+  else
+    print_usage ();
+  endif
+
+  ## get reduction_factor
+  if (nargin - num_string_inputs > i_fv) 
+    reduction_factor = varargin{i_fv + 1};
+    if (! isscalar (reduction_factor) || reduction_factor <= 0)
+      error ("reducepatch: REDUCTION_FACTOR must be a positive scalar");
+    endif
+  endif
+
+  ## check faces and vertices
+  if (columns (vertices) != 3)
+    error ("reducepatch: VERTICES must be an Mx3 matrix");
+  endif
+  if (columns (faces) != 3)
+    ## FIXME: Convert faces to only triangles if necessary
+    error ("reducepatch: Currently patches must consist of triangles only");
+  endif
+  if (any (mod (faces(:), 1)) || any (faces(:) < 1))
+    error ("reducepatch: FACES must consist of positive integer indices only");
+  endif
+  if (max (faces(:)) > rows (vertices))
+    error ("reducepatch: not enough VERTICES for given FACES");
+  endif
+
+  ## get max_faces
+  num_faces = rows (faces);
+  if (reduction_factor < 1)
+    max_faces = floor (num_faces * reduction_factor);
+  else
+    max_faces = reduction_factor;
+  endif
+
+endfunction
+
+## actual function to reduce number of faces
+function [faces_reduced, vertices_reduced] = ...
+              __reducepatch__ (vertices, faces, max_faces, verbose)
+
+  num_faces = rows (faces);
+  faces = sort (faces, 2);
+
+  ## get all unique edges
+  all_edges = sort ([faces(:,1) faces(:,2);
+                     faces(:,2) faces(:,3);
+                     faces(:,3) faces(:,1)], 2);
+  edges = unique (all_edges, "rows");
+  num_edges = rows (edges);
+
+  ## calculate length of edges
+  edge_length = norm (vertices(edges(:,1),:) - vertices(edges(:,2),:), ...
+                      2, "rows");
+
+  if (verbose)
+    printf ("reducepatch: reducing number of faces");
+    ## do not spam the command window with dots if many faces are collapsed
+    verbose_stepwidth = (num_faces - max_faces) / 100;  # max. 100 dots
+    verbose_counter = 0;
+  endif
+
+  ## reduce number of faces
+  clean_finish = true;
+  do
+    ## find shortest edge
+    i_shortest_edge = find (edge_length == min (edge_length), 1, "first");
+    if (any (isinf (vertices(edges(i_shortest_edge,:),:))))
+      warning (["reducepatch: shortest edge is marked as deleted. ", ...
+                "This should never happen."])
+      clean_finish = false;
+      break;
+    endif
+
+    start_point_idx = edges(i_shortest_edge,1);
+    end_point_idx = edges(i_shortest_edge,2);
+
+    ## collapse the edge to its midpoint
+    vertices(start_point_idx,:) = 0.5 * ...
+        (vertices(start_point_idx,:) + vertices(end_point_idx,:));
+    ## endpoint will be deleted later
+
+    ## remove collapsed edge info
+    edges(i_shortest_edge,:) = [];
+    edge_length(i_shortest_edge) = [];
+
+    ## unite collapsed edges of neighboring faces to one edge
+    faces_with_collapsed_edge = any (faces == start_point_idx, 2) & ...
+                                any (faces == end_point_idx, 2);
+    edges_of_collapsed_faces = faces(faces_with_collapsed_edge,:);
+    ## get other vertex of collapsed faces
+    third_vertices = ...
+        edges_of_collapsed_faces(...
+            faces(faces_with_collapsed_edge,:) != start_point_idx & ...
+            faces(faces_with_collapsed_edge,:) != end_point_idx);
+    if (! isempty (third_vertices))
+      ## delete edge of the collapsed faces which also has end_point
+      ## (keep the one with start_point)
+      edges_to_delete = any (edges == end_point_idx, 2) & ...
+          any (any (bsxfun (@eq, edges, ...
+                            reshape (third_vertices, 1, 1, [])), 3), 2);
+      edges(edges_to_delete,:) = [];
+      edge_length(edges_to_delete) = [];
+    endif
+
+    ## mark the faces that collapsed for later removal
+    faces(faces_with_collapsed_edge,:) = Inf;
+
+    ## update the lengths of the moved edges
+    edges_with_moved_point = any (edges == start_point_idx, 2);
+    edge_length(edges_with_moved_point) = ...
+        norm (vertices(edges(edges_with_moved_point,1),:) - ...
+              vertices(edges(edges_with_moved_point,2),:), 2, "rows");
+
+    ## replace all vertices that use end_point to use start_point
+    if (start_point_idx != end_point_idx)
+      edges(edges == end_point_idx) = start_point_idx;
+      faces(faces == end_point_idx) = start_point_idx;
+      vertices(end_point_idx,:) = Inf; # mark vertex for later removal
+    endif
+
+    ## Pretty print a row of dots while performing calulation
+    if (verbose && ++verbose_counter > verbose_stepwidth)
+      printf (".");
+      verbose_counter = 0;
+    endif
+
+  until (max_faces > num_faces - sum (isinf (faces(:,1))))
+
+  if (verbose)
+    printf ("\n");
+  endif
+
+  if (! clean_finish)
+    ## FIXME: What should be done in this case?
+    ## continue anyway?
+  endif
+
+  ## finally, remove vertices and faces
+  removed_vertices = isinf (vertices(:,1));
+  vertices_reduced = vertices(! removed_vertices,:);
+
+  faces_reduced = faces(! isinf (faces(:,1)),:);
+
+  ## renumber vertices in faces with subsequent numbers
+  vertex_renum = ones (rows (vertices), 1);
+  vertex_renum(removed_vertices) = 0;
+  vertex_renum = cumsum (vertex_renum);
+  faces_reduced = vertex_renum(faces_reduced);
+
+endfunction
+
+
+%!demo
+%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);
+%! val = x.^2 + y.^2 + z.^2;
+%! fv = isosurface (x, y, z, val, 1);
+%! figure;
+%! ax1 = subplot (1, 2, 1);
+%! patch (fv, "FaceColor", "g");
+%! view (3);  axis equal;
+%! title ("Sphere with all faces");
+%! ax2 = subplot(1, 2, 2);
+%! patch (reducepatch (fv, 72), "FaceColor", "g");
+%! view (3);  axis equal;
+%! title ("Sphere with reduced number of faces");
+%! linkprop ([ax1, ax2], {"CameraPosition", "CameraUpVector"});
+
+%!shared faces, vertices, fv, num_faces
+%! [x,y,z] = meshgrid (-2:0.5:2, -2:0.5:2, -2:0.5:2);
+%! val = x.^2 + y.^2 + z.^2;
+%! [faces, vertices] = isosurface (x, y, z, val, 1);
+%! fv.faces = faces;  fv.vertices = vertices;
+%! num_faces = rows (faces);
+
+## one input (structure), one output
+%!test
+%! fv_reduced = reducepatch (fv);
+%! assert (size (fv_reduced.faces, 1), num_faces * .5, 3);
+%! assert (size (fv_reduced.faces, 2), 3);
+%! assert (size (fv_reduced.vertices, 2), 3);
+
+## two inputs (faces, vertices), one output
+%!test
+%! fv_reduced = reducepatch (faces, vertices);
+%! assert (size (fv_reduced.faces, 1), num_faces * .5, 3);
+%! assert (size (fv_reduced.faces, 2), 3);
+%! assert (size (fv_reduced.vertices, 2), 3);
+
+## two inputs (structure, reduction_factor > 1), two outputs
+%!test
+%! [faces_reduced, vertices_reduced] = reducepatch (fv, 20);
+%! assert (size (faces_reduced, 1), 20, 3);
+%! assert (size (faces_reduced, 2), 3);
+%! assert (size (vertices_reduced, 2), 3);
+
+## three inputs (faces, vertices, reduction_factor < 1), two outputs
+%!test
+%! [faces_reduced, vertices_reduced] = reducepatch (faces, vertices, .5);
+%! assert (size (faces_reduced, 1), num_faces * .5, 3);
+%! assert (size (faces_reduced, 2), 3);
+%! assert (size (vertices_reduced, 2), 3);
+
+## two inputs (structure, reduction_factor < 1) + one string, no outputs
+## (update patch object in figure)
+%!test
+%! h_fig = figure ("visible", "off");
+%! p = patch (fv);
+%! reducepatch (p, .35, "f");
+%! assert (size (get (p, "Faces"), 1), num_faces * .35, 3);
+%! assert (size (get (p, "Faces"), 2), 3);
+%! assert (size (get (p, "Vertices"), 2), 3);
+%! close (h_fig);
+
+## three inputs (faces, vertices, reduction_factor > 1) + one empty
+## string, one output
+%!test
+%! fv_reduced = reducepatch (faces, vertices, 52, "");
+%! assert (size (fv_reduced.faces, 1), 52, 3);
+%! assert (size (fv_reduced.faces, 2), 3);
+%! assert (size (fv_reduced.vertices, 2), 3);
+
+## two inputs (structure, reduction_factor < 1) + one string, two outputs
+%!test
+%! [faces_reduced, vertices_reduced] = reducepatch (fv, .4, "fast");
+%! assert (size (faces_reduced, 1), num_faces * .4, 3);
+%! assert (size (faces_reduced, 2), 3);
+%! assert (size (vertices_reduced, 2), 3);
+
+## one input (structure) + two (empty) strings, two outputs
+%!test
+%! [faces_reduced, vertices_reduced] = reducepatch (fv, "f", "");
+%! assert (size (faces_reduced, 1), num_faces * .5, 3);
+%! assert (size (faces_reduced, 2), 3);
+%! assert (size (vertices_reduced, 2), 3);
+
+## test for each error
+%!error reducepatch ()
+%!error reducepatch (fv, faces, vertices, .5, "f", "v")
+%!error <reducepatch: parameter 'foo' not supported>
+%! fv_reduced = reducepatch (faces, vertices, .7, "foo");
+%!error <struct FV must contain the fields 'vertices' and 'faces'>
+%! fv_incomplete.faces = faces;
+%! reducepatch (fv_incomplete, .7);
+%!error <PATCH_HANDLE must be a valid handle to a patch> reducepatch (pi, .7)
+%!error <If first argument is a matrix containing FACES, second argument must be a matrix containing VERTICES> reducepatch (faces)
+%!error <REDUCTION_FACTOR must be a positive scalar> reducepatch (fv, [.7 .5])
+%!error <REDUCTION_FACTOR must be a positive scalar> reducepatch (fv, -5)
+%!error <VERTICES must be an Mx3 matrix> reducepatch (faces, .7, "v")
+%!error <reducepatch: Currently patches must consist of triangles only>
+%! faces_new = NaN (size (faces, 1), 4);
+%! faces_new(:,1:3) = faces;
+%! faces_new(1,4) = 5;
+%! reducepatch (faces_new, vertices);
+%!error <reducepatch: not enough VERTICES for given FACES>
+%! faces_new = faces;
+%! faces_new(1,3) = size (vertices, 1) + 1;
+%! reducepatch (faces_new, vertices);
+
# HG changeset patch
# User Rik <rik@octave.org>
# Date 1470786637 25200
#      Tue Aug 09 16:50:37 2016 -0700
# Node ID a4ff69a4f2398658f6452d80a98604ca8b16e1ff
# Parent  654de580bdb38d76a8fe1a016c45395e8c271c74
__unimplemented__.m: Don't print backtrace when issuing warning.

* __unimplemented__.m: Add "\n" to call to warning to stop backtrace.

diff -r 654de580bdb3 -r a4ff69a4f239 scripts/help/__unimplemented__.m
--- a/scripts/help/__unimplemented__.m	Mon Jul 18 19:54:34 2016 +0200
+++ b/scripts/help/__unimplemented__.m	Tue Aug 09 16:50:37 2016 -0700
@@ -515,7 +515,7 @@
   endif
 
   if (nargout == 0)
-    warning ("Octave:missing-function", "%s", txt);
+    warning ("Octave:missing-function", "%s\n", txt);
   endif
 
 endfunction
# HG changeset patch
# User Rik <rik@octave.org>
# Date 1470786936 25200
#      Tue Aug 09 16:55:36 2016 -0700
# Node ID 3d287a11ea18a096217e69552e3d2cfeca8e60da
# Parent  a4ff69a4f2398658f6452d80a98604ca8b16e1ff
doc: Clarify that reducepatch only works on patches, not surfaces.

* reducepatch.m: Remove language that says function works on surfaces.

diff -r a4ff69a4f239 -r 3d287a11ea18 scripts/plot/draw/reducepatch.m
--- a/scripts/plot/draw/reducepatch.m	Tue Aug 09 16:50:37 2016 -0700
+++ b/scripts/plot/draw/reducepatch.m	Tue Aug 09 16:55:36 2016 -0700
@@ -26,8 +26,8 @@
 ## @deftypefnx {} {@var{reduced_fv} =} reducepatch (@dots{}, "verbose")
 ## @deftypefnx {} {[@var{reduced_faces}, @var{reduces_vertices}] =} reducepatch (@dots{})
 ##
-## Reduce the number of faces and vertices in a surface or patch object while
-## retaining the overall shape of the patch.
+## Reduce the number of faces and vertices in a patch object while retaining
+## the overall shape of the patch.
 ##
 ## The input patch can be represented by a structure @var{fv} with the
 ## fields @code{faces} and @code{vertices}, by two matrices @var{faces} and
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470787011 -3600
#      Wed Aug 10 00:56:51 2016 +0100
# Node ID fa917f1f0faf45ddc46e574de7ddbc4942187b0d
# Parent  3d287a11ea18a096217e69552e3d2cfeca8e60da
MatrixType: remove duplicate code for SparseMatrix and ComplexSparseMatrix.

* liboctave/array/MatrixType.cc: constructor for SparseMatrix and
ComplexSparseMatrix is exactly the same.  With C++11, we have conj,
norm, real, and imag functions overloaded for double and float that
behave as we would want them to.

diff -r 3d287a11ea18 -r fa917f1f0faf liboctave/array/MatrixType.cc
--- a/liboctave/array/MatrixType.cc	Tue Aug 09 16:55:36 2016 -0700
+++ b/liboctave/array/MatrixType.cc	Wed Aug 10 00:56:51 2016 +0100
@@ -229,7 +229,9 @@
   typ = matrix_complex_probe (a);
 }
 
-MatrixType::MatrixType (const SparseMatrix &a)
+
+template <typename T>
+MatrixType::MatrixType (const MSparse<T>& a)
   : typ (MatrixType::Unknown),
     sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
     dense (false), full (false), nperm (0), perm (0)
@@ -504,9 +506,9 @@
                 {
                   if (a.ridx (i) == j)
                     {
-                      double d = a.data (i);
-                      is_herm = d > 0.;
-                      diag(j) = d;
+                      T d = a.data (i);
+                      is_herm = std::real (d) > 0.0 && std::imag (d) == 0.0;
+                      diag(j) = std::real (d);
                       break;
                     }
                 }
@@ -521,326 +523,8 @@
                 is_herm = k == j;
                 if (is_herm)
                   continue;
-                double d = a.data (i);
-                if (d*d < diag(j)*diag(k))
-                  {
-                    for (octave_idx_type l = a.cidx (k); l < a.cidx (k+1); l++)
-                      {
-                        if (a.ridx (l) == j)
-                          {
-                            is_herm = a.data (l) == d;
-                            break;
-                          }
-                      }
-                  }
-              }
 
-          if (is_herm)
-            {
-              if (typ == MatrixType::Full)
-                typ = MatrixType::Hermitian;
-              else if (typ == MatrixType::Banded)
-                typ = MatrixType::Banded_Hermitian;
-              else
-                typ = MatrixType::Tridiagonal_Hermitian;
-            }
-        }
-    }
-}
-
-MatrixType::MatrixType (const SparseComplexMatrix &a)
-  : typ (MatrixType::Unknown),
-    sp_bandden (0), bandden (0), upper_band (0), lower_band (0),
-    dense (false), full (false), nperm (0), perm (0)
-{
-  octave_idx_type nrows = a.rows ();
-  octave_idx_type ncols = a.cols ();
-  octave_idx_type nm = (ncols < nrows ? ncols : nrows);
-  octave_idx_type nnz = a.nnz ();
-
-  if (octave_sparse_params::get_key ("spumoni") != 0.)
-    warn_calculating_sparse_type ();
-
-  sp_bandden = octave_sparse_params::get_bandden ();
-  bool maybe_hermitian = false;
-  typ = MatrixType::Full;
-
-  if (nnz == nm)
-    {
-      matrix_type tmp_typ = MatrixType::Diagonal;
-      octave_idx_type i;
-      // Maybe the matrix is diagonal
-      for (i = 0; i < nm; i++)
-        {
-          if (a.cidx (i+1) != a.cidx (i) + 1)
-            {
-              tmp_typ = MatrixType::Full;
-              break;
-            }
-          if (a.ridx (i) != i)
-            {
-              tmp_typ = MatrixType::Permuted_Diagonal;
-              break;
-            }
-        }
-
-      if (tmp_typ == MatrixType::Permuted_Diagonal)
-        {
-          std::vector<bool> found (nrows);
-
-          for (octave_idx_type j = 0; j < i; j++)
-            found[j] = true;
-          for (octave_idx_type j = i; j < nrows; j++)
-            found[j] = false;
-
-          for (octave_idx_type j = i; j < nm; j++)
-            {
-              if ((a.cidx (j+1) > a.cidx (j) + 1)
-                  || ((a.cidx (j+1) == a.cidx (j) + 1) && found[a.ridx (j)]))
-                {
-                  tmp_typ = MatrixType::Full;
-                  break;
-                }
-              found[a.ridx (j)] = true;
-            }
-        }
-      typ = tmp_typ;
-    }
-
-  if (typ == MatrixType::Full)
-    {
-      // Search for banded, upper and lower triangular matrices
-      bool singular = false;
-      upper_band = 0;
-      lower_band = 0;
-      for (octave_idx_type j = 0; j < ncols; j++)
-        {
-          bool zero_on_diagonal = false;
-          if (j < nrows)
-            {
-              zero_on_diagonal = true;
-              for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-                if (a.ridx (i) == j)
-                  {
-                    zero_on_diagonal = false;
-                    break;
-                  }
-            }
-
-          if (zero_on_diagonal)
-            {
-              singular = true;
-              break;
-            }
-
-          if (a.cidx (j+1) != a.cidx (j))
-            {
-              octave_idx_type ru = a.ridx (a.cidx (j));
-              octave_idx_type rl = a.ridx (a.cidx (j+1)-1);
-
-              if (j - ru > upper_band)
-                upper_band = j - ru;
-
-              if (rl - j > lower_band)
-                lower_band = rl - j;
-            }
-        }
-
-      if (! singular)
-        {
-          bandden = double (nnz) /
-                    (double (ncols) * (double (lower_band) +
-                                       double (upper_band)) -
-                     0.5 * double (upper_band + 1) * double (upper_band) -
-                     0.5 * double (lower_band + 1) * double (lower_band));
-
-          if (nrows == ncols && sp_bandden != 1. && bandden > sp_bandden)
-            {
-              if (upper_band == 1 && lower_band == 1)
-                typ = MatrixType::Tridiagonal;
-              else
-                typ = MatrixType::Banded;
-
-              octave_idx_type nnz_in_band =
-                (upper_band + lower_band + 1) * nrows -
-                (1 + upper_band) * upper_band / 2 -
-                (1 + lower_band) * lower_band / 2;
-              if (nnz_in_band == nnz)
-                dense = true;
-              else
-                dense = false;
-            }
-
-          // If a matrix is Banded but also Upper/Lower, set to the latter.
-          if (upper_band == 0)
-            typ = MatrixType::Lower;
-          else if (lower_band == 0)
-            typ = MatrixType::Upper;
-
-          if (upper_band == lower_band && nrows == ncols)
-            maybe_hermitian = true;
-        }
-
-      if (typ == MatrixType::Full)
-        {
-          // Search for a permuted triangular matrix, and test if
-          // permutation is singular
-
-          // FIXME: Perhaps this should be based on a dmperm algorithm?
-          bool found = false;
-
-          nperm = ncols;
-          perm = new octave_idx_type [ncols];
-
-          for (octave_idx_type i = 0; i < ncols; i++)
-            perm[i] = -1;
-
-          for (octave_idx_type i = 0; i < nm; i++)
-            {
-              found = false;
-
-              for (octave_idx_type j = 0; j < ncols; j++)
-                {
-                  if ((a.cidx (j+1) - a.cidx (j)) > 0
-                      && (a.ridx (a.cidx (j+1)-1) == i))
-                    {
-                      perm[i] = j;
-                      found = true;
-                      break;
-                    }
-                }
-
-              if (! found)
-                break;
-            }
-
-          if (found)
-            {
-              typ = MatrixType::Permuted_Upper;
-              if (ncols > nrows)
-                {
-                  octave_idx_type k = nrows;
-                  for (octave_idx_type i = 0; i < ncols; i++)
-                    if (perm[i] == -1)
-                      perm[i] = k++;
-                }
-            }
-          else if (a.cidx (nm) == a.cidx (ncols))
-            {
-              nperm = nrows;
-              delete [] perm;
-              perm = new octave_idx_type [nrows];
-              OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, nrows);
-
-              for (octave_idx_type i = 0; i < nrows; i++)
-                {
-                  perm[i] = -1;
-                  tmp[i] = -1;
-                }
-
-              for (octave_idx_type j = 0; j < ncols; j++)
-                for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-                  perm[a.ridx (i)] = j;
-
-              found = true;
-              for (octave_idx_type i = 0; i < nm; i++)
-                if (perm[i] == -1)
-                  {
-                    found = false;
-                    break;
-                  }
-                else
-                  {
-                    tmp[perm[i]] = 1;
-                  }
-
-              if (found)
-                {
-                  octave_idx_type k = ncols;
-                  for (octave_idx_type i = 0; i < nrows; i++)
-                    {
-                      if (tmp[i] == -1)
-                        {
-                          if (k < nrows)
-                            {
-                              perm[k++] = i;
-                            }
-                          else
-                            {
-                              found = false;
-                              break;
-                            }
-                        }
-                    }
-                }
-
-              if (found)
-                typ = MatrixType::Permuted_Lower;
-              else
-                {
-                  delete [] perm;
-                  nperm = 0;
-                }
-            }
-          else
-            {
-              delete [] perm;
-              nperm = 0;
-            }
-        }
-
-      // FIXME: Disable lower under-determined and upper over-determined
-      //        problems as being detected, and force to treat as singular
-      //        as this seems to cause issues.
-      if (((typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
-           && nrows > ncols)
-          || ((typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
-              && nrows < ncols))
-        {
-          if (typ == MatrixType::Permuted_Upper
-              || typ == MatrixType::Permuted_Lower)
-            delete [] perm;
-          nperm = 0;
-          typ = MatrixType::Rectangular;
-        }
-
-      if (typ == MatrixType::Full && ncols != nrows)
-        typ = MatrixType::Rectangular;
-
-      if (maybe_hermitian && (typ == MatrixType::Full
-                              || typ == MatrixType::Tridiagonal
-                              || typ == MatrixType::Banded))
-        {
-          bool is_herm = true;
-
-          // first, check whether the diagonal is positive & extract it
-          ColumnVector diag (ncols);
-
-          for (octave_idx_type j = 0; is_herm && j < ncols; j++)
-            {
-              is_herm = false;
-              for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
-                {
-                  if (a.ridx (i) == j)
-                    {
-                      Complex d = a.data (i);
-                      is_herm = d.real () > 0. && d.imag () == 0.;
-                      diag(j) = d.real ();
-                      break;
-                    }
-                }
-            }
-
-          // next, check symmetry and 2x2 positiveness
-
-          for (octave_idx_type j = 0; is_herm && j < ncols; j++)
-            for (octave_idx_type i = a.cidx (j); is_herm && i < a.cidx (j+1); i++)
-              {
-                octave_idx_type k = a.ridx (i);
-                is_herm = k == j;
-                if (is_herm)
-                  continue;
-                Complex d = a.data (i);
+                T d = a.data (i);
                 if (std::norm (d) < diag(j)*diag(k))
                   {
                     d = std::conj (d);
@@ -867,6 +551,8 @@
         }
     }
 }
+
+
 MatrixType::MatrixType (const matrix_type t, bool _full)
   : typ (MatrixType::Unknown),
     sp_bandden (octave_sparse_params::get_bandden ()),
diff -r 3d287a11ea18 -r fa917f1f0faf liboctave/array/MatrixType.h
--- a/liboctave/array/MatrixType.h	Tue Aug 09 16:55:36 2016 -0700
+++ b/liboctave/array/MatrixType.h	Wed Aug 10 00:56:51 2016 +0100
@@ -26,6 +26,8 @@
 
 #include "octave-config.h"
 
+#include "MSparse.h"
+
 class Matrix;
 class ComplexMatrix;
 class FloatMatrix;
@@ -68,9 +70,8 @@
 
   MatrixType (const FloatComplexMatrix &a);
 
-  MatrixType (const SparseMatrix &a);
-
-  MatrixType (const SparseComplexMatrix &a);
+  template <typename T>
+  MatrixType (const MSparse<T> &a);
 
   MatrixType (const matrix_type t, bool _full = false);
 
# HG changeset patch
# User Markus Muetzel <markus.muetzel@gmx.de>
# Date 1468856765 -7200
#      Mon Jul 18 17:46:05 2016 +0200
# Node ID c8fc60a183a3fb4d96bccf26b8eb93553c77dbd2
# Parent  fa917f1f0faf45ddc46e574de7ddbc4942187b0d
Add function material. (patch #9013)

* scripts/plot/appearance/material.m: New function.

* scripts/plot/appearance/module.mk: Update build system.

* NEWS: Announce new function.

* __unimplemented__.m: Remove "material" from list.

* doc/interpreter/plot.txi: Add doc string.

* light.m: Add "material" to "see also".

diff -r fa917f1f0faf -r c8fc60a183a3 NEWS
--- a/NEWS	Wed Aug 10 00:56:51 2016 +0100
+++ b/NEWS	Mon Jul 18 17:46:05 2016 +0200
@@ -117,6 +117,7 @@
       hash
       im2double
       localfunctions
+      material
       normest1
       ode45
       odeget
diff -r fa917f1f0faf -r c8fc60a183a3 doc/interpreter/plot.txi
--- a/doc/interpreter/plot.txi	Wed Aug 10 00:56:51 2016 +0100
+++ b/doc/interpreter/plot.txi	Mon Jul 18 17:46:05 2016 +0200
@@ -398,6 +398,8 @@
 
 @DOCSTRING(lighting)
 
+@DOCSTRING(material)
+
 @DOCSTRING(meshgrid)
 
 @DOCSTRING(ndgrid)
diff -r fa917f1f0faf -r c8fc60a183a3 scripts/help/__unimplemented__.m
--- a/scripts/help/__unimplemented__.m	Wed Aug 10 00:56:51 2016 +0100
+++ b/scripts/help/__unimplemented__.m	Mon Jul 18 17:46:05 2016 +0200
@@ -713,7 +713,6 @@
   "lsqr",
   "makehgtform",
   "mapreduce",
-  "material",
   "matfile",
   "matlabrc",
   "memmapfile",
diff -r fa917f1f0faf -r c8fc60a183a3 scripts/plot/appearance/material.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/material.m	Mon Jul 18 17:46:05 2016 +0200
@@ -0,0 +1,312 @@
+## Copyright (C) 2016 Markus Muetzel
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {} material shiny
+## @deftypefnx {} {} material dull
+## @deftypefnx {} {} material metal
+## @deftypefnx {} {} material default
+## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}])
+## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}, @var{se}])
+## @deftypefnx {} {} material ([@var{as}, @var{ds}, @var{ss}, @var{se}, @var{scr}])
+## @deftypefnx {} {} material (@var{hlist}, @dots{})
+## @deftypefnx {} {@var{mtypes} =} material ()
+## @deftypefnx {} {@var{refl_props} =} material (@var{mtype_string})
+## Set reflectance properties for the lighting of surfaces and patches.
+##
+## This function changes the ambient, diffuse, and specular strengths, as well
+## as the specular exponent and specular color reflectance, of all
+## @code{patch} and @code{surface} objects in the current axes.  This can be
+## used to simulate, to some extent, the reflectance properties of certain
+## materials when used with @code{light}.
+##
+## When called with a string, the aforementioned properties are set
+## according to the values in the following table:
+##
+## @multitable @columnfractions .0 .2 .15 .15 .15 .15 .15 .0
+## @headitem @tab @var{mtype} @tab ambient- strength @tab diffuse-
+## strength @tab specular- strength @tab specular- exponent @tab specular-
+## color- reflectance @tab
+## @item @tab @qcode{"shiny"} @tab 0.3 @tab 0.6 @tab 0.9 @tab 20 @tab 1.0 @tab
+## @item @tab @qcode{"dull"} @tab 0.3 @tab 0.8 @tab 0.0 @tab 10 @tab 1.0 @tab
+## @item @tab @qcode{"metal"} @tab 0.3 @tab 0.3 @tab 1.0 @tab 25 @tab 0.5 @tab
+## @item @tab @qcode{"default"} @tab @qcode{"default"} @tab @qcode{"default"} @tab @qcode{"default"} @tab
+## @qcode{"default"} @tab @qcode{"default"} @tab
+## @end multitable
+##
+## When called with a vector of three elements, the ambient, diffuse, and
+## specular strengths of all @code{patch} and @code{surface} objects in the
+## current axes are updated.  An optional fourth vector element updates the
+## specular exponent, and an optional fifth vector element updates the
+## specular color reflectance.
+##
+## A list of graphic handles can also be passed as the first argument.  In
+## this case, the properties of these handles and all child @code{patch} and
+## @code{surface} objects will be updated.
+##
+## Additionally, @code{material} can be called with a single output argument.
+## If called without input arguments, a column cell vector @var{mtypes} with
+## the strings for all available materials is returned.  If the one input
+## argument @var{mtype_string} is the name of a material, a 1x5 cell vector
+## @var{refl_props} with the reflectance properties of that material is
+## returned.  In both cases, no graphic properties are changed.
+##
+## @seealso{light, fill, mesh, patch, pcolor, surf, surface}
+## @end deftypefn
+
+## Author: mmuetzel
+
+function retval = material (varargin)
+
+  if (! ((nargout == 0 && (nargin == 1 || nargin == 2)) ||
+         (nargout == 1 && (nargin == 0 || nargin == 1))) )
+    print_usage ();
+  endif
+
+  ## resolve input
+  if (nargout == 0)
+    ## Check whether first argument is list of graphics handles.
+    if (all (ishandle (varargin{1})))
+      h = varargin{1};
+      varargin(1) = [];
+    else
+      h = gca ();
+    endif
+
+    ## There must be one (additional) argument.
+    if (numel (varargin) != 1)
+      if (nargin == 2)
+        error (["material: When called with two arguments, the first argument " ...
+                "must be a list of handles to graphics objects."]);
+      else
+        print_usage ();
+      endif
+    endif
+  elseif (nargin == 0)
+    ## Return name of materials.
+    retval = {"shiny"; "dull"; "metal"; "default"};
+    return;
+  endif
+
+  mtype = varargin{1};
+
+  se = [];
+  scr = [];
+
+  ## check material type
+  if (ischar (mtype))
+    switch (lower (mtype))
+      case "shiny"
+        as = 0.3;
+        ds = 0.6;
+        ss = 0.9;
+        se = 20;
+        scr = 1.0;
+
+      case "dull"
+        as = 0.3;
+        ds = 0.8;
+        ss = 0.0;
+        se = 10;
+        scr = 1.0;
+
+      case "metal"
+        as = 0.3;
+        ds = 0.3;
+        ss = 1.0;
+        se = 25;
+        scr = .5;
+
+      case "default"
+        as = "default";
+        ds = "default";
+        ss = "default";
+        se = "default";
+        scr = "default";
+
+      otherwise
+        error ("material: unknown material type '%s'", mtype);
+
+    endswitch
+    
+    if (nargout == 1)
+      ## Return 1x5 cell vector with reflectance properties.
+      retval = {as, ds, ss, se, scr};
+      return;
+    endif
+
+  elseif (nargout == 1)
+    ## If we reach here with one output argument, the input was wrong.
+    print_usage ();
+
+  elseif (isvector (mtype))
+    num_mtype = numel (mtype);
+    if (num_mtype < 2 || num_mtype > 5)
+      error ("material: incorrect number of elements in material vector");
+    endif
+    as = mtype(1);
+    ds = mtype(2);
+    ss = mtype(3);
+    if (num_mtype >= 4)
+      se = mtype(4);
+      if (num_mtype == 5)
+        scr = mtype(5);
+      endif
+    endif
+
+  else
+    error ("material: MTYPE must be a named material or a vector");
+  endif
+
+  ## find all patch and surface objects in current axes
+  hps = findobj (h, "Type", "patch", "-or", "Type", "surface");
+
+  ## set properties
+  set (hps,
+       "ambientstrength", as, "diffusestrength", ds, "specularstrength", ss);
+
+  if (! isempty (se))
+    set (hps, "specularexponent", se);
+    if (! isempty (scr))
+      set (hps, "specularcolorreflectance", scr);
+    endif
+  endif
+
+endfunction
+
+
+%!demo
+%! clf;
+%! %% patch
+%! h_axes = axes;
+%! [x,y,z] = meshgrid (-2:0.2:2, -2:0.2:2, -2:0.2:2);
+%! val = x.^2 + y.^2 + z.^2;
+%! fv1 = isosurface (x, y, z, val, 1);
+%! h_patch = patch (fv1, "FaceColor", "r", "EdgeColor", "none", "FaceLighting", "Gouraud");
+%! isonormals (x, y, z, val, h_patch)
+%! axis equal; axis tight
+%! view (3)
+%! drawnow
+%! h_light = light ();
+%! material ([0 0.5 1 10 .5])
+
+%!demo
+%! clf
+%! %% surface
+%! h_axes = axes;
+%! h_surf = surf (h_axes, peaks, "LineStyle", "none", "FaceLighting", "Gouraud");
+%! view (3)
+%! h_light = light ();
+%! material metal
+
+%!test
+%! hf = figure ("Visible", "off");
+%! unwind_protect
+%!   hp = patch;
+%!   hs = surface;
+%!   material dull
+%!   assert (get (hp, "ambientstrength"), 0.3);
+%!   assert (get (hs, "ambientstrength"), 0.3);
+%!   assert (get (hp, "diffusestrength"), 0.8);
+%!   assert (get (hs, "diffusestrength"), 0.8);
+%!   assert (get (hp, "specularstrength"), 0.0);
+%!   assert (get (hs, "specularstrength"), 0.0);
+%!   assert (get (hp, "specularexponent"), 10);
+%!   assert (get (hs, "specularexponent"), 10);
+%!   assert (get (hp, "specularcolorreflectance"), 1.0);
+%!   assert (get (hs, "specularcolorreflectance"), 1.0);
+%!   material default
+%!   assert (get (hp, "ambientstrength"), get (0, "defaultpatchambientstrength"));
+%!   assert (get (hs, "ambientstrength"), get (0, "defaultsurfaceambientstrength"));
+%!   assert (get (hp, "diffusestrength"), get (0, "defaultpatchdiffusestrength"));
+%!   assert (get (hs, "diffusestrength"), get (0, "defaultsurfacediffusestrength"));
+%!   assert (get (hp, "specularstrength"), get (0, "defaultpatchspecularstrength"));
+%!   assert (get (hs, "specularstrength"), get (0, "defaultsurfacespecularstrength"));
+%!   assert (get (hp, "specularexponent"), get (0, "defaultpatchspecularexponent"));
+%!   assert (get (hs, "specularexponent"), get (0, "defaultsurfacespecularexponent"));
+%!   assert (get (hp, "specularcolorreflectance"), get (0, "defaultpatchspecularcolorreflectance"));
+%!   assert (get (hs, "specularcolorreflectance"), get (0, "defaultsurfacespecularcolorreflectance"));
+%!   material ([0.5 0.6 0.7 20 0.8])
+%!   assert (get (hp, "ambientstrength"), 0.5);
+%!   assert (get (hs, "ambientstrength"), 0.5);
+%!   assert (get (hp, "diffusestrength"), 0.6);
+%!   assert (get (hs, "diffusestrength"), 0.6);
+%!   assert (get (hp, "specularstrength"), 0.7);
+%!   assert (get (hs, "specularstrength"), 0.7);
+%!   assert (get (hp, "specularexponent"), 20);
+%!   assert (get (hs, "specularexponent"), 20);
+%!   assert (get (hp, "specularcolorreflectance"), 0.8);
+%!   assert (get (hs, "specularcolorreflectance"), 0.8);
+%!   material (hp, "shiny")
+%!   assert (get (hp, "ambientstrength"), 0.3);
+%!   assert (get (hs, "ambientstrength"), 0.5);
+%!   assert (get (hp, "diffusestrength"), 0.6);
+%!   assert (get (hs, "diffusestrength"), 0.6);
+%!   assert (get (hp, "specularstrength"), 0.9);
+%!   assert (get (hs, "specularstrength"), 0.7);
+%!   assert (get (hp, "specularexponent"), 20);
+%!   assert (get (hs, "specularexponent"), 20);
+%!   assert (get (hp, "specularcolorreflectance"), 1.0);
+%!   assert (get (hs, "specularcolorreflectance"), 0.8);
+%!   material (hf, "metal")
+%!   assert (get (hp, "ambientstrength"), 0.3);
+%!   assert (get (hs, "ambientstrength"), 0.3);
+%!   assert (get (hp, "diffusestrength"), 0.3);
+%!   assert (get (hs, "diffusestrength"), 0.3);
+%!   assert (get (hp, "specularstrength"), 1.0);
+%!   assert (get (hs, "specularstrength"), 1.0);
+%!   assert (get (hp, "specularexponent"), 25);
+%!   assert (get (hs, "specularexponent"), 25);
+%!   assert (get (hp, "specularcolorreflectance"), 0.5);
+%!   assert (get (hs, "specularcolorreflectance"), 0.5);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! mtypes = material ();
+%! assert (iscell (mtypes));
+%! assert (size (mtypes, 2), 1);
+%! assert (all (cellfun (@ischar, mtypes)));
+
+%!test
+%! refl_props = material ("metal");
+%! assert (refl_props, {0.3, 0.3, 1, 25, 0.5})
+
+## Test input validation
+%!error <Invalid call to material> material ()
+%!error <Invalid call to material> material (-1, 2, 3)
+%!error <Invalid call to material> a = material (-1)
+%!error <Invalid call to material> a = material (-1, 2)
+%!error <Invalid call to material> a = material ({})
+%!error <Invalid call to material> a = material ([.3 .4 .5])
+%!error <Invalid call to material> [a, b] = material ()
+%!error <first argument must be a list of handles> material (-1, "metal")
+%!error <unknown material type 'foo'> material foo
+%!error <incorrect number of elements in material vector> material (-1)
+%!error <incorrect number of elements in material vector> material ([1 2 3 4 5 6])
+%!error <MTYPE must be a named material or a vector> material ({})
+
+%!error <Invalid call to material.> 
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   material (hf);
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
diff -r fa917f1f0faf -r c8fc60a183a3 scripts/plot/appearance/module.mk
--- a/scripts/plot/appearance/module.mk	Wed Aug 10 00:56:51 2016 +0100
+++ b/scripts/plot/appearance/module.mk	Mon Jul 18 17:46:05 2016 +0200
@@ -22,6 +22,7 @@
   scripts/plot/appearance/hidden.m \
   scripts/plot/appearance/legend.m \
   scripts/plot/appearance/lighting.m \
+  scripts/plot/appearance/material.m \
   scripts/plot/appearance/orient.m \
   scripts/plot/appearance/pbaspect.m \
   scripts/plot/appearance/shading.m \
diff -r fa917f1f0faf -r c8fc60a183a3 scripts/plot/draw/light.m
--- a/scripts/plot/draw/light.m	Wed Aug 10 00:56:51 2016 +0100
+++ b/scripts/plot/draw/light.m	Mon Jul 18 17:46:05 2016 +0200
@@ -59,7 +59,7 @@
 ##
 ## Optionally, the handle to the light object is returned in @var{h}.
 ##
-## @seealso{get, set, patch, surface, lighting}
+## @seealso{get, set, patch, surface, lighting, material}
 ## @end deftypefn
 
 ## Author: mmuetzel
# HG changeset patch
# User Carnë Draug <carandraug@octave.org>
# Date 1470797798 -3600
#      Wed Aug 10 03:56:38 2016 +0100
# Node ID 60986498af9e1c03d4363f0d3c41feea1510aaaa
# Parent  c8fc60a183a3fb4d96bccf26b8eb93553c77dbd2
svd: use std::vector instead of Matrix when a std::vector is enough.

* liboctave/numeric/svd.cc, liboctave/numeric/svd.h: Matrix<T> was
being used only to create an array for work by the fortran subroutines.
Use std::vector which is lighter but still provides RIIA idiom.

diff -r c8fc60a183a3 -r 60986498af9e liboctave/numeric/svd.cc
--- a/liboctave/numeric/svd.cc	Mon Jul 18 17:46:05 2016 +0200
+++ b/liboctave/numeric/svd.cc	Wed Aug 10 03:56:38 2016 +0100
@@ -29,6 +29,7 @@
 
 #include <cassert>
 #include <algorithm>
+#include <vector>
 
 #include "CMatrix.h"
 #include "dDiagMatrix.h"
@@ -156,7 +157,7 @@
   F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1),            \
                    F77_CONST_CHAR_ARG2 (&jobv, 1),            \
                    m, n, tmp_data, m1, s_vec, u, m1, vt,      \
-                   nrow_vt1, work.fortran_vec (), lwork, info \
+                   nrow_vt1, work.data (), lwork, info \
                    F77_CHAR_ARG_LEN (1)                       \
                    F77_CHAR_ARG_LEN (1)))
 
@@ -166,8 +167,8 @@
                    m, n, CMPLX_ARG (tmp_data),        \
                    m1, s_vec, CMPLX_ARG (u), m1,      \
                    CMPLX_ARG (vt), nrow_vt1,          \
-                   CMPLX_ARG (work.fortran_vec ()),   \
-                   lwork, rwork.fortran_vec (), info  \
+                   CMPLX_ARG (work.data ()),   \
+                   lwork, rwork.data (), info         \
                    F77_CHAR_ARG_LEN (1)               \
                    F77_CHAR_ARG_LEN (1)))
 
@@ -177,13 +178,13 @@
 svd<Matrix>::gesvd (char& jobu, char& jobv, octave_idx_type m,
                     octave_idx_type n, double* tmp_data, octave_idx_type m1,
                     double* s_vec, double* u, double* vt,
-                    octave_idx_type nrow_vt1, Matrix& work,
+                    octave_idx_type nrow_vt1, std::vector<double>& work,
                     octave_idx_type& lwork, octave_idx_type& info)
 {
   GESVD_REAL_STEP (dgesvd, DGESVD);
 
-  lwork = static_cast<octave_idx_type> (work(0));
-  work.resize (lwork, 1);
+  lwork = work[0];
+  work.reserve (lwork);
 
   GESVD_REAL_STEP (dgesvd, DGESVD);
 }
@@ -194,13 +195,13 @@
 svd<FloatMatrix>::gesvd (char& jobu, char& jobv, octave_idx_type m,
                          octave_idx_type n, float* tmp_data,
                          octave_idx_type m1, float* s_vec, float* u, float* vt,
-                         octave_idx_type nrow_vt1, FloatMatrix& work,
+                         octave_idx_type nrow_vt1, std::vector<float>& work,
                          octave_idx_type& lwork, octave_idx_type& info)
 {
   GESVD_REAL_STEP (sgesvd, SGESVD);
 
-  lwork = static_cast<octave_idx_type> (work(0));
-  work.resize (lwork, 1);
+  lwork = work[0];
+  work.reserve (lwork);
 
   GESVD_REAL_STEP (sgesvd, SGESVD);
 }
@@ -212,15 +213,15 @@
                            octave_idx_type n, Complex* tmp_data,
                            octave_idx_type m1, double* s_vec, Complex* u,
                            Complex* vt, octave_idx_type nrow_vt1,
-                           ComplexMatrix& work,
+                           std::vector<Complex>& work,
                            octave_idx_type& lwork, octave_idx_type& info)
 {
-  Matrix rwork (5 * std::max (m, n), 1);
+  std::vector<double> rwork (5 * std::max (m, n));
 
   GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG);
 
-  lwork = static_cast<octave_idx_type> (work(0).real ());
-  work.resize (lwork, 1);
+  lwork = work[0].real ();
+  work.reserve (lwork);
 
   GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG);
 }
@@ -233,15 +234,15 @@
                                 FloatComplex* tmp_data, octave_idx_type m1,
                                 float* s_vec, FloatComplex* u,
                                 FloatComplex* vt, octave_idx_type nrow_vt1,
-                                FloatComplexMatrix& work,
+                                std::vector<FloatComplex>& work,
                                 octave_idx_type& lwork, octave_idx_type& info)
 {
-  FloatMatrix rwork (5 * std::max (m, n), 1);
+  std::vector<float> rwork (5 * std::max (m, n));
 
   GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG);
 
-  lwork = static_cast<octave_idx_type> (work(0).real ());
-  work.resize (lwork, 1);
+  lwork = work[0].real ();
+  work.reserve (lwork);
 
   GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG);
 }
@@ -255,7 +256,7 @@
 #define GESDD_REAL_STEP(f, F)                                       \
   F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1),                  \
                    m, n, tmp_data, m1, s_vec, u, m1, vt, nrow_vt1,  \
-                   work.fortran_vec (), lwork, iwork, info          \
+                   work.data (), lwork, iwork, info                 \
                    F77_CHAR_ARG_LEN (1)))
 
 #define GESDD_COMPLEX_STEP(f, F, CMPLX_ARG)                 \
@@ -263,8 +264,8 @@
                    CMPLX_ARG (tmp_data), m1,                \
                    s_vec, CMPLX_ARG (u), m1,                \
                    CMPLX_ARG (vt), nrow_vt1,                \
-                   CMPLX_ARG (work.fortran_vec ()), lwork,  \
-                   rwork.fortran_vec (), iwork, info        \
+                   CMPLX_ARG (work.data ()), lwork,         \
+                   rwork.data (), iwork, info               \
                    F77_CHAR_ARG_LEN (1)))
 
 // DGESDD
@@ -274,13 +275,13 @@
                     double* tmp_data, octave_idx_type m1,
                     double* s_vec, double* u,
                     double* vt, octave_idx_type nrow_vt1,
-                    Matrix& work, octave_idx_type& lwork,
+                    std::vector<double>& work, octave_idx_type& lwork,
                     octave_idx_type* iwork, octave_idx_type& info)
 {
   GESDD_REAL_STEP (dgesdd, DGESDD);
 
-  lwork = static_cast<octave_idx_type> (work(0));
-  work.resize (lwork, 1);
+  lwork = work[0];
+  work.reserve (lwork);
 
   GESDD_REAL_STEP (dgesdd, DGESDD);
 }
@@ -292,13 +293,13 @@
                          float* tmp_data, octave_idx_type m1,
                          float* s_vec, float* u,
                          float* vt, octave_idx_type nrow_vt1,
-                         FloatMatrix& work, octave_idx_type& lwork,
+                         std::vector<float>& work, octave_idx_type& lwork,
                          octave_idx_type* iwork, octave_idx_type& info)
 {
   GESDD_REAL_STEP (sgesdd, SGESDD);
 
-  lwork = static_cast<octave_idx_type> (work(0));
-  work.resize (lwork, 1);
+  lwork = work[0];
+  work.reserve (lwork);
 
   GESDD_REAL_STEP (sgesdd, SGESDD);
 }
@@ -310,7 +311,7 @@
                            Complex* tmp_data, octave_idx_type m1,
                            double* s_vec, Complex* u,
                            Complex* vt, octave_idx_type nrow_vt1,
-                           ComplexMatrix& work, octave_idx_type& lwork,
+                           std::vector<Complex>& work, octave_idx_type& lwork,
                            octave_idx_type* iwork, octave_idx_type& info)
 {
 
@@ -321,13 +322,13 @@
     lrwork = 7*min_mn;
   else
     lrwork = 5*min_mn*min_mn + 5*min_mn;
-  Matrix rwork (lrwork, 1);
 
+  std::vector<double> rwork (lrwork);
 
   GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG);
 
-  lwork = static_cast<octave_idx_type> (work(0).real ());
-  work.resize (lwork, 1);
+  lwork = work[0].real ();
+  work.reserve (lwork);
 
   GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG);
 }
@@ -340,7 +341,7 @@
                                 FloatComplex* tmp_data, octave_idx_type m1,
                                 float* s_vec, FloatComplex* u,
                                 FloatComplex* vt, octave_idx_type nrow_vt1,
-                                FloatComplexMatrix& work,
+                                std::vector<FloatComplex>& work,
                                 octave_idx_type& lwork, octave_idx_type* iwork,
                                 octave_idx_type& info)
 {
@@ -352,12 +353,12 @@
     lrwork = 5*min_mn;
   else
     lrwork = min_mn * std::max (5*min_mn+7, 2*max_mn+2*min_mn+1);
-  FloatMatrix rwork (lrwork, 1);
+  std::vector<float> rwork (lrwork);
 
   GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG);
 
-  lwork = static_cast<octave_idx_type> (work(0).real ());
-  work.resize (lwork, 1);
+  lwork = work[0].real ();
+  work.reserve (lwork);
 
   GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG);
 }
@@ -459,7 +460,7 @@
 
   octave_idx_type lwork = -1;
 
-  T work (1, 1);
+  std::vector<P> work (1);
 
   octave_idx_type m1 = std::max (m, 1);
   octave_idx_type nrow_vt1 = std::max (nrow_vt, 1);
@@ -472,10 +473,10 @@
       assert (jobu == jobv);
       char jobz = jobu;
 
-      OCTAVE_LOCAL_BUFFER (octave_idx_type, iwork, 8 * std::min (m, n));
+      std::vector<octave_idx_type> iwork (8 * std::min (m, n));
 
       gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1,
-             work, lwork, iwork, info);
+             work, lwork, iwork.data (), info);
     }
   else
     abort ();
diff -r c8fc60a183a3 -r 60986498af9e liboctave/numeric/svd.h
--- a/liboctave/numeric/svd.h	Mon Jul 18 17:46:05 2016 +0200
+++ b/liboctave/numeric/svd.h	Wed Aug 10 03:56:38 2016 +0100
@@ -26,6 +26,8 @@
 
 #include "octave-config.h"
 
+#include "vector"
+
 template <typename T>
 class
 svd
@@ -95,12 +97,13 @@
 
   void gesvd (char& jobu, char& jobv, octave_idx_type m, octave_idx_type n,
               P* tmp_data, octave_idx_type m1, DM_P* s_vec, P* u, P* vt,
-              octave_idx_type nrow_vt1, T& work, octave_idx_type& lwork,
+              octave_idx_type nrow_vt1, std::vector<P>& work, octave_idx_type& lwork,
               octave_idx_type& info);
 
   void gesdd (char& jobz, octave_idx_type m, octave_idx_type n,
               P* tmp_data, octave_idx_type m1, DM_P* s_vec, P* u, P* vt,
-              octave_idx_type nrow_vt1, T& work, octave_idx_type& lwork,
+              octave_idx_type nrow_vt1, std::vector<P>& work,
+              octave_idx_type& lwork,
               octave_idx_type* iwork, octave_idx_type& info);
 
 };
# HG changeset patch
# User Kai T. Ohlhus <k.ohlhus@gmail.com>
# Date 1470812981 -7200
#      Wed Aug 10 09:09:41 2016 +0200
# Node ID da201af35c9720bf58c53936d6330cbff6416f8f
# Parent  60986498af9e1c03d4363f0d3c41feea1510aaaa
maint: properly include <vector> in svd classes.

* liboctave/numeric/gsvd.cc: insert missing include.

* liboctave/numeric/svd.h: use <> rather than "".

* liboctave/numeric/svd.cc: remove include, done in the header already.

diff -r 60986498af9e -r da201af35c97 liboctave/numeric/gsvd.cc
--- a/liboctave/numeric/gsvd.cc	Wed Aug 10 03:56:38 2016 +0100
+++ b/liboctave/numeric/gsvd.cc	Wed Aug 10 09:09:41 2016 +0200
@@ -26,6 +26,8 @@
 #include "dDiagMatrix.h"
 #include "dMatrix.h"
 
+#include <vector>
+
 extern "C"
 {
   F77_RET_T
diff -r 60986498af9e -r da201af35c97 liboctave/numeric/svd.cc
--- a/liboctave/numeric/svd.cc	Wed Aug 10 03:56:38 2016 +0100
+++ b/liboctave/numeric/svd.cc	Wed Aug 10 09:09:41 2016 +0200
@@ -29,7 +29,6 @@
 
 #include <cassert>
 #include <algorithm>
-#include <vector>
 
 #include "CMatrix.h"
 #include "dDiagMatrix.h"
diff -r 60986498af9e -r da201af35c97 liboctave/numeric/svd.h
--- a/liboctave/numeric/svd.h	Wed Aug 10 03:56:38 2016 +0100
+++ b/liboctave/numeric/svd.h	Wed Aug 10 09:09:41 2016 +0200
@@ -26,7 +26,7 @@
 
 #include "octave-config.h"
 
-#include "vector"
+#include <vector>
 
 template <typename T>
 class
# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1470919341 -7200
#      Thu Aug 11 14:42:21 2016 +0200
# Node ID eea02e17c6b8a0b1fe01e4981eba1b6c2eda8371
# Parent  fafe2c4289d968a900af8611cc614aa29fadcc24
just added docs for methods feval

diff -r fafe2c4289d9 -r eea02e17c6b8 libinterp/parse-tree/oct-parse.in.yy
--- a/libinterp/parse-tree/oct-parse.in.yy	Wed Aug 03 23:01:14 2016 +0200
+++ b/libinterp/parse-tree/oct-parse.in.yy	Thu Aug 11 14:42:21 2016 +0200
@@ -4765,11 +4765,14 @@
   return retval;
 }
 
-// Evaluate an Octave function (built-in or interpreted) and return
-// the list of result values.  NAME is the name of the function to
-// call.  ARGS are the arguments to the function.  NARGOUT is the
-// number of output arguments expected.
-
+//! Evaluate an Octave function (built-in or interpreted) and return
+//! the list of result values.  
+//!
+//! @param name the name of the function to call.  
+//! @param args the arguments to the function.  
+//! @param nargout the number of output arguments expected.
+//! @return the list of output values with length @nargout, 
+//! except if the function is not defined.
 octave_value_list
 feval (const std::string& name, const octave_value_list& args, int nargout)
 {
@@ -4778,7 +4781,9 @@
   octave_value fcn = symbol_table::find_function (name, args);
 
   if (fcn.is_defined ())
-    retval = fcn.do_multi_index_op (nargout, args);
+    {
+       retval = fcn.do_multi_index_op (nargout, args);
+    }
   else
     {
       try
@@ -4812,12 +4817,15 @@
 }
 
 
-// Evaluate an Octave function (built-in or interpreted) and return
-// the list of result values.  The first element of ARGS should be a
-// string containing the name of the function to call, then the rest
-// are the actual arguments to the function.  NARGOUT is the number of
-// output arguments expected.
-
+//! Evaluate an Octave function (built-in or interpreted) and return
+//! the list of result values.  
+//! 
+//! @param args The first element of @c args should be a
+//!   string containing the name of the function to call, then the rest
+//!   are the actual arguments to the function.  
+//! @param nargout the number of output arguments expected.
+//! @return the list of output values with length @nargout.
+// really needed? ise feval (string name,... instead) 
 octave_value_list
 feval (const octave_value_list& args, int nargout)
 {
# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1470919985 -7200
#      Thu Aug 11 14:53:05 2016 +0200
# Node ID 021640103c8943ec76affe2ce801a5450d58291e
# Parent  eea02e17c6b8a0b1fe01e4981eba1b6c2eda8371
mainly reformatting.

diff -r eea02e17c6b8 -r 021640103c89 scripts/java/org/octave/ClassHelper.java
--- a/scripts/java/org/octave/ClassHelper.java	Thu Aug 11 14:42:21 2016 +0200
+++ b/scripts/java/org/octave/ClassHelper.java	Thu Aug 11 14:53:05 2016 +0200
@@ -33,7 +33,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
+//import java.lang.reflect.Modifier;
 
 //! Collection of methods being the core of the octave functions
 //! forming Octave's Java Interface.
@@ -77,8 +77,8 @@
 //! used by @file javaArray.m defining @c javaArray.
 public class ClassHelper
 {
-  //! The loader for the dynamic classpath 
-  //! delegating to the loader for the static classpath. 
+  //! The loader for the dynamic classpath
+  //! delegating to the loader for the static classpath.
   private static OctClassLoader loader;
 
   static
@@ -91,23 +91,23 @@
   //! with the former classloader as parent.
   private static OctClassLoader octClsLoader() {
     ClassLoader l = ClassHelper.class.getClassLoader ();
-    return l instanceof OctClassLoader 
-      ? (OctClassLoader) l 
+    return l instanceof OctClassLoader
+      ? (OctClassLoader) l
       : new OctClassLoader (l);
   }
 
   //! Add the given path @c path to the (dynamic) classpath.
   //! Used by @file javaaddpath.m only.
   //!
-  //! @param path 
+  //! @param path
   //!    path to add to the classpath.
   //!    This could be e.g. (examples for Unix)
   //!    <code>/home/charles</code>, <code>~/Octave</code>
   //!    or <code>../Software</code>.
-  //! @return 
+  //! @return
   //!    whether the given path exists and was thus added to the classpath.
   //! @throws MalformedURLException
-  //!    if conversion from URI representing @c path to URL fails. 
+  //!    if conversion from URI representing @c path to URL fails.
   //!    This should not occur if @c path points to a file.
   public static boolean addClassPath (String path)
     throws MalformedURLException
@@ -115,7 +115,6 @@
     File f = new File (path);
     if (f.exists ())
       {
-//        loader.addClassPath (path);
         // file2url may throw MalformedURLException
         loader.addURL (file2url(f));
         return true;
@@ -134,7 +133,7 @@
   //! @throws MalformedURLException
   //!    if conversion from URI representing @c path to URL fails.
   //!    This should not occur if @c path points to a file.
-    public static boolean removeClassPath (String path)
+  public static boolean removeClassPath (String path)
     throws MalformedURLException
   {
     boolean found = false;
@@ -163,7 +162,7 @@
             // path to be re-added
             loader.addURL (url);
           }
-       }
+      }
 
     return found;
   }
@@ -238,7 +237,6 @@
     return file.toURI ().toURL ();
   }
 
-
   // new -MH-
   //! Return a list of public methods
   //! of the class with the given class name @c classname
@@ -256,11 +254,10 @@
     throws ClassNotFoundException
   {
     return getMethods (Class.forName (classname));
-    // FIXME: ****
+    // FIXME: missing involving OctClassloader
     //return getMethods (Class.forName (classname, true, loader));
   }
 
-
   // new -MH-
   //! Return a list of public methods
   //! of the class of the instance @c obj.
@@ -278,7 +275,6 @@
     return getMethods (obj.getClass ());
   }
 
-
   // new -MH-
   //! Return list of public
   //! methods for given class @c klass.
@@ -290,7 +286,7 @@
   //! @param klass
   //!    the class under consideration.
   //! @return
-  //!    the list of methods for given class @c klass as a string, 
+  //!    the list of methods for given class @c klass as a string,
   //!    the signatures of the methods separated by <code>;</code>.
   public static String getMethods (Class klass)
   {
@@ -304,12 +300,12 @@
             sb.append (';');
           }
 
-        // Return type and name 
+        // Return type and name
         sb.append (theMethod[i].getReturnType ().getCanonicalName ());
         sb.append (' ');
         sb.append (theMethod[i].getName ());
 
-        // parameter list 
+        // parameter list
         sb.append ('(');
         Class theParameter[] = theMethod[i].getParameterTypes ();
         for (int j = 0; j < theParameter.length; j++)
@@ -322,13 +318,13 @@
           }
         sb.append (')');
 
-        // exceptions 
+        // exceptions
         Class theExceptions[] = theMethod[i].getExceptionTypes ();
         if (theExceptions.length > 0)
           {
             sb.append (" throws ");
             sb.append (theExceptions[0].getCanonicalName ());
-             for (int j = 1; j < theExceptions.length; j++)
+            for (int j = 1; j < theExceptions.length; j++)
               {
                 sb.append (", ");
                 sb.append (theExceptions[j].getCanonicalName ());
@@ -339,7 +335,6 @@
     return sb.toString ();
   }
 
-
   // new -MH-
   //! Return a list of all accessible public fields
   //! of the given class @c klass.
@@ -350,7 +345,7 @@
   //!
   //! @param klass
   //!    the class under consideration.
-  //! @return 
+  //! @return
   //!    the list of names of accessible public fields
   //!    of the given class @c klass
   //!    as a string, separated by <code>;</code>.
@@ -371,7 +366,6 @@
     return sb.toString ();
   }
 
-
   // new -MH-
   //! Return a list of all accessible public fields
   //! of the class with the given class name @c classname
@@ -389,10 +383,10 @@
     throws ClassNotFoundException
   {
     return getFields (Class.forName (classname));
-//    return getFields (Class.forName (classname, true, loader));
+    // FIXME: should involve OctClassLoader
+    //    return getFields (Class.forName (classname, true, loader));
   }
 
-
   // new -MH-
   //! Return a list of all accessible public fields
   //! of class of the instance @c obj.
@@ -448,6 +442,7 @@
                 return m;
               }
           }
+
         return null;
       }
   }
@@ -476,11 +471,9 @@
     catch (NoSuchMethodException e)
       {
         Constructor[] cList = cls.getConstructors ();
-        //System.out.println("# constructors: " + cList.length);
         Constructor c;
         for (int i = 0; i < cList.length; i++)
           {
-            //System.out.println("Considering constructor: " + cList[i]);
             c = cList[i];
             if (c.getParameterTypes ().length == argTypes.length
                 && isCallableFrom (c, argTypes))
@@ -492,7 +485,7 @@
       }
   }
 
-  //! Invoke method @c mthd on the object @c target with arguments @c args. 
+  //! Invoke method @c mthd on the object @c target with arguments @c args.
   //!
   //! @param mthd
   //!    the method to be invoked.
@@ -519,71 +512,69 @@
   private static Object invokeMethod (Method mthd, Object target, Object[] args)
     throws InvocationTargetException, IllegalAccessException
   {
-    //if (Modifier.isPublic(mthd.getModifiers()))
-    try 
+    // FIXME: maybe the following is a better solution: 
+    // if (Modifier.isPublic(mthd.getModifiers()))...
+    try
       {
-        // may throw InvocationTargetException, 
+        // may throw InvocationTargetException,
         // but no IllegalAccessException
         return mthd.invoke (target, args);
       }
     catch (IllegalAccessException ex)
       {
-        // FIXME: is this really wanted? 
+        // FIXME: is this really wanted?
         String mName   = mthd.getName ();
         Class[] pTypes = mthd.getParameterTypes ();
  
-        // search in target class and in superclasses. 
+        // search in target class and in superclasses.
         for (Class currClass = target.getClass ();
-             currClass != null; 
+             currClass != null;
              currClass = currClass.getSuperclass ())
           {
             try
               {
-                //  may throw NoSuchMethodException
+                // may throw NoSuchMethodException
                 Method meth = currClass.getMethod (mName, pTypes);
                 if (!meth.equals (mthd))
                   {
-                    // may throw InvocationTargetException, 
+                    // may throw InvocationTargetException,
                     // IllegalAccessException
                     return meth.invoke (target, args);
                   }
               }
-            catch (NoSuchMethodException ex2) // NOPMD
+            catch (NoSuchMethodException ex2) // NOPMD: rulecheck suspended
               {
-                // empty catch is really ok: just go on searching 
+                // empty catch is really ok: just go on searching
               }
 
-            // FIXME: I am pretty sure, that this finds no further methods 
-            // and shall thus be removed (ER). 
+            // FIXME: I am pretty sure, that this finds no further methods
+            // and shall thus be removed (ER).
             Class[] ifaceList = currClass.getInterfaces ();
             for (int i = 0; i < ifaceList.length; i++)
               {
                 try
                   {
-                    //  may throw NoSuchMethodException
+                    // may throw NoSuchMethodException
                     Method meth = ifaceList[i].getMethod (mName, pTypes);
                     // may throw InvocationTargetException
                     return meth.invoke (target, args);
                   }
-                catch (NoSuchMethodException ex2) // NOPMD
+                catch (NoSuchMethodException ex2) // NOPMD: rulecheck suspended
                   {
-                    // empty catch is really ok: just go on searching 
+                    // empty catch is really ok: just go on searching
                   }
-              } // for 
-          } // for 
-        // throws IllegalAccessException 
+              }
+          }
+        // throws IllegalAccessException
         throw ex;
-     } // catch IllegalAccessException 
+      } // catch IllegalAccessException
   }
 
-
-  // Used internally and by 
-  // #do_javaMethod(void*, std::string&, octave_value_list&) 
-  // in <code>ov-java.cc</code> only. 
+  // Used internally and by
+  // #do_javaMethod(void*, std::string&, octave_value_list&)
+  // in <code>ov-java.cc</code> only.
   // getField(Object, String)
-  public static Object invokeMethod (Object target, 
-                                     String name,
-                                     Object[] args, 
+  public static Object invokeMethod (Object target, String name, Object[] args,
                                      Class[] argTypes)
     throws Throwable
   {
@@ -607,22 +598,17 @@
 
   }
 
-  // using loader 
-  // Used internally and by @file ov-java.cc only. 
+  // using loader
+  // Used internally and by @file ov-java.cc only.
   // getStaticField(String, String)
-  public static Object invokeStaticMethod (String cls, 
-                                           String name,
-                                           Object[] args, 
-                                           Class[] argTypes)
-    throws ClassNotFoundException, 
-    NoSuchMethodException, 
-    IllegalAccessException, 
-    Throwable
+  public static Object invokeStaticMethod (String cls, String name, 
+                                           Object[] args, Class[] argTypes)
+    throws ClassNotFoundException, NoSuchMethodException,
+    IllegalAccessException, Throwable
   {
-    // forName may throw ClassNotFoundException 
+    // forName may throw ClassNotFoundException
     Method m = findMethod (Class.forName (cls, true, loader), 
-                           name,
-                           argTypes);
+                           name, argTypes);
     if (m == null)
       {
         throw new NoSuchMethodException (name);
@@ -638,15 +624,14 @@
       }
     catch (InvocationTargetException ex)
       {
-        // may throw general Throwable 
+        // may throw general Throwable
         throw ex.getCause ();
       }
   }
 
-  // using loader 
-  // Used @file ov-java.cc only. 
-  public static Object invokeConstructor (String cls, 
-                                          Object[] args,
+  // using loader
+  // Used @file ov-java.cc only.
+  public static Object invokeConstructor (String cls, Object[] args,
                                           Class[] argTypes)
     throws Throwable
   {
@@ -676,18 +661,18 @@
   //! @param target
   //!    an object to query a field which shall not be @c null.
   //! @param name
-  //!    the name of the field of @c target 
-  //!    which shall not be @c null. 
-  //! @throws NoSuchFieldException 
+  //!    the name of the field of @c target
+  //!    which shall not be @c null.
+  //! @throws NoSuchFieldException
   //!    if @c target has no field with the given name.
   //! @throws IllegalAccessException
-  //!    if the field @c name of object @c target is not accessible. 
+  //!    if the field @c name of object @c target is not accessible.
   public static Object getField (Object target, String name)
     throws NoSuchFieldException, IllegalAccessException, Throwable
   {
     try
       {
-        // getField may throw NoSuchFieldException 
+        // getField may throw NoSuchFieldException
         //   if a field with the specified name is not found.
         // get may throw IllegalAccessException
         return target.getClass ().getField (name).get (target);
@@ -696,7 +681,7 @@
       {
         try
           {
-            // may throw Throwable if so does method name() 
+            // may throw Throwable if so does method name()
             return invokeMethod (target, name, new Object[0], new Class[0]);
           }
         catch (NoSuchMethodException ex2)
@@ -706,24 +691,22 @@
       }
   }
 
-  // based on loader 
-  // Used by @file ov-java.cc only. 
+  // based on loader
+  // Used by @file ov-java.cc only.
   public static Object getStaticField (String cls, String name)
-    throws ClassNotFoundException, 
-    NoSuchFieldException, 
-    IllegalAccessException, 
-    Throwable
+    throws ClassNotFoundException, NoSuchFieldException, 
+    IllegalAccessException, Throwable
   {
     try
       {
-        // getField may throw NoSuchFieldException 
+        // getField may throw NoSuchFieldException
         //   if a field with the specified name is not found.
         // get may throw IllegalAccessException
         return Class.forName (cls, true, loader).getField (name).get (null);
       }
     catch (NoSuchFieldException ex)
       {
-        // FIXME: is this really appropriate? 
+        // FIXME: is this really appropriate?
         try
           {
             return invokeStaticMethod (cls, name, new Object[0], new Class[0]);
@@ -735,29 +718,28 @@
       }
   }
 
-  // Used by @file ov-java.cc only. 
+  // Used by @file ov-java.cc only.
   public static void setField (Object target, String name, Object value)
     throws NoSuchFieldException, IllegalAccessException
   {
     // getField may throw NoSuchFieldException
     Field f = target.getClass ().getField (name);
-    // set may throw IllegalAccessException 
+    // set may throw IllegalAccessException
     f.set (target, castArgument (value, value.getClass (), f.getType ()));
   }
 
-  // based on loader 
-  // Used by @file ov-java.cc only. 
+  // based on loader
+  // Used by @file ov-java.cc only.
   public static void setStaticField (String cls, String name, Object value)
     throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException
   {
-    // forName may throw ClassNotFoundException 
+    // forName may throw ClassNotFoundException
     // getField may throw NoSuchFieldException
     Field f = Class.forName (cls, true, loader).getField (name);
-    // set may throw IllegalAccessException 
+    // set may throw IllegalAccessException
     f.set (null, castArgument (value, value.getClass (), f.getType ()));
   }
 
-
   private static boolean isCallableFrom (Method m, Class[] argTypes)
   {
     Class[] expTypes = m.getParameterTypes ();
@@ -771,7 +753,6 @@
     return true;
   }
 
-
   private static boolean isCallableFrom (Constructor c, Class[] argTypes)
   {
     Class[] expTypes = c.getParameterTypes ();
@@ -785,10 +766,8 @@
     return true;
   }
 
-
   private static boolean isCallableFrom (Class expCls, Class argCls)
   {
-    //System.out.println("isCallableFrom: "+expCls.getCanonicalName() + " <=? " + argCls.getCanonicalName());
     if (argCls == null)
       {
         return !expCls.isPrimitive ();
@@ -800,12 +779,12 @@
       }
 
     if ((isNumberClass (expCls) || isBooleanClass (expCls))
-             && isNumberClass (argCls))
+        && isNumberClass (argCls))
       {
         return true;
       }
 
-   if (isCharClass (expCls) && argCls.equals (Character.class))
+    if (isCharClass (expCls) && argCls.equals (Character.class))
       {
         /*
           modified into a more strict check to avoid char to string matching
@@ -831,20 +810,18 @@
       }
 
     if (expCls.isArray () && argCls.isArray ()
-             && isCallableFrom (expCls.getComponentType (),
-                                argCls.getComponentType ()))
+        && isCallableFrom (expCls.getComponentType (),
+                           argCls.getComponentType ()))
       {
         return true;
       }
-    
+
     return expCls.equals (Object.class) && argCls.isPrimitive ();
-
   }
 
-
   private static boolean isNumberClass (Class cls)
   {
-    // FIXME: seems as if Byte is missing. 
+    // FIXME: seems as if Byte is missing.
     return cls.equals (Short.TYPE  ) || cls.equals (Short.class  )
       ||   cls.equals (Integer.TYPE) || cls.equals (Integer.class)
       ||   cls.equals (Long.TYPE   ) || cls.equals (Long.class   )
@@ -852,34 +829,17 @@
       ||   cls.equals (Double.TYPE ) || cls.equals (Double.class );
   }
 
-
   private static boolean isBooleanClass (Class cls)
   {
     return cls.equals (Boolean.class) || cls.equals (Boolean.TYPE);
   }
 
-
   private static boolean isCharClass (Class cls)
   {
     return cls.equals (Character.class) || cls.equals (Character.TYPE);
   }
 
-
-  //   //  * Check whether the supplied class is a String class.
-  //  *
-  //  * Added for more strict char/string matching of method signatures
-  //  * Date: 28-08-2010
-  //  * Author: Martin Hepperle
-  //  * @param cls Class - the class to check
-  //  * @return boolean - true if clas is of class java.lang.String
-  //   // private static boolean isStringClass (Class cls)
-  // {
-  //   return cls.equals (String.class);
-  // }
-
-
-  private static Object[] castArguments (Object[] args, 
-                                         Class[] argTypes,
+  private static Object[] castArguments (Object[] args, Class[] argTypes,
                                          Class[] expTypes)
   {
     for (int i = 0; i < args.length; i++)
@@ -889,8 +849,8 @@
     return args;
   }
 
-  // FIXME: simply null if no success. 
-  // To be analyzed: isn't type just obj.getClass()? 
+  // FIXME: simply null if no success.
+  // To be analyzed: isn't type just obj.getClass()?
   private static Object castArgument (Object obj, Class type, Class expType)
   {
     if (type == null || expType.isAssignableFrom (type))
@@ -900,8 +860,8 @@
     if (isNumberClass (expType))
       {
         Number num = (Number)obj;
-        // FIXME: what if obj is null? 
-        // FIXME: seems as if Byte is missing as in isNumberClass 
+        // FIXME: what if obj is null?
+        // FIXME: seems as if Byte is missing as in isNumberClass
         if (expType.equals (Short.TYPE) || expType.equals (Short.class))
           {
             return Short  .valueOf(num. shortValue());
@@ -923,17 +883,17 @@
             return Double .valueOf(num.doubleValue());
           }
         throw new IllegalStateException
-          ("Missing branch for byte? found "+expType);
+          ("Missing branch for byte? found " + expType);
       }
     if (isBooleanClass (expType))
       {
-        // FIXME: what if obj is null? 
-        // FIXME: why is obj a Number here?? 
+        // FIXME: what if obj is null?
+        // FIXME: why is obj a Number here??
         return Boolean.valueOf(((Number) obj).intValue () != 0);
       }
     if (isCharClass (expType))
       {
-        // FIXME: what if obj is null? 
+        // FIXME: what if obj is null?
         String s = obj.toString ();
         if (s.length () != 1)
           {
@@ -944,7 +904,7 @@
     if (expType.isArray () && type.isArray ())
       {
         // ensure that cast allows obj==null
-        return castArray (obj, 
+        return castArray (obj,
                           type   .getComponentType (),
                           expType.getComponentType ());
       }
@@ -967,8 +927,7 @@
   //!    the target class to cast the entries of @c obj.
   //! @throws IllegalArgumentException
   //!    if obj is no array instance.
-  private static Object castArray (Object obj, 
-                                   Class elemType,
+  private static Object castArray (Object obj, Class elemType,
                                    Class elemExpType)
   {
     // throws IllegalArgumentException if obj is not an array instance
@@ -982,54 +941,31 @@
     return result;
   }
 
-
-  //! Return the mathematical dimension of @c cls. 
-  //! This is 0 if @c cls no array type or if @c null. 
+  //! Return the mathematical dimension of @c cls.
+  //! This is 0 if @c cls no array type or if @c null.
   private static int getArrayClassNDims (Class cls)
   {
     int res = 0;
-    while (cls != null && cls.isArray ()) 
+    while (cls != null && cls.isArray ())
       {
         res++;
         cls = cls.getComponentType ();
       }
     return res;
-
-    // if (cls != null && cls.isArray ())
-    //   {
-    //     return (1 + getArrayClassNDims (cls.getComponentType ()));
-    //   }
-    // else
-    //   {
-    //     return 0;
-    //   }
   }
 
-  //! Return the innermost component type of @c cls. 
+  //! Return the innermost component type of @c cls.
   private static Class getArrayElemClass (Class cls)
   {
 
-    while (cls.isArray ()) 
+    while (cls.isArray ())
       {
         cls = cls.getComponentType ();
       }
     return cls;
-
-
-    // if (cls.isArray ())
-    //   {
-    //     return getArrayElemClass (cls.getComponentType ());
-    //   }
-    // else
-    //   {
-    //     return cls;
-    //   }
   }
 
-
-  private static Object getArrayElements (Object array, 
-                                          int[][] idx,
-                                          int offset,
+  private static Object getArrayElements (Object array, int[][] idx, int offset,
                                           int ndims, Class elemType)
   {
     if (offset >= ndims)
@@ -1052,14 +988,14 @@
         Array.set (retval, i, elem);
       }
     return retval;
-
   }
 
-  // Used by 
-  // #get_array_elements(JNIEnv*, jobject, octave_value_list&) 
-  // in @file ov-java.cc only and is recursive. 
-  //PMD: has an NPath complexity of 582
-  public static Object arraySubsref (Object obj, int[][] idx) // NOPMD
+  // Used by
+  // #get_array_elements(JNIEnv*, jobject, octave_value_list&)
+  // in @file ov-java.cc only and is recursive.
+  // PMD detects: has an NPath complexity of 582
+  public static Object arraySubsref (Object obj, 
+                                     int[][] idx) // NOPMD: rulecheck suspended
   {
     if (!obj.getClass ().isArray ())
       {
@@ -1085,7 +1021,6 @@
           }
       }
 
-
     int[] dims = new int[idx.length];
     for (int i = 0; i < idx.length; i++)
       {
@@ -1140,15 +1075,10 @@
       }
 
     return retval;
-
   }
 
-
-  private static Object setArrayElements (Object array,
-                                          int[][] idx,
-                                          int offset, 
-                                          int ndims, 
-                                          Object rhs)
+  private static Object setArrayElements (Object array, int[][] idx,
+                                          int offset, int ndims, Object rhs)
   {
     if (offset >= ndims)
       {
@@ -1179,12 +1109,11 @@
     return array;
   }
 
-  // PMD: has an NPath complexity of 294
+  // PMD detects: has an NPath complexity of 294
   // return value seems superfluous. 
   // Used by @file ov-java.cc only and is recursive. 
-  public static Object arraySubsasgn (Object obj, // NOPMD
-                                      int[][] idx, 
-                                      Object rhs) 
+  public static Object arraySubsasgn (Object obj, int[][] idx, 
+                                      Object rhs)// NOPMD: rulecheck suspended
   {
     if (!obj.getClass ().isArray ())
       {
@@ -1195,21 +1124,20 @@
       {
         if (idx[0].length == 1)
           {
-            // throws IllegalArgumentException if obj is not an array 
+            // throws IllegalArgumentException if obj is not an array
             Array.set (obj, idx[0][0], rhs);
           }
         else
           {
             for (int i = 0; i < idx[0].length; i++)
               {
-                // throws IllegalArgumentException if obj is not an array 
+                // throws IllegalArgumentException if obj is not an array
                 Array.set (obj, idx[0][i], Array.get (rhs, i));
               }
           }
         return obj;
       }
 
-
     int[] dims = new int[idx.length];
     for (int i = 0; i < idx.length; i++)
       {
@@ -1257,7 +1185,16 @@
   //! with dimensions given by @c dims.
   //! The class may be given directly as a @ref Class object
   //! or as a string via its name.
-  //! Used by @c javaArray only.
+  //! Used by @file javaArray.m defining @c javaArray only.
+  //!
+  //! Note that if you invoke <code>javaArray('java.lang.Object', 1)</code>,
+  //! this is translated into invocation of
+  //! <code>ClassHelper.createArray("java.lang.Object", 1)</code>,
+  //! invoking ::createArray(Object, int),
+  //! whereas <code>javaArray('java.lang.Object', 1, 1)</code>
+  //! this is translated into invocation of
+  //! <code>ClassHelper.createArray("java.lang.Object", 1, 1)</code>,
+  //! invoking ::createArray(Object, int[]).
   //!
   //! @param cls
   //!    the atomic component class given as a class object or as a string.
@@ -1265,25 +1202,26 @@
   //! @param dims
   //!    the dimensions which shall be non-negative but less than 256.
   //! @return
-  //!    an array with the given component type.
+  //!    an array with the given component type and dimensions.
   //!    If @c cls is a string, the class is loaded by #loader.
   //! @throws ClassNotFoundException
   //!    if @c cls is a string representing a class name
   //!    and if #loader could not find the according class.
-  // based on loader but only partially. 
+  //! @see ::createArray(Object, int)
+  // based on loader but only partially.
   // used by javaArray.m
   public static Object createArray (Object cls, int[] dims)
     throws ClassNotFoundException
   {
-    // FIXME: seems as if used in javaArray.m only.  
-    // Then more appropriate seems split into two methods: 
-    // one with cls is a Class other one with cls is a String 
-    // FIXME: if a class is given directly, 
-    // it is not guaranteed, that this is loaded via #loader 
-    // So this shall be fixed. 
-    // Typically, different usages are treated in m file invoking error 
-    // in the last else branch. 
-    // This would be appropriate here also. 
+    // FIXME: seems as if used in javaArray.m only.
+    // Then more appropriate seems split into two methods:
+    // one with cls is a Class other one with cls is a String
+    // FIXME: if a class is given directly,
+    // it is not guaranteed, that this is loaded via #loader
+    // So this shall be fixed.
+    // Typically, different usages are treated in m file invoking error
+    // in the last else branch.
+    // This would be appropriate here also.
     Class theClass;
     if (cls instanceof Class)
       {
@@ -1296,17 +1234,39 @@
       }
     else
       {
-        throw new IllegalArgumentException ("invalid class specification " +
-                                            cls);
+        throw new IllegalArgumentException ("invalid class specification "
+                                            + cls);
       }
 
     return Array.newInstance (theClass, dims);
   }
 
-
-  // public static Object createArray (Object cls, int length)
-  //   throws ClassNotFoundException
-  // {
-  //   return createArray (cls, new int[] {length});
-  // }
+  //! Return a one-dimensional array with entry type given by @c cls
+  //! with length by @c length.
+  //! The class may be given directly as a @ref Class object
+  //! or as a string via its name.
+  //! Used by @file javaArray.m defining @c javaArray only.
+  //!
+  //! @param cls
+  //!    the atomic component class given as a class object or as a string.
+  //!    If given as a string, the class is loaded via #loader.
+  //! @param length
+  //!    the length of the array to be created.
+  //! @return
+  //!    an array with the given component type and length.
+  //!    If @c cls is a string, the class is loaded by #loader.
+  //! @throws ClassNotFoundException
+  //!    if @c cls is a string representing a class name
+  //!    and if #loader could not find the according class.
+  //! @see ::createArray(Object, int)
+  // based on loader but only partially.
+  // used by javaArray.m
+  // would be superfluous with varargs introduced in java 1.5:
+  // the createArray (Object cls, int[] length)
+  // could be written createArray (Object cls, int... length)
+  public static Object createArray (Object cls, int length)
+    throws ClassNotFoundException
+  {
+    return createArray (cls, new int[] {length});
+  }
 }
