changeset 6580:d2bb3b8a8d20

[project @ 2007-04-25 22:19:03 by dbateman]
author dbateman
date Wed, 25 Apr 2007 22:20:28 +0000
parents f569cc721d3b
children 1a414f670635
files ChangeLog doc/ChangeLog doc/interpreter/dynamic.txi examples/fortdemo.cc examples/myfunc.c examples/mysparse.c examples/mystruct.c examples/paramdemo.cc
diffstat 8 files changed, 312 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Apr 25 17:26:49 2007 +0000
+++ b/ChangeLog	Wed Apr 25 22:20:28 2007 +0000
@@ -1,3 +1,9 @@
+2007-04-25  David Bateman  <dbateman@free.fr>
+
+	* examples/myfunc.c, exampples/paramdemo.cc: New files
+	* examples/mystruct.c, examples/mysparse.c, fortdemo.cc: Fix a few
+	formatting issues when included in texinfo files.
+
 2007-04-25  John W. Eaton  <jwe@octave.org>
 
 	* Makeconf.in (do-subst-texinfo-vals): Also substitute top_srcdir.
--- a/doc/ChangeLog	Wed Apr 25 17:26:49 2007 +0000
+++ b/doc/ChangeLog	Wed Apr 25 22:20:28 2007 +0000
@@ -1,3 +1,11 @@
+2007-04-25  David Bateman  <dbateman@free.fr>
+
+	* interpreter/dynamic.txi: Add additional copyrights. Add sections
+	of input parameter checking, documentation and testing of
+	oct-files. Adds a section on calling other functions from
+	mex-files, expands the basic information on mex-files, and add a
+	few new sections (to be completed) to the section about mex-files
+
 2007-04-25  John W. Eaton  <jwe@octave.org>
 
 	* interpreter/dynamic.txi: Use @verbatiminclude for example code.
--- a/doc/interpreter/dynamic.txi	Wed Apr 25 17:26:49 2007 +0000
+++ b/doc/interpreter/dynamic.txi	Wed Apr 25 22:20:28 2007 +0000
@@ -1,4 +1,5 @@
 @c Copyright (C) 2007 John W. Eaton, David Bateman
+@c Copyright (C) 2007 Paul Thomas, Christoph Spiel
 @c This is part of the Octave manual.
 @c For copying conditions, see the file gpl.texi.
 
@@ -974,7 +975,39 @@
 @node Input Parameter Checking in Oct-Files
 @subsection Input Parameter Checking in Oct-Files
 
-WRITE ME
+As oct-files are compiled functions they have the possibility of causing
+Octave to abort abnormally.  It is therefore inportant that the input
+parameters to each and every function has the minimum of parameter
+checking needed to ensure that Octave behaves well.
+
+The minimum requirement, as previously discussed, is to check the number
+of input arguments before using them to avoid referencing a non existent
+argument.  However, it some case this might not be sufficient as the
+underlying code imposes further constraints. For example an external
+function call might be undefined if the input arguments are not
+integers, or if one of the arguments is zero. Therefore, oct-files often
+need additional input parameter checking.
+
+There are several functions within Octave that might be useful for the
+purposes of parameter checking. These include the methods of the
+octave_value class like @code{is_real_matrix}, etc, but equally include
+more specialized functions. Some of the more common ones are
+demonstrated in the following example
+
+@examplefile{paramdemo.cc}
+
+@noindent
+and an example of its use is
+
+@example
+@group
+paramdemo ([1, 2, NaN, Inf])
+@result{} Properties of input array:
+      includes Inf or NaN values
+      includes other values than 1 and 0
+      includes only int, Inf or NaN values
+@end group
+@end example
 
 @node Exception and Error Handling in Oct-Files
 @subsection Exception and Error Handling in Oct-Files
@@ -1050,7 +1083,61 @@
 @node Documentation and Test of Oct-Files
 @subsection Documentation and Test of Oct-Files
 
-WRITE ME, reference how to use Texinfo in oct-file and embed test code.
+The documentation of an oct-file is the fourth string parameter of the
+@code{DEFUN_DLD} macro.  This string can be formatted in the same manner
+as the help strings for user functions (@ref{Documentation Tips}),
+however there are some issue that are particular to the formatting of
+help strings within oct-files.
+
+The major issue is that the help string will typically be longer than a
+single line of text, and so the formatting of long help strings need to
+be taken into account. There are several manner in which to happen this
+issue, but the most common is illustrated in the following example
+
+@example
+@group
+DEFUN_DLD (do_what_i_want, args, nargout, 
+  "-*- texinfo -*-\n\
+@@deftypefn @{Function File@} @{@} do_what_i_say (@@var@{n@})\n\
+A function that does what the user actually wants rather than what\n\
+they requested.\n\
+@@end deftypefn")
+@{
+@dots{}
+@}
+@end group
+@end example
+
+@noindent
+where, as can be seen, end line of text within the help string is
+terminated by @code{\n\} which is an an embedded new-line in the string
+together with a C++ string continuation character.  Note that the final
+@code{\} must be the last character on the line.
+
+Octave also includes the ability to embed the test and demonstration
+code for a function within the code itself (@ref{Test and Demo Functions}).
+This can be used from within oct-files (or in fact any file) with
+certain provisos.  Firstly, the test and demo functions of Octave look
+for a @code{%!} as the first characters on a new-line to identify test
+and demonstration code.  This is equally a requirement for
+oct-files.  Furthermore the test and demonstration code must be included
+in a comment block of the compiled code to avoid it being interpreted by
+the compiler.  Finally, he Octave test and demonstration code must have
+access to the source code of the oct-file and not just the compiled code
+as th<e tests are stripped from the compiled code. An example in an
+oct-file might be
+
+@example
+@group
+/*
+
+%!error (sin())
+%!error (sin(1,1))
+%!assert (sin([1,2]),[sin(1),sin(2)])
+
+*/
+@end group
+@end example
 
 @node Application Programming Interface for Oct-Files
 @subsection Application Programming Interface for Oct-Files
@@ -1076,9 +1163,13 @@
 
 @menu
 * Getting Started with Mex-Files::  
+* Working with Matrices and Arrays in Mex-Files::  
+* Character Strings in Mex-Files::  
+* Cell Arrays with Mex-Files::  
 * Structures with Mex-Files::  
 * Sparse Matrices with Mex-Files::  
-* Calling External Functions in Mex-Files::  
+* Calling Other Functions in Mex-Files::  
+* Application Programming Interface for Mex-Files::  
 @end menu
 
 @node Getting Started with Mex-Files
@@ -1103,24 +1194,146 @@
 
 @examplefile{firstmexdemo.c}
 
-This simple example demonstrates the basics of writing a mex-file.
+This simple example demonstrates the basics of writing a mex-file. The
+entry point into the mex-file is defined by @code{mexFunction}. Note
+that the function name is not explicitly included in the
+@code{mexFunction} and so there can only be a single @code{mexFunction}
+entry point per-file.  Also the name of the function is determined by the
+name of the mex-file itself.  Therefore if the above function is in the
+file @file{firstmexdemo.c}, it can be compiled with
+
+@example
+mkoctfile --mex firstmexdemo.c
+@end example
+
+@noindent
+which creates a file @file{firstmexdemo.mex}.  The function can then be run
+from Octave as
+
+@example
+@group
+firstmexdemo()
+@result{} 1.2346
+@end group
+@end example
+
+It should be noted that the mex-file contains no help string for the
+functions it contains. To document mex-files, there should exist an
+m-file in the same directory as the mex-file itself. Taking the above as
+an example, we would therefore have a file @file{firstmexdemo.m} that might
+contain the text
+
+@example
+%FIRSTMEXDEMO Simple test of the functionality of a mex-file.
+@end example
+
+In this case, the function that will be executed within Octave will be
+given by the mex-file, while the help string will come from the
+m-file. This can also be useful to allow a sample implementation of the
+mex-file within the Octave language itself for testing purposes.
+
+Although we can not have multiple entry points into a single mex-file,
+we can use the @code{mexFunctionName} function to determine what name
+the mex-file was called with. This can be used to alter the behavior of
+the mex-file based on the function name. For example if
+
+@examplefile{myfunc.c}
+
+@noindent
+is in file @file{myfunc.c}, and it is compiled with
+
+@example
+@group
+mkoctfile --mex myfunc.c
+ln -s myfunc.mex myfunc2.mex
+@end group
+@end example
+
+Then as can be seen by
+
+@example
+@group
+myfunc()
+@result{} You called function: myfunc
+    This is the principal function
+myfunc2()
+@result{} You called function: myfunc2
+@end group
+@end example
+
+@noindent
+the behavior of the mex-file can be altered depending on the functions
+name.
+
+@node Working with Matrices and Arrays in Mex-Files
+@subsection Working with Matrices and Arrays in Mex-Files
+
+The basic mex type of all variables is @code{mxArray}. All variables,
+such as Matrices, cell arrays or structures are all stored in this basic
+type, and this type serves basically the same purpose as the
+octave_value class in oct-files. That is it acts as a container for the
+more specialized types.
+
+WRITE ME
+
+@node Character Strings in Mex-Files
+@subsection Character Strings in Mex-Files
+
+WRITE ME
+
+@node Cell Arrays with Mex-Files
+@subsection Cell Arrays with Mex-Files
 
 WRITE ME
 
 @node Structures with Mex-Files
 @subsection Structures with Mex-Files
 
+See the file @file{mystruct.c}
+
+@examplefile{mystruct.c}
+
 WRITE ME
 
 @node Sparse Matrices with Mex-Files
 @subsection Sparse Matrices with Mex-Files
 
+See the file @file{mysparse.c}
+
+@examplefile{mysparse.c}
+
 WRITE ME
 
-@node Calling External Functions in Mex-Files
-@subsection Calling External Functions in Mex-Files
+@node Calling Other Functions in Mex-Files
+@subsection Calling Other Functions in Mex-Files
+
+It is also possible call other Octave functions from within a mex-file
+using @code{mexCallMATLAB}. An example of the use of
+@code{mexCallMATLAB} can be see in the example below
+
+@examplefile{myfeval.c}
+
+If this code is in the file @file{myfeval.c}, and is compiled to
+@file{myfeval.mex}, then an example of its use is
 
-WRITE ME
+@example
+@group
+myfeval("sin", 1)
+a = myfeval("sin", 1)
+@result{} Hello, World!
+    I have 2 inputs and 1 outputs
+    I'm going to call the interpreter function sin
+    a =  0.84147
+@end group
+@end example
+
+Note that it is not possible to use function handles or inline functions
+within a mex-file.
+
+@node Application Programming Interface for Mex-Files
+@subsection Application Programming Interface for Mex-Files
+
+WRITE ME, refer to mex.h and mexproto.h
 
 @node Standalone Programs
 @section Standalone Programs
@@ -1154,6 +1367,7 @@
 @end group
 @end example
 
+@noindent
 mkoctfile can then be used to build a standalone application with a
 command like
 
--- a/examples/fortdemo.cc	Wed Apr 25 17:26:49 2007 +0000
+++ b/examples/fortdemo.cc	Wed Apr 25 22:20:28 2007 +0000
@@ -24,7 +24,8 @@
           octave_idx_type na = a.nelem ();
           OCTAVE_LOCAL_BUFFER (char, ctmp, 128);
 
-          F77_XFCN (fortsub, FORTSUB, (na, av, ctmp F77_CHAR_ARG_LEN (128)));
+          F77_XFCN (fortsub, FORTSUB, (na, av, ctmp 
+                                       F77_CHAR_ARG_LEN (128)));
 
           if (f77_exception_encountered)
             error ("fortdemo: error in fortran");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/myfunc.c	Wed Apr 25 22:20:28 2007 +0000
@@ -0,0 +1,12 @@
+#include "mex.h"
+
+void
+mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  const char *nm;
+  nm = mexFunctionName ();
+  mexPrintf("You called function: %s\n", nm);
+  if (strcmp (nm, "myfunc") == 0)
+    mexPrintf("This is the principal function\n", nm);
+  return; 
+}
--- a/examples/mysparse.c	Wed Apr 25 17:26:49 2007 +0000
+++ b/examples/mysparse.c	Wed Apr 25 22:20:28 2007 +0000
@@ -20,8 +20,8 @@
   
   if (mxIsComplex (prhs[0]))
     {
-      mexPrintf ("Matrix is %d-by-%d complex sparse matrix with %d elements\n",
-		m, n, nz);
+      mexPrintf ("Matrix is %d-by-%d complex sparse matrix", m, n);
+      mexPrintf (" with %d elements\n", nz);
 
       pr = mxGetPr (prhs[0]);
       pi = mxGetPi (prhs[0]);
@@ -30,8 +30,8 @@
 
       i = n;
       while (jc[i] == jc[i-1] && i != 0) i--;
-      mexPrintf ("last non-zero element (%d, %d) = (%g, %g)\n", ir[nz-1]+ 1, 
-		i, pr[nz-1], pi[nz-1]);
+      mexPrintf ("last non-zero element (%d, %d) = (%g, %g)\n", 
+                ir[nz-1]+ 1, i, pr[nz-1], pi[nz-1]);
 
       v = mxCreateSparse (m, n, nz, mxCOMPLEX);
       pr2 = mxGetPr (v);
@@ -40,22 +40,22 @@
       jc2 = mxGetJc (v);
       
       for (i = 0; i < nz; i++)
-	{
-	  pr2[i] = 2 * pr[i];
-	  pi2[i] = 2 * pi[i];
-	  ir2[i] = ir[i];
-	}
+        {
+          pr2[i] = 2 * pr[i];
+          pi2[i] = 2 * pi[i];
+          ir2[i] = ir[i];
+        }
       for (i = 0; i < n + 1; i++)
-	jc2[i] = jc[i];
+        jc2[i] = jc[i];
 
       if (nlhs > 0)
-	plhs[0] = v;
+        plhs[0] = v;
     }
   else if (mxIsLogical (prhs[0]))
     {
       bool *pbr, *pbr2;
-      mexPrintf ("Matrix is %d-by-%d logical sparse matrix with %d elements\n",
-		m, n, nz);
+      mexPrintf ("Matrix is %d-by-%d logical sparse matrix", m, n);
+      mexPrintf (" with %d elements\n", nz);
 
       pbr = mxGetLogicals (prhs[0]);
       ir = mxGetIr (prhs[0]);
@@ -64,7 +64,7 @@
       i = n;
       while (jc[i] == jc[i-1] && i != 0) i--;
       mexPrintf ("last non-zero element (%d, %d) = %d\n", ir[nz-1]+ 1, 
-		i, pbr[nz-1]);
+                i, pbr[nz-1]);
 
       v = mxCreateSparseLogicalMatrix (m, n, nz);
       pbr2 = mxGetLogicals (v);
@@ -72,21 +72,20 @@
       jc2 = mxGetJc (v);
       
       for (i = 0; i < nz; i++)
-	{
-	  pbr2[i] = pbr[i];
-	  ir2[i] = ir[i];
-	}
+        {
+          pbr2[i] = pbr[i];
+          ir2[i] = ir[i];
+        }
       for (i = 0; i < n + 1; i++)
-	jc2[i] = jc[i];
+        jc2[i] = jc[i];
 
       if (nlhs > 0)
-	plhs[0] = v;
+        plhs[0] = v;
     }
   else
     {
-      
-      mexPrintf ("Matrix is %d-by-%d real sparse matrix with %d elements\n",
-		m, n, nz);
+      mexPrintf ("Matrix is %d-by-%d real sparse matrix", m, n);
+      mexPrintf (" with %d elements\n", nz);
 
       pr = mxGetPr (prhs[0]);
       ir = mxGetIr (prhs[0]);
@@ -95,7 +94,7 @@
       i = n;
       while (jc[i] == jc[i-1] && i != 0) i--;
       mexPrintf ("last non-zero element (%d, %d) = %g\n", ir[nz-1]+ 1, 
-		i, pr[nz-1]);
+                i, pr[nz-1]);
 
       v = mxCreateSparse (m, n, nz, mxREAL);
       pr2 = mxGetPr (v);
@@ -103,14 +102,14 @@
       jc2 = mxGetJc (v);
       
       for (i = 0; i < nz; i++)
-	{
-	  pr2[i] = 2 * pr[i];
-	  ir2[i] = ir[i];
-	}
+        {
+          pr2[i] = 2 * pr[i];
+          ir2[i] = ir[i];
+        }
       for (i = 0; i < n + 1; i++)
-	jc2[i] = jc[i];
+        jc2[i] = jc[i];
 
       if (nlhs > 0)
-	plhs[0] = v;
+        plhs[0] = v;
     }
 }
--- a/examples/mystruct.c	Wed Apr 25 17:26:49 2007 +0000
+++ b/examples/mystruct.c	Wed Apr 25 22:20:28 2007 +0000
@@ -13,9 +13,10 @@
   for (i = 0; i < mxGetNumberOfFields (prhs[0]); i++)
     for (j=0; j < mxGetNumberOfElements(prhs[0]); j++)
       {
-	mexPrintf ("field %s(%d) = ", mxGetFieldNameByNumber (prhs[0], i), j);
-	v = mxGetFieldByNumber (prhs[0], j, i);
-	mexCallMATLAB(0, 0, 1, &v, "disp");
+        mexPrintf ("field %s(%d) = ", 
+                   mxGetFieldNameByNumber (prhs[0], i), j);
+        v = mxGetFieldByNumber (prhs[0], j, i);
+        mexCallMATLAB(0, 0, 1, &v, "disp");
       }
 
   v = mxCreateStructMatrix (2, 2, 2, keys);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/paramdemo.cc	Wed Apr 25 22:20:28 2007 +0000
@@ -0,0 +1,30 @@
+#include <octave/oct.h>
+
+DEFUN_DLD (paramdemo, args, nargout, "Parameter Check Demo.")
+{
+  int nargin = args.length ();
+  octave_value retval;
+
+  if (nargin != 1)
+    print_usage();
+  else if (nargout != 0)
+    error ("paramdemo: function has no output arguments");
+  else
+    {
+      NDArray m = args(0).array_value();
+      double min_val = -10.0;
+      double max_val = 10.0;
+      octave_stdout << "Properties of input array:\n";
+      if (m.any_element_is_negative ())
+        octave_stdout << "  includes negative values\n";
+      if (m.any_element_is_inf_or_nan())
+        octave_stdout << "  includes Inf or NaN values\n";
+      if (m.any_element_not_one_or_zero())
+        octave_stdout << "  includes other values than 1 and 0\n";
+      if (m.all_elements_are_int_or_inf_or_nan())
+        octave_stdout << "  includes only int, Inf or NaN values\n";
+      if (m.all_integers (min_val, max_val))
+        octave_stdout << "  includes only integers in [-10,10]\n";
+    }
+  return retval;
+}