s_nextafterl.c revision 1.6
11.6Skamil/* $NetBSD: s_nextafterl.c,v 1.6 2019/04/27 23:04:32 kamil 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.6Skamil__RCSID("$NetBSD: s_nextafterl.c,v 1.6 2019/04/27 23:04:32 kamil 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.6Skamil__strong_alias(nexttowardl, nextafterl) 341.6Skamil 351.1Schristos/* 361.1Schristos * IEEE functions 371.1Schristos * nextafterl(x,y) 381.1Schristos * return the next machine floating-point number of x in the 391.1Schristos * direction toward y. 401.1Schristos * Special cases: 411.1Schristos * If x == y, y shall be returned 421.1Schristos * If x or y is NaN, a NaN shall be returned 431.1Schristos */ 441.1Schristoslong double 451.1Schristosnextafterl(long double x, long double y) 461.1Schristos{ 471.1Schristos volatile long double t; 481.1Schristos union ieee_ext_u ux, uy; 491.1Schristos 501.1Schristos ux.extu_ld = x; 511.1Schristos uy.extu_ld = y; 521.1Schristos 531.5Smatt if ((ux.extu_exp == EXT_EXP_INFNAN && 541.1Schristos ((ux.extu_frach &~ LDBL_NBIT)|ux.extu_fracl) != 0) || 551.5Smatt (uy.extu_exp == EXT_EXP_INFNAN && 561.1Schristos ((uy.extu_frach &~ LDBL_NBIT)|uy.extu_fracl) != 0)) 571.1Schristos return x+y; /* x or y is nan */ 581.1Schristos 591.1Schristos if (x == y) return y; /* x=y, return y */ 601.1Schristos 611.1Schristos if (x == 0.0) { 621.1Schristos ux.extu_frach = 0; /* return +-minsubnormal */ 631.1Schristos ux.extu_fracl = 1; 641.1Schristos ux.extu_sign = uy.extu_sign; 651.1Schristos t = ux.extu_ld * ux.extu_ld; 661.1Schristos if (t == ux.extu_ld) 671.1Schristos return t; 681.1Schristos else 691.1Schristos return ux.extu_ld; /* raise underflow flag */ 701.1Schristos } 711.1Schristos 721.1Schristos if ((x>0.0) ^ (x<y)) { /* x -= ulp */ 731.1Schristos if (ux.extu_fracl == 0) { 741.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 751.1Schristos ux.extu_exp -= 1; 761.1Schristos ux.extu_frach = (ux.extu_frach - 1) | 771.1Schristos (ux.extu_frach & LDBL_NBIT); 781.1Schristos } 791.1Schristos ux.extu_fracl -= 1; 801.1Schristos } else { /* x += ulp */ 811.1Schristos ux.extu_fracl += 1; 821.1Schristos if (ux.extu_fracl == 0) { 831.1Schristos ux.extu_frach = (ux.extu_frach + 1) | 841.1Schristos (ux.extu_frach & LDBL_NBIT); 851.1Schristos if ((ux.extu_frach & ~LDBL_NBIT) == 0) 861.1Schristos ux.extu_exp += 1; 871.1Schristos } 881.1Schristos } 891.1Schristos 901.5Smatt if (ux.extu_exp == EXT_EXP_INFNAN) 911.1Schristos return x+x; /* overflow */ 921.1Schristos 931.1Schristos if (ux.extu_exp == 0) { /* underflow */ 941.3Smatt#ifndef LDBL_IMPLICIT_NBIT 951.1Schristos mask_nbit_l(ux); 961.3Smatt#endif 971.1Schristos t = ux.extu_ld * ux.extu_ld; 981.1Schristos if (t != ux.extu_ld) /* raise underflow flag */ 991.1Schristos return ux.extu_ld; 1001.1Schristos } 1011.1Schristos 1021.1Schristos return ux.extu_ld; 1031.1Schristos} 1041.2Schristos#endif 1051.4Smatt 1061.4Smatt#endif /* __HAVE_LONG_DOUBLE */ 107