brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 0789213 Raw
156 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 div_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::div_sat(minVal, maxVal);29 30  static_assert(noexcept(std::div_sat(minVal, maxVal)));31 32  // clang-format off33 34  // Limit values (-1, 0, 1, min, max)35 36  assert(std::div_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 1});37  assert(std::div_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-1});38  assert(std::div_sat(IntegerT{-1},       minVal) == IntegerT{ 0});39  assert(std::div_sat(IntegerT{-1},       maxVal) == IntegerT{ 0});40  assert(std::div_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 0});41  assert(std::div_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 0});42  assert(std::div_sat(IntegerT{ 0},       minVal) == IntegerT{ 0});43  assert(std::div_sat(IntegerT{ 0},       maxVal) == IntegerT{ 0});44  assert(std::div_sat(IntegerT{ 1}, IntegerT{-1}) == IntegerT{-1});45  assert(std::div_sat(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 1});46  assert(std::div_sat(IntegerT{ 1},       minVal) == IntegerT{ 0});47  assert(std::div_sat(IntegerT{ 1},       maxVal) == IntegerT{ 0});48  assert(std::div_sat(      minVal, IntegerT{ 1}) == minVal);49  assert(std::div_sat(      minVal, IntegerT{-1}) == maxVal); // saturated50  assert(std::div_sat(      minVal,       minVal) == IntegerT{ 1});51  assert(std::div_sat(      minVal,       maxVal) == (minVal / maxVal));52  assert(std::div_sat(      maxVal, IntegerT{-1}) == -maxVal);53  assert(std::div_sat(      maxVal, IntegerT{ 1}) == maxVal);54  assert(std::div_sat(      maxVal,       minVal) == IntegerT{ 0});55  assert(std::div_sat(      maxVal,       maxVal) == IntegerT{ 1});56 57  // No saturation (no limit values)58 59  assert(std::div_sat(IntegerT{27}, IntegerT{28}) == IntegerT{0});60  assert(std::div_sat(IntegerT{28}, IntegerT{27}) == IntegerT{1});61  {62    constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{-28};63    constexpr IntegerT biggerVal = minVal / IntegerT{2} + IntegerT{-27};64    assert(std::div_sat(lesserVal, biggerVal) == IntegerT{1});65    assert(std::div_sat(biggerVal, lesserVal) == IntegerT{0});66  }67  {68    constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{-27};69    constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28};70    assert(std::div_sat(lesserVal, biggerVal) == IntegerT{-1});71    assert(std::div_sat(biggerVal, lesserVal) == IntegerT{-1});72  }73  {74    constexpr IntegerT lesserVal = maxVal / IntegerT{2} + IntegerT{27};75    constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28};76    assert(std::div_sat(lesserVal, biggerVal) == IntegerT{0});77    assert(std::div_sat(biggerVal, lesserVal) == IntegerT{1});78  }79 80  // clang-format on81 82  return true;83}84 85template <typename IntegerT>86constexpr bool test_unsigned() {87  constexpr auto minVal = std::numeric_limits<IntegerT>::min();88  constexpr auto maxVal = std::numeric_limits<IntegerT>::max();89 90  std::same_as<IntegerT> decltype(auto) _ = std::div_sat(minVal, maxVal);91  static_assert(noexcept(std::div_sat(minVal, maxVal)));92 93  // clang-format off94 95  // No limit values (0, 1, min, max)96 97  assert(std::div_sat(IntegerT{0}, IntegerT{1}) == IntegerT{0});98  assert(std::div_sat(IntegerT{0},      maxVal) == IntegerT{0});99 100  assert(std::div_sat(IntegerT{1}, IntegerT{1}) == IntegerT{1});101  assert(std::div_sat(IntegerT{1},      maxVal) == IntegerT{0});102 103  assert(std::div_sat(     minVal, IntegerT{1}) == minVal);104  assert(std::div_sat(     minVal,      maxVal) == IntegerT{0});105 106  assert(std::div_sat(     maxVal, IntegerT{1}) == maxVal);107  assert(std::div_sat(     maxVal,      maxVal) == IntegerT{1});108 109  // No saturation (no limit values)110 111  assert(std::div_sat(IntegerT{27}, IntegerT{28}) == IntegerT{0});112  assert(std::div_sat(IntegerT{28}, IntegerT{27}) == IntegerT{1});113  {114    constexpr IntegerT lesserVal = maxVal / IntegerT{2} + IntegerT{27};115    constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28};116    assert(std::div_sat(lesserVal, biggerVal) == IntegerT{0});117    assert(std::div_sat(biggerVal, lesserVal) == IntegerT{1});118  }119 120  // Unsigned integer division never overflows121 122  // clang-format on123 124  return true;125}126 127constexpr bool test() {128  // Signed129  test_signed<signed char>();130  test_signed<short int>();131  test_signed<int>();132  test_signed<long int>();133  test_signed<long long int>();134#ifndef TEST_HAS_NO_INT128135  test_signed<__int128_t>();136#endif137  // Unsigned138  test_unsigned<unsigned char>();139  test_unsigned<unsigned short int>();140  test_unsigned<unsigned int>();141  test_unsigned<unsigned long int>();142  test_unsigned<unsigned long long int>();143#ifndef TEST_HAS_NO_INT128144  test_unsigned<__uint128_t>();145#endif146 147  return true;148}149 150int main(int, char**) {151  test();152  static_assert(test());153 154  return 0;155}156