-
Notifications
You must be signed in to change notification settings - Fork 41
/
overloaded.tex
506 lines (449 loc) · 21.3 KB
/
overloaded.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
\chapter{Overloaded Operators}\label{overloaded-operators}
A Modelica \lstinline!operator record! can overload the behavior for
operations such as constructing, adding, multiplying etc.
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.
\section{Overview of overloaded operators}\label{overview-of-overloaded-operators}
In an \lstinline!operator record! the definition of operations are done using the specialized class \lstinline!operator! (a specialized class similar to \lstinline!package!, see \cref{specialized-classes}) followed by the name of the operation.
Each \lstinline!operator! class is comprised of functions implementing different variants of the operation for the \lstinline!operator record! class in which the definition resides.
% This was something weird that could be seen as a table originally,
% that is somewhat awkward - but keeping it.
%
% Changing to use itemize was attempted, but currently fails in LaTeXML
% https://github.com/brucemiller/LaTeXML/issues/1057
% (Note: It's pure coincide that this issue occured for this case.)
\begin{itemize}
\item Overloaded constructors, see \cref{overloaded-constructors}:\\ \lstinline!'constructor'!, \lstinline!'0'!
\item Overloaded string conversions, see \cref{overloaded-string-conversions}:\\ \lstinline!'String'!
\item Overloaded binary operations, see \cref{overloaded-binary-operations}:\\
\lstinline!'+'!, \lstinline!'-'! (subtraction), \lstinline!'*'!, \lstinline!'/'!, \lstinline!'^'!,\\
\lstinline!'=='!, \lstinline!'<='!', \lstinline!'>'!, \lstinline!'<'!,
\lstinline!'>='!, \lstinline!'<='!, \lstinline!'and'!, \lstinline!'or'!
\item Overloaded unary operations, see \cref{overloaded-unary-operations}:\\
\lstinline!'-'! (negation), \lstinline!'not'!
\end{itemize}
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 \lstinline!operator record! may also contain additional functions, and
declarations of components of the record. It is not legal to extend from
an \lstinline!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 \cref{interface-or-type-relationships}.
The precedence and associativity of the overloaded operators is
identical to the one defined in \cref{tab:operator-precedence} in \cref{operator-precedence-and-associativity}.
\begin{nonnormative}
Note, the operator overloading as defined in this section is
only a short hand notation for function calls.
\end{nonnormative}
\section{Matching Function}\label{matching-function}
All functions defined inside the \lstinline!operator! class must return one
output (based on the restriction above), and may include functions with
optional arguments, i.e.\ functions of the form
\begin{lstlisting}[language=modelica]
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;
\end{lstlisting}
The vector P indicates whether argument m of f has a default value (\lstinline!true! for default value, \lstinline!false! otherwise). A call
f($A_1$, $a_{2}$,\ldots{}, $a_{k}$, $b_{1}$ = $w_{1}$ ,\ldots{}, $b_{p}$ = $w_{p}$)
with distinct names $b_{j}$ is a valid match for the function f, provided (treating \lstinline!Integer! and \lstinline!Real! as the same type)
\begin{itemize}
\item
$A_{i}$ = typeOf($A_{i}$) for 1 $\le$ i $\le$ k,
\item
the names $b_{j}$ = $u_{Qj}$, Qj \textgreater{}
k, $A_{Qj}$ = typeOf($w_{i}$) for 1 $\le$ j $\le$ p, and
\item
if the union of \{i: 1 $\le$ i $\le$ k \}, \{Qj: 1 $\le$ j $\le$ p\}, and \{m:
$P_{m}$ \lstinline!true! and 1 $\le$ m $\le$ n \} is the set \{i: 1 $\le$
i $\le$ n\}.
\end{itemize}
\begin{nonnormative}
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.
\end{nonnormative}
\section{Overloaded Constructors}\label{overloaded-constructors}
Let \lstinline!C! denote an operator record class and consider an expression
\lstinline!C($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!.
\begin{enumerate}
\item\label{overloaded-constructor-unique}
If there exists a unique function $f$ in \lstinline!C.'constructor'! such that
($A_1$, $a_{2}$, \ldots{}, $a_{k}$, $b_{1}$=$w_{1}$, \ldots{}, $b_{p}$=$w_{p}$)
is a valid match for the function $f$, then
\lstinline!C($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!
is resolved to
\lstinline!C.'constructor'.$f$($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!.
\item
If there is no operator \lstinline!C.'constructor'! the automatically generated record constructor is called.
\item
Otherwise the expression is erroneous.
\end{enumerate}
Restrictions:
\begin{itemize}
\item
The operator \lstinline!C.'constructor'! shall only contain functions that declare one output component, which shall be of the operator record class \lstinline!C!.
\item
For an operator recordclass there shall not exist any potential call that lead to multiple matches in \cref{overloaded-constructor-unique} above.
\begin{nonnormative}
How to verify this is not specified.
\end{nonnormative}
\item
For a pair of operator record classes \lstinline!C! and \lstinline!D! and components \lstinline!c! and \lstinline!d! of these classes both of \lstinline!C.'constructor'(d)! and \lstinline!D.'constructor'(c)! shall not both be legal.
\begin{nonnormative}
Hence, one of the two definitions must be removed.
\end{nonnormative}
\end{itemize}
\begin{nonnormative}
By the last restriction the following problem for binary operators is avoided:
Assume there are two operator record classes \lstinline!C! and \lstinline!D! that both have a constructor from \lstinline!Real!. If we want to extend \lstinline!c + c! and \lstinline!d + d! to support mixed operations, one variant would be to define \lstinline!c + d! and \lstinline!d + c!; but then \lstinline!c + 2! becomes ambiguous (since it is not clear which instance should be converted to). Without mixed operations expressions such as \lstinline!c + d! are only ambiguous if both conversion from \lstinline!C! to \lstinline!D! and back from \lstinline!D! to \lstinline!C! are both available, and this possibility is not allowed by the restriction above.
\end{nonnormative}
Additionally there is an operator \lstinline!'0'! defining the zero-value which can also be used to construct an element. The operator \lstinline!'0'! for an operator record \lstinline!C! can
contain only one function, having zero inputs and one output of type \lstinline!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.
\section{Overloaded String Conversions}\label{overloaded-string-conversions}
Consider an expression \lstinline!String($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!,
$k \ge 1$ where $A_1$ is an element of class \lstinline!A!.
\begin{enumerate}
\item
If \lstinline!A! is a predefined type, i.e., \lstinline!Boolean!, \lstinline!Integer!, \lstinline!Real!, \lstinline!String! or
an enumeration, or a type derived from them, then the corresponding
built-in operation is performed.
\item
If \lstinline!A! is an operator record class and there exists a unique function
$f$ in \lstinline!A.'String'! such that
\lstinline!A.'String'.$f$($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!
is a valid match for $f$, then
\lstinline!String($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!
is evaluated to\\
\lstinline!A.'String'.$f$($A_1$, $a_{2}$, $\ldots$, $a_{k}$, $b_{1}$=$w_{1}$, $\ldots$, $b_{p}$=$w_{p}$)!.
\item
Otherwise the expression is erroneous.
\end{enumerate}
Restrictions:
\begin{itemize}
\item
The operator \lstinline!A.'String'! shall only contain functions that declare one
output component, which shall be of the \lstinline!String! type, and the first
input argument shall be of the operator record class \lstinline!A!.
\item
For an operator record class there shall not exist any call that lead
to multiple matches in (2) above.
\begin{nonnormative}
How to verify this is not specified.
\end{nonnormative}
\end{itemize}
\section{Overloaded Binary Operations}\label{overloaded-binary-operations}
% Can't use \mathit{op} in the \lstinline math due to issue reported here:
% https://github.com/brucemiller/LaTeXML/issues/1274 (marked as fixed as of commit 80d7940)
%\newcommand{\theop}{\mathit{op}}
\newcommand{\theop}{X}
Let $\theop$ denote a binary operator and consider an expression
\lstinline!a $\theop$ b! where \lstinline!a! is an instance or array of instances of
class \lstinline!A! and \lstinline!b! is an instance or array of instances of
class \lstinline!B!.
\begin{enumerate}
\item\label{overloaded-binary-predefined}
If \lstinline!A! and \lstinline!B! are predefined types of such, then the corresponding built-in operation is performed.
\item
Otherwise, if there exists \emph{exactly one} function $f$ in the
union of \lstinline!A.$\theop$! and \lstinline!B.$\theop$! such that
\lstinline!$f$(a, b)! is a valid match for the function $f$, then
\lstinline!a $\theop$ b! is evaluated using this function. It is an error, if
multiple functions match. If \lstinline!A! is not an operator record class, \lstinline!A.$\theop$!
is seen as the empty set, and similarly for \lstinline!B!.
\begin{nonnormative}
Having a union of the operators ensures that if \lstinline!A! and \lstinline!B! are the same, each function only appears once.
\end{nonnormative}
\item
Otherwise, consider the set given by $f$ in \lstinline!A.$\theop$!
and an operator record class \lstinline!C! (different from \lstinline!B!) with a
constructor, $g$, such that \lstinline!C.'constructor'.$g$(b)! is a valid match, and
\lstinline!f(a, C.'constructor'.$g$(b))! is a valid match; and another set given by
$f$ in \lstinline!B.$\theop$! and an operator record class \lstinline!D!
(different from \lstinline!A!) with a constructor, $h$, such that
\lstinline!D.'constructor'.$h$(a)! is a valid match and \lstinline!$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.
\begin{nonnormative}
Informally, this means: If there is no direct match of \lstinline!a $\theop$ b!, then it is tried to find a direct match by automatic type casts of \lstinline!a! or \lstinline!b!, by converting either \lstinline!a! or \lstinline!b! to the needed type using an appropriate constructor function from one of the operator record classes used as arguments of the overloaded \lstinline!op! functions. Example using the \lstinline!Complex!-definition below:
\begin{lstlisting}[language=modelica]
Real a;
Complex b;
Complex c = a * b; // interpreted as:
// Complex.'*'.multiply(Complex.'constructor'.fromReal(a),b);
\end{lstlisting}
\end{nonnormative}
\item\label{overloaded-binary-arrays}
Otherwise, if \lstinline!a! or \lstinline!b! is an array expression, then the expression is
conceptually evaluated according to the rules of \cref{scalar-vector-matrix-and-array-operator-functions} with the
following exceptions concerning \cref{matrix-and-vector-multiplication-of-numeric-arrays}:
\begin{enumerate}
\def\labelenumii{(\alph{enumii})}
\item
\lstinline!$\mathit{vector}$ * $\mathit{vector}$! should be left undefined.
\begin{nonnormative}
The scalar product of \cref{tab:product} does not generalize to the expected linear and conjugate linear scalar product of complex numbers.
\end{nonnormative}
\item
\lstinline!$\mathit{vector}$ * $\mathit{matrix}$! should be left undefined.
\begin{nonnormative}
The corresponding definition of \cref{tab:product} does not generalize to complex numbers in the expected way.
\end{nonnormative}
\item
If the inner dimension for \lstinline!$\mathit{matrix}$ * $\mathit{vector}$! or \lstinline!$\mathit{matrix}$ * $\mathit{matrix}$! is zero, this uses the overloaded \lstinline!'0'! operator of the result array element type. If the operator \lstinline!'0'! is not defined for that class it is an error if the inner dimension is zero.
\end{enumerate}
\begin{nonnormative}
For array multiplication it is assumed that the scalar elements
form a non-commutative ring that does not necessarily have a
multiplicative identity.
\end{nonnormative}
\item\label{overloaded-binary-error}
Otherwise the expression is erroneous.
\end{enumerate}
For an element-wise operator, \lstinline!a .op b!, items~\ref{overloaded-binary-predefined}, \ref{overloaded-binary-arrays}, and~\ref{overloaded-binary-error} are used; e.g.\ the operator \lstinline!.+! will always be defined in terms of \lstinline!'+'!.
Restrictions:
\begin{itemize}
\item
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.
\item
For an operator record class there shall not exist any
(potential) call that lead to multiple matches in (2) above.
\end{itemize}
\section{Overloaded Unary Operations}\label{overloaded-unary-operations}
Let $\theop$ denote a unary operator and consider an expression
\lstinline!$\theop$ a! where \lstinline!a! is an instance or array of instances of class
\lstinline!A!. Then \lstinline!$\theop$ a! is evaluated in the following way.
\begin{enumerate}
\item
If \lstinline!A! is a predefined type, then the corresponding built-in
operation is performed.
\item
If \lstinline!A! is an operator record class and there exists a unique
function $f$ in \lstinline!A.$\theop$! such that \lstinline!A.$\theop$.$f$(a)! is a valid
match, then \lstinline!$\theop$ a! is evaluated to \lstinline!A.$\theop$.$f$(a)!. It is an
error, if there are multiple valid matches.
\item
Otherwise, if \lstinline!a! is an array expression, then the expression
is conceptually evaluated according to the rules of \cref{scalar-vector-matrix-and-array-operator-functions}.
\item
Otherwise the expression is erroneous.
\end{enumerate}
Restrictions:
\begin{itemize}
\item
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.
\item
For an operator record class there shall not exist any
(potential) call that lead to multiple matches in (2) above.
\item
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 \lstinline!'-'! it is the union of these sets, since it may define both a unary
(negation) and binary (subtraction) operator.
\end{itemize}
\section{Example of Overloading for Complex Numbers}\label{example-of-overloading-for-complex-numbers}
\begin{example}
The rules in the previous subsections are demonstrated at hand
of a record class to work conveniently with complex numbers:
\begin{lstlisting}[language=modelica,escapechar=!]
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 !\cref{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}
\end{lstlisting}
How overloaded operators can be symbolically processed. Example:
\begin{lstlisting}[language=modelica]
Real a;
Complex b;
Complex c = a + b;
\end{lstlisting}
Due to inlining of functions, the equation for \lstinline!c! is
transformed to:
\begin{lstlisting}[language=modelica]
c = Complex.'+'.add(Complex.'constructor'.fromReal(a), b);
= Complex.'+'.add(Complex(re=a,im=0), b)
= Complex(re=a+b.re, im=b.im);
\end{lstlisting}
or
\begin{lstlisting}[language=modelica]
c.re = a + b.re;
c.im = b.im;
\end{lstlisting}
These equations can be symbolically processed as other equations.
Complex can be used in a connector:
\begin{lstlisting}[language=modelica]
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);
\end{lstlisting}
The two connect-equations result in the following connection equations:
\begin{lstlisting}[language=modelica]
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'();
\end{lstlisting}
The restrictions on extends are intended to avoid combining two variants inheriting from the same operator record, but with possibly different operations; thus \lstinline!ComplexVoltage! and \lstinline!ComplexCurrent! still use the operations from \lstinline!Complex!. The restriction that it is not legal to extend from any of its enclosing scopes implies that:
\begin{lstlisting}[language=modelica]
package A
extends Icon; // Ok
operator record B $\ldots$ end B;
end A;
package A2
extends A($\ldots$); // Not legal
end A2;
package A3 = A($\ldots$); // Not legal
\end{lstlisting}
\end{example}