function [S,FqS,Q]=MFDFA(X,windowWidthBegin,windowWidthEnd,POWERS,DFAORDER,kindOfElevate,valueOfElevate);
% Мультифрактальний DFA (MF-DFA) за статтею
% "Multifractal detrended fluctuation analysis of nonstationary time series"
% Аргументи:
%   X                - вектор часових значень
%   windowWidthBegin - початкова ширина вікна
%   windowWidthEnd   - кінцева ширина вікна
%   POWERS           - степені, для яких розраховувати DFA (q)
%   DFAORDER         - порядок DFA (1,2,3...)
%   kindOfElevate    - тип збільшення вікна (стрінгова змінна)
%   valueOfElevate   - значення для збільшення вікна (стрінгова змінна)
%      НАПРИКЛАД: [S,Fq,Q]=MFDFA(X,10,1000,[1 2 3 4],'STEP','100');
% Результати:
%   S                - вектор-рядок значень ширини вікна
%   FqS              - значення варіацій для вікон відповідної ширини (з масиву S)
%                      та степеня q ( Fq(s) )
%   Q                - вектор-стовпчик степенів Q
%                      
%                      Отримуємо наступні відповідності між матрицею та векторами
%                                   S         (S - 1 рядок та n стовпчиків
%                                Q FqS        (Q - m рядків та 1 стовпчик
%                                             (FqS - m рядків та n стовпчиків
% Обмеження:
%   1) POWERS повинен бути вектором
%   2) windowWidthBegin < windowWidthEnd !!!
%   3) обов"язково повинні передаватись два останні аргументи
% Використовує:
%              MFDFAOneStep

% визначаємо кількість рядків та стовпчиків у векторі X
% потрібно, щоб був один рядок; якщо не так - розвертаємо
[m,n]=size(X);
if (n==1) X=X'; [m,n]=size(X); end

% КРОК 1. Визначаємо профіль
% знаходимо середнє значення для всієї множини X
AVG=sum(X)/n;
% віднімаємо його від значень X
Y=X-AVG;
% знаходимо вектор накопичень (формула (1))
% перший елемент вже введено
for j=2:n
    Y(1,j)=Y(1,j-1)+Y(1,j);
end

% ділимо на max елемент %%%%%
Y=Y/max(abs(Y));

% виділяємо пам"ять для вектора Q
% визначаємо кількість степенів q - розмір вектора POWERS
[mq,nq]=size(POWERS);
% якщо POWERS має один рядок - транспонуємо, інакше просто записуємо у Q
if (mq==1) Q=POWERS'; else Q=POWERS; end
[nq,mq]=size(Q);

% розраховуємо необхідні для роботи процедури ширини вікон
S=MFDFAScales(windowWidthBegin,windowWidthEnd,kindOfElevate,valueOfElevate);
% визначаємо кількість різних ширин вікон - розмір вектора S
[ms,ns]=size(S);
    
% виділяємо пам"ять для матриці FqS
FqS=zeros(nq,ns);

% заповнюємо вектори та матрицю
% проходимо по усім можливим ширинам вікон
for indexS=1:ns
    % беремо поточну ширину вікна
    currentS=S(1,indexS);
    % визначаємо варіації, використовуючи DFA1
    [F2,Ns]=MFDFAOneStep(Y,currentS,DFAORDER);
    % знаходимо значення FqS для різних степенів q
    %F2t=log(F2); %
    for currentQ=1:nq
        cQ=Q(currentQ,1);
        %F2t2=cQ/2*F2t; %
        %F2t2=exp(F2t2); %
        F2t2=F2.^(cQ/2);
        F2t2=sum(F2t2);
        F2t2=F2t2/Ns;
        FqS(currentQ,indexS)=(F2t2)^(1/cQ);
    end
end

clear m n AVG Y mq nq ms ns indexS currentS F2 currentQ cQ F2t;