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