C++Guns – RoboBlog blogging the bot

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;
}


11.02.2015

replace templates with c++14 auto

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

#include < iostream >

template< class T >
T func1(T t) { return t; }

auto func2(auto t) { return t; }

int main() {
  std::cout << func1(1) << func1(2.2) << func2(3) << func2(4.4);
}

autoauto.cpp:6:18: note: deduced return type only available with -std=c++1y or -std=gnu++1y

g++ --std=c++14 autoauto.cpp 
./a.out 
12.234.4

29.01.2015

Five Myths about C++ BUSTED!

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

This is a short of http://www.stroustrup.com/Myths-final.pdf

Myth 1: “To understand C++, you must first learn C”

C is almost a subset of C++, but it is not the best subset to learn first because C lacks the notational
support, the type safety, and the easier-to-use standard library offered by C++ to simplify simple tasks
.
Consider a trivial function to compose an email address:

Busted!

Myth 2: “C++ is an Object-Oriented Language”

3. Myth 2: “C++ is an Object-Oriented Language”
C++ supports OOP and other programming styles, but is deliberately not limited to any narrow view
of “Object Oriented.” It supports a synthesis of programming techniques including object-oriented and
generic programming
. More often than not, the best solution to a problem involves more than one style
(“paradigm”). By “best,” I mean shortest, most comprehensible, most efficient, most maintainable, etc.

Busted!

Myth 3: “For reliable software, you need Garbage Collection”
In short:
Never use new or delete. Use some classes which does the memory management for you, e.g. std::vector. For short living object, create them on the stack, Instead on the heap with new. Use destructor to clean up memory (and other resources like file handles) if the lifetime of an object comes to an end.

If you have to pass an object around, don't use raw pointer. If it is possible, don't use pointer at all. If there exist only one owner at a time, use the move magic with rvalue reverences. If the object is shared by more than one owner, use std::shared_pointer to store a pointer. It implements a reference counting and deletes the object of nobody owns them anymore. Use auto and make_shared<> for syntactic sugar.

Naked deletes are dangerous – and unnecessary in general/user code. Leave deletes
inside resource management classes, such as string, ostream, thread, unique_ptr, and shared_ptr.

For resource management, I consider garbage collection a last choice, rather than “the solution” or an ideal:
1.Use appropriate abstractions that recursively and implicitly handle their own resources. Prefer such objects to be scoped variables.
2. When you need pointer/reference semantics, use “smart pointers” such as unique_ptr and
shared_ptr to represent ownership.
3. If everything else fails (e.g., because your code is part of a program using a mess of pointers
without a language supported strategy for resource management and error handling), try to
handle non-memory resources “by hand” and plug in a conservative garbage collector to handle
the almost inevitable memory leaks.

Busted!

Myth 4: “For efficiency, you must write low-level code”

I have seen sort run 10 times faster than qsort. How come? The C++ standard-library sort is
clearly at a higher level than qsort
as well as more general and flexible. It is type safe and parameterized
over the storage type
, element type, and sorting criteria. There isn’t a pointer, cast, size, or a byte in
sight
. The C++ standard library STL, of which sort is a part, tries very hard not to throw away information. This makes for excellent inlining and good optimizations.

Generality and high-level code can beat low-level code. It doesn’t always, of course, but the sort/qsort comparison is not an isolated example. Always start out with a higher-level, precise, and type safe version of the solution. Optimize (only) if needed.

Busted!

Myth 5: “C++ is for large, complicated, programs only”

C++ is a big language. The size of its definition is very similar to those of C# and Java. But that does not
imply that you have to know every detail to use it or use every feature directly in every program.

After all, C++ is designed for flexibility and generality, but not every
program has to be a complete library or application framework.

Busted!

Read the paper for detailed examples.
Busted!!

02.01.2015

raw speed of C using OO with C++

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

Programs written in C are very very fast. Those written in C++ can be slower due to the fact that copying object is not alway easy as copying an array of numbers. One have to call the copy constructor maybe with side effects like allocate some space.

The language C++ is full backwards compatible to C. So what must we do to use classes and objects with the copy speed of C?

First of all, in C there exist so called POD (plan old data) types like integers, floating point numbers as well as structs und unions. The C language have no class keyword. But classes in C++ can be POD too under certain circumstances. What exactly we need to get a class POD can be read in the C++11 Standard or under [1].
The great benefit of POD types is that it can be copied by simply moving bytes in RAM from one location to another. No call to constructors is needed. That speed up copying enormously.

Enough theory, lets build our own object oriented POD class!
Let's start with a simple class Point that represent a point in 2D. We want to construct a Point object by passing its x and y coordinate. We also want some getter and setter for the coordinates to make the member variables private.

Here is our first implementation:


#include < iostream >
#include < type_traits >

class Point {
public:
  Point() : x(0), y(0) {}
  Point(double x, double y) : x(x), y(y) {}

  void setX(double x) { this->x = x; }
  void setY(double y) { this->y = y; }
  double getX() const { return x; }
  double getY() const { return y; }

private:
  double x, y;
};

int main() {
  Point p(1,2);
  Point p2;

  std::cout << p.getX() << " " << p.getY() << std::endl;

  return 0;
}

Pretty straight forward, right? Save it under point.cpp and compile it with:

$ g++-4.7 -Wall -Wextra -std=c++11 point.cpp 
$ ./a.out 
1 2

I use as compiler gnu g++ version 4.7 to test backwards compatibility. Current is 4.9.2 and 5.0 will be released soon. But you can use any compiler as long it supports c++11. Except for g++ 4.6 thats too old.

To test of a type id POD c++11 provides a simple test [2] which is defined in header file "type_traits". Add this line to our main() function, recompile and run again


std::cout << std::boolalpha;
std::cout << "Point is POD " << std::is_pod::value << "\n";
$ g++-4.7 -Wall -Wextra -std=c++11 point.cpp 
$ ./a.out
1 2
Point is POD false

This shouldn't be too much surprising. As mentioned earlier there are strict rules for when a type is POD. For example the class must be a TrivialType [3]. We can test with is_trivial().


std::cout << "Point is TrivialType " << std::is_trivial::value << "\n";
$ g++-4.7 -Wall -Wextra -std=c++11 point.cpp 
$ ./a.out
1 2
Point is POD false
Point is trivial false

A TrivialType in turn must be TriviallyCopyable [4] and must have Trivial default constructor [5]. Lets test these:


std::cout << "Point is TriviallyCopyable " << std::is_trivially_copyable::value << "\n";
std::cout << "Point is trivially default-constructible " << std::is_trivially_default_constructible::value << "\n";

...

Unfortunately g++ 4.9 does not implement these tests. So we have to wait for version 5.
Instead we can have a closer look about what a "Trivial default constructor" is.

The default constructor for class T is trivial (i.e. performs no action) if all of the following is true:

  • The constructor is not user-provided (that is, implicitly-defined or defaulted)
  • T has no virtual member functions
  • T has no virtual base classes
  • T has no non-static members with brace-or-equal initializers
  • Every direct base of T has a trivial default constructor
  • Every non-static member of class type has a trivial default constructor
  • Right the first condition does not hold. We provide a user default constructor which simply set x and y to zero. Lets remove this constructor and see whats happen:

    $ g++-4.7 -Wall -Wextra -std=c++11 point.cpp 
    point.cpp: In function ‘int main()’:
    point.cpp:20:9: error: no matching function for call to ‘Point::Point()’
    point.cpp:20:9: note: candidates are:
    point.cpp:7:3: note: Point::Point(double, double)
    point.cpp:7:3: note:   candidate expects 2 arguments, 0 provided
    point.cpp:4:7: note: constexpr Point::Point(const Point&)
    point.cpp:4:7: note:   candidate expects 1 argument, 0 provided
    point.cpp:4:7: note: constexpr Point::Point(Point&&)
    point.cpp:4:7: note:   candidate expects 1 argument, 0 provided
    

    It seems we don't have any default constructor anymore. Only the explicit user defined with two arguments and the implicit copy constructor. Thats right. That c++ standard say, that when a explicit user constructor is provided, the compiler don't have to create default constructors.

    With the new 2011 standard we can explicit request a implicit default constructor!
    Replace this line with the following:

    
    Point() : x(0), y(0) {}
    Point() = default;
    
    $ g++-4.7 -Wall -Wextra -std=c++11 point.cpp 
    $ ./a.out 
    1 2
    Point is POD true
    Point is TrivialType true
    

    Congratulations! We have a object oriented class that is as fast as old C style stuff.

    One important note: Variables in C are not automatic initialized! So our class Point is also not default initialized! See [6] for details. You have to call a constructor explicit e.g.
    Point p = Point();

    Here is some nice code to make sure your types are POD. If something goes wrong and the
    type is not POD, it gave an compiler error

    
    #if __cplusplus >= 201103L
    static_assert(!std::is_polymorphic::value, "Please do not add virtual functions to class Point!");
    static_assert(std::is_pod::value, "Class Point is not POD!");
    #endif
    

    The #if __cplusplus stuff is to check if the compiler has enabled c++11 standard.
    Did you know that gnu g++ has set __cplusplus simply to 1 and this bug was know over 10 years?! The reason is very simple: If they fix it, they broke solaris 8. See [7]. Stupid non standard compliant solaris 8 code!

    You can download the example code here point.cpp.zip

    [1] http://en.cppreference.com/w/cpp/concept/PODType
    [2] http://en.cppreference.com/w/cpp/types/is_pod
    [3] http://en.cppreference.com/w/cpp/concept/TrivialType
    [4] http://en.cppreference.com/w/cpp/concept/TriviallyCopyable
    [5] http://en.cppreference.com/w/cpp/language/default_constructor
    [6] http://en.cppreference.com/w/cpp/language/default_initialization
    [7] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773

    todo:
    *Ich glaube ja nicht daran, dass das Vorhandensein eines Konstruktors den Code langsamer macht.
    *Eine Sache, die ich unterstreichen würde, ist, dass in C++ "harmlos" aussehender Code sehr ineffizient sein kann
    *Für so eine Behauptung muss man schon vernünftige Benchmarks zeigen
    *C++-03 noch kein Moven ga

    16.11.2014

    Spass mit Pointer

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

    "man kann sich so derbe den kopf weg schiessen damit"

    
    int global;
    
    char *func() {
      return (char*)&global;
    }
    
    int main() {
    
      char *x = func();
      int *RocketPtr = (int*)x;
      *RocketPtr = 1337;
      cout << global;
    }
    

    Output : 1337

    20.10.2014

    howto allocate array in C++ and pass it back to fortran

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

    test.cpp

    
    #include < stdlib.h >
    
    // fortran can only call C routines
    extern "C" {
      // we need the address of the fortran pointer thus a pointer of a pointer.
      void myC_func(int **arr) {   
        // we cannot use new() here because fortran deallocate() use free() instead of delete[]
        *arr = (int*) malloc(12*sizeof(int));
        for(int i=0; i < 12; i++) {
          (*arr)[i] = i;
        }
      }
    }
    

    test.F90

    
    ! https://gcc.gnu.org/onlinedocs/gcc-4.6.2/gfortran/Working-with-Pointers.html
    
    program main
      use iso_c_binding
      implicit none
      
      interface
        subroutine my_routine(arr) bind(c,name='myC_func')
          import :: c_ptr
          ! If a pointer is a dummy-argument of an interoperable procedure, 
          ! it usually has to be declared using the VALUE attribute. 
          ! void* matches TYPE(C_PTR), VALUE, while TYPE(C_PTR) alone matches void**. 
          type(c_ptr), intent(out) :: arr
        end subroutine
      end interface
      
      type(c_ptr) :: cptr
      integer,pointer :: fptr(:)
      
      ! allocate and fill cptr
      call my_routine(cptr)
      ! convert it to fortran pointer
      call c_f_pointer(cptr, fptr, [12])
      
      if(associated(fptr)) write(*,*) "associated"
      write(*,*) fptr
      deallocate(fptr)
      
    end program main
    
    g++ -Wall -Wextra -c test.cpp 
    gfortran -Wall -Wextra -fcheck=all test.F90 test.o
    
    valgrind ./a.out 
    ==5256== Memcheck, a memory error detector
    ==5256== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==5256== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
    ==5256== Command: ./a.out
    ==5256== 
     associated
               0           1           2           3           4           5           6           7           8           9          10          11
    ==5256== 
    ==5256== HEAP SUMMARY:
    ==5256==     in use at exit: 0 bytes in 0 blocks
    ==5256==   total heap usage: 22 allocs, 22 frees, 11,874 bytes allocated
    ==5256== 
    ==5256== All heap blocks were freed -- no leaks are possible
    ==5256== 
    ==5256== For counts of detected and suppressed errors, rerun with: -v
    ==5256== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
    

    07.10.2014

    Faster Code – Part 6 – Sprungvorhersage - anschaulich

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

    Sehr schöne anschauliche Erklärung:

    http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array

    04.10.2014

    merge/connect nearby poylgons

    Filed under: Allgemein — Tags: , — Thomas @ 13:10

    Zwei Polygone verbinden die sich überlappen ist einfach (union).
    Aber was, wenn sich die Polygone nur berühren oder einen sehr kleinen Abstand von einander haben?

    Im Internet findet man kaum etwas. Hier findet man einen Ansatz über die Konvexe Hülle. Ich hab ihn mir noch nicht genauer angesehen.

    Mein Ansatz basiert darauf, die Polygone so zu verbinden, wie man das als Mensch auch machen würde. Also an den Stellen, wo sie sich zu nahe kommen, werden sie verbunden. Und die restlichen, dann überflüssigen, Teile vom Polygon gelöscht.

    Um zu verdeutlichen was genau gemeint ist und wie die Ergebnisse aussehen, hier ein kleines Video.

    Die jetzige Version funktioniert recht stabil. Es gibt noch zwei Sonderfälle die zu behandeln sind. Von der Komplexität her hat der Algorithmus eine quadratische Laufzeit und kann Theoretisch auf linear-logarithmisch gesenkt werden.
    Aber erstmal werde ich überprüfen, ob der Algorithmus auch auf realen Daten zufriedenstellende Ergebnisse liefert.

    04.09.2014

    virtual inheritance and sizeof()

    Filed under: Allgemein — Tags: , — Thomas @ 10:09

    Folgender Code:

    
    #include < iostream >
    #include < stdint.h >
    
    using namespace std;
    
    class Base {
       public:
       int32_t a;
    };
    
    class Derived :  public Base {
    public:
      int32_t b;
    };
    
    class VirtualDerived : virtual  public Base {
    public:
      int32_t c;
    };
    
    int main() {
      cout << "sizeof Base " << sizeof(Base) << "\n";
      cout << "sizeof Derived " << sizeof(Derived) << "\n";
      cout << "sizeof VirtualDerived " << sizeof(VirtualDerived) << "\n";
    
      return 0;
    }
    

    ergibt auf einer 32Bit Maschine folgende Ausgabe

    sizeof Base 4
    sizeof Derived 8
    sizeof VirtualDerived 12
    

    Die Größe der VirtualDerived Klasse ist also nicht einfach die Summer zweier 4Byte Variablen, sondern auch noch zusätzlich ein 4Byte Pointer auf die Base Klasse.

    Auf einer 64Bit Maschine sind es entsprechend 16Byte

    sizeof Base 4
    sizeof Derived 8
    sizeof VirtualDerived 16
    

    03.09.2014

    Fortran is DEAD!!

    Filed under: Allgemein — Tags: , , — Thomas @ 19:09

    Leute, ist sag es schon die ganze Zeit: Fortran ist eine tote Sprache.
    Und damit meine ich nicht nur diese verbuggten Compiler. Oder dass es ewig braucht bis man ein neues Feature vom Compiler unterstützt wird. Im Fortran 2003 Standard sind zwar schön viele OO Ansatze festgelegt, aber ich kenne kein Compiler der den Standard nach 10 Jahre komplett unterstützt. Andere Sprachen sind schon 2 Schritte weiter.

    Nein, diesmal habe ich viel bessere Argumente auf Lager. In dem Paper [1] wurden 800000 Software Projekte und 13000 Programmierer ausgewertet. Ich möchte nur zu einem Bild aus diesem Paper meine Meinung loswerden. Dieses da:

    languages

    Also, man sieht hier die Wahrscheinlichkeit, mit der man die Programmiersprache wechselt, wenn ein neues Projekt angefangen wird. Weis bis blau sind niedrige Wahrscheinlichkeiten und rot bis schwarz hohe.
    Die Punkte auf der Diagonalen zeigen, dass man die Sprache NICHT wechselt.
    Was haben wir denn da alles:
    Rote Punkte sehe ich bei allesn *Basic Sprachen. Auch bei der C-Familie mit Java, Perl, PHP, Python bleiben die Programmierer bei ihrer Sprache.

    Welche Sprachen bekommen Zuwachs? Das sieht man schön an den vertikalen Balken. Also Java, C/C++ und meinetwegen noch PHP. Das sind also die view Großen wohin die Programmierer wechseln, nachdem sie erkannten, dass ihre vorherige Wahl Schrott war. Tja, wagt es nicht das Wort gegen C++ zu erheben ;) Die Sprache ist sowas von geil und wird den ganzen anderen Schrott längerfristig schon tot trampeln ;)

    Wohin rennen denn die Fortran Leute? JAVA. Ach ich lach mich kaputt. Das sind doch total verschiedene Welten.
    Ich wette die Auftraggeber wollten parallelisierte hoch performante Software. Haben aber keine Programmierer gefunden der was aufn Kasten hat, und der Rest kam mit der Sprache nicht klar. Also wurde es wieder Java. Das ist ja bekannt und jeder kann es. Und jetzt ärgern die sich mit ihrere total aufgeblasenen, lahmen Software rum, HäHä.

    Die *Basic sprachen sind auch alle hinfällig. Zwar wechseln die Leute hier nicht, aber es kommen auch keine neuen hinzu. Die Sprache stirbt also aus, wenn auch alle *Basic Programmierer ausgestorben sind. Sehr einfach Das ;)

    [1] Empirical Analysis of Programming Language Adoption; Leo A. Meyerovich; Ariel S. Rabkin

    « Newer PostsOlder Posts »

    Powered by WordPress