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