s_nextafterl.c revision 1.3
11.3Smatt/* $NetBSD: s_nextafterl.c,v 1.3 2013/02/14 08:56:56 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.3Smatt__RCSID("$NetBSD: s_nextafterl.c,v 1.3 2013/02/14 08:56:56 matt 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.3Smatt#ifdef LDBL_IMPLICIT_NBIT 281.3Smatt#define LDBL_NBIT 0 291.3Smatt#endif 301.3Smatt 311.1Schristos/* 321.1Schristos * IEEE functions 331.1Schristos * nextafterl(x,y) 341.1Schristos * return the next machine floating-point number of x in the 351.1Schristos * direction toward y. 361.1Schristos * Special cases: 371.1Schristos * If x == y, y shall be returned 381.1Schristos * If x or y is NaN, a NaN shall be returned 391.1Schristos */ 401.1Schristoslong double 411.1Schristosnextafterl(long double x, long double y) 421.1Schristos{ 431.1Schristos volatile long double t; 441.1Schristos union ieee_ext_u ux, uy; 451.1Schristos 461.1Schristos ux.extu_ld = x; 471.1Schristos uy.extu_ld = y; 481.1Schristos 491.1Schristos if ((ux.extu_exp == EXT_EXP_NAN && 501.1Schristos ((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) || 511.1Schristos (uy.extu_exp == EXT_EXP_NAN && 521.1Schristos ((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0)) 531.1Schristos return x+y; /* x or y is nan */ 541.1Schristos 551.1Schristos if (x == y) return y; /* x=y, return y */ 561.1Schristos 571.1Schristos if (x == 0.0) { 581.1Schristos ux.extu_frach = 0; /* return +-minsubnormal */ 591.1Schristos ux.extu_fracl = 1; 601.1Schristos ux.extu_sign = uy.extu_sign; 611.1Schristos t = ux.extu_ld * ux.extu_ld; 621.1Schristos if (t == ux.extu_ld) 631.1Schristos return t; 641.1Schristos else 651.1Schristos return ux.extu_ld; /* raise underflow flag */ 661.1Schristos } 671.1Schristos 681.1Schristos if ((x>0.0) ^ (x<y)) { /* x -= ulp */ 691.1Schristos if (ux.extu_fracl == 0) { 701.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 711.1Schristos ux.extu_exp -= 1; 721.1Schristos ux.extu_frach = (ux.extu_frach - 1) | 731.1Schristos (ux.extu_frach & LDBL_NBIT); 741.1Schristos } 751.1Schristos ux.extu_fracl -= 1; 761.1Schristos } else { /* x += ulp */ 771.1Schristos ux.extu_fracl += 1; 781.1Schristos if (ux.extu_fracl == 0) { 791.1Schristos ux.extu_frach = (ux.extu_frach + 1) | 801.1Schristos (ux.extu_frach & LDBL_NBIT); 811.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 821.1Schristos ux.extu_exp += 1; 831.1Schristos } 841.1Schristos } 851.1Schristos 861.1Schristos if (ux.extu_exp == EXT_EXP_INF) 871.1Schristos return x+x; /* overflow */ 881.1Schristos 891.1Schristos if (ux.extu_exp == 0) { /* underflow */ 901.3Smatt#ifndef LDBL_IMPLICIT_NBIT 911.1Schristos mask_nbit_l(ux); 921.3Smatt#endif 931.1Schristos t = ux.extu_ld * ux.extu_ld; 941.1Schristos if (t != ux.extu_ld) /* raise underflow flag */ 951.1Schristos return ux.extu_ld; 961.1Schristos } 971.1Schristos 981.1Schristos return ux.extu_ld; 991.1Schristos} 1001.2Schristos#endif 101