File: sum.mlw

package info (click to toggle)
why3 1.8.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 45,028 kB
  • sloc: xml: 185,443; ml: 111,224; ansic: 3,998; sh: 2,578; makefile: 2,568; java: 865; python: 720; javascript: 290; lisp: 205; pascal: 173
file content (121 lines) | stat: -rw-r--r-- 3,925 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module SumSingle
  use int.Int
  use real.RealInfix
  use real.Abs
  use real.Sum
  use ufloat.USingle
  use ufloat.USingleLemmas
  use ref.Ref
  use real.FromInt

  function abs_real_fun (f:int -> usingle) : int -> real =
                                                  fun i -> abs (to_real (f i))

  let rec lemma sum_of_fun_le_sum_of_abs_fun (f : int -> usingle) (i:int)
    requires { 0 <= i }
    variant { i }
    ensures { abs (sum (real_fun f) 0 i) <=. sum (abs_real_fun f) 0 i }
  = if i > 1 then sum_of_fun_le_sum_of_abs_fun f (i - 1)

  let ghost usum (f : int -> usingle) (n:int) : usingle
    requires { 0 <= n }
    ensures {
      abs (to_real result -. sum (real_fun f) 0 n) <=. sum (abs_real_fun f) 0 n *. (eps *. from_int n)
    }
  =
  let s = ref u0 in
  for i = 0 to n - 1 do
    (* We use the propagation lemma on IEEE addition to prove the invariant *)
    invariant {
      abs (to_real !s -. sum (real_fun f) 0 i) <=. sum (abs_real_fun f) 0 i *. (eps *. from_int i)
    }
    s := !s ++. f i;
  done;
  !s

  (* We use the propagation lemma on IEEE addition to prove the postcondition *)
  let rec usum_rec (f : int -> usingle) (n:int) : usingle
    requires { 0 <= n }
    variant { n }
    ensures {
      abs (to_real result -. sum (real_fun f) 0 n) <=. sum (abs_real_fun f) 0 n *. (eps *. from_int n)
    }
  = if n = 0 then uzero else usum_rec f (n-1) ++. f (n-1)

  function exact_f : int -> real
  function f' : int -> real
  axiom f'_def : f' = fun i -> abs (exact_f i)
  constant f_rel_err:real
  constant f_cst_err:real

  (* We use the propagation on sum to prove the postcondition *)
  let function example1 (f : int -> usingle) (n : int) : usingle
    requires { 0 <= n }
    requires { forall i. abs (to_real (f i) -. exact_f i) <=. f' i *. f_rel_err }
    ensures {
      abs (to_real result -. sum exact_f 0 n)
      <=. sum f' 0 n *. (f_rel_err +. (eps *. from_int n) *. (1. +. f_rel_err))
    }
  = usum_rec f n
end

module SumDouble
  use int.Int
  use real.RealInfix
  use real.Abs
  use real.Sum
  use ufloat.UDouble
  use ufloat.UDoubleLemmas
  use ref.Ref
  use real.FromInt

  function abs_real_fun (f:int -> udouble) : int -> real =
                                                  fun i -> abs (to_real (f i))

  let rec lemma sum_of_fun_le_sum_of_abs_fun (f : int -> udouble) (i:int)
    requires { 0 <= i }
    variant { i }
    ensures { abs (sum (real_fun f) 0 i) <=. sum (abs_real_fun f) 0 i }
  = if i > 1 then sum_of_fun_le_sum_of_abs_fun f (i - 1)

  let ghost usum (f : int -> udouble) (n:int) : udouble
    requires { 0 <= n }
    ensures {
      abs (to_real result -. sum (real_fun f) 0 n) <=. sum (abs_real_fun f) 0 n *. (eps *. from_int n)
    }
  =
  let s = ref u0 in
  for i = 0 to n - 1 do
    (* We use the propagation lemma on IEEE addition to prove the invariant *)
    invariant {
      abs (to_real !s -. sum (real_fun f) 0 i) <=. sum (abs_real_fun f) 0 i *. (eps *. from_int i)
    }
    s := !s ++. f i;
  done;
  !s

  (* We use the propagation lemma on IEEE addition to prove the postcondition *)
  let rec usum_rec (f : int -> udouble) (n:int) : udouble
    requires { 0 <= n }
    variant { n }
    ensures {
      abs (to_real result -. sum (real_fun f) 0 n) <=. sum (abs_real_fun f) 0 n *. (eps *. from_int n)
    }
  = if n = 0 then uzero else usum_rec f (n-1) ++. f (n-1)

  function exact_f : int -> real
  function f' : int -> real
  axiom f'_def : f' = fun i -> abs (exact_f i)
  constant f_rel_err:real
  constant f_cst_err:real

  (* We use the propagation on sum to prove the postcondition *)
  let function example1 (f : int -> udouble) (n : int) : udouble
    requires { 0 <= n }
    requires { forall i. abs (to_real (f i) -. exact_f i) <=. f' i *. f_rel_err }
    ensures {
      abs (to_real result -. sum exact_f 0 n)
      <=. sum f' 0 n *. (f_rel_err +. (eps *. from_int n) *. (1. +. f_rel_err))
    }
  = usum_rec f n
end