Representing Polynomials with Classes - MATLAB & Simulink (original) (raw)

You can use classes to define new data types. This example implements a class that represents polynomials. The class stores the coefficients of the polynomial terms in a vector and overrides the default MATLAB® display to show the polynomials as powers of x. Using customized indexing, the class also enables you to evaluate the polynomials at one or more values of x using parentheses indexing syntax.

Class Requirements

The design requirements for the DocPolynom class are:

DocPolynom Class Members

The class defines the property coef for storage of the polynomial coefficients.

DocPolynom Class Properties

Name Class Default Description
coef double [] Vector of polynomial coefficients, in order of the highest exponent of x to lowest.

This table summarizes the methods for the DocPolynom class.

DocPolynom Class Methods

Name Description
DocPolynom Class constructor
double Converts the DocPolynom object to a double. In other words, this method returns the coefficients in a vector ofdouble values.
char Creates a formatted display of theDocPolynom object as powers of_x_. This method is used by thedisp method.
disp Defines how MATLAB displays DocPolynom objects on the command line.
plus Adds DocPolynom objects.
minus Subtracts DocPolynom objects.
mtimes Multiplies DocPolynom objects.
dispPoly Evaluates the polynomial for one or more values and returns the results in an organized list instead of a vector ofdouble values.
parenReference Enables evaluation of a polynomial using parentheses indexing syntax. p(x) evaluates the polynomial objectp at each value inx.

Using the DocPolynom Class

These examples show the basic use of the DocPolynom class. Create DocPolynom objects to represent f(x) =x_3 − 2_x − 5 and f(x) = 2_x_4 + 3_x_2 + 2_x_ − 7.

p1 = DocPolynom([1 0 -2 -5])

p2 = DocPolynom([2 0 3 2 -7])

p2 = 2x^4 + 3x^2 + 2*x - 7

Find the roots of the polynomial p1. Use thedouble method of the object and pass the result to the roots function.

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 theDocPolynom class when you add two DocPolynom objects.

ans =

2x^4 + x^3 + 3x^2 - 12

DocPolynom Class Synopsis

Class Code Description
classdef DocPolynom < matlab.mixin.Scalar Value class that implements a data type for polynomials. The class inherits from matlab.mixin.Scalar, which enforces scalar class behavior and also provides functionality to customize parentheses indexing. For more information on the superclass, see matlab.mixin.Scalar.
properties coef end Vector of polynomial coefficients.
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 that creates objects using either:An existing DocPolynom objectA vector of doublesFor more information, see The DocPolynom Constructor.
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; else obj.coef = val(ind(1):end); end end Set method for coef property:Restricts coefficients to type doubleRemoves leading zeros from the coefficient vectorFor more information, see Remove Leading Zeros.
function c = double(obj) c = obj.coef; end Convert DocPolynom object todouble by returning the coefficients.For more information, see Convert DocPolynom Objects to Other Classes.
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
function disp(obj) c = char(obj); if iscell(c) disp([' ' c{:}]) else disp(c) end end Overload disp function. This method displays objects as output of the char method.For more information, see Overload disp for DocPolynom.
function dispPoly(obj,x) p = char(obj); y = zeros(length(x)); disp(['f(x) = ',p]) for k = 1:length(x) y(k) = polyval(obj.coef,x(k)); disp([' f(',num2str(x(k)),') = ',num2str(y(k))]) end end Return evaluated polynomial with formatted output. This method uses polyval in a loop to evaluate the polynomial at specified values of the independent variable.For more information, see Display Evaluated Expression.
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:Polynomial additionPolynomial subtractionPolynomial multiplicationFor information about this code, see Define Arithmetic Operators.For general information about defining operators, seeOperator Overloading.
methods (Access = protected) function f = parenReference(obj,indexOp) n = cell2mat(indexOp(1).Indices); if numel(indexOp) == 1 f = polyval(obj.coef,n); else f = polyval(obj.coef,n).(indexOp(2:end)); end end end end Customize parentheses reference for DocPolynom objects. This implementation of parenReference enables users to evaluate a polynomial using parentheses indexing syntax.p(x) evaluates the polynomial represented by objectp for each value inx.For more information, see Redefine Parentheses Indexing.

Expand for Class Code

classdef DocPolynom < matlab.mixin.Scalar

properties coef end

methods function obj = DocPolynom(c) if nargin > 0 if isa(c,'DocPolynom') obj.coef = c.coef; else obj.coef = c(:).'; end end end

  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;
     else
        obj.coef = val(ind(1):end);
     end
  end
  
  function c = double(obj)
     c = obj.coef;
  end
  
  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
  
  function disp(obj)
     c = char(obj);
     if iscell(c)
        disp(['     ' c{:}])
     else
        disp(c)
     end
  end
  
  function dispPoly(obj,x)
     p = char(obj);
     y = zeros(length(x));
     disp(['f(x) = ',p])
     for k = 1:length(x)
        y(k) = polyval(obj.coef,x(k));
        disp(['   f(',num2str(x(k)),') = ',num2str(y(k))])
     end
  end
  
  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

methods (Access = protected) function f = parenReference(obj,indexOp) n = cell2mat(indexOp(1).Indices); if numel(indexOp) == 1 f = polyval(obj.coef,n); else f = polyval(obj.coef,n).(indexOp(2:end)); end end end end

The DocPolynom Constructor

This is the DocPolynom class constructor:

function obj = DocPolynom(c) if nargin > 0 if isa(c,'DocPolynom') obj.coef = c.coef; else obj.coef = c(:).'; end end end

Constructor Calling Syntax

The DocPolynom constructor can accept two different input arguments:

This example uses a vector as the input argument to theDocPolynom constructor:

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. 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.

Remove Leading Zeros

The DocPolynom class represents polynomials as row vectors containing coefficients ordered by descending powers. Zeros in the coefficient vector represent terms that are not in the polynomial. Leading zeros, therefore, can be ignored when forming the polynomial. In fact, some DocPolynom class methods use the length of the coefficient vector to determine the degree of the polynomials, so removing leading zeros from the coefficient vector ensures that the vector length represents the correct polynomial degree.

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.

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; else obj.coef = val(ind(1):end); end end

Convert DocPolynom Objects to Other Classes

The DocPolynom class defines two methods to convertDocPolynom objects to other classes:

The Double Converter

The double converter method for the DocPolynom class returns the coefficient vector:

function c = double(obj) c = obj.coef; end

For the DocPolynom object p,double returns a vector of class double.

p = DocPolynom([1 0 -2 -5]); c = double(p)

The Character Converter

The char method returns a char vector that represents the polynomial displayed as powers of x. Thechar vector returned is a syntactically correct MATLAB expression.

The char method uses a cell array to collect thechar vector components that make up the displayed polynomial. The disp method uses the char method to format the DocPolynom object for display. Users ofDocPolynom objects are not likely to call thechar or disp methods directly, but these methods enable the DocPolynom class to behave like other data classes in MATLAB.

Overload disp for DocPolynom

To provide a more useful display of DocPolynom objects, this class overloads disp in the class definition. Thisdisp method relies on the char method to produce a text representation of the polynomial, which it then displays.

The char method returns a cell array or the character'0' if the coefficients are all zero.

function disp(obj) c = char(obj); if iscell(c) disp([' ' c{:}]) else disp(c) end end

When MATLAB Calls the disp Method

This statement creates a DocPolynom object. Because the statement is not terminated with a semicolon, the resulting output is displayed on the command line using the overloaded disp method.

p = DocPolynom([1 0 -2 -5])

Display Evaluated Expression

The dispPoly method evaluates the polynomial for one or more values of x. The method loops through the input values ofx and uses the polyval function with thecoef property to evaluate the polynomial.

function dispPoly(obj,x) p = char(obj); y = zeros(length(x)); disp(['f(x) = ',p,]) for k = 1:length(x) y(k) = polyval(obj.coef,x(k)); disp([' f(',num2str(x(k)),') = ',num2str(y(k))]) end end

Create a DocPolynom object p:

p = DocPolynom([1 0 -2 -5])

Evaluate the polynomial at three values of x, [3 5 9]. Instead of returning a vector of values, the method uses function notation to present the results in an organized list.

f(x) = x^3 - 2*x - 5 f(3) = 16 f(5) = 110 f(9) = 706

Define Arithmetic Operators

The DocPolynom class implements methods for three arithmetic operations.

Method and Syntax Operation
plus(a,b) Addition
minus(a,b) Subtraction
mtimes(a,b) Matrix multiplication

The overloaded plus, minus, andmtimes methods accept argument pairs that include at least oneDocPolynom object.

Define the + Operator

If either p or q is aDocPolynom object, this expression generates a call to theplus method overload defined by DocPolynom unless the other object is of higher precedence.

This method overloads the plus (+) operator for the DocPolynom class.

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

The plus method performs these actions:

Define the - Operator

The minus operator (-) uses the same approach as the plus (+) operator. Theminus method computes p -q. The dominant argument must be aDocPolynom object.

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

Define the * Operator

The mtimes method computes the product p*q. The mtimes method implements matrix multiplication because 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

Using the Arithmetic Operators

Create a DocPolynom object.

p = DocPolynom([1 0 -2 -5]);

These two arithmetic operations call the DocPolynom plus and mtimes methods.

q = x^3 - 2*x - 4

r = x^6 - 4x^4 - 9x^3 + 4x^2 + 18x + 20

Redefine Parentheses Indexing

The DocPolynom class inherits from matlab.mixin.Scalar, which in turn inherits from the modular indexing classmatlab.mixin.indexing.RedefinesParen. Overloading theparenReference method of RedefinesParen enables users to evaluate a polynomial represented by a DocPolynom object using parentheses indexing syntax.

For example, create a DocPolynom objectp.

p = DocPolynom([1 0 -2 -5])

The overloaded parenReference method evaluates the value of the polynomial at x = 3 and at x = 4 using this command.

Modular Indexing Implementation Details

The parenReference method handles expressions of the formp(x), where p is aDocPolynom object and x contains numeric inputs. Instead of a traditional MATLAB indexing operation, however, parenReference usespolyval to evaluate the polynomial using the coefficients stored in the coef property.

methods (Access = protected) function f = parenReference(obj,indexOp) n = cell2mat(indexOp(1).Indices); if numel(indexOp) == 1 f = polyval(obj.coef,n); else f = polyval(obj.coef,n).(indexOp(2:end)); end end end

The method performs these steps:

  1. Extract the indexing values from indexOp, which is an instance of the matlab.indexing.IndexingOperation class. TheindexOp object stores them as a cell array, and the method converts them to a numeric array and stores them inn.
  2. Calculate the number of indexing operations in the expression.
  3. Evaluate the polynomial at the values in n. The intended use of this syntax includes one parentheses indexing operation.
  4. If the method finds more than one indexing operation, it usespolyval to evaluate the polynomial and then forwards the rest of the indexing operations to MATLAB using the forwarding syntax,.(indexOp(2:end)). The class does not support any additional customized indexing operations, so MATLAB returns an error.
    For example, attempting to evaluate a polynomial object while also using dot indexing to try to access its coef property at the same time errors.
    Dot indexing is not supported for variables of this type.
    For more information on forwarding operations with modular indexing, see Forward Indexing Operations.

Using the modular indexing class in this way means that only parentheses reference operations are customized. Dot access to properties and methods are unaffected and are handled by MATLAB as expected.