blob: 676d375e946e5dca372e9f4e01b98dce7ef5231e [file] [log] [blame]
/*
* Copyright (C) 2012 Intel Corporation
* Copyright (C) 2019 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <wtf/MathExtras.h>
namespace TestWebKitAPI {
TEST(WTF, Lrint)
{
EXPECT_EQ(lrint(-7.5), -8);
EXPECT_EQ(lrint(-8.5), -8);
EXPECT_EQ(lrint(-0.5), 0);
EXPECT_EQ(lrint(0.5), 0);
EXPECT_EQ(lrint(-0.5), 0);
EXPECT_EQ(lrint(1.3), 1);
EXPECT_EQ(lrint(1.7), 2);
EXPECT_EQ(lrint(0), 0);
EXPECT_EQ(lrint(-0), 0);
if (sizeof(long int) == 8) {
// Largest double number with 0.5 precision and one halfway rounding case below.
EXPECT_EQ(lrint(pow(2.0, 52) - 0.5), pow(2.0, 52));
EXPECT_EQ(lrint(pow(2.0, 52) - 1.5), pow(2.0, 52) - 2);
// Smallest double number with 0.5 precision and one halfway rounding case above.
EXPECT_EQ(lrint(-pow(2.0, 52) + 0.5), -pow(2.0, 52));
EXPECT_EQ(lrint(-pow(2.0, 52) + 1.5), -pow(2.0, 52) + 2);
}
}
TEST(WTF, clampToIntLong)
{
if (sizeof(long) == sizeof(int))
return;
long maxInt = std::numeric_limits<int>::max();
long minInt = std::numeric_limits<int>::min();
long overflowInt = maxInt + 1;
long underflowInt = minInt - 1;
EXPECT_GT(overflowInt, maxInt);
EXPECT_LT(underflowInt, minInt);
EXPECT_EQ(clampTo<int>(maxInt), maxInt);
EXPECT_EQ(clampTo<int>(minInt), minInt);
EXPECT_EQ(clampTo<int>(overflowInt), maxInt);
EXPECT_EQ(clampTo<int>(underflowInt), minInt);
}
TEST(WTF, clampToIntLongLong)
{
long long maxInt = std::numeric_limits<int>::max();
long long minInt = std::numeric_limits<int>::min();
long long overflowInt = maxInt + 1;
long long underflowInt = minInt - 1;
EXPECT_GT(overflowInt, maxInt);
EXPECT_LT(underflowInt, minInt);
EXPECT_EQ(clampTo<int>(maxInt), maxInt);
EXPECT_EQ(clampTo<int>(minInt), minInt);
EXPECT_EQ(clampTo<int>(overflowInt), maxInt);
EXPECT_EQ(clampTo<int>(underflowInt), minInt);
}
TEST(WTF, clampToIntegerFloat)
{
// This test is inaccurate as floats will round the min / max integer
// due to the narrow mantissa. However it will properly checks within
// (close to the extreme) and outside the integer range.
float maxInt = std::numeric_limits<int>::max();
float minInt = std::numeric_limits<int>::min();
float overflowInt = maxInt * 1.1;
float underflowInt = minInt * 1.1;
EXPECT_GT(overflowInt, maxInt);
EXPECT_LT(underflowInt, minInt);
// If maxInt == 2^31 - 1 (ie on I32 architecture), the closest float used to represent it is 2^31.
EXPECT_NEAR(clampToInteger(maxInt), maxInt, 1);
EXPECT_EQ(clampToInteger(minInt), minInt);
EXPECT_NEAR(clampToInteger(overflowInt), maxInt, 1);
EXPECT_EQ(clampToInteger(underflowInt), minInt);
}
TEST(WTF, clampToIntegerDouble)
{
double maxInt = std::numeric_limits<int>::max();
double minInt = std::numeric_limits<int>::min();
double overflowInt = maxInt + 1;
double underflowInt = minInt - 1;
EXPECT_GT(overflowInt, maxInt);
EXPECT_LT(underflowInt, minInt);
EXPECT_EQ(clampToInteger(maxInt), maxInt);
EXPECT_EQ(clampToInteger(minInt), minInt);
EXPECT_EQ(clampToInteger(overflowInt), maxInt);
EXPECT_EQ(clampToInteger(underflowInt), minInt);
}
TEST(WTF, clampToFloat)
{
double maxFloat = std::numeric_limits<float>::max();
double minFloat = -maxFloat;
double overflowFloat = maxFloat * 1.1;
double underflowFloat = minFloat * 1.1;
EXPECT_GT(overflowFloat, maxFloat);
EXPECT_LT(underflowFloat, minFloat);
EXPECT_EQ(clampToFloat(maxFloat), maxFloat);
EXPECT_EQ(clampToFloat(minFloat), minFloat);
EXPECT_EQ(clampToFloat(overflowFloat), maxFloat);
EXPECT_EQ(clampToFloat(underflowFloat), minFloat);
EXPECT_EQ(clampToFloat(std::numeric_limits<float>::infinity()), maxFloat);
EXPECT_EQ(clampToFloat(-std::numeric_limits<float>::infinity()), minFloat);
}
TEST(WTF, clampToUnsignedLong)
{
if (sizeof(unsigned long) == sizeof(unsigned))
return;
unsigned long maxUnsigned = std::numeric_limits<unsigned>::max();
unsigned long overflowUnsigned = maxUnsigned + 1;
EXPECT_GT(overflowUnsigned, maxUnsigned);
EXPECT_EQ(clampTo<unsigned>(maxUnsigned), maxUnsigned);
EXPECT_EQ(clampTo<unsigned>(overflowUnsigned), maxUnsigned);
EXPECT_EQ(clampTo<unsigned>(-1), 0u);
}
TEST(WTF, clampToUnsignedLongLong)
{
unsigned long long maxUnsigned = std::numeric_limits<unsigned>::max();
unsigned long long overflowUnsigned = maxUnsigned + 1;
EXPECT_GT(overflowUnsigned, maxUnsigned);
EXPECT_EQ(clampTo<unsigned>(maxUnsigned), maxUnsigned);
EXPECT_EQ(clampTo<unsigned>(overflowUnsigned), maxUnsigned);
EXPECT_EQ(clampTo<unsigned>(-1), 0u);
}
#if !COMPILER(MSVC)
template<typename TargetType, typename SourceType>
static void testClampFloatingPointToFloatingPoint()
{
// No clamping.
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1.5)), static_cast<TargetType>(1.5));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1)), static_cast<TargetType>(-1));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1.5)), static_cast<TargetType>(-1.5));
// Explicit boundaries, clamped or not.
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-42), static_cast<SourceType>(-42.5)), static_cast<TargetType>(-42));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-43), static_cast<SourceType>(-42.5)), static_cast<TargetType>(static_cast<SourceType>(-42.5)));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(42), static_cast<SourceType>(41), static_cast<SourceType>(42.5)), static_cast<TargetType>(42));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(43), static_cast<SourceType>(41), static_cast<SourceType>(42.5)), static_cast<TargetType>(static_cast<SourceType>(42.5)));
// Integer bounds.
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max()) + 1), static_cast<TargetType>(std::numeric_limits<int32_t>::max()) + 1);
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int64_t>::max())), static_cast<TargetType>(std::numeric_limits<int64_t>::max()));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max()) + 1), static_cast<TargetType>(std::numeric_limits<int32_t>::max()) + 1);
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min())), static_cast<TargetType>(std::numeric_limits<int32_t>::min()));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int64_t>::min())), static_cast<TargetType>(std::numeric_limits<int64_t>::min()));
if (std::is_same<TargetType, double>::value && std::is_same<SourceType, float>::value) {
// If the source is float and target is double, the input of those cases has lost bits in float.
// In that case, we also round the expectation to float.
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max())), static_cast<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max())));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1));
} else {
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::max())), static_cast<TargetType>(std::numeric_limits<int32_t>::max()));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(std::numeric_limits<int32_t>::min()) - 1);
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<int32_t>::min()) - 1), static_cast<TargetType>(std::numeric_limits<int32_t>::min()) - 1);
}
// At the limit.
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<TargetType>::max()), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(-std::numeric_limits<TargetType>::max()), -std::numeric_limits<TargetType>::max());
// At Epsilon from the limit.
TargetType epsilon = std::numeric_limits<TargetType>::epsilon();
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<TargetType>::max() - epsilon), std::numeric_limits<TargetType>::max() - epsilon);
EXPECT_EQ(clampTo<TargetType>(-std::numeric_limits<TargetType>::max() + epsilon), -std::numeric_limits<TargetType>::max() + epsilon);
// Infinity.
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::infinity()), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(-std::numeric_limits<SourceType>::infinity()), -std::numeric_limits<TargetType>::max());
}
TEST(WTF, clampFloatingPointToFloatingPoint)
{
testClampFloatingPointToFloatingPoint<float, float>();
testClampFloatingPointToFloatingPoint<double, double>();
testClampFloatingPointToFloatingPoint<double, float>();
testClampFloatingPointToFloatingPoint<float, double>();
// Large double into smaller float.
EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max())), std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(-static_cast<double>(std::numeric_limits<float>::max())), -std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) + 1), std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(-static_cast<double>(std::numeric_limits<float>::max()) - 1), -std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(std::numeric_limits<double>::max()), std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(-std::numeric_limits<double>::max()), -std::numeric_limits<float>::max());
float floatEspilon = std::numeric_limits<float>::epsilon();
double doubleEspilon = std::numeric_limits<double>::epsilon();
EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) + doubleEspilon), std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) - doubleEspilon), std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) + floatEspilon), std::numeric_limits<float>::max());
EXPECT_EQ(clampTo<float>(static_cast<double>(std::numeric_limits<float>::max()) - floatEspilon), std::numeric_limits<float>::max() - floatEspilon);
}
#endif // !COMPILER(MSVC)
template<typename FloatingPointType>
static void testClampFloatingPointToInteger()
{
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(0)), 0);
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(1)), 1);
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(-1)), -1);
if (std::is_same<FloatingPointType, double>::value)
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) - 1.f), std::numeric_limits<int32_t>::max() - 1);
else
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) - 1.f), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max())), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
if (std::is_same<FloatingPointType, double>::value)
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) + 1.f), std::numeric_limits<int32_t>::min() + 1);
else
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) + 1.f), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min())), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) - 1.f), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint32_t>::max())), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint32_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint32_t>::min())), 0.f);
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::max())), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::min())), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int64_t>::min()) - 1.f), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint64_t>::max())), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint64_t>::max()) + 1.f), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<uint64_t>::min())), 0.f);
FloatingPointType epsilon = std::numeric_limits<FloatingPointType>::epsilon();
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) - epsilon), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::max()) + epsilon), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) - epsilon), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<int32_t>::min()) + epsilon), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(std::numeric_limits<FloatingPointType>::infinity())), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<FloatingPointType>(-std::numeric_limits<FloatingPointType>::infinity())), std::numeric_limits<int32_t>::min());
}
TEST(WTF, clampFloatToInt)
{
testClampFloatingPointToInteger<float>();
testClampFloatingPointToInteger<double>();
// 2**24 = 16777216, the largest integer representable exactly as float.
EXPECT_EQ(clampTo<int32_t>(static_cast<float>(16777215)), 16777215);
EXPECT_EQ(clampTo<int32_t>(static_cast<float>(16777216)), 16777216);
EXPECT_EQ(clampTo<int32_t>(static_cast<float>(16777217)), 16777216);
EXPECT_EQ(clampTo<int32_t>(static_cast<double>(16777216)), 16777216);
EXPECT_EQ(clampTo<int32_t>(static_cast<double>(16777217)), 16777217);
EXPECT_EQ(clampTo<int16_t>(static_cast<float>(16777215)), std::numeric_limits<int16_t>::max());
EXPECT_EQ(clampTo<int16_t>(static_cast<float>(16777216)), std::numeric_limits<int16_t>::max());
EXPECT_EQ(clampTo<int16_t>(static_cast<float>(16777217)), std::numeric_limits<int16_t>::max());
// 2**53 = 9007199254740992, the largest integer representable exactly as double.
EXPECT_EQ(clampTo<uint64_t>(static_cast<double>(9007199254740991)), static_cast<uint64_t>(9007199254740991));
EXPECT_EQ(clampTo<uint64_t>(static_cast<double>(9007199254740992)), static_cast<uint64_t>(9007199254740992));
EXPECT_EQ(clampTo<uint64_t>(static_cast<double>(9007199254740993)), static_cast<uint64_t>(9007199254740992));
EXPECT_EQ(clampTo<int32_t>(static_cast<double>(9007199254740991)), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<double>(9007199254740992)), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(static_cast<double>(9007199254740993)), std::numeric_limits<int32_t>::max());
// Test the double at the edge of max/min and max-1/min+1.
double intMax = static_cast<double>(std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(intMax), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMax, 0)), std::numeric_limits<int32_t>::max() - 1);
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMax, std::numeric_limits<double>::max())), std::numeric_limits<int32_t>::max());
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMax - 1., 0)), std::numeric_limits<int32_t>::max() - 2);
EXPECT_EQ(clampTo<int32_t>(intMax - 1), std::numeric_limits<int32_t>::max() - 1);
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMax - 1., std::numeric_limits<double>::max())), std::numeric_limits<int32_t>::max() - 1);
double intMin = static_cast<double>(std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(intMin), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMin, 0)), std::numeric_limits<int32_t>::min() + 1);
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMin, -std::numeric_limits<double>::max())), std::numeric_limits<int32_t>::min());
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMin + 1, 0)), std::numeric_limits<int32_t>::min() + 2);
EXPECT_EQ(clampTo<int32_t>(intMin + 1), std::numeric_limits<int32_t>::min() + 1);
EXPECT_EQ(clampTo<int32_t>(std::nextafter(intMin + 1, -std::numeric_limits<double>::max())), std::numeric_limits<int32_t>::min() + 1);
}
template<typename TargetType, typename SourceType>
static void testClampSameSignIntegers()
{
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1)), std::numeric_limits<TargetType>::is_signed ? static_cast<TargetType>(-1) : std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::min())), std::numeric_limits<TargetType>::min());
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max())), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::min()), std::numeric_limits<TargetType>::min());
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), std::numeric_limits<TargetType>::max());
}
TEST(WTF, clampSameSignIntegers)
{
testClampSameSignIntegers<char, char>();
testClampSameSignIntegers<unsigned char, unsigned char>();
testClampSameSignIntegers<char, int32_t>();
testClampSameSignIntegers<unsigned char, uint32_t>();
testClampSameSignIntegers<char, int64_t>();
testClampSameSignIntegers<unsigned char, uint64_t>();
testClampSameSignIntegers<int32_t, int32_t>();
testClampSameSignIntegers<uint32_t, uint32_t>();
testClampSameSignIntegers<int32_t, int64_t>();
testClampSameSignIntegers<uint32_t, uint64_t>();
testClampSameSignIntegers<int16_t, int64_t>();
testClampSameSignIntegers<uint16_t, uint64_t>();
}
template<typename TargetType, typename SourceType>
static void testClampUnsignedToSigned()
{
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) - 1), std::numeric_limits<TargetType>::max() - 1);
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max())), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) + 1), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max() - 1), std::numeric_limits<TargetType>::max());
}
TEST(WTF, clampUnsignedToSigned)
{
testClampUnsignedToSigned<char, unsigned char>();
testClampUnsignedToSigned<char, uint32_t>();
testClampUnsignedToSigned<int32_t, uint32_t>();
testClampUnsignedToSigned<int64_t, uint64_t>();
testClampUnsignedToSigned<int32_t, uint64_t>();
testClampUnsignedToSigned<int16_t, uint32_t>();
testClampUnsignedToSigned<int16_t, uint64_t>();
}
template<typename TargetType, typename SourceType>
static void testClampSignedToUnsigned()
{
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(0)), static_cast<TargetType>(0));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(1)), static_cast<TargetType>(1));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(-1)), static_cast<TargetType>(0));
if (sizeof(TargetType) < sizeof(SourceType)) {
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::min())), static_cast<TargetType>(0));
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) - 1), std::numeric_limits<TargetType>::max() - 1);
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max())), std::numeric_limits<TargetType>::max());
EXPECT_EQ(clampTo<TargetType>(static_cast<SourceType>(std::numeric_limits<TargetType>::max()) + 1), std::numeric_limits<TargetType>::max());
}
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::min()), static_cast<TargetType>(0));
if (sizeof(TargetType) < sizeof(SourceType))
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), std::numeric_limits<TargetType>::max());
else
EXPECT_EQ(clampTo<TargetType>(std::numeric_limits<SourceType>::max()), static_cast<TargetType>(std::numeric_limits<SourceType>::max()));
}
TEST(WTF, clampSignedToUnsigned)
{
testClampSignedToUnsigned<unsigned char, char>();
testClampSignedToUnsigned<unsigned char, int32_t>();
testClampSignedToUnsigned<uint32_t, int32_t>();
testClampSignedToUnsigned<uint64_t, int64_t>();
testClampSignedToUnsigned<uint32_t, int64_t>();
testClampSignedToUnsigned<uint16_t, int32_t>();
testClampSignedToUnsigned<uint16_t, int64_t>();
}
TEST(WTF, roundUpToPowerOfTwo)
{
EXPECT_EQ(WTF::roundUpToPowerOfTwo(UINT32_MAX), 0U);
EXPECT_EQ(WTF::roundUpToPowerOfTwo(1U << 31), (1U << 31));
EXPECT_EQ(WTF::roundUpToPowerOfTwo((1U << 31) + 1), 0U);
}
TEST(WTF, clz)
{
EXPECT_EQ(WTF::clz<int32_t>(1), 31U);
EXPECT_EQ(WTF::clz<int32_t>(42), 26U);
EXPECT_EQ(WTF::clz<uint32_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::clz<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 1U);
EXPECT_EQ(WTF::clz<uint32_t>(0), 32U);
EXPECT_EQ(WTF::clz<int8_t>(42), 2U);
EXPECT_EQ(WTF::clz<int8_t>(3), 6U);
EXPECT_EQ(WTF::clz<uint8_t>(static_cast<uint8_t>(-1)), 0U);
EXPECT_EQ(WTF::clz<uint8_t>(0), 8U);
EXPECT_EQ(WTF::clz<int64_t>(-1), 0U);
EXPECT_EQ(WTF::clz<int64_t>(1), 63U);
EXPECT_EQ(WTF::clz<int64_t>(3), 62U);
EXPECT_EQ(WTF::clz<uint64_t>(42), 58U);
EXPECT_EQ(WTF::clz<uint64_t>(0), 64U);
}
TEST(WTF, ctz)
{
EXPECT_EQ(WTF::ctz<int32_t>(1), 0U);
EXPECT_EQ(WTF::ctz<int32_t>(42), 1U);
EXPECT_EQ(WTF::ctz<uint32_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::ctz<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
EXPECT_EQ(WTF::ctz<uint32_t>(0), 32U);
EXPECT_EQ(WTF::ctz<int8_t>(42), 1U);
EXPECT_EQ(WTF::ctz<int8_t>(3), 0U);
EXPECT_EQ(WTF::ctz<uint8_t>(static_cast<uint8_t>(-1)), 0U);
EXPECT_EQ(WTF::ctz<uint8_t>(0), 8U);
EXPECT_EQ(WTF::ctz<int64_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::ctz<int64_t>(1), 0U);
EXPECT_EQ(WTF::ctz<int64_t>(3), 0U);
EXPECT_EQ(WTF::ctz<uint64_t>(42), 1U);
EXPECT_EQ(WTF::ctz<uint64_t>(0), 64U);
}
TEST(WTF, getLSBSet)
{
EXPECT_EQ(WTF::getLSBSet<int32_t>(1), 0U);
EXPECT_EQ(WTF::getLSBSet<int32_t>(42), 1U);
EXPECT_EQ(WTF::getLSBSet<uint32_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::getLSBSet<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
EXPECT_EQ(WTF::getLSBSet<int8_t>(42), 1U);
EXPECT_EQ(WTF::getLSBSet<int8_t>(3), 0U);
EXPECT_EQ(WTF::getLSBSet<uint8_t>(static_cast<uint8_t>(-1)), 0U);
EXPECT_EQ(WTF::getLSBSet<int64_t>(-1), 0U);
EXPECT_EQ(WTF::getLSBSet<int64_t>(1), 0U);
EXPECT_EQ(WTF::getLSBSet<int64_t>(3), 0U);
EXPECT_EQ(WTF::getLSBSet<uint64_t>(42), 1U);
}
TEST(WTF, getMSBSet)
{
EXPECT_EQ(WTF::getMSBSet<int32_t>(1), 0U);
EXPECT_EQ(WTF::getMSBSet<int32_t>(42), 5U);
EXPECT_EQ(WTF::getMSBSet<uint32_t>(static_cast<uint32_t>(-1)), 31U);
EXPECT_EQ(WTF::getMSBSet<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
EXPECT_EQ(WTF::getMSBSet<int8_t>(42), 5U);
EXPECT_EQ(WTF::getMSBSet<int8_t>(3), 1U);
EXPECT_EQ(WTF::getMSBSet<uint8_t>(static_cast<uint8_t>(-1)), 7U);
EXPECT_EQ(WTF::getMSBSet<int64_t>(-1), 63U);
EXPECT_EQ(WTF::getMSBSet<int64_t>(1), 0U);
EXPECT_EQ(WTF::getMSBSet<int64_t>(3), 1U);
EXPECT_EQ(WTF::getMSBSet<uint64_t>(42), 5U);
}
TEST(WTF, clzConstexpr)
{
EXPECT_EQ(WTF::clzConstexpr<int32_t>(1), 31U);
EXPECT_EQ(WTF::clzConstexpr<int32_t>(42), 26U);
EXPECT_EQ(WTF::clzConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::clzConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 1U);
EXPECT_EQ(WTF::clzConstexpr<uint32_t>(0), 32U);
EXPECT_EQ(WTF::clzConstexpr<int8_t>(42), 2U);
EXPECT_EQ(WTF::clzConstexpr<int8_t>(3), 6U);
EXPECT_EQ(WTF::clzConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 0U);
EXPECT_EQ(WTF::clzConstexpr<uint8_t>(0), 8U);
EXPECT_EQ(WTF::clzConstexpr<int64_t>(-1), 0U);
EXPECT_EQ(WTF::clzConstexpr<int64_t>(1), 63U);
EXPECT_EQ(WTF::clzConstexpr<int64_t>(3), 62U);
EXPECT_EQ(WTF::clzConstexpr<uint64_t>(42), 58U);
EXPECT_EQ(WTF::clzConstexpr<uint64_t>(0), 64U);
}
TEST(WTF, ctzConstexpr)
{
EXPECT_EQ(WTF::ctzConstexpr<int32_t>(1), 0U);
EXPECT_EQ(WTF::ctzConstexpr<int32_t>(42), 1U);
EXPECT_EQ(WTF::ctzConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::ctzConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
EXPECT_EQ(WTF::ctzConstexpr<uint32_t>(0), 32U);
EXPECT_EQ(WTF::ctzConstexpr<int8_t>(42), 1U);
EXPECT_EQ(WTF::ctzConstexpr<int8_t>(3), 0U);
EXPECT_EQ(WTF::ctzConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 0U);
EXPECT_EQ(WTF::ctzConstexpr<uint8_t>(0), 8U);
EXPECT_EQ(WTF::ctzConstexpr<int64_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::ctzConstexpr<int64_t>(1), 0U);
EXPECT_EQ(WTF::ctzConstexpr<int64_t>(3), 0U);
EXPECT_EQ(WTF::ctzConstexpr<uint64_t>(42), 1U);
EXPECT_EQ(WTF::ctzConstexpr<uint64_t>(0), 64U);
}
TEST(WTF, getLSBSetConstexpr)
{
EXPECT_EQ(WTF::getLSBSetConstexpr<int32_t>(1), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<int32_t>(42), 1U);
EXPECT_EQ(WTF::getLSBSetConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
EXPECT_EQ(WTF::getLSBSetConstexpr<int8_t>(42), 1U);
EXPECT_EQ(WTF::getLSBSetConstexpr<int8_t>(3), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<int64_t>(-1), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<int64_t>(1), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<int64_t>(3), 0U);
EXPECT_EQ(WTF::getLSBSetConstexpr<uint64_t>(42), 1U);
}
TEST(WTF, getMSBSetConstexpr)
{
EXPECT_EQ(WTF::getMSBSetConstexpr<int32_t>(1), 0U);
EXPECT_EQ(WTF::getMSBSetConstexpr<int32_t>(42), 5U);
EXPECT_EQ(WTF::getMSBSetConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 31U);
EXPECT_EQ(WTF::getMSBSetConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
EXPECT_EQ(WTF::getMSBSetConstexpr<int8_t>(42), 5U);
EXPECT_EQ(WTF::getMSBSetConstexpr<int8_t>(3), 1U);
EXPECT_EQ(WTF::getMSBSetConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 7U);
EXPECT_EQ(WTF::getMSBSetConstexpr<int64_t>(-1), 63U);
EXPECT_EQ(WTF::getMSBSetConstexpr<int64_t>(1), 0U);
EXPECT_EQ(WTF::getMSBSetConstexpr<int64_t>(3), 1U);
EXPECT_EQ(WTF::getMSBSetConstexpr<uint64_t>(42), 5U);
}
} // namespace TestWebKitAPI