diff options
author | Erik Schnetter <schnetter@gmail.com> | 2012-11-30 15:50:03 -0500 |
---|---|---|
committer | Erik Schnetter <schnetter@gmail.com> | 2012-11-30 15:50:03 -0500 |
commit | d2614759a1d542c41af59b04d8711246d2a1e876 (patch) | |
tree | 2689209034d9ccc3d29208d50b82b4f89116aa1b /mathfuncs_convert.h | |
download | vecmathlib-d2614759a1d542c41af59b04d8711246d2a1e876.zip vecmathlib-d2614759a1d542c41af59b04d8711246d2a1e876.tar.gz |
Import initial version
Diffstat (limited to 'mathfuncs_convert.h')
-rw-r--r-- | mathfuncs_convert.h | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/mathfuncs_convert.h b/mathfuncs_convert.h new file mode 100644 index 0000000..4dfffef --- /dev/null +++ b/mathfuncs_convert.h @@ -0,0 +1,86 @@ +// -*-C++-*- + +#ifndef MATHFUNCS_CONVERT_H +#define MATHFUNCS_CONVERT_H + +#include "mathfuncs_base.h" + +#include <cassert> +#include <cmath> + + + +namespace vecmathlib { + + template<typename realvec_t> + realvec_t mathfuncs<realvec_t>::vml_convert_float(intvec_t x) + { + // Convert in two passes. Convert as much as possible during the + // first pass (lobits), so that the second pass (hibits) may be + // omitted if the high bits are known to be zero. + int_t lobits = FP::mantissa_bits; + int_t hibits = FP::bits - lobits; + + // Convert lower bits + intvec_t xlo = x & IV((U(1) << lobits) - 1); + // exponent for the equivalent floating point number + int_t exponent_lo = FP::exponent_offset + lobits; + xlo |= exponent_lo; + // subtract hidden mantissa bit + realvec_t flo = as_float(xlo) - RV(FP::as_float(exponent_lo)); + + // Convert upper bits + // make unsigned by subtracting largest negative number + x ^= FP::sign_mask; + intvec_t xhi = lsr(x, lobits); + // exponent for the equivalent floating point number + int_t exponent_hi = FP::exponent_offset + FP::bits; + xhi |= exponent_hi; + // add largest negative number, and subtract hidden mantissa bit + realvec_t + fhi = as_float(xhi) - RV(FP::as_float(exponent_hi) + R(FP::sign_mask)); + + // Combine results + return flo + fhi; + } + + + + template<typename realvec_t> + auto mathfuncs<realvec_t>::vml_convert_int(realvec_t x) -> intvec_t + { + // Handle zero + boolvec_t is_zero = x == RV(0.0); + // Handle negative numbers + boolvec_t is_negative = signbit(x); + x = fabs(x); + + // Round, by adding a large number that removes the excess + // precision + int_t large = U(1) << FP::mantissa_bits; + x += R(large); + + intvec_t exponent = ilogb(x); + for (int i=0; i<intvec_t::size; ++i) { + assert(exponent[i] >= FP::mantissa_bits); + } + intvec_t ix = as_int(x) & IV(FP::mantissa_mask); + // add hidden mantissa bit + ix |= U(1) << FP::mantissa_bits; + // shift according to exponent + ix <<= exponent - IV(FP::mantissa_bits); + + // Undo the adding above + ix -= large; + + // Handle negative numbers + ix = ifthen(is_negative, -ix, ix); + // Handle zero + ix = ifthen(is_zero, IV(0), ix); + + return ix; + } + +}; // namespace vecmathlib + +#endif // #ifndef MATHFUNCS_CONVERT_H |