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