The attached source presents a multiplication routine with
built-in overflow detection. For x86/GCC, we can avoid
floating point arithmetic by using a small assembler
fragment. Support for other platforms can be added as
necessary.
There are two distinct uses for this in PHP:
- the engine needs to verify whether the result of a
integer multiplication fits into its integral type
(script context)
- the memory allocator has to ensure that no integer
overflows happen
Your input is appreciated.
- Sascha
/* Copyright (c) 2003 Sascha Schumann */
#include <limits.h>
typedef enum {
MR_OK,
MR_OVERFLOW,
MR_OVERFLOW_FP_STORED
} mul_result;
mul_result signed_multiply_long(long a, long b, long *result, double *dresult)
#if defined(__i386__) && defined(__GNUC__)
{
int of;
__asm__ ("imul %3,%0\n" \
"adc $0,%1"
: "=r"(a),"=r"(of)
: "0"(a), "r"(b), "1"(0));
if (of) {
return MR_OVERFLOW;
}
*result = a;
return MR_OK;
}
#else
{
double dr;
dr = (double) a * (double) b;
if (dr >= LONG_MAX || dr <= LONG_MIN) {
*dresult = dr;
return MR_OVERFLOW_FP_STORED;
}
*result = a * b;
return MR_OK;
}
#endif
#ifndef NO_DRIVER
#include <stdio.h>
void test(long a, long b)
{
long l = 0;
double d = 0.0;
printf("%ld * %ld: %d\n",
a, b, signed_multiply_long(a, b, &l, &d));
printf("l=%ld, d=%f\n\n", l, d);
}
int main(void)
{
test(100,-100);
test(100000, 5);
test(100000, 100000);
return 0;
}
#endif
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php