C++Guns – RoboBlog blogging the bot

11.04.2015

Local variable will not retain values between function invocations (Bug of the day 2)

Filed under: Allgemein — Tags: — Thomas @ 07:04

Lokale Variablen behalten ihren Wert NICHT zwischen Funktionsaufrufe!

Es gibt in diesem Beispiel keinen Compilerfehler und auch keinen von Fortran erkannten Laufzeitfehler.
Es gibt Compiler Warnings die diesen Fehler zeigen, aber dazu bedarf es mehr Code. Ich habe dieses Beispiel möglichst klein und übersichtlich gehalten.

Ausgabe ohne Optimierung und ohne Fehler

 kater@ktux:~$ gfortran -Wall -Wextra -fcheck=all  bugoftheday_openreadclose.f95 
kater@ktux:~$ ./a.out 
first round
DEBUG address of fhdl         BFC4D8FC
 open. set fhdl to         100
 read
 all file

 second round
DEBUG address of fhdl         BFC4D8FC
 open. set fhdl to         100
DEBUG address of test         BFC4D90C
 set test variabel to        1000
 read
 all file

Man beachte die unterschiedlichen Adressen der lokalen Variablen. Daher wird der Fehler nicht getriggert.

Ausgabe mit Optimierung und mit Fehler

kater@ktux:~$ gfortran -Wall -Wextra -fcheck=all  bugoftheday_openreadclose.f95 -O1
kater@ktux:~$ ./a.out  
 first round
DEBUG address of fhdl         BFA7DE38
 open. set fhdl to         100
 read
 all file

 second round
DEBUG address of fhdl         BFA7DE38
 open. set fhdl to         100
DEBUG address of test         BFA7DE38
 set test variabel to        1000
 read
 ERROR expect fhdl to be         100 but is        1000

Diesmal sind die Adressen der lokalen Variablen gleich! Die Variable fhdl wird ungeplant ueberschrieben!!
Welche Adresse die lokalen Variablen bekommen und ob so der Fehler auftritt oder nicht, ist zufällig und nicht beeinflussbar!!!


! Local variable will not retain values between function invocations
! compile: gfortran -Wall -Wextra -fcheck=all  bugoftheday_openreadclose.f95
! turn on any optimization to trigger the error


subroutine openread(action)
  use testmodule
  implicit none
  character(len=*), intent(in) :: action
  integer :: fhdl

  if(action == 'open') then
    fhdl = 100
    write(*,'(A,Z16)') "DEBUG address of fhdl ", loc(fhdl)
    write(*,*) "open. set fhdl to", fhdl
  else if(action == 'read') then
    write(*,*) "read"
    if(fhdl /= 100) then
      write(*,*) "ERROR expect fhdl to be", 100, "but is", fhdl
    else
      write(*,*) "all file"
    endif
  else if(action == 'close') then
      write(*,*) "close fhdl", fhdl
  endif
end subroutine


subroutine overwriteLocalValue()
  implicit none
  integer :: test

  test = 1000
  write(*,'(A,Z16)') "DEBUG address of test ", loc(test)
  write(*,*) "set test variabel to", test
end subroutine

program bugoftheday
  use testmodule
  implicit none

  write(*,*) "first round"
  call openread("open")
  call openread("read")

  write(*,*)
  write(*,*) "second round"
  call openread("open")
  call overwriteLocalValue
  call openread("read")
end program

10.04.2015

Bug of the day 1

Filed under: Allgemein — Tags: — Thomas @ 08:04

Der bug of the day kommt diesmal von mir!

Ich hab mir von eine Hand voll 3D Punkten neue Z Werte berechnet.
Aber hab den Z Wert im Punkt nie aktualisiert.
Und anstatt in der Ausgabedatei nun Bloedsinn steht oder lauter 0 Eintraege,
finden sich dort Werte die mit einen berechneten immer ein bis zwei Stellen am Anfang überein stimmen.
Fortran ist seltsam.
Ghosts updates mit einem leichten Fuzzy Faktor.
Da schwappen die Bits wohl von einen ins andere CPU Register über ;)

09.04.2015

Polymorphie virtual abstract pure deconstrutor WTF?

Filed under: Allgemein — Tags: — Thomas @ 08:04

Okay ich fasse mal zusammen. Ich sehe 3 Fälle, vom einfachsten zum schwersten.

1) Ganz normal Klassen ableiten.

class Base {
public:
  ~Base() {
    cout << "~TestClass\n";
  }
};

class Derived : public TestClass {
public:
  ~Derived() {
    cout << "~Derived\n";
  }
};

int main() {
  {
  cout << "a\n";
  Derived a;
  }
  cout << "b\n";
  Derived *b = new Derived();
  delete b;
}
Ausgabe:
a                                                                                                                
~Derived                                                                                                         
~Base
b
~Derived
~Base

Der Destructor wird immer aufgerufen.
2) Mit Polymorphie (Pointer ist vom Type Base)

class Base {
public:
  virtual ~Base() {
    cout << "~TestClass\n";
  }
};

class Derived : public TestClass {
public:
  virtual ~Derived() {
    cout << "~Derived\n";
  }
};

int main() {
  {
  cout << "a\n";
  Derived a;
  }
  cout << "b\n";
  Base *b = new Derived();
  delete b;
}
Ausgabe:
a                                                                                                                
~Derived                                                                                                         
~Base
b
~Derived
~Base

Der Destructor wird immer aufgerufen.

3) Mit Polymorphie und class Derived als abstracte Klasse


class Base {
public:
  virtual ~Base() = 0;
};

Base::~Base() {
    cout << "~Base\n";
}

class Derived : public Base {
public:
  virtual ~Derived() {
    cout << "~Derived\n";
  }
};

int main() {
  {
  cout << "a\n";
  Derived a;
  }
  cout << "b\n";
  Base *b = new Derived();
  delete b;
}
Ausgabe:
a                                                                                                                
~Derived                                                                                                         
~Base
b
~Derived
~Base

Der Destructor wird immer aufgerufen.
Der Destructor von Base ist zwar abstract, es gibt aber eine default Implementation, die im Zweifel garnichts macht. Es muss immer eine Implementation der Spezialfunktionen, wie dem Destructor, geben. Wird keine explicit angegeben, erstellt automatisch der Compiler eine. (Ausser man declariert ihn mit "=0" als abstract).

Wozu das ganze? Abstrace Klassen können nicht instanziiert werden, sie dienen wirklich nur als ein abstractes Interface. Sollte man es dennoch versuchen, bekommt man folgende Compilerfehler:

error: cannot declare variable ‘c’ to be of abstract type ‘Base’
 Base c;
 note:   because the following virtual functions are pure within ‘Base’:
 virtual ~Base() = 0;

PS: Wird das virtual keyword mal vergessen, wird der Base Destructor im ungünstigen Fall nicht aufgerufen ;)

Hf

20.03.2015

Kleine Sonnenfinsternis

Filed under: Allgemein — Thomas @ 10:03

sonnenfinsternis1

sonnenfinsternis2

sonnenfinsternis3

sonnenfinsternis4

sonnenfinsternis5

sonnenfinsternis6

sonnenfinsternis7

sonnenfinsternis8

sonnenfinsternis9

sonnenfinsternis10

sonnenfinsternis11

sonnenfinsternis12

sonnenfinsternis13

sonnenfinsternis14

sonnenfinsternis15

sonnenfinsternis16

sonnenfinsternis17

sonnenfinsternis18

17.03.2015

2qm 2015 Gleisbildstellwerk

Filed under: Allgemein — Tags: , — Thomas @ 20:03

Hier ein provisorisches Gleisbildstellwerk. So oder so ähnlich könnte es aufgebaut sein.

Neue Version. Ein Abstellgleis musste weichen. Es wurde alles zu eng. Entkupplungsknopf eingezeichnet und Block-Signal eingefügt.

gleisstellbild_22.3.2015

Alte Version:

gleisstellbild

11.03.2015

Wikipedia's Kellerautomat

Filed under: Allgemein — Tags: , — Thomas @ 23:03

Wikipedia's Kellerautomat Beispiel in C ist total falsch (Stand 11.03.2015).
Nicht nur, dass es im feinsten C programmiert ist, was kein Mensch versteht. Es wird nicht mal ein Kellerautomat implementiert. Die Konfiguration eines Kellerautomats hängt von seinem Zustand, dem zu lesenden Zeichen und dem Zeichen auf dem Stack (Keller) ab.
In dem Beispiel wird aber nur das zu lesende Zeichen und der Stack benutzt. Es gibt kein expliziten Zustand des Automaten. Vielmehr wird der Zustand in dem Kellerspeicher gespeichert. Was nicht Sinn der Sache ist. Das Beispiel verwirrt also mehr, als dass es nutzt.

Ich habe den Beispielcode nach C++ Qt übersetzt und so auch den Fehler gefunden.


#include < QCoreApplication >
#include < QTextStream >
#include < QString >
#include < QDebug >
#include < QStack > 
#include < QMap >


int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    
    QStack stack;
    QTextStream ss(stdin);
    QByteArray s;

    /* Eingabestring */
    qDebug() << "Bitte Ausdruck eingeben:";

    ss >> s;
    // Wir benutzen in der  Zustandsuebergangsfunktion das Null Byte als Indikator fuer das Ende vom String.
    // Fuege es manuell in den String ein.
    s += '\0';

    /* Start-state auf Stack pushen */
    stack.push(0);

    /*
     Ein einfacher Kellerautomat ("pushdown automaton")

     Symbol   | (       | )     | \0
     ---------+---------+--------+-----------
     State 0  | PUSH 1  | ERROR  | ACCEPT
     State 1  | PUSH 1  | POP    | ERROR
    */

    enum class Actions {PUSH, POP, ERROR, ACCEPT};
    QMap< QPair< int, char>, Actions> states;
    states.insert(qMakePair(0, '('),  Actions::PUSH);
    states.insert(qMakePair(0, ')'),  Actions::ERROR);
    states.insert(qMakePair(0, '\0'), Actions::ACCEPT);
    states.insert(qMakePair(1, '('),  Actions::PUSH);
    states.insert(qMakePair(1, ')'),  Actions::POP);
    states.insert(qMakePair(1, '\0'), Actions::ERROR);


    /* Ausführungsschleife */
    bool finish = false;
    for(int i=0; i < s.size() && finish == false ; i++) {
        /* Aktion auf Basis des Eingabesymbols ermitteln */
        auto key = qMakePair(stack.top(), s.at(i));
        Actions action = states.value(key, Actions::ERROR);

        /* Ausführen der Aktionen */
        switch(action) {
        case Actions::ERROR: {
            qDebug() << "Unerwartetes Zeichen \"" << s.at(i) << "\"an Position" << i+1;
            finish = true;
            break;
        }
        case Actions::ACCEPT: {
            qDebug() << "Ausdruck akzeptiert!";
            finish = true;
            break;
        }
        case Actions::POP: {
            stack.pop();
            break;
        }
        case Actions::PUSH: {
            stack.push(1);
            break;
        }
        default:
            qDebug() << "internal error";
        }
    }

    return 0;
}

26.02.2015

rosettacode - Simple moving variance

Filed under: Allgemein — Tags: , — Thomas @ 11:02

As mentioned in my earlier post original C++ rosettacode sucks.
Here is my example for a simple moving variance and standard deviation. One has to add only a few lines of code:


in add()
...
    sum2 = sum2 - oldValue*oldValue + value*value;
...

double var() const {
    return sum2/size - avg()*avg();
}

double std() const {
    return std::sqrt(var());
}
Data1 Period 3
Added 1 avg:        1 var:        0 std: 0
Added 2 avg:      1.5 var:     0.25 std: 0.5
Added 3 avg:        2 var: 0.666667 std: 0.816497
Added 4 avg:        3 var: 0.666667 std: 0.816497
Added 5 avg:        4 var: 0.666667 std: 0.816497
Added 5 avg:  4.66667 var: 0.222222 std: 0.471405
Added 4 avg:  4.66667 var: 0.222222 std: 0.471405
Added 3 avg:        4 var: 0.666667 std: 0.816497
Added 2 avg:        3 var: 0.666667 std: 0.816497
Added 1 avg:        2 var: 0.666667 std: 0.816497

Data2 Period 8
Added 2 avg:        2 var:        0 std: 0
Added 4 avg:        3 var:        1 std: 1
Added 4 avg:  3.33333 var: 0.888889 std: 0.942809
Added 4 avg:      3.5 var:     0.75 std: 0.866025
Added 5 avg:      3.8 var:     0.96 std: 0.979796
Added 5 avg:        4 var:        1 std: 1
Added 7 avg:  4.42857 var:  1.95918 std: 1.39971
Added 9 avg:        5 var:        4 std: 2

ToDo: add Skewness and Kurtosis

23.02.2015

c++ CYK implementation

Filed under: Allgemein — Tags: — Thomas @ 14:02

Die Wikipedia Artikel zum Cocke-Younger-Kasami-Algorithmu kann man vergessen. Man kapiert nichts. Hab auf youtube ein 15min Video [1] von Benny Neugebauer dazu gefunden. Wunderbar, alles gleich verstanden :)
Hab ihn mal schnell in C++ implementiert. Hier die Hauptschleife:


    /*
    Für j = 2 ... n
      Für i = 1 ... n - j + 1
        Für k = 1 ... j - 1
          Setze V_{i,j} := V_{i,j} + { l | \exists B,C in N ((l -> BC) in P and B in V_{i,k} and C in V_{i + k, j - k}) \}

    Falls S \in V_{1,n}, stoppe und gib "w wird von G erzeugt" aus
    Stoppe und gib "w wird nicht von G erzeugt" aus
    */
    for(size_t row=1; row < n; row++) {
//        cout << "row " << row << "\n";
        for(size_t col=0; col < n-row; col++) {
//            cout << "col " << col << "\n";
            for(size_t k=0; k < row; k++) {
                const auto &e1 = V.at(k, col);
                const auto &e2 = V.at(row-k-1, col+k+1);

                for(size_t i=0; i < e1.size(); i++) {
                    for(size_t j=0; j < e2.size(); j++) {
//                        cout << "Check " << e1.at(i) << " " << e2.at(j) << "\n";
                        const Production::String toTest({e1.at(i), e2.at(j)});
                        for(const Production& p : P) {
                            if(p.right == toTest) {
                                // uniq append
                                if(contains(V.at(row, col), p.left) == false) {
                                    V.at(row, col).push_back(p.left);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

Für jeden Matrixeintrag in der oberen linken Dreiecksmatrix:
Für jeden Eintrag oberhalt in der Spalte und Diagonal nach oben:
Schaue nach ob die Konkatenation der beiden Einträge in der rechten Seite der Produktionsregeln vorkommen:
Ja) Linke Seite der Produktion in die Matrix eintragen.

Steht am Ende in der letzten Zeile, erste Spalte das Startsymbol, dann kann das Wort erkannt werden.

CYK.zip

[1] https://www.youtube.com/watch?v=JugIgxUyA4Q

18.02.2015

rosettacode - Simple moving average

Filed under: Allgemein — Tags: , , — Thomas @ 12:02

http://rosettacode.org/wiki/Averages/Simple_moving_average#C.2B.2B

The original rosetta C example shows the usage of variable function arguments. The C++ example shows how to implement a circular buffer. They are confusing and inefficient. My Version shows how to implement a simple moving average using modern c++ techniques.


#include < iostream >
#include < vector >

class SMA {
public:
    SMA(int period) : values(period), sum(0.0), idx(0), size(0) {
    }

    void add(double value) {
        const size_t period = values.size();
        // here is the magic. Update sum and vector in place
        sum = sum - values[idx] + value;
        values[idx] = value;

        // this implements the circular buffer
        idx = (idx+1)%period;
        if(size+1 <= period) {
            ++size;
        }
    }

    double avg() const {
        return sum/size;
    }

private:
    // store the last seen values
    std::vector values;
    // store the sum. so we dont have to recalculate it every time
    double sum;
    // the next element in the buffer we can override
    int idx;
    // ho many values was allready inserted. This is usually the same as the given periodb
    size_t size;
};

int main() {
    SMA foo(3);
    SMA bar(5);

    std::vector data = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 };

    for(auto &val : data) {
        foo.add(val);
        std::cout << "Added " << val << " avg: " << foo.avg() << std::endl;
    }
    std::cout << std::endl;

    for(auto &val : data) {
        bar.add(val);
        std::cout << "Added " << val << " avg: " << bar.avg() << std::endl;
    }

    return 0;
}


Flussschlauch

Filed under: Allgemein — Thomas @ 10:02
Original Fluss Daten

Original Fluss Daten

Original Vermaschung

Original Vermaschung

Original Vermaschung

Original Vermaschung

With intersecting

With intersecting

Remove intersecting

Remove intersecting

refine + without intersecting

refine + without intersecting

Neuer Ansatz: cross Segmente die sich schneiden kürzen

Neuer Ansatz: cross Segmente die sich schneiden kürzen

refine + cross segmente kürzen

refine + cross segmente kürzen

refine + verbessert

refine + verbessert

need more nodes

need more nodes

Flussschleife interpoliert

Flussschleife interpoliert

0.5m refine Flussschleife interpoliert

0.5m refine Flussschleife interpoliert

« Newer PostsOlder Posts »

Powered by WordPress