s_nextafterl.c revision 1.1
1/* $NetBSD: s_nextafterl.c,v 1.1 2010/09/15 16:12:05 christos Exp $ */ 2 3/* @(#)s_nextafter.c 5.1 93/09/24 */ 4/* 5 * ==================================================== 6 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 7 * 8 * Developed at SunPro, a Sun Microsystems, Inc. business. 9 * Permission to use, copy, modify, and distribute this 10 * software is freely granted, provided that this notice 11 * is preserved. 12 * ==================================================== 13 */ 14 15#include <sys/cdefs.h> 16__RCSID("$NetBSD: s_nextafterl.c,v 1.1 2010/09/15 16:12:05 christos Exp $"); 17 18#include <float.h> 19#include <math.h> 20#include <machine/ieee.h> 21 22#if LDBL_MAX_EXP != 0x4000 23#error "Unsupported long double format" 24#endif 25 26/* 27 * IEEE functions 28 * nextafterl(x,y) 29 * return the next machine floating-point number of x in the 30 * direction toward y. 31 * Special cases: 32 * If x == y, y shall be returned 33 * If x or y is NaN, a NaN shall be returned 34 */ 35long double 36nextafterl(long double x, long double y) 37{ 38 volatile long double t; 39 union ieee_ext_u ux, uy; 40 41 ux.extu_ld = x; 42 uy.extu_ld = y; 43 44 if ((ux.extu_exp == EXT_EXP_NAN && 45 ((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) || 46 (uy.extu_exp == EXT_EXP_NAN && 47 ((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0)) 48 return x+y; /* x or y is nan */ 49 50 if (x == y) return y; /* x=y, return y */ 51 52 if (x == 0.0) { 53 ux.extu_frach = 0; /* return +-minsubnormal */ 54 ux.extu_fracl = 1; 55 ux.extu_sign = uy.extu_sign; 56 t = ux.extu_ld * ux.extu_ld; 57 if (t == ux.extu_ld) 58 return t; 59 else 60 return ux.extu_ld; /* raise underflow flag */ 61 } 62 63 if ((x>0.0) ^ (x<y)) { /* x -= ulp */ 64 if (ux.extu_fracl == 0) { 65 if ((ux.extu_frach & ~LDBL_NBIT) == 0) 66 ux.extu_exp -= 1; 67 ux.extu_frach = (ux.extu_frach - 1) | 68 (ux.extu_frach & LDBL_NBIT); 69 } 70 ux.extu_fracl -= 1; 71 } else { /* x += ulp */ 72 ux.extu_fracl += 1; 73 if (ux.extu_fracl == 0) { 74 ux.extu_frach = (ux.extu_frach + 1) | 75 (ux.extu_frach & LDBL_NBIT); 76 if ((ux.extu_frach & ~LDBL_NBIT) == 0) 77 ux.extu_exp += 1; 78 } 79 } 80 81 if (ux.extu_exp == EXT_EXP_INF) 82 return x+x; /* overflow */ 83 84 if (ux.extu_exp == 0) { /* underflow */ 85 mask_nbit_l(ux); 86 t = ux.extu_ld * ux.extu_ld; 87 if (t != ux.extu_ld) /* raise underflow flag */ 88 return ux.extu_ld; 89 } 90 91 return ux.extu_ld; 92} 93