1 | #ifndef AWS_COMMON_MATH_H |
2 | #define AWS_COMMON_MATH_H |
3 | |
4 | /* |
5 | * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"). |
8 | * You may not use this file except in compliance with the License. |
9 | * A copy of the License is located at |
10 | * |
11 | * http://aws.amazon.com/apache2.0 |
12 | * |
13 | * or in the "license" file accompanying this file. This file is distributed |
14 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
15 | * express or implied. See the License for the specific language governing |
16 | * permissions and limitations under the License. |
17 | */ |
18 | |
19 | #include <aws/common/common.h> |
20 | #include <aws/common/config.h> |
21 | |
22 | #include <limits.h> |
23 | #include <stdlib.h> |
24 | |
25 | /* The number of bits in a size_t variable */ |
26 | #if SIZE_MAX == UINT32_MAX |
27 | # define SIZE_BITS 32 |
28 | #elif SIZE_MAX == UINT64_MAX |
29 | # define SIZE_BITS 64 |
30 | #else |
31 | # error "Target not supported" |
32 | #endif |
33 | |
34 | /* The largest power of two that can be stored in a size_t */ |
35 | #define SIZE_MAX_POWER_OF_TWO (((size_t)1) << (SIZE_BITS - 1)) |
36 | |
37 | AWS_EXTERN_C_BEGIN |
38 | |
39 | #if defined(AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS) && (defined(__clang__) || !defined(__cplusplus)) || \ |
40 | defined(__x86_64__) && defined(AWS_HAVE_GCC_INLINE_ASM) || defined(AWS_HAVE_MSVC_MULX) || defined(CBMC) || \ |
41 | !defined(AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS) |
42 | /* In all these cases, we can use fast static inline versions of this code */ |
43 | # define AWS_COMMON_MATH_API AWS_STATIC_IMPL |
44 | #else |
45 | /* |
46 | * We got here because we are building in C++ mode but we only support overflow extensions |
47 | * in C mode. Because the fallback is _slow_ (involving a division), we'd prefer to make a |
48 | * non-inline call to the fast C intrinsics. |
49 | */ |
50 | # define AWS_COMMON_MATH_API AWS_COMMON_API |
51 | #endif |
52 | |
53 | /** |
54 | * Multiplies a * b. If the result overflows, returns 2^64 - 1. |
55 | */ |
56 | AWS_COMMON_MATH_API uint64_t aws_mul_u64_saturating(uint64_t a, uint64_t b); |
57 | |
58 | /** |
59 | * If a * b overflows, returns AWS_OP_ERR; otherwise multiplies |
60 | * a * b, returns the result in *r, and returns AWS_OP_SUCCESS. |
61 | */ |
62 | AWS_COMMON_MATH_API int aws_mul_u64_checked(uint64_t a, uint64_t b, uint64_t *r); |
63 | |
64 | /** |
65 | * Multiplies a * b. If the result overflows, returns 2^32 - 1. |
66 | */ |
67 | AWS_COMMON_MATH_API uint32_t aws_mul_u32_saturating(uint32_t a, uint32_t b); |
68 | |
69 | /** |
70 | * If a * b overflows, returns AWS_OP_ERR; otherwise multiplies |
71 | * a * b, returns the result in *r, and returns AWS_OP_SUCCESS. |
72 | */ |
73 | AWS_COMMON_MATH_API int aws_mul_u32_checked(uint32_t a, uint32_t b, uint32_t *r); |
74 | |
75 | /** |
76 | * Adds a + b. If the result overflows returns 2^64 - 1. |
77 | */ |
78 | AWS_COMMON_MATH_API uint64_t aws_add_u64_saturating(uint64_t a, uint64_t b); |
79 | |
80 | /** |
81 | * If a + b overflows, returns AWS_OP_ERR; otherwise adds |
82 | * a + b, returns the result in *r, and returns AWS_OP_SUCCESS. |
83 | */ |
84 | AWS_COMMON_MATH_API int aws_add_u64_checked(uint64_t a, uint64_t b, uint64_t *r); |
85 | |
86 | /** |
87 | * Adds a + b. If the result overflows returns 2^32 - 1. |
88 | */ |
89 | AWS_COMMON_MATH_API uint32_t aws_add_u32_saturating(uint32_t a, uint32_t b); |
90 | |
91 | /** |
92 | * If a + b overflows, returns AWS_OP_ERR; otherwise adds |
93 | * a + b, returns the result in *r, and returns AWS_OP_SUCCESS. |
94 | */ |
95 | AWS_COMMON_MATH_API int aws_add_u32_checked(uint32_t a, uint32_t b, uint32_t *r); |
96 | |
97 | /** |
98 | * Multiplies a * b. If the result overflows, returns SIZE_MAX. |
99 | */ |
100 | AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b); |
101 | |
102 | /** |
103 | * Multiplies a * b and returns the result in *r. If the result |
104 | * overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS. |
105 | */ |
106 | AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r); |
107 | |
108 | /** |
109 | * Adds a + b. If the result overflows returns SIZE_MAX. |
110 | */ |
111 | AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b); |
112 | |
113 | /** |
114 | * Adds a + b and returns the result in *r. If the result |
115 | * overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS. |
116 | */ |
117 | AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r); |
118 | |
119 | /** |
120 | * Adds [num] arguments (expected to be of size_t), and returns the result in *r. |
121 | * If the result overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS. |
122 | */ |
123 | AWS_COMMON_API int aws_add_size_checked_varargs(size_t num, size_t *r, ...); |
124 | |
125 | /** |
126 | * Function to check if x is power of 2 |
127 | */ |
128 | AWS_STATIC_IMPL bool aws_is_power_of_two(const size_t x); |
129 | /** |
130 | * Function to find the smallest result that is power of 2 >= n. Returns AWS_OP_ERR if this cannot |
131 | * be done without overflow |
132 | */ |
133 | AWS_STATIC_IMPL int aws_round_up_to_power_of_two(size_t n, size_t *result); |
134 | |
135 | #ifndef AWS_NO_STATIC_IMPL |
136 | # include <aws/common/math.inl> |
137 | #endif /* AWS_NO_STATIC_IMPL */ |
138 | |
139 | AWS_EXTERN_C_END |
140 | |
141 | #endif /* AWS_COMMON_MATH_H */ |
142 | |