Trigo en asm 68k

15 sujets de 1 à 15 (sur un total de 16)

  • 1
  • 2
  • bombseb

      #311615

      Bonjour,

      Une petite question aux connaisseurs…

      Comment faire pour calculer un sinus ou un cosinus en asm ?
      Je sais qu’il existe des outils pour générer des tables précalculées, mais j’aimerais précalculer ma table moi même au lancement de mon programme…

      (Je suis sur un Amiga 1200 émulé avec WinUAE)

       

       

      __sam__

        #311616

        Tu travailles en flottant ou en point fixe ? Tu veux la valeur plutôt exacte de sin/cos ou une approximation suffira ?

        Samuel.

        Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
        A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
        A500 Vampire V2+ ^8^ 🙂
        (mais aussi TO8, TO8D, TO9. Groupe PULS.)

        bombseb

          #311617

          Salut Sam,

          On va dire que j’aimerais générer une table de 1024 valeurs de sinus dont les valeurs vont de 0 à 65535 (une table de word donc)

          Flottant ou point fixe, peu importe….une approximation devrait suffire pour un sine scroller…

          Je viens de tomber là dessus justement  : https://amycoders.org/sources/sinegensource.html

           

          __sam__

            #311618

            Donc du point fixe 16.16.

            Une approximation de sin(x) entre -pi et pi est y=4*(x/pi)*(1-abs(x/pi)). Elle est précise à 6% près.

            Ta table fait 1024 entrées pour 0..2PI, donc pi (en x) vaut: 512, et 1 en y est 65536.

            Donc la formule à mettre dans la table est: 65536*4*(x/512)*(1-abs(x)/512) ce qui se simplifie en: tab[x] = x*(512-abs(x)).

            Vérification: sin(0) -> tab[0]=0, sin(pi/2) -> tab[256] = 256*256 = 65536 -> 1, sin(pi) -> tab[512] = 0. sin(3pi/2) = sin(3pi/2-2pi) = sin(-pi/2) –> -256*(512-abs(-256)) = -256*256 = -65536 -> -1. Ca colle!

            L’abs va nous ennuyer, mais on peut au départ calculer tab[x] avec x>0 (ce qui nous permet d’utiliser une multiplication non signée), puis pour les x<0, il suffit se savoir que sin(-x) = -sin(x) cad tab[x] = -tab[-x].

            Allons y pour l’asm (sans bouées):
            [code]
            calc sin_tab:
            lea sin_tab,a0
            ; calcul de tab[0..511] correspondant aux valeurs de x>0
            moveq #0,d0
            .1
            move.w #512,d1
            sub.w d0,d1
            beq.b .2 ; donc quand on sort, d0 vaut 512. Idéal pour décompter.
            mulu.w d0,d1
            addq.w #1,d0
            move.l d1,(a0)+
            bra.b .1
            ; calcul de tab[512..1023] correspondante aux valeurs de x<0
            ; on ne fait que recopier la table de la partie 1 en inversant
            ; le signe.
            .2
            move.l -512*4(a0),d1
            neg.l d1
            move.l d1,(a0)+
            subq.w #1,d0
            bne.b .2
            ; fini
            rts
            ; tableau de 4ko
            sin_tab:
            ds.l 1024
            [/code]
            Ca devrait être +/- correct, mais j’ai pas testé. En tout cas le principe est là.

            (Désolé pour la mise en page, mais le forum ne respecte pas les blancs dans le code 🙁 Une version correctement formatée est visible >><<.)

            Samuel.

            Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
            A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
            A500 Vampire V2+ ^8^ 🙂
            (mais aussi TO8, TO8D, TO9. Groupe PULS.)

            bombseb

              #311619

              Wow impressionnant 🙂

              Bon je vais devoir digérer tout ca alors…

              Merci beaucoup

               

              Pour info j’ai touvé ca aussi, c’est intéressant : https://amycoders.org/tutorials/sintables.html

               

               

              bombseb

                #311620

                Excuse moi je ne comprend pas cette phrase :

                « Ta table fait 1024 entrées pour 0..2PI, donc pi (en x) vaut: 512, et 1 en y est 65536.  »

                Pourquoi tu remplace pi par 512 ? -> C’est bon j’ai compris 🙂

                 

                __sam__

                  #311622

                  je remplace pi par 512 parce que ta table a 1024 entrées et que 1024 représente la fin de la sinusoide, cad 2pi.

                  Donc si 2pi=1024, il vient pi=512. L’entrée 512 de la table correspond à sin(pi), celle en 256 correspond à sin(pi/2). Ben oui pi/2 c’est 256 quand pi=512. Tu vois le truc? On mappe un x réel entre 0 et 2pi vers un x’ entier entre 0 et 1024.

                  Samuel.

                  Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
                  A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
                  A500 Vampire V2+ ^8^ 🙂
                  (mais aussi TO8, TO8D, TO9. Groupe PULS.)

                  bombseb

                    #311624

                    Oui c’est cool merci, j’aurai pas eu l’idée de voir le truc comme ca 🙂

                     

                    bombseb

                      #311625

                      Je vais encore t’ennuyer un petit peu 🙂

                      Comment tu arrive de ca : 65536*4*(x/512)*(1-abs(x)/512)

                      à ca  x*(512-abs(x)) ?

                      Désolé ca fait un bail que j’ai pas fait de maths….

                      __sam__

                        #311630

                        Bah, c’est pas des maths, juste du calcul… un chouille laborieux là parce que j’ai essayé de détailler toutes les étapes élémentaires
                        65536*4*(x/512) * (1-abs(x)/512)
                        = (65536*4)*(x/512) * (1-abs(x)/512)
                        = 262144*(x/512) * (1-abs(x)/512)
                        = (262144*x/512) * (1-abs(x)/512)
                        = ((262144/512)*x) * (1-abs(x)/512)
                        = (512*x) * (1-abs(x)/512)
                        = (512*x) * (1-abs(x)/512)*1
                        = (512*x) * (1-abs(x)/512)*(512/512)
                        = (512*x) * (((1-abs(x)/512)*512)/512)
                        = (512*x) * ((512 – abs(x))/512
                        = 512*x * (512 – abs(x))/512
                        = x * (512 – abs(x)) * 512/512
                        = x * (512 – abs(x)) * 1
                        = x * (512 – abs(x))
                        CQFD 😉

                        Samuel.

                        Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
                        A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
                        A500 Vampire V2+ ^8^ 🙂
                        (mais aussi TO8, TO8D, TO9. Groupe PULS.)

                        logo

                          #311637

                          Efficace et bien expliqué, même si je sens déjà poindre une légère migraine ;-), ça sent les automatismes et l’amour du travail bien fait.

                           

                          PowerMac - G5 2.0 GHz - 1.7 Go RAM - Radeon 9600P 128 Mo - MorphOs 3.13 et Peg2 - G4 RIP
                          Mac mini - G4 1.42 GHz - 1 Go RAM - Radeon 9200 32 Mo - MorphOs 3.9
                          WinUAE sur HP Core2 Quad 8200
                          Epave de Mist FPGA remplacé par un Sidi
                          A1200 malade 😉 et A500 512+512Ko RAM Kickstart 1.3

                          __sam__

                            #311642

                            Pour ceux qui veulent s’amuser avec l’approximation de sin(x) entre -pi et pi par 4x(1-|x|/pi)/pi, j’ai posé la question à wolfram alpha. Il dit que le max d’erreur est obtenu pour x = +/-0.471972 ou x = +/-2.66962 et vaut 0.0560096. [REVISION BAC-S by sam 😛 ]

                            On est donc juste un peu « au dessus » du sinus au max de 5.6% (par rapport à 1). Mais c’est tout à fait acceptable en pratique car le calcul est rapide. Voyez comment les courbes sont proches.

                            (clickez l’image pour voir sur Wolfram Alpha)

                            Samuel.

                            Amiga A500 + GVP530 (8Mo/fpu/mmu/scsi) - en panne 🙁
                            A500 (+ 1Mo PPS), A1200 (Blizzard-IV/fpu/64Mo)
                            A500 Vampire V2+ ^8^ 🙂
                            (mais aussi TO8, TO8D, TO9. Groupe PULS.)

                            bombseb

                              #311645

                              Yes, très bien expliqué merci beaucoup Sam…Il me manquait surtout cette formule : 4x(1-|x|/pi)/pi que je ne connaissais pas
                              Je vais pouvoir m’amuser maintenant 🙂

                               

                               

                              bombseb

                                #345762

                                Salut,

                                Je remonte ce thread, déjà pour dire que ton algo fonctionne très bien (compile du premier coup avec AsmOne), c’est très rapide (quasi instantané), mais aussi pour poser une question.
                                Je suis tombé sur une routine de Photon de Scoopex pour faire la même chose.

                                ;Bhaskara sine approx by Photon/SCX
                                ;note that this is better than std parabolic so no 2% deviation \o/
                                ;sin x=4x(180-x)/(40500-x(180-x))
                                ;changed from 180 to 126 steps for 180 degs
                                
                                steps2	=126	;orig 180
                                ampl	=-1	;orig 40500 => $1bd0 ampl, -1 => $1080 ampl, 11909=$7ff7 ampl
                                
                                B:
                                	lea Sin(PC),a1
                                	moveq #steps2-1,d0
                                .l:	bsr.s BSine
                                	move.w d1,(a1)+
                                	neg.w d1
                                	move.w d1,steps2*2-2(a1)
                                	DBF d0,.l
                                	RTS
                                
                                BSine:	;d0.w=x (0..steps2=0..179 degs)
                                	moveq #steps2,d1
                                	sub.w d0,d1
                                	mulu d0,d1		;x(180-x)
                                	moveq #-1,d2		;fine-stretch amplitude with this.
                                	sub.w d1,d2
                                	swap d1			;*4*16384ampl/2, lsl.l #8,d1 => 4*64ampl
                                ;	clr.w d1		;@only nec at high amplitudes AND high coord/scr rez.
                                	divu d2,d1		;check if rest works as autorandomvalues. ;)
                                	RTS
                                Sin:
                                	blk.w steps2*2,0
                                E:

                                Visiblement la formule de base est différente, méthode Bhaskara : sin x=4x(180-x)/(40500-x(180-x))

                                Je n’arrive pas à comprendre pourquoi ces deux lignes :

                                – Pourquoi il met -1 dans d2 ? il est pas sensé mettre 40500 ??
                                moveq #-1,d2 ;fine-stretch amplitude with this.

                                – Pourquoi ce swap ? De plus je ne comprend le commentaire…
                                swap d1 ;*4*16384ampl/2, lsl.l #8,d1 => 4*64ampl

                                Le registre d1 est utilisé pour faire une division, pourquoi est t-il d’abord swappé ? J’aurai compris qu’il fasse un lsr à la place du swap, mais là avec le swap, il va y avoir des trucs dans la partie haute de d1 ce qui risque de faire du caca avec le divu….pourtant ca fonctionne

                                bombseb

                                  #345764

                                  Bon,

                                  Pour le swap, je vient de comprendre…
                                  Il fait un swap pour ne pas avoir à faire deux lsl de suite :
                                  lsl.l #8,d1
                                  lsl.l #8,d1

                                  après le swap, la partie basse de d1 n’est pas significative pour le divu (d’où le clr.w en commentaire)

                                  Par contre je ne pige toujours pas pourquoi il met -1 dans d2 à la place du 40500

                                15 sujets de 1 à 15 (sur un total de 16)

                                • 1
                                • 2
                                • Vous devez être connecté pour répondre à ce sujet.

                                Forums AmigaOS, MorphOS et AROS Développement Trigo en asm 68k

                                Amiga Impact