LCOV - code coverage report
Current view: top level - aws-c-common/include/aws/common - math.inl (source / functions) Hit Total Coverage
Test: all_fuzz.info Lines: 27 174 15.5 %
Date: 2021-04-23 16:28:21 Functions: 38 5544 0.7 %

          Line data    Source code
       1             : #ifndef AWS_COMMON_MATH_INL
       2             : #define AWS_COMMON_MATH_INL
       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             : #include <aws/common/math.h>
      12             : 
      13             : #include <limits.h>
      14             : #include <stdlib.h>
      15             : 
      16             : AWS_EXTERN_C_BEGIN
      17             : 
      18             : #if defined(AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS) && (defined(__clang__) || !defined(__cplusplus))
      19             : /*
      20             :  * GCC and clang have these super convenient overflow checking builtins...
      21             :  * but (in the case of GCC) they're only available when building C source.
      22             :  * We'll fall back to one of the other inlinable variants (or a non-inlined version)
      23             :  * if we are building this header on G++.
      24             :  */
      25             : #    include <aws/common/math.gcc_overflow.inl>
      26             : #elif defined(__x86_64__) && defined(AWS_HAVE_GCC_INLINE_ASM)
      27             : #    include <aws/common/math.gcc_x64_asm.inl>
      28             : #elif defined(__aarch64__) && defined(AWS_HAVE_GCC_INLINE_ASM)
      29             : #    include <aws/common/math.gcc_arm64_asm.inl>
      30             : #elif defined(AWS_HAVE_MSVC_MULX)
      31             : #    include <aws/common/math.msvc.inl>
      32             : #elif defined(CBMC)
      33             : #    include <aws/common/math.cbmc.inl>
      34             : #else
      35             : #    ifndef AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS
      36             : /* Fall back to the pure-C implementations */
      37             : #        include <aws/common/math.fallback.inl>
      38             : #    else
      39             : /*
      40             :  * We got here because we are building in C++ mode but we only support overflow extensions
      41             :  * in C mode. Because the fallback is _slow_ (involving a division), we'd prefer to make a
      42             :  * non-inline call to the fast C intrinsics.
      43             :  */
      44             : #    endif /*  AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS */
      45             : #endif     /*  defined(AWS_HAVE_GCC_OVERFLOW_MATH_EXTENSIONS) && (defined(__clang__) || !defined(__cplusplus)) */
      46             : 
      47             : #if defined(__clang__) || defined(__GNUC__)
      48             : #    include <aws/common/math.gcc_builtin.inl>
      49             : #endif
      50             : 
      51             : #if _MSC_VER
      52             : #    pragma warning(push)
      53             : #    pragma warning(disable : 4127) /*Disable "conditional expression is constant" */
      54             : #endif                              /* _MSC_VER */
      55             : 
      56           0 : AWS_STATIC_IMPL uint64_t aws_sub_u64_saturating(uint64_t a, uint64_t b) {
      57           0 :     return a <= b ? 0 : a - b;
      58           0 : }
      59             : 
      60           0 : AWS_STATIC_IMPL int aws_sub_u64_checked(uint64_t a, uint64_t b, uint64_t *r) {
      61           0 :     if (a < b) {
      62           0 :         return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
      63           0 :     }
      64           0 : 
      65           0 :     *r = a - b;
      66           0 :     return AWS_OP_SUCCESS;
      67           0 : }
      68             : 
      69           0 : AWS_STATIC_IMPL uint32_t aws_sub_u32_saturating(uint32_t a, uint32_t b) {
      70           0 :     return a <= b ? 0 : a - b;
      71           0 : }
      72             : 
      73           0 : AWS_STATIC_IMPL int aws_sub_u32_checked(uint32_t a, uint32_t b, uint32_t *r) {
      74           0 :     if (a < b) {
      75           0 :         return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
      76           0 :     }
      77           0 : 
      78           0 :     *r = a - b;
      79           0 :     return AWS_OP_SUCCESS;
      80           0 : }
      81             : 
      82             : /**
      83             :  * Multiplies a * b. If the result overflows, returns SIZE_MAX.
      84             :  */
      85           0 : AWS_STATIC_IMPL size_t aws_mul_size_saturating(size_t a, size_t b) {
      86           0 : #if SIZE_BITS == 32
      87           0 :     return (size_t)aws_mul_u32_saturating(a, b);
      88           0 : #elif SIZE_BITS == 64
      89           0 :     return (size_t)aws_mul_u64_saturating(a, b);
      90           0 : #else
      91           0 : #    error "Target not supported"
      92           0 : #endif
      93           0 : }
      94             : 
      95             : /**
      96             :  * Multiplies a * b and returns the result in *r. If the result
      97             :  * overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS.
      98             :  */
      99     8326111 : AWS_STATIC_IMPL int aws_mul_size_checked(size_t a, size_t b, size_t *r) {
     100           0 : #if SIZE_BITS == 32
     101           0 :     return aws_mul_u32_checked(a, b, (uint32_t *)r);
     102           0 : #elif SIZE_BITS == 64
     103           0 :     return aws_mul_u64_checked(a, b, (uint64_t *)r);
     104           0 : #else
     105           0 : #    error "Target not supported"
     106           0 : #endif
     107           0 : }
     108             : 
     109             : /**
     110             :  * Adds a + b.  If the result overflows returns SIZE_MAX.
     111             :  */
     112       81166 : AWS_STATIC_IMPL size_t aws_add_size_saturating(size_t a, size_t b) {
     113           0 : #if SIZE_BITS == 32
     114           0 :     return (size_t)aws_add_u32_saturating(a, b);
     115           0 : #elif SIZE_BITS == 64
     116           0 :     return (size_t)aws_add_u64_saturating(a, b);
     117           0 : #else
     118           0 : #    error "Target not supported"
     119           0 : #endif
     120           0 : }
     121             : 
     122             : /**
     123             :  * Adds a + b and returns the result in *r. If the result
     124             :  * overflows, returns AWS_OP_ERR; otherwise returns AWS_OP_SUCCESS.
     125             :  */
     126     2951679 : AWS_STATIC_IMPL int aws_add_size_checked(size_t a, size_t b, size_t *r) {
     127           0 : #if SIZE_BITS == 32
     128           0 :     return aws_add_u32_checked(a, b, (uint32_t *)r);
     129           0 : #elif SIZE_BITS == 64
     130           0 :     return aws_add_u64_checked(a, b, (uint64_t *)r);
     131           0 : #else
     132           0 : #    error "Target not supported"
     133           0 : #endif
     134           0 : }
     135             : 
     136           0 : AWS_STATIC_IMPL size_t aws_sub_size_saturating(size_t a, size_t b) {
     137           0 : #if SIZE_BITS == 32
     138           0 :     return (size_t)aws_sub_u32_saturating(a, b);
     139           0 : #elif SIZE_BITS == 64
     140           0 :     return (size_t)aws_sub_u64_saturating(a, b);
     141           0 : #else
     142           0 : #    error "Target not supported"
     143           0 : #endif
     144           0 : }
     145             : 
     146           0 : AWS_STATIC_IMPL int aws_sub_size_checked(size_t a, size_t b, size_t *r) {
     147           0 : #if SIZE_BITS == 32
     148           0 :     return aws_sub_u32_checked(a, b, (uint32_t *)r);
     149           0 : #elif SIZE_BITS == 64
     150           0 :     return aws_sub_u64_checked(a, b, (uint64_t *)r);
     151           0 : #else
     152           0 : #    error "Target not supported"
     153           0 : #endif
     154           0 : }
     155             : 
     156             : /**
     157             :  * Function to check if x is power of 2
     158             :  */
     159     2473707 : AWS_STATIC_IMPL bool aws_is_power_of_two(const size_t x) {
     160     2473707 :     /* First x in the below expression is for the case when x is 0 */
     161     2473707 :     return x && (!(x & (x - 1)));
     162     2473707 : }
     163             : 
     164             : /**
     165             :  * Function to find the smallest result that is power of 2 >= n. Returns AWS_OP_ERR if this cannot
     166             :  * be done without overflow
     167             :  */
     168     2332051 : AWS_STATIC_IMPL int aws_round_up_to_power_of_two(size_t n, size_t *result) {
     169     2332051 :     if (n == 0) {
     170      892826 :         *result = 1;
     171      892826 :         return AWS_OP_SUCCESS;
     172      892826 :     }
     173     1439225 :     if (n > SIZE_MAX_POWER_OF_TWO) {
     174           0 :         return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
     175           0 :     }
     176     1439225 : 
     177     1439225 :     n--;
     178     1439225 :     n |= n >> 1;
     179     1439225 :     n |= n >> 2;
     180     1439225 :     n |= n >> 4;
     181     1439225 :     n |= n >> 8;
     182     1439225 :     n |= n >> 16;
     183     1439225 : #if SIZE_BITS == 64
     184     1439225 :     n |= n >> 32;
     185     1439225 : #endif
     186     1439225 :     n++;
     187     1439225 :     *result = n;
     188     1439225 :     return AWS_OP_SUCCESS;
     189     1439225 : }
     190             : 
     191             : #if _MSC_VER
     192             : #    pragma warning(pop)
     193             : #endif /* _MSC_VER */
     194             : 
     195           0 : AWS_STATIC_IMPL uint8_t aws_min_u8(uint8_t a, uint8_t b) {
     196           0 :     return a < b ? a : b;
     197           0 : }
     198             : 
     199           0 : AWS_STATIC_IMPL uint8_t aws_max_u8(uint8_t a, uint8_t b) {
     200           0 :     return a > b ? a : b;
     201           0 : }
     202             : 
     203           0 : AWS_STATIC_IMPL int8_t aws_min_i8(int8_t a, int8_t b) {
     204           0 :     return a < b ? a : b;
     205           0 : }
     206             : 
     207           0 : AWS_STATIC_IMPL int8_t aws_max_i8(int8_t a, int8_t b) {
     208           0 :     return a > b ? a : b;
     209           0 : }
     210             : 
     211           0 : AWS_STATIC_IMPL uint16_t aws_min_u16(uint16_t a, uint16_t b) {
     212           0 :     return a < b ? a : b;
     213           0 : }
     214             : 
     215           0 : AWS_STATIC_IMPL uint16_t aws_max_u16(uint16_t a, uint16_t b) {
     216           0 :     return a > b ? a : b;
     217           0 : }
     218             : 
     219           0 : AWS_STATIC_IMPL int16_t aws_min_i16(int16_t a, int16_t b) {
     220           0 :     return a < b ? a : b;
     221           0 : }
     222             : 
     223           0 : AWS_STATIC_IMPL int16_t aws_max_i16(int16_t a, int16_t b) {
     224           0 :     return a > b ? a : b;
     225           0 : }
     226             : 
     227           0 : AWS_STATIC_IMPL uint32_t aws_min_u32(uint32_t a, uint32_t b) {
     228           0 :     return a < b ? a : b;
     229           0 : }
     230             : 
     231           0 : AWS_STATIC_IMPL uint32_t aws_max_u32(uint32_t a, uint32_t b) {
     232           0 :     return a > b ? a : b;
     233           0 : }
     234             : 
     235           0 : AWS_STATIC_IMPL int32_t aws_min_i32(int32_t a, int32_t b) {
     236           0 :     return a < b ? a : b;
     237           0 : }
     238             : 
     239           0 : AWS_STATIC_IMPL int32_t aws_max_i32(int32_t a, int32_t b) {
     240           0 :     return a > b ? a : b;
     241           0 : }
     242             : 
     243           0 : AWS_STATIC_IMPL uint64_t aws_min_u64(uint64_t a, uint64_t b) {
     244           0 :     return a < b ? a : b;
     245           0 : }
     246             : 
     247           0 : AWS_STATIC_IMPL uint64_t aws_max_u64(uint64_t a, uint64_t b) {
     248           0 :     return a > b ? a : b;
     249           0 : }
     250             : 
     251           0 : AWS_STATIC_IMPL int64_t aws_min_i64(int64_t a, int64_t b) {
     252           0 :     return a < b ? a : b;
     253           0 : }
     254             : 
     255           0 : AWS_STATIC_IMPL int64_t aws_max_i64(int64_t a, int64_t b) {
     256           0 :     return a > b ? a : b;
     257           0 : }
     258             : 
     259           0 : AWS_STATIC_IMPL size_t aws_min_size(size_t a, size_t b) {
     260           0 :     return a < b ? a : b;
     261           0 : }
     262             : 
     263           0 : AWS_STATIC_IMPL size_t aws_max_size(size_t a, size_t b) {
     264           0 :     return a > b ? a : b;
     265           0 : }
     266             : 
     267           0 : AWS_STATIC_IMPL int aws_min_int(int a, int b) {
     268           0 :     return a < b ? a : b;
     269           0 : }
     270             : 
     271           0 : AWS_STATIC_IMPL int aws_max_int(int a, int b) {
     272           0 :     return a > b ? a : b;
     273           0 : }
     274             : 
     275           0 : AWS_STATIC_IMPL float aws_min_float(float a, float b) {
     276           0 :     return a < b ? a : b;
     277           0 : }
     278             : 
     279           0 : AWS_STATIC_IMPL float aws_max_float(float a, float b) {
     280           0 :     return a > b ? a : b;
     281           0 : }
     282             : 
     283           0 : AWS_STATIC_IMPL double aws_min_double(double a, double b) {
     284           0 :     return a < b ? a : b;
     285           0 : }
     286             : 
     287           0 : AWS_STATIC_IMPL double aws_max_double(double a, double b) {
     288           0 :     return a > b ? a : b;
     289           0 : }
     290             : 
     291             : AWS_EXTERN_C_END
     292             : 
     293             : #endif /* AWS_COMMON_MATH_INL */

Generated by: LCOV version 1.13