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 /floatprops.h | |
download | vecmathlib-d2614759a1d542c41af59b04d8711246d2a1e876.zip vecmathlib-d2614759a1d542c41af59b04d8711246d2a1e876.tar.gz |
Import initial version
Diffstat (limited to 'floatprops.h')
-rw-r--r-- | floatprops.h | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/floatprops.h b/floatprops.h new file mode 100644 index 0000000..7048112 --- /dev/null +++ b/floatprops.h @@ -0,0 +1,152 @@ +// -*-C++-*- + +#ifndef FLOATPROPS_H +#define FLOATPROPS_H + +#include <cmath> +#include <cstdint> +#include <limits> + + + +namespace vecmathlib { + + // A structure describing various properties of a floating point + // type. Most properties are already described in numeric_limits, so + // we inherit it. + template<typename real_t> + struct floatprops { + // Some interesting properties are: + // digits + // min_exponent + // max_exponent + }; + + template<typename int_t> + struct intprops { + }; + + + + // Properties of float + template<> + struct floatprops<float>: std::numeric_limits<float> { + typedef float real_t; + typedef int32_t int_t; + typedef uint32_t uint_t; + + // Ensure the internal representation is what we expect + static_assert(is_signed, "real_t is not signed"); + static_assert(radix==2, "real_t is not binary"); + + // Ensure the sizes match + static_assert(sizeof(real_t) == sizeof(int_t), "int_t has wrong size"); + static_assert(sizeof(real_t) == sizeof(uint_t), "uint_t has wrong size"); + + // Number of bits in internal representation + static int const bits = 8 * sizeof(real_t); + static int const mantissa_bits = digits - 1; + static int const sign_bits = 1; + static int const exponent_bits = bits - mantissa_bits - sign_bits; + static int const exponent_offset = 2 - min_exponent; + static_assert(mantissa_bits + exponent_bits + sign_bits == bits, + "error in bit counts"); + static uint_t const mantissa_mask = (uint_t(1) << mantissa_bits) - 1; + static uint_t const exponent_mask = + ((uint_t(1) << exponent_bits) - 1) << mantissa_bits; + static uint_t const sign_mask = uint_t(1) << (bits-1); + static_assert((mantissa_mask & exponent_mask & sign_mask) == uint_t(0), + "error in masks"); + static_assert((mantissa_mask | exponent_mask | sign_mask) == ~uint_t(0), + "error in masks"); + + // Re-interpret bit patterns + static inline real_t as_float(int_t x) { return *(real_t*)&x; } + static inline int_t as_int(real_t x) { return *(int_t*)&x; } + + // Convert values + static inline real_t convert_float(int_t x) { return real_t(x); } + static inline int_t convert_int(real_t x) + { + static_assert(sizeof(std::rint(x)) == sizeof(int_t), + "rint() has wrong return type"); + return std::rint(x); + } + }; + + template<> + struct intprops<floatprops<float>::int_t> { + typedef float real_t; + }; + + + + // Properties of double + template<> + struct floatprops<double>: std::numeric_limits<double> { + typedef double real_t; + typedef int64_t int_t; + typedef uint64_t uint_t; + + // Ensure the internal representation is what we expect + static_assert(is_signed, "real_t is not signed"); + static_assert(radix==2, "real_t is not binary"); + + // Ensure the sizes match + static_assert(sizeof(real_t) == sizeof(int_t), "int_t has wrong size"); + static_assert(sizeof(real_t) == sizeof(uint_t), "uint_t has wrong size"); + + // Number of bits in internal representation + static int const bits = 8 * sizeof(real_t); + static int const mantissa_bits = digits - 1; + static int const sign_bits = 1; + static int const exponent_bits = bits - mantissa_bits - sign_bits; + static int const exponent_offset = 2 - min_exponent; + static_assert(mantissa_bits + exponent_bits + sign_bits == bits, + "error in bit counts"); + static uint_t const mantissa_mask = (uint_t(1) << mantissa_bits) - 1; + static uint_t const exponent_mask = + ((uint_t(1) << exponent_bits) - 1) << mantissa_bits; + static uint_t const sign_mask = uint_t(1) << (bits-1); + static_assert((mantissa_mask & exponent_mask & sign_mask) == uint_t(0), + "error in masks"); + static_assert((mantissa_mask | exponent_mask | sign_mask) == ~uint_t(0), + "error in masks"); + + // Re-interpret bit patterns + static inline real_t as_float(int_t x) { return *(real_t*)&x; } + static inline int_t as_int(real_t x) { return *(int_t*)&x; } + + // Convert values + static inline real_t convert_float(int_t x) { return real_t(x); } + static inline int_t convert_int(real_t x) + { + static_assert(sizeof(std::llrint(x)) == sizeof(int_t), + "llrint() has wrong return type"); + return std::llrint(x); + } + }; + + template<> + struct intprops<floatprops<double>::int_t> { + typedef double real_t; + }; + + + + template<typename int_t> + inline typename intprops<int_t>::real_t as_float(int_t x) + { + typedef typename intprops<int_t>::real_t real_t; + return floatprops<real_t>::as_float(x); + } + + template<typename real_t> + inline typename floatprops<real_t>::int_t as_int(real_t x) + { + return floatprops<real_t>::as_int(x); + } + +} // namespace vecmathlib + +#endif // #ifndef FLOATPROPS_H |