Boost logo

Boost :

Subject: Re: [boost] [boostcon][proto] Suggestion for LIAW session: fixed-pointnumbers
From: Gruenke, Matt (mgruenke_at_[hidden])
Date: 2011-03-15 21:45:49


I wrote a similar class, years ago. The signature was simply:
 

                template<
                    SignProperty is_signed,
                    int int_bits, //!< Number of integer bits.
                    int frac_bits //!< Number of fractional bits.
>
                class CFixed;

 
The way I structured it was to discard information only on assignment (unless the maximum internal storage had overflowed, of course). While I agree that it's tempting to just use int64 for storage, the size and speed implications of creating large arrays of them provides a strong argument against this approach.
 
Since the most common use of fixed-point arithmetic is for speed, the priority is speed over safety. For example, never assume that overflow checking is performed. Furthermore, operatorns supported by the class are primarily designed to avoid unnecessary arithmetic, while minimizing surprises.
 
The general policies were:

    * No virtual functions! Fixed-point types must be as fast
      and small as hand-coded fixed-point arthmetic, using
      built-in types.

    * Converting constructor is implicit, since conversions (such
      as reductions in precision) are so common, in fixed-point
      arithmetic.

    * add/subtract return the greater of the int_bits and
      frac_bits (independently) of the operands.

    * add/subtract returns signedness of the type with the
      greater range (choosing unsigned, in the event of a tie).

    * multiply returns a type in which the int and frac bits
      are the sum of the corresponding values of the operands.
      The result is signed, unless both operands are unsigned.

    * The return type of divide is equivalent to multiplying
      the numerator by the inverse of the denominator.

    * inverse returns a type with one fewer frac bits than the
      operand had int bits and one more int bits than the
      operand had frac bits. This sacrifice of precision is
      necessary to avoid overflow.

 
I like the idea of abstracting the assigner, but I guess I don't really see what you'd want to vary besides perhaps rounding behavior.
 
One area in which I spent a fair amount of time was fast conversion to/from IEEE floating-point. In trying to use the rounding-by-adding trick, I got slightly burned by differences in FPU configuration of Linux vs. Windows. With x87 arithmetic, the default FPU configuration keeps different amounts of intermediate precision.
 
Optimized formatted string conversion was another time sink.
 
 
Matt
 

 
________________________________

From: boost-bounces_at_[hidden] on behalf of Ravi
Sent: Sun 3/13/2011 5:24 PM
To: boost_at_[hidden]
Subject: [boost] [boostcon][proto] Suggestion for LIAW session: fixed-pointnumbers

Hi,
  Are there any proto-based ideas for the library-in-a-week sessions? If not,
would building a fixed-point data type be of interest? The domain is narrow
enough that something useful can be accomplished in 4 sessions, but of large
enough scope to present opportunities for exploring proto in depth. A fairly
simple design follows representing a number:

fixed_number<int width,
             int ulp, // 2^{ulp} is the smallest increment possible
             bool signed,
             template assigner<first, last, signed> >

'assigner' handles rounding/truncation/wrapping/etc when assigning another
number (floating-point or fixed-point) to the current one. Internally, each
fixed-point number would be represented by a boost::uint64_t or a
boost::int64_t (limiting the maximum precision allowed). As an example,
  fixed_number<5, -3, false>
would represent a data type that would go from 0 to 3.875 in steps of 0.125.

Proto would be used for creating all arithmetic operations since the return
type of a+b could be different from the type of either a or b. A bonus would
involve getting the fixed-point data type to play well with std::complex (and,
yes, I am aware that std::complex is not designed to work with anything other
than double and float, and will require specialization in the std namespace).

If there is sufficient interest, I could even provide a starting point with
+,-,* implemented; / would take more time. The design above is intended as a
starting point for discussion and I am most definitely not wedded to it. I am
a tyro when it comes to proto, and hence would need someone with more proto
expertise to guide the discussion.

Regards,
Ravi

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


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