Logicielsmoto.com
http://www.logicielsmoto.com/phpBB/

atan2
http://www.logicielsmoto.com/phpBB/viewtopic.php?f=3&t=673
Page 2 sur 2

Auteur:  Bentoc [ 21 Mai 2022, 23:53 ]
Sujet du message:  Re: atan2

Ah ouais bien ! bon il y a un coup d'entrée, mais après c'est mega rapide effectivement.
Je n'ai pas pensé au "arsd" "splitté" avec les octets non contigus ... la puissance du 8bit ;-)

Si je délégue la partie d’init au code appellant j’évite d’avoir a passer par x et y, ça peut le faire !!

Auteur:  Bentoc [ 22 Mai 2022, 14:51 ]
Sujet du message:  Re: atan2

En relisant le code d'origine on voit que les cas x=0 et y=0 ne sont pas gérés juste les - et +.
Dans mon cas il m'importe d'avoir des valeurs exactes quand x et/ou y sont à 0, donc obligé d'ajouter du code spécifique ...

Au final sur 265 tests (cercle de 256 valeurs, et 9 cas particuliers) on obtient 160 cycles en moyenne (sans le jsr).

Si qq passe par ici un jour et a mieux, n'hésitez pas.

Auteur:  Samuel Devulder [ 22 Mai 2022, 15:15 ]
Sujet du message:  Re: atan2

As tu vu les dernières mises à jour de viewtopic.php?p=7687#p7687 ? plus besoin d'éparpiller x/y.

Auteur:  Bentoc [ 22 Mai 2022, 15:28 ]
Sujet du message:  Re: atan2

Oui normalement c’est intégré dans mon premier post (si je n’ai rien loupé)

Auteur:  Samuel Devulder [ 22 Mai 2022, 15:37 ]
Sujet du message:  Re: atan2

Sinon dans le code d'origine
Code:
        ; set x
        orcc  #1        ; set carry (x < 0)
        tst   x_h       ; test sign of x using the 16 bit input value
        bmi   >         ; branch if (x > 0)
        andcc #$FE      ; clear carry
        bra   @a
!       nega
@a      rol   octant    ; set octant b2 if x is negative

Si je comprends bien: si x(16bits)<0 on ajoute 1 dans octant et on fait un neg de la partie basse. Sinon (x>=0) on injecte un 0 dans octant et on ne touche pas la partie basse. C'est ca ?

Or le NEGA m'interroge. Il touche à la carry. Or si lors du "BMI >" on a bel et bien la carry à 1 à cause du ORCC juste avant, le NEGA peut la nettoyer, et le ROL injectera 0 et pas 1 comme attendu. C'est peut-être l'une des cause des erreurs de calcul. Il vaudrait mieux déplacer le ORCC juste après le NEGA en fait. Comme ca la carry serra bien positionnée avant le ROL. En plus ca fait gagner quelques cycles (on ne set pas la carry à 1 pour la passer à 0 juste après). On remarque aussi que la CARRY est exactement le bit de poids fort de x_h. On peut l'extraire en ajoutant 128 à x_h, ou encore avec une rotation.

Fort de cette précédente remarque, je pense que cette partie peut être optimisée sans aucun saut.

On remarque que x_h n'a en réalité que 2 valeurs possible après l'étape du "@shift": $00 ou $FF. On peut alors faire ceci:
Code:
    LDA x_h  ; A=$FF ou $00
    ASRA  ; CC=1 si x_h<0, 0 sinon.  Dans tous les cas A est inchangé.
    ROL  octant
    EORA x_l
Le EORA fait presque NEG. En fait il manque +1, mais on on s'en fiche, le code 6502 fait la même approximation. Le résultat sera juste un poil moins précis.

Auteur:  Bentoc [ 22 Mai 2022, 15:49 ]
Sujet du message:  Re: atan2

Très bonne idée !

Auteur:  Bentoc [ 22 Mai 2022, 16:36 ]
Sujet du message:  Re: atan2

Avec ce nouveau code on tombe à 148 cycles en moyenne sur le jeu de test.
On perd un poil en précision sur quelques valeurs mais rien de grave.

Le cas de test suivant fonctionne toujours bien (a droite l'angle calculé) :
Code:
        ;     Y,X - Circle R=1
        fdb   $0000,$0001 ; 40
        fdb   $0001,$0001 ; 60
        fdb   $0001,$0000 ; 80
        fdb   $0001,$FFFF ; A0
        fdb   $0000,$FFFF ; C0
        fdb   $FFFF,$FFFF ; E0
        fdb   $FFFF,$0000 ; 00
        fdb   $FFFF,$0001 ; 20

        ;     Y,X - special case 0
        fdb   $0000,$0000 ; 40


code et résultats maj en page 1

Merci encore une fois Sam !

Auteur:  Samuel Devulder [ 22 Mai 2022, 17:07 ]
Sujet du message:  Re: atan2

Quelques petites optims
Code:
        ; compute ratio
        orcc  #1
        ldx   #log2_tab
        lda   a,x
        sbca  b,x       ; (dynamic instruction) compute y/x ratio
Comme C=1, SBCA B,X est identique à SUBA A,X + SUBA #1. On peut donc retirer le ORCC #1 et mettre un SUBA#1 (et pas un DECA: il ne positionne pas la retenue) ici
Code:
        bcs   >         ; branch if (x < y)
        nega
        andcc #$FE      ; clear carry (x > y)
Ici le ANDCC peut être remplacé par CLRB (2 cycles).

Cependant si la carry dont représenter la comparaison x>y, on peut soustraire y à x, et elle serra automatiquement positionnée comme il faut sans jouer des ORCC/ANDCC. Je propose
Code:
        ldx   #log2_tab
        lda   a,x
        suba  b,x
        bcs   >
        eora #$FF  ; pas exactement NEGA, mais ca ne change pas la carry
!       
        ; retrieve the angle
        ldx   #atan_tab
        lda   a,x

        ; adjust octant
        ldb   octant   
        rolb            ; set octant b0 if (x < y)
        andb  #%111     ; modulo to keep useful values
        ldx   #octant_adjust
        eora  b,x       ; apply octant to angle
        ldx   #octant_adjust2
        adda  b,x

Page 2 sur 2 Heures au format UTC + 1 heure
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/