Forum: Compiler & IDEs Berechnungen beim compilieren


von Benedikt K. (benedikt)


Lesenswert?

Ich versuche ein Makro zu schreiben, das eine Variable in Abhängigkeit 
von einer Konstanten mit einer 2er Potenz multiplizieren soll, so dass 
es keinen Überlauf gibt.
Hier ein paar Beispiele die verdeutlichen was ich machen möchte:
y=pmul(x,13);
x soll hier mit 13*16=208 multipliziert werden, denn 16 ist die größte 
2er Potenz, die sicherstellt, dass das Ergebnis nicht größer als 65535 
werden kann (x=8bit, y=16bit).
y=pmul(x,68);
x soll nun mit 2*68=136 multipliziert werden, denn 2 ist die größte 2er 
Potenz, die sicherstellt, dass das Ergebnis nicht größer als 65535 
werden kann.

In einer Funktion wäre das ganze kein Problem, allerdings kann dann der 
konstante Faktor dann nicht mehr zur Laufzeit berechnet werden. Da der 
Faktor aber auch ein Fließkommazahl sein kann, möchte ich das gerne 
vermeiden.

Ich suche also einen Trick, um zur Compilezeit 255/n zu berechnen und 
das Ergebnis auf eine 2er Potenz abzurunden

von tuppes (Gast)


Lesenswert?

Wenn du genügend Speicher hast: Lookup-Table mit 255 Einträgen.

von Oliver (Gast)


Lesenswert?

Ich habs ja nicht ganz kapiert, was du willst, aber wenn mir bei so 
etwas gar nichts mehr einfällt, und n zur Compilezeit feststeht, dann 
geife ich gerne mal zu Excel, und bau mir eine Tabelle der Art:
(wer will schon Schönheitspreise für das eleganteste Programm...)

#define pmul_1(x) ((65536/2)*(x))
#define pmul_2(x) ((65536/2)*(x))
#define pmul_3(x) ((65535/4)*(x))
...
#define pmul_255(x) ((((65535/256)*(x))

das in eine Headerdatei kopiert, und dann im Programm als

y = pmul_13(x);

aufgerufen. Vielleicht müssen da noch ein paar typecasts rein, aber 
prinzipiell müsste es doch so gehen, oder?

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ist das nicht sowas wie ein Logarithmus?

Das hier sollte doch sowas tun:
1
#define MAXPOW2(x) \
2
  (\
3
  (x) >= 128? 1:\
4
    (\
5
    (x) >= 64? 2:\
6
      (\
7
      (x) >= 32? 4:\
8
        (\
9
        (x) >= 16? 8:\
10
          (\
11
          (x) >= 8? 16:\
12
            (\
13
            (x) >= 4? 32:\
14
              (\
15
              (x) >= 2? 64: 128\
16
              )\
17
            )\
18
          )\
19
        )\
20
      )\
21
    )\
22
  )

Die Einrückungen sind nur der Schönheit wegen :), man kann das
natürlich auch etwas kompakter schreiben:
1
#define MAXPOW2(x) ((x)>=128?1:((x)>=64?2:((x)>=32?4:((x)>=16?8:((x)>=8?16:((x)>=4?32:((x)>=2?64:128)))))))

  

von Benedikt K. (benedikt)


Lesenswert?

Ganz so einfach ist es leider nicht, da die Konstante eine beliebige 
Kommazahl zwischen 0 und 65536 sein kann. Lookup Tabelle o.ä. fallen 
also weg.
Da es bei diesem Zahlenbereich nur 15 Möglichkeiten gibt, könnte ja 15 
verschiedene Funktionen machen, also

#define pmul_1(x, n) ((x)*((n)*1)
#define pmul_2(x, n) ((x)*((n)*2)
#define pmul_4(x, n) ((x)*((n)*4)
#define pmul_8(x, n) ((x)*((n)*8)
#define pmul_16(x, n) ((x)*((n)*16)
#define pmul_32(x, n) ((x)*((n)*32)
#define pmul_64(x, n) ((x)*((n)*64)
...
#define pmul_32768(x, n) ((x)*((n)*32768)

Was ich suche ist, wie ich #if #elif #endif in einem Makro anwende.

Wenn ich also im Programm pmul(x, 5) schreibe, soll das Programm 
pmul_32(x, 5) ausführen, also x*160 berechnen.

#if (n<2)
 pmul_128(x,n)
#elif (n<4)
 pmul_164(x,n)
#elif (n<8)
 pmul_132(x,n)
#elif (n<16)
 pmul_132(x,n)
...
#else
 pmul_11(x,n)
#endif


Mist, zu lange geschrieben, Jörg war schneller.
Ich denke mal das ist genau das was ich suche. Ich werde es mal 
ausprobieren, schonmal Danke !

von Benedikt K. (benedikt)


Lesenswert?

Ich habs mal ausprobiert: Es macht genau das was ich wollte. Nochmals 
Danke !

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.