function c8vec_print_some ( n, x, max_print, title )

%*****************************************************************************80
%
%% C8VEC_PRINT_SOME prints some of a C8VEC.
%
%  Discussion:
%
%    The user specifies MAX_PRINT, the maximum number of lines to print.
%
%    If N, the size of the vector, is no more than MAX_PRINT, then
%    the entire vector is printed, one entry per line.
%
%    Otherwise, if possible, the first MAX_PRINT-2 entries are printed,
%    followed by a line of periods suggesting an omission,
%    and the last entry.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 September 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries of the vector.
%
%    Input, complex X(N), the vector to be printed.
%
%    Input, integer MAX_PRINT, the maximum number of lines to print.
%
%    Input, string TITLE, a title.
%
  if ( max_print <= 0 )
    return
  end

  if ( n <= 0 )
    return
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );
  fprintf ( 1, '\n' );

  if ( n <= max_print )

    for i = 1 : n
      fprintf ( 1, '  %6d:  %s\n', i, num2str ( x(i) ) );
    end

  elseif ( 3 <= max_print )

    for i = 1 : max_print-2
      fprintf ( 1, '  %6d: %s\n', i, num2str ( x(i) ) );
    end
    fprintf ( 1, '  ......  ..............\n' );
    i = n;
    fprintf ( 1, '  %6d: %s\n', i, num2str ( x(i) ) );

  else

    for i = 1 : max_print - 1;
      fprintf ( 1, '  %6d: %s\n', i, num2str ( x(i) ) );
    end
    i = max_print;
    fprintf ( 1, '  %6d: %s  ...more entries...\n', i, num2str ( x(i) ) );

  end

  return
end


function sequence_streak_display ( file_name, direction )

%*****************************************************************************80
%
%% SEQUENCE_STREAK_DISPLAY makes a "streak plot" of a sequence.
%
%  Discussion:
%
%    The sequence information is assumed to be available in
%    a text file, with one sequence entry per line.
%
%    One reason for making plots this way is to try to
%    see the "fill in" pattern of a sequence.  For instance,
%    the van der Corput sequence has the property that all
%    entries lie in [0,1], and that it first eliminates all
%    gaps of size 1/2, then of size 1/4, then 1/8 and so on.
%
%    Perhaps a second reason for looking at plots this way
%    is to notice patterns of convergence in a sequence.
%
%  Example:
%
%    The sequence 1, 3, 5, 7, 6, 2, 4 would plot as
%
%       *---
%        *--
%      *----
%          *
%     *-----
%         *-
%    *------
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 May 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string FILE_NAME, the name of a text file containing
%    the sequence.
%
%    Input, character DIRECTION, defines the direction of the sequence.
%    'R', goes to the right;
%    'L', goes to the left;
%    'U', goes up;
%    'D', goes down.
%
  timestamp ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'SEQUENCE_STREAK_DISPLAY\n' );
  fprintf ( 1, '  MATLAB version\n' );

  y = load ( file_name );

  n = length ( y );
  x(1:n) = 1:n;

  if ( direction == 'R' | direction == 'r' )

    plot ( x, y, '*' );

    for i = 1 : n
      line ( [x(i), n], [y(i), y(i) ] )
    end

    xlabel ( 'Sequence Direction--->', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16  )

    ylabel ( 'Sequence Value', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16, 'Rotation', 90 );

    title ( 'Sequence "Streak" Plot', ...
      'FontName', 'Helvetica', 'FontWeight', ...
      'bold', 'FontSize', 16 );

  elseif ( direction == 'L' | direction == 'l' )

    plot ( x, y, '*' );

    for i = 1 : n
      line ( [1, x(i)], [y(i), y(i) ] )
    end

    xlabel ( 'Sequence Direction--->', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16  )

    ylabel ( 'Sequence Value', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16, 'Rotation', 90 );

    title ( 'Sequence "Streak" Plot', ...
      'FontName', 'Helvetica', 'FontWeight', ...
      'bold', 'FontSize', 16 );

  elseif ( direction == 'U' | direction == 'u' )

    plot ( y, x, '*' );

    for i = 1 : n
      line ( [y(i), y(i) ], [x(i), n] )
    end

    xlabel ( 'Sequence Value', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16  )

    ylabel ( 'Sequence Direction--->', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16, 'Rotation', 90 );

    title ( 'Sequence "Streak" Plot', ...
      'FontName', 'Helvetica', 'FontWeight', ...
      'bold', 'FontSize', 16 );

  elseif ( direction == 'D' | direction == 'd' )

    plot ( y, x, '*' );

    for i = 1 : n
      line ( [y(i), y(i) ], [1, x(i)] )
    end

    xlabel ( 'Sequence Value', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16  )

    ylabel ( 'Sequence Direction--->', ...
      'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16, 'Rotation', 90 );

    title ( 'Sequence Streak Plot', ...
      'FontName', 'Helvetica', 'FontWeight', ...
      'bold', 'FontSize', 16 );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, 'SEQUENCE_STREAK_DISPLAY\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1,'\n' );
  timestamp ( );

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%  out.m           1993-12-28  %       FORMATED OUTPUT OF MATRICES
%%    (c)           M. Balda    %          updated on 2005-12-18
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%          updated on 2006-02-10
%
% The function out.m outputs its first argument to screen or a file in a
% default or required format. The argument can be either empty or a string,
% integer, real or complex numbers or matrices. The format can be either
% user defined or from a previous call of the function, or a default one.
%
% Prerequisity:
% ~~~~~~~~~~~~~
%   function inp.m from  http://www.mathworks.com/matlabcentral/
%
% Forms of calls:
% ~~~~~~~~~~~~~~
%
%   out;        %   Clear the format and close output file if any
%
%   out(arg);   %   Display arg in formats '%s or '%e' or '%d'
%               %   or any other used in the last call of out.m
%       arg   = an argument
%
%   out(arg,form);      %   Display arg in the format form
%       form  = required format of the output (see help to fprintf).
%               A format for complex numbers is generated internally using
%               format for real numbers,
%       fid   = file identifier - handle of the output file
%
%   out(arg,fid);       %   Append arg to the open file of fid handle
%
%   fid = out(arg,form,fname);  % Open file, get handle fid, and write arg
%       fname = name of output file
%       fid   = handle of the file if successfully opened,
%              -1 if not opened,
%               0 if closed.
%
%   out(arg,form,fid);  %   Append arg to fid file
%
% Examples:
% ~~~~~~~~
%  out(rand(2,3));              % display matrix in the '%15.6e' format
%  Z = rand(3,2)+i*rand(3,2);   % create complex matrix Z
%  h = out(Z,'','cmplxZ.dat');  % write Z in '%15.6e' format to the file
%  out('','%s\n',h);            % append new line into the file
%  out(Z,'%8.4f',h);            % append Z once more in '%8.4f' format
%  out;                         % close the file 'cmplxZ.dat'
%  lf = char(10);               % new line character
%  out(['This is a string' lf]);% display a string ending with new line
%  out(1:5,'%4i\n');            % display a column of integers
%  out(char('='*ones(1,50)),'%s\n');% display a line of 50 characters '='
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function fid = out(arg,form,fname)
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
persistent fid_ frm_

if nargin<1                     %   Close file & return
    fid = 0;
    if ~isempty(fid_) && fid_~=1
        fid  = fclose(fid_);
    end
    frm_ = [];
    return
end

%                               %   Format test & reconstruction
S = isempty(findstr('s',frm_));
if (ischar(arg) && S) || (isnumeric(arg) && ~S)
    frm_ = [];
end

%                               %   OUTPUT DESTINATION
fid_ = 1;                       %   screen
if nargin>2                     %   write in a file?
    if ischar(fname)             %   file name
        if exist(fname,'file')
            if strcmp(inp(['Overwrite ' fname '?'],'no'),'no')
                fid=-1;
                return          %   without overwriting
            end
        end
        fid_ = fopen(fname, 'w+');% open file
        fid  = fid_;
        if fid_<0, return, end
    else
        if isreal(fname)        %   file identifier
            fid_ = fname;
        end
    end
end

%                               %   OUTPUT FORMAT
if nargin>1
    if isempty(form)
        frm_ = [];
    elseif ischar(form)          %   format
        if isnumeric(arg)       %   for numeric arg
            if isempty(findstr(form,'-') + findstr(form,'+'))
                frmR_ = ['% ' form(2:end)]; %   real
                frmI_ = ['%+' form(2:end)]; %   imag
            else
                frmR_ = ['% ' form(3:end)]; %   real
                frmI_ = ['%+' form(3:end)]; %   imag
            end
            if ~isreal(arg)
                frm_ = [frmR_ frmI_ 'i  '];  %  complex
            else
                frm_ = frmR_;
            end
        else
            frm_ = form;        %   for string arg
        end
    else
        fid_ = form;            %   file identifier
    end
end

if isempty(frm_)
    if ischar(arg),        frm_ = '%s  ';
    elseif isinteger(arg), frm_ = '% d  ';
    elseif isreal(arg),    frm_ = '% e  ';
    else                   frm_ = '% e %+ei  ';
    end
end
%   disp({arg, frm_, fid_})

%                               %   OUTPUT arg
if ischar(arg)
    fprintf(fid_,frm_,arg);     %   text argument
else
    [m,n] = size(arg);
    if isreal(arg)              %   integer or real arg
        for k = 1:m
            for j = 1:n
                fprintf(fid_, frm_, arg(k,j));
            end
            fprintf(fid_,'\n');
        end
    else                        %   complex arg
        for k = 1:m
            Rc = real(arg(k,:));
            Ic = imag(arg(k,:));
            for j = 1:n
                fprintf(fid_, frm_, Rc(j), Ic(j));
            end
            fprintf(fid_,'\n');
        end
    end
end
fid = fid_;


%EASY4     The ephemeris file is reformated by rinexe. The observation type
%               is selected and the observation files for master and rover are opened.
%               The preliminary (X,Y,Z) position of the master receiver is read from
%               the header.
%               The reading position in the file is moved to the first epoch and
%               sow is computed. sow in master and rover files are synchronized.
%               We test if all SVs have an ephemris and SVs and their
%               observations are sorted to match. Next we call the function
%               baseline which computes the components of the baseline.
%              Some results are printed in workspace and some figures are plotted.

% The code could be shortened by introducing functions. However, for a
% teaching situation I found it more illustrative to compile a script.

%RINEX version 3.03

%Kai Borre 27-07-2002
%Copyright (c) by Kai Borre
%$Revision: 1.0 $  $Date: 2002/07/27  $
% Total revison 2.0, January 13, 2016

% Read RINEX ephemerides file and convert to internal Matlab format
rinexe('log_24h.15n','eph.dat');
Eph = get_eph('eph.dat');

% Selection of observation type
ss = 'C1W'%;

% Open the master observation file
ofile1 = 'log_24h.15o';
fid1 = fopen(ofile1,'rt');

% Open the rover observation file
ofile2 = 'log_r.15o'; % log_24h.15o
fid2 = fopen(ofile2,'rt');

coo = [];
ant_delta = [];
linjer = 0;

% Gobbling the master header, and collecting useful information
while 1
    linjer = linjer +1;
    line = fgetl(fid1);
    answer = strfind(line,'END OF HEADER');
    if  ~isempty(answer), break; end;
    if (line == -1), eof = 1; break; end;

    answer = strfind(line,'REC #');
    if ~isempty(answer)
        var = textscan(fid1,'%s %d14','Delimiter','\n');
        var1 = var{1}{1};
        cox = str2double(var1(1:14));
        coy = str2double(var1(15:28));
        coz = str2double(var1(29:42));
    end

    answer = strfind(line,'ANT #');
    if ~isempty(answer)
        var = textscan(fid1,'%s %d14','Delimiter','\n');
        var1 = var{1}{1};
        ax = str2double(var1(1:14));
        ay = str2double(var1(15:28));
        az = str2double(var1(29:42));
    end

    answer = strfind(line,'SYS / # / OBS TYPES');
    if ~isempty(answer)
        tline1 = strsplit(line);
        line = fgetl(fid1);
        tline2 = strsplit(line);
        tt1 = horzcat(tline1,tline2);
        i = strcmp(tt1,ss); % if tt equals ss, i =1, else 0
        ii = find(i == 1) ;
        ii = ii-2;
        if ii > 15,  ii = ii-7, end;
        % the cell array of strings tline1 originally contains two strings
        % which describe the system and number of observation types.
        % Both tline1 and tline2 terminates with six additional strings.
        % An extra string appears at  the start of tline2; it originates
        % from concatenation of the two lines. The indexing does not
        % change even if you empty the cells. They remain as empty
        % cells and keep a place
        obs_col = ii%;
    end;
    answer = strfind(line,'INTERVAL');
    if ~isempty(answer)
        interval = strtok(line);
        int = str2double(interval);
    end;
end % end reading header

% the string arrays for the tline1 and tline2 contain an integer after the
% carrier phase observation. We must account for this by the following
% correctional table
if         strcmp(ss(2:3), '1C'), obs_col = obs_col +1;
elseif  strcmp(ss(2:3), '1W'), obs_col = obs_col+2;
elseif strcmp(ss(2:3), '2X'), obs_col = obs_col +3;
else  strcmp(ss(2:3), '2W'), obs_col = obs_col +4;
end

Pos = [];
dt1 = [];
dt2 = [];
Gdop = [];
Omc = [];
bases = [];
epoch = 0;

while  1
    epoch = epoch +1;
    time1 = 0;
    sats1 = [];
    time2 = 0;
    sats2 = [];

    % Reading first observation record in master file.

    %  We read the first line in every epoch in the master file.
    % Output is sow nd number of SVs: NoSvs1.
    [time,~] = textscan(fid1,'%s %d8','Delimiter','\n');
    tid = time{1}{1};
    year = str2double(tid(3:6));
    month = str2double(tid(8:9));
    day = str2double(tid(11:12));
    hour = str2double(tid(14:15));
    minute = str2double(tid(17:18));
    second = str2double(tid(20:29));
    % static = str2double(tid(31:32));
    NoSvs1 = str2double(tid(34:36));
    dt1  = str2double(tid(38:56));
    h = hour+minute/60+second/3600;
    jd = julday(year, month, day, h);
    [~, sec_of_week] = gps_time(jd);
    time1 = sec_of_week; % sow1

    Obs1 = zeros(NoSvs1,length(obs_col));
    % Reading NoSvs1 lines of observations in the master file
    for i = 1:NoSvs1
        [obs1,~] = textscan(fid1,'%s %d8','Delimiter','\n');
        obs1x = obs1{1}{1} ;
        obs1y = strsplit(obs1x);
        sat1 = obs1y{1} ;
        sats1(i) = str2double(sat1(2:3));
        Obs1(i,:) = str2double(obs1y(obs_col));
    end

    % Next we test if all observed SVs have an ephemeris.
    % sats1 contains the SVs as read in the observation lines.
    % The intersect command delivers Sats in sorted order!
    % Therefore we must be careful in the follwing manipulations
    Sats = intersect(sats1,Eph(1,:));

    %The command ismember does not change the sequence of entries in sats1
    lia = ismember(sats1,Sats);
    % A 0 (zero) in lia indicates that a SV has been deleted. We delete the
    % corresponding row in the observations
    sats1(lia==0) = [];
    Obs1(lia==0) = [];
    NoSV1 = length(sats1);

    % dimensions
    % time1  % 1 x 1
    % NoSV1  % 1 x 1
    % sats1 % NoSV1 x 1
    % Obs1 % NoSV1 x 1

    % the whole story repated for the rover with index 2
    % we start by gobbeling the header
    if epoch == 1
        for qq = 1:linjer+ 3
            fgetl(fid2);
        end
    end

    % We read the header line for the first epoch in the rover file.
    % It gives us sow and number of SVs.
    [time,~] = textscan(fid2,'%s %d8','Delimiter','\n');
    tid = time{1}{1};
    year = str2double(tid(3:6));
    month = str2double(tid(8:9));
    day = str2double(tid(11:12));
    hour = str2double(tid(14:15));
    minute = str2double(tid(17:18));
    second = str2double(tid(20:29));
    % static = str2double(tid(31:32));
    NoSvs2 = str2double(tid(34:36));
    dt2  = str2double(tid(38:56));
    h = hour+minute/60+second/3600;
    jd = julday(year, month, day, h);
    [~, sec_of_week] = gps_time(jd);
    time2 = sec_of_week; % sow2

    % Reading the observations in the first epch in the rover file
    Obs2 = zeros(NoSvs2,length(obs_col));
    for i = 1:NoSvs2
        [obs2,~] = textscan(fid2,'%s %d8','Delimiter','\n');
        obs2y = obs2{1}{1};
        obs2 = strsplit(obs2y);
        sat2 = obs2{1};
        sats2(i,:) = str2double(sat2(2:3));
        Obs2(i,:) = str2double(obs2(obs_col));
    end

    % Next we test if all observed sats have an ephemeris.
    % sats contains the SVs as read in the observation lines
    % The intersect command delivers Sats in sorted order!
    % Therefore we must be careful in the follwing manipulations
    Sats = intersect(sats2,Eph(1,:));

    % The command ismember does not change the sequence of entries in sats
    lia = ismember(sats2,Sats);
    % A 0 (zero) in lia indicates that a SV has been deleted. We delete the
    % corresponding row in the observations
    sats2(lia==0) = [];
    Obs2(lia==0) = [];
    NoSV2 = length(sats2);

    % dimensions
    % time2  % 1 x 1
    % NoSV2  % 1 x 1
    % sats2   % NoSV2 x 1
    % Obs2  % NoSV2 x  1

    if epoch == 1
        % Establish synchronous reading of fid1 and fid2
        % The epoch interval is int seconds
        if  time1 > time2
            for i = 1: round(time1-time2)
                 [time,~] = textscan(fid2,'%s %d8','Delimiter','\n');
                tid = time{1}{1};
                year = str2double(tid(3:6));
                month = str2double(tid(8:9));
                day = str2double(tid(11:12));
                hour = str2double(tid(14:15));
                minute = str2double(tid(17:18));
                second = str2double(tid(20:29));
                %static = str2double(tid(31:32));
                NoSvs2 = str2double(tid(34:36));
                dt2  = str2double(tid(38:56));
                h = hour+minute/60+second/3600;
                jd = julday(year, month, day, h);
                [~, sec_of_week] = gps_time(jd);
                time2 = sec_of_week; % sow2

                for qq = 1:NoSvs2
                    fgetl(fid2);
                end
            end % i
        end % if time1 ...

        if  time1 < time2
            for i = 1: round(time2-time1)
                [time, ~] = textscan(fid1,'%s %d8','Delimiter','\n');
                tid = time{1}{1};
                year = str2double(tid(3:6));
                month = str2double(tid(8:9));
                day = str2double(tid(11:12));
                hour = str2double(tid(14:15));
                minute = str2double(tid(17:18));
                second = str2double(tid(20:29));
                static = str2double(tid(31:32));
                NoSvs1 = str2double(tid(34:36));
                dt1  = str2double(tid(38:56));
                h = hour+minute/60+second/3600;
                jd = julday(year, month, day, h);
                [~, sec_of_week] = gps_time(jd);
                time1 = sec_of_week; % sow1

                for qq = 1:NoSvs1
                    fgetl(fid1);
                end
            end % i
        end % if time1
        fprintf('First Common Epoch Time1 :  %8.0f\n', time1)
        fprintf('First Common Epoch Time2 :  %8.0f\n', time2)
    end % synchronization

    % By chance sats1 and sats 2 are the same. Otherwise we need to establish
    % a matching between sats1 and sats2 and likewise for Obs1 and Obs2

    % master observations: obs1, and rover observations: obs2
    [omc,base] = baseline([cox;coy;coz],Obs1,Obs2,sats1,time1,Eph);
    Omc = [Omc, omc];
    bases = [bases base];

    [pos, el, gdop] = recpo_ls(Obs1,sats1,time1,Eph);
    Gdop = [Gdop gdop];
    Pos = [Pos pos];
    if feof(fid1) == 1, break, end;
    if feof(fid2) == 1, break; end;
end % while
fclose all;

me1 = mean(bases,2);
spread1 = std(bases,1,2);
fprintf('\nBaseline Components as Computed From %2.0f Epochs:', epoch)
fprintf('\n\nX: %12.3f  Y: %12.3f  Z: %12.3f\n\n', me1(1,1),me1(2,1),me1(3,1))

figure(1);
plot((bases(:,2:end)-bases(:,2)*ones(1,epoch-1))','linewidth',.25)
title(['Variation of Baseline Components Over ',int2str(epoch),' Epochs'],'fontsize',14)
legend('X','Y','Z')
xlabel(['Epochs ', int2str(int), ' s interval'], 'fontsize',14)
ylabel('[m]','fontsize',14)
set(gca,'fontsize',14)
legend
print -dpdf easy41

figure(2);
plot(Omc(:,2:end)')
xlabel('Epochs')
ylabel('[m]','fontsize',14)
title({'Observed minus Computed Values'; 'for All SVs in Each Epoch'},'fontsize',14)
set(gca,'fontsize',14)
print -dpdf easy42

figure(3);
plot(Gdop,'linewidth',1)
axis([1 length(Gdop) 0 5])
title('GDOP')
print -dpdf easy43

%%%%%%%%%%%%%% end easy4.m %%%%%%%%%%%%%%%


% THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION IS RELEASED "AS IS."  THE U.S. GOVERNMENT MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY DAMAGES, INCLUDING ANY LOST PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
%
% file: binopdf_01ok.m
% The regular binopdf returns NaN whenever x=0 and p=0 or whenever
%   x=n and p=1.  The correct value for binopdf to return in both cases is 1.0.
% This corrects that bug.
% This also avoids calling binopdf when it would give an inappropriate warning
%   about taking the log of zero.
% This could more easily be fixed within binopdf.m, but that for MathWorks
%
% 022400 tdr created
% 033100 tdr added check for binopdf returning NaN or Inf, which it may for n > 1000, e.g., x=500, n=1030, p=0.1

function y = binopdf_01ok(x,n,p)

if nargin < 3,
    error('Requires three input arguments (x,n,p)');
end

[errorcode x n_bar p] = distchck(3,x,n,p);

if errorcode > 0
    error('Requires non-scalar arguments to match in size.');
end

y = zeros(size(x));

k = find(~((p == 0) | (p == 1)));
if any(k),
   y(k) = binopdf(x(k),n,p(k));
   if ~isfinite(y),
      error('NaN or Inf value returned from binopdf.m')
   end;
end

k = find((x ~= 0 & p == 0) | (x ~= n & p == 1));
if any(k),
   y(k) = 0;
end

k = find((x == 0 & p == 0) | (x == n & p == 1));
if any(k),
   y(k) = 1;
end


function hydro = combineBEM(hydro)
% Combines multiple BEM outputs into one hydrodynamic ‘system.’ This function
% requires that all BEM outputs have the same water depth, wave frequencies,
% and wave headings. This function would be implemented following multiple
% readWAMIT, readNEMOH, readCAPYTAINE, or readAQWA and before radiationIRF,
% radiationIRFSS, excitationIRF, writeBEMIOH5, or plotBEMIO function calls.
%
% See ``WEC-Sim\examples\BEMIO\NEMOH`` for examples of usage.
%
% Parameters
% ----------
%     hydro : [1 x n] struct
%         Structures of hydro data that will be combined into a single
%         structure
%
% Returns
% -------
%     hydro : [1 x 1] struct
%         Combined structure.

p = waitbar(0,'Combining multiple BEM results...');  % Progress bar

[m,n] = size(hydro);
tol = 1e-2;
if n>1
    for i = 2:n
        if max(abs(hydro(i).h-hydro(i-1).h)) > tol
            error('Error: Inconsistent water depth');
        elseif (size(hydro(i).theta) ~= size(hydro(i-1).theta)) | ...
                (max(abs(sort(hydro(i).theta)-sort(hydro(i-1).theta))) > tol)
            error('Error: Inconsistent wave headings');
        elseif (size(hydro(i).T) ~= size(hydro(i-1).T)) | ...
                (max(abs(sort(hydro(i).T)-sort(hydro(i-1).T))) > tol)
            error('Error: Inconsistent wave frequencies');
        end
    end

    n = n+1;
    hydro(n).theta = hydro(1).theta;
    hydro(n).body = [];
    hydro(n).Khs = [];
    hydro(n).cb = [];
    hydro(n).cg = [];
    hydro(n).code = [];
    hydro(n).dof = [];
    hydro(n).ex_im = [];
    hydro(n).ex_ma = [];
    hydro(n).ex_ph = [];
    hydro(n).ex_re = [];
    hydro(n).fk_im = [];
    hydro(n).fk_ma = [];
    hydro(n).fk_ph = [];
    hydro(n).fk_re = [];
    hydro(n).sc_im = [];
    hydro(n).sc_ma = [];
    hydro(n).sc_ph = [];
    hydro(n).sc_re = [];
    hydro(n).file = [];
    hydro(n).g = 9.807;
    hydro(n).h = hydro(1).h;
    hydro(n).Nb = 0;
    hydro(n).Nf = hydro(1).Nf;
    hydro(n).Nh = hydro(1).Nh;
    hydro(n).rho = 1000;
    hydro(n).T = hydro(1).T;
    hydro(n).Vo = [];
    hydro(n).w = hydro(1).w;
    for i = 1:(n-1)
        hydro(n).body = [hydro(n).body, hydro(i).body];
        hydro(n).Khs = cat(3, hydro(n).Khs, hydro(i).Khs);
        hydro(n).cb = [hydro(n).cb, hydro(i).cb];
        hydro(n).cg = [hydro(n).cg, hydro(i).cg];
        hydro(n).code = [hydro(n).code, hydro(i).code];
        hydro(n).dof = [hydro(n).dof, hydro(i).dof];
        hydro(n).ex_im = cat(1, hydro(n).ex_im, hydro(i).ex_im);
        hydro(n).ex_ma = cat(1, hydro(n).ex_ma, hydro(i).ex_ma);
        hydro(n).ex_ph = cat(1, hydro(n).ex_ph, hydro(i).ex_ph);
        hydro(n).ex_re = cat(1, hydro(n).ex_re, hydro(i).ex_re);
        hydro(n).fk_im = cat(1, hydro(n).fk_im, hydro(i).fk_im);
        hydro(n).fk_ma = cat(1, hydro(n).fk_ma, hydro(i).fk_ma);
        hydro(n).fk_ph = cat(1, hydro(n).fk_ph, hydro(i).fk_ph);
        hydro(n).fk_re = cat(1, hydro(n).fk_re, hydro(i).fk_re);
        hydro(n).sc_im = cat(1, hydro(n).sc_im, hydro(i).sc_im);
        hydro(n).sc_ma = cat(1, hydro(n).sc_ma, hydro(i).sc_ma);
        hydro(n).sc_ph = cat(1, hydro(n).sc_ph, hydro(i).sc_ph);
        hydro(n).sc_re = cat(1, hydro(n).sc_re, hydro(i).sc_re);
        hydro(n).file = [hydro(n).file, hydro(i).file];
        hydro(n).Nb = hydro(n).Nb + hydro(i).Nb;
        hydro(n).Vo = [hydro(n).Vo, hydro(i).Vo];
    end
    hydro(n).Ainf = zeros(sum(hydro(n).dof),sum(hydro(n).dof));
    hydro(n).A = zeros(sum(hydro(n).dof),sum(hydro(n).dof),hydro(n).Nf);
    hydro(n).B = zeros(sum(hydro(n).dof),sum(hydro(n).dof),hydro(n).Nf);
    if isfield(hydro,'gbm')==1
        hydro(n).gbm = zeros(sum(hydro(n).dof),sum(hydro(n).dof),4);
    end
    k = 0;
    for i = 1:(n-1)
        j = sum(hydro(i).dof);
        hydro(n).Ainf((k+1):(k+j),(k+1):(k+j)) = hydro(i).Ainf;
        hydro(n).A((k+1):(k+j),(k+1):(k+j),:) = hydro(i).A;
        hydro(n).B((k+1):(k+j),(k+1):(k+j),:) = hydro(i).B;
        if isfield(hydro,'gbm')==1
            hydro(n).gbm((k+1):(k+j),(k+1):(k+j),:) = hydro(i).gbm;
        end
        k = k + j;
    end

    hydro(1) = hydro(n);
    hydro(2:n) = [];

end
close(p);
end


function varargout = newton_Raphson_GUI(varargin)
% NEWTON_RAPHSON_GUI M-file for newton_Raphson_GUI.fig
%      NEWTON_RAPHSON_GUI, by itself, creates a new NEWTON_RAPHSON_GUI or raises the existing
%      singleton*.
%
%      H = NEWTON_RAPHSON_GUI returns the handle to a new NEWTON_RAPHSON_GUI or the handle to
%      the existing singleton*.
%
%      NEWTON_RAPHSON_GUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in NEWTON_RAPHSON_GUI.M with the given input arguments.
%
%      NEWTON_RAPHSON_GUI('Property','Value',...) creates a new NEWTON_RAPHSON_GUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before newton_Raphson_GUI_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to newton_Raphson_GUI_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help newton_Raphson_GUI

% Last Modified by GUIDE v2.5 09-Sep-2013 22:52:08

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @newton_Raphson_GUI_OpeningFcn, ...
                   'gui_OutputFcn',  @newton_Raphson_GUI_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin & isstr(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before newton_Raphson_GUI is made visible.
function newton_Raphson_GUI_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to newton_Raphson_GUI (see VARARGIN)

% Choose default command line output for newton_Raphson_GUI
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes newton_Raphson_GUI wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = newton_Raphson_GUI_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

% --- Executes during object creation, after setting all properties.
function f_CreateFcn(hObject, eventdata, handles)
% hObject    handle to f (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function f_Callback(hObject, eventdata, handles)
% hObject    handle to f (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of f as text
%        str2double(get(hObject,'String')) returns contents of f as a double

% --- Executes on button press in plot.
function plot_Callback(hObject, eventdata, handles)
syms x;
fun=(x.^2)-1;
ezplot(fun);
% hObject    handle to plot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --- Executes during object creation, after setting all properties.
function x0_CreateFcn(hObject, eventdata, handles)
% hObject    handle to x0 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function x0_Callback(hObject, eventdata, handles)
% hObject    handle to x0 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of x0 as text
%        str2double(get(hObject,'String')) returns contents of x0 as a double

% --- Executes during object creation, after setting all properties.
function edit3_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function edit3_Callback(hObject, eventdata, handles)
% hObject    handle to edit3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit3 as text
%        str2double(get(hObject,'String')) returns contents of edit3 as a double

% --- Executes during object creation, after setting all properties.
function edit5_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function edit5_Callback(hObject, eventdata, handles)
% hObject    handle to edit5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit5 as text
%        str2double(get(hObject,'String')) returns contents of edit5 as a double

% --- Executes on button press in solve.
function solve_Callback(hObject, eventdata, handles)

xi=str2num(get(handles.x0,'string'));

for i=1:20

xn=xi-(polyval([1 0 -1],[xi])/polyval(polyder([1 0 -1]),[xi]));
disp(xn);
set(handles.r,'string',xn);
xi=xn;
i=i+1;

end
% hObject    handle to solve (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


function [bcx,bcy] = specific_flow(xbd,ybd)
%leakycavity_flow   Reference problem 5.3 inflow condition
%   [bcx,bcy] = specific_flow(xbd,ybd);
%   input
%          xbd          x coordinate vector
%          ybd          y coordinate vector
%
%   specifies leaky cavity flow boundary condition
%   IFISS function: DJS; 6 March 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
bcx=0*xbd; bcy=0*xbd;
k=find(ybd==1); bcx(k)=1;
return


function dy = scopy ( n, dx, incx, dy, incy )

%*****************************************************************************80
%
%% SCOPY copies a vector X to a vector Y.
%
%  Discussion:
%
%    The routine uses unrolled loops for increments equal to one.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 May 2006
%
%  Author:
%
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979.
%
%    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
%    Basic Linear Algebra Subprograms for Fortran Usage,
%    Algorithm 539,
%    ACM Transactions on Mathematical Software,
%    Volume 5, Number 3, September 1979, pages 308-323.
%
%  Parameters:
%
%    Input, integer N, the number of elements in DX and DY.
%
%    Input, real DX(*), the first vector.
%
%    Input, integer INCX, the increment between successive entries of DX.
%
%    Input, real DY(*), the second vector, into which elements are copied.
%
%    Input, integer INCY, the increment between successive entries of DY.
%
%    Output, real DY(*), the second vector, with elements copied from DX.
%
  if ( n <= 0 )
    dy = [];
    return
  end

  if ( incx == 1 & incy == 1 )

    m = mod ( n, 7 );

    if ( m ~= 0 )

      dy(1:m) = dx(1:m);

    end

    for i = m+1 : 7 : n
      dy(i) = dx(i);
      dy(i + 1) = dx(i + 1);
      dy(i + 2) = dx(i + 2);
      dy(i + 3) = dx(i + 3);
      dy(i + 4) = dx(i + 4);
      dy(i + 5) = dx(i + 5);
      dy(i + 6) = dx(i + 6);
    end

  else

    if ( 0 <= incx )
      ix = 1;
    else
      ix = ( -n + 1 ) * incx + 1;
    end

    if ( 0 <= incy )
      iy = 1;
    else
      iy = ( -n + 1 ) * incy + 1;
    end

    for i = 1 : n
      dy(iy) = dx(ix);
      ix = ix + incx;
      iy = iy + incy;
    end

  end

  return
end


function x = rosser1_null_right ( )

%*****************************************************************************80
%
%% ROSSER1_NULL_RIGHT returns a right null vector of the ROSSER1 matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real X(8,1), the null vector.
%
  x = [ ...
    1.0; ...
    2.0; ...
   -2.0; ...
   -1.0; ...
   14.0; ...
   14.0; ...
    7.0; ...
    7.0 ];

  return
end


function fd1d_display ( prefix )

%*****************************************************************************80
%
%% FD1D_DISPLAY displays data for a 1D finite difference function.
%
%  Discussion:
%
%    The function is represented as the sum of piecewise linear functions.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Usage:
%
%    fd1d_display ( 'prefix' )
%
%    where
%
%    'prefix_nodes.txt'    contains the point coordinates;
%    'prefix_values.txt'   contains the point values.
%
%  Parameters:
%
%    Input, string PREFIX, the prefix of the input files.
%
  fprintf ( 1, '\n' );
  timestamp ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'FD1D_DISPLAY\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read files defining a finite difference computatation,\n' );
  fprintf ( 1, '  involving a set of nodes, and values of one or more\n' );
  fprintf ( 1, '  functions at those nodes.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Plot the functions in a MATLAB graphics window.\n' );
%
%  First argument is the file prefix.
%
  if ( nargin < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FD1D_DISPLAY:\n' );
    prefix = input ( '  Enter the common prefix of the files (in ''quotes''!).\n' );
  end
%
%  Get the node coordinates.
%
  node_filename = strcat ( prefix, '_nodes.txt' );
  node_x = load ( node_filename );
%
%  Get the function data.
%
  value_filename = strcat ( prefix, '_values.txt' );
  node_value = load ( value_filename );
%
%  Make the plot.
%
  clf

  plot ( node_x, node_value )
  hold on
  plot ( node_x, node_value, '*' )

  grid

  title_string = s_escape_tex ( prefix );
  title ( title_string );
  xlabel ( 'X axis' );
  ylabel ( 'Function values' );

  hold off
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FD1D_DISPLAY\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function s2 = s_escape_tex ( s1 )

%*****************************************************************************80
%
%% S_ESCAPE_TEX de-escapes TeX escape sequences.
%
%  Discussion:
%
%    In particular, every occurrence of the characters '\', '_',
%    '^', '{' and '}' will be replaced by '\\', '\_', '\^',
%    '\{' and '\}'.  A TeX interpreter, on seeing these character
%    strings, is then likely to return the original characters.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 January 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S1, the string to be de-escaped.
%
%    Output, string S2, a copy of the string, modified to avoid TeX escapes.
%
  s1_length = length ( s1 );

  s1_pos = 0;
  s2_pos = 0;
  s2 = [];

  while ( s1_pos < s1_length )

    s1_pos = s1_pos + 1;

    if ( s1(s1_pos) == '\' | ...
         s1(s1_pos) == '_' | ...
         s1(s1_pos) == '^' | ...
         s1(s1_pos) == '{' | ...
         s1(s1_pos) == '}' )
      s2_pos = s2_pos + 1;
      s2 = strcat ( s2, '\' );
    end

    s2_pos = s2_pos + 1;
    s2 = strcat ( s2, s1(s1_pos) );

  end

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


%% Reference Frame Alignment
%
%%
% The most important difference between MTEX and many other EBSD software
% is that in MTEX the Euler angle reference is always the map reference
% frame. This mean the $x$ and $z$ axes of the map are exactly the rotation
% axes of the Euler angles.
%
% In case the map coordinates and the Euler angles in your data are with
% respect to different reference frames it is highly recommended to correct
% for this while importing the data into MTEX. This section explains in
% detail how to do this.
%
%% On Sreen Orientation of the EBSD Map
%
% Many people are concerned when the images produced by MTEX are not
% aligned exactly as they are in their commercial software. It is indeed
% very important to understand exactly the alignment of your data. However,
% the important point is not whether a map is upside down on your screen or
% not. The important point is how your map aligns with the specimen, as we
% want to use the map to describe properties of the specimen.
%
% There are basically two components in an EBSD data set that refer to the
% specimen reference frame: the spatial coordinates $x$, $y$ and the Euler
% angles $\phi_1$, $\Phi$, $\phi_2$. To explain the difference have a look
% at the EDAX export dialog
%
% <<edax_coordinate_systems.png>>
%
% Here we have the axes $x$ and $y$ which describe how the map coordinates
% needs to be interpreted and the axes $A_1$, $A_2$, $A_3$ which describe
% how the Euler angles, and in consequence, the pole figures needs to be
% interpreted. We see that in none of these settings the map reference
% system coincides with the Euler angle reference frame.
%
% This situation is not specific to EDAX but occurs as well with EBSD data
% from Oxford or Bruker, all of them using different reference system
% alignments. For that reason MTEX strongly recommends to transform the data
% such that both map coordinates and Euler angles refer to the same
% coordinate system.
%
% Doing this we have two choices:
%
% # transform everything to the reference system $x$, $y$ using the option
% |'convertEuler2SpatialReferenceFrame'|. This will keep the map
% coordinates while changing the Euler angles
% # transform everything to the reference system $A_1$, $A_2$, $A_3$ using
% the option |'convertSpatial2EulerReferenceFrame'|. This will keep the
% Euler angles while changing the map coordinates.
%
% In the case of EDAX data imported from an |*.ang| file we still need to
% specify the export option used by the EDAX software. This is done by the
% options |'setting 1'|, |'setting 2'|, |'setting 3'| or |'setting 4'|.
%
% Since setting 2 is default for most EDAX exports a typical command for
% importing data from an ang file would look like this

ebsd = EBSD.load([mtexEBSDPath filesep 'olivineopticalmap.ang'],...
  'convertEuler2SpatialReferenceFrame','setting 2')

plot(ebsd('olivine'),ebsd('olivine').orientations,'coordinates','on')

%%
% The plot does not yet fit the alignment of the map in the EDAX software
% as it plots the x-axis be default to east and the z-axis into the plane.
% This is only a plotting convention and can be set in MTEX by

plotx2east
plotzIntoPlane

plot(ebsd('olivine'),ebsd('olivine').orientations,'coordinates','on')

%%
% Other plotting conventions are |plotx2north|, |plotx2west|, |plotx2south|
% and |plotzOutOfPlane|. Note that these options only alter the orientation
% of the EBSD map and the pole figures on the screen but does not change
% any data.
%
%% Verify the reference system
% One way of verifying the reference systems is to visualize crystal shapes
% on top of the orientation map. To do this we proceed as follows

% reconstruct grains
grains = calcGrains(ebsd('indexed'));

% chose the correct crystal shape (cubic, hex are generic forms)
cS = crystalShape.olivine;

% select only large grains
largeGrains = grains(grains.grainSize>500)

% and plot the crystal shapes
hold on
plot(largeGrains,cS)
hold off

%%
% It may also be helpful to inspect pole figures

h = Miller({1,0,0},{0,1,0},{0,0,1},ebsd('O').CS);
plotPDF(ebsd('O').orientations,h,'contourf')

%%
% As pole figures display data relative to the specimen reference frame
% MTEX automatically aligns them on the screen exactly as the spatial map
% above, i.e., according to our last definition with x pointing towards
% east and y to the south.
%
%% Change the map reference system
% In order to manually change the map reference frame one may apply a
% rotation to the map coordinates only. E.g. to flip the map left to right
% while preserving the Euler angles one can do

rot = rotation.byAxisAngle(yvector,180*degree);
ebsd_rot = rotate(ebsd,rot,'keepEuler');

% reconstruct grains
grains = calcGrains(ebsd_rot('indexed'));

% select only large grains
largeGrains = grains(grains.grainSize>500);

plot(ebsd_rot('olivine'),ebsd_rot('olivine').orientations,'coordinates','on')

% and plot the crystal shapes
hold on
plot(largeGrains,cS)
hold off

%% Change the Euler angle reference system
% Analogously we may change the Euler angle reference frame while keeping
% the map coordinates

ebsd_rot = rotate(ebsd,rot,'keepXY');

% reconstruct grains
grains = calcGrains(ebsd_rot('indexed'));

% select only large grains
largeGrains = grains(grains.grainSize>500);

plot(ebsd_rot('olivine'),ebsd_rot('olivine').orientations,'coordinates','on')

% and plot the crystal shapes
hold on
plot(largeGrains,cS)
hold off

%% Changing both reference system simultaneously
%
% Sometimes it is necessary to relate the EBSD data to a different external
% reference frame, or to  change the external reference frame from one to
% the other, e.g. if one wants to concatenate several ebsd data sets where
% the mounting was not done in perfect coincidence. In these cases the data
% has to be rotated or shifted by the commands <EBSD.rotate.html rotate>
% and <EBSD.shift.html shift>. The following commands rotate both reference
% frames of the entire data set by 5 degree about the z-axis.

% define a rotation
rot = rotation.byAxisAngle(zvector,5*degree);

% rotate the EBSD data
ebsd_rot = rotate(ebsd,rot);

% reconstruct grains
grains = calcGrains(ebsd_rot('indexed'));

% select only large grains
largeGrains = grains(grains.grainSize>500);

plot(ebsd_rot('olivine'),ebsd_rot('olivine').orientations,'coordinates','on')

% and plot the crystal shapes
hold on
plot(largeGrains,cS)
hold off


function [bcx,bcy] = specific_flow(xbd,ybd)
%tightcavity_flow   Reference problem 5.3 alternative inflow condition
%   [bcx,bcy] = specific_flow(xbd,ybd);
%   input
%          xbd          x coordinate vector
%          ybd          y coordinate vector
%
%   specifies watertight cavity flow boundary condition
%   IFISS function: DJS; 6 March 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
bcx=0*xbd; bcy=0*xbd;
k=find(ybd==1 & xbd>-1 & xbd<1); bcx(k)=1;
return


function next = next_boundary_node_q9 ( node )

%*****************************************************************************80
%
%% NEXT_BOUNDARY_NODE_Q9 returns the next boundary node in a Q9 element.
%
%  Reference Element Q9:
%
%    |
%    1  4--7--3
%    |  |     |
%    |  |     |
%    S  8  9  6
%    |  |     |
%    |  |     |
%    0  1--5--2
%    |
%    +--0--R--1-->
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE, the index of the current node.  An input
%    value of 0 (or any "unusual" value") indicates that the
%    first edge node is desired.
%
%    Output, integer NEXT, the index of the next edge node.
%
  if ( node == 1 )
    next = 5;
  elseif ( node == 5 )
    next = 2;
  elseif ( node == 2 )
    next = 6;
  elseif ( node == 6 )
    next = 3;
  elseif ( node == 3 )
    next = 7;
  elseif ( node == 7 )
    next = 4;
  elseif ( node == 4 )
    next = 8;
  else
    next = 1;
  end

  return
end


function exact = p00_exact ( problem, dim_num )

%*****************************************************************************80
%
%% P00_EXACT returns the exact integral for any problem.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer PROBLEM, the number of the desired test problem.
%
%    Input, integer DIM_NUM, the dimension of the problem.
%
%    Output, real EXACT, the exact value of the integral.
%
  if ( problem == 1 )
    exact = p01_exact ( dim_num );
  elseif ( problem == 2 )
    exact = p02_exact ( dim_num );
  elseif ( problem == 3 )
    exact = p03_exact ( dim_num );
  elseif ( problem == 4 )
    exact = p04_exact ( dim_num );
  elseif ( problem == 5 )
    exact = p05_exact ( dim_num );
  elseif ( problem == 6 )
    exact = p06_exact ( dim_num );
  elseif ( problem == 7 )
    exact = p07_exact ( dim_num );
  elseif ( problem == 8 )
    exact = p08_exact ( dim_num );
  elseif ( problem == 9 )
    exact = p09_exact ( dim_num );
  elseif ( problem == 10 )
    exact = p10_exact ( dim_num );
  elseif ( problem == 11 )
    exact = p11_exact ( dim_num );
  elseif ( problem == 12 )
    exact = p12_exact ( dim_num );
  elseif ( problem == 13 )
    exact = p13_exact ( dim_num );
  elseif ( problem == 14 )
    exact = p14_exact ( dim_num );
  elseif ( problem == 15 )
    exact = p15_exact ( dim_num );
  elseif ( problem == 16 )
    exact = p16_exact ( dim_num );
  elseif ( problem == 17 )
    exact = p17_exact ( dim_num );
  elseif ( problem == 18 )
    exact = p18_exact ( dim_num );
  elseif ( problem == 19 )
    exact = p19_exact ( dim_num );
  elseif ( problem == 20 )
    exact = p20_exact ( dim_num );
  elseif ( problem == 21 )
    exact = p21_exact ( dim_num );
  elseif ( problem == 22 )
    exact = p22_exact ( dim_num );
  elseif ( problem == 23 )
    exact = p23_exact ( dim_num );
  elseif ( problem == 24 )
    exact = p24_exact ( dim_num );
  elseif ( problem == 25 )
    exact = p25_exact ( dim_num );
  elseif ( problem == 26 )
    exact = p26_exact ( dim_num );
  elseif ( problem == 27 )
    exact = p27_exact ( dim_num );
  elseif ( problem == 28 )
    exact = p28_exact ( dim_num );
  elseif ( problem == 29 )
    exact = p29_exact ( dim_num );
  elseif ( problem == 30 )
    exact = p30_exact ( dim_num );
  elseif ( problem == 31 )
    exact = p31_exact ( dim_num );
  elseif ( problem == 32 )
    exact = p32_exact ( dim_num );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'P00_EXACT - Fatal error!\n' );
    fprintf ( 1, '  Illegal problem number = %d\n', problem );
    error ( 'P00_EXACT - Fatal error!' );
  end

  return
end


function line = sphere_llq_grid_lines ( nlat, nlong, line_num )

%*****************************************************************************80
%
%% SPHERE_LLQ_GRID_LINES returns lines for an LLQ grid on a sphere.
%
%  Discussion:
%
%    A SPHERE LLQ grid imposes a grid of quadrilaterals on a sphere,
%    using latitude and longitude lines.
%
%    The point numbering system is the same used in SPHERE_LLQ_GRID_POINTS,
%    and that routine may be used to compute the coordinates of the points.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 April 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NLAT, NLONG, the number of latitude and longitude
%    lines to draw.  The latitudes do not include the North and South
%    poles, which will be included automatically, so NLAT = 5, for instance,
%    will result in points along 7 lines of latitude.
%
%    Input, integer LINE_NUM, the number of grid lines.
%
%    Output, integer LINE(LINE_NUM,2), contains pairs of point indices for
%    line segments that make up the grid.
%
  l = 0;
  line = zeros ( line_num, 2 );
%
%  "Vertical" lines.
%
  for j = 0 : nlong - 1

    old = 1;
    new = j + 2;
    l = l + 1;
    line(l,1:2) = [ old, new ];

    for i = 1 : nlat - 1

      old = new;
      new = old + nlong;
      l = l + 1;
      line(l,1:2) = [ old, new ];

    end

    old = new;
    l = l + 1;
    line(l,1:2) = [ old, 1 + nlat * nlong + 1 ];

  end
%
%  "Horizontal" lines.
%
  for i = 1 : nlat

    new = 1 + ( i - 1 ) * nlong + 1;

    for j = 0 : nlong - 2
      old = new;
      new = old + 1;
      l = l + 1;
      line(l,1:2) = [ old, new ];
    end

    old = new;
    new = 1 + ( i - 1 ) * nlong + 1;
    l = l + 1;
    line(l,1:2) = [ old, new ];

  end

  return
end


%% abaqusStruct2inp
% Below is a demonstration of the features of the |abaqusStruct2inp| function

%%
clear; close all; clc;

%% Syntax
% |[T]=abaqusStruct2inp(abaqus_spec,fileName,optionStruct);|

%% Description
% This function provides the basis for coding Abaqus .inp input files

%%
% See also: |abaqusStructTemplate|

%% About Abaqus INP input files
% Abaqus input files (.inp) are plain text files.

%% Coding INP files in MATLAB

%%
% Specify file heading
% Users may provide a heading which can be used to give a description of
% the input file.

% *Heading
% ** Job name: ABAQUS inp file creation demo
% ** Generated by: GIBBON

abaqus_spec.Heading.COMMENT{1}='Job name: ABAQUS inp file creation demo';
abaqus_spec.Heading.COMMENT{2}='Generated by: GIBBON';

%%
% The preprint section
%

% *Preprint, echo=NO, model=NO, history=NO, contact=NO
abaqus_spec.Preprint.ATTR.echo='NO';
abaqus_spec.Preprint.ATTR.model='NO';
abaqus_spec.Preprint.ATTR.history='NO';
abaqus_spec.Preprint.ATTR.contact='NO';

%%
% The part section

V=[ 1 1 1; 1 0 1;  1 1 0; 1 0 0; 0 1 1; 0 0 1; 0 1 0; 0 0 0];

nodeIds=(1:1:size(V,1));
E=[5 6 8 7 1 2 4 3];
elementIds=(1:1:size(E,1));

% Node
abaqus_spec.Part{1}.COMMENT='This section defines the part geometry in terms of nodes and elements';
abaqus_spec.Part{1}.ATTR.name='Cube';
abaqus_spec.Part{1}.Node={nodeIds(:),V};

% Element
abaqus_spec.Part{1}.Element{1}.ATTR.type='C3D8R';
abaqus_spec.Part{1}.Element{1}.VAL={elementIds(:),E};

%Element sets
abaqus_spec.Part{1}.Elset{1}.ATTR.elset='Set-1';
abaqus_spec.Part{1}.Elset{1}.VAL=1;

%Node sets
abaqus_spec.Part{1}.Nset{2}.ATTR.nset='Set-2';
abaqus_spec.Part{1}.Nset{2}.VAL=1:1:size(V,1);

%Node sets using "generate"
abaqus_spec.Part{1}.Nset{1}.ATTR.nset='Set-1';
abaqus_spec.Part{1}.Nset{1}.ATTR.generate='';
abaqus_spec.Part{1}.Nset{1}.VAL=[1 size(V,1) 1];

%Sections
abaqus_spec.Part{1}.Solid_section.ATTR.elset='Set-1';
abaqus_spec.Part{1}.Solid_section.ATTR.material='Elastic';

% abaqus_spec.Part{1}.Shell_section.ATTR.elset='Set-1';
% abaqus_spec.Part{1}.Shell_section.ATTR.material='Material-1';
% % abaqus_spec.Part{1}.Shell_section.VAL=[10 5]; %Use numerical data
% abaqus_spec.Part{1}.Shell_section.VAL='10., 5'; %Use custom text data

%%
% The assembly section

abaqus_spec.Assembly.ATTR.name='Assembly-1';

abaqus_spec.Assembly.Instance{1}.ATTR.name='Cube-1';
abaqus_spec.Assembly.Instance{1}.ATTR.part='Cube';

% abaqus_spec.Assembly.Instance{2}.ATTR.name='Clot-1';
% abaqus_spec.Assembly.Instance{2}.ATTR.part='Clot';

abaqus_spec.Assembly.Nset{1}.ATTR.nset='Set-1';
abaqus_spec.Assembly.Nset{1}.ATTR.instance='Cube-1';
abaqus_spec.Assembly.Nset{1}.ATTR.generate='';
abaqus_spec.Assembly.Nset{1}.VAL=[1 4 1];

abaqus_spec.Assembly.Nset{2}.ATTR.nset='Set-3';
abaqus_spec.Assembly.Nset{2}.ATTR.instance='Cube-1';
abaqus_spec.Assembly.Nset{2}.ATTR.generate='';
abaqus_spec.Assembly.Nset{2}.VAL=[5 7 1];

abaqus_spec.Assembly.Nset{3}.ATTR.nset='Set-4';
abaqus_spec.Assembly.Nset{3}.ATTR.instance='Cube-1';
abaqus_spec.Assembly.Nset{3}.ATTR.generate='';
abaqus_spec.Assembly.Nset{3}.VAL=[2 6 2];

abaqus_spec.Assembly.Nset{4}.ATTR.nset='Set-5';
abaqus_spec.Assembly.Nset{4}.ATTR.instance='Cube-1';
abaqus_spec.Assembly.Nset{4}.VAL=[3 4 7];

abaqus_spec.Assembly.Nset{5}.ATTR.nset='origin';
abaqus_spec.Assembly.Nset{5}.ATTR.instance='Cube-1';
abaqus_spec.Assembly.Nset{5}.VAL=8;

abaqus_spec.Assembly.Nset{6}.ATTR.nset='all';
abaqus_spec.Assembly.Nset{6}.ATTR.instance='Cube-1';
% abaqus_spec.Assembly.Nset{6}.ATTR.generate='';
abaqus_spec.Assembly.Nset{6}.VAL=1:size(V,1);

abaqus_spec.Assembly.Surface{1}.ATTR.type='ELEMENT';
abaqus_spec.Assembly.Surface{1}.ATTR.name='innerSurface';
elemSetsInner={[1 2 3 4],[4 5 6 7]};
elemSetSideInner=[1 2];
valCell=cell(numel(elemSetsInner),1);
for qs=1:1:numel(elemSetsInner)
    surfaceElementSetName=['elementSetInnerSurface',num2str(qs)];
    abaqus_spec.Assembly.Elset{qs}.ATTR.elset=surfaceElementSetName;
    abaqus_spec.Assembly.Elset{qs}.ATTR.internal=''; %Remains hidden uppon import
    abaqus_spec.Assembly.Elset{qs}.ATTR.instance='Cube-1';
    abaqus_spec.Assembly.Elset{qs}.VAL=elemSetsInner{qs};

    sidePick=elemSetSideInner(qs);
    valCell{qs}={[surfaceElementSetName,', S',num2str(sidePick)]};
end
abaqus_spec.Assembly.Surface{1}.VAL=valCell;

%%
% Equation constraint

% *Equation
% 2
% X(n-1), 1, 1.
% XControlN, 1, -1.

%%--> Constraints
abaqus_spec.Assembly.COMMENT='Constraint 1';
abaqus_spec.Assembly.Equation.VAL=['2' newline 'X(n-1), ',  '1, 1.' newline 'XContN, ' '1, -1.'];

%%
% The material section

% *Material, name=Material-1
% *Hyperelastic, neo hooke
%  0.03,1.

abaqus_spec.Material.ATTR.name='Neo-Hooke';
abaqus_spec.Material.Hyperelastic.VAL=[0.03 1];
abaqus_spec.Material.Hyperelastic.ATTR.neo_hooke='';
abaqus_spec.Material.ATTR.name='Elastic';
abaqus_spec.Material.Elastic=[0.5 0.49];

%%
% Orientation

% *Orientation, name=Ori-1, system=RECTANGULAR
% Ori-1-DiscOrient
% 2, 90.
abaqus_spec.Orientation.ATTR.name='Ori-1';
abaqus_spec.Orientation.ATTR.system='RECTANGULAR';
abaqus_spec.Orientation.VAL=['Ori-1-DiscOrient' newline vec2strIntDouble([2 90],'%i')];

%%
% Contact pair

%%--> Contact pair
abaqus_spec.contact_pair{1}.ATTR.interaction='user-1';
abaqus_spec.contact_pair{1}.ATTR.type='node to surface';
abaqus_spec.contact_pair{1}.ATTR.adjust='0.0';
abaqus_spec.contact_pair{1}.VAL='AORTA-ASSEMBLY.OUTER, AORTA1-ASSEMBLY.OUTERX';

% surface interaction
abaqus_spec.surface_interaction{1}.ATTR.name='user-1';
abaqus_spec.surface_interaction{1}.ATTR.user='';
abaqus_spec.surface_interaction{1}.ATTR.properties='7';
abaqus_spec.surface_interaction{1}.ATTR.unsymm='';
abaqus_spec.surface_interaction{1}.ATTR.DEPVAR='13';
abaqus_spec.surface_interaction{1}.CSTM=', '; %Line with just comma

%Wrap to max width of 8 entries
t=vec2strIntDouble([0.2, 0.2, 0.05, 0.05,150,1000,0.0],'%6.7e');
t=strwrap(t,8,', ');
abaqus_spec.surface_interaction{1}.VAL=t;

%%
% The step section
%

abaqus_spec.Step.ATTR.name='Step-1';
abaqus_spec.Step.ATTR.nlgeom='YES';
abaqus_spec.Step.Static=[0.1 1 1e-5 0.1];

% Boundary
abaqus_spec.Step.Boundary{1}.VAL={'Set-1',[1 1],0.1};
abaqus_spec.Step.Boundary{2}.VAL={repmat({'origin'},3,1) [1 1; 2 2; 3 3]};
abaqus_spec.Step.Boundary{3}.VAL={'Set-3',[1,1]};
abaqus_spec.Step.Boundary{4}.VAL={'Set-4',[2,2]};
abaqus_spec.Step.Boundary{5}.VAL={'Set-5',[3,3]};

% Loads
% ** LOADS
% **
% ** Name: Load-1   Type: Pressure
% *Dsload
% Surf-1, P, 0.00533
% **
abaqus_spec.Step.Dsload{1}.VAL={'Surf-1','P',0.00533};

%Output
abaqus_spec.Step.Restart.ATTR.write='';
abaqus_spec.Step.Restart.ATTR.frequency=0;

abaqus_spec.Step.Output{1}.ATTR.field='';
abaqus_spec.Step.Output{1}.ATTR.variable='PRESELECT';
abaqus_spec.Step.Output{2}.ATTR.history='';
abaqus_spec.Step.Output{2}.ATTR.variable='PRESELECT';
abaqus_spec.Step.Node_print.ATTR.nset='all';
abaqus_spec.Step.Node_print.ATTR.frequency = 1;
abaqus_spec.Step.Node_print.VAL='COORD';
abaqus_spec.Step.El_print.VAL='S';

% * NODE SET, set=yoursetname, frequency = 1
% U

%%

%% Creating the INP file
% You can use |abaqusStruct2inp| to write the structure data to a file.

%Create file name for INP file
defaultFolder = fileparts(fileparts(mfilename('fullpath')));
savePath=fullfile(defaultFolder,'data','temp');
fileName=fullfile(savePath,'tempModel.inp');
[~,fileNamePart,~]=fileparts(fileName);

%%

[T]=abaqusStruct2inp(abaqus_spec,fileName);

%% View the inp file
%
textView(fileName);

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


%% Copyright (C) 2014-2019, 2022 Colin B. Macdonald
%% Copyright (C) 2016 Lagu
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published
%% by the Free Software Foundation; either version 3 of the License,
%% or (at your option) any later version.
%%
%% This software is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty
%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
%% the GNU General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with this software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @deftypeop  Constructor @@sym {@var{x} =} sym (@var{y})
%% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{y}, @var{assumestr})
%% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{y}, @var{assumestr1}, @var{assumestr2}, @dots{})
%% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{A}, [@var{n}, @var{m}])
%% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{y}, @var{ratflag})
%% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{handle})
%% Define symbols and numbers as symbolic expressions.
%%
%% @var{y} can be an integer, a string or one of several special
%% double values.  It can also be a double matrix or a cell
%% array.
%%
%% Examples:
%% @example
%% @group
%% x = sym ('x')
%%   @result{} x = (sym) x
%% y = sym ('2')
%%   @result{} y = (sym) 2
%% y = sym (3)
%%   @result{} y = (sym) 3
%% y = sym (inf)
%%   @result{} y = (sym) ∞
%% y = sym (pi)
%%   @result{} y = (sym) π
%% y = sym (1i)
%%   @result{} y = (sym) ⅈ
%% @end group
%% @end example
%%
%% A sym of a sym is a sym (idempotence):
%% @example
%% @group
%% sym (sym (pi))
%%   @result{} (sym) π
%% @end group
%% @end example
%%
%% A matrix of integers can be input:
%% @example
%% @group
%% sym ([1 2; 3 4])
%%   @result{} (sym 2×2 matrix)
%%       ⎡1  2⎤
%%       ⎢    ⎥
%%       ⎣3  4⎦
%% @end group
%% @end example
%%
%% However, if the entries are not simply integers, its better to call
%% @code{sym} inside the matrix:
%% @example
%% @group
%% [sym(pi) sym(3)/2; sym(1) 0]
%%   @result{} (sym 2×2 matrix)
%%       ⎡π  3/2⎤
%%       ⎢      ⎥
%%       ⎣1   0 ⎦
%% @end group
%% @end example
%% (Careful: at least one entry per row must be @code{sym} to workaround
%% a GNU Octave bug @url{https://savannah.gnu.org/bugs/?42152}.)
%% @c @example
%% @c [sym(pi) 2; 1 0]
%% @c   @print{} ??? octave_base_value::map_value(): wrong type argument 'scalar'
%% @c @end example
%%
%% Passing double values to sym is not recommended and will give a warning:
%% @example
%% @group
%% sym(0.1)
%%   @print{} warning: passing floating-point values to sym is
%%   @print{}          dangerous, see "help sym"...
%%   @result{} ans = (sym) 1/10
%% @end group
%% @end example
%%
%% In this particular case, the warning is easy to avoid:
%% @example
%% @group
%% sym(1)/10
%%   @result{} (sym) 1/10
%% @end group
%% @end example
%%
%% The ``danger'' here is that typing @code{0.1} gives a double-precision
%% floating-point value which differs slightly from the fraction
%% @code{sym(1)/10} (and this is true for most decimal expressions).
%% It is generally impossible to determine which exact symbolic value the
%% user intended.
%% The warning indicates that some heuristics have been applied
%% (namely a preference for ``small'' fractions, small fractions
%% of π and square roots of integers).
%% Further examples include:
%% @example
%% @group
%% y = sym(pi/100)
%%   @print{} warning: passing floating-point values to sym is
%%   @print{}          dangerous, see "help sym"...
%%   @result{} y = (sym)
%%        π
%%       ───
%%       100
%% @end group
%%
%% @group
%% y = sym(pi)/100
%%   @result{} y = (sym)
%%        π
%%       ───
%%       100
%% @end group
%% @end example
%% (@code{sym(pi)} is a special case; it does not raise the warning).
%%
%%
%% There is an additional reason for the float-point warning,
%% relevant if you are doing something like @code{sym(1.23456789012345678)}.
%% In many cases, floating-point numbers should be thought of as
%% approximations (with about 15 decimal digits of relative accuracy).
%% This means that mixing floating-point values and symbolic computations
%% with the goal of obtaining exact results is often a fool's errand.
%% Compounding this, symbolic computations may not always use numerically
%% stable algorithms (as their inputs are assumed exact) whereas a
%% floating-point input is effectively perturbed in the 15th digit.
%%
%% If what you really want is higher-precision floating-point
%% computations, @pxref{vpa}.
%%
%%
%% If having read the above, you @emph{still} want to do something
%% symbolic with floating-point inputs, you can use the @var{ratflag}
%% argument; by setting it to @qcode{'f'}, you will obtain the precise
%% rational number which is equal to the floating-point value:
%% @example
%% @group
%% sym(0.1, 'f')
%%   @result{} (sym)
%%        3602879701896397
%%       ─────────────────
%%       36028797018963968
%% @end group
%% @end example
%%
%% The default heuristic rational behaviour can be obtained by passing
%% @var{ratflag} as @qcode{'r'}; this avoids the floating-point warning:
%% @example
%% @group
%% sym(0.1, 'r')
%%   @result{} (sym) 1/10
%% @end group
%% @end example
%%
%%
%% For symbols, a second (and further) arguments can provide assumptions
%% or restrictions on the type of the symbol:
%% @example
%% @group
%% x = sym ('x', 'positive')
%%   @result{} x = (sym) x
%% x = sym ('x', 'positive', 'integer')
%%   @result{} x = (sym) x
%% @end group
%% @end example
%% @xref{assumptions}, for the list of supported assumptions.
%%
%% Caution: it is possible to create multiple variants of the
%% same symbol with different assumptions.
%% @example
%% @group
%% x1 = sym('x')
%%   @result{} x1 = (sym) x
%% x2 = sym('x', 'positive')
%%   @result{} x2 = (sym) x
%% x1 == x2
%%   @result{} (sym) x = x
%% isAlways(x1 == x2)
%%   @result{} 0
%% logical(x1 == x2)
%%   @result{} 0
%% @end group
%% @end example
%%
%% The second argument can also specify the size of a matrix:
%% @example
%% @group
%% A = sym('a', [2 3])
%%   @result{} A = (sym 2×3 matrix)
%%       ⎡a₁₁  a₁₂  a₁₃⎤
%%       ⎢             ⎥
%%       ⎣a₂₁  a₂₂  a₂₃⎦
%% @end group
%% @end example
%% or even with symbolic size:
%% @example
%% @group
%% syms m n positive integer
%% B = sym('B', [m n])
%%   @result{} B = (sym) B  (m×n matrix expression)
%% @end group
%% @end example
%%
%% Anonymous functions can be converted to symbolic expressions by
%% passing their function handle:
%% @example
%% @group
%% f = @@(n, x) sin (pi*besselj (n, x)/2)
%%   @result{} f = @@(n, x) sin (pi * besselj (n, x) / 2)
%% class (f)
%%   @result{} function_handle
%% sym(f)
%%   @result{} (sym)
%%          ⎛π⋅besselj(n, x)⎞
%%       sin⎜───────────────⎟
%%          ⎝       2       ⎠
%% @end group
%% @end example
%%
%% It is also possible to save sym objects to file and then load them when
%% needed in the usual way with the @code{save} and @code{load} commands.
%%
%% The underlying SymPy string representation (``srepr'') can usually be passed
%% directly to @code{sym}: @pxref{@@sym/char} for discussion of the details.
%%
%% @seealso{syms, assumptions, @@sym/assume, @@sym/assumeAlso}
%% @end deftypeop

function s = sym(x, varargin)

  if (nargin == 0)
    x = 0;
  end

  %% The actual class constructor
  % Tempting to make a 'private constructor' but we need to access
  % this from the python ipc stuff: outside the class.  We identify
  % this non-user-facing usage by empty x and 6 inputs total.  Note
  % that "sym([])" is valid but "sym([], ...)" is otherwise not.
  if (isempty (x) && nargin == 6)
    s.pickle = varargin{1};
    s.size = varargin{2};
    s.flat = varargin{3};
    s.ascii = varargin{4};
    s.unicode = varargin{5};
    s.extra = [];
    s = class (s, 'sym');
    return
  end

  %% User interface for defining sym
  % sym(1), sym('x'), etc.

  %if (strcmp (class (x), 'symfun')  &&  nargin==1)
  %  % FIXME: pass a symfun to sym() ctor; convert to pure sym
  %  % (SMT does not do this in 2014a).  bad idea?
  %  s = x.sym;
  %  return

  if (isa (x, 'sym'))
    if (nargin == 1)
      s = x;
      return
    else
      x = x.flat;
    end
  end

  if (iscell (x))
    %% Cell arrays are converted to sym arrays
    assert (isempty (varargin));
    s = cell2sym (x);
    return
  end

  if (isa (x, 'function_handle'))
    assert (nargin == 1)
    %% Need argnames of the handle.  TODO: can do better than regex?
    vars = regexp (func2str (x), '^\@\(([\w,\s]*)\)', 'tokens', 'once');
    assert (length (vars) == 1)
    vars = vars{1};
    if (isempty (vars))
      vars = {};  % empty char to empty cell
    else
      vars = strsplit (vars, {',' ' '});
    end
    for i = 1:length (vars)
      vars{i} = sym (sprintf ('Symbol("%s")', vars{i}));
    end
    %% call the function with those arguments as symbolic inputs
    s = x (vars{:});
    if (~ isa (s, 'sym'))  % e.g., for "@(x) 7"
      s = sym (s);
    end
    return
  end

  asm = {};
  isnumber = isnumeric (x) || islogical (x);
  ratwarn = true;
  ratflag = 'r';

  if (nargin >= 2)
    if (ismatrix (varargin{1}) && ~ischar (varargin{1}) && ~isstruct (varargin{1}) && ~iscell (varargin{1}))
      %% Handle MatrixSymbols
      assert (nargin < 3, 'MatrixSymbol do not support assumptions')
      s = make_sym_matrix (x, varargin{1});
      return
    elseif (nargin == 2 && isnumber && ischar (varargin{1}) && isscalar (varargin{1}))
      %% explicit ratflag given
      sclear = false;
      ratflag = varargin{1};
      switch ratflag
        case 'f'
          ratwarn = false;
        case 'r'
          ratwarn = false;
        case {'d' 'e'}
          error ('sym: RATFLAG ''%s'' is not implemented', ratflag)
        otherwise
          error ('sym: invalid RATFLAG ''%s''', ratflag)
      end
    elseif (nargin == 2 && ischar (varargin{1}) && strcmp (varargin{1}, 'clear'))
      sclear = true;
      varargin(1) = [];
      warning ('OctSymPy:deprecated', ...
              ['"sym(x, ''clear'')" is deprecated and will be removed in a future version;\n' ...
               '         use "assume(x, ''clear'')" instead.'])
    else
      sclear = false;
      assert (~isnumber, 'Only symbols can have assumptions.')
      check_assumptions (varargin);  % Check if assumptions exist - Sympy don't check this
      asm = varargin;
    end
  end

  if (~isscalar (x) && isnumber)  % Handle octave numeric matrix
    s = numeric_array_to_sym (x);
    return

  elseif (isa (x, 'double'))  % Handle double/complex
    iscmplx = ~isreal (x);
    if (iscmplx && isequal (x, 1i))
      s = pycall_sympy__ ('return S.ImaginaryUnit');
      return
    elseif (iscmplx)
      xx = {real(x); imag(x)};
    else
      xx = {x};
    end
    yy = cell(2, 1);
    for n = 1:numel (xx)
      x = xx{n};
      switch ratflag
        case 'f'
          y = double_to_sym_exact (x);
        case 'r'
          y = double_to_sym_heuristic (x, ratwarn, []);
        otherwise
          error ('sym: this case should not be possible')
      end
      yy{n} = y;
    end
    if (iscmplx)
      s = yy{1} + yy{2}*1i;
    else
      s = yy{1};
    end
    return

  elseif (isinteger (x)) % Handle integer vealues
    s = pycall_sympy__ ('return Integer(*_ins)', x);
    return

  elseif (islogical (x)) % Handle logical values
    if (x)
      s = pycall_sympy__ ('return S.true');
    else
      s = pycall_sympy__ ('return S.false');
    end
    return
  end

  if (isa (x, 'char'))
    %% Need to decide whether to use S() or Symbol()

      % TODO: tests pass without this?  Is there a example where this is needed?
      %% sym('---1') -> '-' '1' Split first symbols to can search operators correctly.
      %r = 1;
      %xc = '';  % Used to check operators skipping first symbols
      %for i = 1:length (x)
      %  if (strcmp (x (i), '-'))
      %    r = r*-1;
      %  elseif (~strcmp (x (i), '+'))
      %    if (r == -1)
      %      xc = x (i:end);
      %      x = ['-' x(i:end)];
      %    else
      %      x = xc = x (i:end);
      %    end
      %    break
      %  end
      %end

    y = detect_special_str (x);
    if (~ isempty (y))
      assert (isempty (asm), 'Only symbols can have assumptions.')
      s = pycall_sympy__ (['return ' y]);
      return
    end

    isnum = ~isempty (regexp (strtrim (x), ...
                              '^[-+]*?[\d_]*\.?[\d_]*(e[+-]?[\d_]+)?$'));
    %% Use Symbol() for words, not numbers, not "f(x)".
    if ((~ isnum) && (~ isempty (regexp (strtrim (x), '^\w+$'))))

      cmd = { 'd = dict()'
              'x = _ins[0]'
              '_ins = _ins[1:]'
              'for i in range(len(_ins)):'
              '    if isinstance(_ins[i], dict):'
              '        d.update(_ins[i])'
              '    #elif isinstance(_ins[i], list):'  % TODO: allow a list?
              '    #    for j in range(len(_ins[i])):'
              '    #        d.update({_ins[i][j]:True})'
              '    elif isinstance(_ins[i], (str, bytes)):'
              '        d.update({_ins[i]:True})'
              '    else:'
              '        raise ValueError("something unexpected in assumptions")'
              'return Symbol(x, **d)' };
      s = pycall_sympy__ (cmd, x, asm{:});

      if (nargin == 2 && sclear)
        % ---------------------------------------------
        % Muck around in the caller's namespace, replacing syms
        % that match 'xstr' (a string) with the 'newx' sym.
        context = 'caller';
        S = evalin(context, 'whos');
        evalin(context, '[];');  % clear 'ans'
        for i = 1:numel(S)
          obj = evalin(context, S(i).name);
          [newobj, flag] = symreplace(obj, x, s);
          if flag, assignin(context, S(i).name, newobj); end
        end
        % ---------------------------------------------
      end

      return

    else % S() in other case

      assert (isempty (asm), 'Only symbols can have assumptions.')

      % TODO: future version might warn on expression strings
        % Check if the user try to execute operations from sym
        %if (~isempty (regexp (xc, '\!|\&|\^|\:|\*|\/|\\|\+|\-|\>|\<|\=|\~')))
        %  warning ('Please avoid execute operations from sym function.');
        %end

      % Usually want rational output here (i.e., if input was "1.2").
      % But if input has words and parentheses it might be raw Sympy code.
      if (isempty (regexp (x, '\w\(.*\)')))
        s = pycall_sympy__ (['return S("' x '", rational=True)']);
        return
      end

      hint_symfun = false;
      %% distinguish b/w sym('ff(w)') and sym('ff(6, Symbol("w"))')
      % regexp detects F(<words commas spaces>)
      T = regexp (x, '^(\w+)\(([\w,\s]*)\)$', 'tokens');
      if (length (T) == 1 && length (T{1}) == 2)
        hint_symfun = true;
        name = T{1}{1};
        varnamestr = T{1}{2};
        varnames = strtrim (strsplit (varnamestr, ','));

        %% Blocklist some strings for which srepr(x) == str(x)
        % Python code for this:
        % >>> ns = {}; exec('from sympy import *', ns)
        % ... for (k, v) in ns.items():
        % ...    if not callable(v) and k not in ['__builtins__', 'C']:
        % ...        if k == srepr(v):
        % ...            print(k)
        var_blocklist = {'E' 'I' 'nan' 'oo' 'pi' 'zoo' 'Catalan' ...
                         'EulerGamma' 'GoldenRatio' 'true' 'false'};

        %% special case: if all (x,y,z) are in the blocklist, we should *not*
        % force symfun, thus preserving the identity sympy(sym(x)) == x
        if (all (cellfun (@(v) (any (strcmp (v, var_blocklist))), varnames)))
          hint_symfun = false;
        end

        %% special case some function names to always make a Function
        % Currently this is unused, but could be used if we want
        % different behaviour for the "I" in "I(t)" vs "F(I, t)".
        % SMT 2014 compat: does *not* have I, E here
        %function_allowlist = {'I', 'E', 'ff', 'FF'};
        %if (hint_symfun)
        %  if (any (strcmp (name, function_allowlist)))
        %    x = ['Function("' name '")(' varnamestr ')'];
        %  end
        %end
      end

      cmd = {'x, hint_symfun = _ins'
             'if hint_symfun:'
             '    from sympy.abc import _clash1'
             '    myclash = {v: Function(v) for v in ["ff", "FF"]}'
             '    myclash.update(_clash1)'
             '    #myclash.pop("I", None)'  % remove for SMT compat
             '    #myclash.pop("E", None)'
             'else:'
             '    myclash = dict()'
             'try:'
             '    return (0, 0, sympify(x, locals=myclash))'
             'except Exception as e:'
             '    lis = set()'
             '    if "(" in x or ")" in x:'
             '        x2 = split("\(|\)| |,", x)'
             '        x2 = [p for p in x2 if p]'
             '        for i in x2:'
             '            try:'
             '                if eval("callable(" + i + ")"):'
             '                    lis.add(i)'
             '            except:'
             '                pass'
             '    if len(lis) > 0:'
             '        return (str(e), 1, "\", \"".join(str(e) for e in lis))'
             '    return (str(e), 2, 0)' };

      [err flag s] = pycall_sympy__ (cmd, x, hint_symfun);

      switch (flag)
        case 1  % Bad call to python function
          error (['Python: %s\n' ...
                  'Error occurred using "%s" Python function, perhaps use another variable name?'], ...
                 err, s);
        case 2  % Something else
          error (['Python: %s\n' ...
                  'Seems you cannot use "%s" for a variable name; perhaps this is a bug?'], ...
                 err, x);
      end
      return

    end
  end

  error ('Conversion to symbolic with those arguments not (yet) supported')

end

%!test
%! % integers
%! x = sym ('2');
%! y = sym (2);
%! assert (isa (x, 'sym'))
%! assert (isa (y, 'sym'))
%! assert (isequal (x, y))

%!test
%! % infinity
%! for x = {'inf', '-inf', inf, -inf, 'Inf'}
%!   y = sym (x{1});
%!   assert (isa (y, 'sym'))
%!   assert (isinf (double (y)))
%!   assert (isinf (y))
%! end

%!test
%! % pi
%! x = sym ('pi');
%! assert (isa (x, 'sym'))
%! assert (isequal (sin (x), sym (0)))
%! assert (abs (double (x) - pi) < 2*eps )
%! x = sym (pi);
%! assert (isa (x, 'sym'))
%! assert (isequal (sin (x), sym (0)))
%! assert (abs (double (x) - pi) < 2*eps )

%!test
%! % rationals
%! x = sym(1) / 3;
%! assert (isa (x, 'sym'))
%! assert (isequal (3*x - 1, sym (0)))
%! x = 1 / sym (3);
%! assert (isa (x, 'sym'))
%! assert (isequal (3*x - 1, sym (0)))
%! x = sym ('1/3');
%! assert (isa (x, 'sym'))
%! assert (isequal (3*x - 1, sym (0)))

%!test
%! % passing small rationals
%! x = sym ('1/2');
%! assert (double (x) == 1/2 )
%! assert (isequal (2*x, sym (1)))

%!warning <dangerous> x = sym (1/2);

%!test
%! % passing small rationals w/o quotes: despite the warning,
%! % it should work
%! s = warning ('off', 'OctSymPy:sym:rationalapprox');
%! x = sym (1/2);
%! warning (s)
%! assert (double (x) == 1/2 )
%! assert (isequal (2*x, sym (1)))

%!test
%! assert (isa (sym (pi), 'sym'))
%! assert (isa (sym ('beta'), 'sym'))

%!test
%! % sym from array
%! D = [0 1; 2 3];
%! A = [sym(0) 1; sym(2) 3];
%! assert (isa (sym (D), 'sym'))
%! assert (isequal (size (sym (D)), size (D)))
%! assert (isequal (sym (D), A))

%!test
%! % more sym from array
%! syms x
%! A = [x x];
%! assert (isequal (sym (A), A))
%! A = [1 x];
%! assert (isequal (sym (A), A))

%!test
%! %% assumptions and clearing them
%! clear variables  % for matlab test script
%! x = sym('x', 'real');
%! f = {x {2*x}};
%! asm = assumptions();
%! assert ( ~isempty(asm))
%! s = warning ('off', 'OctSymPy:deprecated');
%! x = sym('x', 'clear');
%! warning (s)
%! asm = assumptions();
%! assert ( isempty(asm))

%!test
%! %% matlab compat, syms x clear should add x to workspace
%! x = sym('x', 'real');
%! f = 2*x;
%! clear x
%! assert (~logical(exist('x', 'var')))
%! s = warning ('off', 'OctSymPy:deprecated');
%! x = sym('x', 'clear');
%! warning (s)
%! assert (logical(exist('x', 'var')))

%!test
%! %% assumptions should work if x is already a sym
%! x = sym('x');
%! x = sym(x, 'real');
%! assert (~isempty(assumptions(x)))

%!test
%! %% likewise for clear
%! x = sym('x', 'real');
%! f = 2*x;
%! s = warning ('off', 'OctSymPy:deprecated');
%! x = sym(x, 'clear');
%! warning (s)
%! assert (isempty(assumptions(x)))
%! assert (isempty(assumptions(f)))

%!test
%! % bool
%! t = sym (false);
%! t = sym (true);
%! assert (logical (t))

%!test
%! % bool vec/mat
%! a = sym (1);
%! t = sym ([true false]);
%! assert (isequal (t, [a == 1  a == 0]))
%! t = sym ([true false; false true]);
%! assert (isequal (t, [a == 1  a == 0;  a == 0  a == 1]))

%!test
%! % symbolic matrix
%! A = sym ('A', [2 3]);
%! assert (isa (A, 'sym'))
%! assert (isequal (size (A), [2 3]))
%! A(1, 1) = 7;
%! assert (isa (A, 'sym'))
%! A = A + 1;
%! assert (isa (A, 'sym'))

%!test
%! % symbolic matrix, symbolic but Integer size
%! A = sym ('A', sym([2 3]));
%! assert (isa (A, 'sym'))
%! assert (isequal (size (A), [2 3]))

%!test
%! % symbolic matrix, subs in for size
%! syms n m integer
%! A = sym ('A', [n m]);
%! B = subs (A, [n m], [5 6]);
%! assert (isa (B, 'sym'))
%! assert (isequal (size (B), [5 6]))

%!error <Cannot create symbolic matrix> sym('2*a', [2 3])
%!error <Cannot create symbolic matrix> sym(2*sym('a'), [2 3])
%!error <Cannot create symbolic matrix> sym('1', [2 3])
%!error <Cannot create symbolic matrix> sym(1, [2 3])

%!error <Cannot create symbolic matrix>
%! % TODO: symbolic tensor, maybe supported someday
%! sym('a', [2 3 4])

%!test
%! % 50 shapes of empty
%! a = sym (ones (0, 3));
%! assert (isa (a, 'sym'))
%! assert (isequal (size (a), [0 3]))
%! a = sym (ones (2, 0));
%! assert (isequal (size (a), [2 0]))
%! a = sym ([]);
%! assert (isequal (size (a), [0 0]))

%!test
%! % moar empty
%! a = sym ('a', [0 3]);
%! assert (isa (a, 'sym'))
%! assert (isequal (size (a), [0 3]))
%! a = sym ('a', [2 0]);
%! assert (isa (a, 'sym'))
%! assert (isequal (size (a), [2 0]))

%!test
%! % embedded sympy commands, various quotes, issue #143
%! a = sym ('a');
%! a1 = sym ('Symbol("a")');
%! a2 = sym ('Symbol(''a'')');
%! assert (isequal (a, a1))
%! assert (isequal (a, a2))
%! % Octave only, and eval to hide from Matlab parser
%! if exist ('OCTAVE_VERSION', 'builtin')
%!   eval( 'a3 = sym("Symbol(''a'')");' );
%!   eval( 'a4 = sym("Symbol(\"a\")");' );
%!   assert (isequal (a, a3))
%!   assert (isequal (a, a4))
%! end

%!test
%! % complex
%! x = sym(1 + 2i);
%! assert (isequal (x, sym(1)+sym(2)*1i))

%!test
%! % doubles bigger than int32 INTMAX should not fail
%! d = 4294967295;
%! a = sym (d);
%! assert (isequal (double (a), d))
%! d = d + 123456;
%! a = sym (d);
%! assert (isequal (double (a), d))

%!test
%! % int32 integer types
%! a = sym (100);
%! b = sym (int32 (100));
%! assert (isequal (a, b))

%!test
%! % int32 MAXINT integers
%! a = sym ('2147483647');
%! b = sym (int32 (2147483647));
%! assert (isequal (a, b))
%! a = sym ('-2147483647');
%! b = sym (int32 (-2147483647));
%! assert (isequal (a, b))
%! a = sym ('4294967295');
%! b = sym (uint32 (4294967295));
%! assert (isequal (a, b))

%!test
%! % int64 integer types
%! a = sym ('123456789012345');
%! b = sym (int64(123456789012345));
%! c = sym (uint64(123456789012345));
%! assert (isequal (a, b))
%! assert (isequal (a, c))

%!test
%! % integer arrays
%! a = int64 ([1 2 100]);
%! s = sym (a);
%! assert (isequal (double (a), [1 2 100]))

%!test
%! % bigger int64 integer types
%! q = int64 (123456789012345);
%! w = 10000*q + 123;
%! a = sym ('1234567890123450123');
%! b = sym (w);
%! assert (isequal (a, b))

%!test
%! % sym(double) heuristic
%! s = warning ('off', 'OctSymPy:sym:rationalapprox');
%! x = sym(2*pi/3);
%! assert (isequal (x/sym(pi), sym(2)/3))
%! x = sym(22*pi);
%! assert (isequal (x/sym(pi), sym(22)))
%! x = sym(pi/123);
%! assert (isequal (x/sym(pi), sym(1)/123))
%! warning (s)

%!test
%! % sym(double) with 'r': no warning
%! a = 0.1;
%! x = sym(a, 'r');
%! assert (isequal (x, sym(1)/10))

%!test
%! % sym(double, 'f')
%! a = 0.1;
%! x = sym(a, 'f');
%! assert (~isequal (x, sym(1)/10))
%! assert (isequal (x, sym('3602879701896397')/sym('36028797018963968')))

%!test
%! x = sym(pi, 'f');
%! assert (~isequal (x, sym('pi')))
%! assert (isequal (x, sym('884279719003555')/sym('281474976710656')))

%!test
%! q = sym('3602879701896397')/sym('36028797018963968');
%! x = sym(1 + 0.1i, 'f');
%! assert (isequal (x, 1 + 1i*q))
%! x = sym(0.1 + 0.1i, 'f');
%! assert (isequal (x, q + 1i*q))

%!test
%! assert (isequal (sym(inf, 'f'), sym(inf)))
%! assert (isequal (sym(-inf, 'f'), sym(-inf)))
%! assert (isequaln (sym(nan, 'f'), sym(nan)))
%! assert (isequal (sym(complex(inf, -inf), 'f'), sym(complex(inf, -inf))))
%! assert (isequaln (sym(complex(nan, inf), 'f'), sym(complex(nan, inf))))
%! assert (isequaln (sym(complex(-inf, nan), 'f'), sym(complex(-inf, nan))))

%!test
%! assert (isequal (sym (sqrt(2), 'r'), sqrt (sym (2))))
%! assert (isequal (sym (sqrt(12345), 'r'), sqrt (sym (12345))))

%!test
%! % symbols with special sympy names
%! syms Ei Eq
%! assert (~isempty (regexp (sympy (Eq), '^Symbol')))
%! assert (~isempty (regexp (sympy (Ei), '^Symbol')))

%!test
%! % more symbols with special sympy names
%! x = sym('FF');
%! assert (~isempty (regexp (x.pickle, '^Symbol')))
%! x = sym('ff');
%! assert (~isempty (regexp (x.pickle, '^Symbol')))

%!test
%! % E can be a sym not just exp(sym(1))
%! syms E
%! assert (~logical (E == exp(sym(1))))

%!test
%! % e can be a symbol, not exp(sym(1))
%! syms e
%! assert (~ logical (e == exp(sym(1))))

%!test
%! % double e
%! x = sym (exp (1));
%! y = exp (sym (1));
%! assert (isequal (x, y))
%! if (exist ('OCTAVE_VERSION', 'builtin'))
%!   x = sym (e);
%!   assert (isequal (x, y))
%! end

%!test
%! x = sym (-exp (1));
%! y = -exp (sym (1));
%! assert (isequal (x, y))

%!assert (~ isequal (sym (exp(1)), sym (exp(1), 'f')))

%!warning <dangerous> sym (1e16);
%!warning <dangerous> sym (-1e16);
%!warning <dangerous> sym (10.33);
%!warning <dangerous> sym (-5.23);
%!warning <dangerous> sym (sqrt (1.4142135623731));

%!error <is not supported>
%! x = sym ('x', 'positive2');

%!error <is not supported>
%! x = sym ('x', 'integer', 'positive2');

%!error <is not supported>
%! x = sym ('x', 'integer2', 'positive');

%!error <Only symbols can have assumptions>
%! x = sym ('-pi', 'positive')

%!error <Only symbols can have assumptions>
%! x = sym ('pi', 'integer')

%!test
%! % multiple assumptions
%! n = sym ('n', 'negative', 'even');
%! a = assumptions (n);
%! assert (strcmp (a, 'n: negative, even') || strcmp (a, 'n: even, negative'))

%!error <unexpected in assumptions>
%! % multiple assumptions as a list
%! % TODO: should this be allowed?
%! n = sym ('n', {'negative', 'even'});
%! a = assumptions (n);
%! assert (strcmp (a, 'n: negative, even') || strcmp (a, 'n: even, negative'))

%!error <unexpected in assumptions>
%! n = sym ('n', {{'negative', 'even'}});

%!test
%! % save/load sym objects
%! syms x
%! y = 2*x;
%! a = 42;
%! myfile = tempname ();
%! save (myfile, 'x', 'y', 'a')
%! clear x y a
%! load (myfile)
%! assert (isequal (y, 2*x))
%! assert (a == 42)
%! if (exist ('OCTAVE_VERSION', 'builtin'))
%!   assert (unlink (myfile) == 0)
%! else
%!   delete ([myfile '.mat'])
%! end

%!test
%! a = sym ('2.1');
%! b = sym (21) / 10;
%! %% https://github.com/sympy/sympy/issues/11703
%! assert (pycall_sympy__ ('return _ins[0] == _ins[1] and hash(_ins[0]) == hash(_ins[1])', a, b))

%!test
%! % issue #706
%! a = sym('Float("1.23")');
%! assert (~ isempty (strfind (char (a), '.')))

% TODO: test that might be used in the future
%%!warning <avoid execute operations> sym ('1*2');

%!assert (isequal (sym({1 2 'a'}), [sym(1) sym(2) sym('a')]));

%!error sym({1 2 'a'}, 'positive');
%!error sym({'a' 'b'}, 'positive');

%!test
%! a = sym ('--1');
%! b = sym ('---1');
%! assert (isequal (a, sym (1)))
%! assert (isequal (b, sym (-1)))

%!test
%! % num2cell works on sym arrays
%! syms x
%! C1 = num2cell ([x 2 3; 4 5 6*x]);
%! assert (iscell (C1))
%! assert (isequal (size (C1), [2 3]))
%! assert (isequal (C1{1,1}, x))
%! assert (isequal (C1{2,3}, 6*x))
%! assert (isequal (C1{1,3}, sym(3)))
%! assert (isa (C1{1,3}, 'sym'))

%!test
%! % function_handle
%! f = @(x, y) y*sin(x);
%! syms x y
%! assert (isequal (sym (f), y*sin(x)));
%! f = @(x) 42;
%! assert (isequal (sym (f), sym (42)));
%! f = @() 42;
%! assert (isequal (sym (f), sym (42)));

%!error <ndefined>
%! % function_handle
%! f = @(x) A*sin(x);
%! sym (f)

%!test
%! % Issue #885
%! clear f x  % if test not isolated (e.g., on matlab)
%! syms x
%! f(x) = sym('S(x)');
%! f(x) = sym('I(x)');
%! f(x) = sym('O(x)');

%!test
%! % sym(sympy(x) == x identity, Issue #890
%! syms x
%! f = exp (1i*x);
%! s = sympy (f);
%! g = sym (s);
%! assert (isequal (f, g))

%!test
%! % sym(sympy(x) == x identity
%! % Don't mistake "pi" (which is "srepr(S.Pi)") for a symfun variable
%! f = sym ('ff(pi, pi)');
%! s1 = sympy (f);
%! s2 = 'FallingFactorial(pi, pi)';
%! assert (strcmp (s1, s2))

%!test
%! % sym(sympy(x) == x identity
%! % Don't mistake "I" (which is "srepr(S.ImaginaryUnit)") for a symfun variable
%! f = sym ('sin(I)');
%! g = 1i*sinh (sym (1));
%! assert (isequal (f, g))
%! s = sympy (f);
%! assert (isempty (strfind (s, 'Function')))

%!error
%! % sym(sympy(x) == x identity
%! % Don't mistake "true/false" (which is "srepr(S.true)") for a symfun variable
%! % (Used to print as `S.true` but just `true` in sympy 1.2)
%! sym ('E(true,false)')

%!test
%! % some variable names that are special to sympy but should not be for us
%! f = sym ('f(S, Q, C, O, N)');
%! s1 = sympy (f);
%! s2 = 'Function(''f'')(Symbol(''S''), Symbol(''Q''), Symbol(''C''), Symbol(''O''), Symbol(''N''))';
%! assert (strcmp (s1, s2))

%!test
%! % For SMT 2014 compatibilty, I and E would become ImaginaryUnit and Exp(1)
%! % but I'm not sure this is by design.  This test would need to change if
%! % we want stricter SMT compatibilty.
%! f = sym ('f(x, I, E)');
%! s1 = sympy (f);
%! s2 = 'Function(''f'')(Symbol(''x''), Symbol(''I''), Symbol(''E''))';
%! assert (strcmp (s1, s2))

%!test
%! % not the identity, force symfun
%! f = sym ('FF(w)');
%! s1 = sympy (f);
%! s2 = 'Function(''FF'')(Symbol(''w''))';
%! assert (strcmp (s1, s2))

%!test
%! % not the identity, force symfun
%! f = sym ('FF(w, pi)');
%! s1 = sympy (f);
%! s2 = 'Function(''FF'')(Symbol(''w''), pi)';
%! assert (strcmp (s1, s2))

%!test
%! % not the identity, force symfun
%! f = sym ('ff(x, y)');
%! s1 = sympy (f);
%! s2 = 'Function(''ff'')(Symbol(''x''), Symbol(''y''))';
%! assert (strcmp (s1, s2))

%!test
%! % But this one should satisfy "sym(sympy(x) == x" identity
%! % (OOTB, SymPy has ff -> FallingFactorial)
%! f = sym ('FallingFactorial(x, y)');
%! s1 = sympy (f);
%! s2 = 'FallingFactorial(Symbol(''x''), Symbol(''y''))';
%! assert (strcmp (s1, s2))