blob: bb0be6a3fa6d750ee6fb4e24ecdf13e23b4b7453 [file] [log] [blame]
/*
* Copyright (C) 2012 Intel Corporation
*
* 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 "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace WTF {
TEST(MathExtrasTest, Lrint) {
EXPECT_EQ(-8, lrint(-7.5));
EXPECT_EQ(-8, lrint(-8.5));
EXPECT_EQ(0, lrint(-0.5));
EXPECT_EQ(0, lrint(0.5));
EXPECT_EQ(0, lrint(-0.5));
EXPECT_EQ(1, lrint(1.3));
EXPECT_EQ(2, lrint(1.7));
EXPECT_EQ(0, lrint(0));
EXPECT_EQ(0, lrint(-0));
if (sizeof(long int) == 8) {
// Largest double number with 0.5 precision and one halfway rounding case
// below.
EXPECT_EQ(pow(2.0, 52), lrint(pow(2.0, 52) - 0.5));
EXPECT_EQ(pow(2.0, 52) - 2, lrint(pow(2.0, 52) - 1.5));
// Smallest double number with 0.5 precision and one halfway rounding case
// above.
EXPECT_EQ(-pow(2.0, 52), lrint(-pow(2.0, 52) + 0.5));
EXPECT_EQ(-pow(2.0, 52) + 2, lrint(-pow(2.0, 52) + 1.5));
}
}
TEST(MathExtrasTest, clampToIntLong) {
if (sizeof(long) == sizeof(int))
return;
long max_int = std::numeric_limits<int>::max();
long min_int = std::numeric_limits<int>::min();
long overflow_int = max_int + 1;
long underflow_int = min_int - 1;
EXPECT_GT(overflow_int, max_int);
EXPECT_LT(underflow_int, min_int);
EXPECT_EQ(max_int, clampTo<int>(max_int));
EXPECT_EQ(min_int, clampTo<int>(min_int));
EXPECT_EQ(max_int, clampTo<int>(overflow_int));
EXPECT_EQ(min_int, clampTo<int>(underflow_int));
}
TEST(MathExtrasTest, clampToIntLongLong) {
int64_t max_int = std::numeric_limits<int>::max();
int64_t min_int = std::numeric_limits<int>::min();
int64_t overflow_int = max_int + 1;
int64_t underflow_int = min_int - 1;
EXPECT_GT(overflow_int, max_int);
EXPECT_LT(underflow_int, min_int);
EXPECT_EQ(max_int, clampTo<int>(max_int));
EXPECT_EQ(min_int, clampTo<int>(min_int));
EXPECT_EQ(max_int, clampTo<int>(overflow_int));
EXPECT_EQ(min_int, clampTo<int>(underflow_int));
}
TEST(MathExtrasTest, clampToIntFloat) {
float max_int = static_cast<float>(std::numeric_limits<int>::max());
float min_int = static_cast<float>(std::numeric_limits<int>::min());
float overflow_int = max_int * 1.1f;
float underflow_int = min_int * 1.1f;
EXPECT_GT(overflow_int, max_int);
EXPECT_LT(underflow_int, min_int);
EXPECT_EQ(max_int, clampTo<int>(max_int));
EXPECT_EQ(min_int, clampTo<int>(min_int));
EXPECT_EQ(max_int, clampTo<int>(overflow_int));
EXPECT_EQ(min_int, clampTo<int>(underflow_int));
// This value and the value one greater are typically represented the same
// way when stored in a 32-bit float. Make sure clamping does not cause us
// to erroneously jump to the larger value.
int near_float_precision_limit = 2147483520;
EXPECT_EQ(near_float_precision_limit,
clampTo<int>(static_cast<float>(near_float_precision_limit), 0,
near_float_precision_limit + 1));
EXPECT_EQ(-near_float_precision_limit,
clampTo<int>(static_cast<float>(-near_float_precision_limit),
-near_float_precision_limit - 1, 0));
}
TEST(MathExtrasTest, clampToIntDouble) {
int max_int = std::numeric_limits<int>::max();
int min_int = std::numeric_limits<int>::min();
double almost_overflow_int = max_int - 0.5;
double overflow_int = max_int + 0.5;
double almost_underflow_int = min_int + 0.5;
double underflow_int = min_int - 0.5;
EXPECT_LT(almost_overflow_int, max_int);
EXPECT_GT(overflow_int, max_int);
EXPECT_GT(almost_underflow_int, min_int);
EXPECT_LT(underflow_int, min_int);
EXPECT_EQ(max_int, clampTo<int>(static_cast<double>(max_int)));
EXPECT_EQ(min_int, clampTo<int>(static_cast<double>(min_int)));
EXPECT_EQ(max_int - 1, clampTo<int>(almost_overflow_int));
EXPECT_EQ(max_int, clampTo<int>(overflow_int));
EXPECT_EQ(min_int + 1, clampTo<int>(almost_underflow_int));
EXPECT_EQ(min_int, clampTo<int>(underflow_int));
}
TEST(MathExtrasTest, clampToFloatDouble) {
double max_float = std::numeric_limits<float>::max();
double min_float = -max_float;
double overflow_float = max_float * 1.1;
double underflow_float = min_float * 1.1;
EXPECT_GT(overflow_float, max_float);
EXPECT_LT(underflow_float, min_float);
EXPECT_EQ(max_float, clampTo<float>(max_float));
EXPECT_EQ(min_float, clampTo<float>(min_float));
EXPECT_EQ(max_float, clampTo<float>(overflow_float));
EXPECT_EQ(min_float, clampTo<float>(underflow_float));
EXPECT_EQ(max_float, clampTo<float>(std::numeric_limits<float>::infinity()));
EXPECT_EQ(min_float, clampTo<float>(-std::numeric_limits<float>::infinity()));
}
TEST(MathExtrasTest, clampToDouble) {
EXPECT_EQ(0.0, clampTo<double>(0));
EXPECT_EQ(0.0, clampTo<double>(0.0f));
EXPECT_EQ(0.0, clampTo<double>(0ULL));
EXPECT_EQ(3.5,
clampTo<double>(std::numeric_limits<uint64_t>::max(), 0.0, 3.5));
}
TEST(MathExtrasText, clampToLongLongDouble) {
double overflow_ll =
static_cast<double>(std::numeric_limits<int64_t>::max()) * 2;
EXPECT_EQ(std::numeric_limits<int64_t>::max(), clampTo<int64_t>(overflow_ll));
EXPECT_EQ(std::numeric_limits<int64_t>::min(),
clampTo<int64_t>(-overflow_ll));
}
TEST(MathExtrasText, clampToUnsignedLongLongDouble) {
double overflow_ull =
static_cast<double>(std::numeric_limits<uint64_t>::max()) * 2;
EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
clampTo<uint64_t>(overflow_ull));
EXPECT_EQ(std::numeric_limits<uint64_t>::min(),
clampTo<uint64_t>(-overflow_ull));
}
TEST(MathExtrasTest, clampToUnsignedUint32) {
if (sizeof(uint32_t) == sizeof(unsigned))
return;
uint32_t max_unsigned = std::numeric_limits<unsigned>::max();
uint32_t overflow_unsigned = max_unsigned + 1;
EXPECT_GT(overflow_unsigned, max_unsigned);
EXPECT_EQ(max_unsigned, clampTo<unsigned>(max_unsigned));
EXPECT_EQ(max_unsigned, clampTo<unsigned>(overflow_unsigned));
EXPECT_EQ(0u, clampTo<unsigned>(-1));
}
TEST(MathExtrasTest, clampToUnsignedUint64) {
uint64_t max_unsigned = std::numeric_limits<unsigned>::max();
uint64_t overflow_unsigned = max_unsigned + 1;
EXPECT_GT(overflow_unsigned, max_unsigned);
EXPECT_EQ(max_unsigned, clampTo<unsigned>(max_unsigned));
EXPECT_EQ(max_unsigned, clampTo<unsigned>(overflow_unsigned));
EXPECT_EQ(0u, clampTo<unsigned>(-1));
}
TEST(MathExtrasTest, clampToLongLongUnsignedLongLong) {
int64_t max_long_long_ll = std::numeric_limits<int64_t>::max();
uint64_t max_long_long_ull = max_long_long_ll;
uint64_t overflow_long_long = max_long_long_ull + 1;
EXPECT_GT(overflow_long_long, max_long_long_ull);
EXPECT_EQ(max_long_long_ll, clampTo<int64_t>(max_long_long_ull));
EXPECT_EQ(max_long_long_ll - 1, clampTo<int64_t>(max_long_long_ull - 1));
EXPECT_EQ(max_long_long_ll, clampTo<int64_t>(overflow_long_long));
EXPECT_EQ(-3LL, clampTo<int64_t>(2ULL, -5LL, -3LL));
}
TEST(MathExtrasTest, clampToUnsignedLongLongInt) {
EXPECT_EQ(0ULL, clampTo<uint64_t>(-1));
EXPECT_EQ(0ULL, clampTo<uint64_t>(0));
EXPECT_EQ(1ULL, clampTo<uint64_t>(1));
}
TEST(MathExtrasTest, clampToUnsignedLongLongUnsignedLongLong) {
EXPECT_EQ(0ULL, clampTo<uint64_t>(0ULL));
EXPECT_EQ(1ULL, clampTo<uint64_t>(0ULL, 1ULL, 2ULL));
EXPECT_EQ(2ULL, clampTo<uint64_t>(3ULL, 1ULL, 2ULL));
EXPECT_EQ(0xFFFFFFFFFFFFFFF5ULL, clampTo<uint64_t>(0xFFFFFFFFFFFFFFF5ULL));
}
// Make sure that various +-inf cases are handled properly (they weren't
// by default on older VS).
TEST(MathExtrasTest, infinityMath) {
double pos_inf = std::numeric_limits<double>::infinity();
double neg_inf = -std::numeric_limits<double>::infinity();
double nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_EQ(M_PI_4, atan2(pos_inf, pos_inf));
EXPECT_EQ(3.0 * M_PI_4, atan2(pos_inf, neg_inf));
EXPECT_EQ(-M_PI_4, atan2(neg_inf, pos_inf));
EXPECT_EQ(-3.0 * M_PI_4, atan2(neg_inf, neg_inf));
EXPECT_EQ(0.0, fmod(0.0, pos_inf));
EXPECT_EQ(7.0, fmod(7.0, pos_inf));
EXPECT_EQ(-7.0, fmod(-7.0, pos_inf));
EXPECT_EQ(0.0, fmod(0.0, neg_inf));
EXPECT_EQ(7.0, fmod(7.0, neg_inf));
EXPECT_EQ(-7.0, fmod(-7.0, neg_inf));
EXPECT_EQ(1.0, pow(5.0, 0.0));
EXPECT_EQ(1.0, pow(-5.0, 0.0));
EXPECT_EQ(1.0, pow(nan, 0.0));
}
} // namespace WTF