function varargout = mfs_freq2time(varargin)

# usage: varargout = mfs_freq2time(varargin)
#
#  [x, t] = mfs_freq2time(X, df, dt, bc)
#  cmp    = mfs_freq2time(cmp, spectra, rcase, dt, bc)
#
# In the first form, the function computes the inverse Fourier transform
# from the values of the Fourier transform at the positive frequencies.
#
# In the second form, the function uses results from a frequency
# response analysis, multiplies them by the spectra and performs the
# inverse Fourier transform. The results are stored as results of a 
# transient response analysis.
#
# Input  X(:, :)  Array with Fourier transform
#                 (columns correspond to frequencies)
#        df       Frequency increment
#        dt       Time step (optional)
#        bc       Base correction (optional):
#                  0 = no correction (default)
#                  1 = subtract a constant
#                  2 = subtact a linear function
#        cmp      Structure with component
#        spectra  Structure with spectra
#        rcase    Result case number (optional, default: 1)
#
# Output x(:, :)  Array with time series
#                 (columns correspond to time steps)
#        t(:)     Array with time steps (optional)
#        cmp      Structure with component
#
# Fields of structure spectra
#
#   df          Frequency step
#   lc(:)       Identifiers of load cases with transfer functions
#   spec(:, :)  Spectra assigned to load cases: rows correspond to
#               load cases, columns to frequencies
#
# The base correction can be used to enforce the starting value to be
# zero and to remove a linear shift.
#
# ---------------------------------------------------------------------

# Copyright (c) 2021 by Johannes Wandinger

  t0 = clock();

# Branch according to format

  if (! isstruct(varargin{1}))    % First format

     if (nargin < 2)
        error("mfs_freq2time: at least X and df must be defined\n");
     end
     if (nargout > 3)
        error("mfs_freq2time: bad number of output arguments\n");
     end

     X  = varargin{1};
     df = varargin{2};
     dt = [];
     bc = 0;

     if (! isscalar(df))
        error("mfs_freq2time: second argument must be a scalar\n");
     elseif (df <= 0)
        error("mfs_freq2time: frequency step must be positive\n");
     end

     if (nargin > 2)

        if (! isempty(varargin{3}))
           dt = varargin{3};
           if (! isscalar(dt))
              error("mfs_freq2time: time step must be a scalar\n");
           elseif (dt <= 0)
              error("mfs_freq2time: time step must be positive\n");
           end
        end

        if (nargin == 4)
           bc = varargin{4};
           if (! isscalar(bc) )
              error("mfs_freq2time: bc must be a scalar\n");
           end
           if (! ismember(bc, 0 : 2))
              error("mfs_freq2time: bc must be 0, 1 or 2\n");
           end
        end

     end

     time_stamp = ignore_function_time_stamp("all");
     mfs_paths("add", "mfs_freq2time.m", "util");

     [x, t] = mfs_freq2timex(X, df, dt, bc);

     mfs_paths("remove");
     ignore_function_time_stamp(time_stamp);

     varargout{1} = x; varargout{2} = t;

  else                            % Second format

     if (nargin < 2)
        error("mfs_freq2time: at least component and spectra must be defined\n");
     end

     cmp = varargin{1};
     if (! isfield(cmp, "type"))
        error("mfs_freq2time: first argument is not a component\n");
     end
     if (! strcmp(cmp.type, "solid"))
        error("mfs_freq2time: component type %s not supported\n",
              cmp.type);
     end

     spectra = varargin{2};

     if (! isstruct(spectra))
        error("mfs_freq2time: spectra must be a structure array\n");
     end

     if (! isfield(cmp, "freqresp"))
        error("mfs_freq2time: no results from frequency response analysis found\n");
     end

     rcase =  1;
     dt    = [];
     bc    =  0;

     if (nargin > 2)
        if (! isempty(varargin{3}))
           rcase = varargin{3};
           if (rcase < 1)
              error("mfs_freq2time: result case must be positive\n");
           end
        end
     end

     if (nargin > 3)

        if (! isempty(varargin{4}))
           dt = varargin{4};
           if (! isscalar(dt))
              error("mfs_freq2time: time step must be a scalar\n");
           elseif (dt <= 0)
              error("mfs_freq2time: time step must be positive\n");
           end
        end

        if (nargin == 5)
           bc = varargin{5};
           if (! isscalar(bc) )
              error("mfs_freq2time: bc must be a scalar\n");
           end
           if (! ismember(bc, 0 : 2))
              error("mfs_freq2time: bc must be 0, 1 or 2\n");
           end
        end

     end

     time_stamp = ignore_function_time_stamp("all");
     mfs_paths("add", "mfs_freq2time.m", "solid");

     [cmp, rc] = mfs_freq2timex(cmp, spectra, rcase, dt, bc);

     mfs_paths("remove");
     ignore_function_time_stamp(time_stamp);

     varargout{1} = cmp;

     if (rc)
        error("mfs_freq2time ended with errors\n");
     end

  end

  elapsed_time = etime(clock(), t0);
  printf("%10.4f seconds needed to compute time history from frequency response\n", ...
         elapsed_time);
  fflush(stdout);

end
