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

Reply via email to