# HG changeset patch # User David Bateman # Date 1224145258 -3600 # Node ID 0c91b9a17dcfd3c4fb3810e6f47850ab24d8cfba # Parent 11badf6c9e9fbcd1918850014a303fe8daef6f9e Commit missing files from previous change diff -r 11badf6c9e9f -r 0c91b9a17dcf doc/interpreter/oop.txi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/interpreter/oop.txi Thu Oct 16 09:20:58 2008 +0100 @@ -0,0 +1,474 @@ +@c Copyright (C) 2008 David Bateman +@c +@c This file is part of Octave. +@c +@c Octave is free software; you can redistribute it and/or modify it +@c under the terms of the GNU General Public License as published by the +@c Free Software Foundation; either version 3 of the License, or (at +@c your option) any later version. +@c +@c Octave is distributed in the hope that it will be useful, but WITHOUT +@c ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +@c FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +@c for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with Octave; see the file COPYING. If not, see +@c . + +@c FIXME +@c For now can't include "@" character in the path name, and so name +@c the example directory without the "@"!! + +@macro classfile{class, file} +@example +@group +@verbatiminclude @value{abs_top_srcdir}/examples/\class\/\file\ +@end group +@end example +@end macro + +@macro polynomialfile{file} +@classfile{polynomial,\file\} +@end macro + +@node Object Oriented Programming +@chapter 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. + +@menu +* Creating a Class:: +* Manipulating Classes:: +* Indexing Objects:: +* Overloading Objects:: +@end menu + +@node Creating a Class +@section 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 + +@example +@iftex +@tex +$a_0 + a_1 x + a_2 x^2 + \ldots a_n x^n$ +@end tex +@end iftex +@ifnottex +a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n +@end ifnottex +@end example + +@noindent +where +@iftex +@tex +$a_0$, $a_1$, etc are elements of $\Re$. +@end tex +@end iftex +@ifnottex +a0, a1, etc are real scalars. +@end ifnottex +Thus the polynomial can be represented by a vector + +@example +a = [a0, a1, a2, @dots{}, an]; +@end 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 +@file{@@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 + +@polynomialfile{polynomial.m} + +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 + +@example +p = polynomial ([1, 0, 1]); +@end 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 +@code{isa} functions can be used. for example + +@example +@group +p = polynomial ([1, 0, 1]); +isobject (p) +@result{} 1 +isa (p, "polynomial") +@result{} 1 +@end group +@end example + +@DOCSTRING(isobject) + +@noindent +The available methods of a class can be displayed with the +@code{methods} function. + +@DOCSTRING(methods) + +@noindent +To enquiry whether a particular method is available to a user class, the +@code{ismethod} function can be used. + +@DOCSTRING(ismethod) + +@noindent +For example + +@example +@group +p = polynomial ([1, 0, 1]); +ismethod (p, "roots") +@result{} 1 +@end group +@end example + +@node Manipulating Classes +@section 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. + +@DOCSTRING(display) + +@noindent +An example of a display method for the polynomial class might be + +@polynomialfile{display.m} + +@noindent +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 +@code{get} 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 + +@polynomialfile{get.m} + +@noindent +Similarly, the @code{set} method should taken as its first argument an +object to modify, and then take property/value pairs to be modified. + +@polynomialfile{set.m} + +@noindent +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 + +@example +p = set (p, "a", [1, 0, 0, 0, 1]); +@end example + +@noindent +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 + +@example +@group +p = polynomial ([1, 0, 1]); +save userclass.mat p +clear p +load userclass.mat +@end group +@end example + +@noindent +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 +@code{saveobj} method of the class + +@DOCSTRING(saveobj) + +@noindent +@code{saveobj} 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. + +@DOCSTRING(loadobj) + +@node Indexing Objects +@section Indexing Objects + +Objects in can be indexed with parenthesises, either like +@code{@var{a} (@var{idx})} or like @code{@var{a} @{@var{idx}@}}, or even +like @code{@var{a} (@var{idx}).@var{field}}. However, it is up to the user +to decide what this indexing actually means. In the case of our polynomial +class @code{@var{p} (@var{n})} might mean either the coefficient of the +@var{n}-th 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. + +@DOCSTRING(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 + +@polynomialfile{subsref.m} + +The equivalent functionality for subscripted asignments uses the +@code{subsasgn} method. + +@DOCSTRING(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. + +@DOCSTRING(end) + +For example the @code{end} method for our polynomial class might look like + +@polynomialfile{end.m} + +@noindent +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 + +@example +@group +p = polynomial([1,2,3,4]); +p(end-1) +@result{} 3 +@end group +@end example + +Objects can also be used as the index in a subscripted expression themselves +and this is controlled with the @code{subsindex} function. + +@DOCSTRING(subsindex) + +Finally, objects can equally be used like ranges, using the @code{colon} +method + +@DOCSTRING(colon) + +@node Overloading Objects +@section Overloading Objects + +@menu +* Function Overloading:: +* Operator Overloading:: +* Precedence of Objects:: +@end menu + +@node Function Overloading +@subsection 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 + +@polynomialfile{polyval.m} + +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. + +@polynomialfile{plot.m} + +@noindent +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 +@code{double} function for our polynomial class might look like. + +@polynomialfile{double.m} + +@node Operator Overloading +@subsection Operator Overloading + +@float Table,tab:overload_ops +@iftex +@tex +\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}} +@end tex +@end iftex +@ifnottex +@multitable @columnfractions .1 .20 .20 .40 .1 +@item @tab Operation @tab Method @tab Description @tab +@item @tab a + b @tab plus (a, b) @tab Binary addition @tab +@item @tab a - b$ @tab plus (a, b) @tab Binary subtraction operator @tab +@item @tab + a$ @tab uplus (a) @tab Unary addition operator @tab +@item @tab - a$ @tab uminus (a) @tab Unary subtraction operator @tab +@item @tab a .* b$ @tab times (a, b) @tab Element-wise multiplication operator @tab +@item @tab a * b$ @tab mtimes (a, b) @tab Matirx multiplication operator @tab +@item @tab a ./ b$ @tab rdivide (a, b) @tab Element-wise right division operator @tab +@item @tab a / b$ @tab mrdivide (a, b) @tab Matrix right division operator @tab +@item @tab a .\ b$ @tab ldivide (a, b) @tab Element-wise left division operator @tab +@item @tab a \ b$ @tab mldivide (a, b) @tab Matrix left division operator @tab +@item @tab a .^ b$ @tab ldivide (a, b) @tab Element-wise power operator @tab +@item @tab a ^ b$ @tab mldivide (a, b) @tab Matrix power operator @tab +@item @tab a < b$ @tab lt (a, b) @tab Less than operator @tab +@item @tab a <= b$ @tab le (a, b) @tab Less than or equal to operator @tab +@item @tab a > b$ @tab gt (a, b) @tab Greater than operator @tab +@item @tab a >= b$ @tab ge (a, b) @tab Greater than or equal to operator @tab +@item @tab a == b$ @tab eq (a, b) @tab Equal to operator @tab +@item @tab a != b$ @tab ne (a, b) @tab Not equal to operator @tab +@item @tab a \& b$ @tab and (a, b) @tab Logical and operator @tab +@item @tab a | b$ @tab or (a, b) @tab Logical or operator @tab +@item @tab ! b$ @tab not (a) @tab Logical not operator @tab +@item @tab a'$ @tab ctranspose (a) @tab Complex conjugate transpose operator @tab +@item @tab a.'$ @tab transpose (a) @tab Transpose operator @tab +@item @tab a : b$ @tab colon (a, b) @tab Two element range operator @tab +@item @tab a : b : c$ @tab colon (a, b, c) @tab Three element range operator @tab +@item @tab [a, b]$ @tab horzcat (a, b) @tab Horizontal concatenation opertaor @tab +@item @tab [a; b]$ @tab vertcat (a, b) @tab Vertical concatenation opertaor @tab +@item @tab a(s_1, \ldots, s_n)$ @tab subsref (a, s) @tab Subscripted reference @tab +@item @tab a(s_1, \ldots, s_n) = b$ @tab subsasgn (a, s, b) @tab Subscripted assignment @tab +@item @tab b (a)$ @tab subsindex (a) @tab Convert to zero-based index @tab +@item @tab @dfn{display} @tab display (a) @tab Commandline display function @tab +@end multitable +@end ifnottex +@caption{Available overloaded operators and their corresponding class method} +@end float + +An example @code{mtimes} method for our polynomial class might look like + +@polynomialfile{mtimes.m} + +@node Precedence of Objects +@subsection 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 +@code{inferiorto} functions can be used + +@DOCSTRING(superiorto) + +@DOCSTRING(inferiorto) + +For example with our polynomial class consider the case + +@example +2 * polynomial ([1, 0, 1]); +@end example + +@noindent +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 +@code{superiorto} function in the class constructor. In particular our +polynomial class constructor would be modified to be + +@polynomialfile{polynomial_superiorto.m} + +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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/Makefile.in Thu Oct 16 09:20:58 2008 +0100 @@ -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 +# . + +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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/display.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/display.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/double.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/double.m Thu Oct 16 09:20:58 2008 +0100 @@ -0,0 +1,3 @@ +function b = double (a) + b = a.poly; +endfunction diff -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/end.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/end.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/get.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/get.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/mtimes.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/mtimes.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/plot.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/plot.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/polynomial.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/polynomial.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/polynomial_superiorto.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/polynomial_superiorto.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/polyval.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/polyval.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/set.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/set.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/subsasgn.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/subsasgn.m Thu Oct 16 09:20:58 2008 +0100 @@ -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 -r 11badf6c9e9f -r 0c91b9a17dcf examples/polynomial/subsref.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/polynomial/subsref.m Thu Oct 16 09:20:58 2008 +0100 @@ -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