1*25c28e83SPiotr Jasiukajtis /* 2*25c28e83SPiotr Jasiukajtis * CDDL HEADER START 3*25c28e83SPiotr Jasiukajtis * 4*25c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the 5*25c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License"). 6*25c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License. 7*25c28e83SPiotr Jasiukajtis * 8*25c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*25c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing. 10*25c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions 11*25c28e83SPiotr Jasiukajtis * and limitations under the License. 12*25c28e83SPiotr Jasiukajtis * 13*25c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each 14*25c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*25c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the 16*25c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying 17*25c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner] 18*25c28e83SPiotr Jasiukajtis * 19*25c28e83SPiotr Jasiukajtis * CDDL HEADER END 20*25c28e83SPiotr Jasiukajtis */ 21*25c28e83SPiotr Jasiukajtis 22*25c28e83SPiotr Jasiukajtis /* 23*25c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24*25c28e83SPiotr Jasiukajtis */ 25*25c28e83SPiotr Jasiukajtis /* 26*25c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27*25c28e83SPiotr Jasiukajtis * Use is subject to license terms. 28*25c28e83SPiotr Jasiukajtis */ 29*25c28e83SPiotr Jasiukajtis 30*25c28e83SPiotr Jasiukajtis #pragma weak fmal = __fmal 31*25c28e83SPiotr Jasiukajtis 32*25c28e83SPiotr Jasiukajtis #include "libm.h" 33*25c28e83SPiotr Jasiukajtis #include "fma.h" 34*25c28e83SPiotr Jasiukajtis #include "fenv_inlines.h" 35*25c28e83SPiotr Jasiukajtis 36*25c28e83SPiotr Jasiukajtis #if defined(__sparc) 37*25c28e83SPiotr Jasiukajtis 38*25c28e83SPiotr Jasiukajtis static const union { 39*25c28e83SPiotr Jasiukajtis unsigned i[2]; 40*25c28e83SPiotr Jasiukajtis double d; 41*25c28e83SPiotr Jasiukajtis } C[] = { 42*25c28e83SPiotr Jasiukajtis { 0x3fe00000u, 0 }, 43*25c28e83SPiotr Jasiukajtis { 0x40000000u, 0 }, 44*25c28e83SPiotr Jasiukajtis { 0x3ef00000u, 0 }, 45*25c28e83SPiotr Jasiukajtis { 0x3e700000u, 0 }, 46*25c28e83SPiotr Jasiukajtis { 0x41300000u, 0 }, 47*25c28e83SPiotr Jasiukajtis { 0x3e300000u, 0 }, 48*25c28e83SPiotr Jasiukajtis { 0x3b300000u, 0 }, 49*25c28e83SPiotr Jasiukajtis { 0x38300000u, 0 }, 50*25c28e83SPiotr Jasiukajtis { 0x42300000u, 0 }, 51*25c28e83SPiotr Jasiukajtis { 0x3df00000u, 0 }, 52*25c28e83SPiotr Jasiukajtis { 0x7fe00000u, 0 }, 53*25c28e83SPiotr Jasiukajtis { 0x00100000u, 0 }, 54*25c28e83SPiotr Jasiukajtis { 0x00100001u, 0 }, 55*25c28e83SPiotr Jasiukajtis { 0, 0 }, 56*25c28e83SPiotr Jasiukajtis { 0x7ff00000u, 0 }, 57*25c28e83SPiotr Jasiukajtis { 0x7ff00001u, 0 } 58*25c28e83SPiotr Jasiukajtis }; 59*25c28e83SPiotr Jasiukajtis 60*25c28e83SPiotr Jasiukajtis #define half C[0].d 61*25c28e83SPiotr Jasiukajtis #define two C[1].d 62*25c28e83SPiotr Jasiukajtis #define twom16 C[2].d 63*25c28e83SPiotr Jasiukajtis #define twom24 C[3].d 64*25c28e83SPiotr Jasiukajtis #define two20 C[4].d 65*25c28e83SPiotr Jasiukajtis #define twom28 C[5].d 66*25c28e83SPiotr Jasiukajtis #define twom76 C[6].d 67*25c28e83SPiotr Jasiukajtis #define twom124 C[7].d 68*25c28e83SPiotr Jasiukajtis #define two36 C[8].d 69*25c28e83SPiotr Jasiukajtis #define twom32 C[9].d 70*25c28e83SPiotr Jasiukajtis #define huge C[10].d 71*25c28e83SPiotr Jasiukajtis #define tiny C[11].d 72*25c28e83SPiotr Jasiukajtis #define tiny2 C[12].d 73*25c28e83SPiotr Jasiukajtis #define zero C[13].d 74*25c28e83SPiotr Jasiukajtis #define inf C[14].d 75*25c28e83SPiotr Jasiukajtis #define snan C[15].d 76*25c28e83SPiotr Jasiukajtis 77*25c28e83SPiotr Jasiukajtis static const unsigned int fsr_rm = 0xc0000000u; 78*25c28e83SPiotr Jasiukajtis 79*25c28e83SPiotr Jasiukajtis /* 80*25c28e83SPiotr Jasiukajtis * fmal for SPARC: 128-bit quad precision, big-endian 81*25c28e83SPiotr Jasiukajtis */ 82*25c28e83SPiotr Jasiukajtis long double 83*25c28e83SPiotr Jasiukajtis __fmal(long double x, long double y, long double z) { 84*25c28e83SPiotr Jasiukajtis union { 85*25c28e83SPiotr Jasiukajtis unsigned int i[4]; 86*25c28e83SPiotr Jasiukajtis long double q; 87*25c28e83SPiotr Jasiukajtis } xx, yy, zz; 88*25c28e83SPiotr Jasiukajtis union { 89*25c28e83SPiotr Jasiukajtis unsigned int i[2]; 90*25c28e83SPiotr Jasiukajtis double d; 91*25c28e83SPiotr Jasiukajtis } u; 92*25c28e83SPiotr Jasiukajtis double dx[5], dy[5], dxy[9], c, s; 93*25c28e83SPiotr Jasiukajtis unsigned int xy0, xy1, xy2, xy3, xy4, xy5, xy6, xy7; 94*25c28e83SPiotr Jasiukajtis unsigned int z0, z1, z2, z3, z4, z5, z6, z7; 95*25c28e83SPiotr Jasiukajtis unsigned int rm, sticky; 96*25c28e83SPiotr Jasiukajtis unsigned int fsr; 97*25c28e83SPiotr Jasiukajtis int hx, hy, hz, ex, ey, ez, exy, sxy, sz, e, ibit; 98*25c28e83SPiotr Jasiukajtis int cx, cy, cz; 99*25c28e83SPiotr Jasiukajtis volatile double dummy; 100*25c28e83SPiotr Jasiukajtis 101*25c28e83SPiotr Jasiukajtis /* extract the high order words of the arguments */ 102*25c28e83SPiotr Jasiukajtis xx.q = x; 103*25c28e83SPiotr Jasiukajtis yy.q = y; 104*25c28e83SPiotr Jasiukajtis zz.q = z; 105*25c28e83SPiotr Jasiukajtis hx = xx.i[0] & ~0x80000000; 106*25c28e83SPiotr Jasiukajtis hy = yy.i[0] & ~0x80000000; 107*25c28e83SPiotr Jasiukajtis hz = zz.i[0] & ~0x80000000; 108*25c28e83SPiotr Jasiukajtis 109*25c28e83SPiotr Jasiukajtis /* 110*25c28e83SPiotr Jasiukajtis * distinguish zero, finite nonzero, infinite, and quiet nan 111*25c28e83SPiotr Jasiukajtis * arguments; raise invalid and return for signaling nans 112*25c28e83SPiotr Jasiukajtis */ 113*25c28e83SPiotr Jasiukajtis if (hx >= 0x7fff0000) { 114*25c28e83SPiotr Jasiukajtis if ((hx & 0xffff) | xx.i[1] | xx.i[2] | xx.i[3]) { 115*25c28e83SPiotr Jasiukajtis if (!(hx & 0x8000)) { 116*25c28e83SPiotr Jasiukajtis /* signaling nan, raise invalid */ 117*25c28e83SPiotr Jasiukajtis dummy = snan; 118*25c28e83SPiotr Jasiukajtis dummy += snan; 119*25c28e83SPiotr Jasiukajtis xx.i[0] |= 0x8000; 120*25c28e83SPiotr Jasiukajtis return (xx.q); 121*25c28e83SPiotr Jasiukajtis } 122*25c28e83SPiotr Jasiukajtis cx = 3; /* quiet nan */ 123*25c28e83SPiotr Jasiukajtis } else 124*25c28e83SPiotr Jasiukajtis cx = 2; /* inf */ 125*25c28e83SPiotr Jasiukajtis } else if (hx == 0) { 126*25c28e83SPiotr Jasiukajtis cx = (xx.i[1] | xx.i[2] | xx.i[3]) ? 1 : 0; 127*25c28e83SPiotr Jasiukajtis /* subnormal or zero */ 128*25c28e83SPiotr Jasiukajtis } else 129*25c28e83SPiotr Jasiukajtis cx = 1; /* finite nonzero */ 130*25c28e83SPiotr Jasiukajtis 131*25c28e83SPiotr Jasiukajtis if (hy >= 0x7fff0000) { 132*25c28e83SPiotr Jasiukajtis if ((hy & 0xffff) | yy.i[1] | yy.i[2] | yy.i[3]) { 133*25c28e83SPiotr Jasiukajtis if (!(hy & 0x8000)) { 134*25c28e83SPiotr Jasiukajtis dummy = snan; 135*25c28e83SPiotr Jasiukajtis dummy += snan; 136*25c28e83SPiotr Jasiukajtis yy.i[0] |= 0x8000; 137*25c28e83SPiotr Jasiukajtis return (yy.q); 138*25c28e83SPiotr Jasiukajtis } 139*25c28e83SPiotr Jasiukajtis cy = 3; 140*25c28e83SPiotr Jasiukajtis } else 141*25c28e83SPiotr Jasiukajtis cy = 2; 142*25c28e83SPiotr Jasiukajtis } else if (hy == 0) { 143*25c28e83SPiotr Jasiukajtis cy = (yy.i[1] | yy.i[2] | yy.i[3]) ? 1 : 0; 144*25c28e83SPiotr Jasiukajtis } else 145*25c28e83SPiotr Jasiukajtis cy = 1; 146*25c28e83SPiotr Jasiukajtis 147*25c28e83SPiotr Jasiukajtis if (hz >= 0x7fff0000) { 148*25c28e83SPiotr Jasiukajtis if ((hz & 0xffff) | zz.i[1] | zz.i[2] | zz.i[3]) { 149*25c28e83SPiotr Jasiukajtis if (!(hz & 0x8000)) { 150*25c28e83SPiotr Jasiukajtis dummy = snan; 151*25c28e83SPiotr Jasiukajtis dummy += snan; 152*25c28e83SPiotr Jasiukajtis zz.i[0] |= 0x8000; 153*25c28e83SPiotr Jasiukajtis return (zz.q); 154*25c28e83SPiotr Jasiukajtis } 155*25c28e83SPiotr Jasiukajtis cz = 3; 156*25c28e83SPiotr Jasiukajtis } else 157*25c28e83SPiotr Jasiukajtis cz = 2; 158*25c28e83SPiotr Jasiukajtis } else if (hz == 0) { 159*25c28e83SPiotr Jasiukajtis cz = (zz.i[1] | zz.i[2] | zz.i[3]) ? 1 : 0; 160*25c28e83SPiotr Jasiukajtis } else 161*25c28e83SPiotr Jasiukajtis cz = 1; 162*25c28e83SPiotr Jasiukajtis 163*25c28e83SPiotr Jasiukajtis /* get the fsr and clear current exceptions */ 164*25c28e83SPiotr Jasiukajtis __fenv_getfsr32(&fsr); 165*25c28e83SPiotr Jasiukajtis fsr &= ~FSR_CEXC; 166*25c28e83SPiotr Jasiukajtis 167*25c28e83SPiotr Jasiukajtis /* handle all other zero, inf, and nan cases */ 168*25c28e83SPiotr Jasiukajtis if (cx != 1 || cy != 1 || cz != 1) { 169*25c28e83SPiotr Jasiukajtis /* if x or y is a quiet nan, return it */ 170*25c28e83SPiotr Jasiukajtis if (cx == 3) { 171*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 172*25c28e83SPiotr Jasiukajtis return (x); 173*25c28e83SPiotr Jasiukajtis } 174*25c28e83SPiotr Jasiukajtis if (cy == 3) { 175*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 176*25c28e83SPiotr Jasiukajtis return (y); 177*25c28e83SPiotr Jasiukajtis } 178*25c28e83SPiotr Jasiukajtis 179*25c28e83SPiotr Jasiukajtis /* if x*y is 0*inf, raise invalid and return the default nan */ 180*25c28e83SPiotr Jasiukajtis if ((cx == 0 && cy == 2) || (cx == 2 && cy == 0)) { 181*25c28e83SPiotr Jasiukajtis dummy = zero; 182*25c28e83SPiotr Jasiukajtis dummy *= inf; 183*25c28e83SPiotr Jasiukajtis zz.i[0] = 0x7fffffff; 184*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[2] = zz.i[3] = 0xffffffff; 185*25c28e83SPiotr Jasiukajtis return (zz.q); 186*25c28e83SPiotr Jasiukajtis } 187*25c28e83SPiotr Jasiukajtis 188*25c28e83SPiotr Jasiukajtis /* if z is a quiet nan, return it */ 189*25c28e83SPiotr Jasiukajtis if (cz == 3) { 190*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 191*25c28e83SPiotr Jasiukajtis return (z); 192*25c28e83SPiotr Jasiukajtis } 193*25c28e83SPiotr Jasiukajtis 194*25c28e83SPiotr Jasiukajtis /* 195*25c28e83SPiotr Jasiukajtis * now none of x, y, or z is nan; handle cases where x or y 196*25c28e83SPiotr Jasiukajtis * is inf 197*25c28e83SPiotr Jasiukajtis */ 198*25c28e83SPiotr Jasiukajtis if (cx == 2 || cy == 2) { 199*25c28e83SPiotr Jasiukajtis /* 200*25c28e83SPiotr Jasiukajtis * if z is also inf, either we have inf-inf or 201*25c28e83SPiotr Jasiukajtis * the result is the same as z depending on signs 202*25c28e83SPiotr Jasiukajtis */ 203*25c28e83SPiotr Jasiukajtis if (cz == 2) { 204*25c28e83SPiotr Jasiukajtis if ((int) ((xx.i[0] ^ yy.i[0]) ^ zz.i[0]) < 0) { 205*25c28e83SPiotr Jasiukajtis dummy = inf; 206*25c28e83SPiotr Jasiukajtis dummy -= inf; 207*25c28e83SPiotr Jasiukajtis zz.i[0] = 0x7fffffff; 208*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[2] = zz.i[3] = 209*25c28e83SPiotr Jasiukajtis 0xffffffff; 210*25c28e83SPiotr Jasiukajtis return (zz.q); 211*25c28e83SPiotr Jasiukajtis } 212*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 213*25c28e83SPiotr Jasiukajtis return (z); 214*25c28e83SPiotr Jasiukajtis } 215*25c28e83SPiotr Jasiukajtis 216*25c28e83SPiotr Jasiukajtis /* otherwise the result is inf with appropriate sign */ 217*25c28e83SPiotr Jasiukajtis zz.i[0] = ((xx.i[0] ^ yy.i[0]) & 0x80000000) | 218*25c28e83SPiotr Jasiukajtis 0x7fff0000; 219*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[2] = zz.i[3] = 0; 220*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 221*25c28e83SPiotr Jasiukajtis return (zz.q); 222*25c28e83SPiotr Jasiukajtis } 223*25c28e83SPiotr Jasiukajtis 224*25c28e83SPiotr Jasiukajtis /* if z is inf, return it */ 225*25c28e83SPiotr Jasiukajtis if (cz == 2) { 226*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 227*25c28e83SPiotr Jasiukajtis return (z); 228*25c28e83SPiotr Jasiukajtis } 229*25c28e83SPiotr Jasiukajtis 230*25c28e83SPiotr Jasiukajtis /* 231*25c28e83SPiotr Jasiukajtis * now x, y, and z are all finite; handle cases where x or y 232*25c28e83SPiotr Jasiukajtis * is zero 233*25c28e83SPiotr Jasiukajtis */ 234*25c28e83SPiotr Jasiukajtis if (cx == 0 || cy == 0) { 235*25c28e83SPiotr Jasiukajtis /* either we have 0-0 or the result is the same as z */ 236*25c28e83SPiotr Jasiukajtis if (cz == 0 && (int) ((xx.i[0] ^ yy.i[0]) ^ zz.i[0]) < 237*25c28e83SPiotr Jasiukajtis 0) { 238*25c28e83SPiotr Jasiukajtis zz.i[0] = (fsr >> 30) == FSR_RM ? 0x80000000 : 239*25c28e83SPiotr Jasiukajtis 0; 240*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 241*25c28e83SPiotr Jasiukajtis return (zz.q); 242*25c28e83SPiotr Jasiukajtis } 243*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 244*25c28e83SPiotr Jasiukajtis return (z); 245*25c28e83SPiotr Jasiukajtis } 246*25c28e83SPiotr Jasiukajtis 247*25c28e83SPiotr Jasiukajtis /* if we get here, x and y are nonzero finite, z must be zero */ 248*25c28e83SPiotr Jasiukajtis return (x * y); 249*25c28e83SPiotr Jasiukajtis } 250*25c28e83SPiotr Jasiukajtis 251*25c28e83SPiotr Jasiukajtis /* 252*25c28e83SPiotr Jasiukajtis * now x, y, and z are all finite and nonzero; set round-to- 253*25c28e83SPiotr Jasiukajtis * negative-infinity mode 254*25c28e83SPiotr Jasiukajtis */ 255*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr_rm); 256*25c28e83SPiotr Jasiukajtis 257*25c28e83SPiotr Jasiukajtis /* 258*25c28e83SPiotr Jasiukajtis * get the signs and exponents and normalize the significands 259*25c28e83SPiotr Jasiukajtis * of x and y 260*25c28e83SPiotr Jasiukajtis */ 261*25c28e83SPiotr Jasiukajtis sxy = (xx.i[0] ^ yy.i[0]) & 0x80000000; 262*25c28e83SPiotr Jasiukajtis ex = hx >> 16; 263*25c28e83SPiotr Jasiukajtis hx &= 0xffff; 264*25c28e83SPiotr Jasiukajtis if (!ex) { 265*25c28e83SPiotr Jasiukajtis if (hx | (xx.i[1] & 0xfffe0000)) { 266*25c28e83SPiotr Jasiukajtis ex = 1; 267*25c28e83SPiotr Jasiukajtis } else if (xx.i[1] | (xx.i[2] & 0xfffe0000)) { 268*25c28e83SPiotr Jasiukajtis hx = xx.i[1]; 269*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2]; 270*25c28e83SPiotr Jasiukajtis xx.i[2] = xx.i[3]; 271*25c28e83SPiotr Jasiukajtis xx.i[3] = 0; 272*25c28e83SPiotr Jasiukajtis ex = -31; 273*25c28e83SPiotr Jasiukajtis } else if (xx.i[2] | (xx.i[3] & 0xfffe0000)) { 274*25c28e83SPiotr Jasiukajtis hx = xx.i[2]; 275*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[3]; 276*25c28e83SPiotr Jasiukajtis xx.i[2] = xx.i[3] = 0; 277*25c28e83SPiotr Jasiukajtis ex = -63; 278*25c28e83SPiotr Jasiukajtis } else { 279*25c28e83SPiotr Jasiukajtis hx = xx.i[3]; 280*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0; 281*25c28e83SPiotr Jasiukajtis ex = -95; 282*25c28e83SPiotr Jasiukajtis } 283*25c28e83SPiotr Jasiukajtis while ((hx & 0x10000) == 0) { 284*25c28e83SPiotr Jasiukajtis hx = (hx << 1) | (xx.i[1] >> 31); 285*25c28e83SPiotr Jasiukajtis xx.i[1] = (xx.i[1] << 1) | (xx.i[2] >> 31); 286*25c28e83SPiotr Jasiukajtis xx.i[2] = (xx.i[2] << 1) | (xx.i[3] >> 31); 287*25c28e83SPiotr Jasiukajtis xx.i[3] <<= 1; 288*25c28e83SPiotr Jasiukajtis ex--; 289*25c28e83SPiotr Jasiukajtis } 290*25c28e83SPiotr Jasiukajtis } else 291*25c28e83SPiotr Jasiukajtis hx |= 0x10000; 292*25c28e83SPiotr Jasiukajtis ey = hy >> 16; 293*25c28e83SPiotr Jasiukajtis hy &= 0xffff; 294*25c28e83SPiotr Jasiukajtis if (!ey) { 295*25c28e83SPiotr Jasiukajtis if (hy | (yy.i[1] & 0xfffe0000)) { 296*25c28e83SPiotr Jasiukajtis ey = 1; 297*25c28e83SPiotr Jasiukajtis } else if (yy.i[1] | (yy.i[2] & 0xfffe0000)) { 298*25c28e83SPiotr Jasiukajtis hy = yy.i[1]; 299*25c28e83SPiotr Jasiukajtis yy.i[1] = yy.i[2]; 300*25c28e83SPiotr Jasiukajtis yy.i[2] = yy.i[3]; 301*25c28e83SPiotr Jasiukajtis yy.i[3] = 0; 302*25c28e83SPiotr Jasiukajtis ey = -31; 303*25c28e83SPiotr Jasiukajtis } else if (yy.i[2] | (yy.i[3] & 0xfffe0000)) { 304*25c28e83SPiotr Jasiukajtis hy = yy.i[2]; 305*25c28e83SPiotr Jasiukajtis yy.i[1] = yy.i[3]; 306*25c28e83SPiotr Jasiukajtis yy.i[2] = yy.i[3] = 0; 307*25c28e83SPiotr Jasiukajtis ey = -63; 308*25c28e83SPiotr Jasiukajtis } else { 309*25c28e83SPiotr Jasiukajtis hy = yy.i[3]; 310*25c28e83SPiotr Jasiukajtis yy.i[1] = yy.i[2] = yy.i[3] = 0; 311*25c28e83SPiotr Jasiukajtis ey = -95; 312*25c28e83SPiotr Jasiukajtis } 313*25c28e83SPiotr Jasiukajtis while ((hy & 0x10000) == 0) { 314*25c28e83SPiotr Jasiukajtis hy = (hy << 1) | (yy.i[1] >> 31); 315*25c28e83SPiotr Jasiukajtis yy.i[1] = (yy.i[1] << 1) | (yy.i[2] >> 31); 316*25c28e83SPiotr Jasiukajtis yy.i[2] = (yy.i[2] << 1) | (yy.i[3] >> 31); 317*25c28e83SPiotr Jasiukajtis yy.i[3] <<= 1; 318*25c28e83SPiotr Jasiukajtis ey--; 319*25c28e83SPiotr Jasiukajtis } 320*25c28e83SPiotr Jasiukajtis } else 321*25c28e83SPiotr Jasiukajtis hy |= 0x10000; 322*25c28e83SPiotr Jasiukajtis exy = ex + ey - 0x3fff; 323*25c28e83SPiotr Jasiukajtis 324*25c28e83SPiotr Jasiukajtis /* convert the significands of x and y to doubles */ 325*25c28e83SPiotr Jasiukajtis c = twom16; 326*25c28e83SPiotr Jasiukajtis dx[0] = (double) ((int) hx) * c; 327*25c28e83SPiotr Jasiukajtis dy[0] = (double) ((int) hy) * c; 328*25c28e83SPiotr Jasiukajtis 329*25c28e83SPiotr Jasiukajtis c *= twom24; 330*25c28e83SPiotr Jasiukajtis dx[1] = (double) ((int) (xx.i[1] >> 8)) * c; 331*25c28e83SPiotr Jasiukajtis dy[1] = (double) ((int) (yy.i[1] >> 8)) * c; 332*25c28e83SPiotr Jasiukajtis 333*25c28e83SPiotr Jasiukajtis c *= twom24; 334*25c28e83SPiotr Jasiukajtis dx[2] = (double) ((int) (((xx.i[1] << 16) | (xx.i[2] >> 16)) & 335*25c28e83SPiotr Jasiukajtis 0xffffff)) * c; 336*25c28e83SPiotr Jasiukajtis dy[2] = (double) ((int) (((yy.i[1] << 16) | (yy.i[2] >> 16)) & 337*25c28e83SPiotr Jasiukajtis 0xffffff)) * c; 338*25c28e83SPiotr Jasiukajtis 339*25c28e83SPiotr Jasiukajtis c *= twom24; 340*25c28e83SPiotr Jasiukajtis dx[3] = (double) ((int) (((xx.i[2] << 8) | (xx.i[3] >> 24)) & 341*25c28e83SPiotr Jasiukajtis 0xffffff)) * c; 342*25c28e83SPiotr Jasiukajtis dy[3] = (double) ((int) (((yy.i[2] << 8) | (yy.i[3] >> 24)) & 343*25c28e83SPiotr Jasiukajtis 0xffffff)) * c; 344*25c28e83SPiotr Jasiukajtis 345*25c28e83SPiotr Jasiukajtis c *= twom24; 346*25c28e83SPiotr Jasiukajtis dx[4] = (double) ((int) (xx.i[3] & 0xffffff)) * c; 347*25c28e83SPiotr Jasiukajtis dy[4] = (double) ((int) (yy.i[3] & 0xffffff)) * c; 348*25c28e83SPiotr Jasiukajtis 349*25c28e83SPiotr Jasiukajtis /* form the "digits" of the product */ 350*25c28e83SPiotr Jasiukajtis dxy[0] = dx[0] * dy[0]; 351*25c28e83SPiotr Jasiukajtis dxy[1] = dx[0] * dy[1] + dx[1] * dy[0]; 352*25c28e83SPiotr Jasiukajtis dxy[2] = dx[0] * dy[2] + dx[1] * dy[1] + dx[2] * dy[0]; 353*25c28e83SPiotr Jasiukajtis dxy[3] = dx[0] * dy[3] + dx[1] * dy[2] + dx[2] * dy[1] + 354*25c28e83SPiotr Jasiukajtis dx[3] * dy[0]; 355*25c28e83SPiotr Jasiukajtis dxy[4] = dx[0] * dy[4] + dx[1] * dy[3] + dx[2] * dy[2] + 356*25c28e83SPiotr Jasiukajtis dx[3] * dy[1] + dx[4] * dy[0]; 357*25c28e83SPiotr Jasiukajtis dxy[5] = dx[1] * dy[4] + dx[2] * dy[3] + dx[3] * dy[2] + 358*25c28e83SPiotr Jasiukajtis dx[4] * dy[1]; 359*25c28e83SPiotr Jasiukajtis dxy[6] = dx[2] * dy[4] + dx[3] * dy[3] + dx[4] * dy[2]; 360*25c28e83SPiotr Jasiukajtis dxy[7] = dx[3] * dy[4] + dx[4] * dy[3]; 361*25c28e83SPiotr Jasiukajtis dxy[8] = dx[4] * dy[4]; 362*25c28e83SPiotr Jasiukajtis 363*25c28e83SPiotr Jasiukajtis /* split odd-numbered terms and combine into even-numbered terms */ 364*25c28e83SPiotr Jasiukajtis c = (dxy[1] + two20) - two20; 365*25c28e83SPiotr Jasiukajtis dxy[0] += c; 366*25c28e83SPiotr Jasiukajtis dxy[1] -= c; 367*25c28e83SPiotr Jasiukajtis c = (dxy[3] + twom28) - twom28; 368*25c28e83SPiotr Jasiukajtis dxy[2] += c + dxy[1]; 369*25c28e83SPiotr Jasiukajtis dxy[3] -= c; 370*25c28e83SPiotr Jasiukajtis c = (dxy[5] + twom76) - twom76; 371*25c28e83SPiotr Jasiukajtis dxy[4] += c + dxy[3]; 372*25c28e83SPiotr Jasiukajtis dxy[5] -= c; 373*25c28e83SPiotr Jasiukajtis c = (dxy[7] + twom124) - twom124; 374*25c28e83SPiotr Jasiukajtis dxy[6] += c + dxy[5]; 375*25c28e83SPiotr Jasiukajtis dxy[8] += (dxy[7] - c); 376*25c28e83SPiotr Jasiukajtis 377*25c28e83SPiotr Jasiukajtis /* propagate carries, adjusting the exponent if need be */ 378*25c28e83SPiotr Jasiukajtis dxy[7] = dxy[6] + dxy[8]; 379*25c28e83SPiotr Jasiukajtis dxy[5] = dxy[4] + dxy[7]; 380*25c28e83SPiotr Jasiukajtis dxy[3] = dxy[2] + dxy[5]; 381*25c28e83SPiotr Jasiukajtis dxy[1] = dxy[0] + dxy[3]; 382*25c28e83SPiotr Jasiukajtis if (dxy[1] >= two) { 383*25c28e83SPiotr Jasiukajtis dxy[0] *= half; 384*25c28e83SPiotr Jasiukajtis dxy[1] *= half; 385*25c28e83SPiotr Jasiukajtis dxy[2] *= half; 386*25c28e83SPiotr Jasiukajtis dxy[3] *= half; 387*25c28e83SPiotr Jasiukajtis dxy[4] *= half; 388*25c28e83SPiotr Jasiukajtis dxy[5] *= half; 389*25c28e83SPiotr Jasiukajtis dxy[6] *= half; 390*25c28e83SPiotr Jasiukajtis dxy[7] *= half; 391*25c28e83SPiotr Jasiukajtis dxy[8] *= half; 392*25c28e83SPiotr Jasiukajtis exy++; 393*25c28e83SPiotr Jasiukajtis } 394*25c28e83SPiotr Jasiukajtis 395*25c28e83SPiotr Jasiukajtis /* extract the significand of x*y */ 396*25c28e83SPiotr Jasiukajtis s = two36; 397*25c28e83SPiotr Jasiukajtis u.d = c = dxy[1] + s; 398*25c28e83SPiotr Jasiukajtis xy0 = u.i[1]; 399*25c28e83SPiotr Jasiukajtis c -= s; 400*25c28e83SPiotr Jasiukajtis dxy[1] -= c; 401*25c28e83SPiotr Jasiukajtis dxy[0] -= c; 402*25c28e83SPiotr Jasiukajtis 403*25c28e83SPiotr Jasiukajtis s *= twom32; 404*25c28e83SPiotr Jasiukajtis u.d = c = dxy[1] + s; 405*25c28e83SPiotr Jasiukajtis xy1 = u.i[1]; 406*25c28e83SPiotr Jasiukajtis c -= s; 407*25c28e83SPiotr Jasiukajtis dxy[2] += (dxy[0] - c); 408*25c28e83SPiotr Jasiukajtis dxy[3] = dxy[2] + dxy[5]; 409*25c28e83SPiotr Jasiukajtis 410*25c28e83SPiotr Jasiukajtis s *= twom32; 411*25c28e83SPiotr Jasiukajtis u.d = c = dxy[3] + s; 412*25c28e83SPiotr Jasiukajtis xy2 = u.i[1]; 413*25c28e83SPiotr Jasiukajtis c -= s; 414*25c28e83SPiotr Jasiukajtis dxy[4] += (dxy[2] - c); 415*25c28e83SPiotr Jasiukajtis dxy[5] = dxy[4] + dxy[7]; 416*25c28e83SPiotr Jasiukajtis 417*25c28e83SPiotr Jasiukajtis s *= twom32; 418*25c28e83SPiotr Jasiukajtis u.d = c = dxy[5] + s; 419*25c28e83SPiotr Jasiukajtis xy3 = u.i[1]; 420*25c28e83SPiotr Jasiukajtis c -= s; 421*25c28e83SPiotr Jasiukajtis dxy[4] -= c; 422*25c28e83SPiotr Jasiukajtis dxy[5] = dxy[4] + dxy[7]; 423*25c28e83SPiotr Jasiukajtis 424*25c28e83SPiotr Jasiukajtis s *= twom32; 425*25c28e83SPiotr Jasiukajtis u.d = c = dxy[5] + s; 426*25c28e83SPiotr Jasiukajtis xy4 = u.i[1]; 427*25c28e83SPiotr Jasiukajtis c -= s; 428*25c28e83SPiotr Jasiukajtis dxy[6] += (dxy[4] - c); 429*25c28e83SPiotr Jasiukajtis dxy[7] = dxy[6] + dxy[8]; 430*25c28e83SPiotr Jasiukajtis 431*25c28e83SPiotr Jasiukajtis s *= twom32; 432*25c28e83SPiotr Jasiukajtis u.d = c = dxy[7] + s; 433*25c28e83SPiotr Jasiukajtis xy5 = u.i[1]; 434*25c28e83SPiotr Jasiukajtis c -= s; 435*25c28e83SPiotr Jasiukajtis dxy[8] += (dxy[6] - c); 436*25c28e83SPiotr Jasiukajtis 437*25c28e83SPiotr Jasiukajtis s *= twom32; 438*25c28e83SPiotr Jasiukajtis u.d = c = dxy[8] + s; 439*25c28e83SPiotr Jasiukajtis xy6 = u.i[1]; 440*25c28e83SPiotr Jasiukajtis c -= s; 441*25c28e83SPiotr Jasiukajtis dxy[8] -= c; 442*25c28e83SPiotr Jasiukajtis 443*25c28e83SPiotr Jasiukajtis s *= twom32; 444*25c28e83SPiotr Jasiukajtis u.d = c = dxy[8] + s; 445*25c28e83SPiotr Jasiukajtis xy7 = u.i[1]; 446*25c28e83SPiotr Jasiukajtis 447*25c28e83SPiotr Jasiukajtis /* extract the sign, exponent, and significand of z */ 448*25c28e83SPiotr Jasiukajtis sz = zz.i[0] & 0x80000000; 449*25c28e83SPiotr Jasiukajtis ez = hz >> 16; 450*25c28e83SPiotr Jasiukajtis z0 = hz & 0xffff; 451*25c28e83SPiotr Jasiukajtis if (!ez) { 452*25c28e83SPiotr Jasiukajtis if (z0 | (zz.i[1] & 0xfffe0000)) { 453*25c28e83SPiotr Jasiukajtis z1 = zz.i[1]; 454*25c28e83SPiotr Jasiukajtis z2 = zz.i[2]; 455*25c28e83SPiotr Jasiukajtis z3 = zz.i[3]; 456*25c28e83SPiotr Jasiukajtis ez = 1; 457*25c28e83SPiotr Jasiukajtis } else if (zz.i[1] | (zz.i[2] & 0xfffe0000)) { 458*25c28e83SPiotr Jasiukajtis z0 = zz.i[1]; 459*25c28e83SPiotr Jasiukajtis z1 = zz.i[2]; 460*25c28e83SPiotr Jasiukajtis z2 = zz.i[3]; 461*25c28e83SPiotr Jasiukajtis z3 = 0; 462*25c28e83SPiotr Jasiukajtis ez = -31; 463*25c28e83SPiotr Jasiukajtis } else if (zz.i[2] | (zz.i[3] & 0xfffe0000)) { 464*25c28e83SPiotr Jasiukajtis z0 = zz.i[2]; 465*25c28e83SPiotr Jasiukajtis z1 = zz.i[3]; 466*25c28e83SPiotr Jasiukajtis z2 = z3 = 0; 467*25c28e83SPiotr Jasiukajtis ez = -63; 468*25c28e83SPiotr Jasiukajtis } else { 469*25c28e83SPiotr Jasiukajtis z0 = zz.i[3]; 470*25c28e83SPiotr Jasiukajtis z1 = z2 = z3 = 0; 471*25c28e83SPiotr Jasiukajtis ez = -95; 472*25c28e83SPiotr Jasiukajtis } 473*25c28e83SPiotr Jasiukajtis while ((z0 & 0x10000) == 0) { 474*25c28e83SPiotr Jasiukajtis z0 = (z0 << 1) | (z1 >> 31); 475*25c28e83SPiotr Jasiukajtis z1 = (z1 << 1) | (z2 >> 31); 476*25c28e83SPiotr Jasiukajtis z2 = (z2 << 1) | (z3 >> 31); 477*25c28e83SPiotr Jasiukajtis z3 <<= 1; 478*25c28e83SPiotr Jasiukajtis ez--; 479*25c28e83SPiotr Jasiukajtis } 480*25c28e83SPiotr Jasiukajtis } else { 481*25c28e83SPiotr Jasiukajtis z0 |= 0x10000; 482*25c28e83SPiotr Jasiukajtis z1 = zz.i[1]; 483*25c28e83SPiotr Jasiukajtis z2 = zz.i[2]; 484*25c28e83SPiotr Jasiukajtis z3 = zz.i[3]; 485*25c28e83SPiotr Jasiukajtis } 486*25c28e83SPiotr Jasiukajtis z4 = z5 = z6 = z7 = 0; 487*25c28e83SPiotr Jasiukajtis 488*25c28e83SPiotr Jasiukajtis /* 489*25c28e83SPiotr Jasiukajtis * now x*y is represented by sxy, exy, and xy[0-7], and z is 490*25c28e83SPiotr Jasiukajtis * represented likewise; swap if need be so |xy| <= |z| 491*25c28e83SPiotr Jasiukajtis */ 492*25c28e83SPiotr Jasiukajtis if (exy > ez || (exy == ez && (xy0 > z0 || (xy0 == z0 && (xy1 > z1 || 493*25c28e83SPiotr Jasiukajtis (xy1 == z1 && (xy2 > z2 || (xy2 == z2 && (xy3 > z3 || 494*25c28e83SPiotr Jasiukajtis (xy3 == z3 && (xy4 | xy5 | xy6 | xy7) != 0)))))))))) { 495*25c28e83SPiotr Jasiukajtis e = sxy; sxy = sz; sz = e; 496*25c28e83SPiotr Jasiukajtis e = exy; exy = ez; ez = e; 497*25c28e83SPiotr Jasiukajtis e = xy0; xy0 = z0; z0 = e; 498*25c28e83SPiotr Jasiukajtis e = xy1; xy1 = z1; z1 = e; 499*25c28e83SPiotr Jasiukajtis e = xy2; xy2 = z2; z2 = e; 500*25c28e83SPiotr Jasiukajtis e = xy3; xy3 = z3; z3 = e; 501*25c28e83SPiotr Jasiukajtis z4 = xy4; xy4 = 0; 502*25c28e83SPiotr Jasiukajtis z5 = xy5; xy5 = 0; 503*25c28e83SPiotr Jasiukajtis z6 = xy6; xy6 = 0; 504*25c28e83SPiotr Jasiukajtis z7 = xy7; xy7 = 0; 505*25c28e83SPiotr Jasiukajtis } 506*25c28e83SPiotr Jasiukajtis 507*25c28e83SPiotr Jasiukajtis /* shift the significand of xy keeping a sticky bit */ 508*25c28e83SPiotr Jasiukajtis e = ez - exy; 509*25c28e83SPiotr Jasiukajtis if (e > 236) { 510*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = xy4 = xy5 = xy6 = 0; 511*25c28e83SPiotr Jasiukajtis xy7 = 1; 512*25c28e83SPiotr Jasiukajtis } else if (e >= 224) { 513*25c28e83SPiotr Jasiukajtis sticky = xy7 | xy6 | xy5 | xy4 | xy3 | xy2 | xy1 | 514*25c28e83SPiotr Jasiukajtis ((xy0 << 1) << (255 - e)); 515*25c28e83SPiotr Jasiukajtis xy7 = xy0 >> (e - 224); 516*25c28e83SPiotr Jasiukajtis if (sticky) 517*25c28e83SPiotr Jasiukajtis xy7 |= 1; 518*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = xy4 = xy5 = xy6 = 0; 519*25c28e83SPiotr Jasiukajtis } else if (e >= 192) { 520*25c28e83SPiotr Jasiukajtis sticky = xy7 | xy6 | xy5 | xy4 | xy3 | xy2 | 521*25c28e83SPiotr Jasiukajtis ((xy1 << 1) << (223 - e)); 522*25c28e83SPiotr Jasiukajtis xy7 = (xy1 >> (e - 192)) | ((xy0 << 1) << (223 - e)); 523*25c28e83SPiotr Jasiukajtis if (sticky) 524*25c28e83SPiotr Jasiukajtis xy7 |= 1; 525*25c28e83SPiotr Jasiukajtis xy6 = xy0 >> (e - 192); 526*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = xy4 = xy5 = 0; 527*25c28e83SPiotr Jasiukajtis } else if (e >= 160) { 528*25c28e83SPiotr Jasiukajtis sticky = xy7 | xy6 | xy5 | xy4 | xy3 | 529*25c28e83SPiotr Jasiukajtis ((xy2 << 1) << (191 - e)); 530*25c28e83SPiotr Jasiukajtis xy7 = (xy2 >> (e - 160)) | ((xy1 << 1) << (191 - e)); 531*25c28e83SPiotr Jasiukajtis if (sticky) 532*25c28e83SPiotr Jasiukajtis xy7 |= 1; 533*25c28e83SPiotr Jasiukajtis xy6 = (xy1 >> (e - 160)) | ((xy0 << 1) << (191 - e)); 534*25c28e83SPiotr Jasiukajtis xy5 = xy0 >> (e - 160); 535*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = xy4 = 0; 536*25c28e83SPiotr Jasiukajtis } else if (e >= 128) { 537*25c28e83SPiotr Jasiukajtis sticky = xy7 | xy6 | xy5 | xy4 | ((xy3 << 1) << (159 - e)); 538*25c28e83SPiotr Jasiukajtis xy7 = (xy3 >> (e - 128)) | ((xy2 << 1) << (159 - e)); 539*25c28e83SPiotr Jasiukajtis if (sticky) 540*25c28e83SPiotr Jasiukajtis xy7 |= 1; 541*25c28e83SPiotr Jasiukajtis xy6 = (xy2 >> (e - 128)) | ((xy1 << 1) << (159 - e)); 542*25c28e83SPiotr Jasiukajtis xy5 = (xy1 >> (e - 128)) | ((xy0 << 1) << (159 - e)); 543*25c28e83SPiotr Jasiukajtis xy4 = xy0 >> (e - 128); 544*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = 0; 545*25c28e83SPiotr Jasiukajtis } else if (e >= 96) { 546*25c28e83SPiotr Jasiukajtis sticky = xy7 | xy6 | xy5 | ((xy4 << 1) << (127 - e)); 547*25c28e83SPiotr Jasiukajtis xy7 = (xy4 >> (e - 96)) | ((xy3 << 1) << (127 - e)); 548*25c28e83SPiotr Jasiukajtis if (sticky) 549*25c28e83SPiotr Jasiukajtis xy7 |= 1; 550*25c28e83SPiotr Jasiukajtis xy6 = (xy3 >> (e - 96)) | ((xy2 << 1) << (127 - e)); 551*25c28e83SPiotr Jasiukajtis xy5 = (xy2 >> (e - 96)) | ((xy1 << 1) << (127 - e)); 552*25c28e83SPiotr Jasiukajtis xy4 = (xy1 >> (e - 96)) | ((xy0 << 1) << (127 - e)); 553*25c28e83SPiotr Jasiukajtis xy3 = xy0 >> (e - 96); 554*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = 0; 555*25c28e83SPiotr Jasiukajtis } else if (e >= 64) { 556*25c28e83SPiotr Jasiukajtis sticky = xy7 | xy6 | ((xy5 << 1) << (95 - e)); 557*25c28e83SPiotr Jasiukajtis xy7 = (xy5 >> (e - 64)) | ((xy4 << 1) << (95 - e)); 558*25c28e83SPiotr Jasiukajtis if (sticky) 559*25c28e83SPiotr Jasiukajtis xy7 |= 1; 560*25c28e83SPiotr Jasiukajtis xy6 = (xy4 >> (e - 64)) | ((xy3 << 1) << (95 - e)); 561*25c28e83SPiotr Jasiukajtis xy5 = (xy3 >> (e - 64)) | ((xy2 << 1) << (95 - e)); 562*25c28e83SPiotr Jasiukajtis xy4 = (xy2 >> (e - 64)) | ((xy1 << 1) << (95 - e)); 563*25c28e83SPiotr Jasiukajtis xy3 = (xy1 >> (e - 64)) | ((xy0 << 1) << (95 - e)); 564*25c28e83SPiotr Jasiukajtis xy2 = xy0 >> (e - 64); 565*25c28e83SPiotr Jasiukajtis xy0 = xy1 = 0; 566*25c28e83SPiotr Jasiukajtis } else if (e >= 32) { 567*25c28e83SPiotr Jasiukajtis sticky = xy7 | ((xy6 << 1) << (63 - e)); 568*25c28e83SPiotr Jasiukajtis xy7 = (xy6 >> (e - 32)) | ((xy5 << 1) << (63 - e)); 569*25c28e83SPiotr Jasiukajtis if (sticky) 570*25c28e83SPiotr Jasiukajtis xy7 |= 1; 571*25c28e83SPiotr Jasiukajtis xy6 = (xy5 >> (e - 32)) | ((xy4 << 1) << (63 - e)); 572*25c28e83SPiotr Jasiukajtis xy5 = (xy4 >> (e - 32)) | ((xy3 << 1) << (63 - e)); 573*25c28e83SPiotr Jasiukajtis xy4 = (xy3 >> (e - 32)) | ((xy2 << 1) << (63 - e)); 574*25c28e83SPiotr Jasiukajtis xy3 = (xy2 >> (e - 32)) | ((xy1 << 1) << (63 - e)); 575*25c28e83SPiotr Jasiukajtis xy2 = (xy1 >> (e - 32)) | ((xy0 << 1) << (63 - e)); 576*25c28e83SPiotr Jasiukajtis xy1 = xy0 >> (e - 32); 577*25c28e83SPiotr Jasiukajtis xy0 = 0; 578*25c28e83SPiotr Jasiukajtis } else if (e) { 579*25c28e83SPiotr Jasiukajtis sticky = (xy7 << 1) << (31 - e); 580*25c28e83SPiotr Jasiukajtis xy7 = (xy7 >> e) | ((xy6 << 1) << (31 - e)); 581*25c28e83SPiotr Jasiukajtis if (sticky) 582*25c28e83SPiotr Jasiukajtis xy7 |= 1; 583*25c28e83SPiotr Jasiukajtis xy6 = (xy6 >> e) | ((xy5 << 1) << (31 - e)); 584*25c28e83SPiotr Jasiukajtis xy5 = (xy5 >> e) | ((xy4 << 1) << (31 - e)); 585*25c28e83SPiotr Jasiukajtis xy4 = (xy4 >> e) | ((xy3 << 1) << (31 - e)); 586*25c28e83SPiotr Jasiukajtis xy3 = (xy3 >> e) | ((xy2 << 1) << (31 - e)); 587*25c28e83SPiotr Jasiukajtis xy2 = (xy2 >> e) | ((xy1 << 1) << (31 - e)); 588*25c28e83SPiotr Jasiukajtis xy1 = (xy1 >> e) | ((xy0 << 1) << (31 - e)); 589*25c28e83SPiotr Jasiukajtis xy0 >>= e; 590*25c28e83SPiotr Jasiukajtis } 591*25c28e83SPiotr Jasiukajtis 592*25c28e83SPiotr Jasiukajtis /* if this is a magnitude subtract, negate the significand of xy */ 593*25c28e83SPiotr Jasiukajtis if (sxy ^ sz) { 594*25c28e83SPiotr Jasiukajtis xy0 = ~xy0; 595*25c28e83SPiotr Jasiukajtis xy1 = ~xy1; 596*25c28e83SPiotr Jasiukajtis xy2 = ~xy2; 597*25c28e83SPiotr Jasiukajtis xy3 = ~xy3; 598*25c28e83SPiotr Jasiukajtis xy4 = ~xy4; 599*25c28e83SPiotr Jasiukajtis xy5 = ~xy5; 600*25c28e83SPiotr Jasiukajtis xy6 = ~xy6; 601*25c28e83SPiotr Jasiukajtis xy7 = -xy7; 602*25c28e83SPiotr Jasiukajtis if (xy7 == 0) 603*25c28e83SPiotr Jasiukajtis if (++xy6 == 0) 604*25c28e83SPiotr Jasiukajtis if (++xy5 == 0) 605*25c28e83SPiotr Jasiukajtis if (++xy4 == 0) 606*25c28e83SPiotr Jasiukajtis if (++xy3 == 0) 607*25c28e83SPiotr Jasiukajtis if (++xy2 == 0) 608*25c28e83SPiotr Jasiukajtis if (++xy1 == 0) 609*25c28e83SPiotr Jasiukajtis xy0++; 610*25c28e83SPiotr Jasiukajtis } 611*25c28e83SPiotr Jasiukajtis 612*25c28e83SPiotr Jasiukajtis /* add, propagating carries */ 613*25c28e83SPiotr Jasiukajtis z7 += xy7; 614*25c28e83SPiotr Jasiukajtis e = (z7 < xy7); 615*25c28e83SPiotr Jasiukajtis z6 += xy6; 616*25c28e83SPiotr Jasiukajtis if (e) { 617*25c28e83SPiotr Jasiukajtis z6++; 618*25c28e83SPiotr Jasiukajtis e = (z6 <= xy6); 619*25c28e83SPiotr Jasiukajtis } else 620*25c28e83SPiotr Jasiukajtis e = (z6 < xy6); 621*25c28e83SPiotr Jasiukajtis z5 += xy5; 622*25c28e83SPiotr Jasiukajtis if (e) { 623*25c28e83SPiotr Jasiukajtis z5++; 624*25c28e83SPiotr Jasiukajtis e = (z5 <= xy5); 625*25c28e83SPiotr Jasiukajtis } else 626*25c28e83SPiotr Jasiukajtis e = (z5 < xy5); 627*25c28e83SPiotr Jasiukajtis z4 += xy4; 628*25c28e83SPiotr Jasiukajtis if (e) { 629*25c28e83SPiotr Jasiukajtis z4++; 630*25c28e83SPiotr Jasiukajtis e = (z4 <= xy4); 631*25c28e83SPiotr Jasiukajtis } else 632*25c28e83SPiotr Jasiukajtis e = (z4 < xy4); 633*25c28e83SPiotr Jasiukajtis z3 += xy3; 634*25c28e83SPiotr Jasiukajtis if (e) { 635*25c28e83SPiotr Jasiukajtis z3++; 636*25c28e83SPiotr Jasiukajtis e = (z3 <= xy3); 637*25c28e83SPiotr Jasiukajtis } else 638*25c28e83SPiotr Jasiukajtis e = (z3 < xy3); 639*25c28e83SPiotr Jasiukajtis z2 += xy2; 640*25c28e83SPiotr Jasiukajtis if (e) { 641*25c28e83SPiotr Jasiukajtis z2++; 642*25c28e83SPiotr Jasiukajtis e = (z2 <= xy2); 643*25c28e83SPiotr Jasiukajtis } else 644*25c28e83SPiotr Jasiukajtis e = (z2 < xy2); 645*25c28e83SPiotr Jasiukajtis z1 += xy1; 646*25c28e83SPiotr Jasiukajtis if (e) { 647*25c28e83SPiotr Jasiukajtis z1++; 648*25c28e83SPiotr Jasiukajtis e = (z1 <= xy1); 649*25c28e83SPiotr Jasiukajtis } else 650*25c28e83SPiotr Jasiukajtis e = (z1 < xy1); 651*25c28e83SPiotr Jasiukajtis z0 += xy0; 652*25c28e83SPiotr Jasiukajtis if (e) 653*25c28e83SPiotr Jasiukajtis z0++; 654*25c28e83SPiotr Jasiukajtis 655*25c28e83SPiotr Jasiukajtis /* postnormalize and collect rounding information into z4 */ 656*25c28e83SPiotr Jasiukajtis if (ez < 1) { 657*25c28e83SPiotr Jasiukajtis /* result is tiny; shift right until exponent is within range */ 658*25c28e83SPiotr Jasiukajtis e = 1 - ez; 659*25c28e83SPiotr Jasiukajtis if (e > 116) { 660*25c28e83SPiotr Jasiukajtis z4 = 1; /* result can't be exactly zero */ 661*25c28e83SPiotr Jasiukajtis z0 = z1 = z2 = z3 = 0; 662*25c28e83SPiotr Jasiukajtis } else if (e >= 96) { 663*25c28e83SPiotr Jasiukajtis sticky = z7 | z6 | z5 | z4 | z3 | z2 | 664*25c28e83SPiotr Jasiukajtis ((z1 << 1) << (127 - e)); 665*25c28e83SPiotr Jasiukajtis z4 = (z1 >> (e - 96)) | ((z0 << 1) << (127 - e)); 666*25c28e83SPiotr Jasiukajtis if (sticky) 667*25c28e83SPiotr Jasiukajtis z4 |= 1; 668*25c28e83SPiotr Jasiukajtis z3 = z0 >> (e - 96); 669*25c28e83SPiotr Jasiukajtis z0 = z1 = z2 = 0; 670*25c28e83SPiotr Jasiukajtis } else if (e >= 64) { 671*25c28e83SPiotr Jasiukajtis sticky = z7 | z6 | z5 | z4 | z3 | 672*25c28e83SPiotr Jasiukajtis ((z2 << 1) << (95 - e)); 673*25c28e83SPiotr Jasiukajtis z4 = (z2 >> (e - 64)) | ((z1 << 1) << (95 - e)); 674*25c28e83SPiotr Jasiukajtis if (sticky) 675*25c28e83SPiotr Jasiukajtis z4 |= 1; 676*25c28e83SPiotr Jasiukajtis z3 = (z1 >> (e - 64)) | ((z0 << 1) << (95 - e)); 677*25c28e83SPiotr Jasiukajtis z2 = z0 >> (e - 64); 678*25c28e83SPiotr Jasiukajtis z0 = z1 = 0; 679*25c28e83SPiotr Jasiukajtis } else if (e >= 32) { 680*25c28e83SPiotr Jasiukajtis sticky = z7 | z6 | z5 | z4 | ((z3 << 1) << (63 - e)); 681*25c28e83SPiotr Jasiukajtis z4 = (z3 >> (e - 32)) | ((z2 << 1) << (63 - e)); 682*25c28e83SPiotr Jasiukajtis if (sticky) 683*25c28e83SPiotr Jasiukajtis z4 |= 1; 684*25c28e83SPiotr Jasiukajtis z3 = (z2 >> (e - 32)) | ((z1 << 1) << (63 - e)); 685*25c28e83SPiotr Jasiukajtis z2 = (z1 >> (e - 32)) | ((z0 << 1) << (63 - e)); 686*25c28e83SPiotr Jasiukajtis z1 = z0 >> (e - 32); 687*25c28e83SPiotr Jasiukajtis z0 = 0; 688*25c28e83SPiotr Jasiukajtis } else { 689*25c28e83SPiotr Jasiukajtis sticky = z7 | z6 | z5 | (z4 << 1) << (31 - e); 690*25c28e83SPiotr Jasiukajtis z4 = (z4 >> e) | ((z3 << 1) << (31 - e)); 691*25c28e83SPiotr Jasiukajtis if (sticky) 692*25c28e83SPiotr Jasiukajtis z4 |= 1; 693*25c28e83SPiotr Jasiukajtis z3 = (z3 >> e) | ((z2 << 1) << (31 - e)); 694*25c28e83SPiotr Jasiukajtis z2 = (z2 >> e) | ((z1 << 1) << (31 - e)); 695*25c28e83SPiotr Jasiukajtis z1 = (z1 >> e) | ((z0 << 1) << (31 - e)); 696*25c28e83SPiotr Jasiukajtis z0 >>= e; 697*25c28e83SPiotr Jasiukajtis } 698*25c28e83SPiotr Jasiukajtis ez = 1; 699*25c28e83SPiotr Jasiukajtis } else if (z0 >= 0x20000) { 700*25c28e83SPiotr Jasiukajtis /* carry out; shift right by one */ 701*25c28e83SPiotr Jasiukajtis sticky = (z4 & 1) | z5 | z6 | z7; 702*25c28e83SPiotr Jasiukajtis z4 = (z4 >> 1) | (z3 << 31); 703*25c28e83SPiotr Jasiukajtis if (sticky) 704*25c28e83SPiotr Jasiukajtis z4 |= 1; 705*25c28e83SPiotr Jasiukajtis z3 = (z3 >> 1) | (z2 << 31); 706*25c28e83SPiotr Jasiukajtis z2 = (z2 >> 1) | (z1 << 31); 707*25c28e83SPiotr Jasiukajtis z1 = (z1 >> 1) | (z0 << 31); 708*25c28e83SPiotr Jasiukajtis z0 >>= 1; 709*25c28e83SPiotr Jasiukajtis ez++; 710*25c28e83SPiotr Jasiukajtis } else { 711*25c28e83SPiotr Jasiukajtis if (z0 < 0x10000 && (z0 | z1 | z2 | z3 | z4 | z5 | z6 | z7) 712*25c28e83SPiotr Jasiukajtis != 0) { 713*25c28e83SPiotr Jasiukajtis /* 714*25c28e83SPiotr Jasiukajtis * borrow/cancellation; shift left as much as 715*25c28e83SPiotr Jasiukajtis * exponent allows 716*25c28e83SPiotr Jasiukajtis */ 717*25c28e83SPiotr Jasiukajtis while (!(z0 | (z1 & 0xfffe0000)) && ez >= 33) { 718*25c28e83SPiotr Jasiukajtis z0 = z1; 719*25c28e83SPiotr Jasiukajtis z1 = z2; 720*25c28e83SPiotr Jasiukajtis z2 = z3; 721*25c28e83SPiotr Jasiukajtis z3 = z4; 722*25c28e83SPiotr Jasiukajtis z4 = z5; 723*25c28e83SPiotr Jasiukajtis z5 = z6; 724*25c28e83SPiotr Jasiukajtis z6 = z7; 725*25c28e83SPiotr Jasiukajtis z7 = 0; 726*25c28e83SPiotr Jasiukajtis ez -= 32; 727*25c28e83SPiotr Jasiukajtis } 728*25c28e83SPiotr Jasiukajtis while (z0 < 0x10000 && ez > 1) { 729*25c28e83SPiotr Jasiukajtis z0 = (z0 << 1) | (z1 >> 31); 730*25c28e83SPiotr Jasiukajtis z1 = (z1 << 1) | (z2 >> 31); 731*25c28e83SPiotr Jasiukajtis z2 = (z2 << 1) | (z3 >> 31); 732*25c28e83SPiotr Jasiukajtis z3 = (z3 << 1) | (z4 >> 31); 733*25c28e83SPiotr Jasiukajtis z4 = (z4 << 1) | (z5 >> 31); 734*25c28e83SPiotr Jasiukajtis z5 = (z5 << 1) | (z6 >> 31); 735*25c28e83SPiotr Jasiukajtis z6 = (z6 << 1) | (z7 >> 31); 736*25c28e83SPiotr Jasiukajtis z7 <<= 1; 737*25c28e83SPiotr Jasiukajtis ez--; 738*25c28e83SPiotr Jasiukajtis } 739*25c28e83SPiotr Jasiukajtis } 740*25c28e83SPiotr Jasiukajtis if (z5 | z6 | z7) 741*25c28e83SPiotr Jasiukajtis z4 |= 1; 742*25c28e83SPiotr Jasiukajtis } 743*25c28e83SPiotr Jasiukajtis 744*25c28e83SPiotr Jasiukajtis /* get the rounding mode */ 745*25c28e83SPiotr Jasiukajtis rm = fsr >> 30; 746*25c28e83SPiotr Jasiukajtis 747*25c28e83SPiotr Jasiukajtis /* strip off the integer bit, if there is one */ 748*25c28e83SPiotr Jasiukajtis ibit = z0 & 0x10000; 749*25c28e83SPiotr Jasiukajtis if (ibit) 750*25c28e83SPiotr Jasiukajtis z0 -= 0x10000; 751*25c28e83SPiotr Jasiukajtis else { 752*25c28e83SPiotr Jasiukajtis ez = 0; 753*25c28e83SPiotr Jasiukajtis if (!(z0 | z1 | z2 | z3 | z4)) { /* exact zero */ 754*25c28e83SPiotr Jasiukajtis zz.i[0] = rm == FSR_RM ? 0x80000000 : 0; 755*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[2] = zz.i[3] = 0; 756*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 757*25c28e83SPiotr Jasiukajtis return (zz.q); 758*25c28e83SPiotr Jasiukajtis } 759*25c28e83SPiotr Jasiukajtis } 760*25c28e83SPiotr Jasiukajtis 761*25c28e83SPiotr Jasiukajtis /* 762*25c28e83SPiotr Jasiukajtis * flip the sense of directed roundings if the result is negative; 763*25c28e83SPiotr Jasiukajtis * the logic below applies to a positive result 764*25c28e83SPiotr Jasiukajtis */ 765*25c28e83SPiotr Jasiukajtis if (sz) 766*25c28e83SPiotr Jasiukajtis rm ^= rm >> 1; 767*25c28e83SPiotr Jasiukajtis 768*25c28e83SPiotr Jasiukajtis /* round and raise exceptions */ 769*25c28e83SPiotr Jasiukajtis if (z4) { 770*25c28e83SPiotr Jasiukajtis fsr |= FSR_NXC; 771*25c28e83SPiotr Jasiukajtis 772*25c28e83SPiotr Jasiukajtis /* decide whether to round the fraction up */ 773*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (z4 > 0x80000000u || 774*25c28e83SPiotr Jasiukajtis (z4 == 0x80000000u && (z3 & 1))))) { 775*25c28e83SPiotr Jasiukajtis /* round up and renormalize if necessary */ 776*25c28e83SPiotr Jasiukajtis if (++z3 == 0) 777*25c28e83SPiotr Jasiukajtis if (++z2 == 0) 778*25c28e83SPiotr Jasiukajtis if (++z1 == 0) 779*25c28e83SPiotr Jasiukajtis if (++z0 == 0x10000) { 780*25c28e83SPiotr Jasiukajtis z0 = 0; 781*25c28e83SPiotr Jasiukajtis ez++; 782*25c28e83SPiotr Jasiukajtis } 783*25c28e83SPiotr Jasiukajtis } 784*25c28e83SPiotr Jasiukajtis } 785*25c28e83SPiotr Jasiukajtis 786*25c28e83SPiotr Jasiukajtis /* check for under/overflow */ 787*25c28e83SPiotr Jasiukajtis if (ez >= 0x7fff) { 788*25c28e83SPiotr Jasiukajtis if (rm == FSR_RN || rm == FSR_RP) { 789*25c28e83SPiotr Jasiukajtis zz.i[0] = sz | 0x7fff0000; 790*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[2] = zz.i[3] = 0; 791*25c28e83SPiotr Jasiukajtis } else { 792*25c28e83SPiotr Jasiukajtis zz.i[0] = sz | 0x7ffeffff; 793*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[2] = zz.i[3] = 0xffffffff; 794*25c28e83SPiotr Jasiukajtis } 795*25c28e83SPiotr Jasiukajtis fsr |= FSR_OFC | FSR_NXC; 796*25c28e83SPiotr Jasiukajtis } else { 797*25c28e83SPiotr Jasiukajtis zz.i[0] = sz | (ez << 16) | z0; 798*25c28e83SPiotr Jasiukajtis zz.i[1] = z1; 799*25c28e83SPiotr Jasiukajtis zz.i[2] = z2; 800*25c28e83SPiotr Jasiukajtis zz.i[3] = z3; 801*25c28e83SPiotr Jasiukajtis 802*25c28e83SPiotr Jasiukajtis /* 803*25c28e83SPiotr Jasiukajtis * !ibit => exact result was tiny before rounding, 804*25c28e83SPiotr Jasiukajtis * z4 nonzero => result delivered is inexact 805*25c28e83SPiotr Jasiukajtis */ 806*25c28e83SPiotr Jasiukajtis if (!ibit) { 807*25c28e83SPiotr Jasiukajtis if (z4) 808*25c28e83SPiotr Jasiukajtis fsr |= FSR_UFC | FSR_NXC; 809*25c28e83SPiotr Jasiukajtis else if (fsr & FSR_UFM) 810*25c28e83SPiotr Jasiukajtis fsr |= FSR_UFC; 811*25c28e83SPiotr Jasiukajtis } 812*25c28e83SPiotr Jasiukajtis } 813*25c28e83SPiotr Jasiukajtis 814*25c28e83SPiotr Jasiukajtis /* restore the fsr and emulate exceptions as needed */ 815*25c28e83SPiotr Jasiukajtis if ((fsr & FSR_CEXC) & (fsr >> 23)) { 816*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 817*25c28e83SPiotr Jasiukajtis if (fsr & FSR_OFC) { 818*25c28e83SPiotr Jasiukajtis dummy = huge; 819*25c28e83SPiotr Jasiukajtis dummy *= huge; 820*25c28e83SPiotr Jasiukajtis } else if (fsr & FSR_UFC) { 821*25c28e83SPiotr Jasiukajtis dummy = tiny; 822*25c28e83SPiotr Jasiukajtis if (fsr & FSR_NXC) 823*25c28e83SPiotr Jasiukajtis dummy *= tiny; 824*25c28e83SPiotr Jasiukajtis else 825*25c28e83SPiotr Jasiukajtis dummy -= tiny2; 826*25c28e83SPiotr Jasiukajtis } else { 827*25c28e83SPiotr Jasiukajtis dummy = huge; 828*25c28e83SPiotr Jasiukajtis dummy += tiny; 829*25c28e83SPiotr Jasiukajtis } 830*25c28e83SPiotr Jasiukajtis } else { 831*25c28e83SPiotr Jasiukajtis fsr |= (fsr & 0x1f) << 5; 832*25c28e83SPiotr Jasiukajtis __fenv_setfsr32(&fsr); 833*25c28e83SPiotr Jasiukajtis } 834*25c28e83SPiotr Jasiukajtis return (zz.q); 835*25c28e83SPiotr Jasiukajtis } 836*25c28e83SPiotr Jasiukajtis 837*25c28e83SPiotr Jasiukajtis #elif defined(__x86) 838*25c28e83SPiotr Jasiukajtis 839*25c28e83SPiotr Jasiukajtis static const union { 840*25c28e83SPiotr Jasiukajtis unsigned i[2]; 841*25c28e83SPiotr Jasiukajtis double d; 842*25c28e83SPiotr Jasiukajtis } C[] = { 843*25c28e83SPiotr Jasiukajtis { 0, 0x3fe00000u }, 844*25c28e83SPiotr Jasiukajtis { 0, 0x40000000u }, 845*25c28e83SPiotr Jasiukajtis { 0, 0x3df00000u }, 846*25c28e83SPiotr Jasiukajtis { 0, 0x3bf00000u }, 847*25c28e83SPiotr Jasiukajtis { 0, 0x41f00000u }, 848*25c28e83SPiotr Jasiukajtis { 0, 0x43e00000u }, 849*25c28e83SPiotr Jasiukajtis { 0, 0x7fe00000u }, 850*25c28e83SPiotr Jasiukajtis { 0, 0x00100000u }, 851*25c28e83SPiotr Jasiukajtis { 0, 0x00100001u } 852*25c28e83SPiotr Jasiukajtis }; 853*25c28e83SPiotr Jasiukajtis 854*25c28e83SPiotr Jasiukajtis #define half C[0].d 855*25c28e83SPiotr Jasiukajtis #define two C[1].d 856*25c28e83SPiotr Jasiukajtis #define twom32 C[2].d 857*25c28e83SPiotr Jasiukajtis #define twom64 C[3].d 858*25c28e83SPiotr Jasiukajtis #define two32 C[4].d 859*25c28e83SPiotr Jasiukajtis #define two63 C[5].d 860*25c28e83SPiotr Jasiukajtis #define huge C[6].d 861*25c28e83SPiotr Jasiukajtis #define tiny C[7].d 862*25c28e83SPiotr Jasiukajtis #define tiny2 C[8].d 863*25c28e83SPiotr Jasiukajtis 864*25c28e83SPiotr Jasiukajtis #if defined(__amd64) 865*25c28e83SPiotr Jasiukajtis #define NI 4 866*25c28e83SPiotr Jasiukajtis #else 867*25c28e83SPiotr Jasiukajtis #define NI 3 868*25c28e83SPiotr Jasiukajtis #endif 869*25c28e83SPiotr Jasiukajtis 870*25c28e83SPiotr Jasiukajtis /* 871*25c28e83SPiotr Jasiukajtis * fmal for x86: 80-bit extended double precision, little-endian 872*25c28e83SPiotr Jasiukajtis */ 873*25c28e83SPiotr Jasiukajtis long double 874*25c28e83SPiotr Jasiukajtis __fmal(long double x, long double y, long double z) { 875*25c28e83SPiotr Jasiukajtis union { 876*25c28e83SPiotr Jasiukajtis unsigned i[NI]; 877*25c28e83SPiotr Jasiukajtis long double e; 878*25c28e83SPiotr Jasiukajtis } xx, yy, zz; 879*25c28e83SPiotr Jasiukajtis long double xhi, yhi, xlo, ylo, t; 880*25c28e83SPiotr Jasiukajtis unsigned xy0, xy1, xy2, xy3, xy4, z0, z1, z2, z3, z4; 881*25c28e83SPiotr Jasiukajtis unsigned oldcwsw, cwsw, rm, sticky, carry; 882*25c28e83SPiotr Jasiukajtis int ex, ey, ez, exy, sxy, sz, e, tinyafter; 883*25c28e83SPiotr Jasiukajtis volatile double dummy; 884*25c28e83SPiotr Jasiukajtis 885*25c28e83SPiotr Jasiukajtis /* extract the exponents of the arguments */ 886*25c28e83SPiotr Jasiukajtis xx.e = x; 887*25c28e83SPiotr Jasiukajtis yy.e = y; 888*25c28e83SPiotr Jasiukajtis zz.e = z; 889*25c28e83SPiotr Jasiukajtis ex = xx.i[2] & 0x7fff; 890*25c28e83SPiotr Jasiukajtis ey = yy.i[2] & 0x7fff; 891*25c28e83SPiotr Jasiukajtis ez = zz.i[2] & 0x7fff; 892*25c28e83SPiotr Jasiukajtis 893*25c28e83SPiotr Jasiukajtis /* dispense with inf, nan, and zero cases */ 894*25c28e83SPiotr Jasiukajtis if (ex == 0x7fff || ey == 0x7fff || (ex | xx.i[1] | xx.i[0]) == 0 || 895*25c28e83SPiotr Jasiukajtis (ey | yy.i[1] | yy.i[0]) == 0) /* x or y is inf, nan, or 0 */ 896*25c28e83SPiotr Jasiukajtis return (x * y + z); 897*25c28e83SPiotr Jasiukajtis 898*25c28e83SPiotr Jasiukajtis if (ez == 0x7fff) /* z is inf or nan */ 899*25c28e83SPiotr Jasiukajtis return (x + z); /* avoid spurious under/overflow in x * y */ 900*25c28e83SPiotr Jasiukajtis 901*25c28e83SPiotr Jasiukajtis if ((ez | zz.i[1] | zz.i[0]) == 0) /* z is zero */ 902*25c28e83SPiotr Jasiukajtis /* 903*25c28e83SPiotr Jasiukajtis * x * y isn't zero but could underflow to zero, 904*25c28e83SPiotr Jasiukajtis * so don't add z, lest we perturb the sign 905*25c28e83SPiotr Jasiukajtis */ 906*25c28e83SPiotr Jasiukajtis return (x * y); 907*25c28e83SPiotr Jasiukajtis 908*25c28e83SPiotr Jasiukajtis /* 909*25c28e83SPiotr Jasiukajtis * now x, y, and z are all finite and nonzero; extract signs and 910*25c28e83SPiotr Jasiukajtis * normalize the significands (this will raise the denormal operand 911*25c28e83SPiotr Jasiukajtis * exception if need be) 912*25c28e83SPiotr Jasiukajtis */ 913*25c28e83SPiotr Jasiukajtis sxy = (xx.i[2] ^ yy.i[2]) & 0x8000; 914*25c28e83SPiotr Jasiukajtis sz = zz.i[2] & 0x8000; 915*25c28e83SPiotr Jasiukajtis if (!ex) { 916*25c28e83SPiotr Jasiukajtis xx.e = x * two63; 917*25c28e83SPiotr Jasiukajtis ex = (xx.i[2] & 0x7fff) - 63; 918*25c28e83SPiotr Jasiukajtis } 919*25c28e83SPiotr Jasiukajtis if (!ey) { 920*25c28e83SPiotr Jasiukajtis yy.e = y * two63; 921*25c28e83SPiotr Jasiukajtis ey = (yy.i[2] & 0x7fff) - 63; 922*25c28e83SPiotr Jasiukajtis } 923*25c28e83SPiotr Jasiukajtis if (!ez) { 924*25c28e83SPiotr Jasiukajtis zz.e = z * two63; 925*25c28e83SPiotr Jasiukajtis ez = (zz.i[2] & 0x7fff) - 63; 926*25c28e83SPiotr Jasiukajtis } 927*25c28e83SPiotr Jasiukajtis 928*25c28e83SPiotr Jasiukajtis /* 929*25c28e83SPiotr Jasiukajtis * save the control and status words, mask all exceptions, and 930*25c28e83SPiotr Jasiukajtis * set rounding to 64-bit precision and toward-zero 931*25c28e83SPiotr Jasiukajtis */ 932*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&oldcwsw); 933*25c28e83SPiotr Jasiukajtis cwsw = (oldcwsw & 0xf0c0ffff) | 0x0f3f0000; 934*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw); 935*25c28e83SPiotr Jasiukajtis 936*25c28e83SPiotr Jasiukajtis /* multiply x*y to 128 bits */ 937*25c28e83SPiotr Jasiukajtis exy = ex + ey - 0x3fff; 938*25c28e83SPiotr Jasiukajtis xx.i[2] = 0x3fff; 939*25c28e83SPiotr Jasiukajtis yy.i[2] = 0x3fff; 940*25c28e83SPiotr Jasiukajtis x = xx.e; 941*25c28e83SPiotr Jasiukajtis y = yy.e; 942*25c28e83SPiotr Jasiukajtis xhi = ((x + twom32) + two32) - two32; 943*25c28e83SPiotr Jasiukajtis yhi = ((y + twom32) + two32) - two32; 944*25c28e83SPiotr Jasiukajtis xlo = x - xhi; 945*25c28e83SPiotr Jasiukajtis ylo = y - yhi; 946*25c28e83SPiotr Jasiukajtis x *= y; 947*25c28e83SPiotr Jasiukajtis y = ((xhi * yhi - x) + xhi * ylo + xlo * yhi) + xlo * ylo; 948*25c28e83SPiotr Jasiukajtis if (x >= two) { 949*25c28e83SPiotr Jasiukajtis x *= half; 950*25c28e83SPiotr Jasiukajtis y *= half; 951*25c28e83SPiotr Jasiukajtis exy++; 952*25c28e83SPiotr Jasiukajtis } 953*25c28e83SPiotr Jasiukajtis 954*25c28e83SPiotr Jasiukajtis /* extract the significands */ 955*25c28e83SPiotr Jasiukajtis xx.e = x; 956*25c28e83SPiotr Jasiukajtis xy0 = xx.i[1]; 957*25c28e83SPiotr Jasiukajtis xy1 = xx.i[0]; 958*25c28e83SPiotr Jasiukajtis yy.e = t = y + twom32; 959*25c28e83SPiotr Jasiukajtis xy2 = yy.i[0]; 960*25c28e83SPiotr Jasiukajtis yy.e = (y - (t - twom32)) + twom64; 961*25c28e83SPiotr Jasiukajtis xy3 = yy.i[0]; 962*25c28e83SPiotr Jasiukajtis xy4 = 0; 963*25c28e83SPiotr Jasiukajtis z0 = zz.i[1]; 964*25c28e83SPiotr Jasiukajtis z1 = zz.i[0]; 965*25c28e83SPiotr Jasiukajtis z2 = z3 = z4 = 0; 966*25c28e83SPiotr Jasiukajtis 967*25c28e83SPiotr Jasiukajtis /* 968*25c28e83SPiotr Jasiukajtis * now x*y is represented by sxy, exy, and xy[0-4], and z is 969*25c28e83SPiotr Jasiukajtis * represented likewise; swap if need be so |xy| <= |z| 970*25c28e83SPiotr Jasiukajtis */ 971*25c28e83SPiotr Jasiukajtis if (exy > ez || (exy == ez && (xy0 > z0 || (xy0 == z0 && 972*25c28e83SPiotr Jasiukajtis (xy1 > z1 || (xy1 == z1 && (xy2 | xy3) != 0)))))) { 973*25c28e83SPiotr Jasiukajtis e = sxy; sxy = sz; sz = e; 974*25c28e83SPiotr Jasiukajtis e = exy; exy = ez; ez = e; 975*25c28e83SPiotr Jasiukajtis e = xy0; xy0 = z0; z0 = e; 976*25c28e83SPiotr Jasiukajtis e = xy1; xy1 = z1; z1 = e; 977*25c28e83SPiotr Jasiukajtis z2 = xy2; xy2 = 0; 978*25c28e83SPiotr Jasiukajtis z3 = xy3; xy3 = 0; 979*25c28e83SPiotr Jasiukajtis } 980*25c28e83SPiotr Jasiukajtis 981*25c28e83SPiotr Jasiukajtis /* shift the significand of xy keeping a sticky bit */ 982*25c28e83SPiotr Jasiukajtis e = ez - exy; 983*25c28e83SPiotr Jasiukajtis if (e > 130) { 984*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = 0; 985*25c28e83SPiotr Jasiukajtis xy4 = 1; 986*25c28e83SPiotr Jasiukajtis } else if (e >= 128) { 987*25c28e83SPiotr Jasiukajtis sticky = xy3 | xy2 | xy1 | ((xy0 << 1) << (159 - e)); 988*25c28e83SPiotr Jasiukajtis xy4 = xy0 >> (e - 128); 989*25c28e83SPiotr Jasiukajtis if (sticky) 990*25c28e83SPiotr Jasiukajtis xy4 |= 1; 991*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = xy3 = 0; 992*25c28e83SPiotr Jasiukajtis } else if (e >= 96) { 993*25c28e83SPiotr Jasiukajtis sticky = xy3 | xy2 | ((xy1 << 1) << (127 - e)); 994*25c28e83SPiotr Jasiukajtis xy4 = (xy1 >> (e - 96)) | ((xy0 << 1) << (127 - e)); 995*25c28e83SPiotr Jasiukajtis if (sticky) 996*25c28e83SPiotr Jasiukajtis xy4 |= 1; 997*25c28e83SPiotr Jasiukajtis xy3 = xy0 >> (e - 96); 998*25c28e83SPiotr Jasiukajtis xy0 = xy1 = xy2 = 0; 999*25c28e83SPiotr Jasiukajtis } else if (e >= 64) { 1000*25c28e83SPiotr Jasiukajtis sticky = xy3 | ((xy2 << 1) << (95 - e)); 1001*25c28e83SPiotr Jasiukajtis xy4 = (xy2 >> (e - 64)) | ((xy1 << 1) << (95 - e)); 1002*25c28e83SPiotr Jasiukajtis if (sticky) 1003*25c28e83SPiotr Jasiukajtis xy4 |= 1; 1004*25c28e83SPiotr Jasiukajtis xy3 = (xy1 >> (e - 64)) | ((xy0 << 1) << (95 - e)); 1005*25c28e83SPiotr Jasiukajtis xy2 = xy0 >> (e - 64); 1006*25c28e83SPiotr Jasiukajtis xy0 = xy1 = 0; 1007*25c28e83SPiotr Jasiukajtis } else if (e >= 32) { 1008*25c28e83SPiotr Jasiukajtis sticky = (xy3 << 1) << (63 - e); 1009*25c28e83SPiotr Jasiukajtis xy4 = (xy3 >> (e - 32)) | ((xy2 << 1) << (63 - e)); 1010*25c28e83SPiotr Jasiukajtis if (sticky) 1011*25c28e83SPiotr Jasiukajtis xy4 |= 1; 1012*25c28e83SPiotr Jasiukajtis xy3 = (xy2 >> (e - 32)) | ((xy1 << 1) << (63 - e)); 1013*25c28e83SPiotr Jasiukajtis xy2 = (xy1 >> (e - 32)) | ((xy0 << 1) << (63 - e)); 1014*25c28e83SPiotr Jasiukajtis xy1 = xy0 >> (e - 32); 1015*25c28e83SPiotr Jasiukajtis xy0 = 0; 1016*25c28e83SPiotr Jasiukajtis } else if (e) { 1017*25c28e83SPiotr Jasiukajtis xy4 = (xy3 << 1) << (31 - e); 1018*25c28e83SPiotr Jasiukajtis xy3 = (xy3 >> e) | ((xy2 << 1) << (31 - e)); 1019*25c28e83SPiotr Jasiukajtis xy2 = (xy2 >> e) | ((xy1 << 1) << (31 - e)); 1020*25c28e83SPiotr Jasiukajtis xy1 = (xy1 >> e) | ((xy0 << 1) << (31 - e)); 1021*25c28e83SPiotr Jasiukajtis xy0 >>= e; 1022*25c28e83SPiotr Jasiukajtis } 1023*25c28e83SPiotr Jasiukajtis 1024*25c28e83SPiotr Jasiukajtis /* if this is a magnitude subtract, negate the significand of xy */ 1025*25c28e83SPiotr Jasiukajtis if (sxy ^ sz) { 1026*25c28e83SPiotr Jasiukajtis xy0 = ~xy0; 1027*25c28e83SPiotr Jasiukajtis xy1 = ~xy1; 1028*25c28e83SPiotr Jasiukajtis xy2 = ~xy2; 1029*25c28e83SPiotr Jasiukajtis xy3 = ~xy3; 1030*25c28e83SPiotr Jasiukajtis xy4 = -xy4; 1031*25c28e83SPiotr Jasiukajtis if (xy4 == 0) 1032*25c28e83SPiotr Jasiukajtis if (++xy3 == 0) 1033*25c28e83SPiotr Jasiukajtis if (++xy2 == 0) 1034*25c28e83SPiotr Jasiukajtis if (++xy1 == 0) 1035*25c28e83SPiotr Jasiukajtis xy0++; 1036*25c28e83SPiotr Jasiukajtis } 1037*25c28e83SPiotr Jasiukajtis 1038*25c28e83SPiotr Jasiukajtis /* add, propagating carries */ 1039*25c28e83SPiotr Jasiukajtis z4 += xy4; 1040*25c28e83SPiotr Jasiukajtis carry = (z4 < xy4); 1041*25c28e83SPiotr Jasiukajtis z3 += xy3; 1042*25c28e83SPiotr Jasiukajtis if (carry) { 1043*25c28e83SPiotr Jasiukajtis z3++; 1044*25c28e83SPiotr Jasiukajtis carry = (z3 <= xy3); 1045*25c28e83SPiotr Jasiukajtis } else 1046*25c28e83SPiotr Jasiukajtis carry = (z3 < xy3); 1047*25c28e83SPiotr Jasiukajtis z2 += xy2; 1048*25c28e83SPiotr Jasiukajtis if (carry) { 1049*25c28e83SPiotr Jasiukajtis z2++; 1050*25c28e83SPiotr Jasiukajtis carry = (z2 <= xy2); 1051*25c28e83SPiotr Jasiukajtis } else 1052*25c28e83SPiotr Jasiukajtis carry = (z2 < xy2); 1053*25c28e83SPiotr Jasiukajtis z1 += xy1; 1054*25c28e83SPiotr Jasiukajtis if (carry) { 1055*25c28e83SPiotr Jasiukajtis z1++; 1056*25c28e83SPiotr Jasiukajtis carry = (z1 <= xy1); 1057*25c28e83SPiotr Jasiukajtis } else 1058*25c28e83SPiotr Jasiukajtis carry = (z1 < xy1); 1059*25c28e83SPiotr Jasiukajtis z0 += xy0; 1060*25c28e83SPiotr Jasiukajtis if (carry) { 1061*25c28e83SPiotr Jasiukajtis z0++; 1062*25c28e83SPiotr Jasiukajtis carry = (z0 <= xy0); 1063*25c28e83SPiotr Jasiukajtis } else 1064*25c28e83SPiotr Jasiukajtis carry = (z0 < xy0); 1065*25c28e83SPiotr Jasiukajtis 1066*25c28e83SPiotr Jasiukajtis /* for a magnitude subtract, ignore the last carry out */ 1067*25c28e83SPiotr Jasiukajtis if (sxy ^ sz) 1068*25c28e83SPiotr Jasiukajtis carry = 0; 1069*25c28e83SPiotr Jasiukajtis 1070*25c28e83SPiotr Jasiukajtis /* postnormalize and collect rounding information into z2 */ 1071*25c28e83SPiotr Jasiukajtis if (ez < 1) { 1072*25c28e83SPiotr Jasiukajtis /* result is tiny; shift right until exponent is within range */ 1073*25c28e83SPiotr Jasiukajtis e = 1 - ez; 1074*25c28e83SPiotr Jasiukajtis if (e > 67) { 1075*25c28e83SPiotr Jasiukajtis z2 = 1; /* result can't be exactly zero */ 1076*25c28e83SPiotr Jasiukajtis z0 = z1 = 0; 1077*25c28e83SPiotr Jasiukajtis } else if (e >= 64) { 1078*25c28e83SPiotr Jasiukajtis sticky = z4 | z3 | z2 | z1 | ((z0 << 1) << (95 - e)); 1079*25c28e83SPiotr Jasiukajtis z2 = (z0 >> (e - 64)) | ((carry << 1) << (95 - e)); 1080*25c28e83SPiotr Jasiukajtis if (sticky) 1081*25c28e83SPiotr Jasiukajtis z2 |= 1; 1082*25c28e83SPiotr Jasiukajtis z1 = carry >> (e - 64); 1083*25c28e83SPiotr Jasiukajtis z0 = 0; 1084*25c28e83SPiotr Jasiukajtis } else if (e >= 32) { 1085*25c28e83SPiotr Jasiukajtis sticky = z4 | z3 | z2 | ((z1 << 1) << (63 - e)); 1086*25c28e83SPiotr Jasiukajtis z2 = (z1 >> (e - 32)) | ((z0 << 1) << (63 - e)); 1087*25c28e83SPiotr Jasiukajtis if (sticky) 1088*25c28e83SPiotr Jasiukajtis z2 |= 1; 1089*25c28e83SPiotr Jasiukajtis z1 = (z0 >> (e - 32)) | ((carry << 1) << (63 - e)); 1090*25c28e83SPiotr Jasiukajtis z0 = carry >> (e - 32); 1091*25c28e83SPiotr Jasiukajtis } else { 1092*25c28e83SPiotr Jasiukajtis sticky = z4 | z3 | (z2 << 1) << (31 - e); 1093*25c28e83SPiotr Jasiukajtis z2 = (z2 >> e) | ((z1 << 1) << (31 - e)); 1094*25c28e83SPiotr Jasiukajtis if (sticky) 1095*25c28e83SPiotr Jasiukajtis z2 |= 1; 1096*25c28e83SPiotr Jasiukajtis z1 = (z1 >> e) | ((z0 << 1) << (31 - e)); 1097*25c28e83SPiotr Jasiukajtis z0 = (z0 >> e) | ((carry << 1) << (31 - e)); 1098*25c28e83SPiotr Jasiukajtis } 1099*25c28e83SPiotr Jasiukajtis ez = 1; 1100*25c28e83SPiotr Jasiukajtis } else if (carry) { 1101*25c28e83SPiotr Jasiukajtis /* carry out; shift right by one */ 1102*25c28e83SPiotr Jasiukajtis sticky = (z2 & 1) | z3 | z4; 1103*25c28e83SPiotr Jasiukajtis z2 = (z2 >> 1) | (z1 << 31); 1104*25c28e83SPiotr Jasiukajtis if (sticky) 1105*25c28e83SPiotr Jasiukajtis z2 |= 1; 1106*25c28e83SPiotr Jasiukajtis z1 = (z1 >> 1) | (z0 << 31); 1107*25c28e83SPiotr Jasiukajtis z0 = (z0 >> 1) | 0x80000000; 1108*25c28e83SPiotr Jasiukajtis ez++; 1109*25c28e83SPiotr Jasiukajtis } else { 1110*25c28e83SPiotr Jasiukajtis if (z0 < 0x80000000u && (z0 | z1 | z2 | z3 | z4) != 0) { 1111*25c28e83SPiotr Jasiukajtis /* 1112*25c28e83SPiotr Jasiukajtis * borrow/cancellation; shift left as much as 1113*25c28e83SPiotr Jasiukajtis * exponent allows 1114*25c28e83SPiotr Jasiukajtis */ 1115*25c28e83SPiotr Jasiukajtis while (!z0 && ez >= 33) { 1116*25c28e83SPiotr Jasiukajtis z0 = z1; 1117*25c28e83SPiotr Jasiukajtis z1 = z2; 1118*25c28e83SPiotr Jasiukajtis z2 = z3; 1119*25c28e83SPiotr Jasiukajtis z3 = z4; 1120*25c28e83SPiotr Jasiukajtis z4 = 0; 1121*25c28e83SPiotr Jasiukajtis ez -= 32; 1122*25c28e83SPiotr Jasiukajtis } 1123*25c28e83SPiotr Jasiukajtis while (z0 < 0x80000000u && ez > 1) { 1124*25c28e83SPiotr Jasiukajtis z0 = (z0 << 1) | (z1 >> 31); 1125*25c28e83SPiotr Jasiukajtis z1 = (z1 << 1) | (z2 >> 31); 1126*25c28e83SPiotr Jasiukajtis z2 = (z2 << 1) | (z3 >> 31); 1127*25c28e83SPiotr Jasiukajtis z3 = (z3 << 1) | (z4 >> 31); 1128*25c28e83SPiotr Jasiukajtis z4 <<= 1; 1129*25c28e83SPiotr Jasiukajtis ez--; 1130*25c28e83SPiotr Jasiukajtis } 1131*25c28e83SPiotr Jasiukajtis } 1132*25c28e83SPiotr Jasiukajtis if (z3 | z4) 1133*25c28e83SPiotr Jasiukajtis z2 |= 1; 1134*25c28e83SPiotr Jasiukajtis } 1135*25c28e83SPiotr Jasiukajtis 1136*25c28e83SPiotr Jasiukajtis /* get the rounding mode */ 1137*25c28e83SPiotr Jasiukajtis rm = oldcwsw & 0x0c000000; 1138*25c28e83SPiotr Jasiukajtis 1139*25c28e83SPiotr Jasiukajtis /* adjust exponent if result is subnormal */ 1140*25c28e83SPiotr Jasiukajtis tinyafter = 0; 1141*25c28e83SPiotr Jasiukajtis if (!(z0 & 0x80000000)) { 1142*25c28e83SPiotr Jasiukajtis ez = 0; 1143*25c28e83SPiotr Jasiukajtis tinyafter = 1; 1144*25c28e83SPiotr Jasiukajtis if (!(z0 | z1 | z2)) { /* exact zero */ 1145*25c28e83SPiotr Jasiukajtis zz.i[2] = rm == FCW_RM ? 0x8000 : 0; 1146*25c28e83SPiotr Jasiukajtis zz.i[1] = zz.i[0] = 0; 1147*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&oldcwsw); 1148*25c28e83SPiotr Jasiukajtis return (zz.e); 1149*25c28e83SPiotr Jasiukajtis } 1150*25c28e83SPiotr Jasiukajtis } 1151*25c28e83SPiotr Jasiukajtis 1152*25c28e83SPiotr Jasiukajtis /* 1153*25c28e83SPiotr Jasiukajtis * flip the sense of directed roundings if the result is negative; 1154*25c28e83SPiotr Jasiukajtis * the logic below applies to a positive result 1155*25c28e83SPiotr Jasiukajtis */ 1156*25c28e83SPiotr Jasiukajtis if (sz && (rm == FCW_RM || rm == FCW_RP)) 1157*25c28e83SPiotr Jasiukajtis rm = (FCW_RM + FCW_RP) - rm; 1158*25c28e83SPiotr Jasiukajtis 1159*25c28e83SPiotr Jasiukajtis /* round */ 1160*25c28e83SPiotr Jasiukajtis if (z2) { 1161*25c28e83SPiotr Jasiukajtis if (rm == FCW_RP || (rm == FCW_RN && (z2 > 0x80000000u || 1162*25c28e83SPiotr Jasiukajtis (z2 == 0x80000000u && (z1 & 1))))) { 1163*25c28e83SPiotr Jasiukajtis /* round up and renormalize if necessary */ 1164*25c28e83SPiotr Jasiukajtis if (++z1 == 0) { 1165*25c28e83SPiotr Jasiukajtis if (++z0 == 0) { 1166*25c28e83SPiotr Jasiukajtis z0 = 0x80000000; 1167*25c28e83SPiotr Jasiukajtis ez++; 1168*25c28e83SPiotr Jasiukajtis } else if (z0 == 0x80000000) { 1169*25c28e83SPiotr Jasiukajtis /* rounded up to smallest normal */ 1170*25c28e83SPiotr Jasiukajtis ez = 1; 1171*25c28e83SPiotr Jasiukajtis if ((rm == FCW_RP && z2 > 1172*25c28e83SPiotr Jasiukajtis 0x80000000u) || (rm == FCW_RN && 1173*25c28e83SPiotr Jasiukajtis z2 >= 0xc0000000u)) 1174*25c28e83SPiotr Jasiukajtis /* 1175*25c28e83SPiotr Jasiukajtis * would have rounded up to 1176*25c28e83SPiotr Jasiukajtis * smallest normal even with 1177*25c28e83SPiotr Jasiukajtis * unbounded range 1178*25c28e83SPiotr Jasiukajtis */ 1179*25c28e83SPiotr Jasiukajtis tinyafter = 0; 1180*25c28e83SPiotr Jasiukajtis } 1181*25c28e83SPiotr Jasiukajtis } 1182*25c28e83SPiotr Jasiukajtis } 1183*25c28e83SPiotr Jasiukajtis } 1184*25c28e83SPiotr Jasiukajtis 1185*25c28e83SPiotr Jasiukajtis /* restore the control and status words, check for over/underflow */ 1186*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&oldcwsw); 1187*25c28e83SPiotr Jasiukajtis if (ez >= 0x7fff) { 1188*25c28e83SPiotr Jasiukajtis if (rm == FCW_RN || rm == FCW_RP) { 1189*25c28e83SPiotr Jasiukajtis zz.i[2] = sz | 0x7fff; 1190*25c28e83SPiotr Jasiukajtis zz.i[1] = 0x80000000; 1191*25c28e83SPiotr Jasiukajtis zz.i[0] = 0; 1192*25c28e83SPiotr Jasiukajtis } else { 1193*25c28e83SPiotr Jasiukajtis zz.i[2] = sz | 0x7ffe; 1194*25c28e83SPiotr Jasiukajtis zz.i[1] = 0xffffffff; 1195*25c28e83SPiotr Jasiukajtis zz.i[0] = 0xffffffff; 1196*25c28e83SPiotr Jasiukajtis } 1197*25c28e83SPiotr Jasiukajtis dummy = huge; 1198*25c28e83SPiotr Jasiukajtis dummy *= huge; 1199*25c28e83SPiotr Jasiukajtis } else { 1200*25c28e83SPiotr Jasiukajtis zz.i[2] = sz | ez; 1201*25c28e83SPiotr Jasiukajtis zz.i[1] = z0; 1202*25c28e83SPiotr Jasiukajtis zz.i[0] = z1; 1203*25c28e83SPiotr Jasiukajtis 1204*25c28e83SPiotr Jasiukajtis /* 1205*25c28e83SPiotr Jasiukajtis * tinyafter => result rounded w/ unbounded range would be tiny, 1206*25c28e83SPiotr Jasiukajtis * z2 nonzero => result delivered is inexact 1207*25c28e83SPiotr Jasiukajtis */ 1208*25c28e83SPiotr Jasiukajtis if (tinyafter) { 1209*25c28e83SPiotr Jasiukajtis dummy = tiny; 1210*25c28e83SPiotr Jasiukajtis if (z2) 1211*25c28e83SPiotr Jasiukajtis dummy *= tiny; 1212*25c28e83SPiotr Jasiukajtis else 1213*25c28e83SPiotr Jasiukajtis dummy -= tiny2; 1214*25c28e83SPiotr Jasiukajtis } else if (z2) { 1215*25c28e83SPiotr Jasiukajtis dummy = huge; 1216*25c28e83SPiotr Jasiukajtis dummy += tiny; 1217*25c28e83SPiotr Jasiukajtis } 1218*25c28e83SPiotr Jasiukajtis } 1219*25c28e83SPiotr Jasiukajtis 1220*25c28e83SPiotr Jasiukajtis return (zz.e); 1221*25c28e83SPiotr Jasiukajtis } 1222*25c28e83SPiotr Jasiukajtis 1223*25c28e83SPiotr Jasiukajtis #else 1224*25c28e83SPiotr Jasiukajtis #error Unknown architecture 1225*25c28e83SPiotr Jasiukajtis #endif 1226