Mercurial > repos > public > sbplib
changeset 485:77460b6babe1
Merge feature/subclassable_cellarray
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Wed, 02 Aug 2017 15:25:36 +0200 |
parents | e1a59aafe99c (current diff) da7df0c9af05 (diff) |
children | e9e3973456c0 6aad1c4c8e01 |
files | |
diffstat | 3 files changed, 358 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Cell.m Wed Aug 02 15:25:36 2017 +0200 @@ -0,0 +1,88 @@ +% Cell is a reimplementation of matlabs cell array with the benefit that it is subclassable +% It might be used for giving a typename to a cellarray to increase readability of the code. +classdef Cell + properties + data + end + + methods + function obj = Cell(data) + default_arg('data', {}); + if ~iscell(data) + error('Input argument to Cell must be a cell array'); + end + + obj.data = data; + end + + function str = toString(obj) + str = sprintf('%s%s', class(obj), toString(obj.data)); + end + + function s = size(A) + s = size(A.data); + end + + function l = length(A) + l = length(A.data); + end + + function ind = end(A,k,n) + ind = builtin('end',A.data, k, n); + end + + function B = transpose(A) + b = A.data.'; + B = callConstructor(A, b); + end + + function B = ctranspose(A) + b = A.data'; + B = callConstructor(A, b); + end + + function A = subsasgn(A, S, B) + a = subsasgn(A.data, S, B); + A = callConstructor(A, a); + end + + function B = subsref(A, S) + switch S(1).type + case '()' + b = subsref(A.data, S(1)); + B = callConstructor(A, b); + if length(S) > 1 + B = subsref(B,S(2:end)); + end + case '{}' + B = subsref(A.data, S); + case '.' + B = builtin('subsref',A, S); + otherwise + error('unreachable'); + end + end + + function C = horzcat(varargin) + dataArray = cell(1, length(varargin)); + + for i = 1:length(varargin) + dataArray{i} = varargin{i}.data; + end + + c = horzcat(dataArray{:}); + C = callConstructor(varargin{1}, c); + end + + function C = vertcat(varargin) + dataArray = cell(1, length(varargin)); + + for i = 1:length(varargin) + dataArray{i} = varargin{i}.data; + end + + c = vertcat(dataArray{:}); + C = callConstructor(varargin{1}, c); + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CellTest.m Wed Aug 02 15:25:36 2017 +0200 @@ -0,0 +1,264 @@ +function tests = CellTest() + tests = functiontests(localfunctions); +end + +function testSize(testCase) + cases = { + {{}, [0, 0]}, + {{1}, [1, 1]}, + {{1, 2}, [1, 2]}, + {{1; 2}, [2, 1]}, + {{1, 2; 3, 4}, [2,2]}, + }; + + for i = 1:length(cases) + A = Cell(cases{i}{1}); + expected = cases{i}{2}; + + testCase.verifyEqual(size(A),expected); + end +end + +function testLength(testCase) + cases = { + {{}, 0}, + {{1}, 1}, + {{1, 2}, 2}, + {{1; 2}, 2}, + {{1, 2; 3, 4}, 2}, + }; + + for i = 1:length(cases) + A = Cell(cases{i}{1}); + expected = cases{i}{2}; + + testCase.verifyEqual(length(A),expected); + end +end + +function testTranspose(testCase) + testCase.verifyEqual(Cell({1i, 2}).', Cell({1i; 2})); + testCase.verifyEqual(Cell({1i; 2}).', Cell({1i, 2})); +end + +function testCtranspose(testCase) + testCase.verifyEqual(Cell({1i, 2})', Cell({1i; 2})); + testCase.verifyEqual(Cell({1i; 2})', Cell({1i, 2})); +end + +function testRoundIndexWithProperty(testCase) + A = Cell({3,2,1}); + + result = A([1,3]).data; + testCase.verifyEqual(result, {3, 1}); +end + +function testSubAssignmentRound(testCase) + cases = { + % { + % lArray, + % index, + % rhs, + % expectedResult + % }, + { + {}, + 1, + {'a'}, + {'a'}, + }, + { + {1}, + 1, + {'a'}, + {'a'}, + }, + { + {1,2,3}, + 2, + {'a'}, + {1,'a',3}, + }, + { + {1,2,3}, + 2, + [], + {1,3}, + }, + }; + + for i = 1:length(cases) + lArray = Cell(cases{i}{1}); + index = cases{i}{2}; + rhs = cases{i}{3}; + expectedResult = cases{i}{4}; + + lArray(index) = rhs; + + testCase.verifyEqual(lArray.data, expectedResult) + end +end + +function testSubAssignmentCurly(testCase) + cases = { + % { + % lArray, + % index, + % rhs, + % expectedResult + % }, + { + {}, + 1, + 'a', + {'a'}, + }, + { + {1}, + 1, + 'a', + {'a'}, + }, + { + {1,2,3}, + 2, + 'a', + {1,'a',3}, + }, + }; + + for i = 1:length(cases) + lArray = Cell(cases{i}{1}); + index = cases{i}{2}; + rhs = cases{i}{3}; + expectedResult = cases{i}{4}; + + lArray{index} = rhs; + + testCase.verifyEqual(lArray.data, expectedResult) + end +end + +function testIndexreferenceRound(testCase) + cases = { + % { + % array, + % index, + % roundResult + % }, + { + {1,2,3}, + 1, + {1}, + }, + { + {1,3,2}, + 2, + {3}, + }, + { + {1,3,2}, + [1 3], + {1, 2}, + }, + }; + + + for i = 1:length(cases) + array = Cell(cases{i}{1}); + index = cases{i}{2}; + expected = cases{i}{3}; + + result = array(index); + + testCase.verifyTrue(isa(result, 'Cell')); + testCase.verifyEqual(result.data, expected); + end +end + +function testEndIndexing(testCase) + C = Cell({1,2,3}); + + testCase.verifyEqual(C(end), Cell({3})); + testCase.verifyEqual(C{end}, 3); +end + +function testColonIndexing(testCase) + C = Cell({1, 2, 3}); + D = Cell({1; 2; 3}); + + testCase.verifyEqual(C(:), D); + testCase.verifyEqual(D(:), D); +end + +function testIndexreferenceCurly(testCase) + cases = { + % { + % array, + % index, + % curlyResult + % }, + { + {1,2,3}, + 1, + 1 + }, + { + {1,3,2}, + 2, + 3 + }, + }; + + + for i = 1:length(cases) + array = Cell(cases{i}{1}); + index = cases{i}{2}; + expected = cases{i}{3}; + + result = array{index}; + + testCase.verifyEqual(result, expected); + end +end + +function testConcat(testCase) + cases = { + {{},{}}, + {{1},{}}, + {{},{1}}, + {{1},{2}}, + {{1, 2},{3, 4}}, + {{1; 2},{3; 4}}, + }; + + horzCat = { + {}, + {1}, + {1}, + {1,2}, + {1, 2, 3, 4}, + {1, 3; 2, 4}, + }; + + vertCat = { + {}, + {1}, + {1}, + {1; 2}, + {1, 2; 3, 4}, + {1; 2; 3; 4}, + }; + + for i = 1:length(cases) + A = Cell(cases{i}{1}); + B = Cell(cases{i}{2}); + + C_horz = [A, B]; + C_vert = [A; B]; + + testCase.verifyEqual(C_horz.data, horzCat{i}); + testCase.verifyEqual(C_vert.data, vertCat{i}); + + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/callConstructor.m Wed Aug 02 15:25:36 2017 +0200 @@ -0,0 +1,6 @@ +% Calls the constructor of an object. +% Might be usefull to call the constructor of a subclass object in the superclass +function obj = callConstructor(subclassObj, varargin) + fun = str2func(class(subclassObj)); + obj = fun(varargin{:}); +end