Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/softint/generic/multiplication.c

    r9539be6 rd27ed12  
    2929/** @addtogroup softint
    3030 * @{
    31  */
     31 */ 
    3232/**
    3333 * @file
     
    3636
    3737#include <multiplication.h>
    38 #include <stdint.h>
     38#include <stdint.h> 
    3939
    40 /** Set 1 to return INT64_MAX or INT64_MIN on overflow */
     40/** Set 1 to return MAX_INT64 or MIN_INT64 on overflow */
    4141#ifndef SOFTINT_CHECK_OF
    42         #define SOFTINT_CHECK_OF 0
     42# define SOFTINT_CHECK_OF 0
    4343#endif
    4444
    45 /** Multiply two integers and return long long as result.
    46  *
     45/**
     46 * Multiply two integers and return long long as result.
    4747 * This function is overflow safe.
    48  *
     48 * @param a
     49 * @param b
     50 * @result
    4951 */
    5052static unsigned long long mul(unsigned int a, unsigned int b) {
    51         unsigned int a1 = a >> 16;
    52         unsigned int a2 = a & UINT16_MAX;
    53         unsigned int b1 = b >> 16;
    54         unsigned int b2 = b & UINT16_MAX;
    55        
    56         unsigned long long t1 = a1 * b1;
    57         unsigned long long t2 = a1 * b2;
    58         t2 += a2 * b1;
    59         unsigned long long t3 = a2 * b2;
    60        
    61         t3 = (((t1 << 16) + t2) << 16) + t3;
    62        
     53        unsigned int a1, a2, b1, b2;
     54        unsigned long long t1, t2, t3; 
     55
     56        a1 = a >> 16;
     57        a2 = a & MAX_UINT16;
     58        b1 = b >> 16;
     59        b2 = b & MAX_UINT16;
     60
     61        t1 = a1 * b1;
     62        t2 = a1*b2;
     63        t2 += a2*b1;
     64        t3 = a2*b2;
     65
     66        t3 = (((t1 << 16) + t2) << 16) + t3;
     67
    6368        return t3;
    6469}
     
    6974long long __muldi3 (long long a, long long b)
    7075{
     76        long long result;
     77        unsigned long long t1,t2;
     78        unsigned long long a1, a2, b1, b2;
    7179        char neg = 0;
    72        
     80
    7381        if (a < 0) {
    7482                neg = !neg;
    7583                a = -a;
    7684        }
    77        
     85
    7886        if (b < 0) {
    7987                neg = !neg;
    8088                b = -b;
    8189        }
    82        
    83         unsigned long long a1 = a >> 32;
    84         unsigned long long b1 = b >> 32;
    85        
    86         unsigned long long a2 = a & (UINT32_MAX);
    87         unsigned long long b2 = b & (UINT32_MAX);
    88        
     90
     91        a1 = a >> 32;
     92        b1 = b >> 32;
     93
     94        a2 = a & (MAX_UINT32);
     95        b2 = b & (MAX_UINT32);
     96
    8997        if (SOFTINT_CHECK_OF && (a1 != 0) && (b1 != 0)) {
    90                 /* Error (overflow) */
    91                 return (neg ? INT64_MIN : INT64_MAX);
     98                // error, overflow
     99                return (neg?MIN_INT64:MAX_INT64);
    92100        }
    93        
    94         /* (if OF checked) a1 or b1 is zero => result fits in 64 bits,
    95          * no need to another overflow check
    96          */
    97         unsigned long long t1 = mul(a1, b2) + mul(b1, a2);
    98        
    99         if ((SOFTINT_CHECK_OF) && (t1 > UINT32_MAX)) {
    100                 /* Error (overflow) */
    101                 return (neg ? INT64_MIN : INT64_MAX);
     101
     102        // (if OF checked) a1 or b1 is zero => result fits in 64 bits, no need to another overflow check
     103        t1 = mul(a1,b2) + mul(b1,a2);   
     104
     105        if (SOFTINT_CHECK_OF && t1 > MAX_UINT32) {
     106                // error, overflow
     107                return (neg?MIN_INT64:MAX_INT64);
    102108        }
    103        
     109
    104110        t1 = t1 << 32;
    105         unsigned long long t2 = mul(a2, b2);
     111        t2 = mul(a2,b2);
    106112        t2 += t1;
    107        
     113
    108114        /* t2 & (1ull << 63) - if this bit is set in unsigned long long,
    109115         * result does not fit in signed one */
    110116        if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) {
    111117                // error, overflow
    112                 return (neg ? INT64_MIN : INT64_MAX);
     118                return (neg?MIN_INT64:MAX_INT64);
    113119        }
    114        
    115         long long result = t2;
    116         if (neg)
     120
     121        result = t2;
     122
     123        if (neg) {
    117124                result = -result;
    118        
     125        }
     126
    119127        return result;
    120 }
     128}       
    121129
    122130/** @}
Note: See TracChangeset for help on using the changeset viewer.