[M3devel] integer overflow
Jay K
jay.krell at cornell.edu
Tue Jan 12 10:23:00 CET 2010
I propose that integer signed overflow always raise an immediate exception.
Word.T should either raise an exception for unsigned overflow, or maybe no exceptions at all.
For folks that want silent wraparound, maybe a separate interface like UnsafeInt.
I propose that FloatMode's integer features not be the way forward.
There are two implementation strategies.
- "check the carry flag"
A processor-specific thing, but possibly something easy for the gcc backend to do.
And very likely easy for the integrated backend.
Probably very efficient.
- internally generate function calls for every arithmetic operation
like how sets are implemented
Implementing most such functions is easy enough in portable C.
Or maybe using Modula-3 and interface Word.
e.g.
void add(int a, int b, int* c, int* overflow)
{
int d = (a + b);
/* overflow if input signs are equal and output sign is different;
if input signs are unequal, overflow is not possible
positive + positive: expect positive, else overflow
negative + negative: expect negative, else overflow
positive + negative: overflow not possible */
*overflow = ((a < 0) == (b < 0) && (d < 0) != (a < 0));
*c = d;
}
void sub(int a, int b, int* c, int* overflow)
{
int d = (a - b);
/* overflow if input signs are unequal and output sign is different than first input;
if input signs are equal, overflow is not possible;
positive - negative: expect positive, overflow if negative
negative - positive: expect negative, overflow if positive
positive - positive, negative - negative: overflow not possible */
*overflow = ((a < 0) != (b < 0) && (d < 0) != (a < 0));
*c = d;
}
#include <limits.h>
void mult(int a, int b, int* c, int* overflow)
{
/* do operation in higher precision and check if it fits */
int64 d = (a * (int64)b);
*c = (int)d;
*overflow = (d >= INT_MIN && d <= INT_MAX);
}
/* for interface Word */
typedef unsigned uint;
void addu(uint a, uint b, uint* c, int* overflow)
{
uint d = (a + b);
/* overflow if output less than either input */
*overflow = (d < a);
*c = d;
}
void subu(uint a, uint b, uint* c, int* overflow)
{
uint d = (a - b);
/* overflow if output greater than first input */
*overflow = (d > a);
*c = d;
}
void multu(uint a, uint b, uint* c, int* overflow)
{
/* operate at higher precision and see if it fits */
uint64 d = (a * (uint64)b);
*overflow = (d <= UINT_MAX);
*c = (uint)d;
}
void multLU(uint64 a, uint64 b, uint64* c, int* overflow)
{
/* break it down into smaller operations, not shown, but not difficult */
}
Yes I know this is inefficient, but such is a possible price of portable safety.
A hybrid is probably possible if the gcc backend support must be processor specific and we gradually provide the implementations.
- Jay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20100112/9a600909/attachment-0002.html>
More information about the M3devel
mailing list