summaryrefslogtreecommitdiff
path: root/Zend/zend_multiply.h
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>2004-03-17 09:25:52 +0000
committerAndi Gutmans <andi@php.net>2004-03-17 09:25:52 +0000
commit29ee03aa55688ca9a6441c3aa1ed8be905830027 (patch)
tree3c6cf763687b89bb9d1d971d9dccad327058df70 /Zend/zend_multiply.h
parent8aea19c345fa9f92a8fc7b6cedcb16c9f385e1c3 (diff)
downloadphp-git-29ee03aa55688ca9a6441c3aa1ed8be905830027.tar.gz
- Apply Ard's patch to support multiplication & overflow on both 32bit
and 64bit machines
Diffstat (limited to 'Zend/zend_multiply.h')
-rw-r--r--Zend/zend_multiply.h46
1 files changed, 19 insertions, 27 deletions
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index 2e6fe6a11a..eda4ca135e 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 2003-2004 Sascha Schumann |
+ | Copyright (c) 1998-2004 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -12,36 +12,28 @@
| obtain it through the world-wide-web, please send a note to |
| license@zend.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Sascha Schumann <sascha@schumann.cx> |
+ | Author: Ard Biesheuvel <ard@ard.nu> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
-#if defined(__i386__) && defined(__GNUC__)
+#define HALF (4*sizeof(long))
+#define UH(b) ((b) >> HALF)
+#define LH(a) ((a) & ~(-1L << HALF))
-#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
- __asm__ ("imul %3,%0\n" \
- "adc $0,%1" \
- : "=r"(__tmpvar),"=r"(usedval) \
- : "0"(a), "r"(b), "1"(0)); \
- if (usedval) (dval) = (double) (a) * (double) (b); \
- else (lval) = __tmpvar; \
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+ long __mid,__upr,__res = (a) * (b); \
+ if (-(long)(a) > 0 && -(long)(b) > 0) { /* overflow intended */ \
+ __mid = UH(-(a))*LH(-(b)) + LH(-(a))*UH(-(b)); \
+ __upr = UH(-(a))*UH(-(b)) + UH(__mid); \
+ } else { \
+ __mid = UH(a)*LH(b) + LH(a)*UH(b); \
+ __upr = UH(a)*UH(b) + UH(__mid); \
+ } \
+ if (((usedval) = !((__upr==-1&&__res<0)||(!__upr&&__res>=0)))) { \
+ (dval) = (double)(a)*(double)(b); \
+ } else { \
+ (lval) = __res; \
+ } \
} while (0)
-
-#else
-
-#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- double __tmpvar = (double) (a) * (double) (b); \
- \
- if (__tmpvar >= LONG_MAX || __tmpvar <= LONG_MIN) { \
- (dval) = __tmpvar; \
- (usedval) = 1; \
- } else { \
- (lval) = (a) * (b); \
- (usedval) = 0; \
- } \
-} while (0)
-
-#endif