Box Generator / Sprache Modula3
 
StartSeite | BoxGenerator/ | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Veränderung (letzte Änderung) (keine anderen Diffs, Normalansicht)

Hinzugefügt: 93a94,159


Noch besser gefällt mir aber die folgende Implementation, welche leichter auf höhere Dimensionen übertragen werden kann.

[[Code]
MODULE RndBox?;

IMPORT Random, Math;

TYPE OutIndex? = [0 .. 1];

REVEAL
T = BRANDED REF RECORD
random : Random.T;
x, y, product: LONGREAL;
out : ARRAY OutIndex? OF LONGREAL;
outIndex : OutIndex?;
END;

PROCEDURE New (): T =
BEGIN
RETURN NEW(T, random := NEW(Random.Default).init(),
outIndex := LAST(OutIndex?));
END New;


PROCEDURE RandPoint? (SELF: T; ) =
BEGIN
WITH x = SELF.x,
y = SELF.y,
product = SELF.product DO
REPEAT
x := SELF.random.longreal(-1.0D0, 1.0D0);
y := SELF.random.longreal(-1.0D0, 1.0D0);
product := x * x + y * y;
UNTIL product <= 1.0D0;
END;
END RandPoint?;

PROCEDURE Generate (SELF: T; ) =
BEGIN
RandPoint?(SELF);
WITH p = Math.sqrt((-2.0D0 * Math.log(SELF.product)) / SELF.product) DO
SELF.out[0] := p * SELF.x;
SELF.out[1] := p * SELF.y;
END;
END Generate;

PROCEDURE Next (SELF: T; ) =
BEGIN
IF SELF.outIndex = LAST(OutIndex?) THEN
Generate(SELF);
SELF.outIndex := FIRST(OutIndex?);
ELSE
INC(SELF.outIndex);
END;
END Next;

PROCEDURE LastGaussian? (SELF: T; ): LONGREAL =
BEGIN
RETURN SELF.out[SELF.outIndex];
END LastGaussian?;

BEGIN
END RndBox?.
]

Hier eine Übersetzung des Modula-2-Beispiels in die SpracheModula3. Hab's nicht getestet, aber es kann übersetzt werden. :-)

Zunächst die Schnittstelle in der Datei RndBox?.i3. Es ist Konvention, das Modul nach dem Datentyp zu benennen und den zugehörigen Modula3-Typen T. Alles was den Typen bezeichnet lässt man aus den Bezeichnern weg, denn dafür gibt es die Qualifikation. Man schreibt in den Programmen dann RndBox?.T oder RndBox?.New. Der Typ T wird als Untertyp von Zeigern mit automatischer Speicherverwaltung definiert. Modula-3 hält sich einen GarbageCollector und braucht daher keine explizite Freigabe des Zufallsgenerators.

INTERFACE RndBox;

TYPE T <: REFANY;

PROCEDURE New (): T;
PROCEDURE Next (SELF: T; );
PROCEDURE LastGaussian (SELF: T; ): LONGREAL;

END RndBox.

Jetzt kommt die Implementation in der Datei RndBox?.m3. Mit REVEAL deckt man auf, was sich denn nun wirklich hinter T verbirgt. Der Rest ist nicht weiter spektakulär.

MODULE RndBox;

IMPORT Random, Math;

REVEAL
  T = BRANDED REF RECORD
                    random                      : Random.T;
                    x, y, product, first, second: LONGREAL;
                    available                   : BOOLEAN;
                  END;

PROCEDURE New (): T =
  BEGIN
    RETURN
      NEW(T, random := NEW(Random.Default).init(), available := FALSE);
  END New;


PROCEDURE RandPoint (SELF: T; ) =
  BEGIN
    WITH x       = SELF.x,
         y       = SELF.y,
         product = SELF.product DO
      REPEAT
        x := SELF.random.longreal(-1.0D0, 1.0D0);
        y := SELF.random.longreal(-1.0D0, 1.0D0);
        product := x * x + y * y;
      UNTIL product <= 1.0D0;
    END;
  END RandPoint;

PROCEDURE Generate (SELF: T; ) =
  VAR p: LONGREAL;
  BEGIN
    RandPoint(SELF);
    p := Math.sqrt((-2.0D0 * Math.log(SELF.product)) / SELF.product);
    SELF.available := TRUE;
    SELF.first := p * SELF.x;
    SELF.second := p * SELF.y;
  END Generate;

PROCEDURE Next (SELF: T; ) =
  BEGIN
    IF SELF.available THEN
      SELF.available := FALSE;
    ELSE
      Generate(SELF);
    END;
  END Next;

PROCEDURE LastGaussian (SELF: T; ): LONGREAL =
  BEGIN
    IF SELF.available THEN RETURN SELF.first; ELSE RETURN SELF.second; END;
  END LastGaussian;

BEGIN
END RndBox.

Um das Projekt komplett zu machen, gibt es noch eine Projektdatei namens m3makefile.

import("libm3")

module("RndBox")

library("boxgenerator")

Noch besser gefällt mir aber die folgende Implementation, welche leichter auf höhere Dimensionen übertragen werden kann.

MODULE RndBox;

IMPORT Random, Math;

TYPE OutIndex = [0 .. 1];

REVEAL
  T = BRANDED REF RECORD
                    random       : Random.T;
                    x, y, product: LONGREAL;
                    out          : ARRAY OutIndex OF LONGREAL;
                    outIndex     : OutIndex;
                  END;

PROCEDURE New (): T =
  BEGIN
    RETURN NEW(T, random := NEW(Random.Default).init(),
               outIndex := LAST(OutIndex));
  END New;


PROCEDURE RandPoint (SELF: T; ) =
  BEGIN
    WITH x       = SELF.x,
         y       = SELF.y,
         product = SELF.product DO
      REPEAT
        x := SELF.random.longreal(-1.0D0, 1.0D0);
        y := SELF.random.longreal(-1.0D0, 1.0D0);
        product := x * x + y * y;
      UNTIL product <= 1.0D0;
    END;
  END RandPoint;

PROCEDURE Generate (SELF: T; ) =
  BEGIN
    RandPoint(SELF);
    WITH p = Math.sqrt((-2.0D0 * Math.log(SELF.product)) / SELF.product) DO
      SELF.out[0] := p * SELF.x;
      SELF.out[1] := p * SELF.y;
    END;
  END Generate;

PROCEDURE Next (SELF: T; ) =
  BEGIN
    IF SELF.outIndex = LAST(OutIndex) THEN
      Generate(SELF);
      SELF.outIndex := FIRST(OutIndex);
    ELSE
      INC(SELF.outIndex);
    END;
  END Next;

PROCEDURE LastGaussian (SELF: T; ): LONGREAL =
  BEGIN
    RETURN SELF.out[SELF.outIndex];
  END LastGaussian;

BEGIN
END RndBox.


StartSeite | BoxGenerator/ | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 25. November 2004 14:17 (diff))
Suchbegriff: gesucht wird
im Titel
im Text