Ist im Stack immer 0 ?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 6917
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Ist im Stack immer 0 ?

Beitrag von Mathias »

Habe ich da eine Garantie, das Result von Anfang an mit 0.0 belegt ist ?
Das Ergebniss kommt beim Test richtig.

Code: Alles auswählen

program Project1;
 
uses
  SysUtils;
 
type
  TMatrix = array[0..3, 0..3] of single;
 
  function MatrixIdentity: TMatrix;
  var
    i: integer;
  begin
    for i := 0 to 3 do begin
      Result[i, i] := 1;
    end;
  end;
 
var
  m: TMatrix;
  i: integer;
  j: integer;
begin
  m := MatrixIdentity;
  for  i := 0 to 3 do begin
    for j := 0 to 3 do begin
      Writeln(FloatToStr(m[i, j]));
    end;
  end;
  readln;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: Ist im Stack immer 0 ?

Beitrag von theo »

Nö.
Und von welchem Test sprichst du? Ich sehe keinen.

S.a. http://www.lazarusforum.de/viewtopic.ph ... 47&p=32442

Mathias
Beiträge: 6917
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ist im Stack immer 0 ?

Beitrag von Mathias »

Und von welchem Test sprichst du? Ich sehe keinen.
Von dem kleinen Listing oben.

Somit ist die wohl die beste Lösung:

Code: Alles auswählen

  function MatrixIdentity: TMatrix;
  const
    m: TMatrix = ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0));
  begin
    Result := m;
  end;   
Ein direktes Zuweisen geht nicht.

Code: Alles auswählen

    Result := ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0)); // gibt Fehler beim kompilieren.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: Ist im Stack immer 0 ?

Beitrag von theo »

Kann man auch so machen

Code: Alles auswählen

var m:TMatrix;
begin
Writeln(m[1,1]); //Zufall
FillByte(m,SizeOf(TMatrix),0);
Writeln(m[1,1]);  //0,0
end;

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Ist im Stack immer 0 ?

Beitrag von mse »

Mathias hat geschrieben: Ein direktes Zuweisen geht nicht.

Code: Alles auswählen

 
type
  TMatrix = array[0..3, 0..3] of single;
const
 MatrixIdentity: TMatrix =  ((1.0, 0.0, 0.0, 0.0), 
                             (0.0, 1.0, 0.0, 0.0), 
                             (0.0, 0.0, 1.0, 0.0), 
                             (0.0, 0.0, 0.0, 1.0));
[...]
 m:= MatrixIdentity;
 

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2811
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Ist im Stack immer 0 ?

Beitrag von m.fuchs »

@mse: Ist das nicht genau die Variante, die Mathias oben gepostet hat? Oder ist bei dir etwas anders?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Ist im Stack immer 0 ?

Beitrag von mse »

m.fuchs hat geschrieben:Oder ist bei dir etwas anders?
Es ist effizienter da der Funktionsaufruf entfällt. Ich bin mir auch nicht sicher ob FPC die lokale typisierte Konstante nicht bei jedem Aufruf neu initialisiert. Eine globale typisierte Konstante wird einmalig beim Programmstart initialisiert.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2811
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Ist im Stack immer 0 ?

Beitrag von m.fuchs »

mse hat geschrieben:Es ist effizienter da der Funktionsaufruf entfällt.
Hm, ich glaube nicht, dass Mathias das nur als Initialisierungs-Funktion gemeint hat, aber der Hinweis ist sicherlich nicht falsch.
mse hat geschrieben:Ich bin mir auch nicht sicher ob FPC die lokale typisierte Konstante nicht bei jedem Aufruf neu initialisiert. Eine globale typisierte Konstante wird einmalig beim Programmstart initialisiert.
Da gibt es keine Unterschiede:
http://www.freepascal.org/docs-html/ref/refse10.html:
It should be stressed that typed constants are automatically initialized at program start. This is also true for local typed constants and initialized variables. Local typed constants are also initialized at program start. If their value was changed during previous invocations of the function, they will retain their changed value, i.e. they are not initialized each time the function is invoked.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Ist im Stack immer 0 ?

Beitrag von mse »

Dann ist ja gut. IIRC war das nicht immer so.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Ist im Stack immer 0 ?

Beitrag von pluto »

Und warum nicht einfach so:

Code: Alles auswählen

function MatrixIdentity: TMatrix;
var
    m: TMatrix;
  begin
    Result[0,0] := 0.0;
    Result[1,0] := 0.0;
    Result[2,0] := 0.0;
....
  end;   
Vorher muss natürlich die Größe festgelegt werden. Natürlich geht das auch in zwei Forschleifen, was wohl übersichtlicher wäre.
MFG
Michael Springwald

Mathias
Beiträge: 6917
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ist im Stack immer 0 ?

Beitrag von Mathias »

Vorher muss natürlich die Größe festgelegt werden. Natürlich geht das auch in zwei Forschleifen, was wohl übersichtlicher wäre.
Ich habe mir gerade die Java und Javascript Versionen angeguckt. Es wird überall anderst gemacht.

Code: Alles auswählen

mat4.identity = function (dest) {
    if (!dest) { dest = mat4.create(); }
    dest[0] = 1;
    dest[1] = 0;
    dest[2] = 0;
    dest[3] = 0;
    dest[4] = 0;
    dest[5] = 1;
    dest[6] = 0;
    dest[7] = 0;
    dest[8] = 0;
    dest[9] = 0;
    dest[10] = 1;
    dest[11] = 0;
    dest[12] = 0;
    dest[13] = 0;
    dest[14] = 0;
    dest[15] = 1;
    return dest;
};

Code: Alles auswählen

    public static void setIdentityM(float[] sm, int smOffset) {
        for (int i=0 ; i<16 ; i++) {
            sm[smOffset + i] = 0;
        }
        for(int i = 0; i < 16; i += 5) {
            sm[smOffset + i] = 1.0f;
        }
    }
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Ist im Stack immer 0 ?

Beitrag von Socke »

Die JavaScript Variante könnte man grundsätzlich auch in einer Schleife ausdrücken.

FillByte() ist grundsätzliche immer die schnellste Möglichkeit einen Array mit 0/einem konstanten Wert zu befüllen; die Funktion greift auf entsprechnde Prozessoranweisungen zurück. So etwas ist in Java/JavaScript nicht möglich, da hier es keinen direkten Zugriff auf den Speicher gibt.

Wenn man typisierte Konstanten verwendet und diese nicht mehr ändern möchte, kann man den Kompilerschalter J- setzen - und schon liegt das bei Programmstart fertig im Speicher.

Edit: ähm, ja ... natürlich ... ein Minus!
Zuletzt geändert von Socke am Mi 24. Sep 2014, 18:41, insgesamt 1-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6917
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ist im Stack immer 0 ?

Beitrag von Mathias »

FillByte() ist grundsätzliche immer die schnellste Möglichkeit einen Array mit 0/einem konstanten Wert zu befüllen;
Was hindert mich daran, FillDWord zu nehmen, ich weiss ja, das die Array durch 4 teilbar ist.

Code: Alles auswählen

  function MatrixIdentity: TMatrix;
  var
    i: integer;
  begin
    FillDWord(Result, SizeOf(Result) div 4, 0);
    for i := 0 to 3 do begin
      Result[i, i] := 1;
    end;
  end;  
Ich habe mir die Original-Quellen angeguckt, der Assembler-Text ist recht lange für diese einfachen Befehle.

Code: Alles auswählen

Procedure FillChar(var x;count:SizeInt;value:byte);assembler; nostackframe;
asm
        cmpl    $22,%edx          { empirically determined value on a Core 2 Duo Conroe }
        jg      .LFillFull
        orl     %edx,%edx
        jle     .LFillZero
 
.LFillLoop:
        movb    %cl,(%eax)
        incl    %eax
        decl    %edx
        jne     .LFillLoop
.LFillZero:
        ret
 
.LFillFull:
        cld
        push    %edi
        movl    %eax,%edi
        movzbl  %cl,%eax
        movl    %edx,%ecx
        imul    $0x01010101,%eax  { Expand al into a 4 subbytes of eax}
        shrl    $2,%ecx
        andl    $3,%edx
        rep
        stosl
        movl    %edx,%ecx
.LFill1:
        rep
        stosb
.LFillEnd:
        pop %edi
end;
{$endif FPC_SYSTEM_HAS_FILLCHAR}
 
 
{$ifndef FPC_SYSTEM_HAS_FILLWORD}
{$define FPC_SYSTEM_HAS_FILLWORD}
procedure fillword(var x;count : SizeInt;value : word);assembler;
var
  saveedi : longint;
asm
        movl    %edi,saveedi
        movl    %eax,%edi
        movzwl  %cx,%eax
        movl    %edx,%ecx
{ check for zero or negative count }
        cmpl    $0,%ecx
        jle     .LFillWordEnd
        movl    %eax,%edx
        shll    $16,%eax
        orl     %edx,%eax
        movl    %ecx,%edx
        shrl    $1,%ecx
        cld
        rep
        stosl
        movl    %edx,%ecx
        andl    $1,%ecx
        rep
        stosw
.LFillWordEnd:
        movl    saveedi,%edi
end;
{$endif FPC_SYSTEM_HAS_FILLWORD}
 
 
{$ifndef FPC_SYSTEM_HAS_FILLDWORD}
{$define FPC_SYSTEM_HAS_FILLDWORD}
procedure filldword(var x;count : SizeInt;value : dword);assembler;
var
  saveedi : longint;
asm
        movl    %edi,saveedi
        movl    %eax,%edi
        movl    %ecx,%eax
        movl    %edx,%ecx
{ check for zero or negative count }
        cmpl    $0,%ecx
        jle     .LFillDWordEnd
        cld
        rep
        stosl
.LFillDWordEnd:
        movl    saveedi,%edi
end;                                             
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2811
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Ist im Stack immer 0 ?

Beitrag von m.fuchs »

Socke hat geschrieben:Wenn man typisierte Konstanten verwendet und diese nicht mehr ändern möchte, kann man den Kompilerschalter J+ setzen - und schon liegt das bei Programmstart fertig im Speicher.
Sehr schön, den kannte ich noch nicht. Damit lässt sich dieses dämlich Verhalten von typisierten Konstanten abschalten.

Kleine Korrektur nur:

Code: Alles auswählen

{$J-}
Nicht Plus.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten