|
Boost : |
From: wb_at_[hidden]
Date: 2001-09-14 17:23:19
Issue #1: special case
-----------------------
I have a concern about the way a special case of the gcd algorithm is
handled at the moment.
In common_factor.hpp we currently have:
// Non-recursive case
template < unsigned long Value1 >
struct static_gcd_helper_t< Value1, 0UL >
{
BOOST_STATIC_CONSTANT( unsigned long, value = Value1 );
};
This is generally fine, but not when the template argument is also
0uL. In this case, the above code would give a result of 0uL -- but
the Euclidean algorithm explicitly requires that not both its inputs be
zero. (The rationale, perhaps oversimplified, is that no divisor can
meaningfully be zero, since division by 0 is undefined, and no other
answer is correct.)
I respectfully recommend that a specialization, along the following
lines, be inserted to account for this special case and to force the
compiler to issue a diagnostic if user code ever happens to provoke
this situation:
// Euclidean algorithm excludes this case
template < >
struct static_gcd_helper_t< 0uL, 0uL >
{
// *** gcd<0,0>::value is explicitly not defined ***
};
Issue #2: extension
--------------------
The classic Euclidean algorithm is not defined for negative values.
However, I believe it is a generally useful and straightforward
extension of the algorithm to provide a useful result in such a
circumstance. Indeed, the supplied run-time function already does so,
it seems; should not the compile-time computation do the same? (But
see Issue #3 below.)
Issue #3: question for experts
-------------------------------
This code (as well, I'm sure, as many other programmers' code) uses the
C++ remainder operator % as if it were a mod operator. Technically, of
course, remaindering is a different operation from taking a modulus.
Does this distinction have any practical significance in the context of
the classical (non-negative) Euclidean algorithm? (I believe not.)
But what about the case of the extension described above? Portability
is, of course, the true concern here: recall that the C++ Standard
describes (5.6/4) only the relationship between the division and
remainder operators, and does not prescribe either in isolation; only a
non-normative footnote refers to a "preferred algorithm for integer
division ... in which the quotient is always rounded toward zero."
If use of remaindering on negative operands is deemed non-portable, then
I would recommend against the extension as described in Issue #2 above,
and also in the library's supplied run-time function, unless a portable
workaround can be provided.
- WEB
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk