(*~\Глагол\ПриложенияТесты\ПредмОписПодход\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                                ОТДЕЛ РазмерВыделяемойПамяти_в_Win32+;
(*============================================================================*
 * НАЗНАЧЕНИЕ: 
 *   Быстродействие алгоритмов БПФ по осн.2 с DiT с замещением входа и
 *   последующими 3-мя циклами для m-Слоёв БПФ2 также с замещением
 *
 *   из отдела А\кнБПФ2_сЗам_DiT_и_3цикла.отд - это старые алгоритмы БПФ2 с
 *              DiT с Замещением и 3 цикла тоже с Замещением
 *   из отдела А\кнБПФ2_сЗам_после_DiT_3цикла.отд
 *                   [ 8 алгоритмов с DiT и 3 цикла = DiT и mСлоёв ] 
 *----------------------------------------------------------------------------*
 * ПРИМЕЧАНИЯ: 
 *   1) во временной области формируем сигнал в виде действительной синусоиды;
 *   2) вычисляем спектр сигнала (прямое БПФ по осн.2);
 *   3) обратно вычисляем сигнал по его спектру (обратное БПФ по осн.2).
 *============================================================================*)
(* старые алгоритмы БПФ по осн.2 - 
                                 DiT с Замещением и 3 цикла тоже с Замещением *)
ИСПОЛЬЗУЕТ 
 дМатем   ИЗ "..\..\Отделы\ЧисАн\64\д\",

ВещОселок ИЗ "..\..\Отделы\ЧисАн\64\д\",

кнМатем   ИЗ "..\..\Отделы\ЧисАн\64\к\Набор\",
кнВектор  ИЗ "..\..\Отделы\ЧисАн\64\к\Набор\",

кнБПФ2_сЗам_DiT_и_3цикла ИЗ "..\..\Отделы\ЦОС\64\к\Набор\БПФ2_Кули-Тьюки\3цикла\А\",

  ОС      ИЗ "..\..\Отделы\Обмен\",
  НаЭкран ИЗ "..\..\Отделы\Обмен\ВводВывод\";

ВИД
        (* вид Вещ - это удвоенная точность 64 разряда (16 десятичных знаков) *)
  Вещ = дМатем.Вещ;                   (* локально *)

ПЕР
 i,j,k,N,
  L:ЦЕЛ;(* L=2^28 ДЕЛИТЬ N, N=2^2..2^28 - переменное число повторов теста для N *)

  кВекторД:кнВектор.Доступ;

 (*-=
(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА СоздатьКусок(размер:ЦЕЛ);
(* Цель:  запрос у ОС нового куска памяти с полезным размером <размер>
 * После: <текКусок>  - адрес нового текущего куска в кольцевом списке кусков
 *        <текСвобУч> - адрес первого (и единственного) участка <текКусок>    *)
ПЕР
  нк:ОпКуска; (*   новый кусок в кольцевом списке кусков *)
  тк:ОпКуска; (* текущий кусок в кольцевом списке кусков *)
  ц0:    ЦЕЛ; (* целый 0                                 *)
УКАЗ
  ц0:=0;
  тк:=ОБХОД.Значение(ОпКуска,текКусок);
  УВЕЛИЧИТЬ(размер,РазмерОК);
  УВЕЛИЧИТЬ(размер,(-размер) ОСТАТОК РазмерКуска); (* выравнивание на РазмерКуска *)
  текКусок:=ОС.ВзятьПамять(размер);
  ПРОВЕРИТЬ(текКусок # 0);
  нк:=ОБХОД.Значение(ОпКуска,текКусок);
  текСвобУч:=текКусок+РазмерОК; (* оставляем место для <нк> *)
  УМЕНЬШИТЬ(размер,РазмерОК);
  нк.размер:=размер;
  нк.первуч:=текСвобУч;
  нк.первсв:=текСвобУч;
  ОБХОД.ВПамять(текСвобУч+ПозУчСледСв,ц0);
  ОБХОД.ВПамять(текСвобУч+ПозУчРазмера,-размер);
  (* вставляем новый кусок в кольцевой список после текущего куска *)
  ЕСЛИ тк # ПУСТО ТО
    нк.следку:=тк.следку;
    тк.следку:=нк
  ИНАЧЕ
    нк.следку:=нк
  КОН
КОН СоздатьКусок;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА СоздатьУч(размер:ЦЕЛ):ЦЕЛ;
(* Цель:  создать участок с размером <размер>
 *       ( в конце <текСвобУч>
 *        или весь <текСвобУч> )
 *        и возвратить его адрес
 * До:    <текКусок>  - адрес текущего куска в кольцевом списке кусков
 *        <текСвобУч> - адрес достаточно большого свободного участка в <текКусок>
 * После: <текСвобУч> - бывший или следующий адрес свободного участка *)
ПЕР
  предсв:ЦЕЛ; (* адрес предыдущего свободного участка    *)
  размсв:ЦЕЛ; (* размер свободного участка               *)
  тк:ОпКуска; (* текущий кусок в кольцевом списке кусков *)
  уч:    ЦЕЛ; (* адрес свободного участка                *)
  создуч:ЦЕЛ; (* адрес созданного участка                *)
УКАЗ
  ОБХОД.ИзПамяти(текСвобУч+ПозУчРазмера,размсв);

       размсв:=-размсв; (* размер будет положительным *)
  ЕСЛИ
       размсв > размер+РазмерОУ+4
  ТО                     (* забираем хвост у <текСвобУч> *)
    УМЕНЬШИТЬ(размсв,размер);
    ОБХОД.ВПамять(текСвобУч+ПозУчРазмера,-размсв);
    создуч:=текСвобУч+размсв;
    ОБХОД.ВПамять(создуч+ПозУчРазмера,размер);
    (* ссылки в списке свободных участков остались те же *)
  ИНАЧЕ         (* забираем целиком <текСвобУч> *)
                             создуч:=текСвобУч;
    ОБХОД.ВПамять(создуч+ПозУчРазмера,размсв);
                            (* новый <текСвобУч> *)
    ОБХОД.ИзПамяти(создуч+ПозУчСледСв,текСвобУч);
      (* удаляем <создуч> из списка свободных участков *)
    тк:=ОБХОД.Значение(ОпКуска,текКусок);

    ЕСЛИ создуч = тк.первсв ТО (* это <первсв> в куске *)
      тк.первсв:=текСвобУч
    ИНАЧЕ
      предсв:=тк.первсв; (* ищем предыдущий свободный участок *)
      уч:=предсв;
      ПОКА уч # создуч ВЫП
        предсв:=уч;
        ОБХОД.ИзПамяти(уч+ПозУчСледСв,уч)
      КОН;
      ОБХОД.ВПамять(предсв+ПозУчСледСв,текСвобУч)
    КОН
  КОН;
  ВОЗВРАТ создуч
КОН СоздатьУч;

=-*)


(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА DiT_и_mСлоёв(Отсчетов:ЦЕЛ):ЦЕЛ;                        (* Отсчетов=2^m  [А\0.1] *)
ПЕР
    начВремя,      (* в [мс от старта Windows] *)
  ВремяСчёта:ЦЕЛ;  (* в [мс] *)
  
  i:ЦЕЛ;

  t,dT:Вещ;

  кВекторД:кнВектор.Доступ;
УКАЗ
                     (* Быстродействие БПФ2 из А\кнБПФ2_сЗам_DiT_и_3цикла.отд *)
  СОЗДАТЬ(кВекторД,Отсчетов);
                                      (* заполняем комплексный вектор сигнала *)
  t:=0;
(*dT:=дМатем.ДваПИ*(1/Отсчетов);*)
  ОТ i:=0 ДО Отсчетов-1 ВЫП
                  (* <дМатем.sin(t);0> - вид входного  комплексного сигнала *)
(*
    кнМатем.алгебрВид(дМатем.sin(t),дМатем.cos(t),кВекторД[i]);
*)
    кнМатем.алгебрВид(            1,0,            кВекторД[i]);
(*  t:=t+dT *)           (* 0 <= t <= 2ПИ*(Отсчетов-1)/Отсчетов *)
  КОН;
                 (* [А\0.1] -DiT_и_mСлоёв- *)

    начВремя:= ОС.Время();                        (* в [мс от старта Windows] *)
(*
  ОТ i:=1 ДО L (* L = 2^28 ДЕЛИТЬ Отсчетов *) ВЫП
    кнБПФ2_сЗам_DiT_и_3цикла.DiT_и_mСлоёв(ВКЛ, кВекторД^);
    кнБПФ2_сЗам_DiT_и_3цикла.DiT_и_mСлоёв(ОТКЛ,кВекторД^);
  КОН;
*)
  ВремяСчёта:= ОС.Время()-начВремя;                                 (* в [мс] *)
             (* высвобождение памяти, выделенной для сигналов длиной Отсчётов *)
  кВекторД:=ПУСТО;

  ВОЗВРАТ ВремяСчёта                                                (* в [мс] *)

КОН DiT_и_mСлоёв;


(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Голова;
ПЕР
  m,    (* m - число слоёв, показатель степени двойки в N=2^m *)
  N,    (* N=2^m  - длина sin-синала в отсчётах *)
  M:ЦЕЛ;(* M=2^28 *)

  начТеста,            (* в [мс от старта Windows] *)
  конТеста,            (* в [мс от старта Windows] *)
  ВремяТестаLN:ЦЕЛ;    (* в [мс] при L повторах, длина синусоиды = N отсчётов *)
  всехТестов:ЦЕЛ;      (* в [мс] *)

  мсНаОтсчёт:ВЕЩ;      (* в [мс] на 1 отсчёт сигнала - ВремяТестаLN/L/N *)
УКАЗ                                 
             M:=1;     (* M=2^0=1, m=0 *)
  ОТ m:=1 ДО 27 ВЫП
             M:=M*2;   (* M=2^m=2^28 *)
  КОН;
(*
  НаЭкран.Цел4числа('M = 2**28 = %d ^',M,0,0,0);
*)
  начТеста:=ОС.Время();           (* время в мс, прошедшее от запуска Windows *)

  НаЭкран.ВсяЦепь("^Текущее время (по Гринвичу) - ");
  НаЭкран.ВремяТекущее;

(* старые алгоритмы БПФ по осн.2 - 
                                 DiT с Замещением и 3 цикла тоже с Замещением *)

  НаЭкран.ВсяЦепь("^Измерение быстродействия задачи");
  НаЭкран.ВсяЦепь("^ [0.1] А\кнБПФ2_сЗам_DiT_и_3цикла.DiT_и_mСлоёв()^");
  НаЭкран.ВсяЦепь("^--Время счёта теста БПФ2\ОБПФ2 L раз для синусоид разной длины N (64 разряда)--^");
  НаЭкран.ВсяЦепь("^       А\кнБПФ2_сЗам_DiT_и_3цикла.DiT_и_mСлоёв(ВКЛ, кВектор);");
  НаЭкран.ВсяЦепь("^       А\кнБПФ2_сЗам_DiT_и_3цикла.DiT_и_mСлоёв(ОТКЛ,кВектор);^");
  НаЭкран.ВсяЦепь("^===============================================================================");
  НаЭкран.ВсяЦепь("^  m :   N=2**m   : ВремяТестаLN (мс) : Время/L/N (мс на 1 Отсчёт) : Повторов L");
  НаЭкран.ВсяЦепь("^===============================================================================^");
                    N:=32;    (*     N=2^m, m=5 *)
  ОТ m:=6 ДО 27 ВЫП
                    N:=N*2;   (*     N=2^m      *)
        L:=M ДЕЛИТЬ N;        (* 2^28 ДЕЛИТЬ N  *)

ВЫБРАТЬ m ИЗ
| 16,20,24,25,26(*,27,28*):   (* в моей Win10-домашней x64
                                 этому приложению  OS Windows  на Глаголе
                                 было разрешено выделить только 2^25=32млн.(32 Mbyte) точек ~ 0.5 Гбайт ОЗУ
                                 А в w8.1 x86 было доступно аж  2^26=64млн.(64 Mbyte) точек ~ 1.0 Гбайт ОЗУ
                         а вообще любому приложению  OS Windows (в архитектуре x86) доступно не более 2 Гбайт ОЗУ,
                            т.е. в моей Win10-домашней x64 приложению  OS Windows  на Глаголе 
                                                  окзалось доступно гораздо менее 2 Гбайт ОЗУ
                               *)

    ВремяТестаLN:=DiT_и_mСлоёв(N);              (* в [мс]        *)
    мсНаОтсчёт:=ВремяТестаLN/L/N;               (* в [мс] на 1 отсчёт сигнала *)

    НаЭкран.Вещ4числа(" %2d , %10d , %10d ,         %12.6f           ",
                   m ,   N ,  ВремяТестаLN,  мсНаОтсчёт);
    НаЭкран.Вещ4числа(" %8d ^",
                   L,   0,0,0)
ИНАЧЕ 
КОН
  КОН;
(*
    конТеста:=ОС.Время();         (* время в мс, прошедшее от запуска Windows *)
*)
  всехТестов:=ОС.Время()-начТеста; (* в [мс] *)

  НаЭкран.ВсяЦепь("^Итоговое время измерения быстродействия задач отдела^    А\кнБПФ2_сЗам_DiT_и_3цикла.DiT_и_mСлоёв..() = ");
  НаЭкран.ВремяОтСтартаWindows(всехТестов);

КОН Голова;


(*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
УКАЗ
(*
  ВещОселок.Голова;(* Испытание на Whetstone в MIPS =
                    средняя скорость всех тестов с ВЕЩественными в 64 разряда *)
*)
(*
  Голова
*)
                     N:=16384;  (* 16 байт - это размер куска в Глаголе *)
  ОТ i:=0 ДО 6390 ВЫП
    СОЗДАТЬ(кВекторД,N);
    k:=i*N;
    НаЭкран.Цел4числа(" i= %10d N=%10d  k=i*N= %10d ^",i, N,k,0)
  КОН;

КОН РазмерВыделяемойПамяти_в_Win32.
