diff m-toolbox/classes/@unit/unit.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/unit.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,339 @@
+% UNIT a helper class for implementing units in LTPDA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% UNIT a helper class for implementing units in LTPDA.
+%
+% SUPERCLASSES: ltpda_nuo < ltpda_obj
+%
+% CONSTRUCTORS:
+%
+%   u = unit(str);
+%
+% EXAMPLES:
+%
+%       u = unit('m');            - Create a simple unit
+%       u = unit('m^3');          - With an exponent
+%       u = unit('m^1/2');
+%       u = unit('m^1.5');
+%       u = unit('pm^2');         - With a prefix
+%       u = unit('m s^-2 kg');    - Multiple units
+%       u = unit('m/s');          - Units with division
+%       u = unit('m^.5 / s^2');
+%
+% SUPPORTED PREFIXES:      unit.supportedPrefixes
+% SUPPORTED UNITS:         unit.supportedUnits
+%
+% VERSION:  $Id: unit.m,v 1.54 2011/08/16 04:52:19 hewitson Exp $
+%
+% SEE ALSO: ltpda_obj, ltpda_nuo
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%classdef unit
+
+classdef (Hidden = true) unit < ltpda_nuo
+  
+  %----------------------------------------
+  %- Private properties
+  %----------------------------------------
+  properties (SetAccess = protected)
+    strs    = {}; % unit sign
+    exps    = []; % exponent of the units
+    vals    = []; % prefixes of the units (all SI prefixes are supported)
+  end
+  
+  %----------------------------------------
+  %- Public methods
+  %----------------------------------------
+  methods
+    
+    %----------------------------------------
+    %- Constructor
+    %----------------------------------------
+    function u = unit(varargin)
+      
+      switch nargin
+        case 0
+          % Empty constructor
+        case 1
+          if ischar(varargin{1})
+            % String input
+            ustr = strtrim(varargin{1});
+            if ~isempty(ustr)
+              
+              % Handle the output of char(unit)
+              ustr = strtrim(strrep(strrep(ustr, '[', ' '), ']', ' '));
+              
+              % split on whitespace
+              expr_unit = '([1a-zA-Z]+)';
+              expr_frac = '([+-]?[0-9]*(\.[0-9]+)?(/-?[0-9]+)?)';
+              expr = [' *' expr_unit '(\^(\(' expr_frac '\)|' expr_frac '))* *'];
+              %expr = ' *([1a-zA-Z]+)(\^(\((-?[0-9]+(\/-?[0-9]+)?)\)|(-?[0-9]+(\/-?[0-9]+)?)))* *';
+              tks = strtrim(regexp(ustr, expr, 'match'));
+              ops = strtrim(regexp(ustr, expr, 'split'));
+              
+              % combine each unit
+              for j=1:numel(tks)
+                % Parse string
+                if tks{j} == '1' % Special case for '1/s'
+                  u2.strs = '';
+                  u2.exps = [];
+                  u2.vals = [];
+                else
+                  [us, exp, val] = unit.parse(tks{j});
+                  u2.strs = {us};
+                  u2.exps = exp;
+                  u2.vals = val;
+                end
+                
+                switch ops{j}
+                  case ''
+                    u.strs = [u.strs u2.strs];
+                    u.exps = [u.exps u2.exps];
+                    u.vals = [u.vals u2.vals];
+                  case '+'
+                    u2 = unit(u2);
+                    u = u + u2;
+                  case '-'
+                    u2 = unit(u2);
+                    u = u - u2;
+                  case {'*', '.*'}
+                    u2 = unit(u2);
+                    u = u * u2;
+                  case {'/', './'}
+                    u2 = unit(u2);
+                    u = u / u2;
+                  otherwise
+                    error('### Unknown operator [%s]', ops{j});
+                end
+              end
+            end
+            
+          elseif isstruct(varargin{1})
+            u = fromStruct(u, varargin{1});
+            
+          elseif isa(varargin{1}, 'double')
+            
+            if isempty(varargin{1})
+            else
+              s = unit.supportedUnits;
+              if numel(varargin{1}) == numel(s)
+                positions = not(varargin{1}==0);
+                u.strs = s(positions);
+                u.exps = varargin{1}(positions);
+                u.vals = ones(1, sum(positions));
+              else
+                error('variable unit.supportedUnits does not match');
+              end
+            end
+            
+          elseif isa(varargin{1}, 'unit')
+            u = varargin{1};
+            
+          elseif iscell(varargin{1})
+            
+            for kk=1:numel(varargin{1})
+              u(kk) = unit(varargin{1}{kk});
+            end
+            
+          else
+            error('### Unknown single argument constructor. The constructor doesn''t support the class [%s]', class(varargin{1}));
+          end
+          
+        case 2
+          if  isa(varargin{1}, 'org.apache.xerces.dom.DeferredElementImpl') && ...
+              isa(varargin{2}, 'history')
+            u = fromDom(u, varargin{1}, varargin{2});
+
+          elseif (isa(varargin{1}, 'unit') || ischar(varargin{1})) && ...
+                 (isa(varargin{2}, 'unit') || ischar(varargin{2}))
+            u = varargin{1};
+            u = [u unit(varargin{2})];
+            
+          else
+            error('### Unknown constructor method for two inputs.');
+          end
+          
+        otherwise
+          u = varargin{1};
+          for i=2:numel(varargin)
+            u = [u unit(varargin{i})];
+          end
+      end
+      
+    end % End constructor
+    
+  end % End public methods
+  
+  %----------------------------------------
+  %- Private Static methods
+  %----------------------------------------
+  methods (Static=true, Access=private)
+    
+    %----------------------------------------
+    %- Parse a unit definition string
+    %----------------------------------------
+    function [us, exp, val] = parse(ustr)
+      
+      % get exp
+      [s,t] = strtok(ustr, '^');
+      if ~isempty(t)
+        % drop any ()
+        t = strrep(t(2:end),'(','');
+        t = strrep(t,')','');
+        exp = eval(t);
+      else
+        exp = 1;
+      end
+      
+      if length(s) > 1 && utils.helper.ismember(s(1), unit.supportedPrefixes) && utils.helper.ismember(s(2:end), unit.supportedUnits)
+        % check for prefix
+        sp  = s(1);
+        val = unit.prefix2val(sp);
+        sm  = s(2:end);
+      elseif length(s) > 2 && utils.helper.ismember(s(1:2), unit.supportedPrefixes) && utils.helper.ismember(s(3:end), unit.supportedUnits)
+        % special case for the prefix 'da'
+        sp  = s(1:2);
+        val = unit.prefix2val(sp);
+        sm  = s(3:end);
+      else
+        val = 1;
+        sp  = '';
+        sm  = s;
+      end
+      
+      % Check unit
+      if ~utils.helper.ismember(sm, unit.supportedUnits)
+        error(['### Unsupported unit: [' sm ']']);
+      end
+      
+      % set unit string
+      us  = [sm];
+      
+    end % End parse
+    
+    
+    
+    %----------------------------------------
+    %- Get the value associated with a prefix
+    %----------------------------------------
+    function val = prefix2val(p)
+      [pfxs, pfxvals] = unit.supportedPrefixes;
+      val = pfxvals(strcmp(p, pfxs));
+    end
+    
+    %----------------------------------------
+    %- Get the prefix associated with a value
+    %----------------------------------------
+    function p = val2prefix(val)
+      [pfxs, pfxvals] = unit.supportedPrefixes;
+      res = val==pfxvals;
+      if any(res)
+        p = pfxs{val==pfxvals};
+      else
+        p = '';
+      end
+    end
+  end % End static private methods
+  
+  %----------------------------------------
+  %- Public static methods
+  %----------------------------------------
+  methods (Static=true)
+    
+    function out = VEROUT()
+      out = '$Id: unit.m,v 1.54 2011/08/16 04:52:19 hewitson Exp $';
+    end
+    
+    function ii = getInfo(varargin)
+      ii = utils.helper.generic_getInfo(varargin{:}, 'unit');
+    end
+    
+    function out = SETS()
+      out = {'Default'};
+    end
+    
+    function out = getDefaultPlist(set)
+      switch lower(set)
+        case 'default'
+          out = plist();
+        otherwise
+          error('### Unknown set [%s]', set);
+      end
+    end
+    
+    function obj = initObjectWithSize(n,m)
+      obj = unit.newarray([n m]);
+    end
+    
+    %----------------------------------------
+    %- Return a list of supported prefixes
+    %----------------------------------------
+    function varargout = supportedPrefixes
+      pfxs = {...
+        'y',  'z', 'a', 'f', 'p', 'n', 'u', 'm', 'c', 'd', '', ...
+        'da', 'h', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'};
+      pfxvals = [...
+        1e-24 1e-21 1e-18 1e-15 1e-12 1e-9 1e-6 1e-3 1e-2 1e-1 1 ...
+        10 100 1000 1e6 1e9 1e12 1e15 1e18 1e21 1e24];
+      
+      if nargout == 1
+        varargout{1} = pfxs;
+      elseif nargout == 2
+        varargout{1} = pfxs;
+        varargout{2} = pfxvals;
+      else
+        for kk=1:numel(pfxs)
+          fprintf('%-3s[%g]\n', pfxs{kk}, pfxvals(kk));
+        end
+      end
+      
+    end
+    
+    %----------------------------------------
+    %- Return a list of supported units
+    %----------------------------------------
+    function bu = supportedUnits
+      ltpdaUnits = {'', 'm', 'kg', 's', 'A', 'K', 'mol', 'cd', ...
+        'rad', 'deg', 'sr', 'Hz', 'N', 'Pa', 'J', 'W', 'C', 'V', 'F', ...
+        'Ohm', 'S', 'Wb', 'T', 'H', 'degC', ...
+        'Count', 'arb', 'Index'};
+      
+      prefs = getappdata(0, 'LTPDApreferences');
+      userUnits = prefs.getMiscPrefs.getUnits;
+      bu = [ltpdaUnits cell(1, userUnits.size)];
+      for kk=0:userUnits.size-1
+        bu{numel(ltpdaUnits) + kk + 1} = char(userUnits.get(kk));
+      end
+      
+    end
+    
+  end
+  
+  %----------------------------------------
+  %- Static hidden methods
+  %----------------------------------------
+  
+  methods (Static = true, Hidden = true)
+    varargout = loadobj(varargin)
+    varargout = update_struct(varargin)
+  end
+  
+  %----------------------------------------
+  %- Private methods
+  %----------------------------------------
+  
+  methods (Access = private)
+  end
+  
+  %----------------------------------------
+  %- Protected methods
+  %----------------------------------------
+  
+  methods (Access = protected)
+    varargout = fromStruct(varargin)
+    varargout = fromDom(varargin)
+  end
+  
+  methods (Hidden = true)
+    varargout = attachToDom(varargin)
+  end
+end