function numericValue = str2doubleSI(stringValue)
%
% Similar to str2double, with support for engineering notation (SI prefixes)
% as illustrated in the following examples:
%   str2doubleSI('1.52u') = 1.5200e-06
%   str2doubleSI('2.61G') = 2.6100e+09
%
% Supported SI prefixes (case sensitive):
%   'y' (yocto = 1.0E-24)
%   'z' (zepto = 1.0E-21)
%   'a' ( atto = 1.0E-18)
%   'f' (femto = 1.0E-15)
%   'p' ( pico = 1.0E-12)
%   'n' ( nano = 1.0E-09)
%   'u' (micro = 1.0E-06)
%   'm' (milli = 1.0E-03)
%   'k' ( kilo = 1.0E+03)
%   'M' ( mega = 1.0E+06)
%   'G' ( giga = 1.0E+09)
%   'T' ( tera = 1.0E+12)
%   'P' ( peta = 1.0E+15)
%   'E' (  exa = 1.0E+18)
%   'Z' (zetta = 1.0E+21)
%   'Y' (yotta = 1.0E+24)
%
% Input:
%   stringValue - string representation of number that may include SI prefix.
%
% Output:
%   numericValue - double if successfully converted, or
%                - original input string (stringValue) if unable to convert.

%  Copyright 2020, The MathWorks, Inc.

    % Remove any leading and/or trailing whitespace.
    value = strtrim(stringValue);
    
    % Convert string to number using standard MATLAB str2num function.
    numericValue = str2double(value);
    if ~isnan(numericValue)
      return; % str2double successfully converted string value to a number.
    end
    
    % Look for (and separate) numeric characters preceding alphabetic characters in string value.
    lastAlphaIndex = length(value);
    lastNumberIndex = 1;
    unit = '';
    number = '';
    alphabeticChars = isstrprop(value,'alpha');
    for i = 1:length(alphabeticChars)
        if alphabeticChars(i) && i > lastNumberIndex
            lastAlphaIndex = i;
            unit = [unit value(i)]; %#ok<AGROW> Append alphabetic character following numeric characters (to get unit).
        elseif ~alphabeticChars(i) && i < lastAlphaIndex
            lastNumberIndex = i;
            number = [number value(i)]; %#ok<AGROW> Append numeric character preceding alphabetic characters (to get number).
        else
            % Incorrect order of numeric versus alpha characters encountered.
            numericValue = stringValue; % Return original value (e.g., unchanged string).
            return; 
        end
    end
    switch unit
        case 'y'
            multiplier = 1.0E-24;  % yocto
        case'z'
            multiplier = 1.0E-21;  % zepto
        case'a'
            multiplier = 1.0E-18;  % atto
        case'f'
            multiplier = 1.0E-15;  % femto
        case'p'
            multiplier = 1.0E-12;  % pico
        case'n'
            multiplier = 1.0E-09;  % nano
        case'u'
            multiplier = 1.0E-06;  % micro
        case'm'
            multiplier = 1.0E-03;  % milli
        case'k'
            multiplier = 1.0E+03;  % kilo
        case'M'
            multiplier = 1.0E+06;  % mega
        case'G'
            multiplier = 1.0E+09;  % giga
        case'T'
            multiplier = 1.0E+12;  % tera
        case'P'
            multiplier = 1.0E+15;  % peta
        case'E'
            multiplier = 1.0E+18;  % exa
        case'Z'
            multiplier = 1.0E+21;  % zetta
        case'Y'
            multiplier = 1.0E+24;  % yotta
        otherwise
            multiplier = 1;
    end
    try
        numericValue = str2double(number) * multiplier;
    catch
        % Unexpected error converting numeric portion of string and/or multiplying it.
        numericValue = stringValue;  % Return original value (e.g., unchanged string).
        return;
    end
end
