Line data Source code
1 : #ifndef AWS_COMMON_MATH_H
2 : #define AWS_COMMON_MATH_H
3 :
4 : /**
5 : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 : * SPDX-License-Identifier: Apache-2.0.
7 : */
8 :
9 : #include <aws/common/common.h>
10 : #include <aws/common/config.h>
11 :
12 : #include <limits.h>
13 : #include <stdlib.h>
14 :
15 : /* The number of bits in a size_t variable */
16 : #if SIZE_MAX == UINT32_MAX
17 : # define SIZE_BITS 32
18 : #elif SIZE_MAX == UINT64_MAX
19 1439225 : # define SIZE_BITS 64
20 : #else
21 : # error "Target not supported"
22 : #endif
23 :
24 : /* The largest power of two that can be stored in a size_t */
25 1439225 : #define SIZE_MAX_POWER_OF_TWO (((size_t)1) << (SIZE_BITS - 1))
26 :
27 : AWS_EXTERN_C_BEGIN
28 :
29 : #if defined(AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS) && (defined(__clang__) || !defined(__cplusplus)) || \
30 : (defined(__x86_64__) || defined(__aarch64__)) && defined(AWS_HAVE_GCC_INLINE_ASM) || \
31 : defined(AWS_HAVE_MSVC_MULX) || defined(CBMC) || !defined(AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS)
32 : /* In all these cases, we can use fast static inline versions of this code */
33 : # define AWS_COMMON_MATH_API AWS_STATIC_IMPL
34 : #else
35 : /*
36 : * We got here because we are building in C++ mode but we only support overflow extensions
37 : * in C mode. Because the fallback is _slow_ (involving a division), we'd prefer to make a
38 : * non-inline call to the fast C intrinsics.
39 : */
40 : # define AWS_COMMON_MATH_API AWS_COMMON_API
41 : #endif
42 :
43 : /**
44 : * Multiplies a * b. If the result overflows, returns 2^64 - 1.
45 : */
46 : AWS_COMMON_MATH_API uint64_t aws_mul_u64_saturating(uint64_t a, uint64_t b);
47 :
48 : /**
49 : * If a * b overflows, returns AWS_OP_ERR; otherwise multiplies
50 : * a * b, returns the result in *r, and returns AWS_OP_SUCCESS.
51 : */
52 : AWS_COMMON_MATH_API int aws_mul_u64_checked(uint64_t a, uint64_t b, uint64_t *r);
53 :
54 : /**
55 : * Multiplies a * b. If the result overflows, returns 2^32 - 1.
56 : */
57 : AWS_COMMON_MATH_API uint32_t aws_mul_u32_saturating(uint32_t a, uint32_t b);
58 :
59 : /**
60 : * If a * b overflows, returns AWS_OP_ERR; otherwise multiplies
61 : * a * b, returns the result in *r, and returns AWS_OP_SUCCESS.
62 : */
63 : AWS_COMMON_MATH_API int aws_mul_u32_checked(uint32_t a, uint32_t b, uint32_t *r);
64 :
65 : /**
66 : * Adds a + b. If the result overflows returns 2^64 - 1.
67 : */
68 : AWS_COMMON_MATH_API uint64_t aws_add_u64_saturating(uint64_t a, uint64_t b);
69 :
70 : /**
71 : * If a + b overflows, returns AWS_OP_ERR; otherwise adds
72 : * a + b, returns the result in *r, and returns AWS_OP_SUCCESS.
73 : */
74 : AWS_COMMON_MATH_API int aws_add_u64_checked(uint64_t a, uint64_t b, uint64_t *r);
75 :
76 : /**
77 : * Adds a + b. If the result overflows returns 2^32 - 1.
78 : */
79 : AWS_COMMON_MATH_API uint32_t aws_add_u32_saturating(uint32_t a, uint32_t b);
80 :
81 : /**
82 : * If a + b overflows, returns AWS_OP_ERR; otherwise adds
83 : * a + b, returns the result in *r, and returns AWS_OP_SUCCESS.
84 : */
85 : AWS_COMMON_MATH_API int aws_add_u32_checked(uint32_t a, uint32_t b, uint32_t *r);
86 :
87 : /**
88 : * Subtracts a - b. If the result overflows returns 0.
89 : */
90 : AWS_STATIC_IMPL uint64_t aws_sub_u64_saturating(uint64_t a, uint64_t b);
91 :
92 : /**
93 : * If a - b overflows, returns AWS_OP_ERR; otherwise subtracts
94 : * a - b, returns the result in *r, and returns AWS_OP_SUCCESS.
95 : */
96 : AWS_STATIC_IMPL int aws_sub_u64_checked(uint64_t a, uint64_t b, uint64_t *r);
97 :
98 : /**
99 : * Subtracts a - b. If the result overflows returns 0.
100 : */
101 : AWS_STATIC_IMPL uint32_t aws_sub_u32_saturating(uint32_t a, uint32_t b);
102 :
103 : /**
104 : * If a - b overflows, returns AWS_OP_ERR; otherwise subtracts
105 : * a - b, returns the result in *r, and returns AWS_OP_SUCCESS.
106 : */
107 : AWS_STATIC_IMPL int aws_sub_u32_checked(uint32_t a, uint32_t b, uint32_t *r);
108 :
109 : /**
110 : * Multiplies a * b. If the result overflows, returns SIZE_MAX.
111 : */
112 : AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b);
113 :
114 : /**
115 : * Multiplies a * b and returns the result in *r. If the result
116 : * overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS.
117 : */
118 : AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r);
119 :
120 : /**
121 : * Adds a + b. If the result overflows returns SIZE_MAX.
122 : */
123 : AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b);
124 :
125 : /**
126 : * Adds a + b and returns the result in *r. If the result
127 : * overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS.
128 : */
129 : AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r);
130 :
131 : /**
132 : * Adds [num] arguments (expected to be of size_t), and returns the result in *r.
133 : * If the result overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS.
134 : */
135 : AWS_COMMON_API int aws_add_size_checked_varargs(size_t num, size_t *r, ...);
136 :
137 : /**
138 : * Subtracts a - b. If the result overflows returns 0.
139 : */
140 : AWS_STATIC_IMPL size_t aws_sub_size_saturating(size_t a, size_t b);
141 :
142 : /**
143 : * If a - b overflows, returns AWS_OP_ERR; otherwise subtracts
144 : * a - b, returns the result in *r, and returns AWS_OP_SUCCESS.
145 : */
146 : AWS_STATIC_IMPL int aws_sub_size_checked(size_t a, size_t b, size_t *r);
147 :
148 : /**
149 : * Function to check if x is power of 2
150 : */
151 : AWS_STATIC_IMPL bool aws_is_power_of_two(const size_t x);
152 : /**
153 : * Function to find the smallest result that is power of 2 >= n. Returns AWS_OP_ERR if this cannot
154 : * be done without overflow
155 : */
156 : AWS_STATIC_IMPL int aws_round_up_to_power_of_two(size_t n, size_t *result);
157 :
158 : /**
159 : * Counts the number of leading 0 bits in an integer
160 : */
161 : AWS_STATIC_IMPL size_t aws_clz_u32(uint32_t n);
162 : AWS_STATIC_IMPL size_t aws_clz_i32(int32_t n);
163 : AWS_STATIC_IMPL size_t aws_clz_u64(uint64_t n);
164 : AWS_STATIC_IMPL size_t aws_clz_i64(int64_t n);
165 : AWS_STATIC_IMPL size_t aws_clz_size(size_t n);
166 :
167 : /**
168 : * Counts the number of trailing 0 bits in an integer
169 : */
170 : AWS_STATIC_IMPL size_t aws_ctz_u32(uint32_t n);
171 : AWS_STATIC_IMPL size_t aws_ctz_i32(int32_t n);
172 : AWS_STATIC_IMPL size_t aws_ctz_u64(uint64_t n);
173 : AWS_STATIC_IMPL size_t aws_ctz_i64(int64_t n);
174 : AWS_STATIC_IMPL size_t aws_ctz_size(size_t n);
175 :
176 : AWS_STATIC_IMPL uint8_t aws_min_u8(uint8_t a, uint8_t b);
177 : AWS_STATIC_IMPL uint8_t aws_max_u8(uint8_t a, uint8_t b);
178 : AWS_STATIC_IMPL int8_t aws_min_i8(int8_t a, int8_t b);
179 : AWS_STATIC_IMPL int8_t aws_max_i8(int8_t a, int8_t b);
180 : AWS_STATIC_IMPL uint16_t aws_min_u16(uint16_t a, uint16_t b);
181 : AWS_STATIC_IMPL uint16_t aws_max_u16(uint16_t a, uint16_t b);
182 : AWS_STATIC_IMPL int16_t aws_min_i16(int16_t a, int16_t b);
183 : AWS_STATIC_IMPL int16_t aws_max_i16(int16_t a, int16_t b);
184 : AWS_STATIC_IMPL uint32_t aws_min_u32(uint32_t a, uint32_t b);
185 : AWS_STATIC_IMPL uint32_t aws_max_u32(uint32_t a, uint32_t b);
186 : AWS_STATIC_IMPL int32_t aws_min_i32(int32_t a, int32_t b);
187 : AWS_STATIC_IMPL int32_t aws_max_i32(int32_t a, int32_t b);
188 : AWS_STATIC_IMPL uint64_t aws_min_u64(uint64_t a, uint64_t b);
189 : AWS_STATIC_IMPL uint64_t aws_max_u64(uint64_t a, uint64_t b);
190 : AWS_STATIC_IMPL int64_t aws_min_i64(int64_t a, int64_t b);
191 : AWS_STATIC_IMPL int64_t aws_max_i64(int64_t a, int64_t b);
192 : AWS_STATIC_IMPL size_t aws_min_size(size_t a, size_t b);
193 : AWS_STATIC_IMPL size_t aws_max_size(size_t a, size_t b);
194 : AWS_STATIC_IMPL int aws_min_int(int a, int b);
195 : AWS_STATIC_IMPL int aws_max_int(int a, int b);
196 : AWS_STATIC_IMPL float aws_min_float(float a, float b);
197 : AWS_STATIC_IMPL float aws_max_float(float a, float b);
198 : AWS_STATIC_IMPL double aws_min_double(double a, double b);
199 : AWS_STATIC_IMPL double aws_max_double(double a, double b);
200 :
201 : #ifndef AWS_NO_STATIC_IMPL
202 : # include <aws/common/math.inl>
203 : #endif /* AWS_NO_STATIC_IMPL */
204 :
205 : AWS_EXTERN_C_END
206 :
207 : #endif /* AWS_COMMON_MATH_H */
|