1. Artikel
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forum
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. Paules-PC-Forum.de
  2. Forum
  3. Programmierung
  4. XProfan
  5. Spezielles

ASM + Modulo

  • H.Brill
  • 24. Februar 2023 um 12:23
  • H.Brill
    Stammuser
    Reaktionen
    500
    Beiträge
    1.183
    • 24. Februar 2023 um 12:23
    • #1

    Hallo, ich suche ein Modulo, das auch (oder auch nur) mit Fließkommazahlen klar kommt.

    Das normale X% MOD Y% arbeitet ja nur mit Integerzahlen.

    Da es auch schnell sein muß, käme mir ein ASM-Proc recht. Da der Inline-Assembler ja

    auch FPU - Befehle kann, denke ich, daß sowas hin zu bekommen ist.

    Vielleicht haben ja die Forumsmitglieder, die sich besser als ich in ASM auskennen,

    wie z.B. Volkmar oder p.Specht, eine Idee.

    Wir sind die XProfaner.

    Sie werden von uns assimiliert.

    Widerstand ist zwecklos!

    Wir werden alle ihre Funktionen und Algorithmen

    den unseren hinzufügen.

  • Jens-Arne
    Schüler
    Reaktionen
    98
    Beiträge
    116
    • 17. März 2023 um 07:31
    • #2

    Hallo Heinz,

    ich habe das als fbPROC realisiert (JRPC3 erforderlich). Aber keine Angst, wenn Du JRPC3 nicht benutzen möchtest, ist die erzeugte native DLL hier beigefügt:

    Der Inhalt kann nicht angezeigt werden, da Sie keine Berechtigung haben, diesen Inhalt zu sehen.

    Code
    {$FbSyntax On}
    {$SetFbDllName fmod}
    
    fbPROC fmod(ByRef a As Double,ByRef b As Double,ByRef erg As Double) As Integer Export
      dim c As Double
      dim As LongInt x,y,z
      x=int(a)
      y=int(b)+1
      z=int(x/y) 'Multiplikator, der auf jeden Fall noch nicht ins Negative führt
      c=a-(b*z) 'diese Subtraktion beschleunigt die Ergebnissuche, da sie schon sehr nah ans Ziel führt
      while c>=b 'jetzt noch b solange vom übriggebliebenen Rest von a abziehen, bis wir das Ergebnis haben
        c=c-b
      endwhile
      erg=c
      return 1
    ENDPROC 'fmod
    
    fbPROC smod(ByVal a As Single,ByVal b As Single) As Integer Export
      dim c As Single
      dim As LongInt x,y,z
      dim erg As Integer
      x=int(a)
      y=int(b)+1
      z=int(x/y) 'Multiplikator, der auf jeden Fall noch nicht ins Negative führt
      c=a-(b*z) 'diese Subtraktion beschleunigt die Ergebnissuche, da sie schon sehr nah ans Ziel führt
      while c>=b 'jetzt noch b solange vom übriggebliebenen Rest von a abziehen, bis wir das Ergebnis haben
        c=c-b
      endwhile
      poke single,@erg,c
      return erg
    ENDPROC 'fmod
    
    declare f1!,f2!,erg!
    declare single s1,s2,serg
    
    cls
    f1!=52.2
    f2!=5.151
    fmod(@addr(f1!),@addr(f2!),@addr(erg!)) 'die DLL-Funktion heißt "FMOD@12" (großgeschrieben)
    print erg!
    s1=52.2
    s2=5.151
    serg=smod(s1,s2) 'die DLL-Funktion heißt "SMOD@8" (großgeschrieben) - das Ergebnis muss einer single-Variablen zugewiesen werden, da es sonst als Integer interpretiert wird
    print serg
    waitinput
    end
    Alles anzeigen

    Die Funktion FMOD@12 erwartet zwei Float-Werte. Da diese 8 Byte breit sind, DLL-Funktionsparameter aber stets 4 Byte breit sein müssen, sind hier die beiden zu verarbeitenden Werte als deren Adressen zu übergeben und als dritter Parameter die Adresse eines Float-Wertes, der das Ergebnis aufnimmt.

    Die Funktion SMOD@8 arbeitet mit Single-Werten, die 4 Byte breit sind und daher direkt übergeben werden können (nur zwei Parameter). Allerdings ist die Genauigkeit natürlich auch schlechter.

    Beste Grüße, Jens-Arne

  • Jens-Arne
    Schüler
    Reaktionen
    98
    Beiträge
    116
    • 17. März 2023 um 08:44
    • #3

    Und hier noch eine Version mit abgefangenem "Division durch null"-Fehler:

    Der Inhalt kann nicht angezeigt werden, da Sie keine Berechtigung haben, diesen Inhalt zu sehen.

    Code
    {$FbSyntax On}
    {$SetFbDllName fmod}
    
    fbPROC fmod(ByRef a As Double,ByRef b As Double,ByRef erg As Double) As Integer Export
      dim c As Double
      dim As LongInt x,y,z
      if b=0
        messagebox(0,"fmod: Division durch null.","Division durch null",0)
        erg=-1
        return 0
      else
        x=int(a)
        y=int(b)+1
        z=int(x/y) 'Multiplikator, der auf jeden Fall noch nicht ins Negative führt
        c=a-(b*z) 'diese Subtraktion beschleunigt die Ergebnissuche, da sie schon sehr nah ans Ziel führt
        while c>=b 'jetzt noch b solange vom übriggebliebenen Rest von a abziehen, bis wir das Ergebnis haben
          c=c-b
        endwhile
        erg=c
        return 1
      endif
    ENDPROC 'fmod
    
    fbPROC smod(ByVal a As Single,ByVal b As Single) As Integer Export
      dim c As Single
      dim As LongInt x,y,z
      dim erg As Integer
      if b=0
        messagebox(0,"smod: Division durch null.","Division durch null",0)
        poke single,@erg,-1
      else
        x=int(a)
        y=int(b)+1
        z=int(x/y) 'Multiplikator, der auf jeden Fall noch nicht ins Negative führt
        c=a-(b*z) 'diese Subtraktion beschleunigt die Ergebnissuche, da sie schon sehr nah ans Ziel führt
        while c>=b 'jetzt noch b solange vom übriggebliebenen Rest von a abziehen, bis wir das Ergebnis haben
          c=c-b
        endwhile
        poke single,@erg,c
      endif
      return erg
    ENDPROC 'fmod
    
    declare f1!,f2!,erg!
    declare single s1,s2,serg
    
    cls
    f1!=52.2
    f2!=5.151
    fmod(@addr(f1!),@addr(f2!),@addr(erg!)) 'die DLL-Funktion heißt "FMOD@12" (großgeschrieben)
    print erg!
    s1=52.2
    s2=5.151
    serg=smod(s1,s2) 'die DLL-Funktion heißt "SMOD@8" (großgeschrieben) - das Ergebnis muss einer single-Variablen zugewiesen werden, da es sonst als Integer interpretiert wird
    print serg
    waitinput
    end
    Alles anzeigen
  • H.Brill
    Stammuser
    Reaktionen
    500
    Beiträge
    1.183
    • 17. März 2023 um 10:23
    • #4

    Danke,

    Single-Genauigkeit reicht mir da völlig.

    Wenn mal nicht, kann man ja mit Double() zuerst konvertieren.

    Wir sind die XProfaner.

    Sie werden von uns assimiliert.

    Widerstand ist zwecklos!

    Wir werden alle ihre Funktionen und Algorithmen

    den unseren hinzufügen.

  • Jens-Arne
    Schüler
    Reaktionen
    98
    Beiträge
    116
    • 17. März 2023 um 16:41
    • #5

    Hallo nochmal,

    ich habe gerade festgestellt, dass die Single-Variante auch schneller ist als die genauere Float-Variante (ca. ein viertel).

    Da Du sagtest, dass es Dir auf Geschwindigkeit ankommt, wäre aber zu erwägen, dass Du die gesamte Berechnung in einer fbPROC ausführst. Denn jeder Funktionsaufruf benötigt aufgrund von Registergeschiebe Zeit, sodass es besser wäre, nur eine Funktion aufzurufen und darin alles zu berechnen, was es zu berechnen gibt, als innerhalb einer Schleife tausendfach die eine Funktion aufzurufen, die nur die Modulo-Funktion ausführt.

    Zum Vergleich:

    10.000 Mal smod aus einer Profan-Schleife aufrufen: 268ms

    10.000 Mal smod-Berechnung innerhalb einer fbPROC: 0ms (!!! - also "off scale low")

    Im ersten Fall kosten also keinesfalls die Berechnungen an sich irgendeine messbare Zeit, sondern allein die 10.000 Funktionsaufrufe.

    Allerdings ist das immer noch viel besser, als das in reinem XProfan zu schreiben (2 Sekunden).

    Vermutlich ist die Single-Variante von außen gesehen auch nur deshalb schneller, weil sie einen Parameter weniger hat.

    Gruß, Jens-Arne

    3 Mal editiert, zuletzt von Jens-Arne (17. März 2023 um 16:59)

  • p. specht
    Premium-Mitglied
    Reaktionen
    986
    Beiträge
    5.665
    • 22. März 2023 um 09:51
    • #6

    Interessant! Was kommt dann bei Pi() mod exp(1) raus? Und ist das Ergebnis bei "unendiich" langen Kommastellen sinnvoll? :8O: :8O: :8O:

    HP255G7:Win10pro2.004,4*AMD Ryzen3200U@2.60GHz,6+2GB-RadeonVega/237GBSSD:intlDVDRW,3xUSB3 ext4TB-HDX,XProfanX3+Xasm/Xpse

  • Jens-Arne
    Schüler
    Reaktionen
    98
    Beiträge
    116
    • 22. März 2023 um 13:43
    • #7

    Naja, die Grenzen von Gleitkommaoperationen sollte man schon kennen, wenn man diese Funktion verwendet. Pi ist z.B. überhaupt nicht als Gleitkommazahl darstellbar (nicht exakt jedenfalls). Mir reicht aber für alle Lebenslagen die grobe Approximierung 3,14159. Da wird das Ei schon rund werden. ;)

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Windows 11

  1. Datenschutzerklärung
  2. Impressum
Community-Software: WoltLab Suite™