blob: 9a516f9069ce684590d7aa7bb1d7e46ffaeeebfa [file] [log] [blame]
//===-- Common utility class for differential analysis --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "src/__support/FPUtil/FPBits.h"
#include "utils/testutils/StreamWrapper.h"
#include "utils/testutils/Timer.h"
namespace __llvm_libc {
namespace testing {
template <typename T> class SingleInputSingleOutputDiff {
using FPBits = fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
static constexpr UIntType MSBit = UIntType(1) << (8 * sizeof(UIntType) - 1);
static constexpr UIntType UIntMax = (MSBit - 1) + MSBit;
public:
typedef T Func(T);
static void runDiff(Func myFunc, Func otherFunc, const char *logFile) {
UIntType diffCount = 0;
testutils::OutputFileStream log(logFile);
log << "Starting diff for values from 0 to " << UIntMax << '\n'
<< "Only differing results will be logged.\n\n";
for (UIntType bits = 0;; ++bits) {
T x = T(FPBits(bits));
T myResult = myFunc(x);
T otherResult = otherFunc(x);
UIntType myBits = FPBits(myResult).uintval();
UIntType otherBits = FPBits(otherResult).uintval();
if (myBits != otherBits) {
++diffCount;
log << " Input: " << bits << " (" << x << ")\n"
<< " My result: " << myBits << " (" << myResult << ")\n"
<< "Other result: " << otherBits << " (" << otherResult << ")\n"
<< '\n';
}
if (bits == UIntMax)
break;
}
log << "Total number of differing results: " << diffCount << '\n';
}
static void runPerf(Func myFunc, Func otherFunc, const char *logFile) {
auto runner = [](Func func) {
volatile T result;
for (UIntType bits = 0;; ++bits) {
T x = T(FPBits(bits));
result = func(x);
if (bits == UIntMax)
break;
}
};
testutils::OutputFileStream log(logFile);
Timer timer;
timer.start();
runner(myFunc);
timer.stop();
log << " Run time of my function: " << timer.nanoseconds() << " ns \n";
timer.start();
runner(otherFunc);
timer.stop();
log << "Run time of other function: " << timer.nanoseconds() << " ns \n";
}
};
} // namespace testing
} // namespace __llvm_libc
#define SINGLE_INPUT_SINGLE_OUTPUT_DIFF(T, myFunc, otherFunc, filename) \
int main() { \
__llvm_libc::testing::SingleInputSingleOutputDiff<T>::runDiff( \
&myFunc, &otherFunc, filename); \
return 0; \
}
#define SINGLE_INPUT_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \
int main() { \
__llvm_libc::testing::SingleInputSingleOutputDiff<T>::runPerf( \
&myFunc, &otherFunc, filename); \
return 0; \
}