123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // SPDX-License-Identifier: GPL-2.0 or GPL-3.0
- // Copyright © 2019 Ariadne Devos
- // Integer model: wrap-around
- // Proof status: auto
- #include <stdint.h>
- #include <sHT/index.h>
- #include <sHT/lex/digit.h>
- #include <sHT/lex/nat.h>
- #include <sHT/logic/arithmetic.h>
- #include <sHT/test.h>
- #ifdef __FRAMAC__
- # include <sHT/math/vector-memory.h>
- # include <sHT/math/expnat/lt.h>
- #endif
- /*@ requires S ==> \valid_read(&c[0 .. e - 1]);
- requires S ==> \valid_read(&c[0]);
- requires \valid_read(&c[b .. e - 1]);
- requires NS ==> b <= i < e;
- requires i < e || i == 0;
- requires NS ==> X_num_p(vector_load_u8(c + b, e - b));
- terminates \true;
- assigns \result;
- ensures NS ==> \result == X_val(c[i]); */
- static inline uint32_t
- sHT_X_given_X_num_p(uint8_t *c, size_t b, size_t e, size_t i)
- {
- /*@ assert NS ==> X_p(\nth(vector_load_u8(c + b, e - b), i - b)); */
- /*@ assert NS ==> X_p((c + b)[i - b]); */
- return sHT_X_val(c[i]);
- }
- /** Reduce scope of X_num_p
- (Doing i + 1 here avoids overflow later.) */
- /*@ requires NS ==> i < n;
- requires NS ==> X_num_p(vector_load_u8(c, n));
- terminates \true;
- assigns \nothing;
- ensures NS ==> X_num_p(vector_load_u8(c, i + 1)); */
- static inline void
- sHT_X_num_p_less(uint8_t *c, size_t n, size_t i)
- {
- /* Limit range to 0 .. i: elements */
- /*@ assert \length(vector_load_u8(c, n)) == n; */
- /*@ assert \length(vector_load_u8(c, i + 1)) == i + 1; */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < n
- ==> \nth(vector_load_u8(c, n), j) == c[j]; */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < i + 1
- ==> \nth(vector_load_u8(c, n), j) == c[j]; */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < i + 1
- ==> \nth(vector_load_u8(c, i + 1), j) == c[j]; */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < i + 1
- ==> \nth(vector_load_u8(c, n), j) == \nth(vector_load_u8(c, i + 1), j); */
- /* Limit range to 0 .. i: predicate*/
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < \length(vector_load_u8(c, n))
- ==> X_p(\nth(vector_load_u8(c, n), j)); */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < n
- ==> X_p(\nth(vector_load_u8(c, n), j)); */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < i + 1
- ==> X_p(\nth(vector_load_u8(c, n), j)); */
- /*@ assert NS ==> ∀ ℤ j; 0 <= j < i + 1
- ==> X_p(\nth(vector_load_u8(c, i + 1), j)); */
- }
- /*@ requires NS ==> X_num_p(vector_load_u8(c, n));
- requires NS ==> k <= n;
- terminates \true;
- assigns \nothing;
- ensures NS ==> X_num_val(vector_load_u8(c, k))
- ≤ X_num_val(vector_load_u8(c, n)); */
- static inline void
- sHT_X_num_val_less_lt(uint8_t *c, size_t n, size_t k)
- {
- /*@ assert NS ==> ∀ integer j; 0 <= j < \length(vector_load_u8(c, n))
- ==> X_p(\nth(vector_load_u8(c, n), j)); */
- /*@ assert NS ==> ∀ integer j; 0 <= j < n
- ==> X_p(\nth(vector_load_u8(c, n), j)); */
- /*@ assert NS ==> ∀ integer j; 0 <= j < n
- ==> \nth(vector_load_u8(c, n), j) == c[j]; */
- /*@ assert NS ==> ∀ integer j; 0 <= j < n
- ==> X_p(c[j]); */
- /*@ assert NS ==> ∀ integer j; 0 <= j < n
- ==> 0 <= X_val(c[j]) < X_base; */
- /*@ loop invariant NS ==> k <= i <= n;
- loop invariant NS ==> X_num_val(vector_load_u8(c, k))
- ≤ X_num_val(vector_load_u8(c, i));
- loop assigns i;
- loop variant n - i; */
- for (size_t i = k; i < n; i++) {
- /* Step X_num_val */
- sHT_X_num_p_less(c, n, i);
- /*@ assert vector_load_u8(c, i + 1) == (vector_load_u8(c, i) ^ [| c[i] |]); */
- /*@ assert NS ==> X_num_p(vector_load_u8(c, i) ^ [| c[i] |]); */
- /*@ assert NS ==> X_num_val(vector_load_u8(c, i) ^ [| c[i] |])
- == X_base * X_num_val(vector_load_u8(c, i))
- + X_val(c[i]); */
- /*@ assert NS ==> X_num_val(vector_load_u8(c, i + 1))
- == X_base * X_num_val(vector_load_u8(c, i))
- + X_val(c[i]); */
- /* Bounds on the accumulation */
- /*@ assert NS ==> 0 <= X_num_val(vector_load_u8(c, i)); */
- /* Bounds on the extra digit */
- /*@ assert NS ==> X_p(\nth(vector_load_u8(c, n), i)); */
- /*@ assert NS ==> X_p(c[i]); */
- /*@ assert NS ==> 0 <= X_val(c[i]) < X_base; */
- }
- }
- uint32_t
- sHT_X_to_u32(uint8_t *c, size_t b, size_t e)
- {
- size_t i = b;
- uint32_t x = 0;
- if (sHT_ge(b, e))
- return x;
- /*@ loop invariant NS ==> b <= i < e;
- loop invariant NS ==> x == X_num_val(vector_load_u8(c + b, i - b));
- loop assigns i, x;
- loop variant e - i; */
- do { loop: i = sHT_index_nospec(i, e);
- sHT_X_num_p_less(c + b, e - b, i - b);
- uint32_t y = sHT_X_given_X_num_p(c, b, e, i);
- /* Value */
- /*@ assert NS ==> vector_load_u8(c + b, i - b + 1)
- == (vector_load_u8(c + b, i - b) ^ [| c[i] |]); */
- /*@ assert NS ==> X_num_val(vector_load_u8(c + b, i - b + 1))
- == X_base * X_num_val(vector_load_u8(c + b, i - b))
- + X_val(c[i]); */
- /*@ assert NS ==> X_num_val(vector_load_u8(c + b, i - b + 1))
- == X_base * X_num_val(vector_load_u8(c + b, i - b))
- + y; */
- /* Bounds */
- sHT_X_num_val_less_lt(c + b, e - b, (i - b) + 1);
- /*@ assert NS ==> X_num_val(vector_load_u8(c + b, (i - b) + 1)) <= UINT32_MAX; */
- x = sHT_muladd_nooverflowNS_u32(sHT_X_base, x, y);
- i++;
- } while (sHT_lt(i, e));
- return x;
- }
|