Changes in uspace/lib/softint/generic/multiplication.c [d27ed12:9539be6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/softint/generic/multiplication.c
rd27ed12 r9539be6 29 29 /** @addtogroup softint 30 30 * @{ 31 */ 31 */ 32 32 /** 33 33 * @file … … 36 36 37 37 #include <multiplication.h> 38 #include <stdint.h> 38 #include <stdint.h> 39 39 40 /** Set 1 to return MAX_INT64 or MIN_INT64on overflow */40 /** Set 1 to return INT64_MAX or INT64_MIN on overflow */ 41 41 #ifndef SOFTINT_CHECK_OF 42 # define SOFTINT_CHECK_OF042 #define SOFTINT_CHECK_OF 0 43 43 #endif 44 44 45 /** 46 * Multiply two integers and return long long as result.45 /** Multiply two integers and return long long as result. 46 * 47 47 * This function is overflow safe. 48 * @param a 49 * @param b 50 * @result 48 * 51 49 */ 52 50 static unsigned long long mul(unsigned int a, unsigned int b) { 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 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 68 63 return t3; 69 64 } … … 74 69 long long __muldi3 (long long a, long long b) 75 70 { 76 long long result;77 unsigned long long t1,t2;78 unsigned long long a1, a2, b1, b2;79 71 char neg = 0; 80 72 81 73 if (a < 0) { 82 74 neg = !neg; 83 75 a = -a; 84 76 } 85 77 86 78 if (b < 0) { 87 79 neg = !neg; 88 80 b = -b; 89 81 } 90 91 a1 = a >> 32;92 b1 = b >> 32;93 94 a2 = a & (MAX_UINT32);95 b2 = b & (MAX_UINT32);96 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 97 89 if (SOFTINT_CHECK_OF && (a1 != 0) && (b1 != 0)) { 98 / / error, overflow99 return (neg ?MIN_INT64:MAX_INT64);90 /* Error (overflow) */ 91 return (neg ? INT64_MIN : INT64_MAX); 100 92 } 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); 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); 108 102 } 109 103 110 104 t1 = t1 << 32; 111 t2 = mul(a2,b2);105 unsigned long long t2 = mul(a2, b2); 112 106 t2 += t1; 113 107 114 108 /* t2 & (1ull << 63) - if this bit is set in unsigned long long, 115 109 * result does not fit in signed one */ 116 110 if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) { 117 111 // error, overflow 118 return (neg ?MIN_INT64:MAX_INT64);112 return (neg ? INT64_MIN : INT64_MAX); 119 113 } 120 121 result = t2; 122 123 if (neg) { 114 115 long long result = t2; 116 if (neg) 124 117 result = -result; 125 } 126 118 127 119 return result; 128 } 120 } 129 121 130 122 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.