LAProof.C.cblas.spec_ddot: VST specification of GSL's [cblas_ddot].
Corresponds to C program C/cblas/src/ddot.c (ported from GSL cblas).
double r = 0.0;
for (i = 0; i < N; i++) { r += X[ix] * Y[iy]; ix += incX; iy += incY; }
return r;
i.e. a forward, left-to-right accumulation using *separate* multiply-then-add
(not fused multiply-add), starting from +0.0. That is exactly the
dotprodF model of LAProof.accuracy_proofs.dotprod_model
(dotprodF = dotprod BMULT BPLUS pos_zero), over which the forward-error
theorem dot_acc.dotprod_forward_error is proved -- *not* the FMA-based
floatlib.dotprod.
Require Import VST.floyd.proofauto.
From vcfloat Require Import FPStdCompCert FPStdLib.
From LAProof.C Require Import floatlib.
From LAProof.C.cblas Require Import ddot stride_model ddot_model.
Require Import LAProof.accuracy_proofs.dotprod_model.
#[export] Instance CompSpecs : compspecs.
Definition Vprog : varspecs.
The partial-accumulation model ddot_model and its start/step/end lemmas
live in LAProof.C.cblas.ddot_model (mirroring the sparse_model /
spec_sparse split). This file states only the VST funspec.
A stride is valid when GSL's initial OFFSET calculation, every selected
array index, and every signed-int index update are safe. The strict lower
bound in the nonpositive case makes the C expression -inc defined when
inc is negative.
Definition valid_ddot_stride (N inc n : Z) : Prop :=
Int.min_signed ≤ inc ≤ Int.max_signed ∧
(inc ≤ 0 → Int.min_signed < inc) ∧
Int.min_signed ≤ blas_offset N inc ≤ Int.max_signed ∧
(∀ k, 0 ≤ k < N →
0 ≤ blas_offset N inc + k×inc < n) ∧
(∀ k, 0 ≤ k < N →
Int.min_signed ≤ blas_offset N inc + k×inc + inc ≤ Int.max_signed).
Int.min_signed ≤ inc ≤ Int.max_signed ∧
(inc ≤ 0 → Int.min_signed < inc) ∧
Int.min_signed ≤ blas_offset N inc ≤ Int.max_signed ∧
(∀ k, 0 ≤ k < N →
0 ≤ blas_offset N inc + k×inc < n) ∧
(∀ k, 0 ≤ k < N →
Int.min_signed ≤ blas_offset N inc + k×inc + inc ≤ Int.max_signed).
Definition cblas_ddot_spec :=
DECLARE _cblas_ddot
WITH shX: share, shY: share, nX: Z, nY: Z, N: Z, incX: Z, incY: Z,
X: list (ftype Tdouble), Y: list (ftype Tdouble),
px: val, py: val
PRE [ tint, tptr tdouble, tint, tptr tdouble, tint ]
PROP (readable_share shX; readable_share shY;
Zlength X = nX; Zlength Y = nY;
0 ≤ nX ≤ Int.max_signed; 0 ≤ nY ≤ Int.max_signed;
0 ≤ N ≤ Int.max_signed;
valid_ddot_stride N incX nX;
valid_ddot_stride N incY nY)
PARAMS (Vint (Int.repr N); px; Vint (Int.repr incX);
py; Vint (Int.repr incY))
SEP (data_at shX (tarray tdouble nX) (map Vfloat X) px;
data_at shY (tarray tdouble nY) (map Vfloat Y) py)
POST [ tdouble ]
EX s: ftype Tdouble,
PROP (feq s
(dotprodF (blas_strided incX N X) (blas_strided incY N Y)))
RETURN (Vfloat s)
SEP (data_at shX (tarray tdouble nX) (map Vfloat X) px;
data_at shY (tarray tdouble nY) (map Vfloat Y) py).
Definition DdotASI : funspecs := [ cblas_ddot_spec ].
Definition ddot_imports : funspecs := []. Definition Gprog : funspecs := ddot_imports ++ DdotASI.
DECLARE _cblas_ddot
WITH shX: share, shY: share, nX: Z, nY: Z, N: Z, incX: Z, incY: Z,
X: list (ftype Tdouble), Y: list (ftype Tdouble),
px: val, py: val
PRE [ tint, tptr tdouble, tint, tptr tdouble, tint ]
PROP (readable_share shX; readable_share shY;
Zlength X = nX; Zlength Y = nY;
0 ≤ nX ≤ Int.max_signed; 0 ≤ nY ≤ Int.max_signed;
0 ≤ N ≤ Int.max_signed;
valid_ddot_stride N incX nX;
valid_ddot_stride N incY nY)
PARAMS (Vint (Int.repr N); px; Vint (Int.repr incX);
py; Vint (Int.repr incY))
SEP (data_at shX (tarray tdouble nX) (map Vfloat X) px;
data_at shY (tarray tdouble nY) (map Vfloat Y) py)
POST [ tdouble ]
EX s: ftype Tdouble,
PROP (feq s
(dotprodF (blas_strided incX N X) (blas_strided incY N Y)))
RETURN (Vfloat s)
SEP (data_at shX (tarray tdouble nX) (map Vfloat X) px;
data_at shY (tarray tdouble nY) (map Vfloat Y) py).
Definition DdotASI : funspecs := [ cblas_ddot_spec ].
Definition ddot_imports : funspecs := []. Definition Gprog : funspecs := ddot_imports ++ DdotASI.