Overloaded Operators
====================

.. raw:: latex

   \doublelabel{overloaded-operators}

A Modelica **operator record** can define the behavior for operations
such as constructing, adding, multiplying etc. This is done using the
specialized class **operator** (a restricted class similar to
**package**, see ) comprised of functions implementing different
variants of the operation for the record class in which the respective
**operator** definition resides. [\ *The overloading is defined in such
a way that ambiguities are not allowed and give an error. Furthermore,
it is sufficient to define overloading for scalars. Overloaded array
operations are automatically deduced from the overloaded scalar
operations.*\ ] The **operator** keyword is followed by the name of the
operation:

+-----------------------------------+-----------------------------------+
|                                   |                                   |
+-----------------------------------+-----------------------------------+
|                                   | ``'constructor'``, ``'0'``        |
+-----------------------------------+-----------------------------------+
|                                   |                                   |
+-----------------------------------+-----------------------------------+
|                                   | ``'String'``                      |
+-----------------------------------+-----------------------------------+
|                                   |                                   |
+-----------------------------------+-----------------------------------+
|                                   | ``'+'``, ``'-'`` (subtraction),   |
|                                   | ``'*'``, ``'/'``, ``'^'``,        |
+-----------------------------------+-----------------------------------+
|                                   | ``'=='``, ``'<='``\ ’, ``'>'``,   |
|                                   | ``'<'``, ``'>='``, ``'<='``,      |
|                                   | ``'and'``, ``'or'``               |
+-----------------------------------+-----------------------------------+
|                                   |                                   |
+-----------------------------------+-----------------------------------+
|                                   | ``'-'`` (negation), ``'not'``     |
+-----------------------------------+-----------------------------------+

The functions defined in the operator-class must take at least one
component of the record class as input, except for the
constructor-functions which instead must return one component of the
record class. All of the functions shall return exactly one output.

The functions can be either called as defined in this section, or they
can be called directly using the hierarchical name. The operator or
operator function must be encapsulated; this allows direct calls of the
functions and prohibits the functions from using the elements of
operator record class.

The operator record may also contain additional functions, and
declarations of components of the record. It is not legal to extend from
an operator record, except as a short class definition modifying the
default attributes for the component elements directly inside the
operator record.

If an operator record was derived by a short class definition, the
overloaded operators of this operator record are the operators that are
defined in its base class, for subtyping see .

The precedence and associativity of the overloaded operators is
identical to the one defined in Table 3.1 in .

[\ *Note, the operator overloading as defined in this section is only a
short hand notation for function calls.*\ ]

Matching Function
-----------------

.. raw:: latex

   \doublelabel{matching-function}

All functions defined inside the **operator** class must return one
output (based on the restriction above), and may include functions with
optional arguments, i.e. functions of the form

::

   function f
     input $A_1$ $u_1$;
     ...
     input $A_{m}$ $u_{m}$ := $A_{m}$;
     ...
     input $A_{n}$ $u_{n}$;
     output B y;
   algorithm
     ...
   end f;

The vector P indicates whether argument m of f has a default value
(**true** for default value, **false** otherwise). A call
f(\ :math:`A_1`, :math:`a_{2}`,…, :math:`a_{k}`, :math:`b_{1}` =
:math:`w_{1}` ,…, :math:`b_{p}`\ = :math:`w_{p}`) with distinct names
:math:`b_{j}` is a valid match for the function f, provided (treating
Integer and Real as the same type)

-  :math:`A_{i}` = typeOf(\ :math:`A_{i}`) for 1 :math:`\le` i
   :math:`\le` k,

-  the names :math:`b_{j}` = :math:`u_{Qj}`, Qj > k, :math:`A_{Qj}`
   =typeOf(\ :math:`w_{i}`) for 1 :math:`\le` j :math:`\le` p, and

-  if the union of {i: 1 :math:`\le` i :math:`\le` k }, {Qj: 1
   :math:`\le` j :math:`\le` p}, and {m: :math:`P_{m}` **true** and 1
   :math:`\le` m :math:`\le` n } is the set {i: 1 :math:`\le` i
   :math:`\le` n}.

[\ *This corresponds to the normal treatment of function calls with
named arguments, requiring that all inputs have some value given by a
positional argument, named argument, or a default value (and that
positional and named arguments do not overlap). Note, that this only
defines a valid call, but does not explicitly define the set of
domains.*\ ]

Overloaded Constructors
-----------------------

.. raw:: latex

   \doublelabel{overloaded-constructors}

Let C denote an operator record class and consider an expression
C(\ :math:`A_1`, :math:`a_{2}`,…, :math:`a_{k}`, :math:`b_{1}`\ =
:math:`w_{1}` ,…, :math:`b_{p}`\ = :math:`w_{p}`).

#. | If there exists a unique function f in C.’constructor’ such that
     (:math:`A_1`, :math:`a_{2}`,…, :math:`a_{k}`, :math:`b_{1}`\ =
     :math:`w_{1}` ,…, :math:`b_{p}`\ = :math:`w_{p}`) is a valid match
     for the function f, then C(\ :math:`A_1`, :math:`a_{2}`,…,
     :math:`a_{k}`, :math:`b_{1}`\ = :math:`w_{1}` ,…, :math:`b_{p}`\ =
     :math:`w_{p}`) is resolved to
   | C.’constructor’.f(\ :math:`A_1`, :math:`a_{2}`,…, :math:`a_{k}`,
     :math:`b_{1}`\ = :math:`w_{1}` ,…, :math:`b_{p}`\ = :math:`w_{p}`).

#. If there is no operator C. ’constructor’ the automatically generated
   record constructor is called.

#. Otherwise the expression is erroneous.

Restrictions:

-  The operator C.’constructor’ shall only contain functions that
   declare one output component, which shall be of the operator record
   class C.

-  For an operator recordclass there shall not exist any potential call
   that lead to multiple matches in (1) above. [\ *How to verify this is
   not specified.*\ ]

-  For a pair of operator record classes C and D and components c and d
   of these classes both of C.’constructor’ (d) and D.’constructor’ (c)
   shall not both be legal [\ *, so one of the two definitions must be
   removed*\ ]\ *.*

[\ *By the last restriction the following problem for binary operators
is avoided:*

*Assume there are two operator record classes C and D that both have a
constructor from Real. If we want to extend c+c and d+d to support mixed
operations, one variant would be to define c+d and d+c; but then c+2
becomes ambiguous (since it is not clear which instance should be
converted to). Without mixed operations expressions such as c+d are only
ambiguous if both conversion from C to D and back from D to C are both
available, and this possibility is not allowed by the restriction
above.*\ ]

Additionally there is an operator ‘0’ defining the zero-value which can
also be used to construct an element. The operator ‘0’ for an operator
record C can contain only one function, having zero inputs and one
output – of class C (the called function is therefore unambiguous). It
should return the identity element of addition, and is used for
generating flow-equations for connect-equations and zero elements for
matrix-multiplication.

Overloaded String Conversions
-----------------------------

.. raw:: latex

   \doublelabel{overloaded-string-conversions}

Consider an expression String(\ :math:`A_1`, :math:`a_{2}`,…,
:math:`a_{k}`, :math:`b_{1}`\ = :math:`w_{1}` ,…, :math:`b_{p}`\ =
:math:`w_{p}`), :math:`k\ge 1` where :math:`A_1` is an element of class
A.

#. If A is a predefined , i.e., Boolean, Integer, Real, String or an
   enumeration, or a type derived from them, then the corresponding
   built-in operation is performed.

#. | If A is an operator and there exists a unique function f in
     A.’String’ such that (:math:`A_1`, :math:`a_{2}`,…, :math:`a_{k}`,
     :math:`b_{1}`\ = :math:`w_{1}` ,…, :math:`b_{p}`\ = :math:`w_{p}`)
     is a valid match for f, then String(\ :math:`A_1`, :math:`a_{2}`,…,
     :math:`a_{k}`, :math:`b_{1}`\ = :math:`w_{1}` ,…, :math:`b_{p}`\ =
     :math:`w_{p}`) is evaluated to
   | A.’String’.f(\ :math:`A_1`, :math:`a_{2}`,…, :math:`a_{k}`,
     :math:`b_{1}`\ = :math:`w_{1}` ,…, :math:`b_{p}`\ = :math:`w_{p}`).

#. Otherwise the expression is erroneous.

Restrictions:

-  The operator A.’String’ shall only contain functions that declare one
   output component, which shall be of the String type, and the first
   input argument shall be of the operator record class A.

-  For an operator record class there shall not exist any call that lead
   to multiple matches in (2) above. [\ *How to verify this is not
   specified.*\ ]

Overloaded Binary Operations
----------------------------

.. raw:: latex

   \doublelabel{overloaded-binary-operations}

Let *op* denote a binary operator and consider an expression *a op b*
where *a* is an instance or array of instances of class *A* and *b* is
an instance or array of instances of class *B*.

#. If *A* and *B* are predefined types of such, then the corresponding
   built-in operation is performed.

#. Otherwise, if there exists function *f* in the union of *A*.\ *op*
   and *B.op* such that f(\ *a*,\ *b*) is a valid match for the function
   *f* , then *a op b* is evaluated using this function. It is an error,
   if multiple functions match. If A is not an operator record class,
   A.op is seen as the empty set, and similarly for B. [\ *Having a
   union of the operators ensures that if A and B are the same, each
   function only appears once.*\ ]

#. Otherwise, consider the set given by *f* in *A*.\ *op* and an
   operator record class *C* (different from B) with a constructor, g,
   such that C.’constructor’.g(b) is a valid match, and f(a,
   C.’constructor’.g(b)) is a valid match; and another set given by *f*
   in *B*.\ *op* and an operator record class *D* (different from A)
   with a constructor, h, such that D.’constructor’.h(a) is a valid
   match and f(D.’constructor’.h(a), b) is a valid match. If the sum of
   the sizes of these sets is one this gives the unique match. If the
   sum of the sizes is larger than one it is an error.

   [\ *Informally, this means: If there is no direct match of “a op b”,
   then it is tried to find a direct match by automatic type casts of
   “a” or “b”, by converting either “a” or “b” to the needed type using
   an appropriate constructor function from one of the operator record
   classes used as arguments of the overloaded “op” functions. Example
   using the Complex-definition below:*

   ::

         Real a;
        Complex b;
        Complex c = a*b; // interpreted as:
        // Complex.'*'.multiply(Complex.'constructor'.fromReal(a),b);

   ]

#. Otherwise, if a or b is an , then the expression is conceptually
   evaluated according to the rules of with the following exceptions
   concerning :

   #. vector*vector should be left undefined [\ *as the scalar product
      of does not generalize to the expected linear and conjugate linear
      scalar product of complex numbers*\ ]\ *.*

   #. vector*matrix should be left undefined [\ *as the corresponding
      definition of does not generalize to complex numbers in the
      expected way*\ ].

   #. If the inner dimension for matrix*vector or matrix*matrix is zero,
      this uses the overloaded ’0’ operator of the result array element
      type. If the operator ’0’ is not defined for that class it is an
      error if the inner dimension is zero.

   [\ *For array multiplication it is assumed that the scalar elements
   form a non-commutative ring that does not necessarily have a
   multiplicative identity.*\ ]

#. Otherwise the expression is erroneous.

For an element-wise operator, a .op b, items 1, 4, and 5 are used; e.g.
the operator .+ will always be defined in terms of ’+’.

Restrictions:

-  A function is allowed for a binary operator if and only if it has at
   least two inputs; at least one of which is of the operator record
   class, and the first two inputs shall not have default values, and
   all inputs after the first two must have default values.

-  For an operator record class there shall not exist any
   [\ *potential*\ ] call that lead to multiple matches in (2)
   above\ *.*

Overloaded Unary Operations
---------------------------

.. raw:: latex

   \doublelabel{overloaded-unary-operations}

Let *op* denote a unary operator and consider an expression *op a* where
*a* is an instance or array of instances of class *A*. Then *op a* is
evaluated in the following way.

#. If *A* is a , then the corresponding built-in operation is performed.

#. If *A* is an and there exists a unique function *f* in *A.op* such
   that *A.op.f(a)* is a valid match, then *op a* is evaluated to
   *A.op.f(a)*. It is an error, if there are multiple valid matches.

#. Otherwise, if *a* is an , then the expression is conceptually
   evaluated according to the rules of .

#. Otherwise the expression is erroneous.

Restrictions:

-  A function is allowed for a unary operator if and only if it has
   least one input; and the first input is of the record type (or
   suitable arrays of such) and does not have a default value, and all
   inputs after the first one must have default values.

-  For an operator record class there shall not exist *potential*\ ]
   call that lead to multiple matches in (2) above.

-  A binary and/or unary operator-class may only contain functions that
   are allowed for this binary and/or unary operator-class; and in case
   of ‘-‘ it is the union of these sets, since it may define both a
   unary (negation) and binary (subtraction) operator.

Example of Overloading for Complex Numbers
------------------------------------------

.. raw:: latex

   \doublelabel{example-of-overloading-for-complex-numbers}

[\ *The rules in the previous subsections are demonstrated at hand of a
record class to work conveniently with complex numbers:*

::

   operator record Complex "Record defining a Complex number"
     Real re "Real part of complex number";
     Real im "Imaginary part of complex number";
     encapsulated operator 'constructor'
       import Complex;
       function fromReal
         input Real re;
         input Real im := 0;
         output Complex result(re=re, im=im);
       algorithm
         annotation(Inline=true);
       end fromReal;
     end 'constructor';

     encapsulated operator function '+' // short hand notation, see !\autoref{specialized-classes}!
       import Complex;
       input Complex c1;
       input Complex c2;
       output Complex result "= c1 + c2";
     algorithm 
       result := Complex(c1.re + c2.re, c1.im + c2.im);
      annotation(Inline=true);
     end '+';

     encapsulated operator '-'
       import Complex;
       function negate
         input Complex c;
         output Complex result "= - c";
       algorithm 
         result := Complex(-c.re, -c.im);
         annotation(Inline=true);
       end negate;

       function subtract
         input Complex c1;
         input Complex c2;
         output Complex result "= c1 -- c2";
       algorithm 
         result := Complex(c1.re - c2.re, c1.im - c2.im);
         annotation(Inline=true);
       end subtract;
     end '-';

     encapsulated operator function '*'
       import Complex;
       input Complex c1;
       input Complex c2;
       output Complex result "= c1 * c2";
     algorithm 
       result := Complex(c1.re*c2.re - c1.im*c2.im, c1.re*c2.im + c1.im*c2.re);
       annotation(Inline=true);
     end '*';

     encapsulated operator function '/'
       import Complex; input Complex c1;
       input Complex c2;
       output Complex result "= c1 / c2";
     algorithm 
       result := Complex(( c1.re*c2.re + c1.im*c2.im)/(c2.re^2 +
       c2.im^2),
       (-c1.re*c2.im + c1.im*c2.re)/(c2.re^2 + c2.im^2));
      annotation(Inline=true);
     end '/';

     encapsulated operator function '=='
       import Complex;
       input Complex c1;
       input Complex c2;
       output Boolean result "= c1 == c2";
     algorithm 
       result := c1.re == c2.re and c1.im == c2.im;
      annotation(Inline=true);
    end '==';

     encapsulated operator function 'String'
       import Complex;
       input Complex c;
       input String name := "j" "Name of variable representing sqrt(-1) in the string";
       input Integer significantDigits=6 "Number of significant digits to be shown";
       output String s;
     algorithm 
       s := String(c.re, significantDigits=significantDigits);
       if c.im <> 0 then
         s := if  c.im > 0 then s + " + "
      else s + " - ";
         s := s + String(abs(c.im), significantDigits=significantDigits) + name;
      end if;
     end 'String';

     encapsulated function j
       import Complex;
       output Complex c;
     algorithm 
       c := Complex(0,1);
       annotation(Inline=true);
     end j;

     encapsulated operator function '0'
       import Complex;
       output Complex c;
     algorithm 
       c := Complex(0,0);
       annotation(Inline=true);
     end '0';
   end Complex;

   function eigenValues
     input Real A [:,:];
     output Complex ev[size(A, 1)];
     protected 
     Integer nx=size(A, 1);
     Real eval[nx,2];
     Integer i;
   algorithm 
     eval := Modelica.Math.Matrices.eigenValues(A);
     for i in 1:nx loop
       ev[i] := Complex(eval[i, 1], eval[i, 2]);
     end for;
   end eigenValues;

   // Usage of Complex number above:
     Complex j = Complex.j();
     Complex c1 = 2 + 3*j;
     Complex c2 = 3 + 4*j;
     Complex c3 = c1 + c2;
     Complex c4[:] = eigenValues([1,2; -3,4]);
   algorithm
     Modelica.Utilities.Streams.print("c4 = " + String(c4));
     // results in output:
     // c4 = {2.5 + 1.93649j, 2.5 - 1.93649j}

*How overloaded operators can be symbolically processed. Example:*

::

     Real a;
     Complex b;
     Complex c = a + b;

*Due to inlining of functions, the equation for “c” is transformed to:*

::

   c = Complex.'+'.add(Complex.'constructor'.fromReal(a), b);
     = Complex.'+'.add(Complex(re=a,im=0), b)
     = Complex(re=a+b.re, im=b.im);

*or*

::

     c.re = a + b.re;
     c.im = b.im;

*These equations can be symbolically processed as other equations.*

*Complex can be used in a connector:*

::

     operator record ComplexVoltage = Complex(re(unit="V"),im(unit="V"));
     operator record ComplexCurrent = Complex(re(unit="A"),im(unit="A"));

     connector ComplexPin
       ComplexVoltage v;
       flow ComplexCurrent i;
     end ComplexPin;
     
     ComplexPin p1,p2,p3;
   equation
     connect(p1,p2);
     connect(p1,p3);

*The two connect equations result in the following connection
equations:*

::

     p1.v = p2.v;
     p1.v = p3.v;
     p1.i + p2.i + p3.i = Complex.'0'();
     // Complex.'+'(p1.i, Complex.'+'(p2.i, p3.i)) = Complex.'0'();

*The restrictions on extends are intended to avoid combining two
variants inheriting from the same operator record, but with possibly
different operations; thus ComplexVoltage and ComplexCurrent still use
the operations from Complex. The restriction that it is not legal to
extend from any of its enclosing scopes implies that:*

::

   package A
     extends Icon; //Ok.
     operator record B ... end B;
     end A;

     package A2
       extends A(...); // Not legal
     end A2;
     package A3=A(...); // Not legal

]