1 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 2 // See https://llvm.org/LICENSE.txt for license information. 3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 5 // Do not attempt to use LLVM ostream etc from gtest. 6 // #define GTEST_NO_LLVM_SUPPORT 1 7 8 #include "../nsan.h" 9 #include "gtest/gtest.h" 10 11 #include <cmath> 12 13 namespace __nsan { 14 15 template <typename FT, auto next> void TestFT() { 16 // Basic local tests anchored at 0.0. 17 ASSERT_EQ(GetULPDiff<FT>(0.0, 0.0), 0); 18 ASSERT_EQ(GetULPDiff<FT>(-0.0, 0.0), 0); 19 ASSERT_EQ(GetULPDiff<FT>(next(-0.0, -1.0), 0.0), 1); 20 ASSERT_EQ(GetULPDiff<FT>(next(0.0, 1.0), -0.0), 1); 21 ASSERT_EQ(GetULPDiff<FT>(next(-0.0, -1.0), next(0.0, 1.0)), 2); 22 // Basic local tests anchored at 2.0. 23 ASSERT_EQ(GetULPDiff<FT>(next(2.0, 1.0), 2.0), 1); 24 ASSERT_EQ(GetULPDiff<FT>(next(2.0, 3.0), 2.0), 1); 25 ASSERT_EQ(GetULPDiff<FT>(next(2.0, 1.0), next(2.0, 3.0)), 2); 26 27 ASSERT_NE(GetULPDiff<FT>(-0.01, 0.01), kMaxULPDiff); 28 29 // Basic local tests anchored at a random number. 30 const FT X = 4863.5123; 31 const FT To = 2 * X; 32 FT Y = X; 33 ASSERT_EQ(GetULPDiff<FT>(X, Y), 0); 34 ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 0); 35 Y = next(Y, To); 36 ASSERT_EQ(GetULPDiff<FT>(X, Y), 1); 37 ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 1); 38 Y = next(Y, To); 39 ASSERT_EQ(GetULPDiff<FT>(X, Y), 2); 40 ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 2); 41 Y = next(Y, To); 42 ASSERT_EQ(GetULPDiff<FT>(X, Y), 3); 43 ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 3); 44 45 // Values with larger differences. 46 static constexpr const __sanitizer::u64 MantissaSize = 47 __sanitizer::u64{1} << FTInfo<FT>::kMantissaBits; 48 ASSERT_EQ(GetULPDiff<FT>(1.0, next(2.0, 1.0)), MantissaSize - 1); 49 ASSERT_EQ(GetULPDiff<FT>(1.0, 2.0), MantissaSize); 50 ASSERT_EQ(GetULPDiff<FT>(1.0, next(2.0, 3.0)), MantissaSize + 1); 51 ASSERT_EQ(GetULPDiff<FT>(1.0, 3.0), (3 * MantissaSize) / 2); 52 } 53 54 TEST(NSanTest, Float) { TestFT<float, nextafterf>(); } 55 56 TEST(NSanTest, Double) { 57 TestFT<double, static_cast<double (*)(double, double)>(nextafter)>(); 58 } 59 60 TEST(NSanTest, Float128) { 61 // Very basic tests. FIXME: improve when we have nextafter<__float128>. 62 ASSERT_EQ(GetULPDiff<__float128>(0.0, 0.0), 0); 63 ASSERT_EQ(GetULPDiff<__float128>(-0.0, 0.0), 0); 64 ASSERT_NE(GetULPDiff<__float128>(-0.01, 0.01), kMaxULPDiff); 65 } 66 67 } // end namespace __nsan 68