ROOT  6.06/09
Reference Guide
ulp.h
Go to the documentation of this file.
1 /* This file is part of the Vc library. {{{
2 
3  Copyright (C) 2011-2012 Matthias Kretz <kretz@kde.org>
4 
5  Vc is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as
7  published by the Free Software Foundation, either version 3 of
8  the License, or (at your option) any later version.
9 
10  Vc is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with Vc. If not, see <http://www.gnu.org/licenses/>.
17 
18 }}}*/
19 
20 #ifndef TESTS_ULP_H
21 #define TESTS_ULP_H
22 
23 #include <Vc/Vc>
24 #include <Vc/limits>
25 
26 #ifdef VC_MSVC
27 namespace std
28 {
29  static inline bool isnan(float x) { return _isnan(x); }
30  static inline bool isnan(double x) { return _isnan(x); }
31 } // namespace std
32 #endif
33 
34 template<typename T> static T ulpDiffToReference(T val, T ref)
35 {
36  if (val == ref || (std::isnan(val) && std::isnan(ref))) {
37  return 0;
38  }
39  if (ref == T(0)) {
41  }
42  if (val == T(0)) {
44  }
45 
46  int exp;
47  /*tmp = */ frexp(ref, &exp); // ref == tmp * 2 ^ exp => tmp == ref * 2 ^ -exp
48  // tmp is now in the range [0.5, 1.0[
49  // now we want to know how many times we can fit 2^-numeric_limits<T>::digits between tmp and
50  // val * 2 ^ -exp
51  return ldexp(std::abs(ref - val), std::numeric_limits<T>::digits - exp);
52 }
53 template<typename T> static T ulpDiffToReferenceSigned(T val, T ref)
54 {
55  return ulpDiffToReference(val, ref) * (val - ref < 0 ? -1 : 1);
56 }
57 
58 template<typename T> struct _Ulp_ExponentVector { typedef Vc::int_v Type; };
59 template<> struct _Ulp_ExponentVector<Vc::sfloat_v> { typedef Vc::short_v Type; };
60 
61 template<typename _T> static Vc::Vector<_T> ulpDiffToReference(const Vc::Vector<_T> &_val, const Vc::Vector<_T> &_ref)
62 {
63  using namespace Vc;
64  typedef Vector<_T> V;
65  typedef typename V::EntryType T;
66  typedef typename V::Mask M;
67 
68  V val = _val;
69  V ref = _ref;
70 
71  V diff = V::Zero();
72 
73  M zeroMask = ref == V::Zero();
74  val (zeroMask)= abs(val);
75  ref (zeroMask)= std::numeric_limits<V>::min();
76  diff (zeroMask)= V::One();
77  zeroMask = val == V::Zero();
78  ref (zeroMask)= abs(ref);
79  val (zeroMask)= std::numeric_limits<V>::min();
80  diff (zeroMask)+= V::One();
81 
83  frexp(ref, &exp);
84  diff += ldexp(abs(ref - val), std::numeric_limits<T>::digits - exp);
85  diff.setZero(_val == _ref || (isnan(_val) && isnan(_ref)));
86  return diff;
87 }
88 
89 template<typename _T> static Vc::Vector<_T> ulpDiffToReferenceSigned(const Vc::Vector<_T> &_val, const Vc::Vector<_T> &_ref)
90 {
91  return ulpDiffToReference(_val, _ref).copySign(_val - _ref);
92 }
93 
94 #endif // TESTS_ULP_H
95 
96 // vim: foldmethod=marker
Vector< sfloat > sfloat_v
Definition: vector.h:418
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
Definition: vector.h:433
double T(double x)
Definition: ChebyshevPol.h:34
STL namespace.
VECTOR_NAMESPACE::short_v short_v
Definition: vector.h:90
Double_t x[n]
Definition: legend1.C:17
double_v frexp(double_v::AsArg v, int_v *e)
splits v into exponent and mantissa, the sign is kept with the mantissa
Definition: math.h:38
static T ulpDiffToReferenceSigned(T val, T ref)
Definition: ulp.h:53
static Vc_ALWAYS_INLINE Vector< T > abs(const Vector< T > &x)
Definition: vector.h:450
Vc::int_v Type
Definition: ulp.h:58
int isnan(double)
VECTOR_NAMESPACE::int_v int_v
Definition: vector.h:86
static T ulpDiffToReference(T val, T ref)
Definition: ulp.h:34
Definition: casts.h:28
double exp(double)
double ldexp(double, int)