Mercurial > hg > ltpda
diff m-toolbox/classes/@unit/simplify.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/@unit/simplify.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,146 @@ +% SIMPLIFY the units. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: SIMPLIFY the units. +% +% CALL: a = a.simplify +% +% VERSION: $Id: simplify.m,v 1.10 2011/02/18 16:48:55 ingo Exp $ +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function v = simplify(v, exceptions) + + v = copy(v, nargout); + + if nargin == 1 + exceptions = {}; + elseif nargin == 2 + if ischar(exceptions) + exceptions = cellstr(exceptions); + end + end + + udef = struct('vals', [], 'exps', []); + ustruct = struct(); + ex = struct('strs', {{}}, 'vals', [], 'exps', []); + remain_val = 1; + + % Create a structure with the different units as the fields + % For example: 'mm um ks^2 s' + % + % ustruct.m: vals = [1e-3 1e-6] + % exps = [1 1] + % ustruct.s: vals = [1e3 1] + % exps = [2 1] + % + % 1.) Initialize structure with empty 'vals' and 'exps' fields + % 2.) Fill 'vals' and 'exps' fields + for ii = unique(v.strs) + if ~utils.helper.ismember(ii, exceptions) + ustruct.(cell2mat(ii)) = udef; + end + end + for ii = 1:numel(v.strs) + if ~(utils.helper.ismember(v.strs{ii}, exceptions) || utils.helper.ismember(sprintf('%s%s', unit.val2prefix(v.vals(ii)), v.strs{ii}), exceptions)) + ustruct.(v.strs{ii}).vals = [ustruct.(v.strs{ii}).vals v.vals(ii)]; + ustruct.(v.strs{ii}).exps = [ustruct.(v.strs{ii}).exps v.exps(ii)]; + else + % Collext all units which are in the exception list + ex.strs = [ex.strs v.strs(ii)]; + ex.vals = [ex.vals v.vals(ii)]; + ex.exps = [ex.exps v.exps(ii)]; + end + end + + % Simplify all supported units + fields = fieldnames(ustruct); + for ii = 1:numel(fields) + field = fields{ii}; + + exp = sum(ustruct.(field).exps); + if exp == 0 + % The unit is canced. Keep prefix + remain_val = remain_val * power(10,sum(log10(ustruct.(field).vals) .* ustruct.(field).exps)); + ustruct = rmfield(ustruct, field); + continue + end + + [N,D] = rat(sum( log10(ustruct.(field).vals) .* ustruct.(field).exps ./ exp)); + + if D ~= 1 || ~any(N==[-24:3:-3 -2:1:2 3:3:24]) + % The value is not a supported prefix -> Don't simplify + continue + end + + % Simplify the units + ustruct.(field).vals = eval(['1e' num2str(N)]); + ustruct.(field).exps = exp; + end + + % Prepare output unit-object + % All information of the output object is in 'ustruct' + v.strs = {}; + v.vals = []; + v.exps = []; + fields = fieldnames(ustruct); + for ii = 1:numel(fields) + field = fields{ii}; + strs = {}; + strs(1:numel(ustruct.(field).vals)) = {field}; + v.strs = [v.strs strs]; + v.vals = [v.vals ustruct.(field).vals]; + v.exps = [v.exps ustruct.(field).exps]; + end + + if remain_val ~= 1 && numel(v.vals) >= 1 + % It might be that the units are canceled out but not the prefixes + % For example: 'mm m^-1 Hz' + % Add in this case the prefix to the remaining unit + % Result: 'mHz' + [N,D] = rat((log10(v.vals) .* v.exps + log10(remain_val) ) ./ v.exps); + idx = find(D==1); + + found = false; + for ii = 1:numel(idx) + valexp = N(idx(ii)); + if ~any(valexp==[-24:3:-3 -2:1:2 3:3:24]) + % It is not possibple to add the remaining prefix to one of the other + % units without having an not suported prefix + continue + else + found = true; + break + end + end + + if ~found + % If it is not possible to add the remaining prefix to an other unit + % then retrun the input unit + v = copy(v, 1); + return + else + idx = idx(ii); + end + + v.vals(idx) = eval(['1e' num2str(N(idx))]); + + % It might be that it is possible to simplify the units again + v.simplify(exceptions); + + elseif remain_val ~= 1 && isempty(v.vals) + % It might be that the units are canceled out but not the prefixes + % For example: 'mm m^-1' + % But it is possible that there is no unit left. Return in this case + % the input object. + % Result: 'mm m^-1' + v = copy(v, 1); + return + end + + % Add units which are in the exception list + v.strs = [v.strs ex.strs]; + v.vals = [v.vals ex.vals]; + v.exps = [v.exps ex.exps]; + +end