brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · f49e19a Raw
172 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: std-at-least-c++2610 11// <numeric>12 13// template<class T>14// constexpr T add_sat(T x, T y) noexcept;                     // freestanding15 16#include <cassert>17#include <concepts>18#include <limits>19#include <numeric>20 21#include "test_macros.h"22 23template <typename IntegerT>24constexpr bool test_signed() {25  constexpr auto minVal = std::numeric_limits<IntegerT>::min();26  constexpr auto maxVal = std::numeric_limits<IntegerT>::max();27 28  std::same_as<IntegerT> decltype(auto) _ = std::add_sat(minVal, maxVal);29 30  static_assert(noexcept(std::add_sat(minVal, maxVal)));31 32  // clang-format off33 34  // Limit values (-1, 0, 1, min, max)35 36  assert(std::add_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{-2});37  assert(std::add_sat(IntegerT{-1}, IntegerT{ 0}) == IntegerT{-1});38  assert(std::add_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{ 0});39  assert(std::add_sat(IntegerT{-1},       minVal) == minVal); // saturated40  assert(std::add_sat(IntegerT{-1},       maxVal) == IntegerT{-1} + maxVal);41 42  assert(std::add_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{-1});43  assert(std::add_sat(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0});44  assert(std::add_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 1});45  assert(std::add_sat(IntegerT{ 0},       minVal) == minVal);46  assert(std::add_sat(IntegerT{ 0},       maxVal) == maxVal);47 48  assert(std::add_sat(IntegerT{ 1}, IntegerT{-1}) == IntegerT{ 0});49  assert(std::add_sat(IntegerT{ 1}, IntegerT{ 0}) == IntegerT{ 1});50  assert(std::add_sat(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 2});51  assert(std::add_sat(IntegerT{ 1},       minVal) == IntegerT{ 1} + minVal);52  assert(std::add_sat(IntegerT{ 1},       maxVal) == maxVal); // saturated53 54  assert(std::add_sat(      minVal, IntegerT{-1}) == minVal); // saturated55  assert(std::add_sat(      minVal, IntegerT{ 0}) == minVal);56  assert(std::add_sat(      minVal, IntegerT{ 1}) == minVal + IntegerT{ 1});57  assert(std::add_sat(      minVal,       minVal) == minVal); // saturated58  assert(std::add_sat(      minVal,       maxVal) == IntegerT{-1});59 60  assert(std::add_sat(      maxVal, IntegerT{-1}) == maxVal + IntegerT{-1});61  assert(std::add_sat(      maxVal, IntegerT{ 0}) == maxVal);62  assert(std::add_sat(      maxVal, IntegerT{ 1}) == maxVal); // saturated63  assert(std::add_sat(      maxVal,       minVal) == IntegerT{-1});64  assert(std::add_sat(      maxVal,       maxVal) == maxVal); // saturated65 66  // No saturation (no limit values)67 68  assert(std::add_sat(IntegerT{-27}, IntegerT{28})== IntegerT{ 1});69  assert(std::add_sat(IntegerT{ 27}, IntegerT{28})== IntegerT{55});70  {71    constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27};72    constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28};73    assert(std::add_sat(x, y) == maxVal);74  }75 76  // Saturation (no limit values)77 78  {79    constexpr IntegerT x = minVal / IntegerT{2} + IntegerT{-27};80    constexpr IntegerT y = minVal / IntegerT{2} + IntegerT{-28};81    assert(std::add_sat(x, y) == minVal); // saturated82  }83  {84    constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27};85    constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28};86    assert(std::add_sat(x, y) == maxVal); // saturated87  }88 89  // clang-format on90 91  return true;92}93 94template <typename IntegerT>95constexpr bool test_unsigned() {96  constexpr auto minVal = std::numeric_limits<IntegerT>::min();97  constexpr auto maxVal = std::numeric_limits<IntegerT>::max();98 99  std::same_as<IntegerT> decltype(auto) _ = std::add_sat(minVal, maxVal);100 101  static_assert(noexcept(std::add_sat(minVal, maxVal)));102 103  // clang-format off104 105  // Litmit values (0, 1, min, max)106 107  assert(std::add_sat(IntegerT{0}, IntegerT{0}) == IntegerT{0});108  assert(std::add_sat(IntegerT{0}, IntegerT{1}) == IntegerT{1});109  assert(std::add_sat(IntegerT{0},      minVal) == IntegerT{0});110  assert(std::add_sat(IntegerT{0},      maxVal) == maxVal);111  assert(std::add_sat(IntegerT{1}, IntegerT{0}) == IntegerT{1});112  assert(std::add_sat(IntegerT{1}, IntegerT{1}) == IntegerT{2});113  assert(std::add_sat(IntegerT{1},      minVal) == IntegerT{1});114  assert(std::add_sat(IntegerT{1},      maxVal) == maxVal); // saturated115  assert(std::add_sat(     minVal, IntegerT{0}) == IntegerT{0});116  assert(std::add_sat(     minVal, IntegerT{1}) == IntegerT{1});117  assert(std::add_sat(     minVal,      minVal) == minVal);118  assert(std::add_sat(     minVal,      maxVal) == maxVal);119  assert(std::add_sat(     maxVal, IntegerT{0}) == maxVal);120  assert(std::add_sat(     maxVal, IntegerT{1}) == maxVal); // saturated121  assert(std::add_sat(     maxVal,      minVal) == maxVal);122  assert(std::add_sat(     maxVal,      maxVal) == maxVal); // saturated123 124  // No saturation (no limit values)125 126  assert(std::add_sat(IntegerT{27}, IntegerT{28}) == IntegerT{55});127 128  // Saturation (no limit values)129 130  {131    constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27};132    constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28};133    assert(std::add_sat(     x,           y) == maxVal); // saturated134    assert(std::add_sat(     x,      maxVal) == maxVal); // saturated135    assert(std::add_sat(maxVal,           y) == maxVal); // saturated136  }137 138  // clang-format on139 140  return true;141}142 143constexpr bool test() {144  // Signed145  test_signed<signed char>();146  test_signed<short int>();147  test_signed<int>();148  test_signed<long int>();149  test_signed<long long int>();150#ifndef TEST_HAS_NO_INT128151  test_signed<__int128_t>();152#endif153  // Unsigned154  test_unsigned<unsigned char>();155  test_unsigned<unsigned short int>();156  test_unsigned<unsigned int>();157  test_unsigned<unsigned long int>();158  test_unsigned<unsigned long long int>();159#ifndef TEST_HAS_NO_INT128160  test_unsigned<__uint128_t>();161#endif162 163  return true;164}165 166int main(int, char**) {167  test();168  static_assert(test());169 170  return 0;171}172