| /* { dg-require-effective-target int32plus } */ |
| |
| typedef long unsigned int size_t; |
| extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); |
| |
| static void |
| encode (words, low, hi) |
| long *words; |
| unsigned long low; |
| long hi; |
| { |
| words[0] = ((low) & (((unsigned long) 1 << (sizeof(unsigned long) / 2)) - 1)); |
| words[1] = ((unsigned long) (low) >> sizeof(unsigned long) / 2); |
| words[2] = ((hi) & (((unsigned long) 1 << (sizeof(unsigned long) / 2)) - 1)); |
| words[3] = ((unsigned long) (hi) >> sizeof(unsigned long) / 2); |
| } |
| |
| static void |
| decode (words, low, hi) |
| long *words; |
| unsigned long *low; |
| long *hi; |
| { |
| *low = words[0] + words[1] * ((unsigned long) 1 << sizeof(unsigned long) / 2); |
| *hi = words[2] + words[3] * ((unsigned long) 1 << sizeof(unsigned long) / 2); |
| } |
| |
| int |
| neg_double (l1, h1, lv, hv) |
| unsigned long l1; |
| long h1; |
| unsigned long *lv; |
| long *hv; |
| { |
| if (l1 == 0) |
| { |
| *lv = 0; |
| *hv = - h1; |
| return (*hv & h1) < 0; |
| } |
| else |
| { |
| *lv = -l1; |
| *hv = ~h1; |
| return 0; |
| } |
| } |
| |
| int |
| add_double (l1, h1, l2, h2, lv, hv) |
| unsigned long l1, l2; |
| long h1, h2; |
| unsigned long *lv; |
| long *hv; |
| { |
| unsigned long l; |
| long h; |
| |
| l = l1 + l2; |
| h = h1 + h2 + (l < l1); |
| |
| *lv = l; |
| *hv = h; |
| return ((~((h1) ^ (h2)) & ((h1) ^ (h))) < 0); |
| } |
| |
| int |
| mul_double (l1, h1, l2, h2, lv, hv) |
| unsigned long l1, l2; |
| long h1, h2; |
| unsigned long *lv; |
| long *hv; |
| { |
| long arg1[4]; |
| long arg2[4]; |
| long prod[4 * 2]; |
| unsigned long carry; |
| int i, j, k; |
| unsigned long toplow, neglow; |
| long tophigh, neghigh; |
| |
| encode (arg1, l1, h1); |
| encode (arg2, l2, h2); |
| |
| memset ((char *) prod, 0, sizeof prod); |
| |
| for (i = 0; i < 4; i++) |
| { |
| carry = 0; |
| for (j = 0; j < 4; j++) |
| { |
| k = i + j; |
| |
| carry += arg1[i] * arg2[j]; |
| |
| carry += prod[k]; |
| prod[k] = ((carry) & (((unsigned long) 1 << (sizeof(unsigned long) / 2)) - 1)); |
| carry = ((unsigned long) (carry) >> sizeof(unsigned long) / 2); |
| } |
| prod[i + 4] = carry; |
| } |
| |
| decode (prod, lv, hv); |
| |
| |
| |
| decode (prod + 4, &toplow, &tophigh); |
| if (h1 < 0) |
| { |
| neg_double (l2, h2, &neglow, &neghigh); |
| add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh); |
| } |
| if (h2 < 0) |
| { |
| neg_double (l1, h1, &neglow, &neghigh); |
| add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh); |
| } |
| return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0; |
| } |