File indexing completed on 2025-01-31 10:25:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef VC_SCALAR_MATH_H_
0029 #define VC_SCALAR_MATH_H_
0030
0031 #include <cstdlib>
0032 #include "macros.h"
0033
0034 namespace Vc_VERSIONED_NAMESPACE
0035 {
0036
0037 Vc_INTRINSIC Scalar::float_v copysign(Scalar::float_v mag, Scalar::float_v sign)
0038 {
0039 union {
0040 float f;
0041 unsigned int i;
0042 } value, s;
0043 value.f = mag.data();
0044 s.f = sign.data();
0045 value.i = (s.i & 0x80000000u) | (value.i & 0x7fffffffu);
0046 return Scalar::float_v{value.f};
0047 }
0048 Vc_INTRINSIC Vc_CONST Scalar::double_v copysign(Scalar::double_v mag,
0049 Scalar::double_v sign)
0050 {
0051 union {
0052 double f;
0053 unsigned long long i;
0054 } value, s;
0055 value.f = mag.data();
0056 s.f = sign.data();
0057 value.i = (s.i & 0x8000000000000000ull) | (value.i & 0x7fffffffffffffffull);
0058 return Scalar::double_v{value.f};
0059 }
0060
0061
0062
0063 #define Vc_MINMAX(V) \
0064 static Vc_ALWAYS_INLINE Scalar::V min(const Scalar::V &x, const Scalar::V &y) \
0065 { \
0066 return Scalar::V(std::min(x.data(), y.data())); \
0067 } \
0068 static Vc_ALWAYS_INLINE Scalar::V max(const Scalar::V &x, const Scalar::V &y) \
0069 { \
0070 return Scalar::V(std::max(x.data(), y.data())); \
0071 }
0072 Vc_ALL_VECTOR_TYPES(Vc_MINMAX);
0073 #undef Vc_MINMAX
0074
0075 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> sqrt (const Scalar::Vector<T> &x)
0076 {
0077 return Scalar::Vector<T>(std::sqrt(x.data()));
0078 }
0079
0080 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> rsqrt(const Scalar::Vector<T> &x)
0081 {
0082 const typename Vector<T, VectorAbi::Scalar>::EntryType one = 1; return Scalar::Vector<T>(one / std::sqrt(x.data()));
0083 }
0084
0085 template <typename T,
0086 typename = enable_if<std::is_same<T, double>::value || std::is_same<T, float>::value ||
0087 std::is_same<T, int>::value>>
0088 Vc_ALWAYS_INLINE Vc_PURE Scalar::Vector<T> abs(Scalar::Vector<T> x)
0089 {
0090 return std::abs(x.data());
0091 }
0092
0093 Vc_ALWAYS_INLINE Vc_PURE Scalar::Vector<short> abs(Scalar::Vector<short> x)
0094 {
0095 return std::abs(static_cast<int>(x.data()));
0096 }
0097
0098 template<typename T> static Vc_ALWAYS_INLINE void sincos(const Scalar::Vector<T> &x, Scalar::Vector<T> *sin, Scalar::Vector<T> *cos)
0099 {
0100 #if defined(_WIN32) || defined(__APPLE__)
0101 sin->data() = std::sin(x.data());
0102 cos->data() = std::cos(x.data());
0103 #elif Vc_HAS_BUILTIN(__builtin_sincosf) || defined Vc_GCC
0104 __builtin_sincosf(x.data(), &sin->data(), &cos->data());
0105 #else
0106 sincosf(x.data(), &sin->data(), &cos->data());
0107 #endif
0108 }
0109
0110 template<> Vc_ALWAYS_INLINE void sincos(const Scalar::Vector<double> &x, Scalar::Vector<double> *sin, Scalar::Vector<double> *cos)
0111 {
0112 #if defined(_WIN32) || defined(__APPLE__)
0113 sin->data() = std::sin(x.data());
0114 cos->data() = std::cos(x.data());
0115 #elif Vc_HAS_BUILTIN(__builtin_sincos) || defined Vc_GCC
0116 __builtin_sincos(x.data(), &sin->data(), &cos->data());
0117 #else
0118 ::sincos(x.data(), &sin->data(), &cos->data());
0119 #endif
0120 }
0121
0122 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> sin (const Scalar::Vector<T> &x)
0123 {
0124 return Scalar::Vector<T>(std::sin(x.data()));
0125 }
0126
0127 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> asin (const Scalar::Vector<T> &x)
0128 {
0129 return Scalar::Vector<T>(std::asin(x.data()));
0130 }
0131
0132 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> cos (const Scalar::Vector<T> &x)
0133 {
0134 return Scalar::Vector<T>(std::cos(x.data()));
0135 }
0136
0137 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> log (const Scalar::Vector<T> &x)
0138 {
0139 return Scalar::Vector<T>(std::log(x.data()));
0140 }
0141
0142 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> log10(const Scalar::Vector<T> &x)
0143 {
0144 return Scalar::Vector<T>(std::log10(x.data()));
0145 }
0146
0147 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> log2(const Scalar::Vector<T> &x)
0148 {
0149 return Scalar::Vector<T>(std::log2(x.data()));
0150 }
0151
0152 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> exp (const Scalar::Vector<T> &x)
0153 {
0154 return Scalar::Vector<T>(std::exp(x.data()));
0155 }
0156
0157 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> atan (const Scalar::Vector<T> &x)
0158 {
0159 return Scalar::Vector<T>(std::atan( x.data() ));
0160 }
0161
0162 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> atan2(const Scalar::Vector<T> &x, const Scalar::Vector<T> &y)
0163 {
0164 return Scalar::Vector<T>(std::atan2( x.data(), y.data() ));
0165 }
0166
0167 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> trunc(const Scalar::Vector<T> &x)
0168 {
0169 return std::trunc(x.data());
0170 }
0171
0172 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> floor(const Scalar::Vector<T> &x)
0173 {
0174 return Scalar::Vector<T>(std::floor(x.data()));
0175 }
0176
0177 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> ceil(const Scalar::Vector<T> &x)
0178 {
0179 return Scalar::Vector<T>(std::ceil(x.data()));
0180 }
0181
0182 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> round(const Scalar::Vector<T> &x)
0183 {
0184 return x;
0185 }
0186
0187 namespace
0188 {
0189 template<typename T> bool _realIsEvenHalf(T x) {
0190 const T two = 2;
0191 const T half = 0.5;
0192 const T f = std::floor(x * half) * two;
0193 return (x - f) == half;
0194 }
0195 }
0196 template<> Vc_ALWAYS_INLINE Scalar::Vector<float> round(const Scalar::Vector<float> &x)
0197 {
0198 return Scalar::float_v(std::floor(x.data() + 0.5f) - (_realIsEvenHalf(x.data()) ? 1.f : 0.f));
0199 }
0200
0201 template<> Vc_ALWAYS_INLINE Scalar::Vector<double> round(const Scalar::Vector<double> &x)
0202 {
0203 return Scalar::double_v(std::floor(x.data() + 0.5 ) - (_realIsEvenHalf(x.data()) ? 1. : 0. ));
0204 }
0205
0206 template<typename T> static Vc_ALWAYS_INLINE Scalar::Vector<T> reciprocal(const Scalar::Vector<T> &x)
0207 {
0208 const typename Vector<T, VectorAbi::Scalar>::EntryType one = 1; return Scalar::Vector<T>(one / x.data());
0209 }
0210
0211 #ifdef isfinite
0212 #undef isfinite
0213 #endif
0214 #ifdef isnan
0215 #undef isnan
0216 #endif
0217 template<typename T> static Vc_ALWAYS_INLINE typename Vector<T, VectorAbi::Scalar>::Mask isfinite(const Scalar::Vector<T> &x)
0218 {
0219 return typename Vector<T, VectorAbi::Scalar>::Mask(
0220 #ifdef _MSC_VER
0221 !!_finite(x.data())
0222 #elif defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1500
0223 ::isfinite(x.data())
0224 #else
0225 std::isfinite(x.data())
0226 #endif
0227 );
0228 }
0229
0230 template<typename T> Vc_ALWAYS_INLINE typename Vector<T, VectorAbi::Scalar>::Mask isinf(const Scalar::Vector<T> &x)
0231 {
0232 return typename Vector<T, VectorAbi::Scalar>::Mask(std::isinf(x.data()));
0233 }
0234
0235 template<typename T> static Vc_ALWAYS_INLINE typename Vector<T, VectorAbi::Scalar>::Mask isnan(const Scalar::Vector<T> &x)
0236 {
0237 return typename Vector<T, VectorAbi::Scalar>::Mask(
0238 #ifdef _MSC_VER
0239 !!_isnan(x.data())
0240 #elif defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1500
0241 ::isnan(x.data())
0242 #else
0243 std::isnan(x.data())
0244 #endif
0245 );
0246 }
0247
0248 Vc_ALWAYS_INLINE Scalar::Vector<float> frexp(Scalar::Vector<float> x, SimdArray<int, 1, Scalar::Vector<int>, 1> *e) {
0249 return Scalar::float_v(std::frexp(x.data(), &internal_data(*e).data()));
0250 }
0251 Vc_ALWAYS_INLINE Scalar::Vector<double> frexp(Scalar::Vector<double> x, SimdArray<int, 1, Scalar::Vector<int>, 1> *e) {
0252 return Scalar::double_v(std::frexp(x.data(), &internal_data(*e).data()));
0253 }
0254
0255 Vc_ALWAYS_INLINE Scalar::Vector<float> ldexp(Scalar::Vector<float> x, const SimdArray<int, 1, Scalar::Vector<int>, 1> &e) {
0256 return Scalar::float_v(std::ldexp(x.data(), internal_data(e).data()));
0257 }
0258 Vc_ALWAYS_INLINE Scalar::Vector<double> ldexp(Scalar::Vector<double> x, const SimdArray<int, 1, Scalar::Vector<int>, 1> &e) {
0259 return Scalar::double_v(std::ldexp(x.data(), internal_data(e).data()));
0260 }
0261
0262
0263 template <typename T>
0264 Vc_ALWAYS_INLINE Vector<T, VectorAbi::Scalar> fma(Vector<T, VectorAbi::Scalar> a,
0265 Vector<T, VectorAbi::Scalar> b,
0266 Vector<T, VectorAbi::Scalar> c)
0267 {
0268 if (std::is_integral<T>::value) {
0269 return a * b + c;
0270 } else {
0271 return std::fma(a.data(), b.data(), c.data());
0272 }
0273 }
0274
0275
0276 }
0277
0278 #endif
0279
0280