Skip to content
Snippets Groups Projects
vrpn_FixedPoint.h 4.40 KiB
/** @file vrpn_FixedPoint.h
    @brief Header

    @date 2014

    @author
    Kevin M. Godby
    <kevin@godby.org>
*/

#ifndef VRPN_FIXED_POINT_H_
#define VRPN_FIXED_POINT_H_

// Internal Includes
#include "vrpn_Types.h"

// Library/third-party includes
// - none

// Standard includes
#include <cstddef>  // for NULL

namespace vrpn {

    namespace detail {
        /**
         * Set as the type member of vrpn_IntegerOfSize if too many bits are
         * required.
         * We only support up to 32 bits currently.
         */
        struct IntegerOverflow;

        /**
         * \name Integer types.
         *
         * In the general case, we'll start adding bits to the required size
         *until we
         * land on one of the specialized cases below, then return that
         *specialized
         * case. The end result is that we return an integer type that can
         *contain a
         * value require NUM_BITS bits.
         */
        ///@{
        template <int NUM_BITS> struct IntegerOfSize {
            // An integer requiring n bits can be represented by an integer of
            // size n+1 bits.
            typedef typename IntegerOfSize<NUM_BITS + 1>::type type;
        };

        template <> struct IntegerOfSize<8> {
            typedef vrpn_int8 type;
        };

        template <> struct IntegerOfSize<16> {
            typedef vrpn_int16 type;
        };

        template <> struct IntegerOfSize<32> {
            typedef vrpn_int32 type;
        };

        template <> struct IntegerOfSize<64> {
            typedef IntegerOfSize type;
        };

        /// @todo allow for larger types if we can establish VRPN versions of
        /// them (e.g.,
        /// equivalents to int64_t).
        ///@}
    } // namespace detail

    /**
     * A fixed-point value class. All values are signed, two's-complement.
     *
     * @tparam INTEGER_BITS The number of bits devoted to the integer part.
     * @tparam FRACTIONAL_BITS The number of bits devoted to the fractioal part.
     */
    template <int INTEGER_BITS, int FRACTIONAL_BITS> class FixedPoint {
    public:
        /**
         * Find an integer type large enough to hold INTEGER_BITS.
         */
        typedef typename detail::IntegerOfSize<INTEGER_BITS>::type IntegerType;

        typedef typename detail::IntegerOfSize<INTEGER_BITS +
                                               FRACTIONAL_BITS>::type RawType;

        /**
         * \name Constructors.
         *
         * The bits of an integral type passed to the constructor will be
         * interpreted as as fixed-point value. A floating-point type passed to
         *the
         * constructor will be converted to a fixed-point value.
         */
        //@{
        FixedPoint()
            : value_(0)
        {
        }
        explicit FixedPoint(vrpn_int8 x)
            : value_(x)
        {
        }
        explicit FixedPoint(vrpn_int16 x)
            : value_(x)
        {
        }
        explicit FixedPoint(vrpn_int32 x)
            : value_(x)
        {
        }
        explicit FixedPoint(vrpn_uint8 x)
            : value_(x)
        {
        }
        explicit FixedPoint(vrpn_uint16 x)
            : value_(x)
        {
        }
        explicit FixedPoint(vrpn_uint32 x)
            : value_(x)
        {
        }
        explicit FixedPoint(double x)
            : value_(x * (1 << FRACTIONAL_BITS))
        {
        }
        explicit FixedPoint(float x)
            : value_(x * (1 << FRACTIONAL_BITS))
        {
        }
        //@}

        /// @todo add operators, lots and lots of operators?

        /**
         * Returns a floating-point representation of this
         * fixed-point value.
         */
        template <typename T> T get() const
        {
            return get(reinterpret_cast<TypeWrapper<T> *>(NULL));
        }

        /** \name Debugging functions. */
        ///@{
        /// @todo remove these functions after debugging
        RawType value() const { return value_; }
        ///@}

    private:
        template <typename T> struct TypeWrapper;
        vrpn_float32 get(TypeWrapper<vrpn_float32> *) const
        {
            return static_cast<vrpn_float32>(value_) / (1 << FRACTIONAL_BITS);
        }

        vrpn_float64 get(TypeWrapper<vrpn_float64> *) const
        {
            return static_cast<vrpn_float64>(value_) / (1 << FRACTIONAL_BITS);
        }

        RawType value_;
    };

} // namespace vrpn

#endif // VRPN_FIXED_POINT_H_