s_nextafterl.c revision 1.2
11.2Schristos/* $NetBSD: s_nextafterl.c,v 1.2 2010/09/17 20:39:39 christos Exp $ */ 21.1Schristos 31.1Schristos/* @(#)s_nextafter.c 5.1 93/09/24 */ 41.1Schristos/* 51.1Schristos * ==================================================== 61.1Schristos * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 71.1Schristos * 81.1Schristos * Developed at SunPro, a Sun Microsystems, Inc. business. 91.1Schristos * Permission to use, copy, modify, and distribute this 101.1Schristos * software is freely granted, provided that this notice 111.1Schristos * is preserved. 121.1Schristos * ==================================================== 131.1Schristos */ 141.1Schristos 151.1Schristos#include <sys/cdefs.h> 161.2Schristos__RCSID("$NetBSD: s_nextafterl.c,v 1.2 2010/09/17 20:39:39 christos Exp $"); 171.1Schristos 181.1Schristos#include <float.h> 191.1Schristos#include <math.h> 201.1Schristos#include <machine/ieee.h> 211.1Schristos 221.2Schristos#ifdef EXT_EXP_INFNAN 231.1Schristos#if LDBL_MAX_EXP != 0x4000 241.1Schristos#error "Unsupported long double format" 251.1Schristos#endif 261.1Schristos 271.1Schristos/* 281.1Schristos * IEEE functions 291.1Schristos * nextafterl(x,y) 301.1Schristos * return the next machine floating-point number of x in the 311.1Schristos * direction toward y. 321.1Schristos * Special cases: 331.1Schristos * If x == y, y shall be returned 341.1Schristos * If x or y is NaN, a NaN shall be returned 351.1Schristos */ 361.1Schristoslong double 371.1Schristosnextafterl(long double x, long double y) 381.1Schristos{ 391.1Schristos volatile long double t; 401.1Schristos union ieee_ext_u ux, uy; 411.1Schristos 421.1Schristos ux.extu_ld = x; 431.1Schristos uy.extu_ld = y; 441.1Schristos 451.1Schristos if ((ux.extu_exp == EXT_EXP_NAN && 461.1Schristos ((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) || 471.1Schristos (uy.extu_exp == EXT_EXP_NAN && 481.1Schristos ((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0)) 491.1Schristos return x+y; /* x or y is nan */ 501.1Schristos 511.1Schristos if (x == y) return y; /* x=y, return y */ 521.1Schristos 531.1Schristos if (x == 0.0) { 541.1Schristos ux.extu_frach = 0; /* return +-minsubnormal */ 551.1Schristos ux.extu_fracl = 1; 561.1Schristos ux.extu_sign = uy.extu_sign; 571.1Schristos t = ux.extu_ld * ux.extu_ld; 581.1Schristos if (t == ux.extu_ld) 591.1Schristos return t; 601.1Schristos else 611.1Schristos return ux.extu_ld; /* raise underflow flag */ 621.1Schristos } 631.1Schristos 641.1Schristos if ((x>0.0) ^ (x<y)) { /* x -= ulp */ 651.1Schristos if (ux.extu_fracl == 0) { 661.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 671.1Schristos ux.extu_exp -= 1; 681.1Schristos ux.extu_frach = (ux.extu_frach - 1) | 691.1Schristos (ux.extu_frach & LDBL_NBIT); 701.1Schristos } 711.1Schristos ux.extu_fracl -= 1; 721.1Schristos } else { /* x += ulp */ 731.1Schristos ux.extu_fracl += 1; 741.1Schristos if (ux.extu_fracl == 0) { 751.1Schristos ux.extu_frach = (ux.extu_frach + 1) | 761.1Schristos (ux.extu_frach & LDBL_NBIT); 771.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 781.1Schristos ux.extu_exp += 1; 791.1Schristos } 801.1Schristos } 811.1Schristos 821.1Schristos if (ux.extu_exp == EXT_EXP_INF) 831.1Schristos return x+x; /* overflow */ 841.1Schristos 851.1Schristos if (ux.extu_exp == 0) { /* underflow */ 861.1Schristos mask_nbit_l(ux); 871.1Schristos t = ux.extu_ld * ux.extu_ld; 881.1Schristos if (t != ux.extu_ld) /* raise underflow flag */ 891.1Schristos return ux.extu_ld; 901.1Schristos } 911.1Schristos 921.1Schristos return ux.extu_ld; 931.1Schristos} 941.2Schristos#endif 95