// -*-C++-*- #ifndef MATHFUNCS_FABS_H #define MATHFUNCS_FABS_H #include "mathfuncs_base.h" #include namespace vecmathlib { template realvec_t mathfuncs::vml_copysign(realvec_t x, realvec_t y) { intvec_t value = as_int(x) & IV(U(~FP::signbit_mask)); intvec_t sign = as_int(y) & IV(FP::signbit_mask); return as_float(sign | value); } template realvec_t mathfuncs::vml_fabs(realvec_t x) { return as_float(as_int(x) & IV(U(~FP::signbit_mask))); } template realvec_t mathfuncs::vml_fdim(realvec_t x, realvec_t y) { // return ifthen(x > y, x - y, RV(0.0)); return fmax(x - y, RV(0.0)); } template realvec_t mathfuncs::vml_fma(realvec_t x, realvec_t y, realvec_t z) { return x * y + z; } template realvec_t mathfuncs::vml_fmax(realvec_t x, realvec_t y) { return ifthen(x < y, y, x); } template realvec_t mathfuncs::vml_fmin(realvec_t x, realvec_t y) { return ifthen(y < x, y, x); } template realvec_t mathfuncs::vml_frexp(realvec_t x, typename realvec_t::intvec_t *irp) { intvec_t e = lsr(as_int(x) & IV(FP::exponent_mask), FP::mantissa_bits); intvec_t ir = e - IV(FP::exponent_offset - 1); ir = ifthen(convert_bool(e), ir, IV(std::numeric_limits::min())); #if defined VML_HAVE_INF ir = ifthen(isinf(x), IV(std::numeric_limits::max()), ir); #endif #if defined VML_HAVE_NAN ir = ifthen(isnan(x), IV(std::numeric_limits::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); *irp = ir; return r; } template typename realvec_t::intvec_t mathfuncs::vml_ilogb(realvec_t x) { // TODO: Check SLEEF 2.80 algorithm intvec_t e = lsr(as_int(x) & IV(FP::exponent_mask), FP::mantissa_bits); intvec_t r = e - IV(FP::exponent_offset); r = ifthen(convert_bool(e), r, IV(std::numeric_limits::min())); #if defined VML_HAVE_INF r = ifthen(isinf(x), IV(std::numeric_limits::max()), r); #endif #if defined VML_HAVE_NAN r = ifthen(isnan(x), IV(std::numeric_limits::min()), r); #endif return r; } template typename realvec_t::boolvec_t mathfuncs::vml_ieee_isfinite(realvec_t x) { return (as_int(x) & IV(FP::exponent_mask)) != IV(FP::exponent_mask); } template typename realvec_t::boolvec_t mathfuncs::vml_ieee_isinf(realvec_t x) { return (as_int(x) & IV(I(~FP::signbit_mask))) == IV(FP::exponent_mask); } template typename realvec_t::boolvec_t mathfuncs::vml_ieee_isnan(realvec_t x) { return (as_int(x) & IV(FP::exponent_mask)) == IV(FP::exponent_mask) && (as_int(x) & IV(FP::mantissa_mask)) != IV(I(0)); } template typename realvec_t::boolvec_t mathfuncs::vml_ieee_isnormal(realvec_t x) { return (as_int(x) & IV(FP::exponent_mask)) != IV(FP::exponent_mask) && (as_int(x) & IV(FP::exponent_mask)) != IV(I(0)); } template typename realvec_t::boolvec_t mathfuncs::vml_isfinite(realvec_t x) { #if defined VML_HAVE_INF || defined VML_HAVE_NAN return vml_ieee_isfinite(x); #else return BV(true); #endif } template typename realvec_t::boolvec_t mathfuncs::vml_isinf(realvec_t x) { #if defined VML_HAVE_INF return vml_ieee_isinf(x); #else return BV(false); #endif } template typename realvec_t::boolvec_t mathfuncs::vml_isnan(realvec_t x) { #if defined VML_HAVE_NAN return vml_ieee_isnan(x); #else return BV(false); #endif } template typename realvec_t::boolvec_t mathfuncs::vml_isnormal(realvec_t x) { #if defined VML_HAVE_DENORMALS || defined VML_HAVE_INF || defined VML_HAVE_NAN return vml_ieee_isnormal(x); #else return BV(true); #endif } template realvec_t mathfuncs::vml_ldexp(realvec_t x, intvec_t n) { // TODO: Check SLEEF 2.80 algorithm #if 0 realvec_t r = as_float(as_int(x) + (n << I(FP::mantissa_bits))); r = ifthen((as_int(x) & IV(FP::exponent_mask)) == IV(I(0)), x, r); return r; #endif realvec_t r = as_float(as_int(x) + (n << U(FP::mantissa_bits))); int max_n = FP::max_exponent - FP::min_exponent; boolvec_t underflow = n < IV(I(-max_n)); boolvec_t overflow = n > IV(I(max_n)); intvec_t old_exp = lsr(as_int(x) & IV(FP::exponent_mask), FP::mantissa_bits); intvec_t new_exp = old_exp + n; // TODO: check bit patterns instead underflow = underflow || new_exp < IV(I(FP::min_exponent + FP::exponent_offset)); overflow = overflow || new_exp > IV(I(FP::max_exponent + FP::exponent_offset)); r = ifthen(underflow, copysign(RV(R(0.0)), x), r); r = ifthen(overflow, copysign(RV(FP::infinity()), x), r); boolvec_t dont_change = x == RV(R(0.0)) || isinf(x) || isnan(x); r = ifthen(dont_change, x, r); return r; } template realvec_t mathfuncs::vml_mad(realvec_t x, realvec_t y, realvec_t z) { return x * y + z; } template typename realvec_t::boolvec_t mathfuncs::vml_signbit(realvec_t x) { return convert_bool(as_int(x) & IV(FP::signbit_mask)); } }; // namespace vecmathlib #endif // #ifndef MATHFUNCS_FABS_H