summaryrefslogtreecommitdiffstats
path: root/floatprops.h
diff options
context:
space:
mode:
authorErik Schnetter <schnetter@gmail.com>2012-11-30 15:50:03 -0500
committerErik Schnetter <schnetter@gmail.com>2012-11-30 15:50:03 -0500
commitd2614759a1d542c41af59b04d8711246d2a1e876 (patch)
tree2689209034d9ccc3d29208d50b82b4f89116aa1b /floatprops.h
downloadvecmathlib-d2614759a1d542c41af59b04d8711246d2a1e876.zip
vecmathlib-d2614759a1d542c41af59b04d8711246d2a1e876.tar.gz
Import initial version
Diffstat (limited to 'floatprops.h')
-rw-r--r--floatprops.h152
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
OpenPOWER on IntegriCloud