File : fouriers-io.adb
with Messages, Reps.Ops, Reps.IO;
use Messages;
pragma Elaborate_All (Messages, Reps.IO, Reps.Ops);
package body Fouriers.IO is
package Txt_Int_IO is new Ada.Text_IO.Integer_IO(Integer);
use Txt_Int_IO;
function IMax(I1,I2: Integer) return Integer renames Integer'Max;
procedure EffDeg(H: in Fourier; Dm,Dn: out Integer) is
begin
Dm := -1;
Dn := -1;
for M in Freq1 loop
for N in Nmin(M) .. Ncut(M) loop
if not IsZero(H.C(M,N)) then
Dm := Imax(Abs(M),Dm);
Dn := Imax(N,Dn);
end if;
end loop;
end loop;
end EffDeg;
procedure Show(S: in String; R: in Weights; Decimal: in Boolean := True) is
use Reps.IO;
begin
Put(Current_Output,S & " ( ");
Txt_Put(Current_Output,R.Q,Decimal);
Put(" , ");
Txt_Put(Current_Output,R.P,Decimal);
Put_Line(" )");
end Show;
procedure Show(L: in Degrees) is
begin
Put(" \ M");
for M in Freq1 loop
Put(Current_Output,M,3,10);
end loop;
New_Line;
Put(" N \_");
for M in Freq1 loop
Put("___");
end loop;
New_Line;
for N in reverse Freq2 loop
Put(Current_Output,N,3,10);
Put(" |");
for M in Freq1 loop
if Kcut(M,N)<0 then
Put(" ");
elsif L(M,N)<0 then
Put(" +");
else
Put(Current_Output,L(M,N),3,10);
end if;
end loop;
New_Line;
end loop;
New_Line;
end Show;
procedure ShowIndices(J: in Parity; M: in Freq1; N: in Freq2; K: in Power) is
begin
if J=0 then
Put(Current_Output,"cos(");
else
Put(Current_Output,"sin(");
end if;
Put(Current_Output,M,3,10);
Put(Current_Output,"x+");
Put(Current_Output,N,2,10);
Put(Current_Output,"y) z**");
Put(Current_Output,K,2,10);
Put(Current_Output," ");
end ShowIndices;
procedure ShowIndices(J: in Parity; M: in Freq1; N: in Freq2) is
begin
if J=0 then
Put(Current_Output,"cos(");
else
Put(Current_Output,"sin(");
end if;
Put(Current_Output,M,3,10);
Put(Current_Output,"x+");
Put(Current_Output,N,2,10);
Put(Current_Output,"y) E(z) ");
end ShowIndices;
procedure ShowIndices(I: in FreqE; K: in Power) is
begin
Put(Current_Output,"E(dist >= ");
Put(Current_Output,I,2,10);
if K>0 then
Put(Current_Output,") z**");
Put(Current_Output,K,2,10);
Put(Current_Output," ");
else
Put(Current_Output,") ");
end if;
end ShowIndices;
procedure ShowIndices(I: in FreqE) is
begin
Put(Current_Output,"E(dist >= ");
Put(Current_Output,I,2,10);
Put(Current_Output,") error ");
end ShowIndices;
procedure Show(H: in Fourier; Cut: in Rep := Zero) is
C: Scalar;
begin
Put(Current_Output,"J=");
Put(Current_Output,H.J,1,10);
Show(" R=",H.R);
if not Poly(H,True) then
Show("Poly(H) is False");
end if;
for M in Freq1 loop
for N in Nmin(M) .. Ncut(M) loop
for K in 0 .. Deg(M,N,H) loop
C := Component(M,N,K,H);
if SupAbs(C) > Cut then
if K>Kcut(M,N) then
Put(Current_Output,Kcut(M,N),2,10);
Put(" ??? ");
end if;
ShowIndices(H.J,M,N,K);
Show(C);
end if;
end loop;
C := ErrComp(H.C(M,N));
if SupAbs(C) > Cut then
ShowIndices(H.J,M,N);
Show(C);
end if;
end loop;
end loop;
New_Line;
if Poly(H) then return; end if;
for I in FreqE loop
for K in 0 .. Pdeg loop
C := Component(K,H.E(I));
if SupAbs(C) > Cut then
ShowIndices(I,K);
Show(C);
end if;
end loop;
C := ErrComp(H.E(I));
if SupAbs(C) > Cut then
ShowIndices(I);
Show(C);
end if;
end loop;
New_Line;
end Show;
procedure Read(Name: in String; J: in Parity; R: in Weights; H: out Fourier; Decimal: in Boolean := True) is
use Reps.IO, Components_IO;
F: File_Type;
GetPoly: Boolean;
Warn,Truncated: Boolean := False;
S,Sz,SzE,Dh,KcutMN: Integer;
Rt: Weights;
P: Taylor;
begin
Put_Line("Reading " & Name);
SetZero(J,R,H);
Open(F,In_File,Name);
Get(F,S);
UnJoin(S,SzE,Dh,Sz);
GetPoly := S<10000;
if not GetPoly then
Truncated := Dh<Dho;
H.P := False;
Txt_Get(F,Rt.Q,Decimal);
Txt_Get(F,Rt.P,Decimal);
H.R := Min(Rt,R);
end if;
for M in -Sz .. Sz loop
for N in Nmin(M) .. Sz loop
Get(R.P,F,P,H.P,GetPoly,Decimal);
KcutMN := Kcut(M,N);
if KcutMN >= 0 then
Copy(P,H.C(M,N));
Warn := Warn or Deg(P)>KcutMN;
elsif Deg(P) >= 0 then
Truncated := True;
end if;
end loop;
end loop;
if not GetPoly then
for I in 0 .. SzE loop
Get(R.P,F,P,H.P,GetPoly,Decimal);
if I <= SizeE then
Copy(P,H.E(I));
elsif Deg(P) >= 0 then
Truncated := True;
end if;
end loop;
end if;
Close(F);
H.P := H.P or Trunc;
if H.P then
H.R := R;
elsif H.R /= R then
Show("Reduced domain to ",H.R);
end if;
if Truncated then
Put_Line("Truncated input");
if not Trunc then
Message("Fouriers.IO.Read",Index_Error);
end if;
elsif Warn then
Put_Line("Some degrees exceed Dmax");
end if;
end Read;
procedure Write(Name: in String; H: in Fourier; Decimal: in Boolean := True) is
use Reps.IO, Components_IO;
F: File_Type;
PutPoly: constant Boolean := Poly(H,True);
Dm,Dn,Sz,SzE: Integer;
P0: Taylor;
begin
Put_Line("Writing H to " & Name);
Show("H.R=",H.R);
EffDeg(H,Dm,Dn);
Sz := Imax(Dm,Dn);
SzE := EffSizeE(H);
SetZero(P0);
Create(F,Out_File,Name);
if PutPoly then
Put(F,Sz,3);
else
Put(F,Join(SzE,Dho,Imax(Sz,0)),7);
New_Line(F);
Txt_Put(F,H.R.Q,Decimal);
New_Line(F);
Txt_Put(F,H.R.P,Decimal);
end if;
New_Line(F);
for M in -Sz .. Sz loop
for N in Nmin(M) .. Sz loop
if Kcut(M,N)>=0 then
Put(F,H.C(M,N),PutPoly,Decimal);
else
Put(F,P0,PutPoly,Decimal);
end if;
end loop;
end loop;
if Sz<0 then
Put(F,P0,PutPoly,Decimal);
end if;
if not PutPoly then
for I in 0 .. SzE loop
Put(F,H.E(I),PutPoly,Decimal);
end loop;
end if;
Close(F);
end Write;
procedure EffDeg(H: in Sobolev; Dm,Dn: out Integer) is
begin
Dm := -1;
Dn := -1;
for M in Freq1 loop
for N in Nmin(M) .. Ncut(M) loop
if H.C(M,N) /= ScalZero then
Dm := Imax(Abs(M),Dm);
Dn := Imax(N,Dn);
end if;
end loop;
end loop;
end EffDeg;
procedure Show(H: in Sobolev; Cut: in Rep := Zero) is
C: Scalar;
begin
Put(Current_Output,"J=");
Put(Current_Output,H.J,1,10);
Show(" R=",H.R);
for M in Freq1 loop
for N in Nmin(M) .. Ncut(M) loop
C := Component(M,N,H);
if SupAbs(C) > Cut then
ShowIndices(H.J,M,N,0);
Show(C);
end if;
end loop;
end loop;
New_Line;
if Trunc then return; end if;
for I in FreqE loop
C := H.E(I);
if SupAbs(C) > Cut then
ShowIndices(I);
Show(C);
end if;
end loop;
New_Line;
end Show;
procedure ShowNorms(H: in Sobolev; Cut: in Rep := Zero) is
C,E: Scalar := ScalZero;
begin
Put(Current_Output,"J=");
Put(Current_Output,H.J,1,10);
Show(" R=",H.R);
for M in Freq1 loop
for N in Nmin(M) .. Ncut(M) loop
C := Exp(H.R*Log(ScalOne+Abs(Scal(M)+Rep(-N)*InvGold)));
C := Abs(Component(M,N,H)*C);
E := E+C;
if Sup(C) > Cut then
ShowIndices(H.J,M,N,0);
Show(" Norm ",Sup(C));
end if;
end loop;
end loop;
New_Line;
if not Trunc then
for I in FreqE loop
C := Abs(H.E(I));
E := E+C;
if Sup(C) > Cut then
ShowIndices(I);
Show(" Norm ",Sup(C));
end if;
end loop;
New_Line;
end if;
New_Line;
Show(" Norm total ",Sup(E));
New_Line;
end ShowNorms;
procedure Read(Name: in String; J: in Parity; R: in Radius; H: out Sobolev; Decimal: in Boolean := True) is
use Reps.IO, Components_IO;
F: File_Type;
GetPoly: Boolean;
Truncated: Boolean := False;
S,Sz,SzE,Dh: Integer;
Rt: Radius;
C: Scalar;
begin
Put_Line("Reading " & Name);
SetZero(J,R,H);
Open(F,In_File,Name);
Get(F,S);
UnJoin(S,SzE,Dh,Sz);
GetPoly := S<10000;
if not GetPoly then
Txt_Get(F,Rt,Decimal);
H.R := Radius'Min(Rt,R);
end if;
for M in -Sz .. Sz loop
for N in Nmin(M) .. Sz loop
Get(F,C,Decimal);
if Kcut(M,N) >= 0 then
H.C(M,N) := C;
elsif C /= ScalZero then
Truncated := True;
end if;
end loop;
end loop;
if not GetPoly then
for I in 0 .. SzE loop
Get(F,C,Decimal);
if I <= SizeE then
H.E(I) := C;
elsif C /= ScalZero then
Truncated := True;
end if;
end loop;
end if;
Close(F);
if GetPoly or Trunc then
H.R := R;
elsif Rt<R then
H.R := Rt;
Show("Reduced domain to ",Rt);
end if;
if Truncated then
Put_Line("Truncated input");
if not Trunc then
Message("Fouriers.IO.Read",Index_Error);
end if;
end if;
end Read;
procedure Write(Name: in String; H: in Sobolev; Decimal: in Boolean := True) is
use Reps.IO, Components_IO;
PutPoly: Boolean;
F: File_Type;
Dm,Dn,Sz,SzE: Integer;
begin
Put_Line("Writing H to " & Name);
Show("H.R=",H.R);
EffDeg(H,Dm,Dn);
Sz := Imax(Dm,Dn);
SzE := EffSizeE(H);
PutPoly := Trunc or else SzE<0;
Create(F,Out_File,Name);
if PutPoly then
Put(F,Sz,3);
else
Put(F,Join(SzE,0,Sz),7);
New_Line(F);
Txt_Put(F,H.R,Decimal);
end if;
New_Line(F);
for M in -Sz .. Sz loop
for N in Nmin(M) .. Sz loop
if Kcut(M,N)>=0 then
Put(F,H.C(M,N),Decimal);
New_Line(F);
else
Put(F,ScalZero,Decimal);
New_Line(F);
end if;
end loop;
end loop;
if not PutPoly then
for I in 0 .. SzE loop
Put(F,H.E(I),Decimal);
New_Line(F);
end loop;
end if;
Close(F);
end Write;
end Fouriers.IO;