Commit 56ec3743 authored by Ferdinand Fischer's avatar Ferdinand Fischer
Browse files

First simple version for a compose function h(z,t) = f(g(z,t))

parent d4bad356
......@@ -231,6 +231,59 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
end
methods (Access = public)
function obj_hat = compose(obj, g, varargin)
% COMPOSE compose two functions
% OBJ_hat = compose(obj, G, varargin) composes the function
% defined by OBJ with the function given by G. In particular,
% f_hat(z,t) = f( g(z,t) )
% if f(t) = obj, g is G and f_hat is OBJ_hat.
assert(isscalar(g));
assert(nargin(obj) == 1 );
newDomain = g.domain();
composeOnDomain = g.on();
% the evaluation of obj.on( compositionDomain ) is done by:
domainSize = size(composeOnDomain);
% 1) vectorization of the n-d-grid: compositionDomain
composeOnDomain = composeOnDomain(:);
% 2) then it is sorted in ascending order
[composeOnDomain, I] = sort(composeOnDomain);
% verify the domain to be monotonical increasing
deltaCOD = diff(composeOnDomain);
assert(misc.alln(deltaCOD >= 0), 'The domain for the composition f(g(.)) must be monotonically increasing');
% check if the composition domain is in the range of definition
% of obj.
if( obj.domain.lower > composeOnDomain(1) || ...
obj.domain.upper < composeOnDomain(end) )
warning('quantity:Discrete:compose', ....
'The composition domain is not a subset of obj.domain! The missing values will be extrapolated.');
end
% 3) evaluation on the new grid:
newValues = obj.on( composeOnDomain );
% 4) reorder the computed values, dependent on the sort
% position
newValues(I) = newValues;
% 5) rearrange the computed values, to have the same dimension
% as the required domain
newValues = reshape( newValues, domainSize);
obj_hat = quantity.Discrete( newValues, ...
'name', [obj.name '°' g.name], ...
'size', size(obj), ...
'domain', newDomain );
end
function value = on(obj, myDomain, gridNames)
% ON evaluation of the quantity on a certain domain.
% value = on(obj) or value = obj.on(); evaluates the quantity
......@@ -253,7 +306,7 @@ classdef (InferiorClasses = {?quantity.Symbolic}) Discrete < handle & matlab.mi
% myDomain as a cell-array with grid entries
if iscell(myDomain) || isnumeric(myDomain)
myDomain = misc.ensureIsCell(myDomain);
assert(all(cellfun(@(v)isvector(v), myDomain)), 'The cell entries for a new grid have to be vectors')
% assert(all(cellfun(@(v)isvector(v), myDomain)), 'The cell entries for a new grid have to be vectors')
newGrid = myDomain;
myDomain = quantity.Domain.empty();
......
......@@ -32,19 +32,21 @@ classdef Domain < matlab.mixin.CustomDisplay
%DOMAIN initialize the domain
%
if nargin >= 1
parser = misc.Parser();
parser.addParameter('grid', [], @(g) isvector(g) || isempty(g));
parser.addParameter('name', '', @ischar);
parser.parse(varargin{:});
myParser = misc.Parser();
myParser.addParameter('grid', [], @(g) isvector(g) || isempty(g));
myParser.addParameter('name', '', @ischar);
myParser.parse(varargin{:});
% todo: assertions
% * ascending ?
obj.grid = parser.Results.grid(:);
obj.name = parser.Results.name;
obj.grid = myParser.Results.grid(:);
obj.name = myParser.Results.name;
else
obj = quantity.Domain.empty();
end
myParser.unmatchedWarning();
end
function i = get.ones(obj)
......@@ -103,7 +105,7 @@ classdef Domain < matlab.mixin.CustomDisplay
function l = ne(obj, obj2)
l = ~(obj == obj2);
end
function [joinedDomain, index] = gridJoin(obj1, obj2)
%% gridJoin combines the grid and gridName of two objects (obj1,
% obj2), such that every gridName only occurs once and that the
......
......@@ -4,6 +4,37 @@ function [tests] = testDiscrete()
tests = functiontests(localfunctions);
end
function testCompose(testCase)
t = quantity.Domain('grid', linspace(0, 2), 'name', 't');
f = quantity.Discrete(sin(t.grid * 2 * pi) , 'domain', t, 'name', 'f' );
g = quantity.Discrete( 0.5 * t.grid, 'domain', t, 'name', 'g');
h = quantity.Discrete( 2 * t.grid, 'domain', t, 'name', 'h');
% verify simple evaluation of f( g(t) )
testCase.verifyEqual( on( f.compose(g) ), sin(t.grid * pi), 'AbsTol', 3e-3 )
% verify that a warning is thrown, if the domain of definition is exceeded
testCase.verifyWarning(@()f.compose(h), 'quantity:Discrete:compose')
% verify f(tau) = sin( tau * 2pi ); g(z, t) = t + z^2
% f( g(z, t ) ) = sin( (t + z^2 ) * 2pi )
tau = quantity.Domain('grid', linspace(-1, 3), 'name', 'tau' );
z = quantity.Domain('grid', linspace(0, 1, 51), 'name', 'z');
f = quantity.Discrete( sin( tau.grid * 2 * pi ), 'domain', tau );
g = quantity.Discrete( ( z.grid.^2 ) + t.grid', 'domain', [z, t] );
fg = f.compose(g);
F = quantity.Function(@(z,t) sin( ( t + z.^2 ) * 2 * pi ), ...
'domain', [z, t], 'name', 'f(g) as function handle');
testCase.verifyEqual(fg.on, F.on, 'AbsTol', 1e-2)
end
function testCastDiscrete2Function(testCase)
z = linspace(0, 2*pi)';
......
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