]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/experimental/simd/tests/bits/ulp.h
1 // Copyright (C) 2020-2022 Free Software Foundation, Inc.
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
22 #include <experimental/simd>
23 #include <type_traits>
28 template <typename T
, typename R
= typename
T::value_type
>
34 value_type_impl(float);
37 using value_type_t
= decltype(value_type_impl
<T
>(int()));
41 ulp_distance(const T
& val_
, const T
& ref_
)
43 if constexpr (std::is_floating_point_v
<value_type_t
<T
>>)
45 const int fp_exceptions
= std::fetestexcept(FE_ALL_EXCEPT
);
52 using std::fpclassify
;
58 using std::experimental::where
;
59 using TT
= value_type_t
<T
>;
61 where(ref
== 0, val
) = abs(val
);
62 where(ref
== 0, diff
) = 1;
63 where(ref
== 0, ref
) = std::__norm_min_v
<TT
>;
64 where(isinf(ref
) && ref
== val
, ref
)
65 = 0; // where(val_ == ref_) = 0 below will fix it up
67 where(val
== 0, ref
) = abs(ref
);
68 where(val
== 0, diff
) += 1;
69 where(val
== 0, val
) = std::__norm_min_v
<TT
>;
71 using I
= decltype(fpclassify(std::declval
<T
>()));
74 // lower bound for exp must be min_exponent to scale the resulting
75 // difference from a denormal correctly
76 exp
= max(exp
, I(std::__min_exponent_v
<TT
>));
77 diff
+= ldexp(abs(ref
- val
), std::__digits_v
<TT
> - exp
);
78 where(val_
== ref_
|| (isnan(val_
) && isnan(ref_
)), diff
) = T();
79 std::feclearexcept(FE_ALL_EXCEPT
^ fp_exceptions
);
93 ulp_distance_signed(const T
& _val
, const T
& _ref
)
96 return copysign(ulp_distance(_val
, _ref
), _val
- _ref
);