gcc/libstdc++-v3/testsuite/experimental/simd/tests/bits/mathreference.h
2024-01-03 12:19:35 +01:00

163 lines
4.1 KiB
C++

// Copyright (C) 2020-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef SIMD_TESTS_BITS_MATHREFERENCE_H_
#define SIMD_TESTS_BITS_MATHREFERENCE_H_
#include <tuple>
#include <utility>
#include <cstdio>
template <typename T>
struct SincosReference
{
T x, s, c;
std::tuple<const T &, const T &, const T &>
as_tuple() const
{ return std::tie(x, s, c); }
};
template <typename T>
struct Reference {
T x, ref;
std::tuple<const T &, const T &>
as_tuple() const
{ return std::tie(x, ref); }
};
template <typename T>
struct Array
{
std::size_t size_;
const T *data_;
Array()
: size_(0), data_(nullptr) {}
Array(size_t s, const T *p)
: size_(s), data_(p) {}
const T*
begin() const
{ return data_; }
const T*
end() const
{ return data_ + size_; }
std::size_t
size() const
{ return size_; }
};
namespace function {
struct sincos{ static constexpr const char *const str = "sincos"; };
struct atan { static constexpr const char *const str = "atan"; };
struct asin { static constexpr const char *const str = "asin"; };
struct acos { static constexpr const char *const str = "acos"; };
struct log { static constexpr const char *const str = "ln"; };
struct log2 { static constexpr const char *const str = "log2"; };
struct log10 { static constexpr const char *const str = "log10"; };
}
template <class F>
struct testdatatype_for_function
{
template <class T>
using type = Reference<T>;
};
template <>
struct testdatatype_for_function<function::sincos>
{
template <class T>
using type = SincosReference<T>;
};
template <class F, class T>
using testdatatype_for_function_t
= typename testdatatype_for_function<F>::template type<T>;
template<typename T>
struct StaticDeleter
{
const T *ptr;
StaticDeleter(const T *p)
: ptr(p) {}
~StaticDeleter()
{ delete[] ptr; }
};
template <class F, class T>
inline std::string filename()
{
static_assert(std::is_floating_point<T>::value, "");
static const auto cache
= std::string("reference-") + F::str
+ (sizeof(T) == 4 && std::__digits_v<T> == 24
&& std::__max_exponent_v<T> == 128
? "-sp"
: (sizeof(T) == 8
&& std::__digits_v<T> == 53
&& std::__max_exponent_v<T> == 1024
? "-dp"
: (sizeof(T) == 16 && std::__digits_v<T> == 64
&& std::__max_exponent_v<T> == 16384
? "-ep"
: (sizeof(T) == 16 && std::__digits_v<T> == 113
&& std::__max_exponent_v<T> == 16384
? "-qp"
: "-unknown"))))
+ ".dat";
return cache;
}
template <class Fun, class T, class Ref = testdatatype_for_function_t<Fun, T>>
Array<Ref>
referenceData()
{
static Array<Ref> data;
if (data.data_ == nullptr)
{
FILE* file = std::fopen(filename<Fun, T>().c_str(), "rb");
if (file)
{
std::fseek(file, 0, SEEK_END);
const size_t size = std::ftell(file) / sizeof(Ref);
std::rewind(file);
auto mem = new Ref[size];
static StaticDeleter<Ref> _cleanup(data.data_);
data.size_ = std::fread(mem, sizeof(Ref), size, file);
data.data_ = mem;
std::fclose(file);
}
else
{
__builtin_fprintf(
stderr,
"%s:%d: the reference data %s does not exist in the current "
"working directory.\n",
__FILE__, __LINE__, filename<Fun, T>().c_str());
__builtin_abort();
}
}
return data;
}
#endif // SIMD_TESTS_BITS_MATHREFERENCE_H_