(*~\Глагол\ПриложенияЧисАн\64\д\Быстродействие\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                                     ОТДЕЛ ЦелОселок+;
(*============================================================================*
 * Приложение: "Dhrystone" - скорость целочисленных действий на Глаголе
 * Автор:      Reinhold P. Weicker
 * Издано в:   CACM Т.27, № 10, 10/84, с.1013
 *----------------------------------------------------------------------------*
 * Испытание на скорость работы обычного приложения. В этом приложении:
 *   присваиваний           - 53%
 *   целочисленных действий - 32%
 *   вызовов задач          - 15%.
 * Ничего путного данное приложение не вычисляет.
 *============================================================================*)

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

ВИД
(*  Enumeration   = ЦЕЛ; *)
(*  OneToThirty   = ЦЕЛ; *)
(*  OneToFifty    = ЦЕЛ; *)
(*  CapitalLetter = ЗНАК; *)
(*  String30      = ЦЕПЬ[31]; *)
(*  Array1Dim     = РЯД 51 ИЗ ЦЕЛ; *)
(*  Array2Dim     = РЯД 51,51 ИЗ ЦЕЛ; *)
  RecordType = НАБОР
    цPtrComp   :ЦЕЛ;
    цDiscr     :(*Enumeration*) ЦЕЛ;
    цEnumComp  :(*Enumeration*) ЦЕЛ;
    цComp      :(*OneToFifty*) ЦЕЛ;
    цепочкаComp:(*String30*) ЦЕПЬ[31] 
  КОН;

ПОСТ
  числоИспытаний = 5000;
  Ident1 = 1;
  Ident2 = 2;
  Ident3 = 3;
  Ident4 = 4;
  Ident5 = 5;

ПЕР
  цGlob   :ЦЕЛ;
  ключGlob  :КЛЮЧ;
  знак1Glob :ЗНАК;
  знак2Glob :ЗНАК;
  ряд1Glob  :(*Array1Dim*) РЯД 51 ИЗ ЦЕЛ;
  ряд2Glob  :(*Array2Dim*) РЯД 51,51 ИЗ ЦЕЛ;
  рядМоихНаборов :РЯД 3 ИЗ RecordType;

ПОСТ
  цPtrGlb     = 1;
  цPtrGlbNext = 2;


(*=рррррррррррррррррррррррр= реализация задач =рррррррррррррррррррррррррррррр=*)


(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc7(цПриёмникI1,цПриёмникI2,цПриёмникOut+:(*OneToFifty*)ЦЕЛ);
ПЕР
  цLoc:(*OneToFifty*) ЦЕЛ;
УКАЗ
  цLoc:=цПриёмникI1+2;
  цПриёмникOut:=цПриёмникI2+цLoc
КОН Proc7;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc3(inRecIdx+:ЦЕЛ);
УКАЗ
  ЕСЛИ inRecIdx # 0 ТО
    inRecIdx:=рядМоихНаборов[цPtrGlb].цPtrComp
  ИНАЧЕ
    цGlob:=100
  КОН;
  Proc7(10,цGlob,рядМоихНаборов[цPtrGlb].цComp)
КОН Proc3;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Func3(цEnumПриёмникIn:ЦЕЛ(*Enumeration*)):КЛЮЧ;
ПЕР
  цEnumLoc:ЦЕЛ (*Enumeration*);
УКАЗ
  цEnumLoc:=цEnumПриёмникIn;
  ВОЗВРАТ цEnumLoc = Ident3
КОН Func3;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc6(цEnumПриёмникIn,цEnumПриёмникOut+:ЦЕЛ(*Enumeration*));
УКАЗ
  цEnumПриёмникOut:=цEnumПриёмникIn;
  ЕСЛИ НЕ Func3(цEnumПриёмникIn) ТО
    цEnumПриёмникOut:=Ident4
  КОН;
  ВЫБРАТЬ цEnumПриёмникIn ИЗ
  | Ident1: цEnumПриёмникOut:=Ident1
  | Ident2: ЕСЛИ цGlob > 100 ТО
              цEnumПриёмникOut:=Ident1
            ИНАЧЕ
              цEnumПриёмникOut:=Ident4
            КОН
  | Ident3: цEnumПриёмникOut:=Ident2
  | Ident4: ;
  | Ident5: цEnumПриёмникOut:=Ident3
  КОН
КОН Proc6;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc1(inIdx:ЦЕЛ);
ПЕР
  i:ЦЕЛ;
УКАЗ
  i:=рядМоихНаборов[inIdx].цPtrComp;
  рядМоихНаборов[i]:=рядМоихНаборов[цPtrGlb];
  рядМоихНаборов[inIdx].цComp:=5;
  рядМоихНаборов[i].цComp:=рядМоихНаборов[inIdx].цComp;
  рядМоихНаборов[i].цPtrComp:=i;
  Proc3(рядМоихНаборов[i].цPtrComp);
  ЕСЛИ рядМоихНаборов[i].цDiscr = Ident1 ТО
    рядМоихНаборов[i].цComp:=6;
    Proc6(рядМоихНаборов[inIdx].цEnumComp,рядМоихНаборов[i].цEnumComp);
    рядМоихНаборов[i].цPtrComp:=рядМоихНаборов[цPtrGlb].цPtrComp;
    Proc7(рядМоихНаборов[i].цComp,10,рядМоихНаборов[i].цComp)
  ИНАЧЕ
    рядМоихНаборов[inIdx]:=рядМоихНаборов[i]
  КОН
КОН Proc1;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc2(цПриёмникIO+:(*OneToFifty*)ЦЕЛ);
ПЕР
  цLoc :(*OneToFifty*) ЦЕЛ;
  цEnumLoc:ЦЕЛ (*Enumeration*);
УКАЗ
  цLoc:=цПриёмникIO+10;
  ПОВТОРЯТЬ
    ЕСЛИ знак1Glob = 'A' ТО
      цLoc:=цLoc-1;
      цПриёмникIO:=цLoc-цGlob;
      цEnumLoc:=Ident1
    КОН
  ДО цEnumLoc = Ident1
КОН Proc2;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc4;
ПЕР
  ключLoc:КЛЮЧ;
УКАЗ
  ключLoc:=знак1Glob = 'A';
  ключLoc:=ключLoc ИЛИ ключGlob;
  знак2Glob:='B'
КОН Proc4;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc5;
УКАЗ
  знак1Glob:='A';
  ключGlob:=ОТКЛ
КОН Proc5;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc8(ряд1Приёмник+:(*Array1Dim*) РЯД (*51*) ИЗ ЦЕЛ;
             ряд2Приёмник+:(*Array2Dim*) РЯД (*51,51*) ИЗ РЯД ИЗ ЦЕЛ;
             цПриёмникI1,цПриёмникI2:(*OneToFifty*)ЦЕЛ);
ПЕР
  цLoc  :(*OneToFifty*) ЦЕЛ;
  цIndex:(*OneToFifty*) ЦЕЛ;
УКАЗ
  цLoc:=цПриёмникI1+5;
  ряд1Приёмник[цLoc]:=цПриёмникI2;
  ряд1Приёмник[цLoc+1]:=ряд1Приёмник[цLoc];
  ряд1Приёмник[цLoc+30]:=цLoc;
  ОТ цIndex:=цLoc ДО цLoc+1 ВЫП
     ряд2Приёмник[цLoc,цIndex]:=цLoc
  КОН;
  ряд2Приёмник[цLoc+20,цLoc]:=ряд1Приёмник[цLoc];
  цGlob:=5
КОН Proc8;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Func1(знакПриёмник1,знакПриёмник2:(*CapitalLetter*)ЗНАК):ЦЕЛ(*Enumeration*);
ПЕР
  зLoc1,зLoc2:(*CapitalLetter*) ЗНАК;
УКАЗ
  зLoc1:=знакПриёмник1;
  зLoc2:=зLoc1;
  ЕСЛИ зLoc2 # знакПриёмник2 ТО
    ВОЗВРАТ Ident1
  ИНАЧЕ
    ВОЗВРАТ Ident2
  КОН
КОН Func1;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Func2(цепочкаПриёмникI1+,цепочкаПриёмникI2+:(*String30*)ЦЕПЬ(*[31]*)):КЛЮЧ;
ПЕР
  цLoc :(*OneToThirty*) ЦЕЛ;
  зLoc :(*CapitalLetter*) ЗНАК;
УКАЗ
  цLoc:=2;
  ПОКА (цLoc <= 2) ВЫП
    ЕСЛИ Func1(цепочкаПриёмникI1[цLoc],цепочкаПриёмникI2[цLoc+1]) = Ident1 ТО
      зLoc:='A';
      цLoc:=цLoc+1
    КОН
  КОН;
  ЕСЛИ (зLoc >= 'W') И (зLoc <= 'Z') ТО цLoc:=7 КОН;
  ЕСЛИ зLoc = 'X' ТО
    ВОЗВРАТ ВКЛ
  АЕСЛИ цепочкаПриёмникI1 > цепочкаПриёмникI2 ТО
    цLoc:=цLoc+7;
    ВОЗВРАТ ВКЛ
  ИНАЧЕ
    ВОЗВРАТ ОТКЛ
  КОН
КОН Func2;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Proc0;
ПЕР
  цLoc1   :(*OneToFifty*) ЦЕЛ;
  цLoc2   :(*OneToFifty*) ЦЕЛ;
  цLoc3   :(*OneToFifty*) ЦЕЛ;
  зLoc    :ЗНАК;
  зIndex  :ЗНАК;
  цEnumLoc:ЦЕЛ (*Enumeration*);
  цепочка1Loc,
  цепочка2Loc:ЦЕПЬ[31] (*String30*);
  i,j     :ЦЕЛ;
УКАЗ
  рядМоихНаборов[цPtrGlb].цPtrComp:=цPtrGlbNext;
  рядМоихНаборов[цPtrGlb].цDiscr:=Ident1;
  рядМоихНаборов[цPtrGlb].цEnumComp:=Ident3;
  рядМоихНаборов[цPtrGlb].цComp:=40;
  рядМоихНаборов[цPtrGlb].цепочкаComp:='DHRYSTONE PROGRAM, SOME STRING';
  цепочка1Loc:="DHRYSTONE PROGRAM, 1'ST STRING";
  ОТ i:=1 ДО числоИспытаний ВЫП
    ОТ j:=1 ДО 1000 ВЫП
      Proc5;
      Proc4;
      цLoc1:=2;
      цLoc2:=3;
      цепочка2Loc:="DHRYSTONE PROGRAM, 2'ND STRING";
      цEnumLoc:=Ident2;
      ключGlob:=НЕ Func2(цепочка1Loc,цепочка2Loc);
      ПОКА цLoc1 < цLoc2 ВЫП
        цLoc3:=5*цLoc1-цLoc2;
        Proc7(цLoc1,цLoc2,цLoc3);
        цLoc1:=цLoc1+1
      КОН;
      Proc8(ряд1Glob,ряд2Glob,цLoc1,цLoc3);
      Proc1(цPtrGlb);
      зIndex:='A';
      ПОКА зIndex <= знак2Glob ВЫП
        ЕСЛИ цEnumLoc = Func1(зIndex,'C') ТО
          Proc6(Ident1,цEnumLoc)
        КОН;
        зIndex:=ВЗНАК(ВЦЕЛ(зIndex)+1)
      КОН;
      цLoc3:=цLoc2*цLoc1;
      цLoc2:=цLoc3 ДЕЛИТЬ цLoc1;
      цLoc2:=7*(цLoc3-цLoc2)-цLoc1;
      Proc2(цLoc1)
    КОН
  КОН
КОН Proc0;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Голова;
ПЕР
  начВремя:ЦЕЛ;
  времяРаботыВсехТестовЦЕЛ:ВЕЩ;
УКАЗ
  НаЭкран.ВсяЦепь("Испытание на Dhrystone^(время работы всех тестов с ЦЕЛыми в 32 разряда)");
                              начВремя:= ОС.Время();
  Proc0;
              времяРаботыВсехТестовЦЕЛ:=(ОС.Время()-начВремя)/1000; (* в сек *)
  НаЭкран.Вещ4числа(" = %f секунд = Dhrystone^(чем меньше, тем лучше)^",
              времяРаботыВсехТестовЦЕЛ,0,0,0)
КОН Голова;

(*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*)
УКАЗ
  Голова
КОН ЦелОселок.