s_nextafterl.c revision 1.5
11.5Smatt/* $NetBSD: s_nextafterl.c,v 1.5 2014/01/31 19:38:47 matt 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.5Smatt__RCSID("$NetBSD: s_nextafterl.c,v 1.5 2014/01/31 19:38:47 matt Exp $"); 171.1Schristos 181.1Schristos#include <float.h> 191.1Schristos#include <math.h> 201.1Schristos#include <machine/ieee.h> 211.1Schristos 221.4Smatt#ifdef __HAVE_LONG_DOUBLE 231.4Smatt 241.2Schristos#ifdef EXT_EXP_INFNAN 251.1Schristos#if LDBL_MAX_EXP != 0x4000 261.1Schristos#error "Unsupported long double format" 271.1Schristos#endif 281.1Schristos 291.3Smatt#ifdef LDBL_IMPLICIT_NBIT 301.3Smatt#define LDBL_NBIT 0 311.3Smatt#endif 321.3Smatt 331.1Schristos/* 341.1Schristos * IEEE functions 351.1Schristos * nextafterl(x,y) 361.1Schristos * return the next machine floating-point number of x in the 371.1Schristos * direction toward y. 381.1Schristos * Special cases: 391.1Schristos * If x == y, y shall be returned 401.1Schristos * If x or y is NaN, a NaN shall be returned 411.1Schristos */ 421.1Schristoslong double 431.1Schristosnextafterl(long double x, long double y) 441.1Schristos{ 451.1Schristos volatile long double t; 461.1Schristos union ieee_ext_u ux, uy; 471.1Schristos 481.1Schristos ux.extu_ld = x; 491.1Schristos uy.extu_ld = y; 501.1Schristos 511.5Smatt if ((ux.extu_exp == EXT_EXP_INFNAN && 521.1Schristos ((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) || 531.5Smatt (uy.extu_exp == EXT_EXP_INFNAN && 541.1Schristos ((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0)) 551.1Schristos return x+y; /* x or y is nan */ 561.1Schristos 571.1Schristos if (x == y) return y; /* x=y, return y */ 581.1Schristos 591.1Schristos if (x == 0.0) { 601.1Schristos ux.extu_frach = 0; /* return +-minsubnormal */ 611.1Schristos ux.extu_fracl = 1; 621.1Schristos ux.extu_sign = uy.extu_sign; 631.1Schristos t = ux.extu_ld * ux.extu_ld; 641.1Schristos if (t == ux.extu_ld) 651.1Schristos return t; 661.1Schristos else 671.1Schristos return ux.extu_ld; /* raise underflow flag */ 681.1Schristos } 691.1Schristos 701.1Schristos if ((x>0.0) ^ (x<y)) { /* x -= ulp */ 711.1Schristos if (ux.extu_fracl == 0) { 721.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 731.1Schristos ux.extu_exp -= 1; 741.1Schristos ux.extu_frach = (ux.extu_frach - 1) | 751.1Schristos (ux.extu_frach & LDBL_NBIT); 761.1Schristos } 771.1Schristos ux.extu_fracl -= 1; 781.1Schristos } else { /* x += ulp */ 791.1Schristos ux.extu_fracl += 1; 801.1Schristos if (ux.extu_fracl == 0) { 811.1Schristos ux.extu_frach = (ux.extu_frach + 1) | 821.1Schristos (ux.extu_frach & LDBL_NBIT); 831.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 841.1Schristos ux.extu_exp += 1; 851.1Schristos } 861.1Schristos } 871.1Schristos 881.5Smatt if (ux.extu_exp == EXT_EXP_INFNAN) 891.1Schristos return x+x; /* overflow */ 901.1Schristos 911.1Schristos if (ux.extu_exp == 0) { /* underflow */ 921.3Smatt#ifndef LDBL_IMPLICIT_NBIT 931.1Schristos mask_nbit_l(ux); 941.3Smatt#endif 951.1Schristos t = ux.extu_ld * ux.extu_ld; 961.1Schristos if (t != ux.extu_ld) /* raise underflow flag */ 971.1Schristos return ux.extu_ld; 981.1Schristos } 991.1Schristos 1001.1Schristos return ux.extu_ld; 1011.1Schristos} 1021.2Schristos#endif 1031.4Smatt 1041.4Smatt#endif /* __HAVE_LONG_DOUBLE */ 105