Commit 675ddf17 authored by Jakob Gabriel's avatar Jakob Gabriel
Browse files

quantity.sort: renamed old sort into sortDomain and implemented new sort...

quantity.sort: renamed old sort into sortDomain and implemented new sort method that actually sorts the quantity-array according to its values.
parent 485ba68d
......@@ -590,11 +590,108 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete ...
end
end
function newObj = sort(obj, varargin)
%SORT sorts the grid of the object in a desired order
% obj = sortGrid(obj) sorts the grid in alphabetical order.
% obj = sort(obj, 'descend') sorts the grid in descending
% alphabetical order.
function [B, I] = sort(obj, direction)
% sort Sort in ascending or descending order.
% B = sort(A) sorts in ascending order.
% The sorted output B has the same type and size as A:
% - For vectors, sort(A) sorts the elements of A in ascending order.
% - No implementation for matrices or N-D-arrays yet.
%
% B = sort(A,DIRECTION) specify the sort direction. DIRECTION must be:
% 'ascend' - (default) Sorts in ascending order.
% 'descend' - Sorts in descending order.
%
% [B,I] = sort(A,...) also returns a sort index I which specifies how the
% elements of A were rearranged to obtain the sorted output B:
% - If A is a vector, then B = A(I).
%
% Note that this sort method might cause errors if there is nor strict-ordering
% possible, see try-catch block in this code.
arguments
obj {mustBe.vector};
direction (1, 1) string = "ascend";
end % arguments
[~, I] = sort(obj.at({obj(1).domain.lower}), direction);
B = obj(I);
try
assert(B.issorted(direction), "sort was unsuccessful.");
catch
[~, I] = sort(obj.at({obj(1).domain.upper}), direction);
B = obj(I);
assert(B.issorted(direction), "sort was unsuccessful.");
end
end % sort()
function isIt = issorted(obj, direction)
% issorted Check if data is sorted.
% TF = issorted(A) returns TRUE if the elements of A are sorted in
% ascending order, namely, returns TRUE if A and SORT(A) are identical:
% - For vectors, issorted(A) returns TRUE if A is a sorted vector.
%
% TF = issorted(A,DIRECTION) check if
% A is sorted according to the specified direction. DIRECTION must be:
% 'ascend' - (default) Checks if data is in ascending order.
% 'descend' - Checks if data is in descending order.
% 'monotonic' - Checks if data is in either ascending or
% descending order.
% 'strictascend' - Checks if data is in ascending order and does
% not contain duplicate or missing elements.
% 'strictdescend' - Checks if data is in descending order and does
% not contain duplicate or missing elements.
% 'strictmonotonic' - Checks if data is in either ascending or
% descending order and does not contain duplicate
% or missing elements.
arguments
obj {mustBe.vector};
direction (1, 1) string = "ascend";
end % arguments
diffOfElements = quantity.Discrete.zeros([numel(obj)-1, 1], obj(1).domain);
for it = 1 : numel(diffOfElements)
diffOfElements(it) = obj(it+1) - obj(it);
end
isIt = false;
switch direction
case "ascend" % diffOfElements >= 0
if MAX(-diffOfElements) <= 0
isIt = true;
end
case "descend" % diffOfElements <= 0
if MAX(diffOfElements) <= 0
isIt = true;
end
case "monotonic" % diffOfElements >= 0 || diffOfElements <= 0
if (MAX(-diffOfElements) <= 0) || (MAX(diffOfElements) <= 0)
isIt = true;
end
case "strictascend" % diffOfElements >= 0
if MAX(-diffOfElements) < 0
isIt = true;
end
case "strictdescend" % diffOfElements <= 0
if MAX(diffOfElements) < 0
isIt = true;
end
case "strictmonotonic" % diffOfElements >= 0 || diffOfElements <= 0
if (MAX(-diffOfElements) < 0) || (MAX(diffOfElements) < 0)
isIt = true;
end
otherwise
error("direction = " + direction + "is not valid");
end
end % issorted()
function newObj = sortDomain(obj, varargin)
%SORTDOMAIN sorts the domain of the object in a desired order
% obj = sortDomain(obj) sorts the grid in alphabetical order.
% obj = sortDomain(obj, 'descend') sorts the grid in descending alphabetical order.
newObj = obj.copy();
% only sort the grids if there is something to sort
if ~isempty(newObj) && newObj(1).nargin > 1
......@@ -606,7 +703,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete ...
newObj(k).valueDiscrete = permute(obj(k).valueDiscrete, I);
end
end
end% sort()
end % sortDomain()
function c = horzcat(a, varargin)
%HORZCAT Horizontal concatenation.
......@@ -748,7 +845,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete ...
% sort the grid names of each quantity
for it = 1: (numel(varargin) + 1)
objCell{it} = objCell{it}.sort;
objCell{it} = objCell{it}.sortDomain();
end
[fineGrid, fineGridName] = getFinestGrid(objCell{~isEmpty});
......
......@@ -4,7 +4,36 @@ function [tests] = testDiscrete()
tests = functiontests(localfunctions);
end
function testSortAndIssorted(tc)
z = quantity.Domain("z", linspace(0, 1, 4));
quanSymbolic = quantity.Symbolic([-sym("z")-0.5, 2 + sym("z"), 3.2, -2, 0, 3.5], z);
quanDisc = quantity.Discrete(quanSymbolic);
[quanSorted, I] = quanDisc.sort();
[quan0Sorted, I0] = sort(quanSymbolic.at(0));
tc.verifyEqual(I, I0);
tc.verifyEqual(quanSorted.at(0), quan0Sorted);
tc.verifyEqual(quanSorted.on(), quanSymbolic.sort.on());
tc.verifyEqual(quanDisc(I).on(), quanSorted.on());
tc.verifyEqual(quanSymbolic(I).on(), quanSorted.on());
tc.verifyEqual(quanDisc.sort('ascend').on(), flip(quanDisc.sort('descend').on(), 3))
tc.verifyTrue(quanSorted.issorted('ascend'));
tc.verifyTrue(quanSorted.issorted('strictascend'));
tc.verifyTrue(quanDisc.sort('descend').issorted('descend'));
tc.verifyTrue(quanSorted.issorted('monotonic'));
% 2 domains
t = quantity.Domain("t", linspace(-1, 2, 5));
quan3 = diag([3, 1]) * quantity.Discrete.ones([2, 1], [z, t]) + z.Discrete()*[1; 0] - t.Discrete()*[0; 1];
tc.verifyEqual(quan3.sort.on(), quan3([2; 1]).on());
tc.verifyEqual(quan3.sort("descend").on(), quan3.on());
% values must be distinct pointwise
quan2 = quantity.Symbolic([1-sym("z"), 0.5], z);
tc.verifyError(@() quan2.sort(), "");
quan4 = quantity.Symbolic([1-sym("z"), 1], z);
tc.verifyTrue(quan4.sort('descend').issorted('descend'));
tc.verifyFalse(quan4.sort('descend').issorted('strictdescend'));
end % testSort()
function testEye(tc)
myDomain = [quantity.Domain("z", linspace(0, 1, 11)), quantity.Domain("zeta", linspace(0, 1, 5))];
......@@ -387,7 +416,7 @@ tc.verifyEqual(blubQuadraticNorm.on(), 2*ones(11,1));
tc.verifyEqual(blubQuadraticWeightedNorm.on(), 4*ones(11,1));
end % testQuadraticNorm()
function testSort(tc)
function testSortDomain(tc)
t = linspace(0, pi, 7)';
domA = quantity.Domain('a', t);
......@@ -396,9 +425,10 @@ q = quantity.Discrete(sin(t) .* cos(t'), [domA, domB]);
q1V = q.valueDiscrete;
q.sort('descend');
q2V = q.sort('descend').valueDiscrete;tc.verifyEqual(q1V , q2V.')
end % testSort
q.sortDomain('descend');
q2V = q.sortDomain('descend').valueDiscrete;
tc.verifyEqual(q1V , q2V.');
end % testSortDomain
function testBlkdiag(tc)
z = quantity.Domain('z', linspace(0, 1, 21));
......
......@@ -23,7 +23,7 @@ z = quantity.Domain("z", 0:5);
t = quantity.Domain("t", 0:4);
a = quantity.Function(@(z,t) z + t*0, [z, t]);
b = a.sort;
b = a.sortDomain();
tc.verifyEqual( a.on([z,t]), b.on([z,t]));
......
......@@ -61,7 +61,7 @@ C2 = [zeta.Symbolic + 0*z.Symbolic; x];
tc.verifyEqual(C1.on([z, zeta]), C2.on([z, zeta]));
e = zeta.Symbolic + 0*z.Symbolic;
e = e.sort();
e = e.sortDomain();
f = e.changeGrid({z.grid z.grid}, ["z", "zeta"]);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment