Операции над элементарными слагаемыми


В исходных текстах вычислительных процедур определим элементарное слагаемое в виде структуры:

{ for example case expansion with Bessel function }
unit unalltyp ; { for different types for some case }
interface
const
  maxarr = 74967 ;  // dimension of arrays
  numsel = 8 ;      // selected elements  but only 8 in use
  maxsel : array[1..numsel] of ShortInt = // maximum power
           ( 10 ,    // e                 in use
             10 ,    // s=sin(i)          in use
             10 ,    // e'                in use
             10 ,    // s'=sin(i')        in use
             30 ,    // a  semimajor axis in use
             30 ,    // a' semimajor axis in use
              8 ,    // n  mean motion    im use
              8 ) ;  // n' mean motion    in us
  maxarg = 6 ;       // number of arguments l g h l' g' h'
type
  TDimSel  = array[1..numsel] of ShortInt ; { for power of var. 8 bytes }
  TDimArg  = array[1..maxarg] of ShortInt ; { for arguments 6 bytes }
  { elementary term has a form
     A                    amplitude numeric value
      *e^i_1*(sin i)^i_3       
       *e'^i_2*(sin i')^i_4
        *a^i_5*a'^i_6
         *cos(k_1*l+k_2*g+k_3*h+k_4*l'+k_5*g'+k_6*h') }
  TRowVar  = record
               npa  : Byte ;    { the first  planet    1 byte }
               npb  : Byte ;    { the second planet    1 byte }
               amp  : Extended ; { amplitude simple }
               mec  : TDimSel ; { power of variables   8 bytes }
               mar  : TDimArg ; { coef. for argument   6 bytes }
               fcs  : Char ;    { function sin or cos  1 byte  }
             end;
type
  { for the array }
  TRowDim  = array[1..maxarr] of TRowVar ;
  TOrdNum  = array[0..27] of longint ;
type
  { for the pointer to array }
  TRowPtr  = ^TRowDim ;
implementation
end.
 

Определим также несколько динамических массивов и выделим для них место в оперативной памяти компьютера:

{ for global variables }
unit unallvar ;
interface
uses
  unalltyp ; { for all types }
var
  maxsum  : ShortInt ;{ maximum for sum of powers }
  memrec  : Word ;    { size of record TRowVar UnAllTyp }
  recnul  : TRowVar ; { for nullo record type from UnAllTyp }
  mecone  : longint ;    { number of terms in rowone array }
  mectwo  : longint ;    { number of terms in rowtwo array }
  mectre  : longint ;    { number of terms in rowtre array }
  mecfur  : longint ;    { number of terms in rowfur array }
  mecfiv  : longint ;    { number of terms in rowfiv array }
  mecsix  : longint ;    { number of terms in rowsix array }
  mecaux  : longint ;    { number of terms in rowaux array }
  mectmp  : longint ;    { number of terms in tempor array }
  meccoh  : longint ;    { number of terms in rowcoh array }
  rowone  : TRowPtr ; { to the pointer for array unalltyp }
  rowtwo  : TRowPtr ; { to the pointer for array }
  rowtre  : TRowPtr ; { to the pointer for array }
  rowfur  : TRowPtr ; { to the pointer for array }
  rowfiv  : TRowPtr ; { to the pointer for array }
  rowsix  : TRowPtr ; { to the pointer for array }
  rowaux  : TRowPtr ; { to the pointer for array }
  rowtmp  : TRowPtr ; { pointer for tempor array }
  rowcoh  : TRowPtr ; { pointer for rowcoh array }
implementation
end.
unit ungetmem ; { for dynamic memory }
interface
procedure GetRowMem ;
procedure FreeRowMem ;
implementation
uses
  unalltyp , { for global types }
  unallvar ; { for global variables }
procedure GetRowMem ;  { array to heap by pointer }
begin
  memrec:=SizeOf(TRowVar);
  GetMem(rowone,SizeOf(TRowDim));
  GetMem(rowtwo,SizeOf(TRowDim));
  GetMem(rowtre,SizeOf(TRowDim));
  GetMem(rowfur,SizeOf(TRowDim));
  GetMem(rowfiv,SizeOf(TRowDim));
  GetMem(rowsix,SizeOf(TRowDim));
  GetMem(rowaux,SizeOf(TRowDim));
  GetMem(rowtmp,SizeOf(TRowDim));
  GetMem(rowcoh,SizeOf(TRowDim));
end;
procedure FreeRowMem ; { array to heap by pointer }
begin
  FreeMem(rowcoh,SizeOf(TRowDim));
  FreeMem(rowtmp,SizeOf(TRowDim));
  FreeMem(rowaux,SizeOf(TRowDim));
  FreeMem(rowsix,SizeOf(TRowDim));
  FreeMem(rowfiv,SizeOf(TRowDim));
  FreeMem(rowfur,SizeOf(TRowDim));
  FreeMem(rowtre,SizeOf(TRowDim));
  FreeMem(rowtwo,SizeOf(TRowDim));
  FreeMem(rowone,SizeOf(TRowDim));
end;
end.
 

Выполним присвоение начальных значений:

unit UnRowIni ; { for initial data for rows }
interface
procedure RecNullo ; { without planets numbers }
procedure RowNullo ; { initial nullo for six arrays }
procedure RowTreNul ; { initial nullo for rowtre^ rowaux^ }
implementation
uses
  UnAllTyp , { for type TRowVar var row one two tre aux coh }
  UnAllVar ; { for global variables }
procedure RecNullo ; { without planets numbers }
var
  j  : Byte ;
begin
  recnul.npa:=0;
  recnul.npb:=0;
  recnul.amp:=0.0;  { amplitide nullo initial }
  for j:=1 to numsel do  { numsel = 4  e s e' s' }
    recnul.mec[j]:=0; { for all power nullo }
  for j:=1 to maxarg do
    recnul.mar[j]:=0; { for all argument nullo }
  recnul.fcs:='C';  { let it be cosinus but nullo amplitude }
end;
procedure RowNullo ; { initial nullo for six arrays }
var
  i  : longint ;    { simple count }
begin
  mecone:=0; { initial nullo terms in six array }
  mectwo:=0;
  mectre:=0;
  mecfur:=0; { initial nullo terms in six array }
  mecfiv:=0;
  mecsix:=0;
  mecaux:=0;
  mectmp:=0;
  meccoh:=0;
  for i:=1 to maxarr do  { const maxe from UnTypEcc }
    begin
      rowone^[i]:=recnul;
      rowtwo^[i]:=recnul;
      rowtre^[i]:=recnul;
      rowfur^[i]:=recnul;
      rowfiv^[i]:=recnul;
      rowsix^[i]:=recnul;
      rowaux^[i]:=recnul;
      rowtmp^[i]:=recnul;
      rowcoh^[i]:=recnul;
    end;
end;
procedure RowTreNul ; { initial nullo values for rowtre array }
var
  i  : longint ;    { simple count }
begin
  mectre:=0;
  mecaux:=0;
  for i:=1 to maxarr do  { const maxe from UnTypEcc }
    begin
      rowtre^[i]:=recnul;
      rowaux^[i]:=recnul;
    end;
end;
end.
 

Для элементарных слагаемых опеределены операции сложения, умножения и приведения подобных членов:

unit UnRowMul ; { to multiply two rows result to rowtre }
interface
uses
  Windows  , { for function GetTickCount }
  unalltyp ; { for global types }
procedure AmpFactor ( c  : Extended ;  var  a  : extended ); // UnTypVar
procedure AmplMults ( a , b  : extended ;  var  c  : extended ) ; // UnTypVar
procedure AmplPower ( x  : extended ;  var  y : extended ) ; { UnTypVar }
function BooMaxSum ( a , b  : TRowVar ) : Boolean ;
procedure PowerParm ( a , b  : TRowVar ;  var  c  : TRowVar ) ;
function BooComPair ( x , e  : TRowVar ) : Boolean ;
function BooCompare ( x , e  : TRowVar ) : Boolean ;
procedure ToPositiveA ( var  x  : TRowVar ) ;
procedure ForSinOrCos ( x , y  : TRowVar ;
                        var  a , b  : extended ;
                        var  c  : Char ) ;
procedure ToMultRow ( ua , ub  : TRowVar ) ;  { simple records }
procedure ForAmpNul ;        { rowtre may has nullo amplitudes }
procedure MultForRow ( am  : Extended ) ; { am * rowone * rowtwo = rowtre }
implementation
uses
  UnAllVar , { for global variables  }
  UnRowLow , { for procedure LowerAux }
  ungetida ; { for current date and time function strCurtida }
procedure AmpFactor ( c  : Extended ;  var  a  : extended );
begin
  a:=c*a; { amplitude with the factor c }
end;
procedure AmplMults ( a , b   : extended ;   { two amplitudes }
                      var  c  : extended ) ; { result amplitude }
begin { to multiple two amplitudes }
  c:=a*b; { only amplitudes }
end;
{ amplitude in power -1 :  y = 1/x = x^(-1) }
procedure AmplPower ( x  : extended ;  var  y : extended ) ;
begin
  if  ( Abs(x) < 1.0e-15 )  { too small }
    then  y:=0.0            { nullo simple }
    else  y:=1.0/x;         { +1/x coefficients }
end;
function BooMaxSum ( a , b  : TRowVar ) : Boolean ;
var
  m  : ShortInt ;
begin
  m:=a.mec[1]+b.mec[1]+a.mec[2]+b.mec[2]   // e  s
    +a.mec[3]+b.mec[3]+a.mec[4]+b.mec[4];  // e' s'
  if  m > maxsum       // const maxsum from UnTypVar
    then               // sum of powers is too large
      BooMaxSum:=False // exit no term to row
    else
      BooMaxSum:=True; // there is our term
end;
procedure PowerParm ( a , b  : TRowVar ;  var  c  : TRowVar ) ;
var                 // to analyse power of variables
  i  : Byte ;
begin
  c.npa:=a.npa; { only for selected pair }
  c.npb:=a.npb; { a.npa npb = b.npa npb  }
  for i:=1 to numsel do { for each parameter numsel = 8 e s e' s' }
    c.mec[i]:=a.mec[i]+b.mec[i]; { to sum of two powers a a' n n' }
end;
function BooComPair ( x , e  : TRowVar ) : Boolean ;
begin
  BooComPair:= ( ( x.npa = e.npa ) and ( x.npb = e.npb ) ) ;
end;
function BooCompare ( x , e  : TRowVar ) : Boolean ;
var
  j  : Byte ;
  b  : Boolean ;
begin
  b:= ( x.fcs = e.fcs )  ;  { characters for functions 'C' or 'S' }
  if  b
    then  { to compare numbers for two planets }
      b:=BooComPair(x,e);
  j:=0;
  while  ( b and ( j < numsel ) )  do
    begin
      j:=j+1;
      b:= ( x.mec[j] = e.mec[j] ) ; { the powers of variables }
    end;
  j:=0;
  while  ( b and ( j < maxarg ) )  do
    begin
      j:=j+1;
      b:= ( x.mar[j] = e.mar[j] ) ; { the arguments of variables }
    end;
  BooCompare:=b; { true if it is similar term or false if it is not }
end;
procedure TheNextTerm ( x  : TRowVar ) ; { to find similar if it exists }
var
  m  : longint ;
  b  : Boolean ;
  e  : TRowVar ; { current record for compare }
begin { to find similar terms for current term in array rowtre^[mectre] }
  b:=False;
  m:=0;       { nullo }
  while  ( ( not b ) and ( m < mectre ) )  do
    begin
      m:=m+1; { to try the next term }
      e:=rowtre^[m]; { current record for compare }
      b:=BooCompare(x,e);
    end;
  if  b          { there is similar term  }
    then         { to sum only amplitudes }
      rowtre^[m].amp:=rowtre^[m].amp+x.amp
    else         { there is no similar term in current array }
      begin      { it is our new term in result array }
        if  mectre = maxarr  then  Exit ; { too many terms }
        mectre:=mectre+1;
        rowtre^[mectre]:=x;
      end;
end;
procedure ToPositiveA ( var  x  : TRowVar ) ;
var
  i,j  : Byte ;
begin                  { to positive for the first nonnullo argument }
  for j:=1 to maxarg do
    begin
      if  x.mar[j] > 0
        then
          Exit ;               { well the argument is positive }
      if  x.mar[j] < 0         { the argument may be negative }
        then
          begin
            for i:=j to maxarg do   { to positive for the current argument }
              x.mar[i]:=-x.mar[i];
            if  x.fcs = 'S'    { for sinus function minus for amplitude }
              then
                AmpFactor(-1.0,x.amp); // minus for amplitude
            Exit ;             { well the argument is positive }
          end;
    end;
end;
procedure ForSinOrCos ( x , y  : TRowVar ;
                        var  a , b  : extended ;
                        var  c  : Char ) ;
begin                    { 2*cos(x)*sin(y) =-sin(x-y) + sin(x+y) }
  b:=a;                  { amlpitude may be minus }
  if  x.fcs = y.fcs      { 2*cos(x)*cos(y) = cos(x-y) + cos(x+y) }
    then                 { cos*cos or sin*sin }
      begin              { +cos(x-y) }
        c:='C';          { cosinus function as result }
        if  x.fcs = 'S'  { sin*sin case }
          then           { 2*sin(x)*sin(y) = cos(x-y) - cos(x+y) }
            AmpFactor(-1.0,b); { -cos(x+y) }
      end                { 2*sin(x)*cos(y) = sin(x-y) + sin(x+y) }
    else                 { sin*cos or cos*sin }
      begin              { +sin(x+y) }
        c:='S';          { sinus   function as result }
        if  x.fcs = 'C'  { cos*sin case }
          then           { 2*cos(x)*sin(y) =-sin(x-y) + sin(x+y) }
            AmpFactor(-1.0,a); { -sin(x-y) }
      end;
end;
procedure ToMultRow ( ua , ub  : TRowVar ) ;  { simple records }
var               { 2*cos(x)*cos(y) = cos(x-y) + cos(x+y) }
  j  : Byte ;     { 2*sin(x)*sin(y) = cos(x-y) - cos(x+y) }
  b  : extended ; { 2*sin(x)*cos(y) = sin(x-y) + sin(x+y) }
  x  : TRowVar ;  { 2*cos(x)*sin(y) =-sin(x-y) + sin(x+y) }
begin { from two record may be two new records }
  AmplMults(ua.amp,ub.amp,x.amp);   { to multiply amplitudes }
  if  ( ( Abs(x.amp) < 1.0e-19 )    { may be nearly nullo term }
       or ( not BooMaxSum(ua,ub) ) )
    then  Exit ;                    { sum of powers is too large }
  AmpFactor(0.5,x.amp);             { factor 0.5 for amplitude }
  PowerParm(ua,ub,x);               { to sum all powers }
  ForSinOrCos(ua,ub,x.amp,b,x.fcs); { amplitude function indentify }
  for j:=1 to maxarg do
    x.mar[j]:=ua.mar[j]-ub.mar[j];  { for the first  all arguments minus }
  ToPositiveA(x);
  TheNextTerm(x);                   { for minus in argument x-y }
  x.amp:=b;                         { for plus  in argument x+y }
  for j:=1 to maxarg do
    x.mar[j]:=ua.mar[j]+ub.mar[j];  { for the second all arguments  plus }
  ToPositiveA(x);
  TheNextTerm(x);
end;
procedure ForAmpNul ;        { rowtre may has nullo amplitudes }
var
  m  : longint ;
begin
  mecaux:=0;
  for m:=1 to mectre do
    if  ( Abs(rowtre^[m].amp) > 1.0e-17 )
      then
        begin
          mecaux:=mecaux+1;   { non nullo term }
          rowaux^[mecaux]:=rowtre^[m];
        end;
  if  mecaux < mectre
    then
      LowerAux(3) ; { rowaux to rowtre from UnRowLow }
end;
{ to multiply two rows in arrays
  for current date and time there is
  function strCurtida of shortstring from ungetida }
procedure MultForRow ( am  : Extended ) ; { am * rowone * rowtwo = rowtre }
var                                       { with the factor am }
  ma,mb  : longint ;
  ua,ub  : TRowVar ; { type from UnTypVar }
  la,lb  : longint ; { current time in millisecond }
begin
  la:=GetTickCount ; { function from unit Windows in millisecond }
  for ma:=1 to mecone do
    begin
      ua:=rowone^[ma];     { current record from the first  row }
      AmpFactor(am,ua.amp);  { to multiply by amplitude }
      for mb:=1 to mectwo do
        begin
          ub:=rowtwo^[mb]; { current record from the second row }
          if  ( ( ua.npa = ub.npa ) and ( ua.npb = ub.npb ) )
            then   { result to rowtre with the count mectre }
              ToMultRow(ua,ub);  { only pair numbers  na nb }
          lb:=GetTickCount ;     { current time value in millisecond }
          if  ( (lb-la) > 30000 )  then  { too long interval }
            begin                        { in millisecond }
              writeln('  ',ma,' * ',mb,' = ',mectre,'   term by term');
              la:=lb; { to replace the moment }
            end;
        end;
    end;
  ForAmpNul ; { in current array rowtre may be nullo amplitude }
  WriteLn('to multiply  ',
           mecone,' terms * ',mectwo,' terms = ',mectre,' terms',
           '  power = ',maxsum);
end;
end.
 

Здесь можно вернуться к возмущающей функции

Здесь можно вернуться на страницу Программные приложения

Hosted by uCoz