| 1 | /* Discrete derivative function using backwards differencing, which is first-order
|
|---|
| 2 | * accurate. To verify with CIVL, type:
|
|---|
| 3 | * civl verify derivative.cvl
|
|---|
| 4 | */
|
|---|
| 5 |
|
|---|
| 6 | $input double dx;
|
|---|
| 7 | $assume(0<dx && dx<1);
|
|---|
| 8 | $input int num_elements;
|
|---|
| 9 | $assume(num_elements >= 1);
|
|---|
| 10 | $input double in[num_elements];
|
|---|
| 11 | double out[num_elements];
|
|---|
| 12 | // the following says rho is a function from R to R which has 2 continuous
|
|---|
| 13 | // derivatives in the closed interval [-1,1]:
|
|---|
| 14 | $abstract $differentiable(2, [-1,1]) $real rho($real x);
|
|---|
| 15 |
|
|---|
| 16 | void differentiate(int n, double y[], double h, double result[]) {
|
|---|
| 17 | $assume(n*h<=1);
|
|---|
| 18 | $assume($forall (int i : 0..n-1) y[i] == rho(i*h));
|
|---|
| 19 | /*@ loop invariant 1<=i && i<=n;
|
|---|
| 20 | @ loop invariant $forall (int j : 1..i-1) result[j] == (y[j]-y[j-1])/h;
|
|---|
| 21 | @ loop assigns i, result[1..n-1];
|
|---|
| 22 | @*/
|
|---|
| 23 | for (int i=1; i<n; i++) {
|
|---|
| 24 | result[i] = (y[i] - y[i-1])/h;
|
|---|
| 25 | }
|
|---|
| 26 | result[0] = (y[1] - y[0])/h; // forward differencing used at left end-point
|
|---|
| 27 | $assert($uniform (int i=0..n-1) result[i]-$D[rho,{x,1}](i*h) == $O(h));
|
|---|
| 28 | }
|
|---|
| 29 |
|
|---|
| 30 | int main() {
|
|---|
| 31 | differentiate(num_elements, in, dx, out);
|
|---|
| 32 | }
|
|---|