Seite 1 von 1

IsPowerOf2(), ld() (Logarithmus Dualis)

Verfasst: 24.07.2011 11:32
von cxAlex
Mal ein ganz kleiner Code-Schnipsel, aber doch sehr praktisch (zumindest für mich im Moment). 2 Kleine Macros um den Logarithmus einer Zahl zur Basis 2 zu berechnen und ein Macro um zu Überprüfen ob eine Zahl eine Potenz von 2 ist. Ich brauche das gerade in meinem ByteCode-Compiler um Divisionen und Multiplikationen durch Potenzen von 2 automatisch durch Bit-Shift Befehle ersetzen zu können.

Wers braucht:

Code: Alles auswählen

; Zahl ist 2^x
Macro IsPowerOf2(_Value)
  ((_Value&(_Value-1))=#Null)
EndMacro

; Logarithmus zur basis 2 (binärlogarithmus, Logarithmus Dualis)
#_1dLN_2 = 1.4426950408889634074
Macro ld(x)
  (Log(x)*#_1dLN_2)
EndMacro
Gruß, Alex

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Verfasst: 24.07.2011 13:45
von STARGÅTE
Nur der Formhalber:
Log(x)/#_LN_2
ist zu "langsam", es wäre besser 1/Log(2) als Konstante festzulegen und dann zu multiplizieren.

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Verfasst: 24.07.2011 14:45
von cxAlex
Ist gemacht, danke :)

Gruß, Alex

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Verfasst: 24.07.2011 15:04
von STARGÅTE
Danke, wie gesagt, ist eigentlich kleinkram, da Log() im vergleich dazu ewig braucht ^^

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Verfasst: 11.10.2011 16:41
von Helle
Da ich Ld auch gerade mal brauchte:

Code: Alles auswählen

Procedure.d Ld(x.d)
  !fld1                 ;lade y=1
  !fld qword[p.v_x]     ;lade x
  !fyl2x                ;berechnet y mal Ld(x) 
 ProcedureReturn 
EndProcedure

MessageRequester("Logarithmus dualis", StrD(Ld(123.456), 15))
Die FPU-Instruction "fyl2x" berechnet den Ld von x und multipliziert den dann mit y. Wird y auf 1 gesetzt (mit fld1), kommt eben Ld(x) heraus.

Gruß
Helle

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Verfasst: 14.10.2011 16:21
von Helle
Hier noch eine Version von IsPowerOf2:

Code: Alles auswählen

Procedure IsPowOf2(TestVal.d)                        ;der Testwert wird der Procedure als Double übergeben
  Double.q = PeekQ(@TestVal) & $7FFFFFFFFFFFFFFF      ;Vorzeichen-Bit ausblenden (Bit 63)
  Exp.q = Double >> 52                                ;Exponent = Bits 52 bis 62 (11 Bits)  
  Man.q = Double & $FFFFFFFFFFFFF                     ;Mantisse = Bits 0 bis 51 (52 Bits)
  If Man = $FFFFFFFFFFFFF                             ;also fast 1
    Man = 0                                           ;kann zu Null aufgerundet werden; ist ja Aufaddierung
    Res = 1                                           ;Exponent dafür um eins erhöhen    
  EndIf
  If Double = 0  Or Man <> 0 
    Res = #False                                      ;Null
   Else 
    Res + Exp + #True                                 ;Res mit Bias (1023 für Double), für #True evtl. besser 1
  EndIf  
 ProcedureReturn Res
EndProcedure

;Testwerte
Res = IsPowOf2(1.3079939052566739757e+297)
;Res = IsPowOf2(1025)
;Res = IsPowOf2(1024.000000000001)
;Res = IsPowOf2(1024.000000000000)
;Res = IsPowOf2(1)
;Res = IsPowOf2(0)
;Res = IsPowOf2(0.0625)

If Res
  Res$ = "Ja, der Exponent ist " + Str(Res - 1024)    ;1024 = Bias + 1 (#True)
 Else 
  Res$ = "Nein"
EndIf  

MessageRequester("Is Power of 2 ?", Res$)

Viel Spaß!
Helle