 # Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2003-07-15 09:57:56

Hi Bill,

Bill Seymour <bill-at-the-office_at_[hidden]> wrote in message
news:3F13F84C.2A55B100_at_pobox.com...
> Fernando,
>
>
> The "scale" really is intended to be the number of decimal digits
> to the right of the decimal point; so, yes, if int_type on your
> system is 64 bits, and if you specify a scale of 18, then no
> /whole/ decimal digits will be allowed to the left of the point.
> (You might get a 19th digit if it isn't too big.)
>
> One of your tests, for example:
> >
> > s=2147483647
> > [9,s]=2147483647.000000000
> > [10,s]=302809239.6290448384
> >
>
> Trying to construct the decimal with a scale of 10 results in
> signed integer overflow which yields undefined behavior.
>
OK.
So, correct me if I'm wrong:
For any given decimal with some int_type, a 'digits' constant is associated
with it which comes from numeric_limits<int_type>::digits10. This constant
identifies the maxium number of digits (in both the whole and fractional
parts) that any such decimal can represent.
Thus numeric_limits<decimal>::digits and digits10 are equal to this
constant.
The scale 's' given by the user specifies the desired number of decimal
digits.
It cannot be > '(digits-1'), so 'max_scale = digits-1'.
If a given decimal number 'N' has 'm' whole digits, 'scale+m' must be <
'digits' oherwise undefined behaviour ocurrs.

I'd put a description like the one above in the docs so that the limit on
total number of digits and its relation with the scale is well documented.

> >
> > Here is a list of other minor issues:
> > =====================================
> >
> > I don't think that is_bounded and is_modulo should be inherited
> > from int_type.
> >
> > is_bounded is intended to be false only for those types which
> > can represent numbers in any range. Even if int_type were
> > unbounded (is_bounded=false), decimal itself will always
> > be bounded, ...
> >
>
> Why?
>
Because it has a constant max_scale.
Unless I'm missing something the algorithms (or some of them) are built
assuming that no scale can be longer than max_scale, but for decimal to be
unbounded, there cannot be any constant maximum.

>
> >
> > Similarly, is_modulo tells whether the numeric type uses
> > modulo arithmetic, as do the unsigned integral types,
> > yet decimal does not do that ...
> >
>
> I don't see this. If int_type just wraps around on overflow,
> then why wouldn't the decimal type itself do the same?
>
Because decimal has its own arithmetic.
For instance, would decimal::add/mul wrap around even if int_type would?

> >
> > ... even if int_type where unsigned, ...
> >
>
> int_type can't be unsigned.
>
Indeed.
I'm sure partly because the algorithms are not built to take into account
the lack of negative range and the modulo arithmetic of unsigned integers.
This is OK of course, but it also implies that decimal itself couldn't be
modulo
either.

> >
> > Currently, the library cannot be put in a precompiled header
> > using BCC because of the 'max_val,min_val' constants. This
> > can be solved by making those constants inlined functions.
> >
>
> But then they wouldn't be constants, would they?
>
They would not be constant 'expressions', but they would be constant
'values', which is all the library needs:

inline int_type const& max_val() { return int_type(~unsigned_int_type(0) >>
1); }

Because of the inline, most compilers will replace the function call
expression 'max_scale()' with the actual value.

> >
> > The documentation is clearly written with some 'old' version
> > in mind. I think all references and comparisons with that
> > older version should be removed from the docs, or at least,
> > put aside on a 'history' section.
> >
>
> OK.
>
> >
> > IMO the documentation should begin with a brief (but complete)
> > overview of what is a 'fixed decimal' number, including the
> > concept of a 'scale' (or 'digits' as I much prefer), and of
> > rounding modes.
> >
>
> I was reticent to do this for fear of talking down to my audience.
> I can add more introductory material if others think it would be
> a good idea.
>
> >
> > I understand why it is not supported to construct a decimal
> > from an int_type, but I think that construction from
> > 'unsigned int' should be supported ...
> >
>
> I'll be happy to put that in if you can give me a use case for it.
>
Since the underlying int_type is likely to be as twice as large as 'int',
there is a big range of valid decimal numbers that can not be given as
initializers, namely (INT_MAX,<int_type_max>].
Allowing unsigned int to be given, that range reduces to
(UINT_MAX,<int_type_max>].
IOWs, this considerably extends the range of integer values that can be used
to initialize a decimal.

> >
> > The docs say:
> >
> > "The conversion will be exact if the string contains no more
> > than scale digits to the right of the decimal point; otherwise
> > the value will be rounded as specified"
> >
> > This is incorrect, I think. If the string contains more than
> > (scale+1) digits, whether to the left or right of the decimal
> > point (or both), rounding will ocurr.
> >
>
> I think the documentation is basically correct; although if
> n * scale**10 can't fit in an int_type, then the behavior is
> undefined; so I guess rounding could occur in that case. 8-)
>
It is basically correct, but incomplete.
If the concept of 'digits' is formalized, alon with its relation to 'scale',
then this statement could simply say that "The conversion will be exact if
the string contains no more than 'digits()' digits (whole and/or decimal)"

Fernando Cacciola