[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Documentation for Manual for Dynamically Linked Functions
From: |
David Bateman |
Subject: |
Re: Documentation for Manual for Dynamically Linked Functions |
Date: |
Wed, 25 Apr 2007 23:54:36 +0200 |
User-agent: |
Thunderbird 1.5.0.7 (X11/20060921) |
David Bateman wrote:
> John W. Eaton wrote:
>> I also added a copyright stament to the top of dynamic.txi. If some
>> of the text is based on other sources, please add the names of the
>> other authors here.
>
> Ok, I have a largish patch to dynamic.txi to send and will include it in
> that..
Ok, here is my latest bit of documentation for dynamic.txi, It
* Add copyrights for Paul Thomas and Christophe Spiel to credit the Coda
and Dal Segno source material.
* It adds a section on oct-file input parameter checking
* It adds a section of documentation and test/assert in oct-files
* It expands the basic section on mex-files and adds some other sections
(empty or only with the relevant source for the examples directory).
* Writes a section on calling other functions from mex-files
* A few formatting issues in a couple of example files
* Adds example files paramdemo.cc and myfunc.c
A ChangeLog entry is also attached. The section on dynamically linked
functions is still not complete, but its getting to be relatively
substantial.
Regards
David
*** ./doc/interpreter/dynamic.txi.orig14 2007-04-25 18:04:59.000000000
+0200
--- ./doc/interpreter/dynamic.txi 2007-04-25 20:58:28.096374073 +0200
***************
*** 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,980 ****
@node Input Parameter Checking in Oct-Files
@subsection Input Parameter Checking in Oct-Files
! WRITE ME
@node Exception and Error Handling in Oct-Files
@subsection Exception and Error Handling in Oct-Files
--- 975,1013 ----
@node Input Parameter Checking in Oct-Files
@subsection Input Parameter Checking in Oct-Files
! 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,1056 ****
@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.
@node Application Programming Interface for Oct-Files
@subsection Application Programming Interface for Oct-Files
--- 1083,1143 ----
@node Documentation and Test of Oct-Files
@subsection Documentation and Test of Oct-Files
! 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 address@hidden @address@hidden do_what_i_say
(@@address@hidden@})\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,1084 ****
@menu
* Getting Started with Mex-Files::
* Structures with Mex-Files::
* Sparse Matrices with Mex-Files::
! * Calling External Functions in Mex-Files::
@end menu
@node Getting Started with Mex-Files
--- 1163,1175 ----
@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 Other Functions in Mex-Files::
! * Application Programming Interface for Mex-Files::
@end menu
@node Getting Started with Mex-Files
***************
*** 1103,1127 ****
@examplefile{firstmexdemo.c}
! This simple example demonstrates the basics of writing a mex-file.
WRITE ME
@node Structures with Mex-Files
@subsection Structures with Mex-Files
WRITE ME
@node Sparse Matrices with Mex-Files
@subsection Sparse Matrices with Mex-Files
! WRITE ME
! @node Calling External Functions in Mex-Files
! @subsection Calling External Functions in Mex-Files
WRITE ME
@node Standalone Programs
@section Standalone Programs
--- 1194,1340 ----
@examplefile{firstmexdemo.c}
! 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 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
+
+ @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,1159 ****
--- 1367,1373 ----
@end group
@end example
+ @noindent
mkoctfile can then be used to build a standalone application with a
command like
*** ./examples/myfunc.c.orig14 2007-04-25 14:20:46.227535609 +0200
--- ./examples/myfunc.c 2007-04-25 13:46:20.062621169 +0200
***************
*** 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;
+ }
*** ./examples/mystruct.c.orig14 2007-04-25 14:21:11.812297992 +0200
--- ./examples/mystruct.c 2007-04-25 20:56:31.095418845 +0200
***************
*** 13,21 ****
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");
}
v = mxCreateStructMatrix (2, 2, 2, keys);
--- 13,22 ----
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");
}
v = mxCreateStructMatrix (2, 2, 2, keys);
*** ./examples/mysparse.c.orig14 2007-04-25 14:22:50.826487478 +0200
--- ./examples/mysparse.c 2007-04-25 20:57:09.901413960 +0200
***************
*** 20,27 ****
if (mxIsComplex (prhs[0]))
{
! mexPrintf ("Matrix is %d-by-%d complex sparse matrix with %d
elements\n",
! m, n, nz);
pr = mxGetPr (prhs[0]);
pi = mxGetPi (prhs[0]);
--- 20,27 ----
if (mxIsComplex (prhs[0]))
{
! 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,37 ****
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]);
v = mxCreateSparse (m, n, nz, mxCOMPLEX);
pr2 = mxGetPr (v);
--- 30,37 ----
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]);
v = mxCreateSparse (m, n, nz, mxCOMPLEX);
pr2 = mxGetPr (v);
***************
*** 40,61 ****
jc2 = mxGetJc (v);
for (i = 0; i < nz; 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];
if (nlhs > 0)
! 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);
pbr = mxGetLogicals (prhs[0]);
ir = mxGetIr (prhs[0]);
--- 40,61 ----
jc2 = mxGetJc (v);
for (i = 0; i < nz; 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];
if (nlhs > 0)
! plhs[0] = v;
}
else if (mxIsLogical (prhs[0]))
{
bool *pbr, *pbr2;
! 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,70 ****
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]);
v = mxCreateSparseLogicalMatrix (m, n, nz);
pbr2 = mxGetLogicals (v);
--- 64,70 ----
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]);
v = mxCreateSparseLogicalMatrix (m, n, nz);
pbr2 = mxGetLogicals (v);
***************
*** 72,92 ****
jc2 = mxGetJc (v);
for (i = 0; i < nz; i++)
! {
! pbr2[i] = pbr[i];
! ir2[i] = ir[i];
! }
for (i = 0; i < n + 1; i++)
! jc2[i] = jc[i];
if (nlhs > 0)
! plhs[0] = v;
}
else
{
!
! mexPrintf ("Matrix is %d-by-%d real sparse matrix with %d elements\n",
! m, n, nz);
pr = mxGetPr (prhs[0]);
ir = mxGetIr (prhs[0]);
--- 72,91 ----
jc2 = mxGetJc (v);
for (i = 0; i < nz; i++)
! {
! pbr2[i] = pbr[i];
! ir2[i] = ir[i];
! }
for (i = 0; i < n + 1; i++)
! jc2[i] = jc[i];
if (nlhs > 0)
! plhs[0] = v;
}
else
{
! 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,101 ****
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]);
v = mxCreateSparse (m, n, nz, mxREAL);
pr2 = mxGetPr (v);
--- 94,100 ----
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]);
v = mxCreateSparse (m, n, nz, mxREAL);
pr2 = mxGetPr (v);
***************
*** 103,116 ****
jc2 = mxGetJc (v);
for (i = 0; i < nz; i++)
! {
! pr2[i] = 2 * pr[i];
! ir2[i] = ir[i];
! }
for (i = 0; i < n + 1; i++)
! jc2[i] = jc[i];
if (nlhs > 0)
! plhs[0] = v;
}
}
--- 102,115 ----
jc2 = mxGetJc (v);
for (i = 0; i < nz; i++)
! {
! pr2[i] = 2 * pr[i];
! ir2[i] = ir[i];
! }
for (i = 0; i < n + 1; i++)
! jc2[i] = jc[i];
if (nlhs > 0)
! plhs[0] = v;
}
}
*** ./examples/fortdemo.cc.orig14 2007-04-25 14:27:53.050625020 +0200
--- ./examples/fortdemo.cc 2007-04-25 20:51:19.895496768 +0200
***************
*** 24,30 ****
octave_idx_type na = a.nelem ();
OCTAVE_LOCAL_BUFFER (char, ctmp, 128);
! F77_XFCN (fortsub, FORTSUB, (na, av, ctmp F77_CHAR_ARG_LEN (128)));
if (f77_exception_encountered)
error ("fortdemo: error in fortran");
--- 24,31 ----
octave_idx_type na = a.nelem ();
OCTAVE_LOCAL_BUFFER (char, ctmp, 128);
! F77_XFCN (fortsub, FORTSUB, (na, av, ctmp
! F77_CHAR_ARG_LEN (128)));
if (f77_exception_encountered)
error ("fortdemo: error in fortran");
*** ./examples/paramdemo.cc.orig14 2007-04-25 16:57:17.787027733 +0200
--- ./examples/paramdemo.cc 2007-04-25 20:51:02.777381163 +0200
***************
*** 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;
+ }
2007-04-25 David Bateman <address@hidden>
* 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 David Bateman <address@hidden>
* 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.
- Documentation for Manual for Dynamically Linked Functions, David Bateman, 2007/04/24
- Documentation for Manual for Dynamically Linked Functions, John W. Eaton, 2007/04/24
- Documentation for Manual for Dynamically Linked Functions, John W. Eaton, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, David Bateman, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, John W. Eaton, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, David Bateman, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, John W. Eaton, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, David Bateman, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, John W. Eaton, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions,
David Bateman <=
- Re: Documentation for Manual for Dynamically Linked Functions, John W. Eaton, 2007/04/25
- Re: Documentation for Manual for Dynamically Linked Functions, David Bateman, 2007/04/25
Re: Documentation for Manual for Dynamically Linked Functions, Søren Hauberg, 2007/04/25