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 nexttoward = __nexttoward 31*25c28e83SPiotr Jasiukajtis 32*25c28e83SPiotr Jasiukajtis /* 33*25c28e83SPiotr Jasiukajtis * nexttoward(x, y) delivers the next representable number after x 34*25c28e83SPiotr Jasiukajtis * in the direction of y. If x and y are both zero, the result is 35*25c28e83SPiotr Jasiukajtis * zero with the same sign as y. If either x or y is NaN, the result 36*25c28e83SPiotr Jasiukajtis * is NaN. 37*25c28e83SPiotr Jasiukajtis * 38*25c28e83SPiotr Jasiukajtis * If x != y and the result is infinite, overflow is raised; if 39*25c28e83SPiotr Jasiukajtis * x != y and the result is subnormal or zero, underflow is raised. 40*25c28e83SPiotr Jasiukajtis * (This is wrong, but it's what C99 apparently wants.) 41*25c28e83SPiotr Jasiukajtis */ 42*25c28e83SPiotr Jasiukajtis 43*25c28e83SPiotr Jasiukajtis #include "libm.h" 44*25c28e83SPiotr Jasiukajtis 45*25c28e83SPiotr Jasiukajtis #if defined(__sparc) 46*25c28e83SPiotr Jasiukajtis 47*25c28e83SPiotr Jasiukajtis static union { 48*25c28e83SPiotr Jasiukajtis unsigned i[2]; 49*25c28e83SPiotr Jasiukajtis double d; 50*25c28e83SPiotr Jasiukajtis } C[] = { 51*25c28e83SPiotr Jasiukajtis 0x00100000, 0, 52*25c28e83SPiotr Jasiukajtis 0x7fe00000, 0, 53*25c28e83SPiotr Jasiukajtis 0x7fffffff, 0xffffffff 54*25c28e83SPiotr Jasiukajtis }; 55*25c28e83SPiotr Jasiukajtis 56*25c28e83SPiotr Jasiukajtis #define tiny C[0].d 57*25c28e83SPiotr Jasiukajtis #define huge C[1].d 58*25c28e83SPiotr Jasiukajtis #define qnan C[2].d 59*25c28e83SPiotr Jasiukajtis 60*25c28e83SPiotr Jasiukajtis enum fcc_type { 61*25c28e83SPiotr Jasiukajtis fcc_equal = 0, 62*25c28e83SPiotr Jasiukajtis fcc_less = 1, 63*25c28e83SPiotr Jasiukajtis fcc_greater = 2, 64*25c28e83SPiotr Jasiukajtis fcc_unordered = 3 65*25c28e83SPiotr Jasiukajtis }; 66*25c28e83SPiotr Jasiukajtis 67*25c28e83SPiotr Jasiukajtis #ifdef __sparcv9 68*25c28e83SPiotr Jasiukajtis #define _Q_cmp _Qp_cmp 69*25c28e83SPiotr Jasiukajtis #endif 70*25c28e83SPiotr Jasiukajtis 71*25c28e83SPiotr Jasiukajtis extern enum fcc_type _Q_cmp(const long double *, const long double *); 72*25c28e83SPiotr Jasiukajtis 73*25c28e83SPiotr Jasiukajtis double 74*25c28e83SPiotr Jasiukajtis __nexttoward(double x, long double y) { 75*25c28e83SPiotr Jasiukajtis union { 76*25c28e83SPiotr Jasiukajtis unsigned i[2]; 77*25c28e83SPiotr Jasiukajtis double d; 78*25c28e83SPiotr Jasiukajtis } xx; 79*25c28e83SPiotr Jasiukajtis union { 80*25c28e83SPiotr Jasiukajtis unsigned i[4]; 81*25c28e83SPiotr Jasiukajtis long double q; 82*25c28e83SPiotr Jasiukajtis } yy; 83*25c28e83SPiotr Jasiukajtis long double lx; 84*25c28e83SPiotr Jasiukajtis unsigned hx; 85*25c28e83SPiotr Jasiukajtis volatile double dummy; 86*25c28e83SPiotr Jasiukajtis enum fcc_type rel; 87*25c28e83SPiotr Jasiukajtis 88*25c28e83SPiotr Jasiukajtis /* 89*25c28e83SPiotr Jasiukajtis * It would be somewhat more efficient to check for NaN and 90*25c28e83SPiotr Jasiukajtis * zero operands before converting x to long double and then 91*25c28e83SPiotr Jasiukajtis * to code the comparison in line rather than calling _Q_cmp. 92*25c28e83SPiotr Jasiukajtis * However, since this code probably won't get used much, 93*25c28e83SPiotr Jasiukajtis * I'm opting in favor of simplicity instead. 94*25c28e83SPiotr Jasiukajtis */ 95*25c28e83SPiotr Jasiukajtis lx = xx.d = x; 96*25c28e83SPiotr Jasiukajtis hx = (xx.i[0] & ~0x80000000) | xx.i[1]; 97*25c28e83SPiotr Jasiukajtis 98*25c28e83SPiotr Jasiukajtis /* check for each of four possible orderings */ 99*25c28e83SPiotr Jasiukajtis rel = _Q_cmp(&lx, &y); 100*25c28e83SPiotr Jasiukajtis if (rel == fcc_unordered) 101*25c28e83SPiotr Jasiukajtis return (qnan); 102*25c28e83SPiotr Jasiukajtis 103*25c28e83SPiotr Jasiukajtis if (rel == fcc_equal) { 104*25c28e83SPiotr Jasiukajtis if (hx == 0) { /* x is zero; return zero with y's sign */ 105*25c28e83SPiotr Jasiukajtis yy.q = y; 106*25c28e83SPiotr Jasiukajtis xx.i[0] = yy.i[0]; 107*25c28e83SPiotr Jasiukajtis return (xx.d); 108*25c28e83SPiotr Jasiukajtis } 109*25c28e83SPiotr Jasiukajtis return (x); 110*25c28e83SPiotr Jasiukajtis } 111*25c28e83SPiotr Jasiukajtis 112*25c28e83SPiotr Jasiukajtis if (rel == fcc_less) { 113*25c28e83SPiotr Jasiukajtis if (hx == 0) { /* x is zero */ 114*25c28e83SPiotr Jasiukajtis xx.i[0] = 0; 115*25c28e83SPiotr Jasiukajtis xx.i[1] = 0x00000001; 116*25c28e83SPiotr Jasiukajtis } else if ((int)xx.i[0] >= 0) { /* x is positive */ 117*25c28e83SPiotr Jasiukajtis if (++xx.i[1] == 0) 118*25c28e83SPiotr Jasiukajtis xx.i[0]++; 119*25c28e83SPiotr Jasiukajtis } else { 120*25c28e83SPiotr Jasiukajtis if (xx.i[1]-- == 0) 121*25c28e83SPiotr Jasiukajtis xx.i[0]--; 122*25c28e83SPiotr Jasiukajtis } 123*25c28e83SPiotr Jasiukajtis } else { 124*25c28e83SPiotr Jasiukajtis if (hx == 0) { /* x is zero */ 125*25c28e83SPiotr Jasiukajtis xx.i[0] = 0x80000000; 126*25c28e83SPiotr Jasiukajtis xx.i[1] = 0x00000001; 127*25c28e83SPiotr Jasiukajtis } else if ((int)xx.i[0] >= 0) { /* x is positive */ 128*25c28e83SPiotr Jasiukajtis if (xx.i[1]-- == 0) 129*25c28e83SPiotr Jasiukajtis xx.i[0]--; 130*25c28e83SPiotr Jasiukajtis } else { 131*25c28e83SPiotr Jasiukajtis if (++xx.i[1] == 0) 132*25c28e83SPiotr Jasiukajtis xx.i[0]++; 133*25c28e83SPiotr Jasiukajtis } 134*25c28e83SPiotr Jasiukajtis } 135*25c28e83SPiotr Jasiukajtis 136*25c28e83SPiotr Jasiukajtis /* raise exceptions as needed */ 137*25c28e83SPiotr Jasiukajtis hx = xx.i[0] & ~0x80000000; 138*25c28e83SPiotr Jasiukajtis if (hx == 0x7ff00000) { 139*25c28e83SPiotr Jasiukajtis dummy = huge; 140*25c28e83SPiotr Jasiukajtis dummy *= huge; 141*25c28e83SPiotr Jasiukajtis } else if (hx < 0x00100000) { 142*25c28e83SPiotr Jasiukajtis dummy = tiny; 143*25c28e83SPiotr Jasiukajtis dummy *= tiny; 144*25c28e83SPiotr Jasiukajtis } 145*25c28e83SPiotr Jasiukajtis 146*25c28e83SPiotr Jasiukajtis return (xx.d); 147*25c28e83SPiotr Jasiukajtis } 148*25c28e83SPiotr Jasiukajtis 149*25c28e83SPiotr Jasiukajtis #elif defined(__x86) 150*25c28e83SPiotr Jasiukajtis 151*25c28e83SPiotr Jasiukajtis static union { 152*25c28e83SPiotr Jasiukajtis unsigned i[2]; 153*25c28e83SPiotr Jasiukajtis double d; 154*25c28e83SPiotr Jasiukajtis } C[] = { 155*25c28e83SPiotr Jasiukajtis 0, 0x00100000, 156*25c28e83SPiotr Jasiukajtis 0, 0x7fe00000, 157*25c28e83SPiotr Jasiukajtis }; 158*25c28e83SPiotr Jasiukajtis 159*25c28e83SPiotr Jasiukajtis #define tiny C[0].d 160*25c28e83SPiotr Jasiukajtis #define huge C[1].d 161*25c28e83SPiotr Jasiukajtis 162*25c28e83SPiotr Jasiukajtis double 163*25c28e83SPiotr Jasiukajtis __nexttoward(double x, long double y) { 164*25c28e83SPiotr Jasiukajtis union { 165*25c28e83SPiotr Jasiukajtis unsigned i[2]; 166*25c28e83SPiotr Jasiukajtis double d; 167*25c28e83SPiotr Jasiukajtis } xx; 168*25c28e83SPiotr Jasiukajtis unsigned hx; 169*25c28e83SPiotr Jasiukajtis long double lx; 170*25c28e83SPiotr Jasiukajtis volatile double dummy; 171*25c28e83SPiotr Jasiukajtis 172*25c28e83SPiotr Jasiukajtis lx = xx.d = x; 173*25c28e83SPiotr Jasiukajtis hx = (xx.i[1] & ~0x80000000) | xx.i[0]; 174*25c28e83SPiotr Jasiukajtis 175*25c28e83SPiotr Jasiukajtis /* check for each of four possible orderings */ 176*25c28e83SPiotr Jasiukajtis if (isunordered(lx, y)) 177*25c28e83SPiotr Jasiukajtis return ((double) (lx + y)); 178*25c28e83SPiotr Jasiukajtis 179*25c28e83SPiotr Jasiukajtis if (lx == y) 180*25c28e83SPiotr Jasiukajtis return ((double) y); 181*25c28e83SPiotr Jasiukajtis 182*25c28e83SPiotr Jasiukajtis if (lx < y) { 183*25c28e83SPiotr Jasiukajtis if (hx == 0) { /* x is zero */ 184*25c28e83SPiotr Jasiukajtis xx.i[0] = 0x00000001; 185*25c28e83SPiotr Jasiukajtis xx.i[1] = 0; 186*25c28e83SPiotr Jasiukajtis } else if ((int)xx.i[1] >= 0) { /* x is positive */ 187*25c28e83SPiotr Jasiukajtis if (++xx.i[0] == 0) 188*25c28e83SPiotr Jasiukajtis xx.i[1]++; 189*25c28e83SPiotr Jasiukajtis } else { 190*25c28e83SPiotr Jasiukajtis if (xx.i[0]-- == 0) 191*25c28e83SPiotr Jasiukajtis xx.i[1]--; 192*25c28e83SPiotr Jasiukajtis } 193*25c28e83SPiotr Jasiukajtis } else { 194*25c28e83SPiotr Jasiukajtis if (hx == 0) { /* x is zero */ 195*25c28e83SPiotr Jasiukajtis xx.i[0] = 0x00000001; 196*25c28e83SPiotr Jasiukajtis xx.i[1] = 0x80000000; 197*25c28e83SPiotr Jasiukajtis } else if ((int)xx.i[1] >= 0) { /* x is positive */ 198*25c28e83SPiotr Jasiukajtis if (xx.i[0]-- == 0) 199*25c28e83SPiotr Jasiukajtis xx.i[1]--; 200*25c28e83SPiotr Jasiukajtis } else { 201*25c28e83SPiotr Jasiukajtis if (++xx.i[0] == 0) 202*25c28e83SPiotr Jasiukajtis xx.i[1]++; 203*25c28e83SPiotr Jasiukajtis } 204*25c28e83SPiotr Jasiukajtis } 205*25c28e83SPiotr Jasiukajtis 206*25c28e83SPiotr Jasiukajtis /* raise exceptions as needed */ 207*25c28e83SPiotr Jasiukajtis hx = xx.i[1] & ~0x80000000; 208*25c28e83SPiotr Jasiukajtis if (hx == 0x7ff00000) { 209*25c28e83SPiotr Jasiukajtis dummy = huge; 210*25c28e83SPiotr Jasiukajtis dummy *= huge; 211*25c28e83SPiotr Jasiukajtis } else if (hx < 0x00100000) { 212*25c28e83SPiotr Jasiukajtis dummy = tiny; 213*25c28e83SPiotr Jasiukajtis dummy *= tiny; 214*25c28e83SPiotr Jasiukajtis } 215*25c28e83SPiotr Jasiukajtis 216*25c28e83SPiotr Jasiukajtis return (xx.d); 217*25c28e83SPiotr Jasiukajtis } 218*25c28e83SPiotr Jasiukajtis 219*25c28e83SPiotr Jasiukajtis #else 220*25c28e83SPiotr Jasiukajtis #error Unknown architecture 221*25c28e83SPiotr Jasiukajtis #endif 222