Étude du comportement des nombres flottants dans les

Transcription

Étude du comportement des nombres flottants dans les
Étude du comportement des nombres
flottants dans les programmes C
Ali Ayad et Claude Marché
CEA List & INRIA Île-de-France
6 Octobre 2009
Ali Ayad et Claude Marché
Motivations
Vérification déductive des propriétés flottantes des
programmes C implémentant la norme IEEE-754 :
1
2
3
4
précision du calcul (erreur numérique)
division par zéro
overflows
NaNs et infinis signés
Ali Ayad et Claude Marché
Plan
1
2
3
4
Établir un langage de spécification de programmes
flottants
Établir de modèles du comportement des flottants
dans les programmes C (triplets de Hoare)
Validation des obligations de preuve qui traduisent la
spécification par une coopération des prouveurs
automatiques et interactifs
Expérimentation dans Frama-C/Jessie/Why
Ali Ayad et Claude Marché
Exemple : Approximation des fonctions
transcendantes (Algorithme de Remez)
/*@ requires \abs(x) <= 1.0 ;
@ ensures \abs(\result − \exp(x)) <= 0x1p−4 ;
@
// total error
@ */
double remezexp(double x) {
/*@ assert \abs(0.9890365552 + 1.130258690*x +
@
0.5540440796*x*x − \exp(x)) <= 0x0.FFFFp−4 ;
@
// method error
@*/
return 0.9890365552+1.130258690*x+0.5540440796*x*x ;
}
Opérations sur les réels
Variables flottantes dénotent leurs valeurs réelles
pas d’arrondi, ni overflows dans les annotations
Ali Ayad et Claude Marché
Deux modèles des opérations flottantes
Calcul flottant du standard IEEE-754.
Première composante des modèles : axiomatisation
du premier ordre de la fonction d’arrondi
Deuxième composante : modélisation des opérations
flottantes par des triplets de Hoare avec 2 options :
défensive : pas d’overflows, pas de NaNs : c’est le
cas de la plupart des programmes
full : overflows, NaNs, infinis et zéros signés
Ali Ayad et Claude Marché
Architecture des modèles flottants
Annotated
C program
C front-end
(Frama-C)
VC generator
(Jessie/Why)
verication
conditions
Interactive proof
Automatic proof
(Coq)
(SMT provers and Gappa)
Ali Ayad et Claude Marché
FP operations,
defensive model
axiomatic model
of FP arithmetics
FP operations,
full model
Realization
in Coq
IEEE-754 : formats et représentabilité
Un nombre flottant est représenté par :
(−1)s × 1.m × 2e
où s = 0, 1 : signe
m : matisse
e : exposant
Pour de raisons formelles, un nombre flottant est un
couple d’entiers (n, e) qui représente le réel n × 2e
Un format binaire est un triplet f = (p, emin , emax )
Un nombre réel x = n × 2e est dit représentable dans
le format f (f -représentable) si
|n| < 2p
et emin ≤ e ≤ emax .
Single (binary32) : p = 24, emin = −149 et emax = 104.
Ali Ayad et Claude Marché
IEEE-754 : opérations et valeurs spéciales
5 modes d’arrondi : vers le plus proche pair, vers
+∞, vers −∞, vers 0 et vers le plus près loin de zéro.
Opérations : pour deux nombres flottants x = n1 × 2e1
et y = n2 × 2e2 , f -représentables, la multiplication
x ∗ y est l’arrondi du réel n1 × n2 × 2e1 +e2 .
Valeurs spéciales : +0, −0, +∞, −∞ et NaNs.
(+∞) + (+∞) = (+∞), 1/(+∞) = +0,
1/(−0) = −∞, (+0)/(+0) = NaN,
(−0) × (+∞) = NaN
Ali Ayad et Claude Marché
Axiomatisation du premier ordre : Flottants
génériques
// type abstrait
type gen_float
// 2 fonctions logiques d’observation
logic float_value : gen_float −> real
logic exact_value : gen_float −> real
Ali Ayad et Claude Marché
Axiomatisation du premier ordre : Formats et
Arrondis
// 3 formats possibles
type float_format = Single | Double | Quad
// 5 modes d’arrondi (norme IEEE−754)
type mode = NearestEven | Up | Down
| ToZero | NearestAway
// fonction d’arrondi
round_float : float_format, mode, real −> real
// flottant maximal représentable
max_gen_float : float_format −> real
axiom max_gen_float(Single) = (224 − 1) × 2104
axiom max _gen_float(Double) = (253 − 1) × 2971
Ali Ayad et Claude Marché
Axiomatisation du premier ordre : Axiomatisation de
l’opérateur d’arrondi
// test de non−débordement
predicate
no_overflow(f :float_format,m :mode,x :real) =
abs_real(round_float(f,m,x)) <= max_gen_float(f)
// axiomatisation de round_float
forall f :float_format. m :mode. x :real.
|x| <= max_gen_float(f) −> no_overflow(f,m,x)
forall f :float_format. m :mode. x :real. y :real.
x <= y −> round_float(f,m,x) <= round_float(f,m,y)
etc ...
Ali Ayad et Claude Marché
Autres types abstraits : valeurs spéciales
// 2 autres types
type class = Finite | Infinite | NaN
type sign = Positive | Negative
// 2 autres fonctions d’observation
logic float_class : gen_float −> class
logic float_sign : gen_float −> sign
Ali Ayad et Claude Marché
Autres prédicats utiles : valeurs spéciales
predicate is_finite(x :gen_float) =
float_class(x) = Finite
is_infinite, is_NaN, etc ...
// infinis signés : +/− infini
predicate is_plus_infinity(x :gen_float) =
is_infinite(x) and float_sign(x) = Positive
// zéros signés : −0 et +0
predicate is_gen_zero(x :gen_float) =
is_finite(x) and float_value(x) = 0.0
predicate is_gen_zero_plus(x :gen_float) =
is_gen_zero(x) and float_sign(x) = Positive
etc ...
Ali Ayad et Claude Marché
Signe d’un résultat fini
axiom finite_sign : forall x :gen_float.
is_finite(x) and float_value(x) <> 0.0 −>
same_sign_real(x,float_value(x))
predicate sign_zero_result(m :mode,x :gen_float) =
float_value(x) = 0.0 −>
(m = Down −> float_sign(x) = Negative)
and
(m <> Down −> float_sign(x) = Positive)
Ali Ayad et Claude Marché
Classe d’un résultat dans le cas d’overflow
predicate
overflow_value(f :float_format,m :mode,
x :gen_float)=
m = Down −>
float_sign(x) = Negative −> is_infinite(x)
and
float_sign(x) = Positive −> is_finite(x) and
float_value(x) = max_gen_float(f)
and
m = Up −>
float_sign(x) = Negative −> is_finite(x) and
float_value(x) = − max_gen_float(f)
and
float_sign(x) = Positive −> is_infinite(x)
Ali Ayad et Claude Marché
Classe d’un résultat dans le cas d’overflow
and
m = ToZero −> is_finite(x) and
float_sign(x) = Negative −>
float_value(x) = − max_gen_float(f)
and
float_sign(x) = Positive −>
float_value(x) = max_gen_float(f)
and
m = NearestAway or m = NearestEven −>
is_infinite(x)
Ali Ayad et Claude Marché
Realisation Coq
gappalib-coq-0.12 (Guillaume Melquiond) :
http ://gappa.gforge.inria.fr/
Record gen_float : Set := mk_gen_float {
genf : float2 ;
float_class : Float_class ;
float_sign : sign ;
sign_invariant : float_class = Finite −>
(float2R genf <> 0)%R −>
same_sign_real_bool float_sign (float2R genf) ;
float_value := float2R genf ;
exact_value : R ;
}.
Ali Ayad et Claude Marché
Rappel : Triplet de Hoare
Pour une opération f , le triplet de Hoare est défini par :
f (x1 , . . . , xn ) : {P(x1 , .., xn )} τ {Q(x1 , .., xn , result)},
l’opération f prend comme arguments x1 , . . . , xn qui
vérifient la formule logique du premier ordre P
(pré-condition) et renvoie une valeur result de type τ tel
que la formule Q(x1 , .., xn , r ) est vérifiée (post-condition).
Ali Ayad et Claude Marché
Modèle défensive : div_gen_float
parameter div_gen_float :
f :float_format −> m :mode −>
x :gen_float −> y :gen_float −>
{ float_value(y) <> 0.0
and
no_overflow(f,m,float_value(x)/float_value(y)) }
gen_float
{float_value(result) =
round_float(f,m,float_value(x)/float_value(y))
and
exact_value(result) = exact_value(x)/exact_value(y)
}
Ali Ayad et Claude Marché
Modèle défensive : Exemple
Démo : Approximation de la fonction exponentielle par
l’algorithme de Remez.
Ali Ayad et Claude Marché
Modèle full : add_gen_float
parameter add_gen_float :
f :float_format −> m :mode −>
x :gen_float −> y :gen_float −>
{ }
gen_float
{
exact_value(result)=exact_value(x)+exact_value(y)
and
is_NaN(x) or is_NaN(y) −> is_NaN(result)
Ali Ayad et Claude Marché
Modèle full : add_gen_float
and
is_finite(x) and is_infinite(y) −>
is_infinite(result) and same_sign(result,y)
and
is_infinite(x) and is_finite(y) −>
is_infinite(result) and same_sign(result,x)
and
is_infinite(x) and is_infinite(y)
and same_sign(x,y) −>
is_infinite(result) and same_sign(result,x)
and
is_infinite(x) and is_infinite(y)
and diff_sign(x,y) −> is_NaN(result)
Ali Ayad et Claude Marché
Modèle full : add_gen_float
and
is_finite(x) and is_finite(y)
and no_overflow(f,m,float_value(x)+float_value(y)) −
is_finite(result) and
float_value(result) =
round_float(f,m,float_value(x)+float_value(y))
and sign_zero_result(m,result)
and
is_finite(x) and is_finite(y)
and not no_overflow(f,m,
float_value(x)+float_value(y)) −>
samesign_real(result,float_value(x)+float_value(y))
and overflow_value(f,m,result)
}
Ali Ayad et Claude Marché
Expérimentation : arithmétique d’intervalles
Addition et multiplication des intervalles
Exemple typique : mode d’arrondi (Down), +∞ et −∞
Ali Ayad et Claude Marché
Expérimentation : arithmétique d’intervalles
Addition et multiplication des intervalles
Exemple typique : mode d’arrondi (Down), +∞ et −∞
Preuves des OPs :
Premier essaie dans Coq : dizaines des cas à
considérer !
Les OPs sont automatiquement prouvées en ajoutant
des lemmes et des assertions dans le code
Ali Ayad et Claude Marché
Conclusions et perspectives
Conclusions :
Modélisation des opérations flottantes
indépendamment du langage de programmation
L’arithmétique flottante peut être automatisée mais sa
spécification est complexe !
Faiblesse des prouveurs SMT sur les réels : besoin
d’ajouter manuellement des axiomes
Utilisation de plusieurs types de prouveurs
Perspectives :
Meilleure coopération des prouveurs automatiques et
interactifs : par exemple, utilisation des prouveurs
automatiques comme des tactiques dans Coq
Intégration de Gappa dans les prouveurs SMT
Mélanger les deux modèles défensive et full dans un
même programme.
Ali Ayad et Claude Marché