This example implements a class to represent polynomials in the MATLAB® language. The design requirements are:
Value class behavior—a polynomial object should behave like MATLAB numeric variables when copied and passed to functions.
Specialized display and indexing
Objects can be scalar only. The specialization of display and indexing functionality preclude normal array behavior.
Arithmetic operations
Double converter simplifying the use of polynomial object with existing MATLAB functions that accept numeric inputs.
DocPolynom
Class MembersThe class definition specifies a property for data storage and
defines a folder (@DocPolynom
) that contains the
class definition.
The following table summarizes the properties defined for the DocPolynom
class.
DocPolynom
Class Properties
Name | Class | Default | Description |
---|---|---|---|
|
|
| Vector of polynomial coefficients [highest order ... lowest order] |
The following table summarizes the methods for the DocPolynom
class.
DocPolynom
Class Methods
Name | Description |
---|---|
| Class constructor |
| Converts a |
| Creates a formatted display of the |
| Determines how MATLAB displays |
| Enables you to specify a value for the independent variable
as a subscript, access the |
| Implements addition of |
| Implements subtraction of |
| Implements multiplication of |
DocPolynom
ClassThe following examples illustrate basic use of the DocPolynom
class.
Create DocPolynom
objects to represent the
following polynomials. The argument to the constructor function contains
the polynomial coefficients and
.
p1 = DocPolynom([1 0 -2 -5])
p1 = x^3 - 2*x - 5
p2 = DocPolynom([2 0 3 2 -7])
p2 = 2*x^4 + 3*x^2 + 2*x - 7
Find the roots of the polynomial by passing the coefficients
to the roots
function.
roots(p1.coef)
ans = 2.0946 + 0.0000i -1.0473 + 1.1359i -1.0473 - 1.1359i
Add the two polynomials p1
and p2
.
MATLAB calls the plus
method defined
for the DocPolynom
class when you add two DocPolynom
objects.
p1 + p2
ans = 2*x^4 + x^3 + 3*x^2 - 12
DocPolynom
Class SynopsisExample Code | Discussion |
---|---|
classdef DocPolynom
| Value class that implements a data type for polynomials. |
properties coef end | Vector of polynomial coefficients [highest order ... lowest order] |
methods | For general information about methods, see Ordinary Methods |
function obj = DocPolynom(c) if nargin > 0 if isa(c,'DocPolynom') obj.coef = c.coef; else obj.coef = c(:).'; end end end | Class constructor creates objects using:
|
function obj = set.coef(obj,val) if ~isa(val,'double') error('Coefficients must be doubles') end ind = find(val(:).'~=0); if ~isempty(ind); obj.coef = val(ind(1):end); else obj.coef = val; end end | Set method for
|
function c = double(obj) c = obj.coef; end | Convert |
function str = char(obj) if all(obj.coef == 0) s = '0'; str = s; return else d = length(obj.coef)-1; s = cell(1,d); ind = 1; for a = obj.coef; if a ~= 0; if ind ~= 1 if a > 0 s(ind) = {' + '}; ind = ind + 1; else s(ind) = {' - '}; a = -a; ind = ind + 1; end end if a ~= 1 || d == 0 if a == -1 s(ind) = {'-'}; ind = ind + 1; else s(ind) = {num2str(a)}; ind = ind + 1; if d > 0 s(ind) = {'*'}; ind = ind + 1; end end end if d >= 2 s(ind) = {['x^' int2str(d)]}; ind = ind + 1; elseif d == 1 s(ind) = {'x'}; ind = ind + 1; end end d = d - 1; end end str = [s{:}]; end | Convert y = f(x) |
function disp(obj) c = char(obj); if iscell(c) disp([' ' c{:}]) else disp(c) end end | Overload For information about this code, see Overload disp for DocPolynom |
function dispPoly(obj,x) p = char(obj); e = @(x)eval(p); y = zeros(length(x)); disp(['y = ',p]) for k = 1:length(x) y(k) = e(x(k)); disp([' ',num2str(y(k)),... ' = f(x = ',... num2str(x(k)),')']) end end | Return evaluated expression with formatted output. Uses
output of For information about this code, see Display Evaluated Expression |
function b = subsref(a,s) switch s(1).type case '()' ind = s.subs{:}; b = polyval(a.coef,ind); case '.' switch s(1).subs case 'coef' b = a.coef; case 'disp' disp(a) otherwise if length(s)>1 b = a.(s(1).subs)(s(2).subs{:}); else b = a.(s.subs); end end otherwise error('Specify value for x as obj(x)') end end | Redefine indexed reference for For information about this code, see Redefine Indexed Reference |
function r = plus(obj1,obj2) obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); k = length(obj2.coef) - length(obj1.coef); zp = zeros(1,k); zm = zeros(1,-k); r = DocPolynom([zp,obj1.coef] + [zm,obj2.coef]); end function r = minus(obj1,obj2) obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); k = length(obj2.coef) - length(obj1.coef); zp = zeros(1,k); zm = zeros(1,-k); r = DocPolynom([zp,obj1.coef] - [zm,obj2.coef]); end function r = mtimes(obj1,obj2) obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); r = DocPolynom(conv(obj1.coef,obj2.coef)); end end | Define three arithmetic operators:
For information about this code, see Define Arithmetic Operators. For general information about defining operators, see Operator Overloading |
end end |
|
DocPolynom
ConstructorThe following function is the DocPolynom
class
constructor, which is in the file @DocPolynom/DocPolynom.m
:
methods function obj = DocPolynom(c) if isa(c,'DocPolynom') obj.coef = c.coef; else obj.coef = c(:).'; end end end
It is possible to all the DocPolynom
constructor
with two different arguments:
Input argument is a DocPolynom
object
— If you call the constructor function with an input argument
that is already a DocPolynom
object, the constructor
returns a new DocPolynom
object with the same coefficients
as the input argument. The isa
function
checks for this input.
Input argument is a coefficient vector — If
the input argument is not a DocPolynom
object,
the constructor attempts to reshape the values into a vector and assign
them to the coef
property.
The coef
property set method restricts property
values to doubles. See Remove Irrelevant Coefficients for a description of the
property set method.
An example use of the DocPolynom
constructor
is the statement:
p = DocPolynom([1 0 -2 -5]) p = x^3 - 2*x -5
This statement creates an instance of the DocPolynom
class
with the specified coefficients. Note that the display of the object
shows the equivalent polynomial using MATLAB language syntax.
The DocPolynom
class implements this display using
the disp
and char
class methods.
MATLAB software represents polynomials as row vectors containing coefficients ordered by descending powers. Zeros in the coefficient vector represent terms that drop out of the polynomial. Leading zeros, therefore, can be ignored when forming the polynomial.
Some DocPolynom
class methods use the length
of the coefficient vector to determine the degree of the polynomial.
It is useful, therefore, to remove leading zeros from the coefficient
vector so that its length represents the true value.
The DocPolynom
class stores the coefficient
vector in a property that uses a set method to remove leading zeros
from the specified coefficients before setting the property value.
methods function obj = set.coef(obj,val) if ~isa(val,'double') error('Coefficients must be doubles') end ind = find(val(:).'~=0); if ~isempty(ind); obj.coef = val(ind(1):end); else obj.coef = val; end end end
DocPolynom
Objects to Other TypesThe DocPolynom
class defines two methods
to convert DocPolynom
objects to other classes:
double
— Converts to the
double numeric type so functions can perform mathematical operations
on the coefficients.
char
— Converts to characters
used to format output for display in the command window
The double converter method for the DocPolynom
class
simply returns the coefficient vector:
methods function c = double(obj) c = obj.coef; end end
For the DocPolynom
object p
:
p = DocPolynom([1 0 -2 -5]);
the statement:
c = double(p)
returns:
c= 1 0 -2 -5
which is of class double
:
class(c) ans = double
The char
method produces a char
vector
that represents the polynomial displayed as powers of x
.
The char
vector returned is a syntactically correct MATLAB expression.
The char
method uses a cell array to collect
the char
vector components that make up the displayed
polynomial.
The disp
method uses the char
method
to format the DocPolynom
object for display. The evalPoly
method
uses char
to create the MATLAB expression
to evaluate.
Users of DocPolynom
objects are not likely
to call the char
or disp
methods
directly, but these methods enable the DocPolynom
class
to behave like other data classes in MATLAB.
Here is the char
method.
methods function str = char(obj) if all(obj.coef == 0) s = '0'; str = s; return else d = length(obj.coef)-1; s = cell(1,d); ind = 1; for a = obj.coef; if a ~= 0; if ind ~= 1 if a > 0 s(ind) = {' + '}; ind = ind + 1; else s(ind) = {' - '}; a = -a; ind = ind + 1; end end if a ~= 1 || d == 0 if a == -1 s(ind) = {'-'}; ind = ind + 1; else s(ind) = {num2str(a)}; ind = ind + 1; if d > 0 s(ind) = {'*'}; ind = ind + 1; end end end if d >= 2 s(ind) = {['x^' int2str(d)]}; ind = ind + 1; elseif d == 1 s(ind) = {'x'}; ind = ind + 1; end end d = d - 1; end end str = [s{:}]; end end
disp
for DocPolynomTo provide a more useful display of DocPolynom
objects,
this class overloads disp
in
the class definition.
This disp
method relies on the char
method
to produce a text representation of the polynomial, which it then
displays on the screen.
The char
method returns a cell array or the
character '0'
if the coefficients are all zero.
methods function disp(obj) c = char(obj); if iscell(c) disp([' ' c{:}]) else disp(c) end end end
disp
MethodThe statement:
p = DocPolynom([1 0 -2 -5])
creates a DocPolynom
object. Because the
statement is not terminated with a semicolon, the resulting output
is displayed on the command line:
p = x^3 - 2*x - 5
The char
converter method forms a MATLAB expression
for the polynomial represented by a DocPolynom
object.
The dispPoly
method evaluates the expression returned
by the char
method with a specified value for x
.
methods function dispPoly(obj,x) p = char(obj); e = @(x)eval(p); y = zeros(length(x)); disp(['y = ',p]) for k = 1:length(x) y(k) = e(x(k)); disp([' ',num2str(y(k)),... ' = f(x = ',... num2str(x(k)),')']) end end end
Create a DocPolynom
object p
:
p = DocPolynom([1 0 -2 -5])
p = x^3 - 2*x - 5
Evaluate the polynomial at x
equal to three
values, [3 5 9]
:
dispPoly(p,[3 5 9])
y = x^3 - 2*x - 5 16 = f(x = 3) 110 = f(x = 5) 706 = f(x = 9)
The DocPolynom
class redefines indexed reference to
support the use of objects representing polynomials. In the DocPolynom
class,
a subscripted reference to an object causes an evaluation of the polynomial
with the value of the independent variable equal to the subscript.
For example, given the following polynomial:
Create a DocPolynom
object p
:
p = DocPolynom([1 0 -2 -5])
p = x^3 - 2*x - 5
The following subscripted expression evaluates the value of
the polynomial at x = 3
and at x = 4
,
and returns the resulting values:
p([3 4])
ans = 16 51
Redefine the default subscripted reference behavior by implementing
a subsref
method.
If a class defines a subsref
method, MATLAB calls
this method for objects of this class whenever a subscripted reference
occurs. The subsref
method must define all the
indexed reference behaviors, not just a specific case that you want
to change.
The DocPolynom
subsref
method
implements the following behaviors:
p(x = [a1...an])
—
Evaluate polynomial at x = a
.
p.coef
— Access coef
property
value
p.disp
— Display the polynomial
as a MATLAB expression without assigning an output.
obj = p.method(args)
— Use
dot notation to call methods arguments and return a modified object.
obj = p.method
— Use dot
notation to call methods without arguments and return a modified object.
subsref
Implementation DetailsThe subsref
method overloads the subsref
function.
For example, consider a call to the polyval
function:
p = DocPolynom([1 0 -2 -5]) p = x^3 - 2*x - 5 polyval(p.coef,[3 5 7]) ans = 16 110 324
The polyval
function requires the:
Polynomial coefficients
Values of the independent variable at which to evaluate the polynomial
The polyval
function returns the value
of f(x)
at these values. subsref
calls polyval
through
the statements:
case '()' ind = s.subs{:}; b = polyval(a.coef,ind);
When implementing subsref
to support method
calling with arguments using dot notation, both the type
and subs
structure
fields contain multiple elements.
The subsref
method implements all subscripted
reference explicitly, as show in the following code listing.
methods function b = subsref(a,s) switch s(1).type case '()' ind = s.subs{:}; b = polyval(a.coef,ind); case '.' switch s(1).subs case 'coef' b = a.coef; case 'disp' disp(a) otherwise if length(s)>1 b = a.(s(1).subs)(s(2).subs{:}); else b = a.(s.subs); end end otherwise error('Specify value for x as obj(x)') end end end
Several arithmetic operations are meaningful on polynomials.
The DocPolynom
class implements these methods:
Method and Syntax | Operator Implemented |
---|---|
| Addition |
| Subtraction |
| Matrix multiplication |
When overloading arithmetic operators, consider the data types
you must support. The plus
, minus
,
andmtimes
methods are defined for the DocPolynom
class
to handle addition, subtraction, and multiplication on DocPolynom
— DocPolynom
and DocPolynom
— double
combinations
of operands.
+
OperatorIf either p
or q
is a DocPolynom
object,
this expression:
p + q
Generates a call to a function @DocPolynom/plus
,
unless the other object is of higher precedence.
The following method overloads the plus
(+
)
operator for the DocPolynom
class:
methods function r = plus(obj1,obj2) obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); k = length(obj2.coef) - length(obj1.coef); zp = zeros(1,k); zm = zeros(1,-k); r = DocPolynom([zp,obj1.coef] + [zm,obj2.coef]); end end
Here is how the function works:
Ensure that both input arguments are DocPolynom
objects
so that expressions such as
p + 1
that involve both a DocPolynom
and a double
,
work correctly.
Access the two coefficient vectors and, if necessary, pad one of them with zeros to make both the same length. The actual addition is simply the vector sum of the two coefficient vectors.
Call the DocPolynom
constructor to
create a properly typed object that is the result of adding the polynomials.
-
OperatorImplement the minus
operator (-
)
using the same approach as the plus
(+
)
operator.
The minus
method computes p
- q
.
The dominant argument must be a DocPolynom
object.
methods function r = minus(obj1,obj2) obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); k = length(obj2.coef) - length(obj1.coef); zp = zeros(1,k); zm = zeros(1,-k); r = DocPolynom([zp,obj1.coef] - [zm,obj2.coef]); end end
*
OperatorImplement the mtimes
method to compute the
product p*q
. The mtimes
method
implements matrix multiplication since the multiplication
of two polynomials is the convolution (conv
)
of their coefficient vectors:
methods function r = mtimes(obj1,obj2) obj1 = DocPolynom(obj1); obj2 = DocPolynom(obj2); r = DocPolynom(conv(obj1.coef,obj2.coef)); end end
Given the DocPolynom
object:
p = DocPolynom([1 0 -2 -5]);
The following two arithmetic operations call the DocPolynom
plus
and mtimes
methods:
q = p+1; r = p*q;
to produce
q = x^3 - 2*x - 4 r = x^6 - 4*x^4 - 9*x^3 + 4*x^2 + 18*x + 20