Boost logo

Boost :

From: Michael Marcin (mike.marcin_at_[hidden])
Date: 2008-08-01 13:07:20


Neal Becker wrote:
>
> Multiplication is a bit easier to understand. I thought about mixed-arith mult, but I think it opens a can of worms. What do you want the result to be? So, I decided to only support arith of like-types. If you want the result of mult to be a larger type, then you simply ask for it:
>
> fixed<8,8> x, y;
> fixed<16,16> z = fixed<16,16> (x) * fixed<16,16> (y);
>

fixed<m0,f0> * fixed<m1,f1> naturally yields fixed<m0+m1,f0+f1>

In my fixed point library I chose to make fixed<m,f>*fixed<m,f> return
fixed<m,f> instead of fixed<2*m,2*f> but to make mixed type arithmetic
return a detail type that is convertible to a fixed point type.

namespace detail
{
    template< typename PromotedType, std::size_t F0, std::size_t F1 >
    struct fixed_product
    {
       static const std::size_t frac_0 = F0;
       static const std::size_t frac_1 = F1;

       fixed_product( PromotedType r ) : data(r) {}
       PromotedType data;
    };
} // end namespace detail

/// Product of 2 different fixed-point types
/// @note this currently only supports the case we the two operands
/// have the same bit resolution, it should be extended to
/// cover the case of operands with different bit resolutions
template< std::size_t M0, std::size_t F0,
           std::size_t M1, std::size_t F1 > inline
typename boost::enable_if_c< M0+F0 == M1+F1,
   detail::fixed_product<
      typename detail::type_from_size<M0+F0>::next_size::value_type,
      F0, F1>
>::type
operator * ( fixed<M0,F0> a, fixed<M1,F1> b )
{
    typedef typename fixed<M0,F0>::next_type next_type;
    return detail::fixed_product<next_type,F0,F1>(
          static_cast<next_type>(a.raw()) *
          b.raw()
       );
}

template< std::size_t M, std::size_t F >
template< std::size_t F0, std::size_t F1 >
fixed<M,F>::fixed( detail::fixed_product<next_type,F0,F1> product
       , typename boost::enable_if<
          boost::mpl::greater_equal<
               boost::mpl::int_< F1+F0 >
             , boost::mpl::int_< F >
>
>::type* = 0 )
    : data( static_cast<base_type>( product.data >> ((F1+F0)-F) ) )
{
}

template< std::size_t M, std::size_t F >
template< std::size_t F0, std::size_t F1 >
fixed<M,F>::fixed( detail::fixed_product<next_type,F0,F1> product
       , typename boost::enable_if<
          boost::mpl::less<
               boost::mpl::int_< F1+F0 >
             , boost::mpl::int_< F >
>
>::type* = 0 )
    : data( static_cast<base_type>( product.data << (F-(F1+F0)) ) )
{
}

Thanks,

Michael Marcin


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk