This library provides functions operating on vectors of Complex numbers.
Extends from Modelica.Icons.Package (Icon for standard packages).
| Name | Description |
|---|---|
| Returns the p-norm of a complex vector | |
| Return length of a complex vector | |
| Return normalized complex vector such that length = 1 and prevent zero-division for zero vector | |
| Reverse vector elements (e.g., v[1] becomes last element) | |
| Sort elements of complex vector |
Vectors.norm(v); Vectors.norm(v,p=2); // 1 ≤ p ≤ ∞
The function call "Vectors.norm(v)" returns the
Euclidean norm "sqrt(v*v)" of vector v.
With the optional
second argument "p", any other p-norm can be computed:
Besides the Euclidean norm (p=2), also the 1-norm and the infinity-norm are sometimes used:
| 1-norm | = sum(abs(v)) | norm(v,1) |
| 2-norm | = sqrt(v*v) | norm(v) or norm(v,2) |
| infinity-norm | = max(abs(v)) | norm(v,Modelica.Constants.inf) |
Note, for any vector norm the following inequality holds:
norm(v1+v2,p) ≤ norm(v1,p) + norm(v2,p)
v = {2, -4, -2, -1};
norm(v,1); // = 9
norm(v,2); // = 5
norm(v); // = 5
norm(v,10.5); // = 4.00052597412635
norm(v,Modelica.Constants.inf); // = 4
| Type | Name | Default | Description |
|---|---|---|---|
| Complex | v[:] | Vector | |
| Real | p | 2 | Type of p-norm (often used: 1, 2, or Modelica.Constants.inf) |
| Type | Name | Description |
|---|---|---|
| Real | result | p-norm of vector v |
function norm "Returns the p-norm of a complex vector"
input Complex v[:] "Vector";
input Real p(min=1) = 2
"Type of p-norm (often used: 1, 2, or Modelica.Constants.inf)";
output Real result "p-norm of vector v";
algorithm
if p == 2 then
result:= sqrt(sum(v[i].re^2 + v[i].im^2 for i in 1:size(v,1)));
elseif p == Modelica.Constants.inf then
result:= ComplexMath.'abs'(ComplexMath.'max'(v));
elseif p == 1 then
result:= sum(ComplexMath.'abs'(v[i]) for i in 1:size(v,1));
else
result:=(sum(ComplexMath.'abs'(v[i])^p for i in 1:size(v, 1)))^(1/p);
end if;
end norm;
Vectors.length(v);
The function call "Vectors.length(v)" returns the
Euclidean length "sqrt(v*v)" of vector v.
The function call is equivalent to Vectors.norm(v). The advantage of
length(v) over norm(v)"is that function length(..) is implemented
in one statement and therefore the function is usually automatically
inlined. Further symbolic processing is therefore possible, which is
not the case with function norm(..).
v = {2, -4, -2, -1};
length(v); // = 5
| Type | Name | Default | Description |
|---|---|---|---|
| Complex | v[:] | Vector |
| Type | Name | Description |
|---|---|---|
| Real | result | Length of vector v |
function length "Return length of a complex vector"
input Complex v[:] "Vector";
output Real result "Length of vector v";
algorithm
result := sqrt(sum({v[i].re^2 + v[i].im^2 for i in 1:size(v,1)}));
end length;
Vectors.normalize(v); Vectors.normalize(v,eps=100*Modelica.Constants.eps);
The function call "Vectors.normalize(v)" returns the
unit vector "v/length(v)" of vector v.
If length(v) is close to zero (more precisely, if length(v) < eps),
v is returned in order to avoid
a division by zero. For many applications this is useful, because
often the unit vector e = v/length(v) is used to compute
a vector x*e, where the scalar x is in the order of length(v),
i.e., x*e is small, when length(v) is small and then
it is fine to replace e by v to avoid a division by zero.
Since the function is implemented in one statement, it is usually inlined and therefore symbolic processing is possible.
normalize({1,2,3}); // = {0.267, 0.534, 0.802}
normalize({0,0,0}); // = {0,0,0}
| Type | Name | Default | Description |
|---|---|---|---|
| Complex | v[:] | Vector | |
| Real | eps | 100*Modelica.Constants.eps | if |v| < eps then result = v |
| Type | Name | Description |
|---|---|---|
| Complex | result[size(v, 1)] | Input vector v normalized to length=1 |
function normalize
"Return normalized complex vector such that length = 1 and prevent zero-division for zero vector"
input Complex v[:] "Vector";
input Real eps = 100*Modelica.Constants.eps "if |v| < eps then result = v";
output Complex result[size(v, 1)] "Input vector v normalized to length=1";
protected
Real length_v = length(v);
algorithm
if length_v >= eps then
for i in 1:size(v,1) loop
result[i] :=v[i].re/length_v + (v[i].im/length_v)*j;
end for;
else
result :=v;
end if;
end normalize;
Modelica.ComplexMath.Vectors.reverse
Vectors.reverse(v);
Vectors.reverse(v)" returns the complex vector elements in reverse order.
reverse({1,2,3,4}); // = {4,3,2,1}
Extends from Modelica.Icons.Function (Icon for functions).
| Type | Name | Default | Description |
|---|---|---|---|
| Complex | v[:] | Vector |
| Type | Name | Description |
|---|---|---|
| Complex | result[size(v, 1)] | Elements of vector v in reversed order |
function reverse
"Reverse vector elements (e.g., v[1] becomes last element)"
extends Modelica.Icons.Function;
input Complex v[:] "Vector";
output Complex result[size(v, 1)] "Elements of vector v in reversed order";
algorithm
result := {v[end-i+1] for i in 1:size(v,1)};
end reverse;
sorted_v = Vectors.sort(v);
(sorted_v, indices) = Vectors.sort(v, ascending=true);
Function sort(..) sorts a Real vector v in ascending order and returns the result in sorted_v. If the optional argument "ascending" is false, the vector is sorted in descending order. In the optional second output argument the indices of the sorted vector with respect to the original vector are given, such that sorted_v = v[indices].
(v2, i2) := Vectors.sort({-1, 8, 3, 6, 2});
-> v2 = {-1, 2, 3, 6, 8}
i2 = {1, 5, 3, 4, 2}
| Type | Name | Default | Description |
|---|---|---|---|
| Complex | v[:] | Vector to be sorted | |
| Boolean | ascending | true | = true if ascending order, otherwise descending order |
| Boolean | sortFrequency | true | = true, if sorting is first for imaginary then for real value; = false, if sorting is for absolute value |
| Type | Name | Description |
|---|---|---|
| Complex | sorted_v[size(v, 1)] | Sorted vector |
| Integer | indices[size(v, 1)] | sorted_v = v[indices] |
function sort "Sort elements of complex vector"
input Complex v[:] "Vector to be sorted";
input Boolean ascending = true
"= true if ascending order, otherwise descending order";
input Boolean sortFrequency=true
"= true, if sorting is first for imaginary then for real value; = false, if sorting is for absolute value";
output Complex sorted_v[size(v,1)] = v "Sorted vector";
output Integer indices[size(v,1)] = 1:size(v,1) "sorted_v = v[indices]";
/* shellsort algorithm; should be improved later */
protected
Integer gap;
Integer i;
Integer j;
Complex wv;
Integer wi;
Integer nv = size(v,1);
Boolean swap;
Integer k1;
Integer k2;
algorithm
gap := div(nv,2);
while gap > 0 loop
i := gap;
while i < nv loop
j := i-gap;
if j>=0 then
k1 := j+1;
k2 := j + gap + 1;
if sortFrequency then
if ascending then
swap := abs(sorted_v[k1].im) > abs(sorted_v[k2].im) or
abs(sorted_v[k1].im) == abs(sorted_v[k2].im) and
(sorted_v[k1].re > sorted_v[k2].re or
sorted_v[k1].re == sorted_v[k2].re and sorted_v[k1].im < sorted_v[k2].im);
else
swap := abs(sorted_v[k1].im) < abs(sorted_v[k2].im) or
abs(sorted_v[k1].im) == abs(sorted_v[k2].im) and
(sorted_v[k1].re < sorted_v[k2].re or
sorted_v[k1].re == sorted_v[k2].re and sorted_v[k1].im < sorted_v[k2].im);
end if;
else
if ascending then
swap := ComplexMath.'abs'(sorted_v[k1]) > ComplexMath.'abs'(sorted_v[k2]);
else
swap := ComplexMath.'abs'(sorted_v[k1]) < ComplexMath.'abs'(sorted_v[k2]);
end if;
end if;
else
swap := false;
end if;
while swap loop
wv := sorted_v[j+1];
wi := indices[j+1];
sorted_v[j+1] := sorted_v[j+gap+1];
sorted_v[j+gap+1] := wv;
indices[j+1] := indices[j+gap+1];
indices[j+gap+1] := wi;
j := j - gap;
if j >= 0 then
k1 := j+1;
k2 := j + gap + 1;
if sortFrequency then
if ascending then
swap := abs(sorted_v[k1].im) > abs(sorted_v[k2].im) or
abs(sorted_v[k1].im) == abs(sorted_v[k2].im) and
(sorted_v[k1].re > sorted_v[k2].re or
sorted_v[k1].re == sorted_v[k2].re and sorted_v[k1].im < sorted_v[k2].im);
else
swap := abs(sorted_v[k1].im) < abs(sorted_v[k2].im) or
abs(sorted_v[k1].im) == abs(sorted_v[k2].im) and
(sorted_v[k1].re < sorted_v[k2].re or
sorted_v[k1].re == sorted_v[k2].re and sorted_v[k1].im < sorted_v[k2].im);
end if;
else
if ascending then
swap := ComplexMath.'abs'(sorted_v[k1]) > ComplexMath.'abs'(sorted_v[k2]);
else
swap := ComplexMath.'abs'(sorted_v[k1]) < ComplexMath.'abs'(sorted_v[k2]);
end if;
end if;
else
swap := false;
end if;
end while;
i := i + 1;
end while;
gap := div(gap,2);
end while;
end sort;