PROGRAM Pauli;

TYPE Complex=RECORD Re,Im: REAL END;
     Spinor= RECORD Up,Down: Complex END;
     Operator=RECORD U,D: Spinor END;

CONST Czero:Complex=(Re:0.0; Im:0.0);
      Runit:Complex=(Re:1.0; Im:0.0);
      Cunit:Complex=(Re:0.0; Im:1.0);
      Sx:Operator=(U:(Up:(Re:0.0; Im:0.0) ;Down:(Re:1.0; Im:0.0));
                   D:(Up:(Re:1.0; Im:0.0) ;Down:(Re:0.0; Im:0.0)));
      Sy:Operator=(U:(Up:(Re:0.0; Im:0.0) ;Down:(Re:0.0; Im:1.0));
                   D:(Up:(Re:0.0; Im:-1.0);Down:(Re:0.0; Im:0.0)));
      Sz:Operator=(U:(Up:(Re:1.0; Im:0.0) ;Down:(Re:0.0; Im:0.0));
                   D:(Up:(Re:0.0; Im:0.0) ;Down:(Re:-1.0; Im:1.0)));
VAR Nahoru,Rovne,V1,V2,V3: Spinor;
    C1,C2,C3:Complex;

 PROCEDURE CMult(VAR Vysl:Complex; A,B:Complex);
 BEGIN
   Vysl.Re:=A.Re*B.Re-A.Im*B.Im;
   Vysl.Im:=A.Re*B.Im+A.Im*B.Re
 END;

 PROCEDURE CSum(VAR Vysl:Complex; A,B:Complex);
 BEGIN
   Vysl.Re:=A.Re+B.Re;
   Vysl.Im:=A.Im+B.Im
 END;

 PROCEDURE Conjg(VAR A:Complex);
 BEGIN
   A.Im:=-A.Im
 END;

 PROCEDURE WC(A:Complex);
 BEGIN
   WRITE('(',A.Re,',',A.Im,')')
 END;

 PROCEDURE Prod(VAR Vysl:Complex; A,B:Spinor);
  VAR hlp: Complex;
 BEGIN
   CMult(Vysl,A.Up,B.Up);
   CMult(hlp,A.Down,B.Down);
   CSum(Vysl,Vysl,hlp)
 END;

 PROCEDURE Braket(VAR Vysl:Complex; A,B:Spinor);
  VAR hlp: Spinor;
 BEGIN
   hlp:=A;
   Conjg(hlp.Up);
   Conjg(hlp.Down);
   Prod(Vysl,hlp,B)
 END;

 PROCEDURE Act(VAR Vysl:Spinor; A:Operator; B:Spinor);
 BEGIN
   Prod(Vysl.Up,  A.U,B);
   Prod(Vysl.Down,A.D,B)
 END;

BEGIN
 Nahoru.Up:=Runit;
 Nahoru.Down:=Czero;
 Rovne.Up.Re:=1.0/SQRT(2.0);
 Rovne.Down.Re:=1.0/SQRT(2.0);
 Rovne.Up.Im:=0.0;
 Rovne.Down.Im:=0.0;
 Braket(C1,Nahoru,Rovne);
 WRITE('<Nahoru|Rovne>='); WC(C1); WRITELN;
 Braket(C2,Rovne,Rovne);
 WRITE('<Rovne|Rovne>='); WC(C2); WRITELN;
 WRITELN('Ve stavu Nahoru:');
 Act(V1,Sx,Nahoru);
 Braket(C1,Nahoru,V1);
 Act(V2,Sy,Nahoru);
 Braket(C2,Nahoru,V2);
 Act(V3,Sz,Nahoru);
 Braket(C3,Nahoru,V3);
 WRITE('<Sx>='); WC(C1); WRITELN;
 WRITE('<Sy>='); WC(C2); WRITELN;
 WRITE('<Sz>='); WC(C3); WRITELN;
 WRITELN('Ve stavu Rovne:');
 Act(V1,Sx,Rovne);
 Braket(C1,Rovne,V1);
 Act(V2,Sy,Rovne);
 Braket(C2,Rovne,V2);
 Act(V3,Sz,Rovne);
 Braket(C3,Rovne,V3);
 WRITE('<Sx>='); WC(C1); WRITELN;
 WRITE('<Sy>='); WC(C2); WRITELN;
 WRITE('<Sz>='); WC(C3); WRITELN;
 Braket(C1,V1,V1);
 WRITE('<V1|V1>='); WC(C1); WRITELN;
 WC(Rovne.Up); WC(Rovne.Down); WRITELN;
 READLN;
END.