fonctions de maths

Pour discuter de l'assembleur
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

fonctions de maths

Message par Dr. Dri »

pour commencer des fonctions de trigo

Code : Tout sélectionner

Procedure.f WrapValue(Angle.f) ;[0, 2Pi[
  ;charge 2Pi
  !FLDPI
  !FADD  st, st
  
  ;charge Angle
  !FLD dword [p.v_Angle]
  
  ;calcule WrapValue
  !FPREM
  !FSTP  st1
  
  ;l'angle est négatif ?
  !FLDZ
  !FCOMP
  !FNSTSW ax
  !TEST   ah, $41
  !JNE    l_wrapvalue_ok
  
  ;on lui ajoute 2Pi
  !FLDPI
  !FADD  st, st
  !FADDP
  
  wrapvalue_ok:
  !RET 4
EndProcedure

Procedure.f ATan2(y.f, x.f)    ;[-Pi, Pi[
  !FLD dword [p.v_y]
  !FLD dword [p.v_x]
  !FPATAN
  !RET 8
EndProcedure

Procedure.f ATanFull(y.f, x.f) ;[0, 2Pi[
  !FLD dword [p.v_y]
  !FLD dword [p.v_x]
  !FPATAN
  
  ;l'angle est négatif ?
  !FLDZ
  !FCOMP
  !FNSTSW ax
  !TEST   ah, $41
  !JNE    l_atanfull_ok
  
  ;on lui ajoute 2Pi
  !FLDPI
  !FADD  st, st
  !FADDP
  
  atanfull_ok:
  !RET 8
EndProcedure
ensuite la fonction exponentielle (j'ai galéré mais c'est NICKEL =)

Code : Tout sélectionner

Procedure.f Exp(x.f)
  Protected i.l
  !NewCW equ p.v_i+0
  !OldCW equ p.v_i+2
  
  ;charge x sans s'occuper du signe
  !FLD dword [p.v_x]
  !FABS
  
  ;n = x / Log(2)
  !FLDLN2
  !FDIVR st0, st1
  
  ;récupère le CW
  !FNSTCW word [NewCW]
  !FNSTCW word [OldCW]
  
  ;crée le CW pour arrondi par défaut
  !AND   word [NewCW], $F3FF
  !OR    word [NewCW], $0400
  !FLDCW word [NewCW]
  
  ;n = Floor(n)
  !FRNDINT
  
  ;restore le CW
  !FLDCW word [OldCW]
  
  ;u = x - n * Log(2)
  !FXCH
  !FLD st1 ;charge n
  !FLDLN2
  !FMULP
  !FSUBP
  
  ;m = Exp(u)
  !FLD1 ;m
  !FLD1 ;t
  !MOV  dword [p.v_i], 1
  
  exp_loop:
  ;tant que t > 0
  !FLDZ
  !FCOMP
  !FNSTSW ax
  !TEST   ah, $40
  !JNE    l_exp_end_loop
  
  ;t * u / i
  !FMUL  st0, st2
  !FIDIV dword [p.v_i]
  
  ;i + 1
  !INC   dword [p.v_i]
  
  ;m + t
  !FADD  st1, st0
  
  !JMP l_exp_loop
  exp_end_loop:
  
  !FSTP st0 ;retire t
  !FSTP st1 ;retire u
  !FSCALE   ;r = m * Pow(2, n)
  !FSTP st1 ;retire n
  
  ;si x négatif
  !TEST dword [p.v_x], $80000000
  !JE   l_exp_end
  
  ;r = 1.0 / r
  !FLD1
  !FDIVRP
  
  exp_end:
  
  !ADD esp, 4
  !RET 4
EndProcedure
des fonctions de probabilités (étrangement ca a été super simple =)

Code : Tout sélectionner

Procedure.d Factorial(n.l) ;n!
  ;si n négatif factorielle est indéfinie
  !TEST dword [p.v_n], $80000000
  !JNE  l_factorial_end
  
  !FLD1 ;le résultat dans st0
  
  factorial_loop:
  ;tant que n > 1
  !CMP dword [p.v_n], 1
  !JLE l_factorial_end
  
  ;calcule la factorielle
  !FIMUL dword [p.v_n]
  !DEC   dword [p.v_n]
  
  !JMP l_factorial_loop
  factorial_end:
  
  !RET 4
EndProcedure

Procedure.d Permutations(n.l, p.l) ;A(n, p)
  ;si n négatif pas d'arrangements
  !TEST dword [p.v_n], $80000000
  !JNE  l_permutations_end
  
  ;si p négatif pas d'arrangements
  !TEST dword [p.v_p], $80000000
  !JNE  l_permutations_end
  
  ;si n inférieur à p pas d'arrangements
  !MOV eax, dword [p.v_n]
  !CMP eax, dword [p.v_p]
  !JL  l_permutations_end
  
  !FLD1                   ;résultat dans st0
  !SUB eax, dword [p.v_p] ;eax = n - p
  
  permutations_loop:
  ;tant que n > eax
  !CMP dword [p.v_n], eax
  !JE  l_permutations_end
  
  ;calcule les arrangements
  !FIMUL dword [p.v_n]
  !DEC   dword [p.v_n]
  
  !JMP l_permutations_loop
  permutations_end:
  
  !RET 8
EndProcedure

Procedure.d Combinations(n.l, p.l) ;C(n, p)
  ;si n négatif pas de combinaisons
  !TEST dword [p.v_n], $80000000
  !JNE  l_combinations_end
  
  ;si p négatif pas de combinaisons
  !TEST dword [p.v_p], $80000000
  !JNE  l_combinations_end
  
  ;si n inférieur à p pas de combinaisons
  !MOV eax, dword [p.v_n]
  !CMP eax, dword [p.v_p]
  !JL  l_combinations_end
  
  !FLD1 ;résultat dans st0
  
  ;si p > n/2
  !SHR eax, 1
  !CMP eax, dword [p.v_p]
  !JG l_combinations_loop
  
  ;on prend n - p à la place de p
  !MOV eax, dword [p.v_n]
  !SUB eax, dword [p.v_p]
  !MOV dword [p.v_p], eax
  
  combinations_loop:
  ;tant que p > 0
  !CMP dword [p.v_p], 0
  !JLE l_combinations_end_loop
  
  ;calcule les combinaisons
  !FIMUL dword [p.v_n]
  !FIDIV dword [p.v_p]
  !DEC   dword [p.v_n]
  !DEC   dword [p.v_p]
  
  !JMP l_combinations_loop
  combinations_end_loop:
  
  !FRNDINT
  combinations_end:
  
  !RET 8
EndProcedure
Le modulo version nombres réels

Code : Tout sélectionner

Procedure.f Mod(x.f, y.f) ;x % y
  !FLD  dword [p.v_x]
  !FLD  dword [p.v_y]
  !FPREM
  !FSTP st1
  !RET  8
EndProcedure
Des fonctions d'arrondis (je sais y'a Round...)

Code : Tout sélectionner

Procedure.f Ceil(Value.f)
  Protected CW.l
  !NewCW equ p.v_CW+0
  !OldCW equ p.v_CW+2
  
  ;récupère le CW
  !FNSTCW word [OldCW]
  !FNSTCW word [NewCW]
  
  ;crée le CW pour arrondi par excès
  !AND   word [NewCW], $F3FF
  !OR    word [NewCW], $0800
  !FLDCW word [NewCW]
  
  ;calcule l'arrondi
  !FLD dword [p.v_Value]
  !FRNDINT
  
  ;restore le CW
  !FLDCW word [OldCW]
  
  !ADD esp, 4
  !RET 4
EndProcedure

Procedure.f Floor(Value.f)
  Protected CW.l
  !NewCW equ p.v_CW+0
  !OldCW equ p.v_CW+2
  
  ;récupère le CW
  !FNSTCW word [OldCW]
  !FNSTCW word [NewCW]
  
  ;crée le CW pour arrondi par défaut
  !AND   word [NewCW], $F3FF
  !OR    word [NewCW], $0400
  !FLDCW word [NewCW]
  
  ;calcule l'arrondi
  !FLD dword [p.v_Value]
  !FRNDINT
  
  ;restore le CW
  !FLDCW word [OldCW]
  
  !ADD esp, 4
  !RET 4
EndProcedure
et des fonctions à part sur la représentation des nombres réels

Code : Tout sélectionner

Procedure.f Significand(Value.f)
  !FLD  dword [p.v_Value]
  !FXTRACT
  !FSTP st1
  !RET  4
EndProcedure

Procedure.f Exponent(Value.f)
  !FLD  dword [p.v_Value]
  !FXTRACT
  !FSTP st0
  !RET  4
EndProcedure

Procedure.f Scale(Significand.f, Exponent.f)
  !FLD  dword [p.v_Exponent]
  !FLD  dword [p.v_Significand]
  !FSCALE
  !FSTP st1
  !RET  8
EndProcedure
Les fonctions sont relativement optimisées (chui pas un pro de l'asm...) dans la mesure où je fais appel le moins possible aux variables réelles. Elles ne sont utilisées qu'au chargement...

Dri :D
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

et voila c'est pompé Coloré et envoyé sur le Forum des codes FR

http://michel.dobro.free.fr/forum/

:D
KarLKoX
Messages : 1191
Inscription : jeu. 26/févr./2004 15:36
Localisation : France
Contact :

Message par KarLKoX »

nickel Image
"Qui baise trop bouffe un poil." P. Desproges
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

le PGCD ^_^ (merci PB pour le code ASM du modulo)

Code : Tout sélectionner

Procedure GCD(a.l, b.l)
  !MOV  eax, dword [p.v_a]
  !MOV  ebx, dword [p.v_b]
  
  gcd_loop:
  
  ;tant que b <> 0
  !CMP ebx, 0
  !JE  l_gcd_end
    
  ;calcule le PGCD
  !CDQ
  !IDIV ebx
  !MOV  eax, ebx
  !MOV  ebx, edx
  
  !JMP l_gcd_loop
  
  gcd_end:
  
  !RET 8
EndProcedure
Dri
Anonyme

Message par Anonyme »

Rajoute des fonctions pour les calculs matricielles ^^ et fait en une bonne lib :wink:
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Merci Dr Dri. C'est excellent ces fonctions. J'avais besoin d'Atanfull.
Répondre