Mercurial > hg > octave-avbm
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 +++ b/ChangeLog @@ -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 +++ b/doc/ChangeLog @@ -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 +++ b/doc/interpreter/dynamic.txi @@ -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 +++ b/examples/fortdemo.cc @@ -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");
new file mode 100644 --- /dev/null +++ b/examples/myfunc.c @@ -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 +++ b/examples/mysparse.c @@ -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 +++ b/examples/mystruct.c @@ -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);
new file mode 100644 --- /dev/null +++ b/examples/paramdemo.cc @@ -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; +}