unit Opers; {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! В Е К Т О Р Н Ы Е О П Е Р А Ц И И !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} interface uses WinTypes, WinProcs,gltype,glproc,MathObj,Math,srcs, Classes,SysUtils, MVTU_TLB; function TProduct(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TVecProduct(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TDiv(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TSum(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TVecSum(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TMultiply(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TVecMult(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TMul(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TDeMul(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TNote(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TUnpackMatr(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TPackMatr(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TVecSelect(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TCASENUM(at,adt:RealType;var time,dtime:RealType;var AU,AY:TPtrExt;var AX,ADX:array of RealType; var CU,CY : TIntArray;var Prop:TPtrArray;var Vars:Pointer;Action:Integer):Integer;export; function TEditUnpackMatr(var S : String;var P : array of Pointer;Which,Action:Integer;var F:File):Integer;export; function TEditPackMatr(var S : String;var P : array of Pointer;Which,Action:Integer;var F:File):Integer;export; {********************************************************************************************************} IMPLEMENTATION {********************************************************************************************************} type TMulRec = record Parms : TIntArray end; PVecMultRec = ^TVecMultRec; TVecMultRec = record N,M : ^Integer; Kij : TExtArray2 end; PDivRec = ^TDivRec; TDivRec = record what : ^Integer end; PPackRec = ^TPackRec; TPackRec = record N,M,tX,TY : ^Integer end; PVecSelectRec = ^TVecSelectRec; TVecSelectRec = record tSel : ^Integer; nSel : TIntArray; N : ^Integer; end; {--------------------------------------------------------------------------- Заметка Блок фактически является сервисным и предоставляет возмо;ность Пользователю выполнить поясняющие текстовые сообщения в любом схемном окне Проекта. Для ввода текста необходимо: выделить блок Заметка однократным щелчком левой клавиши “мыши”; используя меню Стиль и команду Заголовок блока “стереть” текст (None) и ввести новое текстовое сообщение; закрыть диалоговое окно, щелкнув “мышью” по кнопке ОК. Для “отбеливания” фона блока Заметка, выбора типа, размера и цвета шрифта необходимо использовать меню Стиль и соответствующие его команды. ---------------------------------------------------------------------------} function TNote; begin Result:=0 end;{END TNote} {--------------------------------------------------------------------------- РАЗМНОЖИТЕЛЬ Блок реализует функции многоканального усилительного звена: уi(t) = Ki*x(t), где yi(t) - векторный выходной сигнал; x(t) - скалярный входной сигнал. Для работы блока в поле диалоговой строке необходимо задать вектор коэффициентов усиления Ki (через пробел). ---------------------------------------------------------------------------} function TMultiplyConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Размножитель'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'M',PChar(ConvertVector(PropStr[0])),Res); finally end; end; end; function TMultiply; var j : Integer; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TMultiplyConvert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : begin CU.arr^[0]:=1;CY.arr^[0]:=Count end; f_InitState, f_GoodStep, f_RestoreOuts, f_UpdateJacoby, f_UpdateOuts : for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=AU.Ptr(0).arr^[0]*arr^[j]; end end; {--------------------------------------------------------------------------- ВЕКТОРНЫЙ РАЗМНОЖИТЕЛЬ Блок размножает входной векторный сигнал у[i,j](t) = K[i,j]*x[i](t), i=1,N;j=1,M где N - размерность входного векторного сигнала x; M - коэффициент размножения входного вектора; K[i,j] - матрица коэффициентов усиления размером N*M y[i][j](t) - элемент векторного выходного сигнала размерностью M*N; x[i](t) - элемент векторного входного сигнала; Для работы блока необходимо задать : N - размер входного вектора; M - коэффициент размножения ; K - матрица коэффициентов; ---------------------------------------------------------------------------} function TVecMultiplyConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Размножитель'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Присваиваем параметры для блока MVTU.SetBlockProp(BlockId,'M',PChar(ConvertMatrix(PropStr[2])),Res); finally end; end; end; function TVecMult; var i,j,k : Integer; begin Result:=0; with PVecMultRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TVecMultiplyConvert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : begin CU.arr^[0]:=N^; CY.arr^[0]:=M^*N^ end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : begin k:=0; for j:=0 to M^-1 do for i:=0 to N^-1 do begin AY.Ptr(0).arr^[k]:=AU.Ptr(0).arr^[i]*Kij.val(i,j); inc(k) end end; end end; {--------------------------------------------------------------------------- Мультиплексор Блок реализует “сжатие” входных сигналов в векторный выходной сигнал типа “шина” данных. Входами могут быть как скалярные, так и векторные (“многожильные”) сигналы. Для работы блока необходимо задать (через пробел) количество сигналов на каждом входном порте блока. Например: 2 5 3. Это соответствует “сжатию” 2 сигналов на 1-ом входе, 5 сигналов на 2-ом входе и 3 сигналов на 3-ем входе в один 10-ти “жильный” векторный выход. ---------------------------------------------------------------------------} function TMultiplexorConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Мультиплексор'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with TMulRec(Prop.arr^[0]) do try //Устанавливаем количество входных портов MVTU.SetBlockProp(BlockId,'nport',PChar(IntToStr(Parms.Count)),Res); MVTU.ExecutePropScript(BlockId,Res,Res); finally end; end; end; function TMul; var s,i,j : Integer; begin Result:=0; with TMulRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TMultiplexorConvert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : begin s:=0; for j:=0 to CU.Count-1 do begin if arr^[j] >= 0 then CU.arr^[j]:=arr^[j]; s:=s+CU.arr^[j]; end; CY.arr^[0]:=s end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : begin s:=0; for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do begin AY.Ptr(0).arr^[s]:=AU.Ptr(i).arr^[j]; Inc(s) end end; end end; {--------------------------------------------------------------------------- Демультиплексор Блок реализует “расщепление” векторного входного сигнала в отдельные выходные сигналы. Выходами могут быть как скалярные, так и векторные (“много;ильные” сигналы). Для работы блока необходимо задать (через пробел) количество сигналов на ка;дом выходном порте блока. Например: 5 4 1. Это соответствует 5 сигналам на 1-ом выходе, 4 сигналам на 2-ом выходе и 1 сигналу на 3-ем выходе при “расщеплении” одного 10-ти “;ильного” векторный входа. ---------------------------------------------------------------------------} function TDeMultiplexorConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Демультиплексор'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with TMulRec(Prop.arr^[0]) do try //Устанавливаем количество входных портов MVTU.SetBlockProp(BlockId,'a',PChar(ConvertVector(PropStr[0])),Res); MVTU.ExecutePropScript(BlockId,Res,Res); finally end; end; end; function TDeMul; var s,i,j : Integer; begin Result:=0; with TMulRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TDeMultiplexorConvert); f_GetDeriCount, f_GetStateCount : Result:=0; f_GetInit : Result:=0; f_GetCount : begin s:=0; for j:=0 to CY.Count-1 do begin s:=s+arr^[j]; CY.arr^[j]:=arr^[j] end; CU.arr^[0]:=s end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : begin s:=0; for i:=0 to AY.Count-1 do for j:=0 to AY.Ptr(i).Count-1 do begin AY.Ptr(i).arr^[j]:=AU.Ptr(0).arr^[s]; Inc(s) end end; end end; {--------------------------------------------------------------------------- Блок имеет один вход, в котором в упакованном виде (в одномерном массиве) содержатся элементы прямоугольной матрицы A. Параметры блока: N - Число строк в матрице M - Число столбцов в матрице tY- Тип преобразования (по строкам или по столбцам) tX- Тип упаковки матрицы (по строкам или по столбцам) Алгоритм работы блока: Входной одномерный массив размерностью N*M, в котором содержатся элементы матрицы A в упакованном виде (по строкам или по столбцам в зависимости от значения флага tX) В зависимости от значения флага tY матрица А распаковывается в N или M выходных сигналов, каждый из которых содержит соответственно столбец или строку матрицы ---------------------------------------------------------------------------} function TUnpackMatrConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Распаковка матрицы'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with PPackRec(Prop.arr)^ do try MVTU.SetBlockProp(BlockId,'tx',PChar(IntToStr(tx^)),Res); MVTU.SetBlockProp(BlockId,'ty',PChar(IntToStr(ty^)),Res); MVTU.SetBlockProp(BlockId,'nrow',PChar(PropStr[0]),Res); MVTU.SetBlockProp(BlockId,'ncol',PChar(PropStr[1]),Res); finally end; end; end; function TUnpackMatr; var i,j : Integer; begin Result:=0; with PPackRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TUnpackMatrConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : begin CU.arr^[0]:=N^*M^; for i:=0 to CY.Count-1 do if tY^ = 0 then CY.arr^[i]:=M^ else CY.arr^[i]:=N^ end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : if (tX^ = 0) then begin if tY^ = 0 then for i:=0 to AY.Count-1 do for j:=0 to AY.Ptr(i).Count-1 do AY.Ptr(i).arr^[j]:=AU.Ptr(0).arr^[M^*i+j] else for i:=0 to AY.Count-1 do for j:=0 to AY.Ptr(i).Count-1 do AY.Ptr(i).arr^[j]:=AU.Ptr(0).arr^[i+M^*j] end else begin if tY^ = 1 then for i:=0 to AY.Count-1 do for j:=0 to AY.Ptr(i).Count-1 do AY.Ptr(i).arr^[j]:=AU.Ptr(0).arr^[N^*i+j] else for i:=0 to AY.Count-1 do for j:=0 to AY.Ptr(i).Count-1 do AY.Ptr(i).arr^[j]:=AU.Ptr(0).arr^[i+N^*j] end; end end; function TEditUnpackMatr; begin Result:=0; case Action of e_inport : Result:=1; e_outport: if PInteger(P[3])^ = 0 then Result:=PInteger(P[0])^ else Result:=PInteger(P[1])^; end; end; {--------------------------------------------------------------------------- Блок имеет один вход, в котором в упакованном виде (в одномерном массиве) содержатся элементы прямоугольной матрицы A. Параметры блока: N - Число строк в матрице M - Число столбцов в матрице tY- Тип преобразования (по строкам или по столбцам) tX- Тип упаковки матрицы (по строкам или по столбцам) Алгоритм работы блока: Входной одномерный массив размерностью N*M, в котором содержатся элементы матрицы A в упакованном виде (по строкам или по столбцам в зависимости от значения флага tX) В зависимости от значения флага tY матрица А распаковывается в N или M выходных сигналов, каждый из которых содержит соответственно столбец или строку матрицы ---------------------------------------------------------------------------} function TPackMatrConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Запаковка матрицы'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with PPackRec(Prop.arr)^ do try MVTU.SetBlockProp(BlockId,'tx',PChar(IntToStr(tx^)),Res); MVTU.SetBlockProp(BlockId,'ty',PChar(IntToStr(ty^)),Res); MVTU.SetBlockProp(BlockId,'nrow',PChar(PropStr[0]),Res); MVTU.SetBlockProp(BlockId,'ncol',PChar(PropStr[1]),Res); finally end; end; end; function TPackMatr; var i,j : Integer; begin Result:=0; with PPackRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TPackMatrConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : begin CY.arr^[0]:=N^*M^; for i:=0 to CU.Count-1 do if tX^ = 0 then CU.arr^[i]:=M^ else CU.arr^[i]:=N^ end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : if (tX^ = 0) then begin if tY^ = 0 then for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do AY.Ptr(0).arr^[M^*i+j]:=AU.Ptr(i).arr^[j] else for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do AY.Ptr(0).arr^[i+N^*j]:=AU.Ptr(i).arr^[j] end else begin if tY^ = 1 then for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do AY.Ptr(0).arr^[N^*i+j]:=AU.Ptr(i).arr^[j] else for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do AY.Ptr(0).arr^[i+M^*j]:=AU.Ptr(i).arr^[j] end; end end; function TEditPackMatr; begin Result:=0; case Action of e_outport : Result:=1; e_inport : if PInteger(P[2])^ = 0 then Result:=PInteger(P[0])^ else Result:=PInteger(P[1])^; end; end; {-------------------------------------------------------------------------- Блок имеет один вход, в котором в упакованном виде (в одномерном массиве) содержатся элементы прямоугольной матрицы A. Параметры блока: N - Число строк в матрице M - Число столбцов в матрице tY- Тип преобразования (по строкам или по столбцам) tX- Тип упаковки матрицы (по строкам или по столбцам) Алгоритм работы блока: Входной одномерный массив размерностью N*M, в котором содержатся элементы матрицы A в упакованном виде (по строкам или по столбцам в зависимости от значения флага tX) В зависимости от значения флага tY матрица А распаковывается в N или M выходных сигналов, каждый из которых содержит соответственно столбец или строку матрицы ---------------------------------------------------------------------------} function TVecSelectConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Выборка из вектора'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: with PVecSelectRec(Prop.arr)^ do try MVTU.SetBlockProp(BlockId,'tsel',PChar(IntToStr(tsel^)),Res); MVTU.SetBlockProp(BlockId,'nsel',PChar(PropStr[1]),Res); MVTU.SetBlockProp(BlockId,'N',PChar(PropStr[2]),Res); finally end; end; end; function TVecSelect; var i,k : Integer; P : Pointer; x : RealType; begin Result:=0; with PVecSelectRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TVecSelectConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : case tSel^ of 0:begin k:=0; for i:=0 to nSel.Count-1 do k:=max(k,nSel.arr^[i]); if CU.arr^[0] < k then CU.arr^[0]:=k; CY.arr^[0]:=nSel.Count end; 1:CY.arr^[0]:=CU.arr^[0] div 2; 2:begin if (CU.arr^[0] mod 2) = 0 then k:=0 else k:=1; CY.arr^[0]:=CU.arr^[0] div 2+k end; 3,4: begin if CU.arr^[0] < N^ then CU.arr^[0]:=N^; CY.arr^[0]:=N^ end; 5:begin if (CU.arr^[0] mod N^) = 0 then k:=0 else k:=1; CY.arr^[0]:=CU.arr^[0] div N^+k; end; 6,7,8:CY.arr^[0]:=CU.arr^[0]; end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : case tSel^ of 0:for i:=0 to nSel.Count-1 do AY.Ptr(0).arr^[i]:=AU.Ptr(0).arr^[nSel.arr^[i]-1]; 1:begin k:=1; for i:=0 to AY.Ptr(0).Count-1 do begin AY.Ptr(0).arr^[i]:=AU.Ptr(0).arr^[k]; Inc(k,2) end end; 2:begin k:=0; for i:=0 to AY.Ptr(0).Count-1 do begin AY.Ptr(0).arr^[i]:=AU.Ptr(0).arr^[k]; Inc(k,2) end end; 3:Move(AU.Ptr(0).arr^,AY.Ptr(0).arr^,N^*SOfR); 4:begin p:=@AU.Ptr(0).arr^[AU.Ptr(0).Count-N^]; Move(p^,AY.Ptr(0).arr^,N^*SOfR) end; 5:begin k:=0; for i:=0 to AY.Ptr(0).Count-1 do begin AY.Ptr(0).arr^[i]:=AU.Ptr(0).arr^[k]; Inc(k,N^) end end; 6:for i:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[i]:=AU.Ptr(0).arr^[AU.Ptr(0).Count-i-1]; 7:begin Move(AU.Ptr(0).arr^,AY.Ptr(0).arr^,AU.Ptr(0).Count*SOfR); rQuickSort(AY.Ptr(0).arr^,0,AY.Ptr(0).Count-1); end; 8:begin Move(AU.Ptr(0).arr^,AY.Ptr(0).arr^,AU.Ptr(0).Count*SOfR); rQuickSort(AY.Ptr(0).arr^,0,AY.Ptr(0).Count-1); for i:=0 to AY.Ptr(0).Count div 2-1 do begin x:=AY.Ptr(0).arr^[AY.Ptr(0).Count-i-1]; AY.Ptr(0).arr^[AY.Ptr(0).Count-i-1]:=AY.Ptr(0).arr^[i]; AY.Ptr(0).arr^[i]:=x end end; end; end end; {--------------------------------------------------------------------------} {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! О П Е Р А Ц И И !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} {--------------------------------------------------------------------------- Сумматор Блок реализует операцию знакового поэлементного сложения входных сигналов: у(t)=Сумма ( a[i]*u[i][j] ), i=1..N, j=1..M(i), где у(t) - выходной сигнал; N - число входных сигналов; M(i) - размер i-го входного сигнала; u - входные сигналы; a - вектор весовых коэффициентов для каждого из входов ---------------------------------------------------------------------------} function TSumConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Суммирование элементов вектора'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Устанавливаем к-ты сумматора MVTU.SetBlockProp(BlockId,'a',PChar(ConvertVector(PropStr[0])),Res); MVTU.ExecutePropScript(BlockId,Res,Res); finally end; end; end; function TSum; var i,j : Integer; s : RealType; u : double; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TSumConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : CY.arr^[0]:=1; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : begin s:=0.0; for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do begin u:=AU.Ptr(i).arr^[j]*arr^[i]; s:=s + u; if abs(s) > ymax then begin Result:=er_overflow_y;exit end end; AY.Ptr(0).arr^[0]:=s end; end end; {--------------------------------------------------------------------------- Векторный сумматор Блок реализует операцию взвешенного векторного сложения N входных сигналов. Алгоритм работы блока: 1. В параметрах блока задается массив взвешенных коэффициентов a[i],i=1,...,N для каждого из входов. Число входов автоматически равно размерности этого массива N. 2. Размер выходного сигнала M равен максимальному из размеров входных сигналов M=max(Dim(u(i))),i=1,...,N. 3. j-ый элемент выходного массива есть взвешенная сумма j-ых элементов по всем входам (y[j]=Sum(a[i]*u(i)[j];i=1,N;j=1,M. Если j-го элемента в i-ом входе u(i)[j] нет, он принимается равным 0. ---------------------------------------------------------------------------} function TVecSumConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Сумматор'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Устанавливаем к-ты сумматора MVTU.SetBlockProp(BlockId,'a',PChar(ConvertVector(PropStr[0])),Res); MVTU.ExecutePropScript(BlockId,Res,Res); finally end; end; end; function TVecSum; var i,j : Integer; u: realtype; begin Result:=0; with TSourceRec(Prop.arr^[0]).Parms do case Action of f_GetConvertFuncAdr: Result:=integer(@TVecSumConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : begin j:=0; for i:=0 to CU.Count-1 do j:=max(CU.arr^[i],j); CY.arr^[0]:=j end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : begin for i:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[i]:=0.0; for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do begin u:=AU.Ptr(i).arr^[j]*arr^[i]; AY.Ptr(0).arr^[j]:=AY.Ptr(0).arr^[j] + u; if abs(AY.Ptr(0).arr^[j]) > ymax then begin Result:=er_overflow_y;exit end end end; end end; {--------------------------------------------------------------------------- Умножение Блок реализует операцию умножения двух сигналов: у(t)=х1(t)*х2(t), где y(t),x1(t) - вектора; x2(t) - скаляр где у(t) - выходной сигнал; x1(t), x2(t) - входные сигналы. Для работы блока параметры не требуются. ---------------------------------------------------------------------------} function TProductConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Умножение на число'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TProduct; var j : Integer; x : RealType; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TProductConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : begin CU.arr^[1]:=1;CY.arr^[0]:=CU.arr^[0] end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : for j:=0 to AY.Ptr(0).Count-1 do begin x:=AU.Ptr(0).arr^[j]*AU.Ptr(1).arr^[0]; if abs(x) > ymax then begin Result:=er_overflow_y;exit end; AY.Ptr(0).arr^[j]:=x end; end end; {--------------------------------------------------------------------------- Векторное умножение Блок реализует операцию векторного умножения N входных сигналов. Алгоритм блока: 1. В параметрах блока задается число входов. 2. Размер выходного сигнала равен максимальному из размеров входных сигналов. 3. i-ый элемент выходного массива есть произведение i-ых элементов по всем входам. Если i-го элемента во входе нет, он принимается равным 1. ---------------------------------------------------------------------------} function TVecProductConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Перемножитель'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); //Конвертируем и устанавливаем параметры при помощи интерфейса МВТУ cnv_Convert: try //Устанавливаем к-ты сумматора MVTU.SetBlockProp(BlockId,'nport',PChar(PropStr[0]),Res); MVTU.ExecutePropScript(BlockId,Res,Res); finally end; end; end; function TVecProduct; var i,j : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TVecProductConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : begin j:=0; for i:=0 to CU.Count-1 do j:=max(j,CU.arr^[i]); CY.arr^[0]:=j end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : begin for j:=0 to AY.Ptr(0).Count-1 do AY.Ptr(0).arr^[j]:=1.0; for i:=0 to AU.Count-1 do for j:=0 to AU.Ptr(i).Count-1 do begin AY.Ptr(0).arr^[j]:=AY.Ptr(0).arr^[j]*AU.Ptr(i).arr^[j]; if abs(AY.Ptr(0).arr^[j]) > ymax then begin Result:=er_overflow_y;exit end end end; end end; {--------------------------------------------------------------------------- Деление Блок реализует операцию деления 1-го входного сигнала на 2-ой входной сигнал. Алгоритм работы блока: 1. В параметрах блока задается тип второго входа - скалярный или векторный. 2. Размер выходного сигнала равен размеру 1-го входного сигнала. 3. Если 2-ой вход скалярный, то i-ый элемент выходного массива есть результат деления i-го элемента 1-го входа на первый (и единственный) элемент 2-го входа. Если 2-ой вход векторный, то размерности всех входов и выхода блока одинаковы, и производится поэлементное деление 1-го входа на второй. ---------------------------------------------------------------------------} function TDivConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName1:PChar = 'Деление скаляра на вектор'; RecName2:PChar = 'Делитель'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 //Для этого блока в зависимости от параметра в МВТУ-4 будут созданы РАЗНЫЕ БЛОКИ !!! cnv_GetRecName: with PDivRec(Prop.arr)^ do case what^ of 0: Result:=integer(RecName1); 1: Result:=integer(RecName2); end; end; end; function TDiv; var j : Integer; x : RealType; begin Result:=0; with PDivRec(Prop.arr)^ do case Action of f_GetConvertFuncAdr: Result:=integer(@TDivConvert); f_GetDeriCount, f_GetStateCount, f_GetInit : Result:=0; f_GetCount : begin if what^ = 0 then CU.arr^[1]:=1 else CU.arr^[1]:=CU.arr^[0]; CY.arr^[0]:=CU.arr^[0] end; f_InitState, f_RestoreOuts, f_UpdateJacoby, f_GoodStep, f_UpdateOuts : for j:=0 to AY.Ptr(0).Count-1 do begin if what^ = 0 then x:=AU.Ptr(1).arr^[0] else x:=AU.Ptr(1).arr^[j]; if x = 0.0 then begin Result:=er_zerodivide;exit end; x:=AU.Ptr(0).arr^[j]/x; if abs(x) > ymax then begin Result:=er_overflow_y;exit end; AY.Ptr(0).arr^[j]:=x end; end end; {--------------------------------------------------------------------------- CASE Блок реализует операцию Алгоритм работы блока: ---------------------------------------------------------------------------} function TCASENUMConvert(Action: integer; Vars: Pointer; Prop: TPtrArray; PropStr: TStringList; BlockId: integer; var MVTU: IMVTU_Server):integer; const RecName:PChar = 'Динамическая выборка'; var Res: integer; begin case Action of //Возвращаем ссылку на имя записи в базе МВТУ-4 cnv_GetRecName: Result:=integer(RecName); end; end; function TCASENUM; var k : Integer; begin Result:=0; case Action of f_GetConvertFuncAdr: Result:=integer(@TCASENUMConvert); f_GetCount : begin CU.arr^[0]:=1; CY.arr^[0]:=1 end; f_InitState, f_RestoreOuts, f_GoodStep : begin k:=round(AU.Ptr(0).arr^[0]); if k < 1 then k:=1; if k > AU.Ptr(1).Count then k:=AU.Ptr(1).Count; AY.Ptr(0).arr^[0]:=AU.Ptr(1).arr^[k-1] end; end end; end.