M
madamemandm
On Apr 26, 7:59 pm, (e-mail address removed) (Gordon Burditt) wrote:
[snip]
Sure thing.
The mixed sign tests look wrong to me. In both of them you are
subtracting VALUE_MIN from a postitive number. This is gaurenteed to
produce a value greater than VALUE_MAX and is therefore undefined.
E.g. let a = 15, b = -2, VALUE_MIN = -2147483648, VALUE_MAX =
2147483647 then the test selected is
(((-b) - VALUE_MIN) / (-b)) - 1 < a
Substituting the values gets.
(((-(-2)) - (-2147483648)) / (-(-2))) - 1 < 15
Simplifying a bit.
((2 - (-2147483648)) / 2) < 15
(2147483650 / 2) < 15
And 2147483650 > 2147483647.
Even if it was correct, it would still be illustrative of the value of
adding the ability to check for overflow to the core language.
Overflow on multiplication can be detected in just a few assembly
instruction on quite a few processors. I'd be impressed if a compiler
managed to convert that source into those instructions.
Martin Shobe
[snip]
The code I'm including here is for signed multiplication only.
Someone might find it useful. Ok, try to break it.
Sure thing.
I'm not sure
I have properly accounted for all the possible wierdities on a
non-2's-complement machine, and I don't have one to test on.
The main source file is pretty simple, for making the code type-generic:
______________________________________________________
#include <limits.h>
#define VALUE_T signed long
#define VALUE_MIN LONG_MIN
#define VALUE_MAX LONG_MAX
#define mul_will_overflow sl_mul_will_overflow
#include "smul.inc"
______________________________________________________
and it included the appropriate code, here for signed multiply:
______________________________________________________
#include "libovflo.h" /* contains function prototypes for the library */
int
mul_will_overflow(VALUE_T a, VALUE_T b, VALUE_T * c)
{
if (a == 0 || a == 1 || b == 0 || b == 1)
{
/* cannot overflow */
}
else
{
if (VALUE_MAX - 1 < -1 - VALUE_MIN)
{
/* -VALUE_MIN overflows */
if (a == VALUE_MIN || b == VALUE_MIN)
{
/* -1 * VALUE_MIN overflows */
/* 0 * VALUE_MIN and 1 * VALUE_MIN handled above */
/* anything else overflows */
return 1;
}
}
if (a > 0)
{
if (b > 0)
{
/* a, b positive */
if (VALUE_MAX / b < a)
{
return 1;
}
}
else
{
/* a positive, b negative */
if ((((-b) - VALUE_MIN) / (-b)) - 1 < a)
{
return 1;
}
}
}
else
{
if (b > 0)
{
/* a negative, b positive */
if (((b - VALUE_MIN) / b) - 1 < (-a))
{
return 1;
}
}
else
{
/* a, b negative */
if (VALUE_MAX / (-b) < (-a))
{
return 1;
}
}
}
}
if (c)
{
*c = a * b;
}
return 0;}
The mixed sign tests look wrong to me. In both of them you are
subtracting VALUE_MIN from a postitive number. This is gaurenteed to
produce a value greater than VALUE_MAX and is therefore undefined.
E.g. let a = 15, b = -2, VALUE_MIN = -2147483648, VALUE_MAX =
2147483647 then the test selected is
(((-b) - VALUE_MIN) / (-b)) - 1 < a
Substituting the values gets.
(((-(-2)) - (-2147483648)) / (-(-2))) - 1 < 15
Simplifying a bit.
((2 - (-2147483648)) / 2) < 15
(2147483650 / 2) < 15
And 2147483650 > 2147483647.
Even if it was correct, it would still be illustrative of the value of
adding the ability to check for overflow to the core language.
Overflow on multiplication can be detected in just a few assembly
instruction on quite a few processors. I'd be impressed if a compiler
managed to convert that source into those instructions.
Martin Shobe