minmax: New module, safe min and max macros
[ccan] / ccan / minmax / minmax.h
1 /* CC0 (Public domain) - see LICENSE file for details */
2 #ifndef CCAN_MINMAX_H
3 #define CCAN_MINMAX_H
4
5 #include "config.h"
6
7 #include <ccan/build_assert/build_assert.h>
8
9 #if !HAVE_STATEMENT_EXPR || !HAVE_TYPEOF
10 /*
11  * Without these, there's no way to avoid unsafe double evaluation of
12  * the arguments
13  */
14 #error Sorry, minmax module requires statement expressions and typeof
15 #endif
16
17 #if HAVE_BUILTIN_TYPES_COMPATIBLE_P
18 #define MINMAX_ASSERT_COMPATIBLE(a, b) \
19         BUILD_ASSERT(__builtin_types_compatible_p(a, b))
20 #else
21 #define MINMAX_ASSERT_COMPATIBLE(a, b) \
22         do { } while (0)
23 #endif
24
25 #define min(a, b) \
26         ({ \
27                 typeof(a) _a = (a); \
28                 typeof(b) _b = (b); \
29                 MINMAX_ASSERT_COMPATIBLE(typeof(_a), typeof(_b)); \
30                 _a < _b ? _a : _b; \
31         })
32
33 #define max(a, b) \
34         ({ \
35                 typeof(a) _a = (a); \
36                 typeof(b) _b = (b); \
37                 MINMAX_ASSERT_COMPATIBLE(typeof(_a), typeof(_b)); \
38                 _a > _b ? _a : _b; \
39         })
40
41 #define clamp(v, f, c)  (max(min((v), (c)), (f)))
42
43
44 #define min_t(t, a, b) \
45         ({ \
46                 t _ta = (a); \
47                 t _tb = (b); \
48                 min(_ta, _tb); \
49         })
50 #define max_t(t, a, b) \
51         ({ \
52                 t _ta = (a); \
53                 t _tb = (b); \
54                 max(_ta, _tb); \
55         })
56
57 #define clamp_t(t, v, f, c) \
58         ({ \
59                 t _tv = (v); \
60                 t _tf = (f); \
61                 t _tc = (c); \
62                 clamp(_tv, _tf, _tc); \
63         })
64
65 #endif /* CCAN_MINMAX_H */