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