octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Changeset]: Documentation for the OOP code of Octave


From: David Bateman
Subject: Re: [Changeset]: Documentation for the OOP code of Octave
Date: Wed, 15 Oct 2008 15:35:19 +0100
User-agent: Mozilla-Thunderbird 2.0.0.16 (X11/20080724)

John W. Eaton wrote:
On 15-Oct-2008, David Bateman wrote:

| In any case before committing this changeset, it would be good if I | could have some comments, or improvements.

The oop.txi file seems to be missing from the changeset.

jwe

Opps, new version of the changeset attached.

D.


--
David Bateman                                address@hidden
Motorola Labs - Paris +33 1 69 35 48 04 (Ph) Parc Les Algorithmes, Commune de St Aubin +33 6 72 01 06 33 (Mob) 91193 Gif-Sur-Yvette FRANCE +33 1 69 35 77 01 (Fax) The information contained in this communication has been classified as: [x] General Business Information [ ] Motorola Internal Use Only [ ] Motorola Confidential Proprietary

# HG changeset patch
# User David Bateman <address@hidden>
# Date 1224081264 -3600
# Node ID 288896543bb44557c47014c31f0f8a961d7e4521
# Parent  5bd29ca61596aec13b0019b2cc944c4d9c055302
Add some documentation for the OOP code of Octave

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2008-10-15  David Bateman  <address@hidden>
+
+       * examples/polynomial/display.m, examples/polynomial/double.m,
+       examples/polynomial/end.m, examples/polynomial/get.m,
+       examples/polynomial/mtimes.m, examples/polynomial/plot.m,
+       examples/polynomial/polynomial.m,
+       examples/polynomial/polynomial_superiorto.m,
+       examples/polynomial/polyval.m, examples/polynomial/set.m,
+       examples/polynomial/subsasgn.m, examples/polynomial/subsref.m:
+       New example files for a sample OOP class.
+       * examples/polynomial/Makefile.in: Add a makefile for this new
+       directory
+       * examples/Makefile.in: Reference the new subdirectory here.
+       * configure.in: Add the new makefile to AC_CONFIG_FILES.
+       
 2008-10-01  Jaroslav Hajek <address@hidden>
 
        * configure.in: Check for sizeof (long double) and randl.
diff --git a/configure.in b/configure.in
--- a/configure.in
+++ b/configure.in
@@ -1989,9 +1989,9 @@
 AC_CONFIG_FILES([Makefile octMakefile Makeconf test/Makefile
   doc/Makefile doc/faq/Makefile doc/interpreter/Makefile
   doc/liboctave/Makefile doc/refcard/Makefile emacs/Makefile
-  examples/Makefile liboctave/Makefile liboctave/oct-types.h
-  src/Makefile src/mxarray.h libcruft/Makefile libcruft/Makerules
-  libcruft/amos/Makefile libcruft/blas/Makefile
+  examples/Makefile examples/polynomial/Makefile liboctave/Makefile
+  liboctave/oct-types.h src/Makefile src/mxarray.h libcruft/Makefile
+  libcruft/Makerules libcruft/amos/Makefile libcruft/blas/Makefile
   libcruft/daspk/Makefile libcruft/dasrt/Makefile
   libcruft/dassl/Makefile libcruft/fftpack/Makefile
   libcruft/lapack/Makefile libcruft/minpack/Makefile
diff --git a/doc/ChangeLog b/doc/ChangeLog
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,4 +1,16 @@
+2008-10-15  David Bateman  <address@hidden>
+
+       * interpreter/oop.txi: New file.
+       * interpreter/Makefile.in (SUB_SOURCES): Add it here.
+       (POLYNOMIAL_FILES_NODIR): New varaible for polynomial example class
+       methods.
+       (EXAMPLE_FILES_NODIR): Add POLYNOMIAL_FILES_NODIR here.
+       * interpreter/octave.texi: Reference new OOP chapter here.
+       * interpreter/func.txi: Document private directories and function
+       precedence here.
+       
 2008-10-03  Thorsten Meyer  <address@hidden>
+
        * interpreter/contrib.txi: added example for mercurial queues
 
 08-10-03  Thorsten Meyer  <address@hidden>
diff --git a/doc/interpreter/Makefile.in b/doc/interpreter/Makefile.in
--- a/doc/interpreter/Makefile.in
+++ b/doc/interpreter/Makefile.in
@@ -33,6 +33,20 @@
 
 SCRIPT_SOURCES = sparseimages.m interpimages.m geometryimages.m plotimages.m
 
+POLYNOMIAL_FILES_NODIR = \
+  display.m \
+  double.m \
+  end.m \
+  get.m \
+  mtimes.m \
+  plot.m \
+  polynomial.m \
+  polynomial_superiorto.m \
+  polyval.m \
+  set.m \
+  subsasgn.m \
+  subsref.m
+
 EXAMPLE_FILES_NODIR = \
   addtwomatrices.cc \
   celldemo.cc \
@@ -52,7 +66,8 @@
   paramdemo.cc \
   stringdemo.cc \
   structdemo.cc \
-  unwinddemo.cc
+  unwinddemo.cc \
+  $(addprefix polynomial/, $(POLYNOMIAL_FILES_NODIR))
 
 EXAMPLE_FILES = $(addprefix $(top_srcdir)/examples/, $(EXAMPLE_FILES_NODIR))
 
@@ -99,7 +114,7 @@
        expr.txi fn-idx.txi func.txi geometry.txi gpl.txi \
        grammar.txi image.txi install.txi interp.txi \
        intro.txi io.txi linalg.txi matrix.txi nonlin.txi numbers.txi \
-       op-idx.txi optim.txi package.txi plot.txi poly.txi preface.txi \
+       oop.txi op-idx.txi optim.txi package.txi plot.txi poly.txi preface.txi \
        quad.txi set.txi signal.txi sparse.txi stats.txi \
        stmt.txi strings.txi system.txi testfun.txi tips.txi var.txi \
        vr-idx.txi
diff --git a/doc/interpreter/func.txi b/doc/interpreter/func.txi
--- a/doc/interpreter/func.txi
+++ b/doc/interpreter/func.txi
@@ -625,8 +625,10 @@
 @menu
 * Manipulating the load path::
 * Subfunctions::
+* Private Functions::
 * Overloading and Autoloading::
 * Function Locking::
+* Function Precedence::
 @end menu
 
 @node Manipulating the load path
@@ -699,6 +701,34 @@
 subfunctions @code{g} and @code{h} may only be called from the main
 function @code{f} or from the other subfunctions, but not from outside
 the file @file{f.m}.
+
address@hidden Private Functions
address@hidden Private Functions
+
+In many cases one function needs to access one or more helper
+functions.  If the helper function is limited to the scope of a single
+function, then subfunctions as discussed above might be used. However,
+if a single helper function is used by more than one function, then
+this is no longer possible.  In this case the helper functions might
+be placed in a subdirectory, called "private", of the directory in which
+the functions needing access to this helper function are found.
+
+As a simple example, consider a function @code{func1}, that calls a helper
+function @code{func2} to do much of the work. For example
+
address@hidden
address@hidden
+function y = func1 (x)
+  y = func2 (x);
+endfunction
address@hidden group
address@hidden example
+
address@hidden
+Then if the path to @code{func1} is @code{<directory>/func1.m}, and if
address@hidden is found in the directory @code{<directory>/private/func2.m}, 
+then @code{func2} is only available for use of the functions, like 
address@hidden, that are found in @code{<directory>}.
 
 @node Overloading and Autoloading
 @subsection Overloading and Autoloading
@@ -825,6 +855,49 @@
 @DOCSTRING(munlock)
 
 @DOCSTRING(mislocked)
+
address@hidden Function Precedence
address@hidden Function Precedence
+
+Given the numereous different ways that Octave can define a function, it
+is possible and even likely that multiple versions of a function, might be
+defined within a particular scope. The precedence of which function will be
+used within a particular scope is given by
+
address@hidden 1
address@hidden Subfunction
+A subfunction with the required function name in the given scope.
+
address@hidden Private function
+A function defined within a private directory of the directory 
+which contains the current function.
+
address@hidden Class constructor
+A function that constuctors a user class as defined in chapter 
address@hidden Oriented Programming}.
+
address@hidden Class method
+An overloaded function of a class as in chapter
address@hidden Oriented Programming}.
+
address@hidden Legacy Dispatch
+An overloaded function as defined by @xref{dispatch}.
+
address@hidden Command-line Function
+A function that has been defined on the command-line.
+
address@hidden Autoload function
+A function that is marked as autoloaded with @xref{autoload}.
+
address@hidden A Function on the Path
+A function that can be found on the users load-path. There can also be
+Oct-file, mex-file or m-file versions of this function and the precedence
+between these versions are in that order.
+
address@hidden Built-in function
+A function that is builtin to Octave itself such as @code{numel},
address@hidden, etc.
address@hidden enumerate
 
 @node Script Files
 @section Script Files
diff --git a/doc/interpreter/octave.texi b/doc/interpreter/octave.texi
--- a/doc/interpreter/octave.texi
+++ b/doc/interpreter/octave.texi
@@ -177,6 +177,7 @@
 * Signal Processing::           
 * Image Processing::            
 * Audio Processing::            
+* Object Oriented Programming::            
 * System Utilities::            
 * Packages:: 
 * Dynamically Linked Functions::
@@ -487,6 +488,13 @@
 * Plotting on top of Images::   
 * Color Conversion::            
 
+Object Oriented Programming
+
+* Creating a Class:
+* Manipulating Classes::
+* Indexing Objects::
+* Overloading Objects::
+
 System Utilities
 
 * Timing Utilities::            
@@ -600,6 +608,7 @@
 @include signal.texi
 @include image.texi
 @include audio.texi
address@hidden oop.texi
 @include system.texi
 @include package.texi
 
diff --git a/doc/interpreter/oop.txi b/doc/interpreter/oop.txi
new file mode 100644
--- /dev/null
+++ b/doc/interpreter/oop.txi
@@ -0,0 +1,474 @@
address@hidden Copyright (C) 2008 David Bateman
address@hidden
address@hidden This file is part of Octave.
address@hidden
address@hidden Octave is free software; you can redistribute it and/or modify it
address@hidden under the terms of the GNU General Public License as published 
by the
address@hidden Free Software Foundation; either version 3 of the License, or (at
address@hidden your option) any later version.
address@hidden 
address@hidden Octave is distributed in the hope that it will be useful, but 
WITHOUT
address@hidden ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or
address@hidden FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public 
License
address@hidden for more details.
address@hidden 
address@hidden You should have received a copy of the GNU General Public License
address@hidden along with Octave; see the file COPYING.  If not, see
address@hidden <http://www.gnu.org/licenses/>.
+
address@hidden FIXME
address@hidden For now can't include "@" character in the path name, and so name
address@hidden the example directory without the "@"!!
+
address@hidden classfile{class, file}
address@hidden
address@hidden
address@hidden @value{abs_top_srcdir}/examples/\class\/\file\
address@hidden group
address@hidden example
address@hidden macro
+
address@hidden polynomialfile{file}
address@hidden,\file\}
address@hidden macro
+
address@hidden Object Oriented Programming
address@hidden Object Oriented Programming
+
+Octave includes the capability to include user classes, including the
+features of operator and function overloading. Equally a user class
+can be used to encapsulate certain properties of the class so that
+they can not be altered accidentally and can be set up to address the
+issue of class precedence in mixed class operations.
+
+This chapter discussions the means of constructing a user class with
+the example of a polynomial class, how to query and set the properties
+of this class, together with the means to overload operators and
+functions.
+
address@hidden
+* Creating a Class::
+* Manipulating Classes::
+* Indexing Objects::
+* Overloading Objects::
address@hidden menu
+
address@hidden Creating a Class
address@hidden Creating a Class
+
+We use in the following text a polynomial class to demonstrate the use
+of object oriented programming within Octave. This class was chosen as
+it is simple, and so doesn't distract unnecessarily from the
+discussion of the programming features of Octave. However, even still
+a small understand of the polynomial class itself is necessary to
+fully grasp the techniques described.
+
+The polynomial class is used to represent polynomials of the form
+
address@hidden
address@hidden
address@hidden
+$a_0 + a_1 x + a_2 x^2 + \ldots a_n x^n$
address@hidden tex
address@hidden iftex
address@hidden
+a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
address@hidden ifnottex
address@hidden example
+
address@hidden
+where
address@hidden
address@hidden
+$a_0$, $a_1$, etc are elements of $\Re$.
address@hidden tex
address@hidden iftex
address@hidden
+a0, a1, etc are real scalars.
address@hidden ifnottex
+Thus the polynomial can be represented by a vector
+
address@hidden
+a = [a0, a1, a2, @dots{}, an];
address@hidden example
+
+We therefore now have sufficient information about the requirements of
+the class constructor for our polynomial class to write it. All object
+oriented classes in Octave, must be contained with a directory taking
+the name of the class, prepended with the @@ symbol. For example, with
+our polynomial class, we would place the methods defining the class in
+the @@polynomial directory.
+
+The constructor of the class, must have the name of the class itself
+and so in our example the constructor with have the name
address@hidden@@polynomial/polynomial.m}. Also ideally when the constructor is
+called with no arguments to should return a value object. So for example
+our polynomial might look like
+
address@hidden
+
+Note that the return value of the constructor must be the output of
+the @code{class} function called with the first argument being a
+structure and the second argument being the class name. An example of
+the call to this constructor function is then
+
address@hidden
+p = polynomial ([1, 0, 1]);
address@hidden example
+
+Note that methods of a class can be documented. The help for the
+constructor itself can be obtained with the constructor name, that is
+for the polynomial constructor @code{help polynomial} will return the
+help string. Also the help can be obtained by restricting the search
+for the help to a particular class, for example @code{help
+@@polynomial/polynomial}. This second method is the only means of
+getting help for the overloaded methods and functions of the class.
+
+The same is true for other Octave functions that take a function name
+as an argument. For example @code{type @@polynomial/display} will
+print the code of the display method of the polynomial class to the
+screen, and @code{dbstop @@polynomial/display} will set a breakpoint
+at the first executable line of the display method of the polynomial
+class.
+
+To check where a variable is a user class, the @code{isobject} and
address@hidden functions can be used. for example
+
address@hidden
address@hidden
+p = polynomial ([1, 0, 1]);
+isobject (p)
address@hidden 1
+isa (p, "polynomial")
address@hidden 1
address@hidden group
address@hidden example
+
address@hidden(isobject)
+
address@hidden
+The available methods of a class can be displayed with the
address@hidden function.
+
address@hidden(methods)
+
address@hidden
+To enquiry whether a particular method is available to a user class, the
address@hidden function can be used.
+
address@hidden(ismethod)
+
address@hidden
+For example
+
address@hidden
address@hidden
+p = polynomial ([1, 0, 1]);
+ismethod (p, "roots")
address@hidden 1
address@hidden group
address@hidden example
+
address@hidden Manipulating Classes
address@hidden Manipulating Classes
+
+There are a number of basic classes methods that can be defined to allow
+the contents of the classes to be queried and set. The most basic of
+these is the @code{display} method. The @code{display} method is used
+by Octave when displaying a class on the screen, due to an expression
+that is not terminated with a semicolon. If this method is not defined,
+then Octave will printed nothing when displaying the contents of a class.
+
address@hidden(display)
+
address@hidden
+An example of a display method for the polynomial class might be
+
address@hidden
+
address@hidden
+Note that in the display method, it makes sense to start the method
+with the line @code{fprintf("%s =", inputname(1))} to be consistent
+with the rest of Octave and print the variable name to be displayed
+when displaying the class. 
+
+To be consistent with the Octave graphic handle classes, a class
+should also define the @code{get} and @code{set} methods. The
address@hidden method should accept one or two arguments, and given one
+argument of the appropriate class it should return a structure with
+all of the properties of the class. For example
+
address@hidden
+
address@hidden
+Similarly, the @code{set} method should taken as its first argument an
+object to modify, and then take property/value pairs to be modified. 
+
address@hidden
+
address@hidden
+Note that as Octave does not implement pass by reference, than the
+modified object is the return value of the @code{set} method and it
+must be called like
+
address@hidden
+p = set (p, "a", [1, 0, 0, 0, 1]);
address@hidden example
+
address@hidden
+Also the @code{set} method makes use of the @code{subsasgn} method of
+the class, and this method must be defined. The @code{subsasgn} method
+is discussed in the next section.
+
+Finally, user classes can be considered as a special type of a
+structure, and so they can be saved to a file in the same manner as a
+structure. For example
+
address@hidden
address@hidden
+p = polynomial ([1, 0, 1]);
+save userclass.mat p
+clear p
+load userclass.mat
address@hidden group
address@hidden example
+
address@hidden
+All of the file formats supported by @code{save} and @code{load} are
+supported. In certain circumstances, a user class might either contain
+a field that it makes no sense to save or a field that needs to be
+initialized before it is saved. This can be done with the
address@hidden method of the class
+
address@hidden(saveobj)
+
address@hidden
address@hidden is called just prior to saving the class to a
+file. Likely, the @code{loadobj} method is called just after a class
+is loaded from a file, and can be used to ensure that any removed
+fields are reinserted into the user object.
+
address@hidden(loadobj)
+
address@hidden Indexing Objects
address@hidden Indexing Objects
+
+Objects in can be indexed with parenthesises, either like 
address@hidden@var{a} (@var{idx})} or like @address@hidden @address@hidden@}}, 
or even
+like @address@hidden (@var{idx})address@hidden However, it is up to the user
+to decide what this indexing actually means. In the case of our polynomial
+class @address@hidden (@var{n})} might mean either the coefficient of the 
address@hidden power of the polynomial, or it might be the evaluation of the 
+polynomial at @var{n}. The meaning of this subscripted referencing is 
+determined by the @code{subsref} method.
+
address@hidden(subsref)
+
+For example we might decide that indexing with "()" evaluates the
+polynomial and indexing with "{}" returns the @var{n}-th coefficient.
+In this case the @code{subsref} method of our polynomial class might look like
+
address@hidden
+
+The equivalent functionality for subscripted asignments uses the 
address@hidden method.
+
address@hidden(subsasgn)
+
+If you wish to use the @code{end} keyword in subscripted expressions
+of an object. Then the user needs to define the @code{end} method for 
+the class.
+
address@hidden(end)
+
+For example the @code{end} method for our polynomial class might look like
+
address@hidden
+
address@hidden
+which is a fairly generic @code{end} method that has a behavior similar to
+the @code{end} keyword for Octave Array classes. It can then be used for
+example like
+
address@hidden
address@hidden
+p = polynomial([1,2,3,4]);
+p(end-1)
address@hidden 3
address@hidden group
address@hidden example
+
+Objects can also be used as the index in a subscripted expression themselves
+and this is controlled with the @code{subsindex} function.
+
address@hidden(subsindex)
+
+Finally, objects can equally be used like ranges, using the @code{colon}
+method
+
address@hidden(colon)
+
address@hidden Overloading Objects
address@hidden Overloading Objects
+
address@hidden
+* Function Overloading::
+* Operator Overloading::
+* Precedence of Objects::
address@hidden menu
+
address@hidden Function Overloading
address@hidden Function Overloading
+
+Any Octave function can be overloaded, and allows a object specific
+version of this function to be called as needed. A pertinent example
+for our polynomial class might be to overload the @code{polyval} function
+like
+
address@hidden
+
+This function just hands off the work to the normal Octave @code{polyval}
+function. Another interesting example for an overloaded function for our
+polynomial class is the @code{plot} function.
+
address@hidden
+
address@hidden
+which allows polynomials to be plotted in the domain near the region
+of the roots of the polynomial.
+
+Functions that are of particular interest to be overloaded are the class
+conversion functions such as @code{double}. Overloading these functions 
+allows the @code{cast} function to work with the user class and can aid 
+in the use of methods of other classes with the user class. An example
address@hidden function for our polynomial class might look like.
+
address@hidden
+
address@hidden Operator Overloading
address@hidden Operator Overloading
+
address@hidden Table,tab:overload_ops
address@hidden
address@hidden
+\vskip 6pt
+{\hbox to \hsize {\hfill\vbox{\offinterlineskip \tabskip=0pt 
+\halign{
+\vrule height2.0ex depth1.ex width 0.6pt #\tabskip=0.3em &
+# \hfil & \vrule # & # \hfil & \vrule # & # \hfil & # \vrule 
+width 0.6pt \tabskip=0pt\cr
+\noalign{\hrule height 0.6pt}
+& Operation && Method && Description &\cr
+\noalign{\hrule}
+& $a + b$ && plus (a, b) && Binary addition operator&\cr
+& $a - b$ && plus (a, b) && Binary subtraction operator&\cr
+& $+ a$ && uplus (a) && Unary addition operator&\cr
+& $- a$ && uminus (a) && Unary subtraction operator&\cr
+& $a .* b$ && times (a, b) && Element-wise multiplication operator&\cr
+& $a * b$ && mtimes (a, b) && Matrix multiplication operator&\cr
+& $a ./ b$ && rdivide (a, b) && Element-wise right division operator&\cr
+& $a / b$ && mrdivide (a, b) && Matrix right division operator&\cr
+& $a .\backslash b$ && ldivide (a, b) && Element-wise left division 
operator&\cr
+& $a \backslash b$ && mldivide (a, b) && Matrix left division operator&\cr
+& $a .\hat b$ && power (a, b) && Element-wise power operator&\cr
+& $a \hat b$ && mpower (a, b) && Matrix power operator&\cr
+& $a < b$ && lt (a, b) && Less than operator&\cr
+& $a <= b$ && le (a, b) && Less than or equal to operator&\cr
+& $a > b$ && gt (a, b) && Greater than operator&\cr
+& $a >= b$ && ge (a, b) && Greater than or equal to operator&\cr
+& $a == b$ && eq (a, b) && Equal to operator&\cr
+& $a != b$ && ne (a, b) && Not equal to operator&\cr
+& $a \& b$ && and (a, b) && Logical and operator&\cr
+& $a | b$ && or (a, b) && Logical or operator&\cr
+& $! b$ && not (a) && Logical not operator&\cr
+& $a'$ && ctranspose (a) && Complex conjugate transpose operator &\cr
+& $a.'$ && transpose (a) && Transpose operator &\cr
+& $a : b$ && colon (a, b) && Two element range operator &\cr
+& $a : b : c$ && colon (a, b, c) && Three element range operator &\cr
+& $[a, b]$ && horzcat (a, b) && Horizontal concatenation opertaor &\cr
+& $[a; b]$ && vertcat (a, b) && Vertical concatenation opertaor &\cr
+& $a(s_1, \ldots, s_n)$ && subsref (a, s) && Subscripted reference &\cr
+& $a(s_1, \ldots, s_n) = b$ && subsasgn (a, s, b) && Subscripted assignment 
&\cr
+& $b (a)$ && subsindex (a) && Convert to zero-based index &\cr
+& {\it display} && display (a) && Commandline display function &\cr
+\noalign{\hrule height 0.6pt}
+}}\hfill}}
address@hidden tex
address@hidden iftex
address@hidden
address@hidden @columnfractions .1 .20 .20 .40 .1
address@hidden @tab Operation @tab Method @tab Description @tab
address@hidden @tab a + b @tab plus (a, b) @tab Binary addition @tab
address@hidden @tab a - b$ @tab plus (a, b) @tab Binary subtraction operator 
@tab
address@hidden @tab + a$ @tab uplus (a) @tab Unary addition operator @tab
address@hidden @tab - a$ @tab uminus (a) @tab Unary subtraction operator @tab
address@hidden @tab a .* b$ @tab times (a, b) @tab Element-wise multiplication 
operator @tab
address@hidden @tab a * b$ @tab mtimes (a, b) @tab Matirx multiplication 
operator @tab
address@hidden @tab a ./ b$ @tab rdivide (a, b) @tab Element-wise right 
division operator @tab
address@hidden @tab a / b$ @tab mrdivide (a, b) @tab Matrix right division 
operator @tab
address@hidden @tab a .\ b$ @tab ldivide (a, b) @tab Element-wise left division 
operator @tab
address@hidden @tab a \ b$ @tab mldivide (a, b) @tab Matrix left division 
operator @tab
address@hidden @tab a .^ b$ @tab ldivide (a, b) @tab Element-wise power 
operator @tab
address@hidden @tab a ^ b$ @tab mldivide (a, b) @tab Matrix power operator @tab
address@hidden @tab a < b$ @tab lt (a, b) @tab Less than operator @tab
address@hidden @tab a <= b$ @tab le (a, b) @tab Less than or equal to operator 
@tab
address@hidden @tab a > b$ @tab gt (a, b) @tab Greater than operator @tab
address@hidden @tab a >= b$ @tab ge (a, b) @tab Greater than or equal to 
operator @tab
address@hidden @tab a == b$ @tab eq (a, b) @tab Equal to operator @tab
address@hidden @tab a != b$ @tab ne (a, b) @tab Not equal to operator @tab
address@hidden @tab a \& b$ @tab and (a, b) @tab Logical and operator @tab
address@hidden @tab a | b$ @tab or (a, b) @tab Logical or operator @tab
address@hidden @tab ! b$ @tab not (a) @tab Logical not operator @tab
address@hidden @tab a'$ @tab ctranspose (a) @tab Complex conjugate transpose 
operator @tab
address@hidden @tab a.'$ @tab transpose (a) @tab Transpose operator @tab
address@hidden @tab a : b$ @tab colon (a, b) @tab Two element range operator 
@tab
address@hidden @tab a : b : c$ @tab colon (a, b, c) @tab Three element range 
operator @tab
address@hidden @tab [a, b]$ @tab horzcat (a, b) @tab Horizontal concatenation 
opertaor @tab
address@hidden @tab [a; b]$ @tab vertcat (a, b) @tab Vertical concatenation 
opertaor @tab
address@hidden @tab a(s_1, \ldots, s_n)$ @tab subsref (a, s) @tab Subscripted 
reference @tab
address@hidden @tab a(s_1, \ldots, s_n) = b$ @tab subsasgn (a, s, b) @tab 
Subscripted assignment @tab
address@hidden @tab b (a)$ @tab subsindex (a) @tab Convert to zero-based index 
@tab
address@hidden @tab  @dfn{display} @tab display (a) @tab Commandline display 
function @tab
address@hidden multitable
address@hidden ifnottex
address@hidden overloaded operators and their corresponding class method}
address@hidden float
+
+An example @code{mtimes} method for our polynomial class might look like
+
address@hidden
+
address@hidden Precedence of Objects
address@hidden Precedence of Objects
+
+Many functions and operators take two or more arguments and so the
+case can easily arise that these functions are called with objects of
+different classes. It is therefore necessary to determine the precedence
+of which method of which class to call when there are mixed objects given
+to a function or operator. To do this the @code{superiorto} and
address@hidden functions can be used
+
address@hidden(superiorto)
+
address@hidden(inferiorto)
+
+For example with our polynomial class consider the case
+
address@hidden
+2 * polynomial ([1, 0, 1]);
address@hidden example
+
address@hidden
+That mixes an object of the class "double" with an object of the class
+"polynomial". In this case we like to ensure that the return type of
+the above is of the type "polynomial" and so we use the
address@hidden function in the class constructor. In particular our
+polynomial class constructor would be modified to be
+
address@hidden
+
+Note that user classes always have higher precedence than built-in
+Octave types. So in fact marking our polynomial class higher than the 
+"double" class is in fact not necessary.
+
+
diff --git a/examples/Makefile.in b/examples/Makefile.in
--- a/examples/Makefile.in
+++ b/examples/Makefile.in
@@ -33,6 +33,10 @@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_DATA = @INSTALL_DATA@
+
+SUBDIRS = polynomial
+
+DISTSUBDIRS = $(SUBDIRS)
 
 SCRIPTS = info-emacs-info info-emacs-octave-help
 
@@ -78,8 +82,12 @@
 
 DISTSUBDIRS = 
 
-all: octave.desktop
+all: $(SUBDIRS) octave.desktop
 .PHONY: all
+
+$(SUBDIRS):
+       $(MAKE) -C $@ all
+.PHONY: $(SUBDIRS)
 
 octave.desktop: octave.desktop.in Makefile ../Makeconf
        echo "making $@ from $<"
@@ -134,4 +142,5 @@
 
 dist:
        ln $(DISTFILES) ../`cat ../.fname`/examples
+       for dir in $(DISTSUBDIRS); do mkdir ../`cat ../.fname`/scripts/$$dir; 
$(MAKE) -C $$dir $@; done
 .PHONY: dist
diff --git a/examples/polynomial/Makefile.in b/examples/polynomial/Makefile.in
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/Makefile.in
@@ -0,0 +1,93 @@
+# Makefile for octave's scripts/geometry directory
+#
+# Copyright (C) 2007 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/>.
+
+TOPDIR = ../..
+
+script_sub_dir = polynomial
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+include $(TOPDIR)/Makeconf
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+SOURCES = \
+  display.m \
+  double.m \
+  end.m \
+  get.m \
+  mtimes.m \
+  plot.m \
+  polynomial.m \
+  polynomial_superiorto.m \
+  polyval.m \
+  set.m \
+  subsasgn.m \
+  subsref.m
+
+DISTFILES = $(addprefix $(srcdir)/,Makefile.in $(SOURCES))
+
+FCN_FILES = $(addprefix $(srcdir)/, $(SOURCES))
+FCN_FILES_NO_DIR = $(notdir $(FCN_FILES))
+
+all: PKG_ADD
+.PHONY: all
+
+install install-strip:
+.PHONY: install install-strip
+
+uninstall:
+.PHONY: uninstall
+
+clean:
+.PHONY: clean
+
+PKG_ADD: $(FCN_FILES)
+       @echo "making PKG_ADD"
+       @$(do-mkpkgadd)
+
+tags: $(SOURCES)
+       ctags $(SOURCES)
+
+TAGS: $(SOURCES)
+       etags $(SOURCES)
+
+mostlyclean: clean
+.PHONY: mostlyclean
+
+distclean: clean
+       rm -f Makefile PKG_ADD
+.PHONY: distclean
+
+maintainer-clean: distclean
+       rm -f tags TAGS
+.PHONY: maintainer-clean
+
+dist:
+       ln $(DISTFILES) ../../`cat ../../.fname`/examples/$(script_sub_dir)
+.PHONY: dist
+
+check-m-sources:
+       @$(do-check-m-sources)
+.PHONY: check-m-sources
diff --git a/examples/polynomial/display.m b/examples/polynomial/display.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/display.m
@@ -0,0 +1,33 @@
+function display (p)
+  a = p.poly;
+  first = true;
+  fprintf("%s =", inputname(1));
+  for i = 1 : length (a);
+    if (a(i) != 0)
+      if (first)
+       first = false;
+      elseif (a(i) > 0)
+       fprintf (" +");
+      endif
+      if (a(i) < 0)
+       fprintf (" -");
+      endif
+      if (i == 1)
+       fprintf (" %g", abs (a(i)));
+      elseif (abs(a(i)) != 1)
+       fprintf (" %g *", abs (a(i)));
+      endif
+      if (i > 1)
+       fprintf (" X");
+      endif
+      if (i > 2)
+       fprintf (" ^ %d", i - 1);
+      endif
+    endif
+  endfor
+  if (first)
+    fprintf(" 0");
+  endif
+  fprintf("\n");
+endfunction
+
diff --git a/examples/polynomial/double.m b/examples/polynomial/double.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/double.m
@@ -0,0 +1,3 @@
+function b = double (a)
+  b = a.poly;
+endfunction
diff --git a/examples/polynomial/end.m b/examples/polynomial/end.m
new file mode 100755
--- /dev/null
+++ b/examples/polynomial/end.m
@@ -0,0 +1,11 @@
+function r = end (obj, index_pos, num_indices)
+  dv = size (obj.x);
+  for i = (num_indices + 1) : length (dv)
+    dv(num_indices) *= dv(i);
+  endfor
+  if (index_pos <= length (dv))
+    r = dv (index_pos);
+  elseif
+    r = 1;
+  endif
+endfunction
diff --git a/examples/polynomial/get.m b/examples/polynomial/get.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/get.m
@@ -0,0 +1,18 @@
+function s = get (p, f)
+  if (nargin == 1)
+    s.poly = p.poly;
+  elseif (nargin == 2)
+    if (ischar (f))
+      switch (f)
+       case "poly"
+         s = p.poly;
+       otherwise
+         error ("get: invalid property %s", f);
+      endswitch
+    else
+      error ("get: expecting the property to be a string");
+    endif
+  else
+    print_usage ();
+  endif
+endfunction
diff --git a/examples/polynomial/mtimes.m b/examples/polynomial/mtimes.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/mtimes.m
@@ -0,0 +1,5 @@
+function y = mtimes (a, b)
+  ap = double (a);
+  bp = double (b);
+  y = polynomial (filter (ap, 1, [bp(:).', zeros(1, length(bp) - 1)]));
+endfunction
\ No newline at end of file
diff --git a/examples/polynomial/plot.m b/examples/polynomial/plot.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/plot.m
@@ -0,0 +1,10 @@
+function h = plot(p, varargin)
+  n = 128;
+  rmax = max (abs (roots (p.poly)));
+  x = [0 : (n - 1)] / (n - 1) * 2.2 * rmax - 1.1 * rmax;
+  if (nargout > 0)
+    h = plot(x, p(x), varargin{:});
+  else
+    plot(x, p(x), varargin{:});
+  endif
+endfunction
\ No newline at end of file
diff --git a/examples/polynomial/polynomial.m b/examples/polynomial/polynomial.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/polynomial.m
@@ -0,0 +1,28 @@
+## -*- texinfo -*-
+## @deftypefn {Function File} {} polynomial ()
+## @deftypefnx {Function File} {} polynomial (@var{a})
+## Creates a polynomial object representing the polynomial
+##
+## @example
+## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
+## @end example
+## @end deftypefn
+
+function p = polynomial (a)
+  if (nargin == 0)
+    p.poly = [];
+    p = class (p, "polynomial");
+  elseif (nargin == 1)
+    if (strcmp (class (a), "polynomial"))
+      p = a;
+    elseif (isvector (a) && isreal (a))
+      p.poly = a(:)';
+      p = class (p, "polynomial");
+    else
+      error ("polynomial: expecting real or complex vector")
+    endif
+  else
+    print_usage ();
+  endif
+  superiorto ("double");
+endfunction
diff --git a/examples/polynomial/polynomial_superiorto.m 
b/examples/polynomial/polynomial_superiorto.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/polynomial_superiorto.m
@@ -0,0 +1,18 @@
+function p = polynomial (a)
+  if (nargin == 0)
+    p.poly = [];
+    p = class (p, "polynomial");
+  elseif (nargin == 1)
+    if (strcmp (class (a), "polynomial"))
+      p = a;
+    elseif (isvector (a) && isreal (a))
+      p.poly = a(:)';
+      p = class (p, "polynomial");
+    else
+      error ("polynomial: expecting real or complex vector")
+    endif
+  else
+    print_usage ();
+  endif
+  superiorto ("double");
+endfunction
diff --git a/examples/polynomial/polyval.m b/examples/polynomial/polyval.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/polyval.m
@@ -0,0 +1,7 @@
+function [y, dy] = polyval (p, varargin)
+  if (nargout == 2)
+    [y, dy] = polyval (p.poly, varargin{:});
+  else
+    y = polyval (p.poly, varargin{:});
+  endif
+endfunction
diff --git a/examples/polynomial/set.m b/examples/polynomial/set.m
new file mode 100644
--- /dev/null
+++ b/examples/polynomial/set.m
@@ -0,0 +1,20 @@
+function s = set (p, varargin)
+  s = p;
+  if (length (varargin) < 2 || rem (length (varargin), 2) != 0)
+    error ("set: expecting property/value pairs");
+  endif
+  while (length (varargin) > 1)
+    prop = varargin{1};
+    val = varargin{2};
+    varargin(1:2) = [];
+    if (ischar (prop) && strcmp (prop, "poly"))
+      if (isvector (val) && isreal (val))
+       s.poly = val(:)';
+      else
+       error ("set: expecting the value to be a real vector");
+      endif
+    else
+      error ("set: invalid property of polynomial class");
+    endif
+  endwhile
+endfunction
\ No newline at end of file
diff --git a/examples/polynomial/subsasgn.m b/examples/polynomial/subsasgn.m
new file mode 100755
--- /dev/null
+++ b/examples/polynomial/subsasgn.m
@@ -0,0 +1,12 @@
+function s = subsasgn (s, index, val)
+  switch (index.type)
+    case "()"
+      if (! isnumeric (val) || iscomplex(val) ||any (val(:)) >= 2.^ s.m || 
+         any (val(:)) < 0 || any (val(:) != fix(val(:))))
+       error ("subsasgn: value must be an array of real integers between 0 and 
2.^m - 1");
+      endif
+      s.x = subsasgn (s.x, index, double (val));
+    case "."
+      error ("subsagn: can not set properties of a galois field directly");
+  endswitch
+endfunction
diff --git a/examples/polynomial/subsref.m b/examples/polynomial/subsref.m
new file mode 100755
--- /dev/null
+++ b/examples/polynomial/subsref.m
@@ -0,0 +1,17 @@
+function b = subsref (a, s)
+  switch s.type
+    case "()"
+      ind = s.subs;
+      b = polyval (fliplr(a.poly), ind{:});
+    case "{}"
+      ind = s.subs;
+      b = polynomial (a.poly(ind{:}));
+    case "."
+      fld = s.subs;
+      if (strcmp (fld, "poly"))
+       b = a.poly;
+      else
+       error ("subsref: unrecognized property \"%s\" of a polynomial", fld);
+      endif
+  endswitch
+endfunction
diff --git a/scripts/ChangeLog b/scripts/ChangeLog
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,8 @@
+2008-10-15  David Bateman  <address@hidden>
+
+       * general/colon.m: Small typo.
+       * general/loadobj.m: Ditto.
+       
 2008-10-14  Daniel J. Sebald  <address@hidden>
 
        * plot/__go_draw_axes__.m: Send binary data to gnuplot.
diff --git a/scripts/general/colon.m b/scripts/general/colon.m
--- a/scripts/general/colon.m
+++ b/scripts/general/colon.m
@@ -27,6 +27,7 @@
 ## a = myclass (@dots{})
 ## b = myclass (@dots{})
 ## c = a : b
+## @end group
 ## @end example
 ##
 ## @seealso{class, subsref, subsasgn}
diff --git a/scripts/general/loadobj.m b/scripts/general/loadobj.m
--- a/scripts/general/loadobj.m
+++ b/scripts/general/loadobj.m
@@ -18,7 +18,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} address@hidden =} loadobj (@var{a})
-## Methof of a class to manipulate an object after loading it tfrom a file. 
+## Method of a class to manipulate an object after loading it tfrom a file. 
 ## The function @code{loadobj} is called when the object @var{a} is loaded 
 ## using the @code{load} function. An example of the use of @code{saveobj}
 ## might be to add fields to an object that don't make sense to be saved.
diff --git a/src/ChangeLog b/src/ChangeLog
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2008-10-15  David Bateman  <address@hidden>
+
+       * ov-class.c (Fsuperiorto, Finferiorto): Allow more than one class
+       to be defined at a time.
+
 2008-10-12  David Bateman  <address@hidden>
 
        * pt-colon.cc (octave_value tree_colon_expression::make_range 
diff --git a/src/ov-class.cc b/src/ov-class.cc
--- a/src/ov-class.cc
+++ b/src/ov-class.cc
@@ -1342,9 +1342,10 @@
 
 DEFUN (superiorto, args, ,
   "-*- texinfo -*-\n\
address@hidden {Built-in Function} {} superiorto (@var{class_name})\n\
address@hidden {Built-in Function} {} superiorto (@var{class_name}, @dots{})\n\
 When called from a class constructor, mark the object currently\n\
 constructed as having a higher precedence than @var{class_name}.\n\
+More that one such class can be specified in a single call.\n\
 This function may only be called from a class constructor.\n\
 @end deftypefn")
 {
@@ -1354,9 +1355,9 @@
 
   if (fcn && fcn->is_class_constructor ())
     {
-      if (args.length () == 1)
+      for (int i = 0; i < args.length(); i++)
        {
-         std::string class_name = args(0).string_value ();
+         std::string class_name = args(i).string_value ();
 
          if (! error_state)
            {
@@ -1366,8 +1367,11 @@
 
                  if (! symbol_table::set_class_relationship (this_class_name,
                                                              class_name))
-                   error ("superiorto: precedence already set for %s and %s",
-                          this_class_name.c_str (), class_name.c_str ());
+                   {
+                     error ("superiorto: precedence already set for %s and %s",
+                            this_class_name.c_str (), class_name.c_str ());
+                     break;
+                   }
                }
              else
                {
@@ -1376,10 +1380,11 @@
                }
            }
          else
-           error ("superiorto: expecting argument to be class name");
+           {
+             error ("superiorto: expecting argument to be class name");
+             break;
+           }
        }
-      else
-       print_usage ();
     }
   else
     error ("superiorto: invalid call from outside class constructor");
@@ -1389,9 +1394,10 @@
 
 DEFUN (inferiorto, args, ,
   "-*- texinfo -*-\n\
address@hidden {Built-in Function} {} inferiorto (@var{class_name})\n\
address@hidden {Built-in Function} {} inferiorto (@var{class_name}, @dots{})\n\
 When called from a class constructor, mark the object currently\n\
 constructed as having a lower precedence than @var{class_name}.\n\
+More that one such class can be specified in a single call.\n\
 This function may only be called from a class constructor.\n\
 @end deftypefn")
 {
@@ -1401,9 +1407,9 @@
 
   if (fcn && fcn->is_class_constructor ())
     {
-      if (args.length () == 1)
+      for (int i = 0; i < args.length(); i++)
        {
-         std::string class_name = args(0).string_value ();
+         std::string class_name = args(i).string_value ();
 
          if (! error_state)
            {
@@ -1416,17 +1422,24 @@
 
                  if (! symbol_table::set_class_relationship (this_class_name,
                                                              class_name))
-                   error ("inferiorto: precedence already set for %s and %s",
-                          this_class_name.c_str (), class_name.c_str ());
+                   {
+                     error ("inferiorto: precedence already set for %s and %s",
+                            this_class_name.c_str (), class_name.c_str ());
+                     break;
+                   }
                }
              else
-               error ("inferiorto: cannot give user-defined class lower 
precedence than built-in class");
+               {
+                 error ("inferiorto: cannot give user-defined class lower 
precedence than built-in class");
+                 break;
+               }
            }
          else
-           error ("inferiorto: expecting argument to be class name");
+           {
+             error ("inferiorto: expecting argument to be class name");
+             break;
+           }
        }
-      else
-       print_usage ();
     }
   else
     error ("inferiorto: invalid call from outside class constructor");

reply via email to

[Prev in Thread] Current Thread [Next in Thread]