Code covered by the BSD License  

Highlights from
smartconvert

from smartconvert by Ali Mohammad Razeghi
Tries to find a set of coordinates that function has simple relations between variables or finds the

smartconvert ( func , cla , p1 , p2 )
function [ sim , coor ] = smartconvert ( func , cla , p1 , p2 )
% Derives number of dimensions (variables) of given function
% (class - inline , symbolic or char) then tries to find a set of
% coordinates that function has simple relations between variables or finds
% the coordinates that function has less variables. See "p1" comments. This is
% done in two (cartesian or polar) or three (cartesian or cylandrical or
% spherical) dimensions. The output also contain an extra parameter that
% shows the result coordinates and you can choose the out put function
% class type (inline , symbolic or char). See "cla" comments. The function
% also can be used manually. See "p1" comments. Some of usual change of
% coordinate are provided that can be used manually. See "p2" comments.
%
% Clarification: If you choose 'S' for p1: When someone wants to integrate
% ( ( x ^ 2 ) + ( y ^ 2 ) + ( z ^ 2 ) ) dx dy dz. It is more simpler that
% integrate in spherical coordinates with integrand ( r ^ 2 ) ( r ^ 2 sin
% ( theta )dr d( theta )d( phi ) ). This program tries to find and convert
% functions like this. If you choose 'L' for p1: When someone wants to
% use del operator on ( ( x ^ 2 ) + ( y ^ 2 ) + ( z ^ 2 ) ). It is more
% simpler that work in spherical coordinates with ( r ^ 2 ) and use
% spherical del operator. This program tries to find and convert functions
% like this. The two case of code using aren't the same always. See
% examples of the code.
%
% function [ sim , coor ] = smartconvert ( func , cla , p1 , p2 )
%
% arguments: ( input )
%  func - ( class - inline , symbolic or char ) - a function of two or
%  three variables
%
%  cla - ( class - char ) - desired output class type
%
%  p1 - ( class - char ) - specifier of code procedure less variables: 'L'
%  or simple relation: 'S' or manual: 'M'
%
%  p2 - ( class - char ) - specifier of code manual coordinates conversion
%  including all conversions between cartesian and polar in two dimensions
%  and between cartesian and cylindrical and spherical in three dimensions 
%
% arguments: ( returned )
%  sim - ( class - inline , symbolic or char as user desired ) - New function,
%  converted to simpler shape in two or three dimensions
%
%  coor - ( class - char ) the output coordinates
%
% Example:
% (1)
%  W = inline ( ' s * cos ( t ) * tan ( e ) ' , ' s ' ,' t ' , ' e ' ) ;
%  [ simp , coord ] = smartconvert ( W , 'sym' , 'L')
%  simp =
%        A*tan(B)
%  coord =
%         Cartesian
%
% (2)
%  W = inline ( ' s * cos ( t ) * tan ( e ) ' , ' s ' ,' t ' , ' e ' ) ;
%  [ simp , coord ] = smartconvert ( W , 'sym' , 'S')
%  simp =
%        C*B/A
%  coord =
%         Cartesian
%
% See also simple.
%
% Copyright 2008
%
% Requirement: symbolic math toolbox


% check for simple errors
if nargin < 3 || isempty ( p1 ) % checks the number of inputs
    p1 = 'S' ;
end % end of if loop

if p1 == 'M'
    if nargin == 3
        error 'must determine the result coodinates.'
    end % end of if loop
end % end of if loop

if nargin < 2 || isempty ( cla ) % checks the number of inputs
    cla = char ( class ( func ) ) ;  % if the user doesn't want to change the out put class type he/she can just enter one input argument
end % end of if loop

cl1 = class ( func ) ; % determines the class of given function
cl = char ( cl1 ) ; % converts the class of given function to charcter class

if strcmp ( cl , 'inline' ) % if the class of input function just saves the class
end % end of if loop

if  strcmp ( cl , 'sym' ) % if the class of input function was symbolic converts it to class inline
    func = inline ( func ) ; % converts the class of given function from symbolic to inline
end % end of if loop

if strcmp ( cl , 'char' ) % if the class of input function was char converts it to class inline
    func = inline ( func ) ; % converts the class of given function from char to inline
end % end of if loop

arg1 = argnames ( func ) ; % returns the matrix of input function arguments names
lengarg1 = length ( arg1 ) ; % returns the length of matrix of input function arguments names

func = sym ( func ) ; % converts the class of given function from inline to symbolic
alph = 'a' : 'z' ; % creates a string from a to z alphabetic letters
EU = 0 ; % preallocating

if lengarg1 < 27 % checks that the number of arguments of given function is less than 27
    for nu = 1 : lengarg1 % a loop that converts all alphabetic letters from class char to class symbolic
        var = sym ( alph ( nu ) ) ; % converts all alphabetic letters from class char to class symbolic
        func = subs ( func , arg1 ( nu ) , var ) ; % substitutes all alphabetic variables in the given function for simplicity
    end % end of for loop
end % end of if loop

if lengarg1 == 2
    syms A B a b % creates symbolic variables
    CO ( 1 ) = ( A ) ;
    CO ( 2 ) = ( B ) ;

    CO ( 3 ) = ( A ) ;
    CO ( 4 ) = ( B ) ;

    CO ( 5 ) = ( A ) .* cos ( B ) ; % creates x variable from polar coordinates
    CO ( 6 ) = ( A ) .* sin ( B ) ; % creates y variable from polar coordinates

    CO ( 7 ) = sqrt ( ( A .^ 2 ) + ( B .^ 2 ) ) ; % creates rho variable from cartesian coordinates
    CO ( 8 ) = atan ( B ./ A ) ; % creates phi variable from cartesian coordinates

    FU = sym ( '0' ) ;
    for mu = 1 : 2 : 7

        FU ( mu ) = subs ( func , a , CO ( ( ( ( ( mu + 1 ) / 2 ) - 1 ) * 2 ) + 1 ) ) ;
        FU ( mu ) = subs ( FU ( mu ) , b , CO ( ( ( ( ( mu + 1 ) / 2 ) - 1 ) * 2 ) + 2 ) ) ;

        FU ( mu + 1 ) = subs ( func , a , CO ( ( ( ( ( mu + 1 ) / 2 ) - 1 ) * 2 ) + 2 ) ) ;
        FU ( mu + 1 ) = subs ( FU ( mu + 1 ) , b , CO ( ( ( ( ( mu + 1 ) / 2 ) - 1 ) * 2 ) + 1 ) ) ;

    end
    Fs = simple ( FU ) ; % simplifies the result function row vector
end % end of if loop

if lengarg1 == 3
    syms A B C a b c % creates symbolic variables

    CO ( 1 ) = ( A ) ; % creates x variable in cartesian coordinates from cylindrical coordinates
    CO ( 2 ) = ( B ) ; % creates y variable in cartesian coordinates from cylindrical coordinates
    CO ( 3 ) = ( C ) ; % creates z variable in cartesian coordinates from cylindrical coordinates

    CO ( 4 ) = ( A ) ; % creates x variable in cartesian coordinates from cylindrical coordinates
    CO ( 5 ) = ( B ) ; % creates y variable in cartesian coordinates from cylindrical coordinates
    CO ( 6 ) = ( C ) ; % creates z variable in cartesian coordinates from cylindrical coordinates

    CO ( 7 ) = sqrt ( ( A .^ 2 ) + ( B .^ 2 ) ) ; % creates r variable from cartesian coordinates
    CO ( 8 ) = atan ( B ./ A ) ; % creares theta variable from cartesian cooadinates
    CO ( 9 ) = C ; % creates phi variable from cartesian coordinates

    CO ( 10 ) = sqrt ( ( A .^ 2 ) + ( B .^ 2 ) + ( C .^ 2 ) ) ; % creates r variable from cartesian coordinates
    CO ( 11 ) = atan ( sqrt ( ( A .^ 2 ) + ( B .^ 2 ) ) ./ C ) ; % creares theta variable from cartesian cooadinates
    CO ( 12 ) = atan ( B ./ A ) ; % creates phi variable from cartesian coordinates

    CO ( 13 ) = ( A ) .* cos ( B ) ; % creates x variable in cartesian coordinates from cylindrical coordinates
    CO ( 14 ) = ( A ) .* sin ( B ) ; % creates y variable in cartesian coordinates from cylindrical coordinates
    CO ( 15 ) = C ; % creates z variable in cartesian coordinates from cylindrical coordinates

    CO ( 16 ) = sqrt ( ( A .^ 2 ) + ( C .^ 2 ) ) ; % creates r variable from cartesian coordinates
    CO ( 17 ) = atan ( A ./ C ) ; % creares theta variable from cartesian cooadinates
    CO ( 18 ) = B ; % creates phi variable from cartesian coordinates

    CO ( 19 ) = ( A ) .* sin ( C ) .* cos ( B ) ; % creates x variable in cartesian coordinates from cylindrical coordinates
    CO ( 20 ) = ( A ) .* sin ( C ) .* sin ( B ) ; % creates y variable in cartesian coordinates from cylindrical coordinates
    CO ( 21 ) = ( A ) .* cos ( C ) ; % creates z variable in cartesian coordinates from cylindrical coordinates


    CO ( 22 ) = ( A ) .* sin ( C ) ; % creates x variable in cartesian coordinates from cylindrical coordinates
    CO ( 23 ) = ( B ) ; % creates y variable in cartesian coordinates from cylindrical coordinates
    CO ( 24 ) = ( A ) .* cos ( C ) ; % creates z variable in cartesian coordinates from cylindrical coordinates

    FU = sym ( '0' ) ; % preallocating
    for mu = 1 : 6 : 43

        FU ( mu ) = subs ( func , a , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 1 ) ) ;
        FU ( mu ) = subs ( FU ( mu ) , b , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 2 ) ) ;
        FU ( mu ) = subs ( FU ( mu ) , c , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 3 ) ) ;

        FU ( mu + 1 ) = subs ( func , a , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 1 ) ) ;
        FU ( mu + 1 ) = subs ( FU ( mu + 1 ) , b , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 3 ) ) ;
        FU ( mu + 1 ) = subs ( FU ( mu + 1 ) , c , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 2 ) ) ;

        FU ( mu + 2 ) = subs ( func , a , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 2 ) ) ;
        FU ( mu + 2 ) = subs ( FU ( mu + 2 ) , b , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 3 ) ) ;
        FU ( mu + 2 ) = subs ( FU ( mu + 2 ) , c , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 1 ) ) ;

        FU ( mu + 3 ) = subs ( func , a , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 2 ) ) ;
        FU ( mu + 3 ) = subs ( FU ( mu + 3 ) , b , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 1 ) ) ;
        FU ( mu + 3 ) = subs ( FU ( mu + 3 ) , c , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 3 ) ) ;

        FU ( mu + 4 ) = subs ( func , a , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 3 ) ) ;
        FU ( mu + 4 ) = subs ( FU ( mu + 4 ) , b , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 1 ) ) ;
        FU ( mu + 4 ) = subs ( FU ( mu + 4 ) , c , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 2 ) ) ;

        FU ( mu + 5 ) = subs ( func , a , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 3 ) ) ;
        FU ( mu + 5 ) = subs ( FU ( mu + 5 ) , b , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 2 ) ) ;
        FU ( mu + 5 ) = subs ( FU ( mu + 5 ) , c , CO ( ( ( ( ( ( ( mu + 2 ) / 3 ) + 1 ) / 2 ) - 1 ) * 3 ) + 1 ) ) ;
    end
    Fs = simple ( FU ) ;  % simplifies the result function row vector
end % end of if loop

ST = [ ] ; % preallocating of length string row vector
Fi = inline ( Fs ) ; % converts the result function row vector from class symbolic to class inline
Fc = char ( Fi ) ; % converts the result function row vector from class inline to class char
NU = strfind ( Fc , ' ') ; % finds the spaces in the string tha shows that the length of each function

for nu = 1 : length ( NU ) - 1 % i is the numerator of for loop
    ST ( nu + 1 ) = NU ( nu + 1 ) - NU ( nu ) ; % a row vector that shows the lenght of each function
end % end of for loop

ST ( 1 ) = NU ( 1 ) ; % first element of S vector

if p1 == 'S'
    [ MIN , MI ] = min ( ST ) ; % finds the function that has more simple relation between variables
elseif p1 == 'L'
    for i = 1 : length ( Fs )
        EU ( i ) = length ( argnames ( inline ( Fs ( i ) ) ) ) ; % finds the function that has less variables
    end % end of if loop
    [ MIN , MI ] = min ( EU ) ;
end % end of if loop

if p1 == 'M'
    if lengarg1 == 2 % used for two dimensional case
        if strcmp ( p2 , 'pol2cart' )
            MI = 5 ;
        elseif strcmp ( p2 , 'cart2pol' )
            MI = 7 ;
        end % end of if loop
    end % end of if loop
    
    if lengarg1 == 3 % used for three dimensional case
        if strcmp ( p2 , 'cart2cyl' ) % converts the input function from cartesian to cylindrical
            MI = 25 ;
        elseif strcmp ( p2 , 'cart2sph' ) % converts the input function from cartesian to spherical
            MI = 37 ;
        elseif strcmp ( p2 , 'cyl2sph' ) % converts the input function from cylindrical to spherical
            MI = 42 ;
        elseif strcmp ( p2 , 'cyl2cart' ) % converts the input function from cylindrical to cartesian
            MI = 13 ;
        elseif strcmp ( p2 , 'sph2cart' ) % converts the input function from spherical to cartesian
            MI = 19 ;
        elseif strcmp ( p2 , 'sph2cyl' ) % converts the input function from spherical to cylindrical
            MI = 31 ;
        end % end of if loop
    end % end of if loop
end % end of if loop

simsym = Fs ( MI ) ; % finds the result function in class symbolic

final = inline ( simsym ) ; % converts the result function from class symbolic to class inline

if strcmp( cla , 'inline') % if the user wants the result in class inline the output is in class inline
    sim = final ;
end % end of if loop

if strcmp( cla , 'char') % if the user wants the result in class char converts the output from class inline to class char
    sim = char ( final ) ; % converts returned function to class - char
end % end of if loop

arg2 = argnames ( final ) ; % creates the column vector of output variables
lengarg2 = length ( arg2 ) ; % counts the number of output variables

if strcmp( cla , 'sym') % if the user wants the result in class symbolic converts the output from class inline to class symbolic
    alpha = 'A' : 'Z' ; % creates a string from A to Z alphabetic letters
    if lengarg2 < 27 % checks that the number of arguments of given function is less than 27
        for nu = 1 : lengarg2 % a loop that converts all alphabetic letters from class char to class symbolic
            var = sym ( alpha ( nu ) ) ; % converts all alphabetic letters from class char to class symbolic
            sim = subs ( final , arg2 ( nu ) , var ) ; % substitutes all alphabetic variables in the given function for simplicity
        end % end of for loop
    end % end of if loop
end % end of if loop

if lengarg1 == 2 % used for two dimensional case
    if MI < 5 % if there is no change in the output from input shows it to user
        coor = 'Same with input function' ;
    elseif MI < 9 % if the output is in polar cordinates shows it to user
        coor = 'Cartesian' ;
    elseif MI < 13 % if the output is in cartesian cordinates shows it to user
        coor = 'Polar' ;
    end % end of if loop
end % end of if loop

if lengarg1 == 3 % used for three dimensional case
    if MI < 13 % if there is no change in the output from input shows it to user
        coor = 'Same with input function' ;
    elseif MI < 25 % if the output is in cartesian cordinates shows it to user
        coor = 'Cartesian' ;
    elseif MI < 37 % if the output is in cylindrical cordinates shows it to user
        coor = 'Cylindrical' ;
    elseif MI < 49 % if the output is in spherical cordinates shows it to user
        coor = 'Spherical' ;
    end % end of if loop
end % end of if loop

% With special thanks to John D'Errico
% By Ali Mohammad Razeghi

Contact us at files@mathworks.com