95 #if defined(__x86_64__)
96 #include <x86intrin.h>
101 #if defined(__x86_64__) || defined(_M_AMD64)
103 #include <emmintrin.h>
104 #include <immintrin.h>
105 #include <xmmintrin.h>
109 #if defined(__clang__)
110 #pragma STDC FENV_ACCESS ON
116 static inline double AddUp(
double a,
double b) {
return a +
b; }
117 static inline double AddDown(
double a,
double b) {
return a +
b; }
123 std::fesetround(new_mode);
135 static inline double AddUp(
double a,
double b) {
176 constexpr
int kRoundingModeMask = 0x6000;
177 constexpr
int kRoundingModeShift = 3;
179 (mode << kRoundingModeShift));
197 static inline double AddUp(
double a,
double b) {
218 static inline double AddUp(
double a,
double b) {
219 const __m128d x = _mm_set_sd(
a);
220 const __m128d y = _mm_set_sd(
b);
221 const __m128d result =
222 _mm_add_round_sd(x, y, (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC));
223 return _mm_cvtsd_f64(result);
226 static inline double AddDown(
double a,
double b) {
227 const __m128d x = _mm_set_sd(
a);
228 const __m128d y = _mm_set_sd(
b);
229 const __m128d result =
230 _mm_add_round_sd(x, y, (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC));
231 return _mm_cvtsd_f64(result);
236 static inline double AddUp(
double a,
double b) {
return 0.0; }
237 static inline double AddDown(
double a,
double b) {
return 0.0; }
256 std::chrono::steady_clock::time_point begin =
257 std::chrono::steady_clock::now();
261 std::chrono::steady_clock::time_point
end = std::chrono::steady_clock::now();
262 double time_in_nanos =
263 std::chrono::duration_cast<std::chrono::nanoseconds>(
end - begin).count();
264 printf(
"%g,[,%20.14f,%20.14f,]\n", time_in_nanos / n, result.
lb, result.
ub);
271 template <
typename Impl>
273 const double max = n;
276 for (
double d = 0.0; d <=
max; d += 1.0) {
277 l = Impl::AddDown(l, d);
278 u = Impl::AddUp(u, d);
302 template <
typename Impl>
307 for (
int i = 0; i <= n; ++i) {
308 const double d = std::sqrt(i);
309 l = Impl::AddDown(l, d);
310 u = Impl::AddUp(u, d);
320 #define BENCHMARK(fn, n) \
322 printf("%s,", #fn); \
328 printf(
"Warning: x86-64 instrinsics not supported.\n");
330 #if !defined(__AVX512F__)
331 printf(
"Warning: AVX512F not supported.\n");
333 const int n = 1'000'000'000;
334 printf(
"Name,ns/it,result\n");
LowLevelRoundingScope(int new_mode)
StdRoundingScope(int new_mode)
template Interval SumOfSquareRoots< RoundToNearestEven >(int)
template Interval SumOfIntegers< Avx512Rounding >(int)
Interval SumOfIntegers(int n)
void Runner(IntervalFunction f, int n)
template Interval SumOfIntegers< LowLevelRounding >(int)
template Interval SumOfIntegers< RoundToNearestEven >(int)
template Interval SumOfSquareRoots< StdRounding >(int)
template Interval SumOfSquareRoots< Avx512Rounding >(int)
Interval(* IntervalFunction)(int n)
template Interval SumOfIntegers< StdRounding >(int)
Interval SumOfSquareRoots(int n)
unsigned int GetFloatingPointControlRegister()
void SetRoundingMode(int status, int mode)
template Interval SumOfSquareRoots< LowLevelRounding >(int)
void SetFloatingPointControlRegister(unsigned int status)
std::optional< int64_t > end
static double AddDown(double a, double b)
static double AddUp(double a, double b)
Interval(double l, double u)
static double AddDown(double a, double b)
static double AddUp(double a, double b)
static double AddDown(double a, double b)
static double AddUp(double a, double b)
static double AddDown(double a, double b)
static double AddUp(double a, double b)