blob: d6a1965662b1e001111ce229db258f716a75c94e [file] [log] [blame]
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <math.h>
#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/half_float.h"
namespace gfx {
class HalfFloatTest : public testing::Test {
public:
union FloatUIntUnion {
// this must come first for the initializations below to work
uint32_t fUInt;
float fFloat;
};
// Convert an IEEE 754 half-float to a float value
// that we can do math on.
float FromHalfFloat(HalfFloat half_float) {
int sign = (half_float & 0x8000) ? -1 : 1;
int exponent = (half_float >> 10) & 0x1F;
int fraction = half_float & 0x3FF;
if (exponent == 0) {
return powf(2.0f, -24.0f) * fraction;
} else if (exponent == 0x1F) {
return sign * 1000000000000.0f;
} else {
return pow(2.0f, exponent - 25) * (0x400 + fraction);
}
}
HalfFloat ConvertTruth(float f) {
if (f < 0.0)
return 0x8000 | ConvertTruth(-f);
int max = 0x8000;
int min = 0;
while (max - min > 1) {
int mid = (min + max) >> 1;
if (FromHalfFloat(mid) > f) {
max = mid;
} else {
min = mid;
}
}
float low = FromHalfFloat(min);
float high = FromHalfFloat(min + 1);
if (f - low <= high - f) {
return min;
} else {
return min + 1;
}
}
HalfFloat Convert(float f) {
HalfFloat ret;
FloatToHalfFloat(&f, &ret, 1);
return ret;
}
};
TEST_F(HalfFloatTest, NoCrashTest) {
Convert(nanf(""));
Convert(1.0E30f);
Convert(-1.0E30f);
Convert(1.0E-30f);
Convert(-1.0E-30f);
}
TEST_F(HalfFloatTest, SimpleTest) {
static float test[] = {
0.0f, 1.0f, 10.0f, 1000.0f, 65503.0f,
1.0E-3f, 1.0E-6f, 1.0E-20f, 1.0E-44f,
};
for (size_t i = 0; i < base::size(test); i++) {
EXPECT_EQ(ConvertTruth(test[i]), Convert(test[i])) << " float = "
<< test[i];
if (test[i] != 0.0) {
EXPECT_EQ(ConvertTruth(-test[i]), Convert(-test[i])) << " float = "
<< -test[i];
}
}
}
} // namespace