diff options
author | Erik Schnetter <schnetter@gmail.com> | 2013-06-28 14:04:29 -0400 |
---|---|---|
committer | Erik Schnetter <schnetter@gmail.com> | 2013-06-28 14:04:29 -0400 |
commit | ba43da889e5d662eedb4c2957162b4d9254557f9 (patch) | |
tree | 839bf17b2201bd5b912c461cd36a63e97a4200ab | |
parent | 137ce80e5535eb98872e5b49970fad2615cb57fe (diff) | |
download | vecmathlib-ba43da889e5d662eedb4c2957162b4d9254557f9.zip vecmathlib-ba43da889e5d662eedb4c2957162b4d9254557f9.tar.gz |
Implement frexp
-rw-r--r-- | floattypes.h | 2 | ||||
-rw-r--r-- | mathfuncs_base.h | 1 | ||||
-rw-r--r-- | mathfuncs_fabs.h | 22 | ||||
-rw-r--r-- | test.cc | 28 | ||||
-rw-r--r-- | vec_altivec_float4.h | 1 | ||||
-rw-r--r-- | vec_avx_double4.h | 1 | ||||
-rw-r--r-- | vec_avx_float8.h | 1 | ||||
-rw-r--r-- | vec_base.h | 7 | ||||
-rw-r--r-- | vec_builtin.h | 1 | ||||
-rw-r--r-- | vec_neon_float2.h | 1 | ||||
-rw-r--r-- | vec_neon_float4.h | 1 | ||||
-rw-r--r-- | vec_pseudo.h | 20 | ||||
-rw-r--r-- | vec_qpx_double4.h | 1 | ||||
-rw-r--r-- | vec_sse_double1.h | 1 | ||||
-rw-r--r-- | vec_sse_double2.h | 1 | ||||
-rw-r--r-- | vec_sse_float1.h | 1 | ||||
-rw-r--r-- | vec_sse_float4.h | 1 | ||||
-rw-r--r-- | vec_test.h | 8 | ||||
-rw-r--r-- | vec_vsx_double2.h | 1 |
19 files changed, 99 insertions, 1 deletions
diff --git a/floattypes.h b/floattypes.h index 8e70b27..426b23a 100644 --- a/floattypes.h +++ b/floattypes.h @@ -46,6 +46,7 @@ namespace std { float fma(float x, float y, float z) { return ::fmaf(x, y, z); } float fmax(float x, float y) { return ::fmaxf(x, y); } float fmin(float x, float y) { return ::fminf(x, y); } + float frexp(float x, int* r) { return ::frexp(x, r); } float hypot(float x, float y) { return ::hypotf(x, y); } int ilogb(float x) { return ::ilogbf(x); } float log1p(float x) { return ::log1pf(x); } @@ -70,6 +71,7 @@ namespace std { double fma(double x, double y, double z) { return ::fma(x, y, z); } double fmax(double x, double y) { return ::fmax(x, y); } double fmin(double x, double y) { return ::fmin(x, y); } + double frexp(double x, int* r) { return ::frexp(x, r); } double hypot(double x, double y) { return ::hypot(x, y); } int ilogb(double x) { return ::ilogb(x); } double log1p(double x) { return ::log1p(x); } diff --git a/mathfuncs_base.h b/mathfuncs_base.h index 20dba73..06cb590 100644 --- a/mathfuncs_base.h +++ b/mathfuncs_base.h @@ -67,6 +67,7 @@ namespace vecmathlib { static realvec_t vml_fma(realvec_t x, realvec_t y, realvec_t z); static realvec_t vml_fmax(realvec_t x, realvec_t y); static realvec_t vml_fmin(realvec_t x, realvec_t y); + static realvec_t vml_frexp(realvec_t x, intvec_t& r); static intvec_t vml_ilogb(realvec_t x); static boolvec_t vml_ieee_isfinite(realvec_t x); static boolvec_t vml_ieee_isinf(realvec_t x); diff --git a/mathfuncs_fabs.h b/mathfuncs_fabs.h index d6e78f0..07b5664 100644 --- a/mathfuncs_fabs.h +++ b/mathfuncs_fabs.h @@ -51,6 +51,28 @@ namespace vecmathlib { } template<typename realvec_t> + realvec_t mathfuncs<realvec_t>::vml_frexp(realvec_t x, + typename realvec_t::intvec_t& ir) + { + intvec_t e = lsr(as_int(x) & IV(FP::exponent_mask), FP::mantissa_bits); + ir = e - IV(FP::exponent_offset - 1); + ir = ifthen(convert_bool(e), ir, IV(std::numeric_limits<int_t>::min())); +#if defined VML_HAVE_INF + ir = ifthen(isinf(x), IV(std::numeric_limits<int_t>::max()), ir); +#endif +#if defined VML_HAVE_NAN + ir = ifthen(isnan(x), IV(std::numeric_limits<int_t>::min()), ir); +#endif + realvec_t r = + as_float((as_int(x) & IV(FP::signbit_mask | FP::mantissa_mask)) | + IV(FP::as_int(R(0.5)) & FP::exponent_mask)); + boolvec_t iszero = x == RV(0.0); + ir = ifthen(iszero, IV(I(0)), ir); + r = ifthen(iszero, copysign(RV(R(0.0)), r), r); + return r; + } + + template<typename realvec_t> typename realvec_t::intvec_t mathfuncs<realvec_t>::vml_ilogb(realvec_t x) { intvec_t e = lsr(as_int(x) & IV(FP::exponent_mask), FP::mantissa_bits); @@ -1024,6 +1024,30 @@ struct vecmathlib_test { } // Change signature: "int" -> "int_t" + static real_t local_frexp0(real_t x) + { + int r; + return std::frexp(x, &r); + } + static int_t local_frexp1(real_t x) + { + int r; + std::frexp(x, &r); + if (r==FP_ILOGB0) r=std::numeric_limits<int_t>::min(); + if (r==FP_ILOGBNAN) r=std::numeric_limits<int_t>::max(); + return r; + } + static realvec_t local_vfrexp0(realvec_t x) + { + intvec_t r; + return vecmathlib::frexp(x, r); + } + static intvec_t local_vfrexp1(realvec_t x) + { + intvec_t r; + vecmathlib::frexp(x, r); + return r; + } static int_t local_ilogb(real_t x) { int r = std::ilogb(x); @@ -1034,7 +1058,7 @@ struct vecmathlib_test { static real_t local_ldexp(real_t x, int_t n) { return ldexp(x, n); } static void test_fabs() { - cout << " testing + - + - * == != < <= > >= copysign fabs fdim fma fmax fmin ilogb isfinite isinf isnan isnormal ldexp nextafter signbit...\n" << flush; + cout << " testing + - + - * == != < <= > >= copysign fabs fdim fma fmax fmin frexp ilogb isfinite isinf isnan isnormal ldexp nextafter signbit...\n" << flush; const real_t eps = FP::epsilon(); const real_t int_min = R(std::numeric_limits<int_t>::min()); @@ -1126,6 +1150,8 @@ struct vecmathlib_test { x, y, z, R(2.0)*accuracy()); check_real<RV,RV>("fmax", std::fmax, vecmathlib::fmax, x, y, 0.0); check_real<RV,RV>("fmin", std::fmin, vecmathlib::fmin, x, y, 0.0); + check_real<RV>("frexp0", local_frexp0, local_vfrexp0, x, 0.0); + check_int<RV>("frexp1", local_frexp1, local_vfrexp1, x); check_int<RV>("ilogb", local_ilogb, (intvec_t(*)(realvec_t))vecmathlib::ilogb, x); #if defined VML_HAVE_INF && defined VML_HAVE_NAN diff --git a/vec_altivec_float4.h b/vec_altivec_float4.h index 813141e..c5eb28b 100644 --- a/vec_altivec_float4.h +++ b/vec_altivec_float4.h @@ -445,6 +445,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return vec_max(v, y.v); } realvec fmin(realvec y) const { return vec_min(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } diff --git a/vec_avx_double4.h b/vec_avx_double4.h index 15f7edf..9102e67 100644 --- a/vec_avx_double4.h +++ b/vec_avx_double4.h @@ -564,6 +564,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return _mm256_max_pd(v, y.v); } realvec fmin(realvec y) const { return _mm256_min_pd(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } diff --git a/vec_avx_float8.h b/vec_avx_float8.h index e7e1187..6431227 100644 --- a/vec_avx_float8.h +++ b/vec_avx_float8.h @@ -556,6 +556,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return _mm256_max_ps(v, y.v); } realvec fmin(realvec y) const { return _mm256_min_ps(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } @@ -358,6 +358,13 @@ namespace vecmathlib { } template<typename real_t, int size> + inline realvec<real_t, size> frexp(realvec<real_t, size> x, + intvec<real_t, size>& r) + { + return x.frexp(r); + } + + template<typename real_t, int size> inline realvec<real_t, size> hypot(realvec<real_t, size> x, realvec<real_t, size> y) { diff --git a/vec_builtin.h b/vec_builtin.h index a240a6d..f7db8ca 100644 --- a/vec_builtin.h +++ b/vec_builtin.h @@ -532,6 +532,7 @@ namespace vecmathlib { realvec_t fmax(realvec_t y) const { return MF::vml_fmax(*this, y); } realvec_t fmin(realvec_t y) const { return MF::vml_fmin(*this, y); } realvec_t fmod(realvec_t y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec_t hypot(realvec_t y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } diff --git a/vec_neon_float2.h b/vec_neon_float2.h index 0030c88..ba14d86 100644 --- a/vec_neon_float2.h +++ b/vec_neon_float2.h @@ -459,6 +459,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return vmax_f32(v, y.v); } realvec fmin(realvec y) const { return vmin_f32(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } diff --git a/vec_neon_float4.h b/vec_neon_float4.h index cf72a6d..2951420 100644 --- a/vec_neon_float4.h +++ b/vec_neon_float4.h @@ -473,6 +473,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return vmaxq_f32(v, y.v); } realvec fmin(realvec y) const { return vminq_f32(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } diff --git a/vec_pseudo.h b/vec_pseudo.h index 0764d94..c3658c0 100644 --- a/vec_pseudo.h +++ b/vec_pseudo.h @@ -746,6 +746,19 @@ namespace vecmathlib { realpseudovec fmax(realpseudovec y) const { return map(std::fmax, y); } realpseudovec fmin(realpseudovec y) const { return map(std::fmin, y); } realpseudovec fmod(realpseudovec y) const { return map(std::fmod, y); } + realpseudovec frexp(intvec_t& ires) const + { + realvec_t res; + for (int d=0; d<size; ++d) { + int ir; + real_t r = std::frexp(v[d], &ir); + if (ir == FP_ILOGB0) ir = std::numeric_limits<int_t>::min(); + else if (ir == FP_ILOGBNAN) ir = std::numeric_limits<int_t>::max(); + res.v[d] = r; + ires.v[d] = ir; + } + return res; + } realpseudovec hypot(realpseudovec y) const { return map(std::hypot, y); } intvec_t ilogb() const { @@ -1203,6 +1216,13 @@ namespace vecmathlib { } template<typename real_t, int size> + inline realpseudovec<real_t, size> frexp(realpseudovec<real_t, size> x, + intpseudovec<real_t, size>& r) + { + return x.frexp(r); + } + + template<typename real_t, int size> inline realpseudovec<real_t, size> hypot(realpseudovec<real_t, size> x, realpseudovec<real_t, size> y) { diff --git a/vec_qpx_double4.h b/vec_qpx_double4.h index e7a1c05..afcbcbb 100644 --- a/vec_qpx_double4.h +++ b/vec_qpx_double4.h @@ -560,6 +560,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return MF::vml_fmax(v, y.v); } realvec fmin(realvec y) const { return MF::vml_fmin(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return hypotd4(v, y.v); } intvec_t ilogb() const { diff --git a/vec_sse_double1.h b/vec_sse_double1.h index d4626dd..a30cd2d 100644 --- a/vec_sse_double1.h +++ b/vec_sse_double1.h @@ -421,6 +421,7 @@ namespace vecmathlib { return to_double(_mm_min_sd(from_double(v), from_double(y.v))); } realvec fmod(realvec y) const { return std::fmod(v, y.v); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { diff --git a/vec_sse_double2.h b/vec_sse_double2.h index 2cbbd38..ee689cd 100644 --- a/vec_sse_double2.h +++ b/vec_sse_double2.h @@ -551,6 +551,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return _mm_max_pd(v, y.v); } realvec fmin(realvec y) const { return _mm_min_pd(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } diff --git a/vec_sse_float1.h b/vec_sse_float1.h index 56ece24..12ab1ae 100644 --- a/vec_sse_float1.h +++ b/vec_sse_float1.h @@ -421,6 +421,7 @@ namespace vecmathlib { return to_float(_mm_min_ss(from_float(v), from_float(y.v))); } realvec fmod(realvec y) const { return std::fmod(v, y.v); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { diff --git a/vec_sse_float4.h b/vec_sse_float4.h index 5259cb2..2163e09 100644 --- a/vec_sse_float4.h +++ b/vec_sse_float4.h @@ -545,6 +545,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return _mm_max_ps(v, y.v); } realvec fmin(realvec y) const { return _mm_min_ps(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } @@ -688,6 +688,7 @@ namespace vecmathlib { realtestvec fmax(realtestvec y) const { return MF::vml_fmax(*this, y); } realtestvec fmin(realtestvec y) const { return MF::vml_fmin(*this, y); } realtestvec fmod(realtestvec y) const { return MF::vml_fmod(*this, y); } + realtestvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realtestvec hypot(realtestvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } @@ -1118,6 +1119,13 @@ namespace vecmathlib { } template<typename real_t, int size> + inline realtestvec<real_t, size> frexp(realtestvec<real_t, size> x, + inttestvec<real_t, size>& r) + { + return x.frexp(r); + } + + template<typename real_t, int size> inline realtestvec<real_t, size> hypot(realtestvec<real_t, size> x, realtestvec<real_t, size> y) { diff --git a/vec_vsx_double2.h b/vec_vsx_double2.h index 024056d..562969a 100644 --- a/vec_vsx_double2.h +++ b/vec_vsx_double2.h @@ -560,6 +560,7 @@ namespace vecmathlib { realvec fmax(realvec y) const { return vec_max(v, y.v); } realvec fmin(realvec y) const { return vec_min(v, y.v); } realvec fmod(realvec y) const { return MF::vml_fmod(*this, y); } + realvec frexp(intvec_t& r) const { return MF::vml_frexp(*this, r); } realvec hypot(realvec y) const { return MF::vml_hypot(*this, y); } intvec_t ilogb() const { return MF::vml_ilogb(*this); } boolvec_t isfinite() const { return MF::vml_isfinite(*this); } |