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
37AWS_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 */
56AWS_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 */
62AWS_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 */
67AWS_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 */
73AWS_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 */
78AWS_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 */
84AWS_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 */
89AWS_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 */
95AWS_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 */
100AWS_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 */
106AWS_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 */
111AWS_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 */
117AWS_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 */
123AWS_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 */
128AWS_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 */
133AWS_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
139AWS_EXTERN_C_END
140
141#endif /* AWS_COMMON_MATH_H */
142