1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "quad.h" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate static const double C[] = { 32*7c478bd9Sstevel@tonic-gate 0.0, 33*7c478bd9Sstevel@tonic-gate 1.0, 34*7c478bd9Sstevel@tonic-gate 68719476736.0, 35*7c478bd9Sstevel@tonic-gate 402653184.0, 36*7c478bd9Sstevel@tonic-gate 24.0, 37*7c478bd9Sstevel@tonic-gate 16.0, 38*7c478bd9Sstevel@tonic-gate 3.66210937500000000000e-04, 39*7c478bd9Sstevel@tonic-gate 1.52587890625000000000e-05, 40*7c478bd9Sstevel@tonic-gate 1.43051147460937500000e-06, 41*7c478bd9Sstevel@tonic-gate 5.96046447753906250000e-08, 42*7c478bd9Sstevel@tonic-gate 3.72529029846191406250e-09, 43*7c478bd9Sstevel@tonic-gate 2.18278728425502777100e-11, 44*7c478bd9Sstevel@tonic-gate 8.52651282912120223045e-14, 45*7c478bd9Sstevel@tonic-gate 3.55271367880050092936e-15, 46*7c478bd9Sstevel@tonic-gate 1.30104260698260532081e-18, 47*7c478bd9Sstevel@tonic-gate 8.67361737988403547206e-19, 48*7c478bd9Sstevel@tonic-gate 2.16840434497100886801e-19, 49*7c478bd9Sstevel@tonic-gate 3.17637355220362627151e-22, 50*7c478bd9Sstevel@tonic-gate 7.75481824268463445192e-26, 51*7c478bd9Sstevel@tonic-gate 4.62223186652936604733e-33, 52*7c478bd9Sstevel@tonic-gate 9.62964972193617926528e-35, 53*7c478bd9Sstevel@tonic-gate 4.70197740328915003187e-38, 54*7c478bd9Sstevel@tonic-gate 2.75506488473973634680e-40, 55*7c478bd9Sstevel@tonic-gate }; 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate #define zero C[0] 58*7c478bd9Sstevel@tonic-gate #define one C[1] 59*7c478bd9Sstevel@tonic-gate #define two36 C[2] 60*7c478bd9Sstevel@tonic-gate #define three2p27 C[3] 61*7c478bd9Sstevel@tonic-gate #define three2p3 C[4] 62*7c478bd9Sstevel@tonic-gate #define two4 C[5] 63*7c478bd9Sstevel@tonic-gate #define three2m13 C[6] 64*7c478bd9Sstevel@tonic-gate #define twom16 C[7] 65*7c478bd9Sstevel@tonic-gate #define three2m21 C[8] 66*7c478bd9Sstevel@tonic-gate #define twom24 C[9] 67*7c478bd9Sstevel@tonic-gate #define twom28 C[10] 68*7c478bd9Sstevel@tonic-gate #define three2m37 C[11] 69*7c478bd9Sstevel@tonic-gate #define three2m45 C[12] 70*7c478bd9Sstevel@tonic-gate #define twom48 C[13] 71*7c478bd9Sstevel@tonic-gate #define three2m61 C[14] 72*7c478bd9Sstevel@tonic-gate #define twom60 C[15] 73*7c478bd9Sstevel@tonic-gate #define twom62 C[16] 74*7c478bd9Sstevel@tonic-gate #define three2m73 C[17] 75*7c478bd9Sstevel@tonic-gate #define three2m85 C[18] 76*7c478bd9Sstevel@tonic-gate #define three2m109 C[19] 77*7c478bd9Sstevel@tonic-gate #define twom113 C[20] 78*7c478bd9Sstevel@tonic-gate #define twom124 C[21] 79*7c478bd9Sstevel@tonic-gate #define three2m133 C[22] 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate static const unsigned int 82*7c478bd9Sstevel@tonic-gate fsr_re = 0x00000000u, 83*7c478bd9Sstevel@tonic-gate fsr_rn = 0xc0000000u; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #ifdef __sparcv9 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * _Qp_div(pz, x, y) sets *pz = *x / *y. 89*7c478bd9Sstevel@tonic-gate */ 90*7c478bd9Sstevel@tonic-gate void 91*7c478bd9Sstevel@tonic-gate _Qp_div(union longdouble *pz, const union longdouble *x, 92*7c478bd9Sstevel@tonic-gate const union longdouble *y) 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate #else 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * _Q_div(x, y) returns *x / *y. 98*7c478bd9Sstevel@tonic-gate */ 99*7c478bd9Sstevel@tonic-gate union longdouble 100*7c478bd9Sstevel@tonic-gate _Q_div(const union longdouble *x, const union longdouble *y) 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate { 105*7c478bd9Sstevel@tonic-gate union longdouble z; 106*7c478bd9Sstevel@tonic-gate union xdouble u; 107*7c478bd9Sstevel@tonic-gate double c, d, ry, xx[4], yy[5], zz[5]; 108*7c478bd9Sstevel@tonic-gate unsigned int xm, ym, fsr, lx, ly, wx[3], wy[3]; 109*7c478bd9Sstevel@tonic-gate unsigned int msw, frac2, frac3, frac4, rm; 110*7c478bd9Sstevel@tonic-gate int ibit, ex, ey, ez, sign; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate xm = x->l.msw & 0x7fffffff; 113*7c478bd9Sstevel@tonic-gate ym = y->l.msw & 0x7fffffff; 114*7c478bd9Sstevel@tonic-gate sign = (x->l.msw ^ y->l.msw) & ~0x7fffffff; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate __quad_getfsrp(&fsr); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* handle nan and inf cases */ 119*7c478bd9Sstevel@tonic-gate if (xm >= 0x7fff0000 || ym >= 0x7fff0000) { 120*7c478bd9Sstevel@tonic-gate /* handle nan cases according to V9 app. B */ 121*7c478bd9Sstevel@tonic-gate if (QUAD_ISNAN(*y)) { 122*7c478bd9Sstevel@tonic-gate if (!(y->l.msw & 0x8000)) { 123*7c478bd9Sstevel@tonic-gate /* snan, signal invalid */ 124*7c478bd9Sstevel@tonic-gate if (fsr & FSR_NVM) { 125*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 126*7c478bd9Sstevel@tonic-gate } else { 127*7c478bd9Sstevel@tonic-gate Z = *y; 128*7c478bd9Sstevel@tonic-gate Z.l.msw |= 0x8000; 129*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_NVA | 130*7c478bd9Sstevel@tonic-gate FSR_NVC; 131*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 134*7c478bd9Sstevel@tonic-gate } else if (QUAD_ISNAN(*x) && !(x->l.msw & 0x8000)) { 135*7c478bd9Sstevel@tonic-gate /* snan, signal invalid */ 136*7c478bd9Sstevel@tonic-gate if (fsr & FSR_NVM) { 137*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 138*7c478bd9Sstevel@tonic-gate } else { 139*7c478bd9Sstevel@tonic-gate Z = *x; 140*7c478bd9Sstevel@tonic-gate Z.l.msw |= 0x8000; 141*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_NVA | 142*7c478bd9Sstevel@tonic-gate FSR_NVC; 143*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate Z = *y; 148*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate if (QUAD_ISNAN(*x)) { 151*7c478bd9Sstevel@tonic-gate if (!(x->l.msw & 0x8000)) { 152*7c478bd9Sstevel@tonic-gate /* snan, signal invalid */ 153*7c478bd9Sstevel@tonic-gate if (fsr & FSR_NVM) { 154*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 155*7c478bd9Sstevel@tonic-gate } else { 156*7c478bd9Sstevel@tonic-gate Z = *x; 157*7c478bd9Sstevel@tonic-gate Z.l.msw |= 0x8000; 158*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_NVA | 159*7c478bd9Sstevel@tonic-gate FSR_NVC; 160*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate Z = *x; 165*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate if (xm == 0x7fff0000) { 168*7c478bd9Sstevel@tonic-gate /* x is inf */ 169*7c478bd9Sstevel@tonic-gate if (ym == 0x7fff0000) { 170*7c478bd9Sstevel@tonic-gate /* inf / inf, signal invalid */ 171*7c478bd9Sstevel@tonic-gate if (fsr & FSR_NVM) { 172*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 173*7c478bd9Sstevel@tonic-gate } else { 174*7c478bd9Sstevel@tonic-gate Z.l.msw = 0x7fffffff; 175*7c478bd9Sstevel@tonic-gate Z.l.frac2 = Z.l.frac3 = 176*7c478bd9Sstevel@tonic-gate Z.l.frac4 = 0xffffffff; 177*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_NVA | 178*7c478bd9Sstevel@tonic-gate FSR_NVC; 179*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate /* inf / finite, return inf */ 184*7c478bd9Sstevel@tonic-gate Z.l.msw = sign | 0x7fff0000; 185*7c478bd9Sstevel@tonic-gate Z.l.frac2 = Z.l.frac3 = Z.l.frac4 = 0; 186*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate /* y is inf */ 189*7c478bd9Sstevel@tonic-gate Z.l.msw = sign; 190*7c478bd9Sstevel@tonic-gate Z.l.frac2 = Z.l.frac3 = Z.l.frac4 = 0; 191*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* handle zero cases */ 195*7c478bd9Sstevel@tonic-gate if (xm == 0 || ym == 0) { 196*7c478bd9Sstevel@tonic-gate if (QUAD_ISZERO(*x)) { 197*7c478bd9Sstevel@tonic-gate if (QUAD_ISZERO(*y)) { 198*7c478bd9Sstevel@tonic-gate /* zero / zero, signal invalid */ 199*7c478bd9Sstevel@tonic-gate if (fsr & FSR_NVM) { 200*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 201*7c478bd9Sstevel@tonic-gate } else { 202*7c478bd9Sstevel@tonic-gate Z.l.msw = 0x7fffffff; 203*7c478bd9Sstevel@tonic-gate Z.l.frac2 = Z.l.frac3 = 204*7c478bd9Sstevel@tonic-gate Z.l.frac4 = 0xffffffff; 205*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_NVA | 206*7c478bd9Sstevel@tonic-gate FSR_NVC; 207*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate /* zero / nonzero, return zero */ 212*7c478bd9Sstevel@tonic-gate Z.l.msw = sign; 213*7c478bd9Sstevel@tonic-gate Z.l.frac2 = Z.l.frac3 = Z.l.frac4 = 0; 214*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate if (QUAD_ISZERO(*y)) { 217*7c478bd9Sstevel@tonic-gate /* nonzero / zero, signal zero divide */ 218*7c478bd9Sstevel@tonic-gate if (fsr & FSR_DZM) { 219*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 220*7c478bd9Sstevel@tonic-gate } else { 221*7c478bd9Sstevel@tonic-gate Z.l.msw = sign | 0x7fff0000; 222*7c478bd9Sstevel@tonic-gate Z.l.frac2 = Z.l.frac3 = Z.l.frac4 = 0; 223*7c478bd9Sstevel@tonic-gate fsr = (fsr & ~FSR_CEXC) | FSR_DZA | FSR_DZC; 224*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* now x and y are finite, nonzero */ 231*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr_re); 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /* get their normalized significands and exponents */ 234*7c478bd9Sstevel@tonic-gate ex = (int)(xm >> 16); 235*7c478bd9Sstevel@tonic-gate lx = xm & 0xffff; 236*7c478bd9Sstevel@tonic-gate if (ex) { 237*7c478bd9Sstevel@tonic-gate lx |= 0x10000; 238*7c478bd9Sstevel@tonic-gate wx[0] = x->l.frac2; 239*7c478bd9Sstevel@tonic-gate wx[1] = x->l.frac3; 240*7c478bd9Sstevel@tonic-gate wx[2] = x->l.frac4; 241*7c478bd9Sstevel@tonic-gate } else { 242*7c478bd9Sstevel@tonic-gate if (lx | (x->l.frac2 & 0xfffe0000)) { 243*7c478bd9Sstevel@tonic-gate wx[0] = x->l.frac2; 244*7c478bd9Sstevel@tonic-gate wx[1] = x->l.frac3; 245*7c478bd9Sstevel@tonic-gate wx[2] = x->l.frac4; 246*7c478bd9Sstevel@tonic-gate ex = 1; 247*7c478bd9Sstevel@tonic-gate } else if (x->l.frac2 | (x->l.frac3 & 0xfffe0000)) { 248*7c478bd9Sstevel@tonic-gate lx = x->l.frac2; 249*7c478bd9Sstevel@tonic-gate wx[0] = x->l.frac3; 250*7c478bd9Sstevel@tonic-gate wx[1] = x->l.frac4; 251*7c478bd9Sstevel@tonic-gate wx[2] = 0; 252*7c478bd9Sstevel@tonic-gate ex = -31; 253*7c478bd9Sstevel@tonic-gate } else if (x->l.frac3 | (x->l.frac4 & 0xfffe0000)) { 254*7c478bd9Sstevel@tonic-gate lx = x->l.frac3; 255*7c478bd9Sstevel@tonic-gate wx[0] = x->l.frac4; 256*7c478bd9Sstevel@tonic-gate wx[1] = wx[2] = 0; 257*7c478bd9Sstevel@tonic-gate ex = -63; 258*7c478bd9Sstevel@tonic-gate } else { 259*7c478bd9Sstevel@tonic-gate lx = x->l.frac4; 260*7c478bd9Sstevel@tonic-gate wx[0] = wx[1] = wx[2] = 0; 261*7c478bd9Sstevel@tonic-gate ex = -95; 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate while ((lx & 0x10000) == 0) { 264*7c478bd9Sstevel@tonic-gate lx = (lx << 1) | (wx[0] >> 31); 265*7c478bd9Sstevel@tonic-gate wx[0] = (wx[0] << 1) | (wx[1] >> 31); 266*7c478bd9Sstevel@tonic-gate wx[1] = (wx[1] << 1) | (wx[2] >> 31); 267*7c478bd9Sstevel@tonic-gate wx[2] <<= 1; 268*7c478bd9Sstevel@tonic-gate ex--; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate ez = ex; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate ey = (int)(ym >> 16); 274*7c478bd9Sstevel@tonic-gate ly = ym & 0xffff; 275*7c478bd9Sstevel@tonic-gate if (ey) { 276*7c478bd9Sstevel@tonic-gate ly |= 0x10000; 277*7c478bd9Sstevel@tonic-gate wy[0] = y->l.frac2; 278*7c478bd9Sstevel@tonic-gate wy[1] = y->l.frac3; 279*7c478bd9Sstevel@tonic-gate wy[2] = y->l.frac4; 280*7c478bd9Sstevel@tonic-gate } else { 281*7c478bd9Sstevel@tonic-gate if (ly | (y->l.frac2 & 0xfffe0000)) { 282*7c478bd9Sstevel@tonic-gate wy[0] = y->l.frac2; 283*7c478bd9Sstevel@tonic-gate wy[1] = y->l.frac3; 284*7c478bd9Sstevel@tonic-gate wy[2] = y->l.frac4; 285*7c478bd9Sstevel@tonic-gate ey = 1; 286*7c478bd9Sstevel@tonic-gate } else if (y->l.frac2 | (y->l.frac3 & 0xfffe0000)) { 287*7c478bd9Sstevel@tonic-gate ly = y->l.frac2; 288*7c478bd9Sstevel@tonic-gate wy[0] = y->l.frac3; 289*7c478bd9Sstevel@tonic-gate wy[1] = y->l.frac4; 290*7c478bd9Sstevel@tonic-gate wy[2] = 0; 291*7c478bd9Sstevel@tonic-gate ey = -31; 292*7c478bd9Sstevel@tonic-gate } else if (y->l.frac3 | (y->l.frac4 & 0xfffe0000)) { 293*7c478bd9Sstevel@tonic-gate ly = y->l.frac3; 294*7c478bd9Sstevel@tonic-gate wy[0] = y->l.frac4; 295*7c478bd9Sstevel@tonic-gate wy[1] = wy[2] = 0; 296*7c478bd9Sstevel@tonic-gate ey = -63; 297*7c478bd9Sstevel@tonic-gate } else { 298*7c478bd9Sstevel@tonic-gate ly = y->l.frac4; 299*7c478bd9Sstevel@tonic-gate wy[0] = wy[1] = wy[2] = 0; 300*7c478bd9Sstevel@tonic-gate ey = -95; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate while ((ly & 0x10000) == 0) { 303*7c478bd9Sstevel@tonic-gate ly = (ly << 1) | (wy[0] >> 31); 304*7c478bd9Sstevel@tonic-gate wy[0] = (wy[0] << 1) | (wy[1] >> 31); 305*7c478bd9Sstevel@tonic-gate wy[1] = (wy[1] << 1) | (wy[2] >> 31); 306*7c478bd9Sstevel@tonic-gate wy[2] <<= 1; 307*7c478bd9Sstevel@tonic-gate ey--; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate ez -= ey - 0x3fff; 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* extract the significands into doubles */ 313*7c478bd9Sstevel@tonic-gate c = twom16; 314*7c478bd9Sstevel@tonic-gate xx[0] = (double)((int)lx) * c; 315*7c478bd9Sstevel@tonic-gate yy[0] = (double)((int)ly) * c; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate c *= twom24; 318*7c478bd9Sstevel@tonic-gate xx[0] += (double)((int)(wx[0] >> 8)) * c; 319*7c478bd9Sstevel@tonic-gate yy[1] = (double)((int)(wy[0] >> 8)) * c; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate c *= twom24; 322*7c478bd9Sstevel@tonic-gate xx[1] = (double)((int)(((wx[0] << 16) | 323*7c478bd9Sstevel@tonic-gate (wx[1] >> 16)) & 0xffffff)) * c; 324*7c478bd9Sstevel@tonic-gate yy[2] = (double)((int)(((wy[0] << 16) | 325*7c478bd9Sstevel@tonic-gate (wy[1] >> 16)) & 0xffffff)) * c; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate c *= twom24; 328*7c478bd9Sstevel@tonic-gate xx[2] = (double)((int)(((wx[1] << 8) | 329*7c478bd9Sstevel@tonic-gate (wx[2] >> 24)) & 0xffffff)) * c; 330*7c478bd9Sstevel@tonic-gate yy[3] = (double)((int)(((wy[1] << 8) | 331*7c478bd9Sstevel@tonic-gate (wy[2] >> 24)) & 0xffffff)) * c; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate c *= twom24; 334*7c478bd9Sstevel@tonic-gate xx[3] = (double)((int)(wx[2] & 0xffffff)) * c; 335*7c478bd9Sstevel@tonic-gate yy[4] = (double)((int)(wy[2] & 0xffffff)) * c; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* approximate the reciprocal of y */ 338*7c478bd9Sstevel@tonic-gate ry = one / ((yy[0] + yy[1]) + yy[2]); 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* compute the first five "digits" of the quotient */ 341*7c478bd9Sstevel@tonic-gate zz[0] = (ry * (xx[0] + xx[1]) + three2p27) - three2p27; 342*7c478bd9Sstevel@tonic-gate xx[0] = ((xx[0] - zz[0] * yy[0]) - zz[0] * yy[1]) + xx[1]; 343*7c478bd9Sstevel@tonic-gate d = zz[0] * yy[2]; 344*7c478bd9Sstevel@tonic-gate c = (d + three2m13) - three2m13; 345*7c478bd9Sstevel@tonic-gate xx[0] -= c; 346*7c478bd9Sstevel@tonic-gate xx[1] = xx[2] - (d - c); 347*7c478bd9Sstevel@tonic-gate d = zz[0] * yy[3]; 348*7c478bd9Sstevel@tonic-gate c = (d + three2m37) - three2m37; 349*7c478bd9Sstevel@tonic-gate xx[1] -= c; 350*7c478bd9Sstevel@tonic-gate xx[2] = xx[3] - (d - c); 351*7c478bd9Sstevel@tonic-gate d = zz[0] * yy[4]; 352*7c478bd9Sstevel@tonic-gate c = (d + three2m61) - three2m61; 353*7c478bd9Sstevel@tonic-gate xx[2] -= c; 354*7c478bd9Sstevel@tonic-gate xx[3] = c - d; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate zz[1] = (ry * (xx[0] + xx[1]) + three2p3) - three2p3; 357*7c478bd9Sstevel@tonic-gate xx[0] = ((xx[0] - zz[1] * yy[0]) - zz[1] * yy[1]) + xx[1]; 358*7c478bd9Sstevel@tonic-gate d = zz[1] * yy[2]; 359*7c478bd9Sstevel@tonic-gate c = (d + three2m37) - three2m37; 360*7c478bd9Sstevel@tonic-gate xx[0] -= c; 361*7c478bd9Sstevel@tonic-gate xx[1] = xx[2] - (d - c); 362*7c478bd9Sstevel@tonic-gate d = zz[1] * yy[3]; 363*7c478bd9Sstevel@tonic-gate c = (d + three2m61) - three2m61; 364*7c478bd9Sstevel@tonic-gate xx[1] -= c; 365*7c478bd9Sstevel@tonic-gate xx[2] = xx[3] - (d - c); 366*7c478bd9Sstevel@tonic-gate d = zz[1] * yy[4]; 367*7c478bd9Sstevel@tonic-gate c = (d + three2m85) - three2m85; 368*7c478bd9Sstevel@tonic-gate xx[2] -= c; 369*7c478bd9Sstevel@tonic-gate xx[3] = c - d; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate zz[2] = (ry * (xx[0] + xx[1]) + three2m21) - three2m21; 372*7c478bd9Sstevel@tonic-gate xx[0] = ((xx[0] - zz[2] * yy[0]) - zz[2] * yy[1]) + xx[1]; 373*7c478bd9Sstevel@tonic-gate d = zz[2] * yy[2]; 374*7c478bd9Sstevel@tonic-gate c = (d + three2m61) - three2m61; 375*7c478bd9Sstevel@tonic-gate xx[0] -= c; 376*7c478bd9Sstevel@tonic-gate xx[1] = xx[2] - (d - c); 377*7c478bd9Sstevel@tonic-gate d = zz[2] * yy[3]; 378*7c478bd9Sstevel@tonic-gate c = (d + three2m85) - three2m85; 379*7c478bd9Sstevel@tonic-gate xx[1] -= c; 380*7c478bd9Sstevel@tonic-gate xx[2] = xx[3] - (d - c); 381*7c478bd9Sstevel@tonic-gate d = zz[2] * yy[4]; 382*7c478bd9Sstevel@tonic-gate c = (d + three2m109) - three2m109; 383*7c478bd9Sstevel@tonic-gate xx[2] -= c; 384*7c478bd9Sstevel@tonic-gate xx[3] = c - d; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate zz[3] = (ry * (xx[0] + xx[1]) + three2m45) - three2m45; 387*7c478bd9Sstevel@tonic-gate xx[0] = ((xx[0] - zz[3] * yy[0]) - zz[3] * yy[1]) + xx[1]; 388*7c478bd9Sstevel@tonic-gate d = zz[3] * yy[2]; 389*7c478bd9Sstevel@tonic-gate c = (d + three2m85) - three2m85; 390*7c478bd9Sstevel@tonic-gate xx[0] -= c; 391*7c478bd9Sstevel@tonic-gate xx[1] = xx[2] - (d - c); 392*7c478bd9Sstevel@tonic-gate d = zz[3] * yy[3]; 393*7c478bd9Sstevel@tonic-gate c = (d + three2m109) - three2m109; 394*7c478bd9Sstevel@tonic-gate xx[1] -= c; 395*7c478bd9Sstevel@tonic-gate xx[2] = xx[3] - (d - c); 396*7c478bd9Sstevel@tonic-gate d = zz[3] * yy[4]; 397*7c478bd9Sstevel@tonic-gate c = (d + three2m133) - three2m133; 398*7c478bd9Sstevel@tonic-gate xx[2] -= c; 399*7c478bd9Sstevel@tonic-gate xx[3] = c - d; 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate zz[4] = (ry * (xx[0] + xx[1]) + three2m73) - three2m73; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate /* reduce to three doubles, making sure zz[1] is positive */ 404*7c478bd9Sstevel@tonic-gate zz[0] += zz[1] - twom48; 405*7c478bd9Sstevel@tonic-gate zz[1] = twom48 + zz[2] + zz[3]; 406*7c478bd9Sstevel@tonic-gate zz[2] = zz[4]; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* if the third term might lie on a rounding boundary, perturb it */ 409*7c478bd9Sstevel@tonic-gate if (zz[2] == (twom62 + zz[2]) - twom62) { 410*7c478bd9Sstevel@tonic-gate /* here we just need to get the sign of the remainder */ 411*7c478bd9Sstevel@tonic-gate c = (((((xx[0] - zz[4] * yy[0]) - zz[4] * yy[1]) + xx[1]) + 412*7c478bd9Sstevel@tonic-gate (xx[2] - zz[4] * yy[2])) + (xx[3] - zz[4] * yy[3])) 413*7c478bd9Sstevel@tonic-gate - zz[4] * yy[4]; 414*7c478bd9Sstevel@tonic-gate if (c < zero) 415*7c478bd9Sstevel@tonic-gate zz[2] -= twom124; 416*7c478bd9Sstevel@tonic-gate else if (c > zero) 417*7c478bd9Sstevel@tonic-gate zz[2] += twom124; 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * propagate carries/borrows, using round-to-negative-infinity mode 422*7c478bd9Sstevel@tonic-gate * to make all terms nonnegative (note that we can't encounter a 423*7c478bd9Sstevel@tonic-gate * borrow so large that the roundoff is unrepresentable because 424*7c478bd9Sstevel@tonic-gate * we took care to make zz[1] positive above) 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr_rn); 427*7c478bd9Sstevel@tonic-gate c = zz[1] + zz[2]; 428*7c478bd9Sstevel@tonic-gate zz[2] += (zz[1] - c); 429*7c478bd9Sstevel@tonic-gate zz[1] = c; 430*7c478bd9Sstevel@tonic-gate c = zz[0] + zz[1]; 431*7c478bd9Sstevel@tonic-gate zz[1] += (zz[0] - c); 432*7c478bd9Sstevel@tonic-gate zz[0] = c; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* check for borrow */ 435*7c478bd9Sstevel@tonic-gate if (c < one) { 436*7c478bd9Sstevel@tonic-gate /* postnormalize */ 437*7c478bd9Sstevel@tonic-gate zz[0] += zz[0]; 438*7c478bd9Sstevel@tonic-gate zz[1] += zz[1]; 439*7c478bd9Sstevel@tonic-gate zz[2] += zz[2]; 440*7c478bd9Sstevel@tonic-gate ez--; 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate /* if exponent > 0 strip off integer bit, else denormalize */ 444*7c478bd9Sstevel@tonic-gate if (ez > 0) { 445*7c478bd9Sstevel@tonic-gate ibit = 1; 446*7c478bd9Sstevel@tonic-gate zz[0] -= one; 447*7c478bd9Sstevel@tonic-gate } else { 448*7c478bd9Sstevel@tonic-gate ibit = 0; 449*7c478bd9Sstevel@tonic-gate if (ez > -128) 450*7c478bd9Sstevel@tonic-gate u.l.hi = (unsigned int)(0x3fe + ez) << 20; 451*7c478bd9Sstevel@tonic-gate else 452*7c478bd9Sstevel@tonic-gate u.l.hi = 0x37e00000; 453*7c478bd9Sstevel@tonic-gate u.l.lo = 0; 454*7c478bd9Sstevel@tonic-gate zz[0] *= u.d; 455*7c478bd9Sstevel@tonic-gate zz[1] *= u.d; 456*7c478bd9Sstevel@tonic-gate zz[2] *= u.d; 457*7c478bd9Sstevel@tonic-gate ez = 0; 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* the first 48 bits of fraction come from zz[0] */ 461*7c478bd9Sstevel@tonic-gate u.d = d = two36 + zz[0]; 462*7c478bd9Sstevel@tonic-gate msw = u.l.lo; 463*7c478bd9Sstevel@tonic-gate zz[0] -= (d - two36); 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate u.d = d = two4 + zz[0]; 466*7c478bd9Sstevel@tonic-gate frac2 = u.l.lo; 467*7c478bd9Sstevel@tonic-gate zz[0] -= (d - two4); 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* the next 32 come from zz[0] and zz[1] */ 470*7c478bd9Sstevel@tonic-gate u.d = d = twom28 + (zz[0] + zz[1]); 471*7c478bd9Sstevel@tonic-gate frac3 = u.l.lo; 472*7c478bd9Sstevel@tonic-gate zz[0] -= (d - twom28); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* condense the remaining fraction; errors here won't matter */ 475*7c478bd9Sstevel@tonic-gate c = zz[0] + zz[1]; 476*7c478bd9Sstevel@tonic-gate zz[1] = ((zz[0] - c) + zz[1]) + zz[2]; 477*7c478bd9Sstevel@tonic-gate zz[0] = c; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate /* get the last word of fraction */ 480*7c478bd9Sstevel@tonic-gate u.d = d = twom60 + (zz[0] + zz[1]); 481*7c478bd9Sstevel@tonic-gate frac4 = u.l.lo; 482*7c478bd9Sstevel@tonic-gate zz[0] -= (d - twom60); 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate /* keep track of what's left for rounding; note that the error */ 485*7c478bd9Sstevel@tonic-gate /* in computing c will be non-negative due to rounding mode */ 486*7c478bd9Sstevel@tonic-gate c = zz[0] + zz[1]; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate /* get the rounding mode, fudging directed rounding modes */ 489*7c478bd9Sstevel@tonic-gate /* as though the result were positive */ 490*7c478bd9Sstevel@tonic-gate rm = fsr >> 30; 491*7c478bd9Sstevel@tonic-gate if (sign) 492*7c478bd9Sstevel@tonic-gate rm ^= (rm >> 1); 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate /* round and raise exceptions */ 495*7c478bd9Sstevel@tonic-gate fsr &= ~FSR_CEXC; 496*7c478bd9Sstevel@tonic-gate if (c != zero) { 497*7c478bd9Sstevel@tonic-gate fsr |= FSR_NXC; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate /* decide whether to round the fraction up */ 500*7c478bd9Sstevel@tonic-gate if (rm == FSR_RP || (rm == FSR_RN && (c > twom113 || 501*7c478bd9Sstevel@tonic-gate (c == twom113 && ((frac4 & 1) || (c - zz[0] != 502*7c478bd9Sstevel@tonic-gate zz[1])))))) { 503*7c478bd9Sstevel@tonic-gate /* round up and renormalize if necessary */ 504*7c478bd9Sstevel@tonic-gate if (++frac4 == 0) 505*7c478bd9Sstevel@tonic-gate if (++frac3 == 0) 506*7c478bd9Sstevel@tonic-gate if (++frac2 == 0) 507*7c478bd9Sstevel@tonic-gate if (++msw == 0x10000) { 508*7c478bd9Sstevel@tonic-gate msw = 0; 509*7c478bd9Sstevel@tonic-gate ez++; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate /* check for under/overflow */ 515*7c478bd9Sstevel@tonic-gate if (ez >= 0x7fff) { 516*7c478bd9Sstevel@tonic-gate if (rm == FSR_RN || rm == FSR_RP) { 517*7c478bd9Sstevel@tonic-gate z.l.msw = sign | 0x7fff0000; 518*7c478bd9Sstevel@tonic-gate z.l.frac2 = z.l.frac3 = z.l.frac4 = 0; 519*7c478bd9Sstevel@tonic-gate } else { 520*7c478bd9Sstevel@tonic-gate z.l.msw = sign | 0x7ffeffff; 521*7c478bd9Sstevel@tonic-gate z.l.frac2 = z.l.frac3 = z.l.frac4 = 0xffffffff; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate fsr |= FSR_OFC | FSR_NXC; 524*7c478bd9Sstevel@tonic-gate } else { 525*7c478bd9Sstevel@tonic-gate z.l.msw = sign | (ez << 16) | msw; 526*7c478bd9Sstevel@tonic-gate z.l.frac2 = frac2; 527*7c478bd9Sstevel@tonic-gate z.l.frac3 = frac3; 528*7c478bd9Sstevel@tonic-gate z.l.frac4 = frac4; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* !ibit => exact result was tiny before rounding, */ 531*7c478bd9Sstevel@tonic-gate /* t nonzero => result delivered is inexact */ 532*7c478bd9Sstevel@tonic-gate if (!ibit) { 533*7c478bd9Sstevel@tonic-gate if (c != zero) 534*7c478bd9Sstevel@tonic-gate fsr |= FSR_UFC | FSR_NXC; 535*7c478bd9Sstevel@tonic-gate else if (fsr & FSR_UFM) 536*7c478bd9Sstevel@tonic-gate fsr |= FSR_UFC; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate if ((fsr & FSR_CEXC) & (fsr >> 23)) { 541*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 542*7c478bd9Sstevel@tonic-gate __quad_fdivq(x, y, &Z); 543*7c478bd9Sstevel@tonic-gate } else { 544*7c478bd9Sstevel@tonic-gate Z = z; 545*7c478bd9Sstevel@tonic-gate fsr |= (fsr & 0x1f) << 5; 546*7c478bd9Sstevel@tonic-gate __quad_setfsrp(&fsr); 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate QUAD_RETURN(Z); 549*7c478bd9Sstevel@tonic-gate } 550