Forum: Compiler & IDEs Fixpoint Berechung GCC AVR Studio


von Joerg K. (kohlibri)


Lesenswert?

Hallo Leute,
ich habe eine Frage, vielleicht könnt ihr mir weiterhelfen.
Ich verwende: AVR Studio 6.2 mit AVR8_Toolchain_Version:3.4.4.1229 
GCC_VERSION:4.8.1.

Ich habe eine Funktion um eine Line zwischen zwei Punkten zu berechnen. 
Dabei berechne ich die Steigung vor der Schleife um Divisionen zu 
vermeiden. Um den Compiler zu bewegen, erst die Multiplikation und dann 
die eine Division auszuführen, habe ich die Zwischenwertvariable als 
volatile definiert. Es treten keine Überläufe auf und x2 ist immer 
größer als x1.
1
void line(int16_t x1, int16_t y1, int16_t x2, int16_t y2)  {
2
...
3
volatile int32_t a;
4
...
5
a=(y2-y1)*16384;
6
a=a/(x2-x1);
7
...
8
for(x=0;x<(x2-x1);x++)  {
9
  b=a*x;
10
  set_pixel(abs(x1+x),abs((b/16384)+y1));
11
}
In dem einfachen Beispiel line (0,0,200,20) geht das aber nicht, denn a 
bleibt immer 0.

Wenn ich aber anstelle a=(y2-y1)*16384;
a=(y2-y1);
a=a*16384;
verwende, was ja im Prinzip das gleiche ist, funktioniert es bestens.

Ich habe mir schon den Wolf gesucht und den Workaround beim Debuggen 
gefunden. Ein ähnlichen Problem tritt auf, wenn ich in der Schleife den 
y Wert direkt nach der Geradengleichung berechne:
a=(y2-y1)/(x2-x1)*x;
Das Ergebnis ist immer falsch. Eigentlich sollten doch alle Berechnungen 
als 32 bit integer ausgeführt werden, oder?

Ist das ein generelles CPP Problem oder hat das nur der AVR GCC. Ich 
habe schon mit älteren Versionen des AVR GCC gearbeitet aber bisher noch 
solche Probleme gehabt.
Danke für Hinweise! Grüße Jörg

: Bearbeitet durch User
von holger (Gast)


Lesenswert?

>Eigentlich sollten doch alle Berechnungen
>als 32 bit integer ausgeführt werden, oder?

Nö. Das wär ja Verschwendung pur.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Joerg K. schrieb:
> Ich habe eine Funktion um eine Line zwischen zwei Punkten zu berechnen.
> Dabei berechne ich die Steigung vor der Schleife um Divisionen zu

Division brauch man keine:

http://de.wikipedia.org/wiki/Bresenham-Algorithmus

von Karl H. (kbuchegg)


Lesenswert?

Joerg K. schrieb:

>
1
> void line(int16_t x1, int16_t y1, int16_t x2, int16_t y2)  {
2
> ...
3
> volatile int32_t a;
4
> ...
5
> a=(y2-y1)*16384;
6
> a=a/(x2-x1);
7
> ...
8
> for(x=0;x<(x2-x1);x++)  {
9
>   b=a*x;
10
>   set_pixel(abs(x1+x),abs((b/16384)+y1));
11
> }
12
>
> In dem einfachen Beispiel line (0,0,200,20) geht das aber nicht, denn a
> bleibt immer 0.
>
> Wenn ich aber anstelle a=(y2-y1)*16384;
> a=(y2-y1);
> a=a*16384;
> verwende, was ja im Prinzip das gleiche ist

Nicht ganz.
Denn in
1
   ... (y2-y1)*16384
hast du mit
1
    .... int16_t y1, ...., int16_t y2 ....

eine 16 Bit Berechnung (auch die Mutliplikation).

Während du in
1
volatile int32_t a;
2
...
3
   a=(y2-y1);
4
   a=a*16384;
5
...

die Multiplikation in 32 Bit ausführst!


Datentypen sind nicht nur reine Dekoration. Die haben schon auch 
handfeste Auswirkungen.

> Ist das ein generelles CPP Problem oder hat das nur der AVR GCC.
Es ist ein generelles Problem aller C-Lernenden, dass sie die Rolle der 
Datentypen von Variablen und wie sich die in den durchgeführten 
Operationen auswirken, nicht richtig einschätzen. D.h. sofern sie die 
geltenden Regeln überhaupt kennen.

: Bearbeitet durch User
von Joerg K. (kohlibri)


Lesenswert?

> Es ist ein generelles Problem aller C-Lernenden, dass sie die Rolle der
> Datentypen von Variablen und wie sich die in den durchgeführten
> Operationen auswirken, nicht richtig einschätzen. D.h. sofern sie die
> geltenden Regeln überhaupt kennen.

Karl Heinz, vielen Dank für die Aufklärung, Man lernt ja nie aus... 
Könntest Du was zum Nachlesen empfehlen?

Johann, auch vielen Dank für den Link. Das werde ich mir mal genauer 
ansehen. Im Moment kann ich mit einer Division gut leben, in der 
Schleife sind es nur Multiplikationen/ Schiebeoperationen.

von Michael (Gast)


Lesenswert?

Joerg K. schrieb:
> for(x=0;x<(x2-x1);x++)  {
>   b=a*x;
> ...

Joerg K. schrieb:
> in der Schleife sind es nur Multiplikationen/ Schiebeoperationen.

In deiner Schleife erhöhst du x jeweils um 1. Warum multiplizierst du 
dann bei wirklich jedem Schleifendurchlauf x mit a, um b zu bestimmen. 
Ein
1
b += a
 würde es genauso tun.

von Joerg K. (kohlibri)


Lesenswert?

Michael schrieb:
> In deiner Schleife erhöhst du x jeweils um 1. Warum multiplizierst du
> dann bei wirklich jedem Schleifendurchlauf x mit a, um b zu bestimmen.
> Einb += a würde es genauso tun.

Danke für den Hinweis! Du hast natürlich recht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.