-
Notifications
You must be signed in to change notification settings - Fork 0
/
wrap.h
64 lines (58 loc) · 1.5 KB
/
wrap.h
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
/****************************************************************
* Wraparound arithmetic library
*
* VeriFast's truncating add seems to be an
* uninterpreted function so I wrote my own.
*
* Copyright Alastair Reid 2020
* SPDX-Licence-Identifier: BSD-3-Clause
****************************************************************/
#include "stdint.h"
uint64_t wrap_add64(uint64_t x, uint64_t y)
//@ requires true;
/*@
ensures
(x + y) <= UINT64_MAX
?
result == (x + y)
:
result == (x + y) - (UINT64_MAX + 1)
;
@*/
//@ terminates;
{
uint128_t r1 = (uint128_t)x + (uint128_t)y;
uint64_t r = (uint64_t)(r1 <= UINT64_MAX ? r1 : (r1 - UINT64_MAX - 1u));
return r;
}
// Unsigned version of UINT64_MAX == 2^64-1
#define myUINT64_MAX 18446744073709551615u
// 2^63
#define myUINT64_HALF 9223372036854775808u
uint64_t wrap_sub64(uint64_t x, uint64_t y)
//@ requires true;
/*@
ensures
x >= y
?
result == (x - y)
:
result == (x - y) + UINT64_MAX + 1
;
@*/
//@ terminates;
{
if (x >= y) {
return x-y;
} else if (y <= INT64_MAX) { // y <= INT64_MAX && x < y
uint64_t y1 = (myUINT64_MAX - y) + 1u;
return (x + y1);
} else if (x > INT64_MAX) { // x > INT64_MAX && y > INT64_MAX && x < y
return (x - (y - myUINT64_HALF)) + myUINT64_HALF;
} else { // x <= INT64_MAX && y > INT64_MAX && x > y
return (x + myUINT64_HALF) - (y - myUINT64_HALF);
}
}
/****************************************************************
* End
****************************************************************/