Trigo en asm 68k

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

  • 1
  • 2
  • bombseb

    • Messages : 64
    #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__

    • Messages : 2626
    #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

    • Messages : 64
    #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__

    • Messages : 2626
    #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

    • Messages : 64
    #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

    • Messages : 64
    #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__

    • Messages : 2626
    #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

    • Messages : 64
    #311624

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

     

    bombseb

    • Messages : 64
    #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__

    • Messages : 2626
    #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

    • Messages : 1821
    #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
    Epave de Peg2 - G4
    Mac mini - G4 1.42 GHz - 1 Go RAM - Radeon 9200 32 Mo - MorphOs 3.9
    WinUAE 4.0.1 (350 SysInfo Mips, boing boing boing ball !)
    Mist FPGA (68020_7.10 SysInfo MIPS AGA)
    A1200 en cours de résurrection 😉
    A500 512+512Ko RAM Kickstart 1.3

    __sam__

    • Messages : 2626
    #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

    • Messages : 64
    #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

    • Messages : 64
    #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

    • Messages : 64
    #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

Do NOT follow this link or you will be banned from the site!