Jo en Bug. So assigment subroutine und gfort 4.8 4.9. Vllt geht es in 5.0 ja wieder.
09.02.2015
02.02.2015
normalized-rgb
Als ich gestern etwas mit OpenCV gearbeitet habe, bin ich auf eine
interesannte Seite gestossen [1] . Es wird dort von normailsierten RGB
geredet. Dabei wird getrennt für jeden Kanal, der Pixelwert durch die
Summe des Pixels über alle 3 Kanäle geteilt.
R’ = R/(R+G+B)
G’ = G/(R+G+B)
B’ = B/(R+G+B)
Dabei geht die Lichtinformation im Bild verloren. Ich finde das eine
interesannte Ausgangslage für weitere Berechnungen. Oft ist doch nur die
Farbe einzelner Objekte wichtig, nicht aber wie sie beleuchtet wurden.
Es sind nur noch 2 Byte pro Pixel, statt 3 Byte, notwenig.
R' + G' + B'=1
B' = 1 - R' - G'
Ein Angabe von 2 der 3 Werte ist also hinreichend. Damit kann der Farbort
charakterisiert werden, nicht aber die absolute Intensit¨t des Farbreizes. Das
heißt die Länge des Farbvektors wird nicht angegeben.
[1] http://www.aishack.in/tutorials/normalized-rgb/
more crazy C
#include
#define CACHE 256
enum { h_unknown = 0, h_yes, h_no };
unsigned char buf[CACHE] = {0, h_yes, 0};
int happy(int n)
{
int sum = 0, x, nn;
if (n < CACHE) {
if (buf[n]) return 2 - buf[n];
buf[n] = h_no;
}
for (nn = n; nn; nn /= 10) x = nn % 10, sum += x * x;
x = happy(sum);
if (n < CACHE) buf[n] = 2 - x;
return x;
}
int main()
{
int i, cnt = 8;
for (i = 1; cnt || !printf("\n"); i++)
if (happy(i)) --cnt, printf("%d ", i);
printf("The %dth happy number: ", cnt = 1000000);
for (i = 1; cnt; i++)
if (happy(i)) --cnt || printf("%d\n", i);
return 0;
}
from http://rosettacode.org/wiki/Happy_numbers#C
29.01.2015
Five Myths about C++ BUSTED!
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!!
26.01.2015
Fortran save, data, static, global, parameter WTF?
Whats the difference between between save, static, global, local and parameter variables?
Save and static are two words for the same thing.
I found a nice definition of what save do in the Fortran 77 Standard [1]
Within a function or subroutine subprogram, an entity specified by a SAVE statement does not become undefined as a result of the execution of a RETURN or END statement in the subprogram
subroutine func()
implicit none
real, save :: time
time = time + 1
write(*,*) time
end subroutine
program test
implicit none
integer :: i
do i = 1, 10
call func()
end do
end
1.00000000
2.00000000
3.00000000
4.00000000
5.00000000
6.00000000
7.00000000
8.00000000
9.00000000
10.0000000
You can count how often a subroutine is called. If you ever want to do this... I can not recommend to do it in this way.
As you may have noticed, I have not initialized the time variable with an start value.
You can do this with the data instruction.
subroutine func()
implicit none
real :: time
data time/100/
time = time + 1
write(*,*) time
end subroutine
101.000000
102.000000
103.000000
104.000000
105.000000
106.000000
107.000000
108.000000
109.000000
110.000000
The save specifier is not needed by using the data keyword.
This may result in confusion, because not everybody knows exactly what the data specifier does.
Again: do not use it.
The greatest pitfall with static variables is this:
real :: time = 0
If you initialize a variable by the declaration, it become a static variable! That really really hurts. You want be a good programer and always zero your variables and then you crash the hole program :D
Lets talk about parameters. Many programmers declare they constans with the save attribute.
I can not recommend this.
First: Constants does not change. Variables with save attribute can change.
real, save :: PI = 3.14...
PI = 4
All fine ;)
If you use parameter instead of save the compiler can detect this issue.
real, parameter :: PI = 3.14...
PI = 4
PI = 4
1
Error: Named constant 'pi' in variable definition context (assignment) at (1)
Second: Fortran is a high performance language. You can easily vectorize assigments using the forall constrcut.
All functions called from the forall constrcut must be declared as pure. to ensure that they have no side effects.
function func() result(val)
implicit none
real, save :: PI = 3.14
real :: val
val = PI
end function
forall( i = 1:100 ) A(i) = func()
forall( i = 1:100 ) A(i) = func()
1
Error: Reference to non-PURE function 'func' at (1) inside a FORALL block
And a pure function can not have static variables
pure function func() result(val)
implicit none
real, save :: PI = 3.14
real :: val
val = PI
end function
real, save :: PI = 3.14
1
Error: SAVE attribute at (1) cannot be specified in a PURE procedure
Using parameter solves the issue
pure function func() result(val)
implicit none
real, parameter :: PI = 3.14
real :: val
val = PI
end function
forall( i = 1:100 ) A(i) = func()
$ ifort -O2 -c save.f90 -vec-report3
save.f90(19): (col. 25) remark: LOOP WAS VECTORIZED
The last thing I talk about are global variables.
They can be accessed and overwritten from everywhere by everyone anytime. Happy bug chasing...
One way to create global variables in Fortran is using the COMMON keyword. I allready wrote about that..
[1] http://www.fortran.com/fortran/F77_std/rjcnf-8.html#sh-8.9
17.01.2015
suppress "unused dummy argument" warning in fortran
Here is my way to supress the "unused dummy argument" warning. I'm searched a long time but did not find a solution which works on any compiler and newer fortran standard.
In C/C++ it is very easy. Just write (void)variable; But this just trigger an "Unclassifiable statement" error.
#define UNUSED(x) if(size( (/(x)/) ) < 0) continue
program main
implicit none
type testtype
integer :: x
end type
type(testtype) :: x
type(testtype), pointer :: y => null()
integer :: z
UNUSED(x)
UNUSED(y)
UNUSED(z)
end program
$ gfortran -Wall -Wextra -fcheck=all -g test.F90 $ ./a.out $
hf
13.01.2015
Windows ist fürn Arsch
Ja wirklich. Windows ist fürn Arsch. Und nicht erst seit heute. Diese Erfahrung mach ich jetzt schon seit 15 Jahren. Immer wieder.
Typisches Scenario:
Man wacht morgens auf und schaltet das Laptop ein. "Piiieep Pip Pip", schwarzer Bildschirm. Laptop kaputt (Nvidia Bug (google it!)). Wurde schon einmal repariert. Jetzt endgültig gestorben.
Und wie es Murphy will, muss man ganz dringed weiter arbeiten, denn der Abgabetermin ist bald. Ach kein Problem, wir bauen die Festpatte einfach in den großen Rechner ein und kaufen bei Gelegeheit ein neues Laptop.
Festplatte ausbauen geht dank Levono in 30 Sekunden und einbauen geht genauso schnell.
Anschalt:
Bios Screen, Window Logo, *reboot.
Biso Screen, Windows reparieren - ja, 15min warten *reboot*
Bios Screen, Window Logo, *reboot.
Biso Screen, Windows reparieren - ja, 30min!! warten *reboot*
Bios Screen, Window Logo, *reboot.
Biso Screen, Windows reparieren - NEIN! Normal starten, bitte, endlich, bitte!
Bios Screen, Window Logo, *reboot.
Biso Screen, Windows reparieren - ja, keine Ahnung wie lange, bin weg gegangen...
"Ihr Windows konnte nicht repariert werden" Wenden sie sich an ein Admin der eine Neuinstallation macht...
Bei den manuellen Reperaturoptionen ist mir aufgefallen, dass die Festplatte als D: erkannt wurde und nicht C: AAAh HA! Es ist ja bekannt, dass sich Windows selbst umbringt wenn es nicht von C: aus startet. Also DVD Laufwerk abgestöpselt und (nach 3 weiteren Fehlversuchen) im Bios von IDE nach AHCI umgestellt und siehe da, es bootet.
Naja, nach weiteren fümf Minuten.
Ok, fassen wir zusammen. Um 9Uhr habe ich angefangen. Jetzt ist 11Uhr. Macht zwei Stunden. Jetzt fehlt nur noch der neue Grafikkartentreiber...
Und unter Linux? Denk es euch. Eine Minute um die Festplatte zu wechseln und auch evtl. den Grafikkartenteriber neu installieren.
Also Windows ist fürn Arsch, und das schreib ich bestimmt alle 2 Jahre. Ich sollte meine älteren Posts mal ausgraben...
04.01.2015
Detecting undesired lines
Sehr nette Idee. Müsste man nur noch herausfinden wie man diese Cluster erkennt.
SOME ASPECTS OF PATTERN RECOGNITION BY COMPUTER
by ADOLFO GUZMAN-ARENAS
B.S., Instituto Politecnico Nacional (Mexico), 1965;
"The alpha-Lambda transformation.
The following scheme is useful in detecting undesired lines when dealing with rectliniear bodies. Given an array containing elementary segments (a small number of points plus a direction associated to them), as indicate in figure 'LITTE SEGMENTS', as we associate with each segment a pair of numbers, alpha is the angle that this segment forms with the x-axis, and lambda if the distance of the (extended) line from the origin.
That is to say, we convert the figure to an array of points (see figure 'CLUSTERING'). In the alpha-lambda space, points which fall close together are over the same line, so that frequency count will eliminate the spurious segments, as desired. Clouds with the same alpha are parallel lines, and this fact could be used in order to look for parallel lines.
Smooth curved lines could also be detected by this method, if we use a fancier criteria for the detection of clusters (1).
(1) Work in the area is:
1. Evan L. Ivie. PhD Thesis [18].
2. Probably a conventional pattern clasifier will do it. See N. J. Nilsson [26].
[18] Ivie, E. L., Search Procedures based on Measure of Relatedness Between Documents, Project MAC Technical Report MAC-TR-29 (M.I.T. Ph.D. Thesis), June 1966.
[26] Nilsson, N.J., Learning Machines, McGraw Hill, 1965."
02.01.2015
raw speed of C using OO with C++
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
