OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 #include <algorithm> |
| 12 #include <limits> |
| 13 |
| 14 #include "webrtc/base/safe_minmax.h" |
| 15 #include "webrtc/test/gtest.h" |
| 16 |
| 17 namespace rtc { |
| 18 |
| 19 namespace { |
| 20 |
| 21 // Functions that check that SafeMin() and SafeMax() return the specified type. |
| 22 // The functions that end in "R" use an explicitly given return type. |
| 23 |
| 24 template <typename T1, typename T2, typename Tmin, typename Tmax> |
| 25 constexpr bool TypeCheckMinMax() { |
| 26 return std::is_same<decltype(SafeMin(std::declval<T1>(), std::declval<T2>())), |
| 27 Tmin>::value && |
| 28 std::is_same<decltype(SafeMax(std::declval<T1>(), std::declval<T2>())), |
| 29 Tmax>::value; |
| 30 } |
| 31 |
| 32 template <typename T1, typename T2, typename R> |
| 33 constexpr bool TypeCheckMinR() { |
| 34 return std::is_same< |
| 35 decltype(SafeMin<R>(std::declval<T1>(), std::declval<T2>())), R>::value; |
| 36 } |
| 37 |
| 38 template <typename T1, typename T2, typename R> |
| 39 constexpr bool TypeCheckMaxR() { |
| 40 return std::is_same< |
| 41 decltype(SafeMax<R>(std::declval<T1>(), std::declval<T2>())), R>::value; |
| 42 } |
| 43 |
| 44 // clang-format off |
| 45 |
| 46 // SafeMin/SafeMax: Check that all combinations of signed/unsigned 8/64 bits |
| 47 // give the correct default result type. |
| 48 static_assert(TypeCheckMinMax< int8_t, int8_t, int8_t, int8_t>(), ""); |
| 49 static_assert(TypeCheckMinMax< int8_t, uint8_t, int8_t, uint8_t>(), ""); |
| 50 static_assert(TypeCheckMinMax< int8_t, int64_t, int64_t, int64_t>(), ""); |
| 51 static_assert(TypeCheckMinMax< int8_t, uint64_t, int8_t, uint64_t>(), ""); |
| 52 static_assert(TypeCheckMinMax< uint8_t, int8_t, int8_t, uint8_t>(), ""); |
| 53 static_assert(TypeCheckMinMax< uint8_t, uint8_t, uint8_t, uint8_t>(), ""); |
| 54 static_assert(TypeCheckMinMax< uint8_t, int64_t, int64_t, int64_t>(), ""); |
| 55 static_assert(TypeCheckMinMax< uint8_t, uint64_t, uint8_t, uint64_t>(), ""); |
| 56 static_assert(TypeCheckMinMax< int64_t, int8_t, int64_t, int64_t>(), ""); |
| 57 static_assert(TypeCheckMinMax< int64_t, uint8_t, int64_t, int64_t>(), ""); |
| 58 static_assert(TypeCheckMinMax< int64_t, int64_t, int64_t, int64_t>(), ""); |
| 59 static_assert(TypeCheckMinMax< int64_t, uint64_t, int64_t, uint64_t>(), ""); |
| 60 static_assert(TypeCheckMinMax<uint64_t, int8_t, int8_t, uint64_t>(), ""); |
| 61 static_assert(TypeCheckMinMax<uint64_t, uint8_t, uint8_t, uint64_t>(), ""); |
| 62 static_assert(TypeCheckMinMax<uint64_t, int64_t, int64_t, uint64_t>(), ""); |
| 63 static_assert(TypeCheckMinMax<uint64_t, uint64_t, uint64_t, uint64_t>(), ""); |
| 64 |
| 65 using ld = long double; |
| 66 |
| 67 // SafeMin/SafeMax: Check that some floating-point combinations give the |
| 68 // correct result type. |
| 69 static_assert(TypeCheckMinMax< int, int, int, int>(), ""); |
| 70 static_assert(TypeCheckMinMax< int, float, float, float>(), ""); |
| 71 static_assert(TypeCheckMinMax< int, double, double, double>(), ""); |
| 72 static_assert(TypeCheckMinMax< int, ld, ld, ld>(), ""); |
| 73 static_assert(TypeCheckMinMax< float, int, float, float>(), ""); |
| 74 static_assert(TypeCheckMinMax< float, float, float, float>(), ""); |
| 75 static_assert(TypeCheckMinMax< float, double, double, double>(), ""); |
| 76 static_assert(TypeCheckMinMax< float, ld, ld, ld>(), ""); |
| 77 static_assert(TypeCheckMinMax<double, int, double, double>(), ""); |
| 78 static_assert(TypeCheckMinMax<double, float, double, double>(), ""); |
| 79 static_assert(TypeCheckMinMax<double, double, double, double>(), ""); |
| 80 static_assert(TypeCheckMinMax<double, ld, ld, ld>(), ""); |
| 81 static_assert(TypeCheckMinMax< ld, int, ld, ld>(), ""); |
| 82 static_assert(TypeCheckMinMax< ld, float, ld, ld>(), ""); |
| 83 static_assert(TypeCheckMinMax< ld, double, ld, ld>(), ""); |
| 84 static_assert(TypeCheckMinMax< ld, ld, ld, ld>(), ""); |
| 85 |
| 86 // clang-format on |
| 87 |
| 88 // SafeMin/SafeMax: Check some cases of explicitly specified return type. The |
| 89 // commented-out lines give compilation errors due to the requested return type |
| 90 // being too small. |
| 91 static_assert(TypeCheckMinR<int8_t, int8_t, int16_t>(), ""); |
| 92 static_assert(TypeCheckMinR<int8_t, int8_t, float>(), ""); |
| 93 static_assert(TypeCheckMinR<uint32_t, uint64_t, uint32_t>(), ""); |
| 94 static_assert(TypeCheckMaxR<uint64_t, float, float>(), ""); |
| 95 // static_assert(TypeCheckMaxR<uint64_t, double, float>(), ""); |
| 96 static_assert(TypeCheckMaxR<uint32_t, int32_t, uint32_t>(), ""); |
| 97 // static_assert(TypeCheckMaxR<uint32_t, int32_t, int32_t>(), ""); |
| 98 |
| 99 template <typename T1, typename T2, typename Tmin, typename Tmax> |
| 100 constexpr bool CheckMinMax(T1 a, T2 b, Tmin min, Tmax max) { |
| 101 return TypeCheckMinMax<T1, T2, Tmin, Tmax>() && SafeMin(a, b) == min && |
| 102 SafeMax(a, b) == max; |
| 103 } |
| 104 |
| 105 // SafeMin/SafeMax: Check a few values. |
| 106 static_assert(CheckMinMax(int8_t{1}, int8_t{-1}, int8_t{-1}, int8_t{1}), ""); |
| 107 static_assert(CheckMinMax(uint8_t{1}, int8_t{-1}, int8_t{-1}, uint8_t{1}), ""); |
| 108 static_assert(CheckMinMax(uint8_t{5}, uint64_t{2}, uint8_t{2}, uint64_t{5}), |
| 109 ""); |
| 110 static_assert(CheckMinMax(std::numeric_limits<int32_t>::min(), |
| 111 std::numeric_limits<uint32_t>::max(), |
| 112 std::numeric_limits<int32_t>::min(), |
| 113 std::numeric_limits<uint32_t>::max()), |
| 114 ""); |
| 115 static_assert(CheckMinMax(std::numeric_limits<int32_t>::min(), |
| 116 std::numeric_limits<uint16_t>::max(), |
| 117 std::numeric_limits<int32_t>::min(), |
| 118 int32_t{std::numeric_limits<uint16_t>::max()}), |
| 119 ""); |
| 120 static_assert(CheckMinMax(1.f, 2, 1.f, 2.f), ""); |
| 121 static_assert(CheckMinMax(1.f, 0.0, 0.0, 1.0), ""); |
| 122 |
| 123 } // namespace |
| 124 |
| 125 // clang-format off |
| 126 |
| 127 // These functions aren't used in the tests, but it's useful to look at the |
| 128 // compiler output for them, and verify that (1) the same-signedness *Safe |
| 129 // functions result in exactly the same code as their *Ref counterparts, and |
| 130 // that (2) the mixed-signedness *Safe functions have just a few extra |
| 131 // arithmetic and logic instructions (but no extra control flow instructions). |
| 132 int32_t TestMinRef( int32_t a, int32_t b) { return std::min(a, b); } |
| 133 uint32_t TestMinRef( uint32_t a, uint32_t b) { return std::min(a, b); } |
| 134 int32_t TestMinSafe( int32_t a, int32_t b) { return SafeMin(a, b); } |
| 135 int32_t TestMinSafe( int32_t a, uint32_t b) { return SafeMin(a, b); } |
| 136 int32_t TestMinSafe(uint32_t a, int32_t b) { return SafeMin(a, b); } |
| 137 uint32_t TestMinSafe(uint32_t a, uint32_t b) { return SafeMin(a, b); } |
| 138 |
| 139 // clang-format on |
| 140 |
| 141 } // namespace rtc |
OLD | NEW |